https://git.reactos.org/?p=reactos.git;a=commitdiff;h=370982aa1d75240282b97…
commit 370982aa1d75240282b9778b4916342b63984cac
Author: Jérôme Gardou <jerome.gardou(a)reactos.org>
AuthorDate: Wed Apr 7 08:49:26 2021 +0200
Commit: Jérôme Gardou <zefklop(a)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 */