mirror of
https://github.com/reactos/reactos.git
synced 2024-07-02 02:34:53 +00:00
[ÇNTOSKRNL]
- modify MiResolveDemandZeroFault to take the page protection as a parameter instead of the PTE. This will be used soon. - Move increment of counters into the region where the pfn lock is held to avoid race conditions and make heavy locked operations unneccessary - Add some ASSERTs svn path=/trunk/; revision=55454
This commit is contained in:
parent
12f8a6d6a6
commit
b207b33d11
|
@ -209,11 +209,12 @@ MiZeroPfn(IN PFN_NUMBER PageFrameNumber)
|
|||
NTSTATUS
|
||||
NTAPI
|
||||
MiResolveDemandZeroFault(IN PVOID Address,
|
||||
IN PMMPTE PointerPte,
|
||||
IN ULONG Protection,
|
||||
IN PEPROCESS Process,
|
||||
IN KIRQL OldIrql)
|
||||
{
|
||||
PFN_NUMBER PageFrameNumber = 0;
|
||||
PMMPTE PointerPte = MiAddressToPte(Address);
|
||||
MMPTE TempPte;
|
||||
BOOLEAN NeedZero = FALSE, HaveLock = FALSE;
|
||||
ULONG Color;
|
||||
|
@ -294,14 +295,12 @@ MiResolveDemandZeroFault(IN PVOID Address,
|
|||
/* Initialize it */
|
||||
MiInitializePfn(PageFrameNumber, PointerPte, TRUE);
|
||||
|
||||
/* Increment demand zero faults */
|
||||
KeGetCurrentPrcb()->MmDemandZeroCount++;
|
||||
|
||||
/* Release PFN lock if needed */
|
||||
if (HaveLock) KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
||||
|
||||
//
|
||||
// Increment demand zero faults
|
||||
//
|
||||
InterlockedIncrement(&KeGetCurrentPrcb()->MmDemandZeroCount);
|
||||
|
||||
/* Zero the page if need be */
|
||||
if (NeedZero) MiZeroPfn(PageFrameNumber);
|
||||
|
||||
|
@ -311,7 +310,7 @@ MiResolveDemandZeroFault(IN PVOID Address,
|
|||
/* For user mode */
|
||||
MI_MAKE_HARDWARE_PTE_USER(&TempPte,
|
||||
PointerPte,
|
||||
PointerPte->u.Soft.Protection,
|
||||
Protection,
|
||||
PageFrameNumber);
|
||||
}
|
||||
else
|
||||
|
@ -319,7 +318,7 @@ MiResolveDemandZeroFault(IN PVOID Address,
|
|||
/* For kernel mode */
|
||||
MI_MAKE_HARDWARE_PTE(&TempPte,
|
||||
PointerPte,
|
||||
PointerPte->u.Soft.Protection,
|
||||
Protection,
|
||||
PageFrameNumber);
|
||||
}
|
||||
|
||||
|
@ -462,7 +461,10 @@ MiResolveProtoPteFault(IN BOOLEAN StoreInstruction,
|
|||
ASSERT(TempPte.u.Soft.Transition == 0);
|
||||
|
||||
/* Resolve the demand zero fault */
|
||||
Status = MiResolveDemandZeroFault(Address, PointerProtoPte, Process, OldIrql);
|
||||
Status = MiResolveDemandZeroFault(Address,
|
||||
(ULONG)PointerProtoPte->u.Soft.Protection,
|
||||
Process,
|
||||
OldIrql);
|
||||
ASSERT(NT_SUCCESS(Status));
|
||||
|
||||
/* Complete the prototype PTE fault -- this will release the PFN lock */
|
||||
|
@ -494,6 +496,9 @@ MiDispatchFault(IN BOOLEAN StoreInstruction,
|
|||
Address,
|
||||
Process);
|
||||
|
||||
/* Make sure the addresses are ok */
|
||||
ASSERT(PointerPte == MiAddressToPte(Address));
|
||||
|
||||
//
|
||||
// Make sure APCs are off and we're not at dispatch
|
||||
//
|
||||
|
@ -609,7 +614,7 @@ MiDispatchFault(IN BOOLEAN StoreInstruction,
|
|||
// we want. Go handle it!
|
||||
//
|
||||
Status = MiResolveDemandZeroFault(Address,
|
||||
PointerPte,
|
||||
(ULONG)PointerPte->u.Soft.Protection,
|
||||
Process,
|
||||
MM_NOIRQL);
|
||||
ASSERT(KeAreAllApcsDisabled() == TRUE);
|
||||
|
@ -658,30 +663,23 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
|
|||
|
||||
DPRINT("ARM3 FAULT AT: %p\n", Address);
|
||||
|
||||
//
|
||||
// Check for dispatch-level snafu
|
||||
//
|
||||
/* Check for page fault on high IRQL */
|
||||
if (OldIrql > APC_LEVEL)
|
||||
{
|
||||
//
|
||||
// There are some special cases where this is okay, but not in ARM3 yet
|
||||
//
|
||||
DbgPrint("MM:***PAGE FAULT AT IRQL > 1 Va %p, IRQL %lx\n",
|
||||
Address,
|
||||
OldIrql);
|
||||
ASSERT(OldIrql <= APC_LEVEL);
|
||||
}
|
||||
|
||||
//
|
||||
// Check for kernel fault address
|
||||
//
|
||||
/* Check for kernel fault address */
|
||||
while (Address >= MmSystemRangeStart)
|
||||
{
|
||||
//
|
||||
// What are you even DOING here?
|
||||
//
|
||||
/* Bail out, if the fault came from user mode */
|
||||
if (Mode == UserMode) return STATUS_ACCESS_VIOLATION;
|
||||
|
||||
/* PXEs and PPEs for kernel mode are mapped for everything we need */
|
||||
#if (_MI_PAGING_LEVELS >= 3)
|
||||
if (
|
||||
#if (_MI_PAGING_LEVELS == 4)
|
||||
|
@ -689,6 +687,7 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
|
|||
#endif
|
||||
(PointerPpe->u.Hard.Valid == 0))
|
||||
{
|
||||
/* The address is not from any pageable area! */
|
||||
KeBugCheckEx(PAGE_FAULT_IN_NONPAGED_AREA,
|
||||
(ULONG_PTR)Address,
|
||||
StoreInstruction,
|
||||
|
@ -697,9 +696,7 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
|
|||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
// Is the PDE valid?
|
||||
//
|
||||
/* Check if the PDE is invalid */
|
||||
if (PointerPde->u.Hard.Valid == 0)
|
||||
{
|
||||
//
|
||||
|
@ -732,9 +729,7 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
|
|||
}
|
||||
}
|
||||
|
||||
//
|
||||
// The PDE is valid, so read the PTE
|
||||
//
|
||||
/* The PDE is valid, so read the PTE */
|
||||
TempPte = *PointerPte;
|
||||
if (TempPte.u.Hard.Valid == 1)
|
||||
{
|
||||
|
@ -751,9 +746,7 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
|
|||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// Check for a fault on the page table or hyperspace itself
|
||||
//
|
||||
// Check for a fault on the page table or hyperspace
|
||||
if (MI_IS_PAGE_TABLE_OR_HYPER_ADDRESS(Address))
|
||||
{
|
||||
#if (_MI_PAGING_LEVELS == 2)
|
||||
|
@ -776,26 +769,21 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
|
|||
KeRaiseIrql(APC_LEVEL, &LockIrql);
|
||||
MiLockWorkingSet(CurrentThread, WorkingSet);
|
||||
|
||||
//
|
||||
// Re-read PTE now that the IRQL has been raised
|
||||
//
|
||||
/* Re-read PTE now that we own the lock */
|
||||
TempPte = *PointerPte;
|
||||
if (TempPte.u.Hard.Valid == 1)
|
||||
{
|
||||
//
|
||||
// Only two things can go wrong here:
|
||||
// Executing NX page (we couldn't care less)
|
||||
// Writing to a read-only page (the stuff ARM3 works with is write,
|
||||
// so again, moot point.
|
||||
//
|
||||
// so again, moot point).
|
||||
ASSERT(TempPte.u.Hard.Write == 1);
|
||||
|
||||
/* Release the working set */
|
||||
MiUnlockWorkingSet(CurrentThread, WorkingSet);
|
||||
KeLowerIrql(LockIrql);
|
||||
|
||||
//
|
||||
// Otherwise, the PDE was probably invalid, and all is good now
|
||||
//
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -823,15 +811,13 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
|
|||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// We don't implement transition PTEs
|
||||
//
|
||||
/* We don't implement transition PTEs */
|
||||
ASSERT(TempPte.u.Soft.Transition == 0);
|
||||
|
||||
/* Check for no-access PTE */
|
||||
if (TempPte.u.Soft.Protection == MM_NOACCESS)
|
||||
{
|
||||
/* Bad boy, bad boy, whatcha gonna do, whatcha gonna do when ARM3 comes for you! */
|
||||
/* Bugcheck the system! */
|
||||
KeBugCheckEx(PAGE_FAULT_IN_NONPAGED_AREA,
|
||||
(ULONG_PTR)Address,
|
||||
StoreInstruction,
|
||||
|
@ -855,9 +841,7 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
|
|||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Now do the real fault handling
|
||||
//
|
||||
/* Now do the real fault handling */
|
||||
Status = MiDispatchFault(StoreInstruction,
|
||||
Address,
|
||||
PointerPte,
|
||||
|
@ -872,9 +856,7 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
|
|||
MiUnlockWorkingSet(CurrentThread, WorkingSet);
|
||||
KeLowerIrql(LockIrql);
|
||||
|
||||
//
|
||||
// We are done!
|
||||
//
|
||||
/* We are done! */
|
||||
DPRINT("Fault resolved with status: %lx\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
@ -939,7 +921,7 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
|
|||
{
|
||||
/* Resolve the fault */
|
||||
MiResolveDemandZeroFault(Address,
|
||||
PointerPte,
|
||||
(ULONG)PointerPte->u.Soft.Protection,
|
||||
CurrentProcess,
|
||||
MM_NOIRQL);
|
||||
|
||||
|
@ -1038,11 +1020,12 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
|
|||
/* Initialize the PFN entry now */
|
||||
MiInitializePfn(PageFrameIndex, PointerPte, 1);
|
||||
|
||||
/* One more demand-zero fault */
|
||||
KeGetCurrentPrcb()->MmDemandZeroCount++;
|
||||
|
||||
/* And we're done with the lock */
|
||||
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
||||
|
||||
/* One more demand-zero fault */
|
||||
InterlockedIncrement(&KeGetCurrentPrcb()->MmDemandZeroCount);
|
||||
|
||||
/* Was the fault on an actual user page, or a kernel page for the user? */
|
||||
if (PointerPte <= MiHighestUserPte)
|
||||
|
|
Loading…
Reference in a new issue