Author: tkreuzer
Date: Sun Nov 8 03:39:47 2009
New Revision: 44024
URL:
http://svn.reactos.org/svn/reactos?rev=44024&view=rev
Log:
[MM]
Implement amd64 versions for MiIsHyperspaceAddress, MiFlushTlb, MiGetPteForProcess,
MiGetPteValueForProcess, MmGetPfnForProcess, MmGetPhysicalAddress, MmIsPagePresent,
MmIsPageSwapEntry, MmIsDirtyPage, MmGetPageProtect, MmSetPageProtect, MmSetCleanPage,
MmSetDirtyPage, MmDeleteVirtualMapping
Modified:
branches/ros-amd64-bringup/reactos/ntoskrnl/mm/amd64/page.c
Modified: branches/ros-amd64-bringup/reactos/ntoskrnl/mm/amd64/page.c
URL:
http://svn.reactos.org/svn/reactos/branches/ros-amd64-bringup/reactos/ntosk…
==============================================================================
--- branches/ros-amd64-bringup/reactos/ntoskrnl/mm/amd64/page.c [iso-8859-1] (original)
+++ branches/ros-amd64-bringup/reactos/ntoskrnl/mm/amd64/page.c [iso-8859-1] Sun Nov 8
03:39:47 2009
@@ -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,43 +26,298 @@
/* 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 ***************************************************************/
-
-NTSTATUS
-NTAPI
-Mmi386ReleaseMmInfo(PEPROCESS Process)
-{
- UNIMPLEMENTED;
- 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;
+ 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)
+{
+ UNIMPLEMENTED;
+ return STATUS_UNSUCCESSFUL;
}
VOID
@@ -81,10 +336,48 @@
VOID
NTAPI
-MmDeleteVirtualMapping(PEPROCESS Process, PVOID Address, BOOLEAN FreePage,
- BOOLEAN* WasDirty, PPFN_TYPE Page)
-{
- UNIMPLEMENTED;
+MmDeleteVirtualMapping(
+ PEPROCESS Process,
+ PVOID Address,
+ BOOLEAN FreePage,
+ BOOLEAN* WasDirty,
+ PPFN_TYPE Page)
+{
+ 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 @@
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 @@
UNIMPLEMENTED;
}
-BOOLEAN
-NTAPI
-MmIsPagePresent(PEPROCESS Process, PVOID Address)
-{
- UNIMPLEMENTED;
- return 0;
-}
-
-BOOLEAN
-NTAPI
-MmIsPageSwapEntry(PEPROCESS Process, PVOID Address)
-{
- UNIMPLEMENTED;
- return 0;
-}
NTSTATUS
NTAPI
@@ -173,30 +430,6 @@
{
UNIMPLEMENTED;
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
@@ -244,5 +477,24 @@
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 */