mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 01:55:19 +00:00
[NTOS:MM] Make i386/page.c usable for all x86 variants
This includes PAE & amd64
This commit is contained in:
parent
6d957d6958
commit
370982aa1d
1 changed files with 92 additions and 105 deletions
|
@ -15,35 +15,13 @@
|
|||
|
||||
#include <mm/ARM3/miarm.h>
|
||||
|
||||
#ifndef _MI_PAGING_LEVELS
|
||||
#error "Dude, fix your stuff before using this file"
|
||||
#endif
|
||||
|
||||
/* 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))
|
||||
|
||||
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 */
|
||||
|
|
Loading…
Reference in a new issue