mirror of
https://github.com/reactos/reactos.git
synced 2025-02-22 16:36:33 +00:00
Revert "[NTOS:MM] Add private pages to process working sets"
This is so full of bugs, I don't know what to say.
This reverts commit 374fef2d59
.
This commit is contained in:
parent
969e60a06d
commit
7eff8a36d5
4 changed files with 63 additions and 106 deletions
|
@ -1674,21 +1674,6 @@ VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
MiInitializeWorkingSetList(_Inout_ PMMSUPPORT WorkingSet);
|
MiInitializeWorkingSetList(_Inout_ PMMSUPPORT WorkingSet);
|
||||||
|
|
||||||
_Requires_exclusive_lock_held_(Vm->WorkingSetMutex)
|
|
||||||
VOID
|
|
||||||
NTAPI
|
|
||||||
MiInsertInWorkingSetList(
|
|
||||||
_Inout_ PMMSUPPORT Vm,
|
|
||||||
_In_ PVOID Address,
|
|
||||||
_In_ ULONG Protection);
|
|
||||||
|
|
||||||
_Requires_exclusive_lock_held_(Vm->WorkingSetMutex)
|
|
||||||
VOID
|
|
||||||
NTAPI
|
|
||||||
MiRemoveFromWorkingSetList(
|
|
||||||
_Inout_ PMMSUPPORT Vm,
|
|
||||||
_In_ PVOID Address);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
|
|
||||||
|
|
|
@ -697,6 +697,16 @@ MiResolveDemandZeroFault(IN PVOID Address,
|
||||||
/* Increment demand zero faults */
|
/* Increment demand zero faults */
|
||||||
KeGetCurrentPrcb()->MmDemandZeroCount++;
|
KeGetCurrentPrcb()->MmDemandZeroCount++;
|
||||||
|
|
||||||
|
/* Do we have the lock? */
|
||||||
|
if (HaveLock)
|
||||||
|
{
|
||||||
|
/* Release it */
|
||||||
|
MiReleasePfnLock(OldIrql);
|
||||||
|
|
||||||
|
/* Update performance counters */
|
||||||
|
if (Process > HYDRA_PROCESS) Process->NumberOfPrivatePages++;
|
||||||
|
}
|
||||||
|
|
||||||
/* Zero the page if need be */
|
/* Zero the page if need be */
|
||||||
if (NeedZero) MiZeroPfn(PageFrameNumber);
|
if (NeedZero) MiZeroPfn(PageFrameNumber);
|
||||||
|
|
||||||
|
@ -733,19 +743,6 @@ MiResolveDemandZeroFault(IN PVOID Address,
|
||||||
/* Windows does these sanity checks */
|
/* Windows does these sanity checks */
|
||||||
ASSERT(Pfn1->u1.Event == 0);
|
ASSERT(Pfn1->u1.Event == 0);
|
||||||
ASSERT(Pfn1->u3.e1.PrototypePte == 0);
|
ASSERT(Pfn1->u3.e1.PrototypePte == 0);
|
||||||
|
|
||||||
/* Release it */
|
|
||||||
MiReleasePfnLock(OldIrql);
|
|
||||||
|
|
||||||
/* Update performance counters */
|
|
||||||
if (Process > HYDRA_PROCESS) Process->NumberOfPrivatePages++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add the page to our working set, if it's not a proto PTE */
|
|
||||||
if ((Process > HYDRA_PROCESS) && (PointerPte == MiAddressToPte(Address)))
|
|
||||||
{
|
|
||||||
/* FIXME: Also support session VM scenario */
|
|
||||||
MiInsertInWorkingSetList(&Process->Vm, Address, Protection);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -965,9 +962,6 @@ MiResolvePageFileFault(_In_ BOOLEAN StoreInstruction,
|
||||||
KeSetEvent(Pfn1->u1.Event, IO_NO_INCREMENT, FALSE);
|
KeSetEvent(Pfn1->u1.Event, IO_NO_INCREMENT, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* And we can insert this into the working set */
|
|
||||||
MiInsertInWorkingSetList(&CurrentProcess->Vm, FaultingAddress, Protection);
|
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -985,8 +979,6 @@ MiResolveTransitionFault(IN BOOLEAN StoreInstruction,
|
||||||
PMMPFN Pfn1;
|
PMMPFN Pfn1;
|
||||||
MMPTE TempPte;
|
MMPTE TempPte;
|
||||||
PMMPTE PointerToPteForProtoPage;
|
PMMPTE PointerToPteForProtoPage;
|
||||||
ULONG Protection;
|
|
||||||
|
|
||||||
DPRINT("Transition fault on 0x%p with PTE 0x%p in process %s\n",
|
DPRINT("Transition fault on 0x%p with PTE 0x%p in process %s\n",
|
||||||
FaultingAddress, PointerPte, CurrentProcess->ImageFileName);
|
FaultingAddress, PointerPte, CurrentProcess->ImageFileName);
|
||||||
|
|
||||||
|
@ -1080,9 +1072,8 @@ MiResolveTransitionFault(IN BOOLEAN StoreInstruction,
|
||||||
ASSERT(PointerPte->u.Hard.Valid == 0);
|
ASSERT(PointerPte->u.Hard.Valid == 0);
|
||||||
ASSERT(PointerPte->u.Trans.Prototype == 0);
|
ASSERT(PointerPte->u.Trans.Prototype == 0);
|
||||||
ASSERT(PointerPte->u.Trans.Transition == 1);
|
ASSERT(PointerPte->u.Trans.Transition == 1);
|
||||||
Protection = TempPte.u.Trans.Protection;
|
|
||||||
TempPte.u.Long = (PointerPte->u.Long & ~0xFFF) |
|
TempPte.u.Long = (PointerPte->u.Long & ~0xFFF) |
|
||||||
(MmProtectToPteMask[Protection]) |
|
(MmProtectToPteMask[PointerPte->u.Trans.Protection]) |
|
||||||
MiDetermineUserGlobalPteMask(PointerPte);
|
MiDetermineUserGlobalPteMask(PointerPte);
|
||||||
|
|
||||||
/* Is the PTE writeable? */
|
/* Is the PTE writeable? */
|
||||||
|
@ -1102,10 +1093,6 @@ MiResolveTransitionFault(IN BOOLEAN StoreInstruction,
|
||||||
/* Write the valid PTE */
|
/* Write the valid PTE */
|
||||||
MI_WRITE_VALID_PTE(PointerPte, TempPte);
|
MI_WRITE_VALID_PTE(PointerPte, TempPte);
|
||||||
|
|
||||||
/* If this was a user fault, add it to the working set */
|
|
||||||
if (CurrentProcess > HYDRA_PROCESS)
|
|
||||||
MiInsertInWorkingSetList(&CurrentProcess->Vm, FaultingAddress, Protection);
|
|
||||||
|
|
||||||
/* Return success */
|
/* Return success */
|
||||||
return STATUS_PAGE_FAULT_TRANSITION;
|
return STATUS_PAGE_FAULT_TRANSITION;
|
||||||
}
|
}
|
||||||
|
@ -1247,9 +1234,6 @@ MiResolveProtoPteFault(IN BOOLEAN StoreInstruction,
|
||||||
Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
|
Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
|
||||||
MiInitializePfn(PageFrameIndex, PointerPte, TRUE);
|
MiInitializePfn(PageFrameIndex, PointerPte, TRUE);
|
||||||
|
|
||||||
/* The caller expects us to release the PFN lock */
|
|
||||||
MiReleasePfnLock(OldIrql);
|
|
||||||
|
|
||||||
/* Fix the protection */
|
/* Fix the protection */
|
||||||
Protection &= ~MM_WRITECOPY;
|
Protection &= ~MM_WRITECOPY;
|
||||||
Protection |= MM_READWRITE;
|
Protection |= MM_READWRITE;
|
||||||
|
@ -1267,12 +1251,8 @@ MiResolveProtoPteFault(IN BOOLEAN StoreInstruction,
|
||||||
/* And finally, write the valid PTE */
|
/* And finally, write the valid PTE */
|
||||||
MI_WRITE_VALID_PTE(PointerPte, PteContents);
|
MI_WRITE_VALID_PTE(PointerPte, PteContents);
|
||||||
|
|
||||||
/* Add the page to our working set */
|
/* The caller expects us to release the PFN lock */
|
||||||
if (Process > HYDRA_PROCESS)
|
MiReleasePfnLock(OldIrql);
|
||||||
{
|
|
||||||
/* FIXME: Also support session VM scenario */
|
|
||||||
MiInsertInWorkingSetList(&Process->Vm, Address, Protection);
|
|
||||||
}
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2231,7 +2211,6 @@ UserFault:
|
||||||
{
|
{
|
||||||
PFN_NUMBER PageFrameIndex, OldPageFrameIndex;
|
PFN_NUMBER PageFrameIndex, OldPageFrameIndex;
|
||||||
PMMPFN Pfn1;
|
PMMPFN Pfn1;
|
||||||
ProtectionCode = TempPte.u.Soft.Protection;
|
|
||||||
|
|
||||||
LockIrql = MiAcquirePfnLock();
|
LockIrql = MiAcquirePfnLock();
|
||||||
|
|
||||||
|
@ -2255,18 +2234,13 @@ UserFault:
|
||||||
|
|
||||||
/* And make a new shiny one with our page */
|
/* And make a new shiny one with our page */
|
||||||
MiInitializePfn(PageFrameIndex, PointerPte, TRUE);
|
MiInitializePfn(PageFrameIndex, PointerPte, TRUE);
|
||||||
|
|
||||||
MiReleasePfnLock(LockIrql);
|
|
||||||
|
|
||||||
TempPte.u.Hard.PageFrameNumber = PageFrameIndex;
|
TempPte.u.Hard.PageFrameNumber = PageFrameIndex;
|
||||||
TempPte.u.Hard.Write = 1;
|
TempPte.u.Hard.Write = 1;
|
||||||
TempPte.u.Hard.CopyOnWrite = 0;
|
TempPte.u.Hard.CopyOnWrite = 0;
|
||||||
|
|
||||||
MI_WRITE_VALID_PTE(PointerPte, TempPte);
|
MI_WRITE_VALID_PTE(PointerPte, TempPte);
|
||||||
|
|
||||||
/* We can now add it to our working set */
|
MiReleasePfnLock(LockIrql);
|
||||||
MiInsertInWorkingSetList(&CurrentProcess->Vm, Address, ProtectionCode);
|
|
||||||
|
|
||||||
|
|
||||||
/* Return the status */
|
/* Return the status */
|
||||||
MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
|
MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
|
||||||
|
@ -2383,7 +2357,6 @@ UserFault:
|
||||||
TempPte.u.Soft.Protection = ProtectionCode;
|
TempPte.u.Soft.Protection = ProtectionCode;
|
||||||
MI_WRITE_INVALID_PTE(PointerPte, TempPte);
|
MI_WRITE_INVALID_PTE(PointerPte, TempPte);
|
||||||
}
|
}
|
||||||
ProtectionCode = PointerPte->u.Soft.Protection;
|
|
||||||
|
|
||||||
/* Lock the PFN database since we're going to grab a page */
|
/* Lock the PFN database since we're going to grab a page */
|
||||||
OldIrql = MiAcquirePfnLock();
|
OldIrql = MiAcquirePfnLock();
|
||||||
|
@ -2415,14 +2388,14 @@ UserFault:
|
||||||
/* Initialize the PFN entry now */
|
/* Initialize the PFN entry now */
|
||||||
MiInitializePfn(PageFrameIndex, PointerPte, 1);
|
MiInitializePfn(PageFrameIndex, PointerPte, 1);
|
||||||
|
|
||||||
/* And be done with the lock */
|
|
||||||
MiReleasePfnLock(OldIrql);
|
|
||||||
|
|
||||||
/* Increment the count of pages in the process */
|
/* Increment the count of pages in the process */
|
||||||
CurrentProcess->NumberOfPrivatePages++;
|
CurrentProcess->NumberOfPrivatePages++;
|
||||||
|
|
||||||
/* One more demand-zero fault */
|
/* One more demand-zero fault */
|
||||||
InterlockedIncrement(&KeGetCurrentPrcb()->MmDemandZeroCount);
|
KeGetCurrentPrcb()->MmDemandZeroCount++;
|
||||||
|
|
||||||
|
/* And we're done with the lock */
|
||||||
|
MiReleasePfnLock(OldIrql);
|
||||||
|
|
||||||
/* Fault on user PDE, or fault on user PTE? */
|
/* Fault on user PDE, or fault on user PTE? */
|
||||||
if (PointerPte <= MiHighestUserPte)
|
if (PointerPte <= MiHighestUserPte)
|
||||||
|
@ -2450,9 +2423,6 @@ UserFault:
|
||||||
Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
|
Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
|
||||||
ASSERT(Pfn1->u1.Event == NULL);
|
ASSERT(Pfn1->u1.Event == NULL);
|
||||||
|
|
||||||
/* We can now insert it into the working set */
|
|
||||||
MiInsertInWorkingSetList(&CurrentProcess->Vm, Address, ProtectionCode);
|
|
||||||
|
|
||||||
/* Demand zero */
|
/* Demand zero */
|
||||||
ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
|
ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
|
||||||
MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
|
MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
|
||||||
|
|
|
@ -398,6 +398,9 @@ MiDeletePte(IN PMMPTE PointerPte,
|
||||||
PFN_NUMBER PageFrameIndex;
|
PFN_NUMBER PageFrameIndex;
|
||||||
PMMPDE PointerPde;
|
PMMPDE PointerPde;
|
||||||
|
|
||||||
|
/* PFN lock must be held */
|
||||||
|
MI_ASSERT_PFN_LOCK_HELD();
|
||||||
|
|
||||||
/* Capture the PTE */
|
/* Capture the PTE */
|
||||||
TempPte = *PointerPte;
|
TempPte = *PointerPte;
|
||||||
|
|
||||||
|
@ -422,8 +425,6 @@ MiDeletePte(IN PMMPTE PointerPte,
|
||||||
/* Destroy the PTE */
|
/* Destroy the PTE */
|
||||||
MI_ERASE_PTE(PointerPte);
|
MI_ERASE_PTE(PointerPte);
|
||||||
|
|
||||||
KIRQL OldIrql = MiAcquirePfnLock();
|
|
||||||
|
|
||||||
/* Drop the reference on the page table. */
|
/* Drop the reference on the page table. */
|
||||||
MiDecrementShareCount(MiGetPfnEntry(Pfn1->u4.PteFrame), Pfn1->u4.PteFrame);
|
MiDecrementShareCount(MiGetPfnEntry(Pfn1->u4.PteFrame), Pfn1->u4.PteFrame);
|
||||||
|
|
||||||
|
@ -443,8 +444,6 @@ MiDeletePte(IN PMMPTE PointerPte,
|
||||||
MI_SET_PFN_DELETED(Pfn1);
|
MI_SET_PFN_DELETED(Pfn1);
|
||||||
MiDecrementReferenceCount(Pfn1, PageFrameIndex);
|
MiDecrementReferenceCount(Pfn1, PageFrameIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
MiReleasePfnLock(OldIrql);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -475,8 +474,6 @@ MiDeletePte(IN PMMPTE PointerPte,
|
||||||
#if (_MI_PAGING_LEVELS == 2)
|
#if (_MI_PAGING_LEVELS == 2)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
KIRQL OldIrql = MiAcquirePfnLock();
|
|
||||||
/* Drop the share count on the page table */
|
/* Drop the share count on the page table */
|
||||||
PointerPde = MiPteToPde(PointerPte);
|
PointerPde = MiPteToPde(PointerPte);
|
||||||
MiDecrementShareCount(MiGetPfnEntry(PointerPde->u.Hard.PageFrameNumber),
|
MiDecrementShareCount(MiGetPfnEntry(PointerPde->u.Hard.PageFrameNumber),
|
||||||
|
@ -484,7 +481,6 @@ MiDeletePte(IN PMMPTE PointerPte,
|
||||||
|
|
||||||
/* Drop the share count */
|
/* Drop the share count */
|
||||||
MiDecrementShareCount(Pfn1, PageFrameIndex);
|
MiDecrementShareCount(Pfn1, PageFrameIndex);
|
||||||
MiReleasePfnLock(OldIrql);
|
|
||||||
|
|
||||||
/* Either a fork, or this is the shared user data page */
|
/* Either a fork, or this is the shared user data page */
|
||||||
if ((PointerPte <= MiHighestUserPte) && (PrototypePte != Pfn1->PteAddress))
|
if ((PointerPte <= MiHighestUserPte) && (PrototypePte != Pfn1->PteAddress))
|
||||||
|
@ -507,9 +503,6 @@ MiDeletePte(IN PMMPTE PointerPte,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Remove this address from the WS list */
|
|
||||||
MiRemoveFromWorkingSetList(&CurrentProcess->Vm, VirtualAddress);
|
|
||||||
|
|
||||||
/* Make sure the saved PTE address is valid */
|
/* Make sure the saved PTE address is valid */
|
||||||
if ((PMMPTE)((ULONG_PTR)Pfn1->PteAddress & ~0x1) != PointerPte)
|
if ((PMMPTE)((ULONG_PTR)Pfn1->PteAddress & ~0x1) != PointerPte)
|
||||||
{
|
{
|
||||||
|
@ -524,7 +517,6 @@ MiDeletePte(IN PMMPTE PointerPte,
|
||||||
/* Erase the PTE */
|
/* Erase the PTE */
|
||||||
MI_ERASE_PTE(PointerPte);
|
MI_ERASE_PTE(PointerPte);
|
||||||
|
|
||||||
KIRQL OldIrql = MiAcquirePfnLock();
|
|
||||||
/* There should only be 1 shared reference count */
|
/* There should only be 1 shared reference count */
|
||||||
ASSERT(Pfn1->u2.ShareCount == 1);
|
ASSERT(Pfn1->u2.ShareCount == 1);
|
||||||
|
|
||||||
|
@ -534,7 +526,6 @@ MiDeletePte(IN PMMPTE PointerPte,
|
||||||
/* Mark the PFN for deletion and dereference what should be the last ref */
|
/* Mark the PFN for deletion and dereference what should be the last ref */
|
||||||
MI_SET_PFN_DELETED(Pfn1);
|
MI_SET_PFN_DELETED(Pfn1);
|
||||||
MiDecrementShareCount(Pfn1, PageFrameIndex);
|
MiDecrementShareCount(Pfn1, PageFrameIndex);
|
||||||
MiReleasePfnLock(OldIrql);
|
|
||||||
|
|
||||||
/* We should eventually do this */
|
/* We should eventually do this */
|
||||||
//CurrentProcess->NumberOfPrivatePages--;
|
//CurrentProcess->NumberOfPrivatePages--;
|
||||||
|
@ -2348,23 +2339,24 @@ MiProtectVirtualMemory(IN PEPROCESS Process,
|
||||||
if ((NewAccessProtection & PAGE_NOACCESS) ||
|
if ((NewAccessProtection & PAGE_NOACCESS) ||
|
||||||
(NewAccessProtection & PAGE_GUARD))
|
(NewAccessProtection & PAGE_GUARD))
|
||||||
{
|
{
|
||||||
/* Remove this from the working set */
|
KIRQL OldIrql = MiAcquirePfnLock();
|
||||||
MiRemoveFromWorkingSetList(AddressSpace, MiPteToAddress(PointerPte));
|
|
||||||
|
|
||||||
/* Mark the PTE as transition and change its protection */
|
/* Mark the PTE as transition and change its protection */
|
||||||
PteContents.u.Hard.Valid = 0;
|
PteContents.u.Hard.Valid = 0;
|
||||||
PteContents.u.Soft.Transition = 1;
|
PteContents.u.Soft.Transition = 1;
|
||||||
PteContents.u.Trans.Protection = ProtectionMask;
|
PteContents.u.Trans.Protection = ProtectionMask;
|
||||||
/* Decrease PFN share count and write the PTE */
|
/* Decrease PFN share count and write the PTE */
|
||||||
KIRQL OldIrql = MiAcquirePfnLock();
|
|
||||||
MiDecrementShareCount(Pfn1, PFN_FROM_PTE(&PteContents));
|
MiDecrementShareCount(Pfn1, PFN_FROM_PTE(&PteContents));
|
||||||
MiReleasePfnLock(OldIrql);
|
// FIXME: remove the page from the WS
|
||||||
MI_WRITE_INVALID_PTE(PointerPte, PteContents);
|
MI_WRITE_INVALID_PTE(PointerPte, PteContents);
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
// FIXME: Should invalidate entry in every CPU TLB
|
// FIXME: Should invalidate entry in every CPU TLB
|
||||||
ASSERT(FALSE);
|
ASSERT(FALSE);
|
||||||
#endif
|
#endif
|
||||||
KeInvalidateTlbEntry(MiPteToAddress(PointerPte));
|
KeInvalidateTlbEntry(MiPteToAddress(PointerPte));
|
||||||
|
|
||||||
|
/* We are done for this PTE */
|
||||||
|
MiReleasePfnLock(OldIrql);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -2493,44 +2485,41 @@ MiMakePdeExistAndMakeValid(IN PMMPDE PointerPde,
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
MiProcessValidPteList(
|
MiProcessValidPteList(IN PMMPTE *ValidPteList,
|
||||||
_Inout_ PMMSUPPORT Vm,
|
IN ULONG Count)
|
||||||
_Inout_ PMMPTE *ValidPteList,
|
|
||||||
_In_ ULONG Count)
|
|
||||||
{
|
{
|
||||||
|
KIRQL OldIrql;
|
||||||
ULONG i;
|
ULONG i;
|
||||||
|
MMPTE TempPte;
|
||||||
|
PFN_NUMBER PageFrameIndex;
|
||||||
|
PMMPFN Pfn1, Pfn2;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Loop all the PTEs in the list
|
// Acquire the PFN lock and loop all the PTEs in the list
|
||||||
//
|
//
|
||||||
|
OldIrql = MiAcquirePfnLock();
|
||||||
for (i = 0; i != Count; i++)
|
for (i = 0; i != Count; i++)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
// The PTE must currently be valid
|
// The PTE must currently be valid
|
||||||
//
|
//
|
||||||
MMPTE TempPte = *ValidPteList[i];
|
TempPte = *ValidPteList[i];
|
||||||
ASSERT(TempPte.u.Hard.Valid == 1);
|
ASSERT(TempPte.u.Hard.Valid == 1);
|
||||||
|
|
||||||
//
|
|
||||||
// We can now remove this addres from the working set
|
|
||||||
//
|
|
||||||
MiRemoveFromWorkingSetList(Vm, MiPteToAddress(ValidPteList[i]));
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the PFN entry for the page itself, and then for its page table
|
// Get the PFN entry for the page itself, and then for its page table
|
||||||
//
|
//
|
||||||
PFN_NUMBER PageFrameIndex = PFN_FROM_PTE(&TempPte);
|
PageFrameIndex = PFN_FROM_PTE(&TempPte);
|
||||||
PMMPFN Pfn1 = MiGetPfnEntry(PageFrameIndex);
|
Pfn1 = MiGetPfnEntry(PageFrameIndex);
|
||||||
PMMPFN Pfn2 = MiGetPfnEntry(Pfn1->u4.PteFrame);
|
Pfn2 = MiGetPfnEntry(Pfn1->u4.PteFrame);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Decrement the share count on the page table, and then on the page
|
// Decrement the share count on the page table, and then on the page
|
||||||
// itself
|
// itself
|
||||||
//
|
//
|
||||||
KIRQL OldIrql = MiAcquirePfnLock();
|
|
||||||
MiDecrementShareCount(Pfn2, Pfn1->u4.PteFrame);
|
MiDecrementShareCount(Pfn2, Pfn1->u4.PteFrame);
|
||||||
MI_SET_PFN_DELETED(Pfn1);
|
MI_SET_PFN_DELETED(Pfn1);
|
||||||
MiDecrementShareCount(Pfn1, PageFrameIndex);
|
MiDecrementShareCount(Pfn1, PageFrameIndex);
|
||||||
MiReleasePfnLock(OldIrql);
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Make the page decommitted
|
// Make the page decommitted
|
||||||
|
@ -2543,6 +2532,7 @@ MiProcessValidPteList(
|
||||||
// and then release the PFN lock
|
// and then release the PFN lock
|
||||||
//
|
//
|
||||||
KeFlushCurrentTb();
|
KeFlushCurrentTb();
|
||||||
|
MiReleasePfnLock(OldIrql);
|
||||||
}
|
}
|
||||||
|
|
||||||
ULONG
|
ULONG
|
||||||
|
@ -2557,6 +2547,7 @@ MiDecommitPages(IN PVOID StartingAddress,
|
||||||
ULONG CommitReduction = 0;
|
ULONG CommitReduction = 0;
|
||||||
PMMPTE ValidPteList[256];
|
PMMPTE ValidPteList[256];
|
||||||
ULONG PteCount = 0;
|
ULONG PteCount = 0;
|
||||||
|
PMMPFN Pfn1;
|
||||||
MMPTE PteContents;
|
MMPTE PteContents;
|
||||||
PETHREAD CurrentThread = PsGetCurrentThread();
|
PETHREAD CurrentThread = PsGetCurrentThread();
|
||||||
|
|
||||||
|
@ -2588,10 +2579,10 @@ MiDecommitPages(IN PVOID StartingAddress,
|
||||||
// such, and does not flush the entire TLB all the time, but right
|
// such, and does not flush the entire TLB all the time, but right
|
||||||
// now we have bigger problems to worry about than TLB flushing.
|
// now we have bigger problems to worry about than TLB flushing.
|
||||||
//
|
//
|
||||||
PointerPde = MiPteToPde(PointerPte);
|
PointerPde = MiAddressToPde(StartingAddress);
|
||||||
if (PteCount)
|
if (PteCount)
|
||||||
{
|
{
|
||||||
MiProcessValidPteList(&Process->Vm, ValidPteList, PteCount);
|
MiProcessValidPteList(ValidPteList, PteCount);
|
||||||
PteCount = 0;
|
PteCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2626,13 +2617,21 @@ MiDecommitPages(IN PVOID StartingAddress,
|
||||||
//Process->NumberOfPrivatePages--;
|
//Process->NumberOfPrivatePages--;
|
||||||
if (PteContents.u.Hard.Valid)
|
if (PteContents.u.Hard.Valid)
|
||||||
{
|
{
|
||||||
|
//
|
||||||
|
// It's valid. At this point make sure that it is not a ROS
|
||||||
|
// PFN. Also, we don't support ProtoPTEs in this code path.
|
||||||
|
//
|
||||||
|
Pfn1 = MiGetPfnEntry(PteContents.u.Hard.PageFrameNumber);
|
||||||
|
ASSERT(MI_IS_ROS_PFN(Pfn1) == FALSE);
|
||||||
|
ASSERT(Pfn1->u3.e1.PrototypePte == FALSE);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Flush any pending PTEs that we had not yet flushed, if our
|
// Flush any pending PTEs that we had not yet flushed, if our
|
||||||
// list has gotten too big, then add this PTE to the flush list.
|
// list has gotten too big, then add this PTE to the flush list.
|
||||||
//
|
//
|
||||||
if (PteCount == 256)
|
if (PteCount == 256)
|
||||||
{
|
{
|
||||||
MiProcessValidPteList(&Process->Vm, ValidPteList, PteCount);
|
MiProcessValidPteList(ValidPteList, PteCount);
|
||||||
PteCount = 0;
|
PteCount = 0;
|
||||||
}
|
}
|
||||||
ValidPteList[PteCount++] = PointerPte;
|
ValidPteList[PteCount++] = PointerPte;
|
||||||
|
@ -2662,7 +2661,7 @@ MiDecommitPages(IN PVOID StartingAddress,
|
||||||
// This used to be a zero PTE and it no longer is, so we must add a
|
// This used to be a zero PTE and it no longer is, so we must add a
|
||||||
// reference to the pagetable.
|
// reference to the pagetable.
|
||||||
//
|
//
|
||||||
MiIncrementPageTableReferences(MiPteToAddress(PointerPte));
|
MiIncrementPageTableReferences(StartingAddress);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Next, we account for decommitted PTEs and make the PTE as such
|
// Next, we account for decommitted PTEs and make the PTE as such
|
||||||
|
@ -2672,16 +2671,17 @@ MiDecommitPages(IN PVOID StartingAddress,
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Move to the next PTE
|
// Move to the next PTE and the next address
|
||||||
//
|
//
|
||||||
PointerPte++;
|
PointerPte++;
|
||||||
|
StartingAddress = (PVOID)((ULONG_PTR)StartingAddress + PAGE_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Flush any dangling PTEs from the loop in the last page table, and then
|
// Flush any dangling PTEs from the loop in the last page table, and then
|
||||||
// release the working set and return the commit reduction accounting.
|
// release the working set and return the commit reduction accounting.
|
||||||
//
|
//
|
||||||
if (PteCount) MiProcessValidPteList(&Process->Vm, ValidPteList, PteCount);
|
if (PteCount) MiProcessValidPteList(ValidPteList, PteCount);
|
||||||
MiUnlockProcessWorkingSetUnsafe(Process, CurrentThread);
|
MiUnlockProcessWorkingSetUnsafe(Process, CurrentThread);
|
||||||
return CommitReduction;
|
return CommitReduction;
|
||||||
}
|
}
|
||||||
|
|
|
@ -572,14 +572,15 @@ MmDeleteProcessAddressSpace(PEPROCESS Process)
|
||||||
|
|
||||||
#if (_MI_PAGING_LEVELS == 2)
|
#if (_MI_PAGING_LEVELS == 2)
|
||||||
{
|
{
|
||||||
|
KIRQL OldIrql;
|
||||||
PVOID Address;
|
PVOID Address;
|
||||||
PMMPDE pointerPde;
|
PMMPDE pointerPde;
|
||||||
KAPC_STATE ApcState;
|
|
||||||
|
|
||||||
/* Attach to Process */
|
/* Attach to Process */
|
||||||
KeStackAttachProcess(&Process->Pcb, &ApcState);
|
KeAttachProcess(&Process->Pcb);
|
||||||
|
|
||||||
MiLockProcessWorkingSet(Process, PsGetCurrentThread());
|
/* Acquire PFN lock */
|
||||||
|
OldIrql = MiAcquirePfnLock();
|
||||||
|
|
||||||
for (Address = MI_LOWEST_VAD_ADDRESS;
|
for (Address = MI_LOWEST_VAD_ADDRESS;
|
||||||
Address < MM_HIGHEST_VAD_ADDRESS;
|
Address < MM_HIGHEST_VAD_ADDRESS;
|
||||||
|
@ -603,10 +604,11 @@ MmDeleteProcessAddressSpace(PEPROCESS Process)
|
||||||
ASSERT(pointerPde->u.Hard.Valid == 0);
|
ASSERT(pointerPde->u.Hard.Valid == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
MiUnlockProcessWorkingSet(Process, PsGetCurrentThread());
|
/* Release lock */
|
||||||
|
MiReleasePfnLock(OldIrql);
|
||||||
|
|
||||||
/* Detach */
|
/* Detach */
|
||||||
KeUnstackDetachProcess(&ApcState);
|
KeDetachProcess();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue