Split the page fault handler from the trap handler.
authorHartmut Birr <osexpert@googlemail.com>
Sat, 23 Jul 2005 11:25:12 +0000 (11:25 +0000)
committerHartmut Birr <osexpert@googlemail.com>
Sat, 23 Jul 2005 11:25:12 +0000 (11:25 +0000)
svn path=/trunk/; revision=16700

reactos/ntoskrnl/ke/i386/exp.c
reactos/ntoskrnl/ke/i386/trap.s
reactos/ntoskrnl/ke/i386/v86m.c
reactos/ntoskrnl/mm/i386/pfault.c

index 65a2919..f1631c1 100644 (file)
@@ -473,6 +473,8 @@ KiTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr)
    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 @@ KiTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr)
    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
     */
@@ -523,26 +520,6 @@ KiTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr)
        return(0);
      }
 
-   /*
-    * 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.
     */
index 2ae7e06..cdd970f 100644 (file)
@@ -307,7 +307,7 @@ _KiTrap14:
        pushl   %ebx
        pushl   %esi
        movl    $14, %esi
-       movl    $_KiTrapHandler, %ebx
+       movl    $_KiPageFaultHandler, %ebx
        jmp     _KiTrapProlog2
 
 .globl _KiTrap15
index a2109ab..712f150 100644 (file)
@@ -686,26 +686,27 @@ KeV86Exception(ULONG ExceptionNr, PKTRAP_FRAME Tf, ULONG address)
   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 @@ KeV86Exception(ULONG ExceptionNr, PKTRAP_FRAME Tf, ULONG address)
     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:
index 066165b..0e1ad6a 100644 (file)
 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)
 {
-   KPROCESSOR_MODE Mode;
+   ULONG_PTR cr2;
    NTSTATUS Status;
+   KPROCESSOR_MODE Mode;
+   
+   ASSERT(ExceptionNr == 14);
+   
+   /* Store the exception number in an unused field in the trap frame. */
+   Tf->DebugArgMark = (PVOID)14;
+
+   /* get the faulting address */
+   cr2 = Ke386GetCr2();
+   Tf->DebugPointer = (PVOID)cr2;
+
+   /* it's safe to enable interrupts after cr2 has been saved */
+   if (Tf->Eflags & (X86_EFLAGS_VM|X86_EFLAGS_IF))
+   {
+      Ke386EnableInterrupts();
+   }
+
+   if (cr2 >= (ULONG_PTR)MmSystemRangeStart)
+   {
+      /* 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);
+      }
+   }
 
-   DPRINT("MmPageFault(Eip %x, Cr2 %x, ErrorCode %x)\n",
-          *Eip, Cr2, ErrorCode);
+   Mode = Tf->ErrorCode & 0x4 ? UserMode : KernelMode;
 
-   if (ErrorCode & 0x4)
+   /* handle the fault */
+   if (Tf->ErrorCode & 0x1)
    {
-      Mode = UserMode;
+      Status = MmAccessFault(Mode, cr2, FALSE);
    }
    else
    {
-      Mode = KernelMode;
+      Status = MmNotPresentFault(Mode, cr2, FALSE);
    }
-
-   if (Mode == KernelMode && Cr2 >= (ULONG_PTR)MmSystemRangeStart &&
-         Mmi386MakeKernelPageTableGlobal((PVOID)Cr2))
+   
+   /* handle the return for v86 mode */
+   if (Tf->Eflags & X86_EFLAGS_VM)
    {
-      return(STATUS_SUCCESS);
+      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);
 }
+