xref: /reactos/ntoskrnl/mm/i386/procsup.c (revision 09dde2cf)
1 /*
2  * PROJECT:         ReactOS Kernel
3  * LICENSE:         BSD-3-Clause (https://spdx.org/licenses/BSD-3-Clause)
4  * FILE:            ntoskrnl/mm/i386/procsup.c
5  * PURPOSE:         Process handling for i386 architecture
6  * PROGRAMMERS:     Jérôme Gardou
7  */
8 
9 /* INCLUDES *******************************************************************/
10 
11 #include <ntoskrnl.h>
12 #define NDEBUG
13 #include <debug.h>
14 
15 #define MODULE_INVOLVED_IN_ARM3
16 #include <mm/ARM3/miarm.h>
17 
18 BOOLEAN
19 MiArchCreateProcessAddressSpace(
20     _In_ PEPROCESS Process,
21     _In_ PULONG_PTR DirectoryTableBase)
22 {
23     PFN_NUMBER PdeIndex = DirectoryTableBase[0] >> PAGE_SHIFT;
24     PFN_NUMBER HyperIndex = DirectoryTableBase[1] >> PAGE_SHIFT;
25     PMMPTE PointerPte;
26     MMPTE PdePte, TempPte;
27     PMMPTE PteTable;
28     ULONG PdeOffset;
29     KIRQL OldIrql;
30 
31     /* Get a PTE  */
32     PointerPte = MiReserveSystemPtes(1, SystemPteSpace);
33     if (!PointerPte)
34         return FALSE;
35     PteTable = MiPteToAddress(PointerPte);
36 
37     /* Build a page table for hyper space */
38     MI_MAKE_HARDWARE_PTE_KERNEL(&PdePte,
39                                 PointerPte,
40                                 MM_READWRITE,
41                                 HyperIndex);
42 
43     /* Set it dirty and map it */
44     MI_MAKE_DIRTY_PAGE(&PdePte);
45     MI_WRITE_VALID_PTE(PointerPte, PdePte);
46 
47     /* Now write the PTE/PDE entry for the working set list index itself */
48     TempPte = ValidKernelPteLocal;
49     TempPte.u.Hard.PageFrameNumber = Process->WorkingSetPage;
50     PdeOffset = MiAddressToPteOffset(MmWorkingSetList);
51     PteTable[PdeOffset] = TempPte;
52 
53     /* Now we map the page directory */
54     MI_MAKE_HARDWARE_PTE_KERNEL(&PdePte,
55                                 PointerPte,
56                                 MM_READWRITE,
57                                 PdeIndex);
58 
59     /* Set it dirty and map it */
60     MI_MAKE_DIRTY_PAGE(&PdePte);
61     *PointerPte = PdePte;
62     /* We changed the page! */
63     __invlpg(PteTable);
64 
65     /* Now get the page directory (which we'll double map, so call it a page table) */
66     PteTable = MiPteToAddress(PointerPte);
67 
68     /* Copy all the kernel mappings */
69     PdeOffset = MiGetPdeOffset(MmSystemRangeStart);
70     RtlCopyMemory(&PteTable[PdeOffset],
71                   MiAddressToPde(MmSystemRangeStart),
72                   PAGE_SIZE - PdeOffset * sizeof(MMPTE));
73 
74     /* Now write the PTE/PDE entry for hyperspace itself */
75     TempPte = ValidKernelPteLocal;
76     TempPte.u.Hard.PageFrameNumber = HyperIndex;
77     PdeOffset = MiGetPdeOffset(HYPER_SPACE);
78     PteTable[PdeOffset] = TempPte;
79 
80     /* Sanity check */
81     PdeOffset++;
82     ASSERT(MiGetPdeOffset(MmHyperSpaceEnd) >= PdeOffset);
83 
84     /* Now do the x86 trick of making the PDE a page table itself */
85     PdeOffset = MiGetPdeOffset(PTE_BASE);
86     TempPte.u.Hard.PageFrameNumber = PdeIndex;
87     PteTable[PdeOffset] = TempPte;
88 
89     /* Let go of the system PTE */
90     MiReleaseSystemPtes(PointerPte, 1, SystemPteSpace);
91 
92     /* Insert us into the Mm process list */
93     OldIrql = MiAcquireExpansionLock();
94     InsertTailList(&MmProcessList, &Process->MmProcessLinks);
95     MiReleaseExpansionLock(OldIrql);
96 
97     return TRUE;
98 }
99