Split the page fault handler from the trap handler.
Modified: trunk/reactos/ntoskrnl/ke/i386/exp.c
Modified: trunk/reactos/ntoskrnl/ke/i386/trap.s
Modified: trunk/reactos/ntoskrnl/ke/i386/v86m.c
Modified: trunk/reactos/ntoskrnl/mm/i386/pfault.c

Modified: trunk/reactos/ntoskrnl/ke/i386/exp.c
--- trunk/reactos/ntoskrnl/ke/i386/exp.c	2005-07-23 10:08:15 UTC (rev 16699)
+++ trunk/reactos/ntoskrnl/ke/i386/exp.c	2005-07-23 11:25:12 UTC (rev 16700)
@@ -473,6 +473,8 @@
    NTSTATUS Status;
    ULONG Esp0;
 
+   ASSERT(ExceptionNr != 14);
+
    /* Store the exception number in an unused field in the trap frame. */
    Tf->DebugArgMark = (PVOID)ExceptionNr;
 
@@ -483,11 +485,6 @@
    cr2 = Ke386GetCr2();
    Tf->DebugPointer = (PVOID)cr2;
 
-   if (ExceptionNr == 14 && Tf->Eflags & FLAG_IF)
-   {
-     Ke386EnableInterrupts();
-   }
-
    /*
     * If this was a V86 mode exception then handle it specially
     */
@@ -524,26 +521,6 @@
      }
 
    /*
-    * Maybe handle the page fault and return
-    */
-   if (ExceptionNr == 14)
-     {
-        if (Ke386NoExecute && Tf->ErrorCode & 0x10 && cr2 >= (ULONG_PTR)MmSystemRangeStart)
-	{
-           KEBUGCHECKWITHTF(ATTEMPTED_EXECUTE_OF_NOEXECUTE_MEMORY, 0, 0, 0, 0, Tf);
-	}
-	Status = MmPageFault(Tf->Cs&0xffff,
-			     &Tf->Eip,
-			     &Tf->Eax,
-			     cr2,
-			     Tf->ErrorCode);
-	if (NT_SUCCESS(Status))
-	  {
-	     return(0);
-	  }
-     }
-
-   /*
     * Check for a breakpoint that was only for the attention of the debugger.
     */
    if (ExceptionNr == 3 && Tf->Eip == ((ULONG)DbgBreakPointNoBugCheck) + 1)

Modified: trunk/reactos/ntoskrnl/ke/i386/trap.s
--- trunk/reactos/ntoskrnl/ke/i386/trap.s	2005-07-23 10:08:15 UTC (rev 16699)
+++ trunk/reactos/ntoskrnl/ke/i386/trap.s	2005-07-23 11:25:12 UTC (rev 16700)
@@ -307,7 +307,7 @@
 	pushl	%ebx
 	pushl	%esi
 	movl	$14, %esi
-	movl	$_KiTrapHandler, %ebx
+	movl	$_KiPageFaultHandler, %ebx
 	jmp	_KiTrapProlog2
 
 .globl _KiTrap15

Modified: trunk/reactos/ntoskrnl/ke/i386/v86m.c
--- trunk/reactos/ntoskrnl/ke/i386/v86m.c	2005-07-23 10:08:15 UTC (rev 16699)
+++ trunk/reactos/ntoskrnl/ke/i386/v86m.c	2005-07-23 11:25:12 UTC (rev 16700)
@@ -686,26 +686,27 @@
   PUCHAR Ip;
   PKV86M_TRAP_FRAME VTf;
 
+  ASSERT (ExceptionNr != 14);
+
   VTf = (PKV86M_TRAP_FRAME)Tf;
 
   /* FIXME: This should use ->VdmObjects */
   if(KeGetCurrentProcess()->Unused)
   {
     VTf->regs->PStatus = (PNTSTATUS) ExceptionNr;
-    if(ExceptionNr != 14) return 1;
+    return 1;
   }
 
   /*
    * Check if we have reached the recovery instruction
    */
   Ip = (PUCHAR)((Tf->Cs & 0xFFFF) * 16 + (Tf->Eip & 0xFFFF));
