[NTOS:MM] Split MmCreateProcessAddressSpace in two parts
authorJérôme Gardou <jerome.gardou@reactos.org>
Thu, 1 Apr 2021 13:54:19 +0000 (15:54 +0200)
committerJérôme Gardou <zefklop@users.noreply.github.com>
Thu, 8 Apr 2021 13:40:37 +0000 (15:40 +0200)
Generic one and arch-specific one.
Properly fail if we are out of resources.
Restore a lost assert.

ntoskrnl/include/internal/mm.h
ntoskrnl/mm/ARM3/procsup.c
ntoskrnl/mm/amd64/page.c
ntoskrnl/mm/amd64/procsup.c [new file with mode: 0644]
ntoskrnl/mm/i386/procsup.c [new file with mode: 0644]
ntoskrnl/ntos.cmake

index d2cb012..6f9d6f5 100644 (file)
@@ -1205,6 +1205,13 @@ MmDeleteVirtualMapping(
     PPFN_NUMBER Page
 );
 
+/* arch/procsup.c ************************************************************/
+
+BOOLEAN
+MiArchCreateProcessAddressSpace(
+    _In_ PEPROCESS Process,
+    _In_ PULONG_PTR DirectoryTableBase);
+
 /* wset.c ********************************************************************/
 
 NTSTATUS
index eb8e681..23981bc 100644 (file)
@@ -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);
     }
 
-    /* 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[0] = TableBaseIndex << 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;
+    /* 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;
+    }
 
-    /* Let go of the system PTE */
-    MiReleaseSystemPtes(PointerPte, 1, SystemPteSpace);
+    /* Switch to phase 1 initialization */
+    ASSERT(Process->AddressSpaceInitialized == 0);
+    Process->AddressSpaceInitialized = 1;
 
     /* Add the process to the session */
     MiSessionAddProcess(Process);
     return TRUE;
 }
-#endif
 
 VOID
 NTAPI
index 90a5d74..3a3c3e4 100644 (file)
@@ -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 (file)
index 0000000..4cde151
--- /dev/null
@@ -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 <ntoskrnl.h>
+#define NDEBUG
+#include <debug.h>
+
+#define MODULE_INVOLVED_IN_ARM3
+#include <mm/ARM3/miarm.h>
+
+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 (file)
index 0000000..8ffaec1
--- /dev/null
@@ -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 <ntoskrnl.h>
+#define NDEBUG
+#include <debug.h>
+
+#define MODULE_INVOLVED_IN_ARM3
+#include <mm/ARM3/miarm.h>
+
+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;
+}
index 2a09833..d3349f9 100644 (file)
@@ -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)