mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 19:52:56 +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
1 changed files with 34 additions and 51 deletions
|
@ -209,11 +209,12 @@ MiZeroPfn(IN PFN_NUMBER PageFrameNumber)
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
MiResolveDemandZeroFault(IN PVOID Address,
|
MiResolveDemandZeroFault(IN PVOID Address,
|
||||||
IN PMMPTE PointerPte,
|
IN ULONG Protection,
|
||||||
IN PEPROCESS Process,
|
IN PEPROCESS Process,
|
||||||
IN KIRQL OldIrql)
|
IN KIRQL OldIrql)
|
||||||
{
|
{
|
||||||
PFN_NUMBER PageFrameNumber = 0;
|
PFN_NUMBER PageFrameNumber = 0;
|
||||||
|
PMMPTE PointerPte = MiAddressToPte(Address);
|
||||||
MMPTE TempPte;
|
MMPTE TempPte;
|
||||||
BOOLEAN NeedZero = FALSE, HaveLock = FALSE;
|
BOOLEAN NeedZero = FALSE, HaveLock = FALSE;
|
||||||
ULONG Color;
|
ULONG Color;
|
||||||
|
@ -294,14 +295,12 @@ MiResolveDemandZeroFault(IN PVOID Address,
|
||||||
/* Initialize it */
|
/* Initialize it */
|
||||||
MiInitializePfn(PageFrameNumber, PointerPte, TRUE);
|
MiInitializePfn(PageFrameNumber, PointerPte, TRUE);
|
||||||
|
|
||||||
|
/* Increment demand zero faults */
|
||||||
|
KeGetCurrentPrcb()->MmDemandZeroCount++;
|
||||||
|
|
||||||
/* Release PFN lock if needed */
|
/* Release PFN lock if needed */
|
||||||
if (HaveLock) KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
if (HaveLock) KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
||||||
|
|
||||||
//
|
|
||||||
// Increment demand zero faults
|
|
||||||
//
|
|
||||||
InterlockedIncrement(&KeGetCurrentPrcb()->MmDemandZeroCount);
|
|
||||||
|
|
||||||
/* Zero the page if need be */
|
/* Zero the page if need be */
|
||||||
if (NeedZero) MiZeroPfn(PageFrameNumber);
|
if (NeedZero) MiZeroPfn(PageFrameNumber);
|
||||||
|
|
||||||
|
@ -311,7 +310,7 @@ MiResolveDemandZeroFault(IN PVOID Address,
|
||||||
/* For user mode */
|
/* For user mode */
|
||||||
MI_MAKE_HARDWARE_PTE_USER(&TempPte,
|
MI_MAKE_HARDWARE_PTE_USER(&TempPte,
|
||||||
PointerPte,
|
PointerPte,
|
||||||
PointerPte->u.Soft.Protection,
|
Protection,
|
||||||
PageFrameNumber);
|
PageFrameNumber);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -319,7 +318,7 @@ MiResolveDemandZeroFault(IN PVOID Address,
|
||||||
/* For kernel mode */
|
/* For kernel mode */
|
||||||
MI_MAKE_HARDWARE_PTE(&TempPte,
|
MI_MAKE_HARDWARE_PTE(&TempPte,
|
||||||
PointerPte,
|
PointerPte,
|
||||||
PointerPte->u.Soft.Protection,
|
Protection,
|
||||||
PageFrameNumber);
|
PageFrameNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -462,7 +461,10 @@ MiResolveProtoPteFault(IN BOOLEAN StoreInstruction,
|
||||||
ASSERT(TempPte.u.Soft.Transition == 0);
|
ASSERT(TempPte.u.Soft.Transition == 0);
|
||||||
|
|
||||||
/* Resolve the demand zero fault */
|
/* 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));
|
ASSERT(NT_SUCCESS(Status));
|
||||||
|
|
||||||
/* Complete the prototype PTE fault -- this will release the PFN lock */
|
/* Complete the prototype PTE fault -- this will release the PFN lock */
|
||||||
|
@ -494,6 +496,9 @@ MiDispatchFault(IN BOOLEAN StoreInstruction,
|
||||||
Address,
|
Address,
|
||||||
Process);
|
Process);
|
||||||
|
|
||||||
|
/* Make sure the addresses are ok */
|
||||||
|
ASSERT(PointerPte == MiAddressToPte(Address));
|
||||||
|
|
||||||
//
|
//
|
||||||
// Make sure APCs are off and we're not at dispatch
|
// Make sure APCs are off and we're not at dispatch
|
||||||
//
|
//
|
||||||
|
@ -609,7 +614,7 @@ MiDispatchFault(IN BOOLEAN StoreInstruction,
|
||||||
// we want. Go handle it!
|
// we want. Go handle it!
|
||||||
//
|
//
|
||||||
Status = MiResolveDemandZeroFault(Address,
|
Status = MiResolveDemandZeroFault(Address,
|
||||||
PointerPte,
|
(ULONG)PointerPte->u.Soft.Protection,
|
||||||
Process,
|
Process,
|
||||||
MM_NOIRQL);
|
MM_NOIRQL);
|
||||||
ASSERT(KeAreAllApcsDisabled() == TRUE);
|
ASSERT(KeAreAllApcsDisabled() == TRUE);
|
||||||
|
@ -658,30 +663,23 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
|
||||||
|
|
||||||
DPRINT("ARM3 FAULT AT: %p\n", Address);
|
DPRINT("ARM3 FAULT AT: %p\n", Address);
|
||||||
|
|
||||||
//
|
/* Check for page fault on high IRQL */
|
||||||
// Check for dispatch-level snafu
|
|
||||||
//
|
|
||||||
if (OldIrql > APC_LEVEL)
|
if (OldIrql > APC_LEVEL)
|
||||||
{
|
{
|
||||||
//
|
|
||||||
// There are some special cases where this is okay, but not in ARM3 yet
|
// 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",
|
DbgPrint("MM:***PAGE FAULT AT IRQL > 1 Va %p, IRQL %lx\n",
|
||||||
Address,
|
Address,
|
||||||
OldIrql);
|
OldIrql);
|
||||||
ASSERT(OldIrql <= APC_LEVEL);
|
ASSERT(OldIrql <= APC_LEVEL);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
/* Check for kernel fault address */
|
||||||
// Check for kernel fault address
|
|
||||||
//
|
|
||||||
while (Address >= MmSystemRangeStart)
|
while (Address >= MmSystemRangeStart)
|
||||||
{
|
{
|
||||||
//
|
/* Bail out, if the fault came from user mode */
|
||||||
// What are you even DOING here?
|
|
||||||
//
|
|
||||||
if (Mode == UserMode) return STATUS_ACCESS_VIOLATION;
|
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 (_MI_PAGING_LEVELS >= 3)
|
||||||
if (
|
if (
|
||||||
#if (_MI_PAGING_LEVELS == 4)
|
#if (_MI_PAGING_LEVELS == 4)
|
||||||
|
@ -689,6 +687,7 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
|
||||||
#endif
|
#endif
|
||||||
(PointerPpe->u.Hard.Valid == 0))
|
(PointerPpe->u.Hard.Valid == 0))
|
||||||
{
|
{
|
||||||
|
/* The address is not from any pageable area! */
|
||||||
KeBugCheckEx(PAGE_FAULT_IN_NONPAGED_AREA,
|
KeBugCheckEx(PAGE_FAULT_IN_NONPAGED_AREA,
|
||||||
(ULONG_PTR)Address,
|
(ULONG_PTR)Address,
|
||||||
StoreInstruction,
|
StoreInstruction,
|
||||||
|
@ -697,9 +696,7 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//
|
/* Check if the PDE is invalid */
|
||||||
// Is the PDE valid?
|
|
||||||
//
|
|
||||||
if (PointerPde->u.Hard.Valid == 0)
|
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;
|
TempPte = *PointerPte;
|
||||||
if (TempPte.u.Hard.Valid == 1)
|
if (TempPte.u.Hard.Valid == 1)
|
||||||
{
|
{
|
||||||
|
@ -751,9 +746,7 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
// Check for a fault on the page table or hyperspace
|
||||||
// Check for a fault on the page table or hyperspace itself
|
|
||||||
//
|
|
||||||
if (MI_IS_PAGE_TABLE_OR_HYPER_ADDRESS(Address))
|
if (MI_IS_PAGE_TABLE_OR_HYPER_ADDRESS(Address))
|
||||||
{
|
{
|
||||||
#if (_MI_PAGING_LEVELS == 2)
|
#if (_MI_PAGING_LEVELS == 2)
|
||||||
|
@ -776,26 +769,21 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
|
||||||
KeRaiseIrql(APC_LEVEL, &LockIrql);
|
KeRaiseIrql(APC_LEVEL, &LockIrql);
|
||||||
MiLockWorkingSet(CurrentThread, WorkingSet);
|
MiLockWorkingSet(CurrentThread, WorkingSet);
|
||||||
|
|
||||||
//
|
/* Re-read PTE now that we own the lock */
|
||||||
// Re-read PTE now that the IRQL has been raised
|
|
||||||
//
|
|
||||||
TempPte = *PointerPte;
|
TempPte = *PointerPte;
|
||||||
if (TempPte.u.Hard.Valid == 1)
|
if (TempPte.u.Hard.Valid == 1)
|
||||||
{
|
{
|
||||||
//
|
|
||||||
// Only two things can go wrong here:
|
// Only two things can go wrong here:
|
||||||
// Executing NX page (we couldn't care less)
|
// Executing NX page (we couldn't care less)
|
||||||
// Writing to a read-only page (the stuff ARM3 works with is write,
|
// 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 */
|
/* Release the working set */
|
||||||
MiUnlockWorkingSet(CurrentThread, WorkingSet);
|
MiUnlockWorkingSet(CurrentThread, WorkingSet);
|
||||||
KeLowerIrql(LockIrql);
|
KeLowerIrql(LockIrql);
|
||||||
|
|
||||||
//
|
|
||||||
// Otherwise, the PDE was probably invalid, and all is good now
|
// Otherwise, the PDE was probably invalid, and all is good now
|
||||||
//
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -823,15 +811,13 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//
|
/* We don't implement transition PTEs */
|
||||||
// We don't implement transition PTEs
|
|
||||||
//
|
|
||||||
ASSERT(TempPte.u.Soft.Transition == 0);
|
ASSERT(TempPte.u.Soft.Transition == 0);
|
||||||
|
|
||||||
/* Check for no-access PTE */
|
/* Check for no-access PTE */
|
||||||
if (TempPte.u.Soft.Protection == MM_NOACCESS)
|
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,
|
KeBugCheckEx(PAGE_FAULT_IN_NONPAGED_AREA,
|
||||||
(ULONG_PTR)Address,
|
(ULONG_PTR)Address,
|
||||||
StoreInstruction,
|
StoreInstruction,
|
||||||
|
@ -855,9 +841,7 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
/* Now do the real fault handling */
|
||||||
// Now do the real fault handling
|
|
||||||
//
|
|
||||||
Status = MiDispatchFault(StoreInstruction,
|
Status = MiDispatchFault(StoreInstruction,
|
||||||
Address,
|
Address,
|
||||||
PointerPte,
|
PointerPte,
|
||||||
|
@ -872,9 +856,7 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
|
||||||
MiUnlockWorkingSet(CurrentThread, WorkingSet);
|
MiUnlockWorkingSet(CurrentThread, WorkingSet);
|
||||||
KeLowerIrql(LockIrql);
|
KeLowerIrql(LockIrql);
|
||||||
|
|
||||||
//
|
/* We are done! */
|
||||||
// We are done!
|
|
||||||
//
|
|
||||||
DPRINT("Fault resolved with status: %lx\n", Status);
|
DPRINT("Fault resolved with status: %lx\n", Status);
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
@ -939,7 +921,7 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
|
||||||
{
|
{
|
||||||
/* Resolve the fault */
|
/* Resolve the fault */
|
||||||
MiResolveDemandZeroFault(Address,
|
MiResolveDemandZeroFault(Address,
|
||||||
PointerPte,
|
(ULONG)PointerPte->u.Soft.Protection,
|
||||||
CurrentProcess,
|
CurrentProcess,
|
||||||
MM_NOIRQL);
|
MM_NOIRQL);
|
||||||
|
|
||||||
|
@ -1038,11 +1020,12 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
|
||||||
/* Initialize the PFN entry now */
|
/* Initialize the PFN entry now */
|
||||||
MiInitializePfn(PageFrameIndex, PointerPte, 1);
|
MiInitializePfn(PageFrameIndex, PointerPte, 1);
|
||||||
|
|
||||||
|
/* One more demand-zero fault */
|
||||||
|
KeGetCurrentPrcb()->MmDemandZeroCount++;
|
||||||
|
|
||||||
/* And we're done with the lock */
|
/* And we're done with the lock */
|
||||||
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
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? */
|
/* Was the fault on an actual user page, or a kernel page for the user? */
|
||||||
if (PointerPte <= MiHighestUserPte)
|
if (PointerPte <= MiHighestUserPte)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue