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); -}