From 7ea8312617df0219277b73e84d4452cb2f9f3caf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Gardou?= Date: Thu, 1 Apr 2021 15:54:19 +0200 Subject: [PATCH] [NTOS:MM] Split MmCreateProcessAddressSpace in two parts Generic one and arch-specific one. Properly fail if we are out of resources. Restore a lost assert. --- ntoskrnl/include/internal/mm.h | 7 ++ ntoskrnl/mm/ARM3/procsup.c | 145 ++++++++++----------------------- ntoskrnl/mm/amd64/page.c | 131 ----------------------------- ntoskrnl/mm/amd64/procsup.c | 132 ++++++++++++++++++++++++++++++ ntoskrnl/mm/i386/procsup.c | 98 ++++++++++++++++++++++ ntoskrnl/ntos.cmake | 2 + 6 files changed, 281 insertions(+), 234 deletions(-) create mode 100644 ntoskrnl/mm/amd64/procsup.c create mode 100644 ntoskrnl/mm/i386/procsup.c diff --git a/ntoskrnl/include/internal/mm.h b/ntoskrnl/include/internal/mm.h index d2cb0123bed..6f9d6f57f40 100644 --- a/ntoskrnl/include/internal/mm.h +++ b/ntoskrnl/include/internal/mm.h @@ -1205,6 +1205,13 @@ MmDeleteVirtualMapping( PPFN_NUMBER Page ); +/* arch/procsup.c ************************************************************/ + +BOOLEAN +MiArchCreateProcessAddressSpace( + _In_ PEPROCESS Process, + _In_ PULONG_PTR DirectoryTableBase); + /* wset.c ********************************************************************/ NTSTATUS diff --git a/ntoskrnl/mm/ARM3/procsup.c b/ntoskrnl/mm/ARM3/procsup.c index eb8e68180d4..23981bcadf1 100644 --- a/ntoskrnl/mm/ARM3/procsup.c +++ b/ntoskrnl/mm/ARM3/procsup.c @@ -999,18 +999,24 @@ MmInitializeProcessAddressSpace(IN PEPROCESS Process, /* Do the same for hyperspace */ PointerPde = MiAddressToPde((PVOID)HYPER_SPACE); PageFrameNumber = PFN_FROM_PTE(PointerPde); - //ASSERT(Process->Pcb.DirectoryTableBase[0] == PageFrameNumber * PAGE_SIZE); // we're not lucky MiInitializePfn(PageFrameNumber, (PMMPTE)PointerPde, TRUE); +#if (_MI_PAGING_LEVELS == 2) + ASSERT(Process->Pcb.DirectoryTableBase[1] == PageFrameNumber * PAGE_SIZE); +#endif #if (_MI_PAGING_LEVELS >= 3) PointerPpe = MiAddressToPpe((PVOID)HYPER_SPACE); PageFrameNumber = PFN_FROM_PTE(PointerPpe); MiInitializePfn(PageFrameNumber, PointerPpe, TRUE); +#if (_MI_PAGING_LEVELS == 3) + ASSERT(Process->Pcb.DirectoryTableBase[1] == PageFrameNumber * PAGE_SIZE); +#endif #endif #if (_MI_PAGING_LEVELS == 4) PointerPxe = MiAddressToPxe((PVOID)HYPER_SPACE); PageFrameNumber = PFN_FROM_PTE(PointerPxe); MiInitializePfn(PageFrameNumber, PointerPxe, TRUE); + ASSERT(Process->Pcb.DirectoryTableBase[1] == PageFrameNumber * PAGE_SIZE); #endif /* Setup the PFN for the PTE for the working set */ @@ -1149,8 +1155,6 @@ MmInitializeHandBuiltProcess2(IN PEPROCESS Process) return STATUS_SUCCESS; } -#ifdef _M_IX86 -/* FIXME: Evaluate ways to make this portable yet arch-specific */ BOOLEAN NTAPI MmCreateProcessAddressSpace(IN ULONG MinWs, @@ -1158,13 +1162,13 @@ MmCreateProcessAddressSpace(IN ULONG MinWs, OUT PULONG_PTR DirectoryTableBase) { KIRQL OldIrql; - PFN_NUMBER PdeIndex, HyperIndex, WsListIndex; - PMMPTE PointerPte; - MMPTE TempPte, PdePte; - ULONG PdeOffset; - PMMPTE SystemTable, HyperTable; + PFN_NUMBER TableBaseIndex, HyperIndex, WsListIndex; ULONG Color; - PMMPFN Pfn1; + + /* Make sure we don't already have a page directory setup */ + ASSERT(Process->Pcb.DirectoryTableBase[0] == 0); + ASSERT(Process->Pcb.DirectoryTableBase[1] == 0); + ASSERT(Process->WorkingSetPage == 0); /* Choose a process color */ Process->NextPageColor = (USHORT)RtlRandom(&MmProcessColorSeed); @@ -1175,22 +1179,25 @@ MmCreateProcessAddressSpace(IN ULONG MinWs, /* Lock PFN database */ OldIrql = MiAcquirePfnLock(); - /* Get a zero page for the PDE, if possible */ + /* + * Get a page for the table base, one for hyper space & one for the working set list. + * The PFNs for these pages will be initialized in MmInitializeProcessAddressSpace, + * when we are already attached to the process. + * The other pages (if any) are allocated in the arch-specific part. + */ Color = MI_GET_NEXT_PROCESS_COLOR(Process); MI_SET_USAGE(MI_USAGE_PAGE_DIRECTORY); - PdeIndex = MiRemoveZeroPageSafe(Color); - if (!PdeIndex) + TableBaseIndex = MiRemoveZeroPageSafe(Color); + if (!TableBaseIndex) { /* No zero pages, grab a free one */ - PdeIndex = MiRemoveAnyPage(Color); + TableBaseIndex = MiRemoveAnyPage(Color); /* Zero it outside the PFN lock */ MiReleasePfnLock(OldIrql); - MiZeroPhysicalPage(PdeIndex); + MiZeroPhysicalPage(TableBaseIndex); OldIrql = MiAcquirePfnLock(); } - - /* Get a zero page for hyperspace, if possible */ MI_SET_USAGE(MI_USAGE_PAGE_DIRECTORY); Color = MI_GET_NEXT_PROCESS_COLOR(Process); HyperIndex = MiRemoveZeroPageSafe(Color); @@ -1204,8 +1211,6 @@ MmCreateProcessAddressSpace(IN ULONG MinWs, MiZeroPhysicalPage(HyperIndex); OldIrql = MiAcquirePfnLock(); } - - /* Get a zero page for the woring set list, if possible */ MI_SET_USAGE(MI_USAGE_PAGE_TABLE); Color = MI_GET_NEXT_PROCESS_COLOR(Process); WsListIndex = MiRemoveZeroPageSafe(Color); @@ -1224,99 +1229,33 @@ MmCreateProcessAddressSpace(IN ULONG MinWs, MiReleasePfnLock(OldIrql); } + /* Set the base directory pointers */ + Process->WorkingSetPage = WsListIndex; + DirectoryTableBase[0] = TableBaseIndex << PAGE_SHIFT; + DirectoryTableBase[1] = HyperIndex << PAGE_SHIFT; + + /* Perform the arch-specific parts */ + if (!MiArchCreateProcessAddressSpace(Process, DirectoryTableBase)) + { + OldIrql = MiAcquirePfnLock(); + MiInsertPageInFreeList(WsListIndex); + MiInsertPageInFreeList(HyperIndex); + MiInsertPageInFreeList(TableBaseIndex); + MiReleasePfnLock(OldIrql); + Process->WorkingSetPage = 0; + DirectoryTableBase[0] = 0; + DirectoryTableBase[1] = 0; + return FALSE; + } + /* Switch to phase 1 initialization */ ASSERT(Process->AddressSpaceInitialized == 0); Process->AddressSpaceInitialized = 1; - /* Set the base directory pointers */ - Process->WorkingSetPage = WsListIndex; - DirectoryTableBase[0] = PdeIndex << PAGE_SHIFT; - DirectoryTableBase[1] = HyperIndex << PAGE_SHIFT; - - /* Make sure we don't already have a page directory setup */ - ASSERT(Process->Pcb.DirectoryTableBase[0] == 0); - - /* Get a PTE to map hyperspace */ - PointerPte = MiReserveSystemPtes(1, SystemPteSpace); - ASSERT(PointerPte != NULL); - - /* Build it */ - MI_MAKE_HARDWARE_PTE_KERNEL(&PdePte, - PointerPte, - MM_READWRITE, - HyperIndex); - - /* Set it dirty and map it */ - MI_MAKE_DIRTY_PAGE(&PdePte); - MI_WRITE_VALID_PTE(PointerPte, PdePte); - - /* Now get hyperspace's page table */ - HyperTable = MiPteToAddress(PointerPte); - - /* Now write the PTE/PDE entry for the working set list index itself */ - TempPte = ValidKernelPteLocal; - TempPte.u.Hard.PageFrameNumber = WsListIndex; - PdeOffset = MiAddressToPteOffset(MmWorkingSetList); - HyperTable[PdeOffset] = TempPte; - - /* Let go of the system PTE */ - MiReleaseSystemPtes(PointerPte, 1, SystemPteSpace); - - /* Save the PTE address of the page directory itself */ - Pfn1 = MiGetPfnEntry(PdeIndex); - Pfn1->PteAddress = (PMMPTE)PDE_BASE; - - /* Insert us into the Mm process list */ - OldIrql = MiAcquireExpansionLock(); - InsertTailList(&MmProcessList, &Process->MmProcessLinks); - MiReleaseExpansionLock(OldIrql); - - /* Get a PTE to map the page directory */ - PointerPte = MiReserveSystemPtes(1, SystemPteSpace); - ASSERT(PointerPte != NULL); - - /* Build it */ - MI_MAKE_HARDWARE_PTE_KERNEL(&PdePte, - PointerPte, - MM_READWRITE, - PdeIndex); - - /* Set it dirty and map it */ - MI_MAKE_DIRTY_PAGE(&PdePte); - MI_WRITE_VALID_PTE(PointerPte, PdePte); - - /* Now get the page directory (which we'll double map, so call it a page table */ - SystemTable = MiPteToAddress(PointerPte); - - /* Copy all the kernel mappings */ - PdeOffset = MiGetPdeOffset(MmSystemRangeStart); - RtlCopyMemory(&SystemTable[PdeOffset], - MiAddressToPde(MmSystemRangeStart), - PAGE_SIZE - PdeOffset * sizeof(MMPTE)); - - /* Now write the PTE/PDE entry for hyperspace itself */ - TempPte = ValidKernelPteLocal; - TempPte.u.Hard.PageFrameNumber = HyperIndex; - PdeOffset = MiGetPdeOffset(HYPER_SPACE); - SystemTable[PdeOffset] = TempPte; - - /* Sanity check */ - PdeOffset++; - ASSERT(MiGetPdeOffset(MmHyperSpaceEnd) >= PdeOffset); - - /* Now do the x86 trick of making the PDE a page table itself */ - PdeOffset = MiGetPdeOffset(PTE_BASE); - TempPte.u.Hard.PageFrameNumber = PdeIndex; - SystemTable[PdeOffset] = TempPte; - - /* Let go of the system PTE */ - MiReleaseSystemPtes(PointerPte, 1, SystemPteSpace); - /* Add the process to the session */ MiSessionAddProcess(Process); return TRUE; } -#endif VOID NTAPI diff --git a/ntoskrnl/mm/amd64/page.c b/ntoskrnl/mm/amd64/page.c index 90a5d74b3b2..3a3c3e4c89a 100644 --- a/ntoskrnl/mm/amd64/page.c +++ b/ntoskrnl/mm/amd64/page.c @@ -618,135 +618,4 @@ MmCreateVirtualMapping(PEPROCESS Process, return MmCreateVirtualMappingUnsafe(Process, Address, Protect, Pages, PageCount); } -BOOLEAN -NTAPI -MmCreateProcessAddressSpace(IN ULONG MinWs, - IN PEPROCESS Process, - OUT PULONG_PTR DirectoryTableBase) -{ - KIRQL OldIrql; - PFN_NUMBER TableBasePfn, HyperPfn, HyperPdPfn, HyperPtPfn, WorkingSetPfn; - PMMPTE SystemPte; - MMPTE TempPte, PdePte; - ULONG TableIndex; - PMMPTE PageTablePointer; - - /* Make sure we don't already have a page directory setup */ - ASSERT(Process->Pcb.DirectoryTableBase[0] == 0); - ASSERT(Process->Pcb.DirectoryTableBase[1] == 0); - ASSERT(Process->WorkingSetPage == 0); - - /* Choose a process color */ - Process->NextPageColor = (USHORT)RtlRandom(&MmProcessColorSeed); - - /* Setup the hyperspace lock */ - KeInitializeSpinLock(&Process->HyperSpaceLock); - - /* Lock PFN database */ - OldIrql = MiAcquirePfnLock(); - - /* Get a page for the table base and one for hyper space. The PFNs for - these pages will be initialized in MmInitializeProcessAddressSpace, - when we are already attached to the process. */ - TableBasePfn = MiRemoveAnyPage(MI_GET_NEXT_PROCESS_COLOR(Process)); - HyperPfn = MiRemoveAnyPage(MI_GET_NEXT_PROCESS_COLOR(Process)); - HyperPdPfn = MiRemoveAnyPage(MI_GET_NEXT_PROCESS_COLOR(Process)); - HyperPtPfn = MiRemoveAnyPage(MI_GET_NEXT_PROCESS_COLOR(Process)); - WorkingSetPfn = MiRemoveAnyPage(MI_GET_NEXT_PROCESS_COLOR(Process)); - - /* Release PFN lock */ - MiReleasePfnLock(OldIrql); - - /* Zero pages */ - MiZeroPhysicalPage(TableBasePfn); - MiZeroPhysicalPage(HyperPfn); - MiZeroPhysicalPage(HyperPdPfn); - MiZeroPhysicalPage(HyperPtPfn); - MiZeroPhysicalPage(WorkingSetPfn); - - /* Set the base directory pointers */ - Process->WorkingSetPage = WorkingSetPfn; - DirectoryTableBase[0] = TableBasePfn << PAGE_SHIFT; - DirectoryTableBase[1] = HyperPfn << PAGE_SHIFT; - - /* Get a PTE to map the page directory */ - SystemPte = MiReserveSystemPtes(1, SystemPteSpace); - ASSERT(SystemPte != NULL); - - /* Get its address */ - PageTablePointer = MiPteToAddress(SystemPte); - - /* Build the PTE for the page directory and map it */ - PdePte = ValidKernelPte; - PdePte.u.Hard.PageFrameNumber = TableBasePfn; - *SystemPte = PdePte; - -/// architecture specific - //MiInitializePageDirectoryForProcess( - - /* Copy the kernel mappings and zero out the rest */ - TableIndex = PXE_PER_PAGE / 2; - RtlZeroMemory(PageTablePointer, TableIndex * sizeof(MMPTE)); - RtlCopyMemory(PageTablePointer + TableIndex, - MiAddressToPxe(0) + TableIndex, - PAGE_SIZE - TableIndex * sizeof(MMPTE)); - - /* Sanity check */ - ASSERT(MiAddressToPxi(MmHyperSpaceEnd) >= TableIndex); - - /* Setup a PTE for the page directory mappings */ - TempPte = ValidKernelPte; - - /* Update the self mapping of the PML4 */ - TableIndex = MiAddressToPxi((PVOID)PXE_SELFMAP); - TempPte.u.Hard.PageFrameNumber = TableBasePfn; - PageTablePointer[TableIndex] = TempPte; - - /* Write the PML4 entry for hyperspace */ - TableIndex = MiAddressToPxi((PVOID)HYPER_SPACE); - TempPte.u.Hard.PageFrameNumber = HyperPfn; - PageTablePointer[TableIndex] = TempPte; - - /* Map the hyperspace PDPT to the system PTE */ - PdePte.u.Hard.PageFrameNumber = HyperPfn; - *SystemPte = PdePte; - __invlpg(PageTablePointer); - - /* Write the hyperspace entry for the first PD */ - TempPte.u.Hard.PageFrameNumber = HyperPdPfn; - PageTablePointer[0] = TempPte; - - /* Map the hyperspace PD to the system PTE */ - PdePte.u.Hard.PageFrameNumber = HyperPdPfn; - *SystemPte = PdePte; - __invlpg(PageTablePointer); - - /* Write the hyperspace entry for the first PT */ - TempPte.u.Hard.PageFrameNumber = HyperPtPfn; - PageTablePointer[0] = TempPte; - - /* Map the hyperspace PT to the system PTE */ - PdePte.u.Hard.PageFrameNumber = HyperPtPfn; - *SystemPte = PdePte; - __invlpg(PageTablePointer); - - /* Write the hyperspace PTE for the working set list index */ - TempPte.u.Hard.PageFrameNumber = WorkingSetPfn; - TableIndex = MiAddressToPti(MmWorkingSetList); - PageTablePointer[TableIndex] = TempPte; - -/// end architecture specific - - /* Release the system PTE */ - MiReleaseSystemPtes(SystemPte, 1, SystemPteSpace); - - /* Switch to phase 1 initialization */ - ASSERT(Process->AddressSpaceInitialized == 0); - Process->AddressSpaceInitialized = 1; - - /* Add the process to the session */ - MiSessionAddProcess(Process); - return TRUE; -} - /* EOF */ diff --git a/ntoskrnl/mm/amd64/procsup.c b/ntoskrnl/mm/amd64/procsup.c new file mode 100644 index 00000000000..4cde151fb9e --- /dev/null +++ b/ntoskrnl/mm/amd64/procsup.c @@ -0,0 +1,132 @@ +/* + * COPYRIGHT: GPL, See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/mm/amd64/procsup.c + * PURPOSE: Low level memory managment manipulation + * + * PROGRAMMER: Timo Kreuzer (timo.kreuzer@reactos.org) + * ReactOS Portable Systems Group + */ + +/* INCLUDES *******************************************************************/ + +#include +#define NDEBUG +#include + +#define MODULE_INVOLVED_IN_ARM3 +#include + +BOOLEAN +MiArchCreateProcessAddressSpace( + _In_ PEPROCESS Process, + _In_ PULONG_PTR DirectoryTableBase) +{ + KIRQL OldIrql; + PFN_NUMBER TableBasePfn, HyperPfn, HyperPdPfn, HyperPtPfn; + PMMPTE SystemPte; + MMPTE TempPte, PdePte; + ULONG TableIndex; + PMMPTE PageTablePointer; + ULONG PageColor; + + /* Non-arch specific code-path allocated those for us */ + TableBasePfn = DirectoryTableBase[0] >> PAGE_SHIFT; + HyperPfn = DirectoryTableBase[1] >> PAGE_SHIFT; + + /* + * Lock PFN database. Try getting zero pages. + * If that doesn't work, we take the slow path + * outside of the PFN lock. + */ + OldIrql = MiAcquirePfnLock(); + PageColor = MI_GET_NEXT_PROCESS_COLOR(Process); + HyperPdPfn = MiRemoveZeroPageSafe(PageColor); + if(!HyperPdPfn) + { + HyperPdPfn = MiRemoveAnyPage(PageColor); + MiReleasePfnLock(OldIrql); + MiZeroPhysicalPage(HyperPdPfn); + OldIrql = MiAcquirePfnLock(); + } + PageColor = MI_GET_NEXT_PROCESS_COLOR(Process); + HyperPtPfn = MiRemoveZeroPageSafe(PageColor); + if(!HyperPtPfn) + { + HyperPtPfn = MiRemoveAnyPage(PageColor); + MiReleasePfnLock(OldIrql); + MiZeroPhysicalPage(HyperPtPfn); + } + else + { + MiReleasePfnLock(OldIrql); + } + + /* Get a PTE to map the page directory */ + SystemPte = MiReserveSystemPtes(1, SystemPteSpace); + if (!SystemPte) + return FALSE; + + /* Get its address */ + PageTablePointer = MiPteToAddress(SystemPte); + + /* Build the PTE for the page directory and map it */ + MI_MAKE_HARDWARE_PTE_KERNEL(&PdePte, SystemPte, MM_READWRITE, TableBasePfn); + MI_WRITE_VALID_PTE(SystemPte, PdePte); + + /* Copy the kernel mappings and zero out the rest */ + TableIndex = PXE_PER_PAGE / 2; + RtlZeroMemory(PageTablePointer, TableIndex * sizeof(MMPTE)); + RtlCopyMemory(PageTablePointer + TableIndex, + MiAddressToPxe(0) + TableIndex, + PAGE_SIZE - TableIndex * sizeof(MMPTE)); + + /* Sanity check */ + ASSERT(MiAddressToPxi(MmHyperSpaceEnd) >= TableIndex); + + /* Setup a PTE for the page directory mappings */ + TempPte = ValidKernelPte; + + /* Update the self mapping of the PML4 */ + TableIndex = MiAddressToPxi((PVOID)PXE_SELFMAP); + TempPte.u.Hard.PageFrameNumber = TableBasePfn; + PageTablePointer[TableIndex] = TempPte; + + /* Write the PML4 entry for hyperspace */ + TableIndex = MiAddressToPxi((PVOID)HYPER_SPACE); + TempPte.u.Hard.PageFrameNumber = HyperPfn; + PageTablePointer[TableIndex] = TempPte; + + /* Map the hyperspace PDPT to the system PTE */ + PdePte.u.Hard.PageFrameNumber = HyperPfn; + *SystemPte = PdePte; + __invlpg(PageTablePointer); + + /* Write the hyperspace entry for the first PD */ + TempPte.u.Hard.PageFrameNumber = HyperPdPfn; + PageTablePointer[0] = TempPte; + + /* Map the hyperspace PD to the system PTE */ + PdePte.u.Hard.PageFrameNumber = HyperPdPfn; + *SystemPte = PdePte; + __invlpg(PageTablePointer); + + /* Write the hyperspace entry for the first PT */ + TempPte.u.Hard.PageFrameNumber = HyperPtPfn; + PageTablePointer[0] = TempPte; + + /* Map the hyperspace PT to the system PTE */ + PdePte.u.Hard.PageFrameNumber = HyperPtPfn; + *SystemPte = PdePte; + __invlpg(PageTablePointer); + + /* Write the hyperspace PTE for the working set list index */ + TempPte.u.Hard.PageFrameNumber = Process->WorkingSetPage; + TableIndex = MiAddressToPti(MmWorkingSetList); + PageTablePointer[TableIndex] = TempPte; + + /* Release the system PTE */ + MiReleaseSystemPtes(SystemPte, 1, SystemPteSpace); + + return TRUE; +} diff --git a/ntoskrnl/mm/i386/procsup.c b/ntoskrnl/mm/i386/procsup.c new file mode 100644 index 00000000000..8ffaec103c6 --- /dev/null +++ b/ntoskrnl/mm/i386/procsup.c @@ -0,0 +1,98 @@ +/* + * PROJECT: ReactOS Kernel + * LICENSE: BSD-3-Clause (https://spdx.org/licenses/BSD-3-Clause.html) + * FILE: ntoskrnl/mm/i386/procsup.c + * PURPOSE: Process handling for i386 architecture + * PROGRAMMERS: Jérôme Gardou + */ + +/* INCLUDES *******************************************************************/ + +#include +#define NDEBUG +#include + +#define MODULE_INVOLVED_IN_ARM3 +#include + +BOOLEAN +MiArchCreateProcessAddressSpace( + _In_ PEPROCESS Process, + _In_ PULONG_PTR DirectoryTableBase) +{ + PFN_NUMBER PdeIndex = DirectoryTableBase[0] >> PAGE_SHIFT; + PFN_NUMBER HyperIndex = DirectoryTableBase[1] >> PAGE_SHIFT; + PMMPTE PointerPte; + MMPTE PdePte, TempPte; + PMMPTE PteTable; + ULONG PdeOffset; + KIRQL OldIrql; + + /* Get a PTE */ + PointerPte = MiReserveSystemPtes(1, SystemPteSpace); + if (!PointerPte) + return FALSE; + PteTable = MiPteToAddress(PointerPte); + + /* Build a page table for hyper space */ + MI_MAKE_HARDWARE_PTE_KERNEL(&PdePte, + PointerPte, + MM_READWRITE, + HyperIndex); + + /* Set it dirty and map it */ + MI_MAKE_DIRTY_PAGE(&PdePte); + MI_WRITE_VALID_PTE(PointerPte, PdePte); + + /* Now write the PTE/PDE entry for the working set list index itself */ + TempPte = ValidKernelPteLocal; + TempPte.u.Hard.PageFrameNumber = Process->WorkingSetPage; + PdeOffset = MiAddressToPteOffset(MmWorkingSetList); + PteTable[PdeOffset] = TempPte; + + /* Now we map the page directory */ + MI_MAKE_HARDWARE_PTE_KERNEL(&PdePte, + PointerPte, + MM_READWRITE, + PdeIndex); + + /* Set it dirty and map it */ + MI_MAKE_DIRTY_PAGE(&PdePte); + *PointerPte = PdePte; + /* We changed the page! */ + __invlpg(PteTable); + + /* Now get the page directory (which we'll double map, so call it a page table) */ + PteTable = MiPteToAddress(PointerPte); + + /* Copy all the kernel mappings */ + PdeOffset = MiGetPdeOffset(MmSystemRangeStart); + RtlCopyMemory(&PteTable[PdeOffset], + MiAddressToPde(MmSystemRangeStart), + PAGE_SIZE - PdeOffset * sizeof(MMPTE)); + + /* Now write the PTE/PDE entry for hyperspace itself */ + TempPte = ValidKernelPteLocal; + TempPte.u.Hard.PageFrameNumber = HyperIndex; + PdeOffset = MiGetPdeOffset(HYPER_SPACE); + PteTable[PdeOffset] = TempPte; + + /* Sanity check */ + PdeOffset++; + ASSERT(MiGetPdeOffset(MmHyperSpaceEnd) >= PdeOffset); + + /* Now do the x86 trick of making the PDE a page table itself */ + PdeOffset = MiGetPdeOffset(PTE_BASE); + TempPte.u.Hard.PageFrameNumber = PdeIndex; + PteTable[PdeOffset] = TempPte; + + /* Let go of the system PTE */ + MiReleaseSystemPtes(PointerPte, 1, SystemPteSpace); + + /* Insert us into the Mm process list */ + OldIrql = MiAcquireExpansionLock(); + InsertTailList(&MmProcessList, &Process->MmProcessLinks); + MiReleaseExpansionLock(OldIrql); + + return TRUE; +} diff --git a/ntoskrnl/ntos.cmake b/ntoskrnl/ntos.cmake index 2a098336288..d3349f9f808 100644 --- a/ntoskrnl/ntos.cmake +++ b/ntoskrnl/ntos.cmake @@ -314,6 +314,7 @@ if(ARCH STREQUAL "i386") ${REACTOS_SOURCE_DIR}/ntoskrnl/ke/i386/usercall.c ${REACTOS_SOURCE_DIR}/ntoskrnl/ke/i386/v86vdm.c ${REACTOS_SOURCE_DIR}/ntoskrnl/mm/i386/page.c + ${REACTOS_SOURCE_DIR}/ntoskrnl/mm/i386/procsup.c ${REACTOS_SOURCE_DIR}/ntoskrnl/mm/ARM3/i386/init.c ${REACTOS_SOURCE_DIR}/ntoskrnl/ps/i386/psctx.c ${REACTOS_SOURCE_DIR}/ntoskrnl/ps/i386/psldt.c @@ -339,6 +340,7 @@ elseif(ARCH STREQUAL "amd64") ${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 ${REACTOS_SOURCE_DIR}/ntoskrnl/ke/amd64/usercall.c)