Split the page fault handler from the trap handler.

svn path=/trunk/; revision=16700
This commit is contained in:
Hartmut Birr 2005-07-23 11:25:12 +00:00
parent 184ff4dd27
commit 82cd3d5f80
4 changed files with 100 additions and 97 deletions

View 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.
*/

View file

@ -307,7 +307,7 @@ _KiTrap14:
pushl %ebx
pushl %esi
movl $14, %esi
movl $_KiTrapHandler, %ebx
movl $_KiPageFaultHandler, %ebx
jmp _KiTrapProlog2
.globl _KiTrap15

View 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:

View file

@ -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)
{
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;
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();
}
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);
}
}
Mode = Tf->ErrorCode & 0x4 ? UserMode : KernelMode;
/* handle the fault */
if (Tf->ErrorCode & 0x1)
{
Status = MmAccessFault(Mode, cr2, FALSE);
}
else
{
Mode = KernelMode;
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 (Mode == KernelMode && Cr2 >= (ULONG_PTR)MmSystemRangeStart &&
Mmi386MakeKernelPageTableGlobal((PVOID)Cr2))
if (Mode == KernelMode)
{
return(STATUS_SUCCESS);
}
if (ErrorCode & 0x1)
{
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);
}