Author: tkreuzer Date: Sat Dec 19 04:43:33 2009 New Revision: 44653
URL: http://svn.reactos.org/svn/reactos?rev=44653&view=rev Log: [MM] - Improve MiGetPteForProcess Implement MiGetPteProtection, MiSetPteProtection, MmCreateVirtualMappingUnsafe, MmCreateVirtualMapping
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] Sat Dec 19 04:43:33 2009 @@ -18,6 +18,14 @@ #pragma alloc_text(INIT, MiInitPageDirectoryMap) #endif
+#undef InterlockedExchangePte +#define InterlockedExchangePte(pte1, pte2) \ + InterlockedExchange64(&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 *****************************************************************/ @@ -53,7 +61,7 @@ PVOID Address, BOOLEAN Create) { - PMMPTE Pte; + MMPTE TmplPte, *Pte;
/* Check if we need hypersapce mapping */ if (Address < MmSystemRangeStart && @@ -64,25 +72,33 @@ } else if (Create) { + TmplPte.u.Long = 0; + TmplPte.u.Flush.Valid = 1; + TmplPte.u.Flush.Write = 1; + /* Get the PXE */ Pte = MiAddressToPxe(Address); if (!Pte->u.Hard.Valid) - InterlockedBitTestAndSet64(&Pte->u.Long, 0); + { + TmplPte.u.Hard.PageFrameNumber = MiAllocPage(TRUE); + InterlockedExchangePte(Pte, TmplPte); + }
/* Get the PPE */ Pte = MiAddressToPpe(Address); if (!Pte->u.Hard.Valid) - InterlockedBitTestAndSet64(&Pte->u.Long, 0); + { + TmplPte.u.Hard.PageFrameNumber = MiAllocPage(TRUE); + InterlockedExchangePte(Pte, TmplPte); + }
/* Get the PDE */ Pte = MiAddressToPde(Address); if (!Pte->u.Hard.Valid) - InterlockedBitTestAndSet64(&Pte->u.Long, 0); - - /* Get the PTE */ - Pte = MiAddressToPte(Address); - - return Pte; + { + TmplPte.u.Hard.PageFrameNumber = MiAllocPage(TRUE); + InterlockedExchangePte(Pte, TmplPte); + } } else { @@ -100,14 +116,9 @@ Pte = MiAddressToPde(Address); if (!Pte->u.Hard.Valid) return NULL; - - /* Get the PTE */ - Pte = MiAddressToPte(Address); - - return Pte; - } - - return 0; + } + + return MiAddressToPte(Address); }
static @@ -128,75 +139,11 @@ return PteValue; }
- -/* 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; -} - -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; +MiGetPteProtection(MMPTE Pte) +{ ULONG Protect; - - Pte.u.Long = MiGetPteValueForProcess(Process, Address);
if (!Pte.u.Flush.Valid) { @@ -228,11 +175,93 @@ Protect |= PAGE_WRITETHROUGH;
// PAGE_GUARD ? - return Protect; }
-#define PAGE_EXECUTE_ANY (PAGE_EXECUTE|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE|PAGE_EXECUTE_WRITECOPY) +VOID +NTAPI +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; +} + +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); + + return MiGetPteProtection(Pte); +}
VOID NTAPI @@ -241,27 +270,14 @@ 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); + ASSERT(Pte != NULL); + + NewPte = *Pte; + + MiSetPteProtection(&NewPte, flProtect); + + InterlockedExchangePte(Pte, NewPte);
MiFlushTlb(Pte, Address); } @@ -409,26 +425,74 @@
NTSTATUS NTAPI -MmCreateVirtualMappingUnsafe(PEPROCESS Process, - PVOID Address, - ULONG flProtect, - PPFN_NUMBER Pages, - ULONG PageCount) -{ - UNIMPLEMENTED; - return STATUS_UNSUCCESSFUL; +MmCreateVirtualMappingUnsafe( + PEPROCESS Process, + PVOID Address, + ULONG PageProtection, + PPFN_NUMBER Pages, + ULONG PageCount) +{ + ULONG i; + MMPTE TmplPte, *Pte; + + /* 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); + +//__debugbreak(); + + for (i = 0; i < PageCount; i++) + { + TmplPte.u.Hard.PageFrameNumber = Pages[i]; + + Pte = MiGetPteForProcess(Process, Address, TRUE); + +DPRINT1("MmCreateVirtualMappingUnsafe, Address=%p, TmplPte=%p, Pte=%p\n", + Address, TmplPte.u.Long, Pte); + + if (InterlockedExchangePte(Pte, TmplPte)) + { + KeInvalidateTlbEntry(Address); + } + + if (MiIsHyperspaceAddress(Pte)) + MmDeleteHyperspaceMapping((PVOID)PAGE_ROUND_DOWN(Pte)); + + Address = (PVOID)((ULONG64)Address + PAGE_SIZE); + } + + + return STATUS_SUCCESS; }
NTSTATUS NTAPI MmCreateVirtualMapping(PEPROCESS Process, PVOID Address, - ULONG flProtect, + ULONG Protect, PPFN_NUMBER Pages, ULONG PageCount) { - UNIMPLEMENTED; - return STATUS_UNSUCCESSFUL; + ULONG i; + + 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); }
NTSTATUS