- NDK 0.98, now with versionned headers. Too many changes to list, see the TinyKRNL...
[reactos.git] / reactos / ntoskrnl / ke / i386 / v86m.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/ke/i386/v86m.c
6 * PURPOSE: Support for v86 mode
7 *
8 * PROGRAMMERS: David Welch (welch@cwcom.net)
9 */
10
11 /* INCLUDES *****************************************************************/
12
13 #include <ntoskrnl.h>
14 #define NDEBUG
15 #include <internal/debug.h>
16
17 /* GLOBALS *******************************************************************/
18
19 #define IOPL_FLAG ((1 << 12) | (1 << 13))
20 #define INTERRUPT_FLAG (1 << 9)
21 #define TRAP_FLAG (1 << 8)
22 #define DIRECTION_FLAG (1 << 10)
23
24 #define VALID_FLAGS (0xDFF)
25
26 /* FUNCTIONS *****************************************************************/
27
28 ULONG
29 KeV86GPF(PKV86M_TRAP_FRAME VTf, PKTRAP_FRAME Tf)
30 {
31 PUCHAR ip;
32 PUSHORT sp;
33 PULONG dsp;
34 BOOL BigDataPrefix = FALSE;
35 BOOL BigAddressPrefix = FALSE;
36 BOOL RepPrefix = FALSE;
37 ULONG i = 0;
38 BOOL Exit = FALSE;
39
40 ip = (PUCHAR)((Tf->SegCs & 0xFFFF) * 16 + (Tf->Eip & 0xFFFF));
41 sp = (PUSHORT)((Tf->HardwareSegSs & 0xFFFF) * 16 + (Tf->HardwareEsp & 0xFFFF));
42 dsp = (PULONG)sp;
43
44 DPRINT("KeV86GPF handling %x at %x:%x ss:sp %x:%x Flags %x\n",
45 ip[0], Tf->SegCs, Tf->Eip, Tf->Ss, Tf->HardwareEsp, VTf->regs->Flags);
46
47 while (!Exit)
48 {
49 switch (ip[i])
50 {
51 /* 32-bit data prefix */
52 case 0x66:
53 BigDataPrefix = TRUE;
54 i++;
55 Tf->Eip++;
56 break;
57
58 /* 32-bit address prefix */
59 case 0x67:
60 BigAddressPrefix = TRUE;
61 i++;
62 Tf->Eip++;
63 break;
64
65 /* rep prefix */
66 case 0xFC:
67 RepPrefix = TRUE;
68 i++;
69 Tf->Eip++;
70 break;
71
72 /* sti */
73 case 0xFB:
74 if (BigDataPrefix || BigAddressPrefix || RepPrefix)
75 {
76 *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
77 return(1);
78 }
79 if (VTf->regs->Flags & KV86M_EMULATE_CLI_STI)
80 {
81 Tf->Eip++;
82 VTf->regs->Vif = 1;
83 return(0);
84 }
85 Exit = TRUE;
86 break;
87
88 /* cli */
89 case 0xFA:
90 if (BigDataPrefix || BigAddressPrefix || RepPrefix)
91 {
92 *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
93 return(1);
94 }
95 if (VTf->regs->Flags & KV86M_EMULATE_CLI_STI)
96 {
97 Tf->Eip++;
98 VTf->regs->Vif = 0;
99 return(0);
100 }
101 Exit = TRUE;
102 break;
103
104 /* pushf */
105 case 0x9C:
106 if (RepPrefix)
107 {
108 *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
109 return(1);
110 }
111 if (VTf->regs->Flags & KV86M_EMULATE_CLI_STI)
112 {
113 Tf->Eip++;
114 if (!BigAddressPrefix)
115 {
116 Tf->HardwareEsp = Tf->HardwareEsp - 2;
117 sp = sp - 1;
118 sp[0] = (USHORT)(Tf->EFlags & 0xFFFF);
119 if (VTf->regs->Vif == 1)
120 {
121 sp[0] = (USHORT)(sp[0] | INTERRUPT_FLAG);
122 }
123 else
124 {
125 sp[0] = (USHORT)(sp[0] & (~INTERRUPT_FLAG));
126 }
127 }
128 else
129 {
130 Tf->HardwareEsp = Tf->HardwareEsp - 4;
131 dsp = dsp - 1;
132 dsp[0] = Tf->EFlags;
133 dsp[0] = dsp[0] & VALID_FLAGS;
134 if (VTf->regs->Vif == 1)
135 {
136 dsp[0] = dsp[0] | INTERRUPT_FLAG;
137 }
138 else
139 {
140 dsp[0] = dsp[0] & (~INTERRUPT_FLAG);
141 }
142 }
143 return(0);
144 }
145 Exit = TRUE;
146 break;
147
148 /* popf */
149 case 0x9D:
150 if (RepPrefix)
151 {
152 *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
153 return(1);
154 }
155 if (VTf->regs->Flags & KV86M_EMULATE_CLI_STI)
156 {
157 Tf->Eip++;
158 if (!BigAddressPrefix)
159 {
160 Tf->EFlags = Tf->EFlags & (~0xFFFF);
161 Tf->EFlags = Tf->EFlags | (sp[0] & VALID_FLAGS);
162 if (Tf->EFlags & INTERRUPT_FLAG)
163 {
164 VTf->regs->Vif = 1;
165 }
166 else
167 {
168 VTf->regs->Vif = 0;
169 }
170 Tf->EFlags = Tf->EFlags | INTERRUPT_FLAG;
171 Tf->HardwareEsp = Tf->HardwareEsp + 2;
172 }
173 else
174 {
175 Tf->EFlags = Tf->EFlags | (dsp[0] & VALID_FLAGS);
176 if (dsp[0] & INTERRUPT_FLAG)
177 {
178 VTf->regs->Vif = 1;
179 }
180 else
181 {
182 VTf->regs->Vif = 0;
183 }
184 Tf->EFlags = Tf->EFlags | INTERRUPT_FLAG;
185 Tf->HardwareEsp = Tf->HardwareEsp + 2;
186 }
187 return(0);
188 }
189 Exit = TRUE;
190 break;
191
192 /* iret */
193 case 0xCF:
194 if (RepPrefix)
195 {
196 *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
197 return(1);
198 }
199 if (VTf->regs->Flags & KV86M_EMULATE_CLI_STI)
200 {
201 Tf->Eip = sp[0];
202 Tf->SegCs = sp[1];
203 Tf->EFlags = Tf->EFlags & (~0xFFFF);
204 Tf->EFlags = Tf->EFlags | sp[2];
205 if (Tf->EFlags & INTERRUPT_FLAG)
206 {
207 VTf->regs->Vif = 1;
208 }
209 else
210 {
211 VTf->regs->Vif = 0;
212 }
213 Tf->EFlags = Tf->EFlags & (~INTERRUPT_FLAG);
214 Tf->HardwareEsp = Tf->HardwareEsp + 6;
215 return(0);
216 }
217 Exit = TRUE;
218 break;
219
220 /* out imm8, al */
221 case 0xE6:
222 if (RepPrefix)
223 {
224 *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
225 return(1);
226 }
227 if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS)
228 {
229 DPRINT("outb %d, %x\n", (ULONG)ip[i + 1], Tf->Eax & 0xFF);
230 WRITE_PORT_UCHAR((PUCHAR)(ULONG)ip[i + 1],
231 (UCHAR)(Tf->Eax & 0xFF));
232 Tf->Eip = Tf->Eip + 2;
233 return(0);
234 }
235 Exit = TRUE;
236 break;
237
238 /* out imm8, ax */
239 case 0xE7:
240 if (RepPrefix)
241 {
242 *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
243 return(1);
244 }
245 if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS)
246 {
247 if (!BigDataPrefix)
248 {
249 DPRINT("outw %d, %x\n", (ULONG)ip[i + 1], Tf->Eax & 0xFFFF);
250 WRITE_PORT_USHORT((PUSHORT)(ULONG)ip[1], (USHORT)(Tf->Eax & 0xFFFF));
251 }
252 else
253 {
254 DPRINT("outl %d, %x\n", (ULONG)ip[i + 1], Tf->Eax);
255 WRITE_PORT_ULONG((PULONG)(ULONG)ip[1], Tf->Eax);
256 }
257 Tf->Eip = Tf->Eip + 2;
258 return(0);
259 }
260 Exit = TRUE;
261 break;
262
263 /* out dx, al */
264 case 0xEE:
265 if (RepPrefix)
266 {
267 *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
268 return(1);
269 }
270 if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS)
271 {
272 DPRINT("outb %d, %x\n", Tf->Edx & 0xFFFF, Tf->Eax & 0xFF);
273 WRITE_PORT_UCHAR((PUCHAR)(Tf->Edx & 0xFFFF), (UCHAR)(Tf->Eax & 0xFF));
274 Tf->Eip = Tf->Eip + 1;
275 return(0);
276 }
277 Exit = TRUE;
278 break;
279
280 /* out dx, ax */
281 case 0xEF:
282 if (RepPrefix)
283 {
284 *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
285 return(1);
286 }
287 if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS)
288 {
289 if (!BigDataPrefix)
290 {
291 DPRINT("outw %d, %x\n", Tf->Edx & 0xFFFF, Tf->Eax & 0xFFFF);
292 WRITE_PORT_USHORT((PUSHORT)(Tf->Edx & 0xFFFF),
293 (USHORT)(Tf->Eax & 0xFFFF));
294 }
295 else
296 {
297 DPRINT("outl %d, %x\n", Tf->Edx & 0xFFFF, Tf->Eax);
298 WRITE_PORT_ULONG((PULONG)(Tf->Edx & 0xFFFF),
299 Tf->Eax);
300 }
301 Tf->Eip = Tf->Eip + 1;
302 return(0);
303 }
304 Exit = TRUE;
305 break;
306
307 /* in al, imm8 */
308 case 0xE4:
309 if (RepPrefix)
310 {
311 *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
312 return(1);
313 }
314 if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS)
315 {
316 UCHAR v;
317
318 v = READ_PORT_UCHAR((PUCHAR)(ULONG)ip[1]);
319 DPRINT("inb %d\t%X\n", (ULONG)ip[1], v);
320 Tf->Eax = Tf->Eax & (~0xFF);
321 Tf->Eax = Tf->Eax | v;
322 Tf->Eip = Tf->Eip + 2;
323 return(0);
324 }
325 Exit = TRUE;
326 break;
327
328 /* in ax, imm8 */
329 case 0xE5:
330 if (RepPrefix)
331 {
332 *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
333 return(1);
334 }
335 if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS)
336 {
337 if (!BigDataPrefix)
338 {
339 USHORT v;
340 v = READ_PORT_USHORT((PUSHORT)(ULONG)ip[1]);
341 DPRINT("inw %d\t%X\n", (ULONG)ip[1], v);
342 Tf->Eax = Tf->Eax & (~0xFFFF);
343 Tf->Eax = Tf->Eax | v;
344 }
345 else
346 {
347 ULONG v;
348 v = READ_PORT_ULONG((PULONG)(ULONG)ip[1]);
349 DPRINT("inl %d\t%X\n", (ULONG)ip[1], v);
350 Tf->Eax = v;
351 }
352 Tf->Eip = Tf->Eip + 2;
353 return(0);
354 }
355 Exit = TRUE;
356 break;
357
358 /* in al, dx */
359 case 0xEC:
360 if (RepPrefix)
361 {
362 *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
363 return(1);
364 }
365 if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS)
366 {
367 UCHAR v;
368
369 v = READ_PORT_UCHAR((PUCHAR)(Tf->Edx & 0xFFFF));
370 DPRINT("inb %d\t%X\n", Tf->Edx & 0xFFFF, v);
371 Tf->Eax = Tf->Eax & (~0xFF);
372 Tf->Eax = Tf->Eax | v;
373 Tf->Eip = Tf->Eip + 1;
374 return(0);
375 }
376 Exit = TRUE;
377 break;
378
379 /* in ax, dx */
380 case 0xED:
381 if (RepPrefix)
382 {
383 *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
384 return(1);
385 }
386 if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS)
387 {
388 if (!BigDataPrefix)
389 {
390 USHORT v;
391
392 v = READ_PORT_USHORT((PUSHORT)(Tf->Edx & 0xFFFF));
393 DPRINT("inw %d\t%X\n", Tf->Edx & 0xFFFF, v);
394 Tf->Eax = Tf->Eax & (~0xFFFF);
395 Tf->Eax = Tf->Eax | v;
396 }
397 else
398 {
399 ULONG v;
400
401 v = READ_PORT_ULONG((PULONG)(Tf->Edx & 0xFFFF));
402 DPRINT("inl %d\t%X\n", Tf->Edx & 0xFFFF, v);
403 Tf->Eax = v;
404 }
405 Tf->Eip = Tf->Eip + 1;
406 return(0);
407 }
408 Exit = TRUE;
409 break;
410
411 /* outsb */
412 case 0x6E:
413 if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS)
414 {
415 ULONG Count;
416 PUCHAR Port;
417 PUCHAR Buffer;
418 ULONG Offset;
419
420 Count = 1;
421 if (RepPrefix)
422 {
423 Count = Tf->Ecx;
424 if (!BigAddressPrefix)
425 {
426 Count = Count & 0xFFFF;
427 }
428 }
429
430 Port = (PUCHAR)(Tf->Edx & 0xFFFF);
431 Offset = Tf->Edi;
432 if (!BigAddressPrefix)
433 {
434 Offset = Offset & 0xFFFF;
435 }
436 Buffer = (PUCHAR)((Tf->SegEs * 16) + Offset);
437 for (; Count > 0; Count--)
438 {
439 WRITE_PORT_UCHAR(Port, *Buffer);
440 if (Tf->EFlags & DIRECTION_FLAG)
441 {
442 Buffer++;
443 }
444 else
445 {
446 Buffer--;
447 }
448 }
449 Tf->Eip++;
450 return(0);
451 }
452 Exit = TRUE;
453 break;
454
455 /* insw/insd */
456 case 0x6F:
457 if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS)
458 {
459 ULONG Count;
460 PUCHAR Port;
461 PUSHORT BufferS = NULL;
462 PULONG BufferL = NULL;
463 ULONG Offset;
464
465 Count = 1;
466 if (RepPrefix)
467 {
468 Count = Tf->Ecx;
469 if (!BigAddressPrefix)
470 {
471 Count = Count & 0xFFFF;
472 }
473 }
474
475 Port = (PUCHAR)(Tf->Edx & 0xFFFF);
476 Offset = Tf->Edi;
477 if (!BigAddressPrefix)
478 {
479 Offset = Offset & 0xFFFF;
480 }
481 if (BigDataPrefix)
482 {
483 BufferL = (PULONG)((Tf->SegEs * 16) + Offset);
484 }
485 else
486 {
487 BufferS = (PUSHORT)((Tf->SegEs * 16) + Offset);
488 }
489 for (; Count > 0; Count--)
490 {
491 if (BigDataPrefix)
492 {
493 WRITE_PORT_ULONG((PULONG)Port, *BufferL);
494 }
495 else
496 {
497 WRITE_PORT_USHORT((PUSHORT)Port, *BufferS);
498 }
499 if (Tf->EFlags & DIRECTION_FLAG)
500 {
501 if (BigDataPrefix)
502 {
503 BufferL++;
504 }
505 else
506 {
507 BufferS++;
508 }
509 }
510 else
511 {
512 if (BigDataPrefix)
513 {
514 BufferL--;
515 }
516 else
517 {
518 BufferS--;
519 }
520 }
521 }
522 Tf->Eip++;
523 return(0);
524 }
525 Exit = TRUE;
526 break;
527
528 /* insb */
529 case 0x6C:
530 if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS)
531 {
532 ULONG Count;
533 PUCHAR Port;
534 PUCHAR Buffer;
535 ULONG Offset;
536
537 Count = 1;
538 if (RepPrefix)
539 {
540 Count = Tf->Ecx;
541 if (!BigAddressPrefix)
542 {
543 Count = Count & 0xFFFF;
544 }
545 }
546
547 Port = (PUCHAR)(Tf->Edx & 0xFFFF);
548 Offset = Tf->Edi;
549 if (!BigAddressPrefix)
550 {
551 Offset = Offset & 0xFFFF;
552 }
553 Buffer = (PUCHAR)((Tf->SegEs * 16) + Offset);
554 for (; Count > 0; Count--)
555 {
556 *Buffer = READ_PORT_UCHAR(Port);
557 if (Tf->EFlags & DIRECTION_FLAG)
558 {
559 Buffer++;
560 }
561 else
562 {
563 Buffer--;
564 }
565 }
566 Tf->Eip++;
567 return(0);
568 }
569 Exit = TRUE;
570 break;
571
572 /* insw/insd */
573 case 0x6D:
574 if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS)
575 {
576 ULONG Count;
577 PUCHAR Port;
578 PUSHORT BufferS = NULL;
579 PULONG BufferL = NULL;
580 ULONG Offset;
581
582 Count = 1;
583 if (RepPrefix)
584 {
585 Count = Tf->Ecx;
586 if (!BigAddressPrefix)
587 {
588 Count = Count & 0xFFFF;
589 }
590 }
591
592 Port = (PUCHAR)(Tf->Edx & 0xFFFF);
593 Offset = Tf->Edi;
594 if (!BigAddressPrefix)
595 {
596 Offset = Offset & 0xFFFF;
597 }
598 if (BigDataPrefix)
599 {
600 BufferL = (PULONG)((Tf->SegEs * 16) + Offset);
601 }
602 else
603 {
604 BufferS = (PUSHORT)((Tf->SegEs * 16) + Offset);
605 }
606 for (; Count > 0; Count--)
607 {
608 if (BigDataPrefix)
609 {
610 *BufferL = READ_PORT_ULONG((PULONG)Port);
611 }
612 else
613 {
614 *BufferS = READ_PORT_USHORT((PUSHORT)Port);
615 }
616 if (Tf->EFlags & DIRECTION_FLAG)
617 {
618 if (BigDataPrefix)
619 {
620 BufferL++;
621 }
622 else
623 {
624 BufferS++;
625 }
626 }
627 else
628 {
629 if (BigDataPrefix)
630 {
631 BufferL--;
632 }
633 else
634 {
635 BufferS--;
636 }
637 }
638 }
639 Tf->Eip++;
640 return(0);
641 }
642 Exit = TRUE;
643 break;
644
645 /* Int nn */
646 case 0xCD:
647 {
648 unsigned int inum;
649 unsigned int entry;
650
651 inum = ip[1];
652 entry = ((unsigned int *)0)[inum];
653
654 Tf->HardwareEsp = Tf->HardwareEsp - 6;
655 sp = sp - 3;
656
657 sp[0] = (USHORT)((Tf->Eip & 0xFFFF) + 2);
658 sp[1] = (USHORT)(Tf->SegCs & 0xFFFF);
659 sp[2] = (USHORT)(Tf->EFlags & 0xFFFF);
660 if (VTf->regs->Vif == 1)
661 {
662 sp[2] = (USHORT)(sp[2] | INTERRUPT_FLAG);
663 }
664 DPRINT("sp[0] %x sp[1] %x sp[2] %x\n", sp[0], sp[1], sp[2]);
665 Tf->Eip = entry & 0xFFFF;
666 Tf->SegCs = entry >> 16;
667 Tf->EFlags = Tf->EFlags & (~TRAP_FLAG);
668
669 return(0);
670 }
671 }
672
673 /* FIXME: Also emulate ins and outs */
674 /* FIXME: Handle opcode prefixes */
675 /* FIXME: Don't allow the BIOS to write to sensitive I/O ports */
676 }
677
678 DPRINT1("V86GPF unhandled (was %x)\n", ip[i]);
679 *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
680 return(1);
681 }
682
683 ULONG
684 NTAPI
685 KeV86Exception(ULONG ExceptionNr, PKTRAP_FRAME Tf, ULONG address)
686 {
687 PUCHAR Ip;
688 PKV86M_TRAP_FRAME VTf;
689
690 ASSERT (ExceptionNr != 14);
691
692 VTf = (PKV86M_TRAP_FRAME)Tf;
693
694 /* FIXME: This should use ->VdmObjects */
695 if(KeGetCurrentProcess()->Unused)
696 {
697 VTf->regs->PStatus = (PNTSTATUS) ExceptionNr;
698 return 1;
699 }
700
701 /*
702 * Check if we have reached the recovery instruction
703 */
704 Ip = (PUCHAR)((Tf->SegCs & 0xFFFF) * 16 + (Tf->Eip & 0xFFFF));
705
706 DPRINT("ExceptionNr %d Ip[0] %x Ip[1] %x Ip[2] %x Ip[3] %x Tf->SegCs %x "
707 "Tf->Eip %x\n", ExceptionNr, Ip[0], Ip[1], Ip[2], Ip[3], Tf->SegCs,
708 Tf->Eip);
709 DPRINT("VTf %x VTf->regs %x\n", VTf, VTf->regs);
710
711 if (ExceptionNr == 6 &&
712 memcmp(Ip, VTf->regs->RecoveryInstruction, 4) == 0 &&
713 (Tf->SegCs * 16 + Tf->Eip) == VTf->regs->RecoveryAddress)
714 {
715 *VTf->regs->PStatus = STATUS_SUCCESS;
716 return(1);
717 }
718
719 /*
720 * Handle the exceptions
721 */
722 switch (ExceptionNr)
723 {
724 /* Divide error */
725 case 0:
726 *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
727 return(1);
728
729 /* Single step */
730 case 1:
731 *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
732 return(1);
733
734 /* NMI */
735 case 2:
736 *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
737 return(1);
738
739 /* Breakpoint */
740 case 3:
741 *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
742 return(1);
743
744 /* Overflow */
745 case 4:
746 *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
747 return(1);
748
749 /* Array bounds check */
750 case 5:
751 *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
752 return(1);
753
754 /* Invalid opcode */
755 case 6:
756 *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
757 return(1);
758
759 /* Device not available */
760 case 7:
761 *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
762 return(1);
763
764 /* Double fault */
765 case 8:
766 *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
767 return(1);
768
769 /* Intel reserved */
770 case 9:
771 *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
772 return(1);
773
774 /* Invalid TSS */
775 case 10:
776 *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
777 return(1);
778
779 /* Segment not present */
780 case 11:
781 *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
782 return(1);
783
784 /* Stack fault */
785 case 12:
786 *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
787 return(1);
788
789 /* General protection fault */
790 case 13:
791 return(KeV86GPF(VTf, Tf));
792
793 /* Intel reserved */
794 case 15:
795 case 16:
796 *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
797 return(1);
798
799 /* Alignment check */
800 case 17:
801 *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
802 return(1);
803
804 default:
805 *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
806 return(1);
807 }
808 }
809
810
811