-  if (ExceptionNr != 14)
-    {
-      DPRINT("ExceptionNr %d Ip[0] %x Ip[1] %x Ip[2] %x Ip[3] %x Tf->Cs %x "
-	     "Tf->Eip %x\n", ExceptionNr, Ip[0], Ip[1], Ip[2], Ip[3], Tf->Cs,
-	     Tf->Eip);
-      DPRINT("VTf %x VTf->regs %x\n", VTf, VTf->regs);
-    }
+  
+  DPRINT("ExceptionNr %d Ip[0] %x Ip[1] %x Ip[2] %x Ip[3] %x Tf->Cs %x "
+	 "Tf->Eip %x\n", ExceptionNr, Ip[0], Ip[1], Ip[2], Ip[3], Tf->Cs,
+	 Tf->Eip);
+  DPRINT("VTf %x VTf->regs %x\n", VTf, VTf->regs);
+
   if (ExceptionNr == 6 &&
       memcmp(Ip, VTf->regs->RecoveryInstruction, 4) == 0 &&
       (Tf->Cs * 16 + Tf->Eip) == VTf->regs->RecoveryAddress)
@@ -788,32 +789,6 @@
     case 13:
       return(KeV86GPF(VTf, Tf));
 
-      /* Page fault */
-    case 14:
-      {
-	NTSTATUS Status;
-
-	Status = MmPageFault(USER_CS,
-			     &Tf->Eip,
-			     NULL,
-			     address,
-			     Tf->ErrorCode);
-	if (!NT_SUCCESS(Status))
-	  {
-            /* FIXME: This should use ->VdmObjects */
-            if(KeGetCurrentProcess()->Unused)
-            {
-              VTf->regs->PStatus = (PNTSTATUS) STATUS_NONCONTINUABLE_EXCEPTION;
-              return 1;
-            }
-
-            DPRINT("V86Exception, halting due to page fault\n");
-	    *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
-	    return(1);
-	  }
-	return(0);
-      }
-
       /* Intel reserved */
     case 15:
     case 16:

Modified: trunk/reactos/ntoskrnl/mm/i386/pfault.c
--- trunk/reactos/ntoskrnl/mm/i386/pfault.c	2005-07-23 10:08:15 UTC (rev 16699)
+++ trunk/reactos/ntoskrnl/mm/i386/pfault.c	2005-07-23 11:25:12 UTC (rev 16700)
@@ -19,66 +19,117 @@
 extern VOID MmSafeReadPtrStart(VOID);
 extern VOID MmSafeReadPtrEnd(VOID);
 
-extern ULONG MmGlobalKernelPageDirectory[1024];
 
-BOOLEAN
-Mmi386MakeKernelPageTableGlobal(PVOID Address);
+extern BOOLEAN Mmi386MakeKernelPageTableGlobal(PVOID Address);
+extern ULONG KiKernelTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr, PVOID Cr2);
 
+extern BOOLEAN Ke386NoExecute;
+
 /* FUNCTIONS *****************************************************************/
 
