[NTOSKRNL]: When dispatching a prototype PTE fault, call MiCompleteProtoPteFault instead of directly calling MiResolveProtoPteFault. Also add support/detection for clustering.

svn path=/trunk/; revision=57001
This commit is contained in:
Alex Ionescu 2012-07-31 07:32:19 +00:00
parent a2cb9d5ee2
commit 838bc812fe

View file

@ -841,12 +841,14 @@ MiDispatchFault(IN BOOLEAN StoreInstruction,
IN BOOLEAN Recursive, IN BOOLEAN Recursive,
IN PEPROCESS Process, IN PEPROCESS Process,
IN PVOID TrapInformation, IN PVOID TrapInformation,
IN PVOID Vad) IN PMMVAD Vad)
{ {
MMPTE TempPte; MMPTE TempPte;
KIRQL OldIrql, LockIrql; KIRQL OldIrql, LockIrql;
NTSTATUS Status; NTSTATUS Status;
PMMPTE SuperProtoPte; PMMPTE SuperProtoPte;
PMMPFN Pfn1;
PFN_NUMBER PageFrameIndex, PteCount, ProcessedPtes;
DPRINT("ARM3 Page Fault Dispatcher for address: %p in process: %p\n", DPRINT("ARM3 Page Fault Dispatcher for address: %p in process: %p\n",
Address, Address,
Process); Process);
@ -910,29 +912,73 @@ MiDispatchFault(IN BOOLEAN StoreInstruction,
} }
else else
{ {
/* We currently only handle very limited paths */ /* We only handle the lookup path */
ASSERT(PointerPte->u.Soft.Prototype == 1);
ASSERT(PointerPte->u.Soft.PageFileHigh == MI_PTE_LOOKUP_NEEDED); ASSERT(PointerPte->u.Soft.PageFileHigh == MI_PTE_LOOKUP_NEEDED);
/* Is there a non-image VAD? */
if ((Vad) &&
(Vad->u.VadFlags.VadType != VadImageMap) &&
!(Vad->u2.VadFlags2.ExtendableFile))
{
/* One day, ReactOS will cluster faults */
ASSERT(Address <= MM_HIGHEST_USER_ADDRESS);
DPRINT("Should cluster fault, but won't\n");
}
/* Only one PTE to handle for now */
PteCount = 1;
ProcessedPtes = 0;
/* Lock the PFN database */ /* Lock the PFN database */
LockIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock); LockIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
/* For our current usage, this should be true */ /* We only handle the valid path */
ASSERT(SuperProtoPte->u.Hard.Valid == 1); ASSERT(SuperProtoPte->u.Hard.Valid == 1);
ASSERT(TempPte.u.Hard.Valid == 0);
/* Resolve the fault -- this will release the PFN lock */ /* Capture the PTE */
Status = MiResolveProtoPteFault(StoreInstruction, TempPte = *PointerProtoPte;
/* Loop to handle future case of clustered faults */
while (TRUE)
{
/* For our current usage, this should be true */
ASSERT(TempPte.u.Hard.Valid == 1);
ASSERT(TempPte.u.Soft.Prototype == 0);
ASSERT(TempPte.u.Soft.Transition == 0);
/* Bump the share count on the PTE */
PageFrameIndex = PFN_FROM_PTE(&TempPte);
Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
Pfn1->u2.ShareCount++;
/* One more done, was it the last? */
if (++ProcessedPtes == PteCount)
{
/* Complete the fault */
MiCompleteProtoPteFault(StoreInstruction,
Address, Address,
PointerPte, PointerPte,
PointerProtoPte, PointerProtoPte,
NULL,
NULL,
NULL,
Process,
LockIrql, LockIrql,
TrapInformation); NULL);
ASSERT(Status == STATUS_SUCCESS);
/* THIS RELEASES THE PFN LOCK! */
break;
}
/* No clustered faults yet */
ASSERT(FALSE);
}
/* Only path that we support for now */
ASSERT(ProcessedPtes != 0);
/* Bump the transition count */
InterlockedExchangeAdd(&KeGetCurrentPrcb()->MmTransitionCount, ProcessedPtes);
ProcessedPtes--;
/* Loop all the processing we did */
ASSERT(ProcessedPtes == 0);
/* Complete this as a transition fault */ /* Complete this as a transition fault */
ASSERT(OldIrql == KeGetCurrentIrql()); ASSERT(OldIrql == KeGetCurrentIrql());