mirror of
https://github.com/reactos/reactos.git
synced 2025-05-03 12:50:05 +00:00
[NTOS:MM] Handle PXE/PPE gaps in MiDeleteVirtualAddresses
This commit is contained in:
parent
c5a700fd06
commit
e67b62251f
1 changed files with 55 additions and 15 deletions
|
@ -543,6 +543,12 @@ MiDeleteVirtualAddresses(IN ULONG_PTR Va,
|
|||
{
|
||||
PMMPTE PointerPte, PrototypePte, LastPrototypePte;
|
||||
PMMPDE PointerPde;
|
||||
#if (_MI_PAGING_LEVELS >= 3)
|
||||
PMMPPE PointerPpe;
|
||||
#endif
|
||||
#if (_MI_PAGING_LEVELS >= 4)
|
||||
PMMPPE PointerPxe;
|
||||
#endif
|
||||
MMPTE TempPte;
|
||||
PEPROCESS CurrentProcess;
|
||||
KIRQL OldIrql;
|
||||
|
@ -552,10 +558,8 @@ MiDeleteVirtualAddresses(IN ULONG_PTR Va,
|
|||
/* Get out if this is a fake VAD, RosMm will free the marea pages */
|
||||
if ((Vad) && (Vad->u.VadFlags.Spare == 1)) return;
|
||||
|
||||
/* Grab the process and PTE/PDE for the address being deleted */
|
||||
/* Get the current process */
|
||||
CurrentProcess = PsGetCurrentProcess();
|
||||
PointerPde = MiAddressToPde(Va);
|
||||
PointerPte = MiAddressToPte(Va);
|
||||
|
||||
/* Check if this is a section VAD or a VM VAD */
|
||||
if (!(Vad) || (Vad->u.VadFlags.PrivateMemory) || !(Vad->FirstPrototypePte))
|
||||
|
@ -573,24 +577,59 @@ MiDeleteVirtualAddresses(IN ULONG_PTR Va,
|
|||
/* In all cases, we don't support fork() yet */
|
||||
ASSERT(CurrentProcess->CloneRoot == NULL);
|
||||
|
||||
/* Loop the PTE for each VA */
|
||||
while (TRUE)
|
||||
/* Loop the PTE for each VA (EndingAddress is inclusive!) */
|
||||
while (Va <= EndingAddress)
|
||||
{
|
||||
/* First keep going until we find a valid PDE */
|
||||
while (!PointerPde->u.Long)
|
||||
#if (_MI_PAGING_LEVELS >= 4)
|
||||
/* Get the PXE and check if it's valid */
|
||||
PointerPxe = MiAddressToPxe((PVOID)Va);
|
||||
if (!PointerPxe->u.Hard.Valid)
|
||||
{
|
||||
/* Check for unmapped range and skip it */
|
||||
if (!PointerPxe->u.Long)
|
||||
{
|
||||
/* There are gaps in the address space */
|
||||
AddressGap = TRUE;
|
||||
|
||||
/* Update Va and continue looping */
|
||||
Va = (ULONG_PTR)MiPxeToAddress(PointerPxe + 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Make the PXE valid */
|
||||
MiMakeSystemAddressValid(MiPteToAddress(PointerPxe), CurrentProcess);
|
||||
}
|
||||
#endif
|
||||
#if (_MI_PAGING_LEVELS >= 3)
|
||||
/* Get the PPE and check if it's valid */
|
||||
PointerPpe = MiAddressToPpe((PVOID)Va);
|
||||
if (!PointerPpe->u.Hard.Valid)
|
||||
{
|
||||
/* Check for unmapped range and skip it */
|
||||
if (!PointerPpe->u.Long)
|
||||
{
|
||||
/* There are gaps in the address space */
|
||||
AddressGap = TRUE;
|
||||
|
||||
/* Update Va and continue looping */
|
||||
Va = (ULONG_PTR)MiPpeToAddress(PointerPpe + 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Make the PPE valid */
|
||||
MiMakeSystemAddressValid(MiPteToAddress(PointerPpe), CurrentProcess);
|
||||
}
|
||||
#endif
|
||||
/* Skip invalid PDEs */
|
||||
PointerPde = MiAddressToPde((PVOID)Va);
|
||||
if (!PointerPde->u.Long)
|
||||
{
|
||||
/* There are gaps in the address space */
|
||||
AddressGap = TRUE;
|
||||
|
||||
/* Still no valid PDE, try the next 4MB (or whatever) */
|
||||
PointerPde++;
|
||||
|
||||
/* Update the PTE on this new boundary */
|
||||
PointerPte = MiPteToAddress(PointerPde);
|
||||
|
||||
/* Check if all the PDEs are invalid, so there's nothing to free */
|
||||
Va = (ULONG_PTR)MiPteToAddress(PointerPte);
|
||||
if (Va > EndingAddress) return;
|
||||
Va = (ULONG_PTR)MiPdeToAddress(PointerPde + 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Now check if the PDE is mapped in */
|
||||
|
@ -627,6 +666,7 @@ MiDeleteVirtualAddresses(IN ULONG_PTR Va,
|
|||
|
||||
/* Lock the PFN Database while we delete the PTEs */
|
||||
OldIrql = MiAcquirePfnLock();
|
||||
PointerPte = MiAddressToPte(Va);
|
||||
do
|
||||
{
|
||||
/* Capture the PDE and make sure it exists */
|
||||
|
|
Loading…
Reference in a new issue