https://git.reactos.org/?p=reactos.git;a=commitdiff;h=e67b62251f75083acd4fb9...
commit e67b62251f75083acd4fb9b98bc13f5ba3a30085 Author: Timo Kreuzer timo.kreuzer@reactos.org AuthorDate: Fri Jan 3 10:59:43 2020 +0100 Commit: Timo Kreuzer timo.kreuzer@reactos.org CommitDate: Sat Nov 7 20:16:41 2020 +0100
[NTOS:MM] Handle PXE/PPE gaps in MiDeleteVirtualAddresses --- ntoskrnl/mm/ARM3/virtual.c | 70 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 55 insertions(+), 15 deletions(-)
diff --git a/ntoskrnl/mm/ARM3/virtual.c b/ntoskrnl/mm/ARM3/virtual.c index f0ab5d08f7b..19eb8a69b01 100644 --- a/ntoskrnl/mm/ARM3/virtual.c +++ b/ntoskrnl/mm/ARM3/virtual.c @@ -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) { - /* There are gaps in the address space */ - AddressGap = TRUE; + /* Check for unmapped range and skip it */ + if (!PointerPxe->u.Long) + { + /* There are gaps in the address space */ + AddressGap = TRUE;
- /* Still no valid PDE, try the next 4MB (or whatever) */ - PointerPde++; + /* Update Va and continue looping */ + Va = (ULONG_PTR)MiPxeToAddress(PointerPxe + 1); + continue; + }
- /* Update the PTE on this new boundary */ - PointerPte = MiPteToAddress(PointerPde); + /* 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;
/* 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 */