mirror of
https://github.com/reactos/reactos.git
synced 2024-12-27 09:34:43 +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));
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
VOID
|
||||
MmInitGlobalKernelPageDirectory(VOID)
|
||||
{
|
||||
/* Nothing to do */
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
BOOLEAN
|
||||
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)
|
||||
list(APPEND SOURCE
|
||||
${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/ke/amd64/context.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/thrdini.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/ps/amd64/psctx.c
|
||||
${REACTOS_SOURCE_DIR}/ntoskrnl/ke/amd64/stubs.c
|
||||
|
|
Loading…
Reference in a new issue