KD System Rewrite:
[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->Cs & 0xFFFF) * 16 + (Tf->Eip & 0xFFFF));
41 sp = (PUSHORT)((Tf->Ss & 0xFFFF) * 16 + (Tf->Esp & 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->Cs, Tf->Eip, Tf->Ss, Tf->Esp, 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->Esp = Tf->Esp - 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->Esp = Tf->Esp - 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->Esp = Tf->Esp + 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->Esp = Tf->Esp + 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->Cs = 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->Esp = Tf->Esp + 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->Es * 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->Es * 16) + Offset);
484 }
485 else
486 {
487 BufferS = (PUSHORT)((Tf->Es * 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->Es * 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->Es * 16) + Offset);
601 }
602 else
603 {
604 BufferS = (PUSHORT)((Tf->Es * 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->Esp = Tf->Esp - 6;
655 sp = sp - 3;
656
657 sp[0] = (USHORT)((Tf->Eip & 0xFFFF) + 2);
658 sp[1] = (USHORT)(Tf->Cs & 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->Cs = 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 KeV86Exception(ULONG ExceptionNr, PKTRAP_FRAME Tf, ULONG address)
685 {
686 PUCHAR Ip;
687 PKV86M_TRAP_FRAME VTf;
688
689 VTf = (PKV86M_TRAP_FRAME)Tf;
690
691 if(KeGetCurrentProcess()->NtVdmFlag)
692 {
693 VTf->regs->PStatus = (PNTSTATUS) ExceptionNr;
694 if(ExceptionNr != 14) return 1;
695 }
696
697 /*
698 * Check if we have reached the recovery instruction
699 */
700 Ip = (PUCHAR)((Tf->Cs & 0xFFFF) * 16 + (Tf->Eip & 0xFFFF));
701 if (ExceptionNr != 14)
702 {
703 DPRINT("ExceptionNr %d Ip[0] %x Ip[1] %x Ip[2] %x Ip[3] %x Tf->Cs %x "
704 "Tf->Eip %x\n", ExceptionNr, Ip[0], Ip[1], Ip[2], Ip[3], Tf->Cs,
705 Tf->Eip);
706 DPRINT("VTf %x VTf->regs %x\n", VTf, VTf->regs);
707 }
708 if (ExceptionNr == 6 &&
709 memcmp(Ip, VTf->regs->RecoveryInstruction, 4) == 0 &&
710 (Tf->Cs * 16 + Tf->Eip) == VTf->regs->RecoveryAddress)
711 {
712 *VTf->regs->PStatus = STATUS_SUCCESS;
713 return(1);
714 }
715
716 /*
717 * Handle the exceptions
718 */
719 switch (ExceptionNr)
720 {
721 /* Divide error */
722 case 0:
723 *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
724 return(1);
725
726 /* Single step */
727 case 1:
728 *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
729 return(1);
730
731 /* NMI */
732 case 2:
733 *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
734 return(1);
735
736 /* Breakpoint */
737 case 3:
738 *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
739 return(1);
740
741 /* Overflow */
742 case 4:
743 *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
744 return(1);
745
746 /* Array bounds check */
747 case 5:
748 *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
749 return(1);
750
751 /* Invalid opcode */
752 case 6:
753 *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
754 return(1);
755
756 /* Device not available */
757 case 7:
758 *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
759 return(1);
760
761 /* Double fault */
762 case 8:
763 *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
764 return(1);
765
766 /* Intel reserved */
767 case 9:
768 *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
769 return(1);
770
771 /* Invalid TSS */
772 case 10:
773 *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
774 return(1);
775
776 /* Segment not present */
777 case 11:
778 *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;;
779 return(1);
780
781 /* Stack fault */
782 case 12:
783 *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
784 return(1);
785
786 /* General protection fault */
787 case 13:
788 return(KeV86GPF(VTf, Tf));
789
790 /* Page fault */
791 case 14:
792 {
793 NTSTATUS Status;
794
795 Status = MmPageFault(USER_CS,
796 &Tf->Eip,
797 NULL,
798 address,
799 Tf->ErrorCode);
800 if (!NT_SUCCESS(Status))
801 {
802 if(KeGetCurrentProcess()->NtVdmFlag)
803 {
804 VTf->regs->PStatus = (PNTSTATUS) STATUS_NONCONTINUABLE_EXCEPTION;
805 return 1;
806 }
807
808 DPRINT("V86Exception, halting due to page fault\n");
809 *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
810 return(1);
811 }
812 return(0);
813 }
814
815 /* Intel reserved */
816 case 15:
817 case 16:
818 *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
819 return(1);
820
821 /* Alignment check */
822 case 17:
823 *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
824 return(1);
825
826 default:
827 *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
828 return(1);
829 }
830 }
831
832
833