mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 18:15:11 +00:00
[NTOS:MM] Share "page.c" between i386 & amd64 builds
This commit is contained in:
parent
7ea8312617
commit
a34d9bcfb6
3 changed files with 1 additions and 629 deletions
|
@ -295,13 +295,6 @@ MI_IS_MAPPED_PTE(PMMPTE PointerPte)
|
||||||
(PointerPte->u.Hard.PageFrameNumber != 0));
|
(PointerPte->u.Hard.PageFrameNumber != 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCEINLINE
|
|
||||||
VOID
|
|
||||||
MmInitGlobalKernelPageDirectory(VOID)
|
|
||||||
{
|
|
||||||
/* Nothing to do */
|
|
||||||
}
|
|
||||||
|
|
||||||
FORCEINLINE
|
FORCEINLINE
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
MiIsPdeForAddressValid(PVOID Address)
|
MiIsPdeForAddressValid(PVOID Address)
|
||||||
|
|
|
@ -1,621 +0,0 @@
|
||||||
/*
|
|
||||||
* COPYRIGHT: GPL, See COPYING in the top level directory
|
|
||||||
* PROJECT: ReactOS kernel
|
|
||||||
* FILE: ntoskrnl/mm/amd64/page.c
|
|
||||||
* PURPOSE: Low level memory managment manipulation
|
|
||||||
*
|
|
||||||
* PROGRAMMER: Timo Kreuzer (timo.kreuzer@reactos.org)
|
|
||||||
* ReactOS Portable Systems Group
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* INCLUDES ***************************************************************/
|
|
||||||
|
|
||||||
#include <ntoskrnl.h>
|
|
||||||
#define NDEBUG
|
|
||||||
#include <debug.h>
|
|
||||||
#include <mm/ARM3/miarm.h>
|
|
||||||
|
|
||||||
#undef InterlockedExchangePte
|
|
||||||
#define InterlockedExchangePte(pte1, pte2) \
|
|
||||||
InterlockedExchange64((LONG64*)&pte1->u.Long, pte2.u.Long)
|
|
||||||
|
|
||||||
#define PAGE_EXECUTE_ANY (PAGE_EXECUTE|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE|PAGE_EXECUTE_WRITECOPY)
|
|
||||||
#define PAGE_WRITE_ANY (PAGE_EXECUTE_READWRITE|PAGE_READWRITE|PAGE_EXECUTE_WRITECOPY|PAGE_WRITECOPY)
|
|
||||||
#define PAGE_WRITECOPY_ANY (PAGE_EXECUTE_WRITECOPY|PAGE_WRITECOPY)
|
|
||||||
|
|
||||||
extern MMPTE HyperTemplatePte;
|
|
||||||
|
|
||||||
/* GLOBALS *****************************************************************/
|
|
||||||
|
|
||||||
const
|
|
||||||
ULONG64
|
|
||||||
MmProtectToPteMask[32] =
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// These are the base MM_ protection flags
|
|
||||||
//
|
|
||||||
0,
|
|
||||||
PTE_READONLY | PTE_ENABLE_CACHE,
|
|
||||||
PTE_EXECUTE | PTE_ENABLE_CACHE,
|
|
||||||
PTE_EXECUTE_READ | PTE_ENABLE_CACHE,
|
|
||||||
PTE_READWRITE | PTE_ENABLE_CACHE,
|
|
||||||
PTE_WRITECOPY | PTE_ENABLE_CACHE,
|
|
||||||
PTE_EXECUTE_READWRITE | PTE_ENABLE_CACHE,
|
|
||||||
PTE_EXECUTE_WRITECOPY | PTE_ENABLE_CACHE,
|
|
||||||
//
|
|
||||||
// These OR in the MM_NOCACHE flag
|
|
||||||
//
|
|
||||||
0,
|
|
||||||
PTE_READONLY | PTE_DISABLE_CACHE,
|
|
||||||
PTE_EXECUTE | PTE_DISABLE_CACHE,
|
|
||||||
PTE_EXECUTE_READ | PTE_DISABLE_CACHE,
|
|
||||||
PTE_READWRITE | PTE_DISABLE_CACHE,
|
|
||||||
PTE_WRITECOPY | PTE_DISABLE_CACHE,
|
|
||||||
PTE_EXECUTE_READWRITE | PTE_DISABLE_CACHE,
|
|
||||||
PTE_EXECUTE_WRITECOPY | PTE_DISABLE_CACHE,
|
|
||||||
//
|
|
||||||
// These OR in the MM_DECOMMIT flag, which doesn't seem supported on x86/64/ARM
|
|
||||||
//
|
|
||||||
0,
|
|
||||||
PTE_READONLY | PTE_ENABLE_CACHE,
|
|
||||||
PTE_EXECUTE | PTE_ENABLE_CACHE,
|
|
||||||
PTE_EXECUTE_READ | PTE_ENABLE_CACHE,
|
|
||||||
PTE_READWRITE | PTE_ENABLE_CACHE,
|
|
||||||
PTE_WRITECOPY | PTE_ENABLE_CACHE,
|
|
||||||
PTE_EXECUTE_READWRITE | PTE_ENABLE_CACHE,
|
|
||||||
PTE_EXECUTE_WRITECOPY | PTE_ENABLE_CACHE,
|
|
||||||
//
|
|
||||||
// These OR in the MM_NOACCESS flag, which seems to enable WriteCombining?
|
|
||||||
//
|
|
||||||
0,
|
|
||||||
PTE_READONLY | PTE_WRITECOMBINED_CACHE,
|
|
||||||
PTE_EXECUTE | PTE_WRITECOMBINED_CACHE,
|
|
||||||
PTE_EXECUTE_READ | PTE_WRITECOMBINED_CACHE,
|
|
||||||
PTE_READWRITE | PTE_WRITECOMBINED_CACHE,
|
|
||||||
PTE_WRITECOPY | PTE_WRITECOMBINED_CACHE,
|
|
||||||
PTE_EXECUTE_READWRITE | PTE_WRITECOMBINED_CACHE,
|
|
||||||
PTE_EXECUTE_WRITECOPY | PTE_WRITECOMBINED_CACHE,
|
|
||||||
};
|
|
||||||
|
|
||||||
const
|
|
||||||
ULONG MmProtectToValue[32] =
|
|
||||||
{
|
|
||||||
PAGE_NOACCESS,
|
|
||||||
PAGE_READONLY,
|
|
||||||
PAGE_EXECUTE,
|
|
||||||
PAGE_EXECUTE_READ,
|
|
||||||
PAGE_READWRITE,
|
|
||||||
PAGE_WRITECOPY,
|
|
||||||
PAGE_EXECUTE_READWRITE,
|
|
||||||
PAGE_EXECUTE_WRITECOPY,
|
|
||||||
PAGE_NOACCESS,
|
|
||||||
PAGE_NOCACHE | PAGE_READONLY,
|
|
||||||
PAGE_NOCACHE | PAGE_EXECUTE,
|
|
||||||
PAGE_NOCACHE | PAGE_EXECUTE_READ,
|
|
||||||
PAGE_NOCACHE | PAGE_READWRITE,
|
|
||||||
PAGE_NOCACHE | PAGE_WRITECOPY,
|
|
||||||
PAGE_NOCACHE | PAGE_EXECUTE_READWRITE,
|
|
||||||
PAGE_NOCACHE | PAGE_EXECUTE_WRITECOPY,
|
|
||||||
PAGE_NOACCESS,
|
|
||||||
PAGE_GUARD | PAGE_READONLY,
|
|
||||||
PAGE_GUARD | PAGE_EXECUTE,
|
|
||||||
PAGE_GUARD | PAGE_EXECUTE_READ,
|
|
||||||
PAGE_GUARD | PAGE_READWRITE,
|
|
||||||
PAGE_GUARD | PAGE_WRITECOPY,
|
|
||||||
PAGE_GUARD | PAGE_EXECUTE_READWRITE,
|
|
||||||
PAGE_GUARD | PAGE_EXECUTE_WRITECOPY,
|
|
||||||
PAGE_NOACCESS,
|
|
||||||
PAGE_WRITECOMBINE | PAGE_READONLY,
|
|
||||||
PAGE_WRITECOMBINE | PAGE_EXECUTE,
|
|
||||||
PAGE_WRITECOMBINE | PAGE_EXECUTE_READ,
|
|
||||||
PAGE_WRITECOMBINE | PAGE_READWRITE,
|
|
||||||
PAGE_WRITECOMBINE | PAGE_WRITECOPY,
|
|
||||||
PAGE_WRITECOMBINE | PAGE_EXECUTE_READWRITE,
|
|
||||||
PAGE_WRITECOMBINE | PAGE_EXECUTE_WRITECOPY
|
|
||||||
};
|
|
||||||
|
|
||||||
/* PRIVATE FUNCTIONS *******************************************************/
|
|
||||||
|
|
||||||
BOOLEAN
|
|
||||||
FORCEINLINE
|
|
||||||
MiIsHyperspaceAddress(PVOID Address)
|
|
||||||
{
|
|
||||||
return ((ULONG64)Address >= HYPER_SPACE &&
|
|
||||||
(ULONG64)Address <= HYPER_SPACE_END);
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
MiFlushTlb(PMMPTE Pte, PVOID Address, KIRQL OldIrql)
|
|
||||||
{
|
|
||||||
if (MiIsHyperspaceAddress(Pte))
|
|
||||||
{
|
|
||||||
MiUnmapPageInHyperSpace(PsGetCurrentProcess(), (PVOID)PAGE_ROUND_DOWN(Pte), OldIrql);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
__invlpg(Address);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
PMMPTE
|
|
||||||
MiGetPteForProcess(
|
|
||||||
PEPROCESS Process,
|
|
||||||
PVOID Address,
|
|
||||||
BOOLEAN Create,
|
|
||||||
PKIRQL OldIrql
|
|
||||||
)
|
|
||||||
{
|
|
||||||
PMMPTE Pte;
|
|
||||||
PMMPDE Pde;
|
|
||||||
PMMPPE Ppe;
|
|
||||||
PMMPXE Pxe;
|
|
||||||
|
|
||||||
*OldIrql = 0;
|
|
||||||
/* Make sure the process is correct */
|
|
||||||
if (Address < MmSystemRangeStart)
|
|
||||||
{
|
|
||||||
/* FIXME: Implement this case */
|
|
||||||
ASSERT(Process == PsGetCurrentProcess());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ASSERT((Process == NULL) || (Process == PsGetCurrentProcess()));
|
|
||||||
}
|
|
||||||
|
|
||||||
Pxe = MiAddressToPxe(Address);
|
|
||||||
Ppe = MiAddressToPpe(Address);
|
|
||||||
Pde = MiAddressToPde(Address);
|
|
||||||
Pte = MiAddressToPte(Address);
|
|
||||||
|
|
||||||
if (Create)
|
|
||||||
{
|
|
||||||
/* Check the PXE */
|
|
||||||
if (Pxe->u.Long == 0)
|
|
||||||
{
|
|
||||||
/* Make it demand zero */
|
|
||||||
MI_WRITE_INVALID_PDE(Pxe, DemandZeroPde);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check the PPE */
|
|
||||||
if (Ppe->u.Long == 0)
|
|
||||||
{
|
|
||||||
/* Make it demand zero */
|
|
||||||
MI_WRITE_INVALID_PDE(Ppe, DemandZeroPde);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check the PDE */
|
|
||||||
if (Pde->u.Long == 0)
|
|
||||||
{
|
|
||||||
/* Make it demand zero */
|
|
||||||
MI_WRITE_INVALID_PDE(Pde, DemandZeroPde);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Check the PXE */
|
|
||||||
if (!Pxe->u.Hard.Valid)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
/* Check the PPE */
|
|
||||||
if (!Ppe->u.Hard.Valid)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
/* Check the PDE */
|
|
||||||
if (!Pde->u.Hard.Valid)
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Pte;
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
ULONG64
|
|
||||||
MiGetPteValueForProcess(
|
|
||||||
PEPROCESS Process,
|
|
||||||
PVOID Address)
|
|
||||||
{
|
|
||||||
PMMPTE Pte;
|
|
||||||
ULONG64 PteValue;
|
|
||||||
KIRQL OldIrql;
|
|
||||||
|
|
||||||
Pte = MiGetPteForProcess(Process, Address, FALSE, &OldIrql);
|
|
||||||
PteValue = Pte ? Pte->u.Long : 0;
|
|
||||||
|
|
||||||
if (MiIsHyperspaceAddress(Pte))
|
|
||||||
MiUnmapPageInHyperSpace(PsGetCurrentProcess(), (PVOID)PAGE_ROUND_DOWN(Pte), OldIrql);
|
|
||||||
|
|
||||||
return PteValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
ULONG
|
|
||||||
NTAPI
|
|
||||||
MiGetPteProtection(MMPTE Pte)
|
|
||||||
{
|
|
||||||
ULONG Protect;
|
|
||||||
|
|
||||||
if (!Pte.u.Flush.Valid)
|
|
||||||
{
|
|
||||||
Protect = PAGE_NOACCESS;
|
|
||||||
}
|
|
||||||
else if (Pte.u.Flush.NoExecute)
|
|
||||||
{
|
|
||||||
if (Pte.u.Flush.CopyOnWrite)
|
|
||||||
Protect = PAGE_WRITECOPY;
|
|
||||||
else if (Pte.u.Flush.Write)
|
|
||||||
Protect = PAGE_READWRITE;
|
|
||||||
else
|
|
||||||
Protect = PAGE_READONLY;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (Pte.u.Flush.CopyOnWrite)
|
|
||||||
Protect = PAGE_EXECUTE_WRITECOPY;
|
|
||||||
else if (Pte.u.Flush.Write)
|
|
||||||
Protect = PAGE_EXECUTE_READWRITE;
|
|
||||||
else
|
|
||||||
Protect = PAGE_EXECUTE_READ;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Pte.u.Flush.CacheDisable)
|
|
||||||
Protect |= PAGE_NOCACHE;
|
|
||||||
|
|
||||||
if (Pte.u.Flush.WriteThrough)
|
|
||||||
Protect |= PAGE_WRITETHROUGH;
|
|
||||||
|
|
||||||
// PAGE_GUARD ?
|
|
||||||
return Protect;
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
VOID
|
|
||||||
MiSetPteProtection(PMMPTE Pte, ULONG Protection)
|
|
||||||
{
|
|
||||||
Pte->u.Flush.CopyOnWrite = (Protection & PAGE_WRITECOPY_ANY) ? 1 : 0;
|
|
||||||
Pte->u.Flush.Write = (Protection & PAGE_WRITE_ANY) ? 1 : 0;
|
|
||||||
Pte->u.Flush.CacheDisable = (Protection & PAGE_NOCACHE) ? 1 : 0;
|
|
||||||
Pte->u.Flush.WriteThrough = (Protection & PAGE_WRITETHROUGH) ? 1 : 0;
|
|
||||||
|
|
||||||
// FIXME: This doesn't work. Why?
|
|
||||||
Pte->u.Flush.NoExecute = (Protection & PAGE_EXECUTE_ANY) ? 0 : 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* FUNCTIONS ***************************************************************/
|
|
||||||
|
|
||||||
PFN_NUMBER
|
|
||||||
NTAPI
|
|
||||||
MmGetPfnForProcess(PEPROCESS Process,
|
|
||||||
PVOID Address)
|
|
||||||
{
|
|
||||||
MMPTE Pte;
|
|
||||||
Pte.u.Long = MiGetPteValueForProcess(Process, Address);
|
|
||||||
return Pte.u.Hard.Valid ? Pte.u.Hard.PageFrameNumber : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOLEAN
|
|
||||||
NTAPI
|
|
||||||
MmIsPagePresent(PEPROCESS Process, PVOID Address)
|
|
||||||
{
|
|
||||||
MMPTE Pte;
|
|
||||||
Pte.u.Long = MiGetPteValueForProcess(Process, Address);
|
|
||||||
return (BOOLEAN)Pte.u.Hard.Valid;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOLEAN
|
|
||||||
NTAPI
|
|
||||||
MmIsDisabledPage(PEPROCESS Process, PVOID Address)
|
|
||||||
{
|
|
||||||
MMPTE Pte;
|
|
||||||
Pte.u.Long = MiGetPteValueForProcess(Process, Address);
|
|
||||||
|
|
||||||
return (Pte.u.Hard.Valid == 0) &&
|
|
||||||
(Pte.u.Trans.Transition == 0) &&
|
|
||||||
(Pte.u.Hard.PageFrameNumber != 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOLEAN
|
|
||||||
NTAPI
|
|
||||||
MmIsPageSwapEntry(PEPROCESS Process, PVOID Address)
|
|
||||||
{
|
|
||||||
MMPTE Pte;
|
|
||||||
Pte.u.Long = MiGetPteValueForProcess(Process, Address);
|
|
||||||
return !Pte.u.Hard.Valid && Pte.u.Soft.Transition;
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
NTAPI
|
|
||||||
MmGetPageFileMapping(
|
|
||||||
PEPROCESS Process,
|
|
||||||
PVOID Address,
|
|
||||||
SWAPENTRY* SwapEntry)
|
|
||||||
{
|
|
||||||
PMMPTE PointerPte;
|
|
||||||
|
|
||||||
ASSERT(Process == PsGetCurrentProcess());
|
|
||||||
|
|
||||||
PointerPte = MiAddressToPte(Address);
|
|
||||||
*SwapEntry = PointerPte->u.Long >> 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOLEAN
|
|
||||||
NTAPI
|
|
||||||
MmIsDirtyPage(PEPROCESS Process, PVOID Address)
|
|
||||||
{
|
|
||||||
MMPTE Pte;
|
|
||||||
Pte.u.Long = MiGetPteValueForProcess(Process, Address);
|
|
||||||
return Pte.u.Hard.Valid && Pte.u.Hard.Dirty;
|
|
||||||
}
|
|
||||||
|
|
||||||
ULONG
|
|
||||||
NTAPI
|
|
||||||
MmGetPageProtect(PEPROCESS Process, PVOID Address)
|
|
||||||
{
|
|
||||||
MMPTE Pte;
|
|
||||||
|
|
||||||
Pte.u.Long = MiGetPteValueForProcess(Process, Address);
|
|
||||||
|
|
||||||
return MiGetPteProtection(Pte);
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
NTAPI
|
|
||||||
MmSetPageProtect(PEPROCESS Process, PVOID Address, ULONG flProtect)
|
|
||||||
{
|
|
||||||
PMMPTE Pte;
|
|
||||||
MMPTE NewPte;
|
|
||||||
KIRQL OldIrql;
|
|
||||||
|
|
||||||
Pte = MiGetPteForProcess(Process, Address, FALSE, &OldIrql);
|
|
||||||
ASSERT(Pte != NULL);
|
|
||||||
|
|
||||||
NewPte = *Pte;
|
|
||||||
|
|
||||||
MiSetPteProtection(&NewPte, flProtect);
|
|
||||||
|
|
||||||
InterlockedExchangePte(Pte, NewPte);
|
|
||||||
|
|
||||||
MiFlushTlb(Pte, Address, OldIrql);
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
NTAPI
|
|
||||||
MmSetCleanPage(PEPROCESS Process, PVOID Address)
|
|
||||||
{
|
|
||||||
PMMPTE Pte;
|
|
||||||
KIRQL OldIrql;
|
|
||||||
|
|
||||||
Pte = MiGetPteForProcess(Process, Address, FALSE, &OldIrql);
|
|
||||||
if (!Pte)
|
|
||||||
{
|
|
||||||
KeBugCheckEx(MEMORY_MANAGEMENT, 0x1234, (ULONG64)Address, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Ckear the dirty bit */
|
|
||||||
if (InterlockedBitTestAndReset64((PVOID)Pte, 6))
|
|
||||||
{
|
|
||||||
if (!MiIsHyperspaceAddress(Pte))
|
|
||||||
__invlpg(Address);
|
|
||||||
}
|
|
||||||
|
|
||||||
MiFlushTlb(Pte, Address, OldIrql);
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
NTAPI
|
|
||||||
MmSetDirtyPage(PEPROCESS Process, PVOID Address)
|
|
||||||
{
|
|
||||||
PMMPTE Pte;
|
|
||||||
KIRQL OldIrql;
|
|
||||||
|
|
||||||
Pte = MiGetPteForProcess(Process, Address, FALSE, &OldIrql);
|
|
||||||
if (!Pte)
|
|
||||||
{
|
|
||||||
KeBugCheckEx(MEMORY_MANAGEMENT, 0x1234, (ULONG64)Address, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Ckear the dirty bit */
|
|
||||||
if (InterlockedBitTestAndSet64((PVOID)Pte, 6))
|
|
||||||
{
|
|
||||||
if (!MiIsHyperspaceAddress(Pte))
|
|
||||||
__invlpg(Address);
|
|
||||||
}
|
|
||||||
|
|
||||||
MiFlushTlb(Pte, Address, OldIrql);
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
NTAPI
|
|
||||||
MmDeleteVirtualMapping(
|
|
||||||
PEPROCESS Process,
|
|
||||||
PVOID Address,
|
|
||||||
BOOLEAN* WasDirty,
|
|
||||||
PPFN_NUMBER Page)
|
|
||||||
{
|
|
||||||
PFN_NUMBER Pfn;
|
|
||||||
PMMPTE Pte;
|
|
||||||
MMPTE OldPte;
|
|
||||||
KIRQL OldIrql;
|
|
||||||
|
|
||||||
Pte = MiGetPteForProcess(Process, Address, FALSE, &OldIrql);
|
|
||||||
|
|
||||||
if (Pte)
|
|
||||||
{
|
|
||||||
/* Atomically set the entry to zero and get the old value. */
|
|
||||||
OldPte.u.Long = InterlockedExchange64((LONG64*)&Pte->u.Long, 0);
|
|
||||||
|
|
||||||
if (OldPte.u.Hard.Valid)
|
|
||||||
{
|
|
||||||
Pfn = OldPte.u.Hard.PageFrameNumber;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
Pfn = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
OldPte.u.Long = 0;
|
|
||||||
Pfn = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return information to the caller */
|
|
||||||
if (WasDirty)
|
|
||||||
*WasDirty = (BOOLEAN)OldPte.u.Hard.Dirty;
|
|
||||||
|
|
||||||
if (Page)
|
|
||||||
*Page = Pfn;
|
|
||||||
|
|
||||||
MiFlushTlb(Pte, Address, OldIrql);
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
NTAPI
|
|
||||||
MmDeletePageFileMapping(PEPROCESS Process, PVOID Address,
|
|
||||||
SWAPENTRY* SwapEntry)
|
|
||||||
{
|
|
||||||
PMMPTE Pte;
|
|
||||||
KIRQL OldIrql;
|
|
||||||
|
|
||||||
Pte = MiGetPteForProcess(Process, Address, FALSE, &OldIrql);
|
|
||||||
if (Pte == NULL)
|
|
||||||
{
|
|
||||||
*SwapEntry = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Pte->u.Trans.Valid || !Pte->u.Trans.Transition)
|
|
||||||
{
|
|
||||||
DPRINT1("Pte %x (want not 1 and 0x800)\n", Pte);
|
|
||||||
KeBugCheck(MEMORY_MANAGEMENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
*SwapEntry = Pte->u.Long >> 1;
|
|
||||||
MI_ERASE_PTE(Pte);
|
|
||||||
|
|
||||||
if (MiIsHyperspaceAddress(Pte))
|
|
||||||
MiUnmapPageInHyperSpace(PsGetCurrentProcess(), (PVOID)PAGE_ROUND_DOWN(Pte), OldIrql);
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
NTAPI
|
|
||||||
MmCreatePageFileMapping(PEPROCESS Process,
|
|
||||||
PVOID Address,
|
|
||||||
SWAPENTRY SwapEntry)
|
|
||||||
{
|
|
||||||
PMMPTE Pte;
|
|
||||||
MMPTE PteValue;
|
|
||||||
KIRQL OldIrql;
|
|
||||||
|
|
||||||
if (Process == NULL && Address < MmSystemRangeStart)
|
|
||||||
{
|
|
||||||
DPRINT1("No process\n");
|
|
||||||
KeBugCheck(MEMORY_MANAGEMENT);
|
|
||||||
}
|
|
||||||
if (Process != NULL && Address >= MmSystemRangeStart)
|
|
||||||
{
|
|
||||||
DPRINT1("Setting kernel address with process context\n");
|
|
||||||
KeBugCheck(MEMORY_MANAGEMENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SwapEntry & (1ull << 63))
|
|
||||||
{
|
|
||||||
KeBugCheck(MEMORY_MANAGEMENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Allocate a PTE */
|
|
||||||
Pte = MiGetPteForProcess(Process, Address, TRUE, &OldIrql);
|
|
||||||
if (Pte == NULL)
|
|
||||||
{
|
|
||||||
return STATUS_UNSUCCESSFUL;
|
|
||||||
}
|
|
||||||
|
|
||||||
NT_ASSERT(Pte->u.Long == 0);
|
|
||||||
PteValue.u.Long = SwapEntry << 1;
|
|
||||||
MI_WRITE_INVALID_PTE(Pte, PteValue);
|
|
||||||
|
|
||||||
if (MiIsHyperspaceAddress(Pte))
|
|
||||||
MiUnmapPageInHyperSpace(PsGetCurrentProcess(), (PVOID)PAGE_ROUND_DOWN(Pte), OldIrql);
|
|
||||||
|
|
||||||
return STATUS_UNSUCCESSFUL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
NTAPI
|
|
||||||
MmCreateVirtualMappingUnsafe(
|
|
||||||
PEPROCESS Process,
|
|
||||||
PVOID Address,
|
|
||||||
ULONG PageProtection,
|
|
||||||
PPFN_NUMBER Pages,
|
|
||||||
ULONG PageCount)
|
|
||||||
{
|
|
||||||
ULONG i;
|
|
||||||
MMPTE TmplPte, *Pte;
|
|
||||||
|
|
||||||
ASSERT((ULONG_PTR)Address % PAGE_SIZE == 0);
|
|
||||||
|
|
||||||
/* Check if the range is valid */
|
|
||||||
if ((Process == NULL && Address < MmSystemRangeStart) ||
|
|
||||||
(Process != NULL && Address > MmHighestUserAddress))
|
|
||||||
{
|
|
||||||
DPRINT1("Address 0x%p is invalid for process %p\n", Address, Process);
|
|
||||||
ASSERT(FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
TmplPte.u.Long = 0;
|
|
||||||
TmplPte.u.Hard.Valid = 1;
|
|
||||||
MiSetPteProtection(&TmplPte, PageProtection);
|
|
||||||
|
|
||||||
TmplPte.u.Flush.Owner = (Address < MmHighestUserAddress) ? 1 : 0;
|
|
||||||
|
|
||||||
//__debugbreak();
|
|
||||||
|
|
||||||
for (i = 0; i < PageCount; i++)
|
|
||||||
{
|
|
||||||
KIRQL OldIrql;
|
|
||||||
|
|
||||||
TmplPte.u.Hard.PageFrameNumber = Pages[i];
|
|
||||||
|
|
||||||
Pte = MiGetPteForProcess(Process, Address, TRUE, &OldIrql);
|
|
||||||
|
|
||||||
DPRINT("MmCreateVirtualMappingUnsafe, Address=%p, TmplPte=%p, Pte=%p\n",
|
|
||||||
Address, TmplPte.u.Long, Pte);
|
|
||||||
|
|
||||||
if (InterlockedExchangePte(Pte, TmplPte))
|
|
||||||
{
|
|
||||||
KeInvalidateTlbEntry(Address);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (MiIsHyperspaceAddress(Pte))
|
|
||||||
MiUnmapPageInHyperSpace(PsGetCurrentProcess(), (PVOID)PAGE_ROUND_DOWN(Pte), OldIrql);
|
|
||||||
|
|
||||||
Address = (PVOID)((ULONG64)Address + PAGE_SIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
NTAPI
|
|
||||||
MmCreateVirtualMapping(PEPROCESS Process,
|
|
||||||
PVOID Address,
|
|
||||||
ULONG Protect,
|
|
||||||
PPFN_NUMBER Pages,
|
|
||||||
ULONG PageCount)
|
|
||||||
{
|
|
||||||
ULONG i;
|
|
||||||
|
|
||||||
ASSERT((ULONG_PTR)Address % PAGE_SIZE == 0);
|
|
||||||
|
|
||||||
for (i = 0; i < PageCount; i++)
|
|
||||||
{
|
|
||||||
if (!MmIsPageInUse(Pages[i]))
|
|
||||||
{
|
|
||||||
DPRINT1("Page %x not in use\n", Pages[i]);
|
|
||||||
KeBugCheck(MEMORY_MANAGEMENT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return MmCreateVirtualMappingUnsafe(Process, Address, Protect, Pages, PageCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* EOF */
|
|
|
@ -328,6 +328,7 @@ elseif(ARCH STREQUAL "amd64")
|
||||||
${REACTOS_SOURCE_DIR}/ntoskrnl/ke/amd64/usercall_asm.S)
|
${REACTOS_SOURCE_DIR}/ntoskrnl/ke/amd64/usercall_asm.S)
|
||||||
list(APPEND SOURCE
|
list(APPEND SOURCE
|
||||||
${REACTOS_SOURCE_DIR}/ntoskrnl/config/i386/cmhardwr.c
|
${REACTOS_SOURCE_DIR}/ntoskrnl/config/i386/cmhardwr.c
|
||||||
|
${REACTOS_SOURCE_DIR}/ntoskrnl/mm/i386/page.c
|
||||||
${REACTOS_SOURCE_DIR}/ntoskrnl/kd64/amd64/kdx64.c
|
${REACTOS_SOURCE_DIR}/ntoskrnl/kd64/amd64/kdx64.c
|
||||||
${REACTOS_SOURCE_DIR}/ntoskrnl/ke/amd64/context.c
|
${REACTOS_SOURCE_DIR}/ntoskrnl/ke/amd64/context.c
|
||||||
${REACTOS_SOURCE_DIR}/ntoskrnl/ke/amd64/cpu.c
|
${REACTOS_SOURCE_DIR}/ntoskrnl/ke/amd64/cpu.c
|
||||||
|
@ -339,7 +340,6 @@ elseif(ARCH STREQUAL "amd64")
|
||||||
${REACTOS_SOURCE_DIR}/ntoskrnl/ke/amd64/spinlock.c
|
${REACTOS_SOURCE_DIR}/ntoskrnl/ke/amd64/spinlock.c
|
||||||
${REACTOS_SOURCE_DIR}/ntoskrnl/ke/amd64/thrdini.c
|
${REACTOS_SOURCE_DIR}/ntoskrnl/ke/amd64/thrdini.c
|
||||||
${REACTOS_SOURCE_DIR}/ntoskrnl/mm/amd64/init.c
|
${REACTOS_SOURCE_DIR}/ntoskrnl/mm/amd64/init.c
|
||||||
${REACTOS_SOURCE_DIR}/ntoskrnl/mm/amd64/page.c
|
|
||||||
${REACTOS_SOURCE_DIR}/ntoskrnl/mm/amd64/procsup.c
|
${REACTOS_SOURCE_DIR}/ntoskrnl/mm/amd64/procsup.c
|
||||||
${REACTOS_SOURCE_DIR}/ntoskrnl/ps/amd64/psctx.c
|
${REACTOS_SOURCE_DIR}/ntoskrnl/ps/amd64/psctx.c
|
||||||
${REACTOS_SOURCE_DIR}/ntoskrnl/ke/amd64/stubs.c
|
${REACTOS_SOURCE_DIR}/ntoskrnl/ke/amd64/stubs.c
|
||||||
|
|
Loading…
Reference in a new issue