mirror of
https://github.com/reactos/reactos.git
synced 2025-01-03 21:09:19 +00:00
[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:
parent
a2cb9d5ee2
commit
838bc812fe
1 changed files with 59 additions and 13 deletions
|
@ -841,12 +841,14 @@ MiDispatchFault(IN BOOLEAN StoreInstruction,
|
|||
IN BOOLEAN Recursive,
|
||||
IN PEPROCESS Process,
|
||||
IN PVOID TrapInformation,
|
||||
IN PVOID Vad)
|
||||
IN PMMVAD Vad)
|
||||
{
|
||||
MMPTE TempPte;
|
||||
KIRQL OldIrql, LockIrql;
|
||||
NTSTATUS Status;
|
||||
PMMPTE SuperProtoPte;
|
||||
PMMPFN Pfn1;
|
||||
PFN_NUMBER PageFrameIndex, PteCount, ProcessedPtes;
|
||||
DPRINT("ARM3 Page Fault Dispatcher for address: %p in process: %p\n",
|
||||
Address,
|
||||
Process);
|
||||
|
@ -910,29 +912,73 @@ MiDispatchFault(IN BOOLEAN StoreInstruction,
|
|||
}
|
||||
else
|
||||
{
|
||||
/* We currently only handle very limited paths */
|
||||
ASSERT(PointerPte->u.Soft.Prototype == 1);
|
||||
/* We only handle the lookup path */
|
||||
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 */
|
||||
LockIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
||||
|
||||
/* For our current usage, this should be true */
|
||||
/* We only handle the valid path */
|
||||
ASSERT(SuperProtoPte->u.Hard.Valid == 1);
|
||||
ASSERT(TempPte.u.Hard.Valid == 0);
|
||||
|
||||
/* Resolve the fault -- this will release the PFN lock */
|
||||
Status = MiResolveProtoPteFault(StoreInstruction,
|
||||
/* Capture the PTE */
|
||||
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,
|
||||
PointerPte,
|
||||
PointerProtoPte,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
Process,
|
||||
LockIrql,
|
||||
TrapInformation);
|
||||
ASSERT(Status == STATUS_SUCCESS);
|
||||
NULL);
|
||||
|
||||
/* 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 */
|
||||
ASSERT(OldIrql == KeGetCurrentIrql());
|
||||
|
|
Loading…
Reference in a new issue