https://git.reactos.org/?p=reactos.git;a=commitdiff;h=370982aa1d75240282b977...
commit 370982aa1d75240282b9778b4916342b63984cac Author: Jérôme Gardou jerome.gardou@reactos.org AuthorDate: Wed Apr 7 08:49:26 2021 +0200 Commit: Jérôme Gardou zefklop@users.noreply.github.com CommitDate: Thu Apr 8 15:40:37 2021 +0200
[NTOS:MM] Make i386/page.c usable for all x86 variants
This includes PAE & amd64 --- ntoskrnl/mm/i386/page.c | 197 ++++++++++++++++++++++-------------------------- 1 file changed, 92 insertions(+), 105 deletions(-)
diff --git a/ntoskrnl/mm/i386/page.c b/ntoskrnl/mm/i386/page.c index 8b3ed370e94..3e5f5797218 100644 --- a/ntoskrnl/mm/i386/page.c +++ b/ntoskrnl/mm/i386/page.c @@ -15,35 +15,13 @@
#include <mm/ARM3/miarm.h>
-/* GLOBALS *****************************************************************/ - -#define PA_BIT_PRESENT (0) -#define PA_BIT_READWRITE (1) -#define PA_BIT_USER (2) -#define PA_BIT_WT (3) -#define PA_BIT_CD (4) -#define PA_BIT_ACCESSED (5) -#define PA_BIT_DIRTY (6) -#define PA_BIT_GLOBAL (8) - -#define PA_PRESENT (1 << PA_BIT_PRESENT) -#define PA_READWRITE (1 << PA_BIT_READWRITE) -#define PA_USER (1 << PA_BIT_USER) -#define PA_DIRTY (1 << PA_BIT_DIRTY) -#define PA_WT (1 << PA_BIT_WT) -#define PA_CD (1 << PA_BIT_CD) -#define PA_ACCESSED (1 << PA_BIT_ACCESSED) -#define PA_GLOBAL (1 << PA_BIT_GLOBAL) - -#define IS_HYPERSPACE(v) (((ULONG)(v) >= HYPER_SPACE && (ULONG)(v) <= HYPER_SPACE_END)) - -#define PTE_TO_PFN(X) ((X) >> PAGE_SHIFT) -#define PFN_TO_PTE(X) ((X) << PAGE_SHIFT) - -#define PAGE_MASK(x) ((x)&(~0xfff)) +#ifndef _MI_PAGING_LEVELS +#error "Dude, fix your stuff before using this file" +#endif
+/* GLOBALS *****************************************************************/ const -ULONG +ULONG_PTR MmProtectToPteMask[32] = { // @@ -179,7 +157,7 @@ MmDeleteVirtualMapping(PEPROCESS Process, PVOID Address, */ { PMMPTE PointerPte; - ULONG Pte; + MMPTE OldPte;
DPRINT("MmDeleteVirtualMapping(%p, %p, %p, %p)\n", Process, Address, WasDirty, Page);
@@ -196,8 +174,11 @@ MmDeleteVirtualMapping(PEPROCESS Process, PVOID Address, DPRINT1("NULL process given for user-mode mapping at %p\n", Address); KeBugCheck(MEMORY_MANAGEMENT); } - +#if (_MI_PAGING_LEVELS == 2) if (!MiSynchronizeSystemPde(MiAddressToPde(Address))) +#else + if (!MiIsPdeForAddressValid(Address)) +#endif { /* There can't be a page if there is no PDE */ if (WasDirty) @@ -234,9 +215,9 @@ MmDeleteVirtualMapping(PEPROCESS Process, PVOID Address, }
PointerPte = MiAddressToPte(Address); - Pte = InterlockedExchangePte(PointerPte, 0); + OldPte.u.Long = InterlockedExchangePte(PointerPte, 0);
- if (Pte == 0) + if (OldPte.u.Long == 0) { /* There was nothing here */ if (Address < MmSystemRangeStart) @@ -249,9 +230,9 @@ MmDeleteVirtualMapping(PEPROCESS Process, PVOID Address, }
/* It must have been present, or not a swap entry */ - ASSERT(FlagOn(Pte, PA_PRESENT) || !FlagOn(Pte, 0x800)); + ASSERT(OldPte.u.Hard.Valid || !FlagOn(OldPte.u.Long, 0x800));
- if (FlagOn(Pte, PA_PRESENT)) + if (OldPte.u.Hard.Valid) KeInvalidateTlbEntry(Address);
if (Address < MmSystemRangeStart) @@ -269,9 +250,9 @@ MmDeleteVirtualMapping(PEPROCESS Process, PVOID Address, }
if (WasDirty) - *WasDirty = FlagOn(Pte, PA_DIRTY); + *WasDirty = !!OldPte.u.Hard.Dirty; if (Page) - *Page = PTE_TO_PFN(Pte); + *Page = OldPte.u.Hard.PageFrameNumber; }
@@ -283,7 +264,7 @@ MmDeletePageFileMapping( SWAPENTRY* SwapEntry) { PMMPTE PointerPte; - ULONG Pte; + MMPTE OldPte;
/* This should not be called for kernel space anymore */ ASSERT(Process != NULL); @@ -304,10 +285,11 @@ MmDeletePageFileMapping( MiMakePdeExistAndMakeValid(MiAddressToPde(Address), Process, MM_NOIRQL);
PointerPte = MiAddressToPte(Address); - Pte = InterlockedExchangePte(PointerPte, 0); - if (!FlagOn(Pte, 0x800) || FlagOn(Pte, PA_PRESENT)) + OldPte.u.Long = InterlockedExchangePte(PointerPte, 0); + /* This must be a swap entry ! */ + if (!FlagOn(OldPte.u.Long, 0x800) || OldPte.u.Hard.Valid) { - KeBugCheckEx(MEMORY_MANAGEMENT, Pte, (ULONG_PTR)Process, (ULONG_PTR)Address, 0); + KeBugCheckEx(MEMORY_MANAGEMENT, OldPte.u.Long, (ULONG_PTR)Process, (ULONG_PTR)Address, 0); }
/* This used to be a non-zero PTE, now we can let the PDE go. */ @@ -322,22 +304,7 @@ MmDeletePageFileMapping(
MiUnlockProcessWorkingSetUnsafe(Process, PsGetCurrentThread());
- *SwapEntry = Pte >> 1; -} - -BOOLEAN -Mmi386MakeKernelPageTableGlobal(PVOID Address) -{ - PMMPDE PointerPde = MiAddressToPde(Address); - PMMPTE PointerPte = MiAddressToPte(Address); - - if (PointerPde->u.Hard.Valid == 0) - { - if(!MiSynchronizeSystemPde(PointerPde)) - return FALSE; - return PointerPte->u.Hard.Valid != 0; - } - return FALSE; + *SwapEntry = OldPte.u.Long >> 1; }
BOOLEAN @@ -349,7 +316,11 @@ MmIsPagePresent(PEPROCESS Process, PVOID Address) if (Address >= MmSystemRangeStart) { ASSERT(Process == NULL); +#if _MI_PAGING_LEVELS == 2 if (!MiSynchronizeSystemPde(MiAddressToPde(Address))) +#else + if (!MiIsPdeForAddressValid(Address)) +#endif { /* It can't be present if there is no PDE */ return FALSE; @@ -384,18 +355,20 @@ NTAPI MmIsDisabledPage(PEPROCESS Process, PVOID Address) { BOOLEAN Ret; - ULONG Pte; + PMMPTE PointerPte;
if (Address >= MmSystemRangeStart) { ASSERT(Process == NULL); +#if _MI_PAGING_LEVELS == 2 if (!MiSynchronizeSystemPde(MiAddressToPde(Address))) +#else + if (!MiIsPdeForAddressValid(Address)) +#endif { /* It's not disabled if it's not present */ return FALSE; } - - Pte = MiAddressToPte(Address)->u.Long; } else { @@ -412,11 +385,12 @@ MmIsDisabledPage(PEPROCESS Process, PVOID Address) }
MiMakePdeExistAndMakeValid(MiAddressToPde(Address), Process, MM_NOIRQL); - - Pte = MiAddressToPte(Address)->u.Long; }
- Ret = !FlagOn(Pte, PA_PRESENT) && !FlagOn(Pte, 0x800) && (PAGE_MASK(Pte) != 0); + PointerPte = MiAddressToPte(Address); + Ret = !PointerPte->u.Hard.Valid + && !FlagOn(PointerPte->u.Long, 0x800) + && (PointerPte->u.Hard.PageFrameNumber != 0);
if (Address < MmSystemRangeStart) MiUnlockProcessWorkingSetShared(Process, PsGetCurrentThread()); @@ -429,7 +403,7 @@ NTAPI MmIsPageSwapEntry(PEPROCESS Process, PVOID Address) { BOOLEAN Ret; - ULONG Pte; + PMMPTE PointerPte;
/* We never set swap entries for kernel addresses */ if (Address >= MmSystemRangeStart) @@ -452,8 +426,8 @@ MmIsPageSwapEntry(PEPROCESS Process, PVOID Address)
MiMakePdeExistAndMakeValid(MiAddressToPde(Address), Process, MM_NOIRQL);
- Pte = MiAddressToPte(Address)->u.Long; - Ret = !FlagOn(Pte, PA_PRESENT) && FlagOn(Pte, 0x800); + PointerPte = MiAddressToPte(Address); + Ret = !PointerPte->u.Hard.Valid && FlagOn(PointerPte->u.Long, 0x800);
MiUnlockProcessWorkingSetShared(Process, PsGetCurrentThread());
@@ -464,7 +438,7 @@ VOID NTAPI MmGetPageFileMapping(PEPROCESS Process, PVOID Address, SWAPENTRY* SwapEntry) { - ULONG Pte; + PMMPTE PointerPte;
/* We never set swap entries for kernel addresses */ if (Address >= MmSystemRangeStart) @@ -489,9 +463,9 @@ MmGetPageFileMapping(PEPROCESS Process, PVOID Address, SWAPENTRY* SwapEntry)
MiMakePdeExistAndMakeValid(MiAddressToPde(Address), Process, MM_NOIRQL);
- Pte = MiAddressToPte(Address)->u.Long; - if (!FlagOn(Pte, PA_PRESENT) && FlagOn(Pte, 0x800)) - *SwapEntry = Pte >> 1; + PointerPte = MiAddressToPte(Address); + if (!PointerPte->u.Hard.Valid && FlagOn(PointerPte->u.Long, 0x800)) + *SwapEntry = PointerPte->u.Long >> 1; else *SwapEntry = 0;
@@ -505,7 +479,7 @@ MmCreatePageFileMapping(PEPROCESS Process, SWAPENTRY SwapEntry) { PMMPTE PointerPte; - ULONG Pte; + ULONG_PTR Pte;
/* This should not be called for kernel space anymore */ ASSERT(Process != NULL); @@ -571,8 +545,10 @@ MmCreateVirtualMappingUnsafe(PEPROCESS Process, DPRINT1("NULL process given for user-mode mapping at %p\n", Address); KeBugCheck(MEMORY_MANAGEMENT); } +#if _MI_PAGING_LEVELS == 2 if (!MiSynchronizeSystemPde(MiAddressToPde(Address))) MiFillSystemPageDirectory(Address, PAGE_SIZE); +#endif } else { @@ -631,7 +607,7 @@ MmCreateVirtualMapping(PEPROCESS Process, ASSERT((ULONG_PTR)Address % PAGE_SIZE == 0); if (!MmIsPageInUse(Page)) { - DPRINT1("Page at address %x not in use\n", PFN_TO_PTE(Page)); + DPRINT1("Page %lx is not in use\n", Page); KeBugCheck(MEMORY_MANAGEMENT); }
@@ -642,15 +618,21 @@ ULONG NTAPI MmGetPageProtect(PEPROCESS Process, PVOID Address) { - ULONG_PTR Pte; + PMMPTE PointerPte; ULONG Protect;
if (Address >= MmSystemRangeStart) { ASSERT(Process == NULL);
+#if _MI_PAGING_LEVELS == 2 if (!MiSynchronizeSystemPde(MiAddressToPde(Address))) +#else + if (!MiIsPdeForAddressValid(Address)) +#endif + { return PAGE_NOACCESS; + } } else { @@ -671,34 +653,29 @@ MmGetPageProtect(PEPROCESS Process, PVOID Address) MiMakePdeExistAndMakeValid(MiAddressToPde(Address), Process, MM_NOIRQL); }
- Pte = MiAddressToPte(Address)->u.Long; + PointerPte = MiAddressToPte(Address);
- if (!(Pte & PA_PRESENT)) + if (!PointerPte->u.Flush.Valid) { Protect = PAGE_NOACCESS; } else { - if (Pte & PA_READWRITE) - { + if (PointerPte->u.Flush.CopyOnWrite) + Protect = PAGE_WRITECOPY; + else if (PointerPte->u.Flush.Write) Protect = PAGE_READWRITE; - } else - { - Protect = PAGE_EXECUTE_READ; - } - if (Pte & PA_CD) - { + Protect = PAGE_READONLY; +#if _MI_PAGING_LEVELS >= 3 + /* PAE & AMD64 long mode support NoExecute bit */ + if (!PointerPte->u.Flush.NoExecute) + Protect <<= 4; +#endif + if (PointerPte->u.Flush.CacheDisable) Protect |= PAGE_NOCACHE; - } - if (Pte & PA_WT) - { + if (PointerPte->u.Flush.WriteThrough) Protect |= PAGE_WRITETHROUGH; - } - if (!(Pte & PA_USER)) - { - Protect |= PAGE_SYSTEM; - } }
if (Address < MmSystemRangeStart) @@ -713,8 +690,7 @@ MmSetPageProtect(PEPROCESS Process, PVOID Address, ULONG flProtect) { ULONG ProtectionMask; PMMPTE PointerPte; - MMPTE TempPte; - ULONG_PTR Pte; + MMPTE TempPte, OldPte;
DPRINT("MmSetPageProtect(Process %p Address %p flProtect %x)\n", Process, Address, flProtect); @@ -739,16 +715,16 @@ MmSetPageProtect(PEPROCESS Process, PVOID Address, ULONG flProtect) TempPte.u.Hard.Accessed = PointerPte->u.Hard.Accessed; TempPte.u.Hard.Dirty = PointerPte->u.Hard.Dirty;
- Pte = InterlockedExchangePte(PointerPte, TempPte.u.Long); + OldPte.u.Long = InterlockedExchangePte(PointerPte, TempPte.u.Long);
// We should be able to bring a page back from PAGE_NOACCESS - if ((Pte & 0x800) || !(Pte >> PAGE_SHIFT)) + if (!OldPte.u.Hard.Valid && (FlagOn(OldPte.u.Long, 0x800) || (OldPte.u.Hard.PageFrameNumber == 0))) { - DPRINT1("Invalid Pte %lx\n", Pte); + DPRINT1("Invalid Pte %lx\n", OldPte.u.Long); KeBugCheck(MEMORY_MANAGEMENT); }
- if (Pte != TempPte.u.Long) + if (OldPte.u.Long != TempPte.u.Long) KeInvalidateTlbEntry(Address);
MiUnlockProcessWorkingSetUnsafe(Process, PsGetCurrentThread()); @@ -759,7 +735,6 @@ NTAPI MmSetDirtyBit(PEPROCESS Process, PVOID Address, BOOLEAN Bit) { PMMPTE PointerPte; - ULONG Pte;
DPRINT("MmSetDirtyBit(Process %p Address %p Bit %x)\n", Process, Address, Bit); @@ -774,20 +749,15 @@ MmSetDirtyBit(PEPROCESS Process, PVOID Address, BOOLEAN Bit) MiMakePdeExistAndMakeValid(MiAddressToPde(Address), Process, MM_NOIRQL);
PointerPte = MiAddressToPte(Address); - Pte = PointerPte->u.Long; - if (Bit) - Pte |= PA_DIRTY; - else - Pte &= ~PA_DIRTY; - Pte = InterlockedExchangePte(PointerPte, Pte); - // We shouldnl't set dirty bit on non-mapped adresses - if ((Pte & 0x800) || !(Pte >> PAGE_SHIFT)) + if (!PointerPte->u.Hard.Valid && (FlagOn(PointerPte->u.Long, 0x800) || (PointerPte->u.Hard.PageFrameNumber == 0))) { - DPRINT1("Invalid Pte %lx\n", Pte); + DPRINT1("Invalid Pte %lx\n", PointerPte->u.Long); KeBugCheck(MEMORY_MANAGEMENT); }
+ PointerPte->u.Hard.Dirty = !!Bit; + if (!Bit) KeInvalidateTlbEntry(Address);
@@ -802,4 +772,21 @@ MmInitGlobalKernelPageDirectory(VOID) /* Nothing to do here */ }
+#ifdef _M_IX86 +BOOLEAN +Mmi386MakeKernelPageTableGlobal(PVOID Address) +{ + PMMPDE PointerPde = MiAddressToPde(Address); + PMMPTE PointerPte = MiAddressToPte(Address); + + if (PointerPde->u.Hard.Valid == 0) + { + if (!MiSynchronizeSystemPde(PointerPde)) + return FALSE; + return PointerPte->u.Hard.Valid != 0; + } + return FALSE; +} +#endif + /* EOF */