mirror of
https://github.com/reactos/reactos.git
synced 2025-01-05 13:59:25 +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 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());
|
||||||
|
|
Loading…
Reference in a new issue