1 /*
2 * COPYRIGHT: GPL, See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/mm/amd64/procsup.c
5 * PURPOSE: Low level memory management manipulation
6 *
7 * PROGRAMMER: Timo Kreuzer (timo.kreuzer@reactos.org)
8 * ReactOS Portable Systems Group
9 */
10
11 /* INCLUDES *******************************************************************/
12
13 #include <ntoskrnl.h>
14 #define NDEBUG
15 #include <debug.h>
16
17 #define MODULE_INVOLVED_IN_ARM3
18 #include <mm/ARM3/miarm.h>
19
20 BOOLEAN
MiArchCreateProcessAddressSpace(_In_ PEPROCESS Process,_In_ PULONG_PTR DirectoryTableBase)21 MiArchCreateProcessAddressSpace(
22 _In_ PEPROCESS Process,
23 _In_ PULONG_PTR DirectoryTableBase)
24 {
25 KIRQL OldIrql;
26 PFN_NUMBER TableBasePfn, HyperPfn, HyperPdPfn, HyperPtPfn;
27 PMMPTE SystemPte;
28 MMPTE TempPte, PdePte;
29 ULONG TableIndex;
30 PMMPTE PageTablePointer;
31 ULONG PageColor;
32
33 /* Non-arch specific code-path allocated those for us */
34 TableBasePfn = DirectoryTableBase[0] >> PAGE_SHIFT;
35 HyperPfn = DirectoryTableBase[1] >> PAGE_SHIFT;
36
37 /*
38 * Lock PFN database. Try getting zero pages.
39 * If that doesn't work, we take the slow path
40 * outside of the PFN lock.
41 */
42 OldIrql = MiAcquirePfnLock();
43 PageColor = MI_GET_NEXT_PROCESS_COLOR(Process);
44 HyperPdPfn = MiRemoveZeroPageSafe(PageColor);
45 if(!HyperPdPfn)
46 {
47 HyperPdPfn = MiRemoveAnyPage(PageColor);
48 MiReleasePfnLock(OldIrql);
49 MiZeroPhysicalPage(HyperPdPfn);
50 OldIrql = MiAcquirePfnLock();
51 }
52 PageColor = MI_GET_NEXT_PROCESS_COLOR(Process);
53 HyperPtPfn = MiRemoveZeroPageSafe(PageColor);
54 if(!HyperPtPfn)
55 {
56 HyperPtPfn = MiRemoveAnyPage(PageColor);
57 MiReleasePfnLock(OldIrql);
58 MiZeroPhysicalPage(HyperPtPfn);
59 }
60 else
61 {
62 MiReleasePfnLock(OldIrql);
63 }
64
65 /* Get a PTE to map the page directory */
66 SystemPte = MiReserveSystemPtes(1, SystemPteSpace);
67 if (!SystemPte)
68 return FALSE;
69
70 /* Get its address */
71 PageTablePointer = MiPteToAddress(SystemPte);
72
73 /* Build the PTE for the page directory and map it */
74 MI_MAKE_HARDWARE_PTE_KERNEL(&PdePte, SystemPte, MM_READWRITE, TableBasePfn);
75 MI_WRITE_VALID_PTE(SystemPte, PdePte);
76
77 /* Copy the kernel mappings and zero out the rest */
78 TableIndex = PXE_PER_PAGE / 2;
79 RtlZeroMemory(PageTablePointer, TableIndex * sizeof(MMPTE));
80 RtlCopyMemory(PageTablePointer + TableIndex,
81 MiAddressToPxe(0) + TableIndex,
82 PAGE_SIZE - TableIndex * sizeof(MMPTE));
83
84 /* Sanity check */
85 ASSERT(MiAddressToPxi(MmHyperSpaceEnd) >= TableIndex);
86
87 /* Setup a PTE for the page directory mappings */
88 TempPte = ValidKernelPte;
89
90 /* Update the self mapping of the PML4 */
91 TableIndex = MiAddressToPxi((PVOID)PXE_SELFMAP);
92 TempPte.u.Hard.PageFrameNumber = TableBasePfn;
93 PageTablePointer[TableIndex] = TempPte;
94
95 /* Write the PML4 entry for hyperspace */
96 TableIndex = MiAddressToPxi((PVOID)HYPER_SPACE);
97 TempPte.u.Hard.PageFrameNumber = HyperPfn;
98 PageTablePointer[TableIndex] = TempPte;
99
100 /* Map the hyperspace PDPT to the system PTE */
101 PdePte.u.Hard.PageFrameNumber = HyperPfn;
102 *SystemPte = PdePte;
103 __invlpg(PageTablePointer);
104
105 /* Write the hyperspace entry for the first PD */
106 TempPte.u.Hard.PageFrameNumber = HyperPdPfn;
107 PageTablePointer[0] = TempPte;
108
109 /* Map the hyperspace PD to the system PTE */
110 PdePte.u.Hard.PageFrameNumber = HyperPdPfn;
111 *SystemPte = PdePte;
112 __invlpg(PageTablePointer);
113
114 /* Write the hyperspace entry for the first PT */
115 TempPte.u.Hard.PageFrameNumber = HyperPtPfn;
116 PageTablePointer[0] = TempPte;
117
118 /* Map the hyperspace PT to the system PTE */
119 PdePte.u.Hard.PageFrameNumber = HyperPtPfn;
120 *SystemPte = PdePte;
121 __invlpg(PageTablePointer);
122
123 /* Write the hyperspace PTE for the working set list index */
124 TempPte.u.Hard.PageFrameNumber = Process->WorkingSetPage;
125 TableIndex = MiAddressToPti(MmWorkingSetList);
126 PageTablePointer[TableIndex] = TempPte;
127
128 /* Release the system PTE */
129 MiReleaseSystemPtes(SystemPte, 1, SystemPteSpace);
130
131 return TRUE;
132 }
133