-NTSTATUS MmPageFault(ULONG Cs,
-                     PULONG Eip,
-                     PULONG Eax,
-                     ULONG Cr2,
-                     ULONG ErrorCode)
+ULONG KiPageFaultHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr)
 {
+   ULONG_PTR cr2;
+   NTSTATUS Status;
    KPROCESSOR_MODE Mode;
-   NTSTATUS Status;
+   
+   ASSERT(ExceptionNr == 14);
+   
+   /* Store the exception number in an unused field in the trap frame. */
+   Tf->DebugArgMark = (PVOID)14;
 
-   DPRINT("MmPageFault(Eip %x, Cr2 %x, ErrorCode %x)\n",
-          *Eip, Cr2, ErrorCode);
+   /* get the faulting address */
+   cr2 = Ke386GetCr2();
+   Tf->DebugPointer = (PVOID)cr2;
 
-   if (ErrorCode & 0x4)
+   /* it's safe to enable interrupts after cr2 has been saved */
+   if (Tf->Eflags & (X86_EFLAGS_VM|X86_EFLAGS_IF))
    {
-      Mode = UserMode;
+      Ke386EnableInterrupts();
    }
-   else
+
+   if (cr2 >= (ULONG_PTR)MmSystemRangeStart)
    {
-      Mode = KernelMode;
+      /* check for an invalid page directory in kernel mode */
+      if (!(Tf->ErrorCode & 0x5) && Mmi386MakeKernelPageTableGlobal((PVOID)cr2))
+      {
+         return 0;
+      }
+
+      /* check for non executable memory in kernel mode */
+      if (Ke386NoExecute && Tf->ErrorCode & 0x10)
+      {
+         KEBUGCHECKWITHTF(ATTEMPTED_EXECUTE_OF_NOEXECUTE_MEMORY, 0, 0, 0, 0, Tf);
+      }
    }
 
-   if (Mode == KernelMode && Cr2 >= (ULONG_PTR)MmSystemRangeStart &&
-         Mmi386MakeKernelPageTableGlobal((PVOID)Cr2))
+   Mode = Tf->ErrorCode & 0x4 ? UserMode : KernelMode;
+
+   /* handle the fault */
+   if (Tf->ErrorCode & 0x1)
    {
-      return(STATUS_SUCCESS);
+      Status = MmAccessFault(Mode, cr2, FALSE);
    }
+   else
+   {
+      Status = MmNotPresentFault(Mode, cr2, FALSE);
+   }
+   
+   /* handle the return for v86 mode */
+   if (Tf->Eflags & X86_EFLAGS_VM)
+   {
+      if (!NT_SUCCESS(Status))
+      {
+         /* FIXME: This should use ->VdmObjects */
+         if(!KeGetCurrentProcess()->Unused)
+         {
+            *((PKV86M_TRAP_FRAME)Tf)->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
+	 }
+         return 1;
+      }
+      return 0;
+   }
 
-   if (ErrorCode & 0x1)
+   if (Mode == KernelMode)
    {
-      Status = MmAccessFault(Mode, Cr2, FALSE);
+      if (!NT_SUCCESS(Status))
+      {
+         if (Tf->Eip >= (ULONG_PTR)MmSafeReadPtrStart &&
+                  Tf->Eip < (ULONG_PTR)MmSafeReadPtrEnd)
+         {
+            Tf->Eip = (ULONG_PTR)MmSafeReadPtrEnd;
+            Tf->Eax = 0;
+            return 0;
+         }
+      }
    }
    else
    {
-      Status = MmNotPresentFault(Mode, Cr2, FALSE);
+      if (KeGetCurrentThread()->ApcState.UserApcPending)
+      {
+         KIRQL oldIrql;
+      
+         KeRaiseIrql(APC_LEVEL, &oldIrql);
+         KiDeliverApc(UserMode, NULL, NULL);
+         KeLowerIrql(oldIrql);
+      }
    }
 
-   if (Mode == UserMode && KeGetCurrentThread()->ApcState.UserApcPending)
+   if (NT_SUCCESS(Status))
    {
-      KIRQL oldIrql;
-
-      KeRaiseIrql(APC_LEVEL, &oldIrql);
-      KiDeliverApc(UserMode, NULL, NULL);
-      KeLowerIrql(oldIrql);
+      return 0;
    }
 
-   if (!NT_SUCCESS(Status) && (Mode == KernelMode) &&
-         ((*Eip) >= (ULONG_PTR)MmSafeReadPtrStart) &&
-         ((*Eip) <= (ULONG_PTR)MmSafeReadPtrEnd))
+   /*
+    * Handle user exceptions differently
+    */
+   if (Mode == KernelMode)
    {
-      (*Eip) = (ULONG_PTR)MmSafeReadPtrEnd;
-      (*Eax) = 0;
-      return(STATUS_SUCCESS);
+      return(KiKernelTrapHandler(Tf, 14, (PVOID)cr2));
    }
+   else
+   {
+      return(KiUserTrapHandler(Tf, 14, (PVOID)cr2));
+   }
+}
 
-   return(Status);
-}