diff --git a/ntoskrnl/include/internal/amd64/mm.h b/ntoskrnl/include/internal/amd64/mm.h index 1afab8fd17b..e62df71cfe0 100644 --- a/ntoskrnl/include/internal/amd64/mm.h +++ b/ntoskrnl/include/internal/amd64/mm.h @@ -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) diff --git a/ntoskrnl/mm/amd64/page.c b/ntoskrnl/mm/amd64/page.c deleted file mode 100644 index 3a3c3e4c89a..00000000000 --- a/ntoskrnl/mm/amd64/page.c +++ /dev/null @@ -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 -#define NDEBUG -#include -#include - -#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 */ diff --git a/ntoskrnl/ntos.cmake b/ntoskrnl/ntos.cmake index d3349f9f808..c392bcd95ec 100644 --- a/ntoskrnl/ntos.cmake +++ b/ntoskrnl/ntos.cmake @@ -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