[NTOSKRNL]

- Implement MiSynchronizeSystemPde, which does what its name suggests, synchronize a system PDE and is an improved replacement (with a more proper name) for MiCheckPdeForPagedPool
- Move some code to avoid an additional check
- Call MiResolveDemandZeroFault directy instead of creating a demand zero PDE and then calling MiDispatchFault, which after a lot of checks will finally do the same

svn path=/trunk/; revision=55456
This commit is contained in:
Timo Kreuzer 2012-02-06 10:46:52 +00:00
parent ed64af75b6
commit 44d9f6f838

View file

@ -100,6 +100,28 @@ MiCheckVirtualAddress(IN PVOID VirtualAddress,
} }
} }
#if (_MI_PAGING_LEVELS == 2)
BOOLEAN
FORCEINLINE
MiSynchronizeSystemPde(PMMPDE PointerPde)
{
MMPDE SystemPde;
ULONG Index;
/* Get the Index from the PDE */
Index = ((ULONG_PTR)PointerPde & (SYSTEM_PD_SIZE - 1)) / sizeof(MMPTE);
/* Copy the PDE from the double-mapped system page directory */
SystemPde = MmSystemPagePtes[Index];
*PointerPde = SystemPde;
/* Make sure we re-read the PDE and PTE */
KeMemoryBarrierWithoutFence();
/* Return, if we had success */
return (BOOLEAN)SystemPde.u.Hard.Valid;
}
NTSTATUS NTSTATUS
FASTCALL FASTCALL
MiCheckPdeForPagedPool(IN PVOID Address) MiCheckPdeForPagedPool(IN PVOID Address)
@ -159,6 +181,7 @@ MiCheckPdeForPagedPool(IN PVOID Address)
// //
return Status; return Status;
} }
#endif
VOID VOID
NTAPI NTAPI
@ -699,28 +722,12 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
/* Check if the PDE is invalid */ /* Check if the PDE is invalid */
if (PointerPde->u.Hard.Valid == 0) if (PointerPde->u.Hard.Valid == 0)
{ {
//
// Debug spew (eww!)
//
DPRINT("Invalid PDE\n");
#if (_MI_PAGING_LEVELS == 2) #if (_MI_PAGING_LEVELS == 2)
// /* Sync this PDE and check, if that made it valid */
// Handle mapping in "Special" PDE directoreis if (!MiSynchronizeSystemPde(PointerPde))
//
MiCheckPdeForPagedPool(Address);
#endif #endif
//
// Now we SHOULD be good
//
if (PointerPde->u.Hard.Valid == 0)
{ {
// /* PDE (still) not valid, kill the system */
// FIXFIX: Do the S-LIST hack
//
//
// Kill the system
//
KeBugCheckEx(PAGE_FAULT_IN_NONPAGED_AREA, KeBugCheckEx(PAGE_FAULT_IN_NONPAGED_AREA,
(ULONG_PTR)Address, (ULONG_PTR)Address,
StoreInstruction, StoreInstruction,
@ -824,15 +831,14 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
(ULONG_PTR)TrapInformation, (ULONG_PTR)TrapInformation,
1); 1);
} }
}
/* Check for demand page */ /* Check for demand page */
if ((StoreInstruction) && !(ProtoPte) && !(TempPte.u.Hard.Valid)) if ((StoreInstruction) && !(TempPte.u.Hard.Valid))
{ {
/* Get the protection code */ /* Get the protection code */
if (!(TempPte.u.Soft.Protection & MM_READWRITE)) if (!(TempPte.u.Soft.Protection & MM_READWRITE))
{ {
/* Bad boy, bad boy, whatcha gonna do, whatcha gonna do when ARM3 comes for you! */ /* Bugcheck the system! */
KeBugCheckEx(ATTEMPTED_WRITE_TO_READONLY_MEMORY, KeBugCheckEx(ATTEMPTED_WRITE_TO_READONLY_MEMORY,
(ULONG_PTR)Address, (ULONG_PTR)Address,
TempPte.u.Long, TempPte.u.Long,
@ -840,6 +846,7 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
14); 14);
} }
} }
}
/* Now do the real fault handling */ /* Now do the real fault handling */
Status = MiDispatchFault(StoreInstruction, Status = MiDispatchFault(StoreInstruction,
@ -889,21 +896,15 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
/* Right now, we expect a valid protection mask on the VAD */ /* Right now, we expect a valid protection mask on the VAD */
ASSERT(ProtectionCode != MM_NOACCESS); ASSERT(ProtectionCode != MM_NOACCESS);
/* Make the PDE demand-zero */
MI_WRITE_INVALID_PDE(PointerPde, DemandZeroPde);
/* And go dispatch the fault on the PDE. This should handle the demand-zero */ /* And go dispatch the fault on the PDE. This should handle the demand-zero */
#if MI_TRACE_PFNS #if MI_TRACE_PFNS
UserPdeFault = TRUE; UserPdeFault = TRUE;
#endif #endif
Status = MiDispatchFault(TRUE, /* Resolve a demand zero fault */
PointerPte, Status = MiResolveDemandZeroFault(PointerPte,
(PMMPTE)PointerPde, MM_READWRITE,
NULL, CurrentProcess,
FALSE, MM_NOIRQL);
PsGetCurrentProcess(),
TrapInformation,
NULL);
#if MI_TRACE_PFNS #if MI_TRACE_PFNS
UserPdeFault = FALSE; UserPdeFault = FALSE;
#endif #endif
@ -930,15 +931,14 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
return STATUS_PAGE_FAULT_DEMAND_ZERO; return STATUS_PAGE_FAULT_DEMAND_ZERO;
} }
/* Get protection and check if it's a prototype PTE */ /* Make sure it's not a prototype PTE */
ProtectionCode = (ULONG)TempPte.u.Soft.Protection;
ASSERT(TempPte.u.Soft.Prototype == 0); ASSERT(TempPte.u.Soft.Prototype == 0);
/* Check for non-demand zero PTE */ /* Check for non-demand zero PTE */
if (TempPte.u.Long != 0) if (TempPte.u.Long != 0)
{ {
/* This is a page fault, check for valid protection */ /* This is a page fault, check for valid protection */
ASSERT(ProtectionCode != 0x100); ASSERT(TempPte.u.Soft.Protection != 0x100);
/* FIXME: Run MiAccessCheck */ /* FIXME: Run MiAccessCheck */