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/ntoskr... ============================================================================== --- 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 */