[NTOS:KE]
authorThomas Faber <thomas.faber@reactos.org>
Fri, 14 Apr 2017 11:18:22 +0000 (11:18 +0000)
committerThomas Faber <thomas.faber@reactos.org>
Fri, 14 Apr 2017 11:18:22 +0000 (11:18 +0000)
- Gracefully handle page faults during V86 code execution. This is a bit of a hack because with our limited use of V86 code it is unclear how a page fault can even occur.
CORE-12993 #resolve

svn path=/trunk/; revision=74305

reactos/ntoskrnl/include/internal/i386/ke.h
reactos/ntoskrnl/ke/i386/traphdlr.c
reactos/ntoskrnl/vdm/vdmexec.c

index 5af888b..c7c48ea 100644 (file)
@@ -480,6 +480,12 @@ VdmDispatchBop(
     IN PKTRAP_FRAME TrapFrame
 );
 
+BOOLEAN
+NTAPI
+VdmDispatchPageFault(
+    _In_ PKTRAP_FRAME TrapFrame
+);
+
 BOOLEAN
 FASTCALL
 KiVdmOpcodePrefix(
index 4dccea4..be5dd31 100644 (file)
@@ -1304,8 +1304,20 @@ KiTrap0EHandler(IN PKTRAP_FRAME TrapFrame)
         UNIMPLEMENTED_FATAL();
     }
 #endif
+
     /* Check for VDM trap */
-    ASSERT((KiVdmTrap(TrapFrame)) == FALSE);
+    if (KiVdmTrap(TrapFrame))
+    {
+        DPRINT1("VDM PAGE FAULT at %lx:%lx for address %lx\n",
+                TrapFrame->SegCs, TrapFrame->Eip, Cr2);
+        if (VdmDispatchPageFault(TrapFrame))
+        {
+            /* Return and end VDM execution */
+            DPRINT1("VDM page fault with status 0x%lx resolved\n", Status);
+            KiEoiHelper(TrapFrame);
+        }
+        DPRINT1("VDM page fault with status 0x%lx NOT resolved\n", Status);
+    }
 
     /* Either kernel or user trap (non VDM) so dispatch exception */
     if (Status == STATUS_ACCESS_VIOLATION)
index cdcd313..8d8ce7a 100644 (file)
@@ -239,7 +239,7 @@ VdmpStartExecution(VOID)
         KeLowerIrql(OldIrql);
         return STATUS_INVALID_SYSTEM_SERVICE;
     }
-    
+
     /* Now do the VDM Swap */
     VdmSwapContext(VdmFrame, &VdmTib->MonitorContext, &VdmContext);
 
@@ -269,7 +269,7 @@ VdmEndExecution(IN PKTRAP_FRAME TrapFrame,
 
     /* Make a copy of the monitor context */
     Context = VdmTib->MonitorContext;
-    
+
     /* Check if V86 mode was enabled or the trap was edited */
     if ((Context.EFlags & EFLAGS_V86_MASK) || (Context.SegCs & FRAME_EDITED))
     {
@@ -291,7 +291,7 @@ VdmEndExecution(IN PKTRAP_FRAME TrapFrame,
                 /* Remove real IF flag */
                 VdmTib->VdmContext.EFlags &= ~EFLAGS_INTERRUPT_MASK;
             }
-            
+
             /* Turn off VIP and VIF */
             TrapFrame->EFlags &= ~(EFLAGS_VIP | EFLAGS_VIF);
             VdmTib->VdmContext.EFlags &= ~(EFLAGS_VIP | EFLAGS_VIF);
@@ -362,4 +362,45 @@ VdmDispatchBop(IN PKTRAP_FRAME TrapFrame)
     return TRUE;
 }
 
+BOOLEAN
+NTAPI
+VdmDispatchPageFault(
+    _In_ PKTRAP_FRAME TrapFrame)
+{
+    NTSTATUS Status;
+    PVDM_TIB VdmTib;
+
+    PAGED_CODE();
+
+    /* Get the VDM TIB so we can terminate V86 execution */
+    Status = VdmpGetVdmTib(&VdmTib);
+    if (!NT_SUCCESS(Status))
+    {
+        /* Not a proper VDM fault, keep looking */
+        DPRINT1("VdmDispatchPageFault: no VDM TIB, Vdm=%p\n", NtCurrentTeb()->Vdm);
+        return FALSE;
+    }
+
+    /* Must be coming from V86 code */
+    ASSERT(TrapFrame->EFlags & EFLAGS_V86_MASK);
+
+    _SEH2_TRY
+    {
+        /* Fill out a VDM Event */
+        VdmTib->EventInfo.Event = VdmMemAccess;
+        VdmTib->EventInfo.InstructionSize = 0;
+
+        /* End VDM Execution */
+        VdmEndExecution(TrapFrame, VdmTib);
+    }
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    {
+        Status = _SEH2_GetExceptionCode();
+    }
+    _SEH2_END;
+
+    /* Consider the exception handled if we succeeded */
+    DPRINT1("VdmDispatchPageFault EFlags %lx exit with 0x%lx\n", TrapFrame->EFlags, Status);
+    return NT_SUCCESS(Status);
+}