https://git.reactos.org/?p=reactos.git;a=commitdiff;h=7ea8312617df0219277b7…
commit 7ea8312617df0219277b73e84d4452cb2f9f3caf
Author: Jérôme Gardou <jerome.gardou(a)reactos.org>
AuthorDate: Thu Apr 1 15:54:19 2021 +0200
Commit: Jérôme Gardou <zefklop(a)users.noreply.github.com>
CommitDate: Thu Apr 8 15:40:37 2021 +0200
[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 | 141 ++++++++++++-----------------------------
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, 279 insertions(+), 232 deletions(-)
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);
}
- /* 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
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(a)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
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 <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;
+}
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)