Implement amd64 versions for MiIsHyperspaceAddress, MiFlushTlb, MiGetPteForProcess, MiGetPteValueForProcess, MmGetPfnForProcess, MmGetPhysicalAddress, MmIsPagePresent, MmIsPageSwapEntry, MmIsDirtyPage, MmGetPageProtect, MmSetPageProtect, MmSetCleanPage, MmSetDirtyPage, MmDeleteVirtualMapping

svn path=/branches/ros-amd64-bringup/; revision=44024
This commit is contained in:
Timo Kreuzer
2009-11-08 02:39:47 +00:00
parent aa636e0ec3
commit a1908d10b4
+344 -92
View File
@@ -1,5 +1,5 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* COPYRIGHT: GPL, See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/mm/amd64/page.c
* PURPOSE: Low level memory managment manipulation
@@ -26,9 +26,292 @@ ULONG64 MmGlobalKernelPageDirectory[512];
/* PRIVATE FUNCTIONS *******************************************************/
BOOLEAN
FORCEINLINE
MiIsHyperspaceAddress(PVOID Address)
{
return ((ULONG64)Address >= MI_HYPER_SPACE_START &&
(ULONG64)Address <= MI_HYPER_SPACE_END);
}
VOID
MiFlushTlb(PMMPTE Pte, PVOID Address)
{
if (MiIsHyperspaceAddress(Pte))
{
MmDeleteHyperspaceMapping((PVOID)PAGE_ROUND_DOWN(Pte));
}
else
{
__invlpg(Address);
}
}
static
PMMPTE
MiGetPteForProcess(
PEPROCESS Process,
PVOID Address,
BOOLEAN Create)
{
PMMPTE Pte;
/* Check if we need hypersapce mapping */
if (Address < MmSystemRangeStart &&
Process && Process != PsGetCurrentProcess())
{
UNIMPLEMENTED;
return NULL;
}
else if (Create)
{
/* Get the PXE */
Pte = MiAddressToPxe(Address);
if (!Pte->u.Hard.Valid)
InterlockedBitTestAndSet64(&Pte->u.Long, 0);
/* Get the PPE */
Pte = MiAddressToPpe(Address);
if (!Pte->u.Hard.Valid)
InterlockedBitTestAndSet64(&Pte->u.Long, 0);
/* Get the PDE */
Pte = MiAddressToPde(Address);
if (!Pte->u.Hard.Valid)
InterlockedBitTestAndSet64(&Pte->u.Long, 0);
/* Get the PTE */
Pte = MiAddressToPte(Address);
return Pte;
}
else
{
/* Get the PXE */
Pte = MiAddressToPxe(Address);
if (!Pte->u.Hard.Valid)
return NULL;
/* Get the PPE */
Pte = MiAddressToPpe(Address);
if (Pte->u.Hard.Valid)
return NULL;
/* Get the PDE */
Pte = MiAddressToPde(Address);
if (Pte->u.Hard.Valid)
return NULL;
/* Get the PTE */
Pte = MiAddressToPte(Address);
return Pte;
}
return 0;
}
static
ULONG64
MiGetPteValueForProcess(
PEPROCESS Process,
PVOID Address)
{
PMMPTE Pte;
ULONG64 PteValue;
Pte = MiGetPteForProcess(Process, Address, FALSE);
PteValue = Pte ? Pte->u.Long : 0;
if (MiIsHyperspaceAddress(Pte))
MmDeleteHyperspaceMapping((PVOID)PAGE_ROUND_DOWN(Pte));
return PteValue;
}
/* FUNCTIONS ***************************************************************/
PFN_TYPE
NTAPI
MmGetPfnForProcess(PEPROCESS Process,
PVOID Address)
{
MMPTE Pte;
Pte.u.Long = MiGetPteValueForProcess(Process, Address);
return Pte.u.Hard.Valid ? Pte.u.Hard.PageFrameNumber : 0;
}
PHYSICAL_ADDRESS
NTAPI
MmGetPhysicalAddress(PVOID Address)
{
PHYSICAL_ADDRESS p;
MMPTE Pte;
Pte.u.Long = MiGetPteValueForProcess(NULL, Address);
if (Pte.u.Hard.Valid)
{
p.QuadPart = Pte.u.Hard.PageFrameNumber * PAGE_SIZE;
p.u.LowPart |= (ULONG_PTR)Address & (PAGE_SIZE - 1);
}
else
{
p.QuadPart = 0;
}
return p;
}
BOOLEAN
NTAPI
MmIsPagePresent(PEPROCESS Process, PVOID Address)
{
MMPTE Pte;
Pte.u.Long = MiGetPteValueForProcess(Process, Address);
return Pte.u.Hard.Valid;
}
BOOLEAN
NTAPI
MmIsPageSwapEntry(PEPROCESS Process, PVOID Address)
{
MMPTE Pte;
Pte.u.Long = MiGetPteValueForProcess(Process, Address);
return Pte.u.Hard.Valid && Pte.u.Soft.Transition;
}
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;
ULONG Protect;
Pte.u.Long = MiGetPteValueForProcess(Process, Address);
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;
}
#define PAGE_EXECUTE_ANY (PAGE_EXECUTE|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE|PAGE_EXECUTE_WRITECOPY)
VOID
NTAPI
MmSetPageProtect(PEPROCESS Process, PVOID Address, ULONG flProtect)
{
PMMPTE Pte;
MMPTE NewPte;
if (!(flProtect & PAGE_EXECUTE_ANY))
NewPte.u.Flush.NoExecute = 1;
if (flProtect & (PAGE_EXECUTE_WRITECOPY|PAGE_WRITECOPY))
{
NewPte.u.Flush.Write = 1;
NewPte.u.Flush.CopyOnWrite = 1;
}
if (flProtect & (PAGE_EXECUTE_READWRITE|PAGE_READWRITE))
NewPte.u.Flush.Write = 1;
if (flProtect & PAGE_NOCACHE)
NewPte.u.Flush.CacheDisable = 1;
if (flProtect & PAGE_WRITETHROUGH)
NewPte.u.Flush.WriteThrough = 1;
Pte = MiGetPteForProcess(Process, Address, FALSE);
InterlockedExchange64(&Pte->u.Long, NewPte.u.Long);
MiFlushTlb(Pte, Address);
}
VOID
NTAPI
MmSetCleanPage(PEPROCESS Process, PVOID Address)
{
PMMPTE Pte;
Pte = MiGetPteForProcess(Process, Address, FALSE);
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);
}
VOID
NTAPI
MmSetDirtyPage(PEPROCESS Process, PVOID Address)
{
PMMPTE Pte;
Pte = MiGetPteForProcess(Process, Address, FALSE);
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);
}
NTSTATUS
NTAPI
Mmi386ReleaseMmInfo(PEPROCESS Process)
@@ -37,34 +320,6 @@ Mmi386ReleaseMmInfo(PEPROCESS Process)
return STATUS_UNSUCCESSFUL;
}
NTSTATUS
NTAPI
MmInitializeHandBuiltProcess(IN PEPROCESS Process,
IN PULONG_PTR DirectoryTableBase)
{
UNIMPLEMENTED;
return STATUS_UNSUCCESSFUL;
}
BOOLEAN
NTAPI
MmCreateProcessAddressSpace(IN ULONG MinWs,
IN PEPROCESS Process,
IN PULONG_PTR DirectoryTableBase)
{
UNIMPLEMENTED;
return 0;
}
PFN_TYPE
NTAPI
MmGetPfnForProcess(PEPROCESS Process,
PVOID Address)
{
UNIMPLEMENTED;
return 0;
}
VOID
NTAPI
MmDisableVirtualMapping(PEPROCESS Process, PVOID Address, BOOLEAN* WasDirty, PPFN_TYPE Page)
@@ -81,10 +336,48 @@ MmRawDeleteVirtualMapping(PVOID Address)
VOID
NTAPI
MmDeleteVirtualMapping(PEPROCESS Process, PVOID Address, BOOLEAN FreePage,
BOOLEAN* WasDirty, PPFN_TYPE Page)
MmDeleteVirtualMapping(
PEPROCESS Process,
PVOID Address,
BOOLEAN FreePage,
BOOLEAN* WasDirty,
PPFN_TYPE Page)
{
UNIMPLEMENTED;
PFN_NUMBER Pfn;
PMMPTE Pte;
MMPTE OldPte;
Pte = MiGetPteForProcess(Process, Address, FALSE);
if (Pte)
{
/* Atomically set the entry to zero and get the old value. */
OldPte.u.Long = InterlockedExchange64(&Pte->u.Long, 0);
if (OldPte.u.Hard.Valid)
{
Pfn = OldPte.u.Hard.PageFrameNumber;
if (FreePage)
MmReleasePageMemoryConsumer(MC_NPPOOL, Pfn);
}
else
Pfn = 0;
}
else
{
OldPte.u.Long = 0;
Pfn = 0;
}
/* Return information to the caller */
if (WasDirty)
*WasDirty = OldPte.u.Hard.Dirty;;
if (Page)
*Page = Pfn;
MiFlushTlb(Pte, Address);
}
VOID
@@ -95,27 +388,6 @@ MmDeletePageFileMapping(PEPROCESS Process, PVOID Address,
UNIMPLEMENTED;
}
BOOLEAN
NTAPI
MmIsDirtyPage(PEPROCESS Process, PVOID Address)
{
UNIMPLEMENTED;
return FALSE;
}
VOID
NTAPI
MmSetCleanPage(PEPROCESS Process, PVOID Address)
{
UNIMPLEMENTED;
}
VOID
NTAPI
MmSetDirtyPage(PEPROCESS Process, PVOID Address)
{
UNIMPLEMENTED;
}
VOID
NTAPI
@@ -124,21 +396,6 @@ MmEnableVirtualMapping(PEPROCESS Process, PVOID Address)
UNIMPLEMENTED;
}
BOOLEAN
NTAPI
MmIsPagePresent(PEPROCESS Process, PVOID Address)
{
UNIMPLEMENTED;
return 0;
}
BOOLEAN
NTAPI
MmIsPageSwapEntry(PEPROCESS Process, PVOID Address)
{
UNIMPLEMENTED;
return 0;
}
NTSTATUS
NTAPI
@@ -175,30 +432,6 @@ MmCreateVirtualMapping(PEPROCESS Process,
return STATUS_UNSUCCESSFUL;
}
ULONG
NTAPI
MmGetPageProtect(PEPROCESS Process, PVOID Address)
{
UNIMPLEMENTED;
return 0;
}
VOID
NTAPI
MmSetPageProtect(PEPROCESS Process, PVOID Address, ULONG flProtect)
{
UNIMPLEMENTED;
}
PHYSICAL_ADDRESS
NTAPI
MmGetPhysicalAddress(PVOID vaddr)
{
PHYSICAL_ADDRESS ret = {{0}};
UNIMPLEMENTED;
return ret;
}
VOID
NTAPI
MmUpdatePageDir(PEPROCESS Process, PVOID Address, ULONG Size)
@@ -244,5 +477,24 @@ MmInitGlobalKernelPageDirectory(VOID)
UNIMPLEMENTED;
}
NTSTATUS
NTAPI
MmInitializeHandBuiltProcess(IN PEPROCESS Process,
IN PULONG_PTR DirectoryTableBase)
{
UNIMPLEMENTED;
return STATUS_UNSUCCESSFUL;
}
BOOLEAN
NTAPI
MmCreateProcessAddressSpace(IN ULONG MinWs,
IN PEPROCESS Process,
IN PULONG_PTR DirectoryTableBase)
{
UNIMPLEMENTED;
return 0;
}
/* EOF */