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