mirror of
https://github.com/reactos/reactos.git
synced 2025-04-26 16:40:27 +00:00
Split the page fault handler from the trap handler.
svn path=/trunk/; revision=16700
This commit is contained in:
parent
184ff4dd27
commit
82cd3d5f80
4 changed files with 100 additions and 97 deletions
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -307,7 +307,7 @@ _KiTrap14:
|
|||
pushl %ebx
|
||||
pushl %esi
|
||||
movl $14, %esi
|
||||
movl $_KiTrapHandler, %ebx
|
||||
movl $_KiPageFaultHandler, %ebx
|
||||
jmp _KiTrapProlog2
|
||||
|
||||
.globl _KiTrap15
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
||||
DPRINT("MmPageFault(Eip %x, Cr2 %x, ErrorCode %x)\n",
|
||||
*Eip, Cr2, ErrorCode);
|
||||
ASSERT(ExceptionNr == 14);
|
||||
|
||||
if (ErrorCode & 0x4)
|
||||
/* 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))
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue