xref: /reactos/ntoskrnl/mm/amd64/procsup.c (revision 6db0d24f)
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