xref: /reactos/ntoskrnl/mm/mminit.c (revision 9cfd8dd9)
1 /*
2  * PROJECT:         ReactOS Kernel
3  * LICENSE:         GPL - See COPYING in the top level directory
4  * FILE:            ntoskrnl/mm/mminit.c
5  * PURPOSE:         Memory Manager Initialization
6  * PROGRAMMERS:
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 "ARM3/miarm.h"
17 
18 /* GLOBALS *******************************************************************/
19 
20 BOOLEAN Mm64BitPhysicalAddress = FALSE;
21 ULONG MmReadClusterSize;
22 //
23 // 0 | 1 is on/off paging, 2 is undocumented
24 //
25 UCHAR MmDisablePagingExecutive = 1; // Forced to off
26 PMMPTE MmSharedUserDataPte;
27 PMMSUPPORT MmKernelAddressSpace;
28 
29 extern KEVENT MmWaitPageEvent;
30 extern FAST_MUTEX MiGlobalPageOperation;
31 extern LIST_ENTRY MiSegmentList;
32 extern NTSTATUS MiRosTrimCache(ULONG Target, ULONG Priority, PULONG NrFreed);
33 
34 /* PRIVATE FUNCTIONS *********************************************************/
35 
36 //
37 // Helper function to create initial memory areas.
38 // The created area is always read/write.
39 //
40 CODE_SEG("INIT")
41 VOID
42 NTAPI
43 MiCreateArm3StaticMemoryArea(PVOID BaseAddress, SIZE_T Size, BOOLEAN Executable)
44 {
45     const ULONG Protection = Executable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE;
46     PVOID pBaseAddress = BaseAddress;
47     PMEMORY_AREA MArea;
48     NTSTATUS Status;
49 
50     Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
51                                 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
52                                 &pBaseAddress,
53                                 Size,
54                                 Protection,
55                                 &MArea,
56                                 0,
57                                 PAGE_SIZE);
58     ASSERT(Status == STATUS_SUCCESS);
59     // TODO: Perhaps it would be  prudent to bugcheck here, not only assert?
60 }
61 
62 CODE_SEG("INIT")
63 VOID
64 NTAPI
65 MiInitSystemMemoryAreas(VOID)
66 {
67     //
68     // Create all the static memory areas.
69     //
70 
71     MmLockAddressSpace(MmGetKernelAddressSpace());
72 
73 #ifdef _M_AMD64
74     // Reserved range FFFF800000000000 - FFFFF68000000000
75     MiCreateArm3StaticMemoryArea((PVOID)MI_REAL_SYSTEM_RANGE_START, PTE_BASE - MI_REAL_SYSTEM_RANGE_START, FALSE);
76 #endif /* _M_AMD64 */
77 
78     // The loader mappings. The only Executable area.
79     MiCreateArm3StaticMemoryArea((PVOID)KSEG0_BASE, MmBootImageSize, TRUE);
80 
81     // The PTE base
82     MiCreateArm3StaticMemoryArea((PVOID)PTE_BASE, PTE_TOP - PTE_BASE + 1, FALSE);
83 
84     // Hyperspace
85     MiCreateArm3StaticMemoryArea((PVOID)HYPER_SPACE, HYPER_SPACE_END - HYPER_SPACE + 1, FALSE);
86 
87     // Protect the PFN database
88     MiCreateArm3StaticMemoryArea(MmPfnDatabase, (MxPfnAllocation << PAGE_SHIFT), FALSE);
89 
90     // ReactOS requires a memory area to keep the initial NP area off-bounds
91     MiCreateArm3StaticMemoryArea(MmNonPagedPoolStart, MmSizeOfNonPagedPoolInBytes, FALSE);
92 
93     // System PTE space
94     MiCreateArm3StaticMemoryArea(MmNonPagedSystemStart, (MmNumberOfSystemPtes + 1) * PAGE_SIZE, FALSE);
95 
96     // Nonpaged pool expansion space
97     MiCreateArm3StaticMemoryArea(MmNonPagedPoolExpansionStart, (ULONG_PTR)MmNonPagedPoolEnd - (ULONG_PTR)MmNonPagedPoolExpansionStart, FALSE);
98 
99     // System view space
100     MiCreateArm3StaticMemoryArea(MiSystemViewStart, MmSystemViewSize, FALSE);
101 
102     // Session space
103     MiCreateArm3StaticMemoryArea(MmSessionBase, (ULONG_PTR)MiSessionSpaceEnd - (ULONG_PTR)MmSessionBase, FALSE);
104 
105     // Paged pool
106     MiCreateArm3StaticMemoryArea(MmPagedPoolStart, MmSizeOfPagedPoolInBytes, FALSE);
107 
108     // Debugger mapping
109     MiCreateArm3StaticMemoryArea(MI_DEBUG_MAPPING, PAGE_SIZE, FALSE);
110 
111 #if defined(_X86_)
112     // Reserved HAL area (includes KUSER_SHARED_DATA and KPCR)
113     MiCreateArm3StaticMemoryArea((PVOID)MM_HAL_VA_START, MM_HAL_VA_END - MM_HAL_VA_START + 1, FALSE);
114 #else /* _X86_ */
115 #ifndef _M_AMD64
116     // KPCR, one page per CPU. Only for 32-bit kernel.
117     MiCreateArm3StaticMemoryArea(PCR, PAGE_SIZE * KeNumberProcessors, FALSE);
118 #endif /* _M_AMD64 */
119 
120     // KUSER_SHARED_DATA
121     MiCreateArm3StaticMemoryArea((PVOID)KI_USER_SHARED_DATA, PAGE_SIZE, FALSE);
122 #endif /* _X86_ */
123 
124     MmUnlockAddressSpace(MmGetKernelAddressSpace());
125 }
126 
127 CODE_SEG("INIT")
128 VOID
129 NTAPI
130 MiDbgDumpAddressSpace(VOID)
131 {
132     //
133     // Print the memory layout
134     //
135     DPRINT1("          0x%p - 0x%p\t%s\n",
136             KSEG0_BASE,
137             (ULONG_PTR)KSEG0_BASE + MmBootImageSize,
138             "Boot Loaded Image");
139     DPRINT1("          0x%p - 0x%p\t%s\n",
140             MmPfnDatabase,
141             (ULONG_PTR)MmPfnDatabase + (MxPfnAllocation << PAGE_SHIFT),
142             "PFN Database");
143     DPRINT1("          0x%p - 0x%p\t%s\n",
144             MmNonPagedPoolStart,
145             (ULONG_PTR)MmNonPagedPoolStart + MmSizeOfNonPagedPoolInBytes,
146             "ARM3 Non Paged Pool");
147     DPRINT1("          0x%p - 0x%p\t%s\n",
148             MiSystemViewStart,
149             (ULONG_PTR)MiSystemViewStart + MmSystemViewSize,
150             "System View Space");
151     DPRINT1("          0x%p - 0x%p\t%s\n",
152             MmSessionBase,
153             MiSessionSpaceEnd,
154             "Session Space");
155     DPRINT1("          0x%p - 0x%p\t%s\n",
156             PTE_BASE, PTE_TOP,
157             "Page Tables");
158     DPRINT1("          0x%p - 0x%p\t%s\n",
159             PDE_BASE, PDE_TOP,
160             "Page Directories");
161     DPRINT1("          0x%p - 0x%p\t%s\n",
162             HYPER_SPACE, HYPER_SPACE_END,
163             "Hyperspace");
164     DPRINT1("          0x%p - 0x%p\t%s\n",
165             MmSystemCacheStart, MmSystemCacheEnd,
166             "System Cache");
167     DPRINT1("          0x%p - 0x%p\t%s\n",
168             MmPagedPoolStart,
169             (ULONG_PTR)MmPagedPoolStart + MmSizeOfPagedPoolInBytes,
170             "ARM3 Paged Pool");
171     DPRINT1("          0x%p - 0x%p\t%s\n",
172             MmNonPagedSystemStart, MmNonPagedPoolExpansionStart,
173             "System PTE Space");
174     DPRINT1("          0x%p - 0x%p\t%s\n",
175             MmNonPagedPoolExpansionStart, MmNonPagedPoolEnd,
176             "Non Paged Pool Expansion PTE Space");
177 }
178 
179 CODE_SEG("INIT")
180 NTSTATUS
181 NTAPI
182 MmInitBsmThread(VOID)
183 {
184     NTSTATUS Status;
185     OBJECT_ATTRIBUTES ObjectAttributes;
186     HANDLE ThreadHandle;
187 
188     /* Create the thread */
189     InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL);
190     Status = PsCreateSystemThread(&ThreadHandle,
191                                   THREAD_ALL_ACCESS,
192                                   &ObjectAttributes,
193                                   NULL,
194                                   NULL,
195                                   KeBalanceSetManager,
196                                   NULL);
197 
198     /* Close the handle and return status */
199     ZwClose(ThreadHandle);
200     return Status;
201 }
202 
203 CODE_SEG("INIT")
204 BOOLEAN
205 NTAPI
206 MmInitSystem(IN ULONG Phase,
207              IN PLOADER_PARAMETER_BLOCK LoaderBlock)
208 {
209     extern MMPTE ValidKernelPte;
210     PMMPTE PointerPte;
211     MMPTE TempPte = ValidKernelPte;
212     PFN_NUMBER PageFrameNumber;
213     PLIST_ENTRY ListEntry;
214     PLDR_DATA_TABLE_ENTRY DataTableEntry;
215 
216     /* Initialize the kernel address space */
217     ASSERT(Phase == 1);
218 
219 #ifdef NEWCC
220     InitializeListHead(&MiSegmentList);
221     ExInitializeFastMutex(&MiGlobalPageOperation);
222     KeInitializeEvent(&MmWaitPageEvent, SynchronizationEvent, FALSE);
223     // Until we're fully demand paged, we can do things the old way through
224     // the balance manager
225     // CcInitView will override this...
226     MmInitializeMemoryConsumer(MC_CACHE, MiRosTrimCache);
227 #else
228     KeInitializeEvent(&MmWaitPageEvent, SynchronizationEvent, FALSE);
229 #endif
230 
231     MmKernelAddressSpace = &PsIdleProcess->Vm;
232 
233     /* Intialize system memory areas */
234     MiInitSystemMemoryAreas();
235 
236     /* Dump the address space */
237     MiDbgDumpAddressSpace();
238 
239     MmInitGlobalKernelPageDirectory();
240     MmInitializeMemoryConsumer(MC_USER, MmTrimUserMemory);
241     MmInitializeRmapList();
242     MmInitSectionImplementation();
243     MmInitPagingFile();
244 
245     //
246     // Create a PTE to double-map the shared data section. We allocate it
247     // from paged pool so that we can't fault when trying to touch the PTE
248     // itself (to map it), since paged pool addresses will already be mapped
249     // by the fault handler.
250     //
251     MmSharedUserDataPte = ExAllocatePoolWithTag(PagedPool,
252                           sizeof(MMPTE),
253                           TAG_MM);
254     if (!MmSharedUserDataPte) return FALSE;
255 
256     //
257     // Now get the PTE for shared data, and read the PFN that holds it
258     //
259     PointerPte = MiAddressToPte((PVOID)KI_USER_SHARED_DATA);
260     ASSERT(PointerPte->u.Hard.Valid == 1);
261     PageFrameNumber = PFN_FROM_PTE(PointerPte);
262 
263     /* Build the PTE and write it */
264     MI_MAKE_HARDWARE_PTE_KERNEL(&TempPte,
265                                 PointerPte,
266                                 MM_READONLY,
267                                 PageFrameNumber);
268     *MmSharedUserDataPte = TempPte;
269 
270     /* Initialize session working set support */
271     MiInitializeSessionWsSupport();
272 
273     /* Setup session IDs */
274     MiInitializeSessionIds();
275 
276     /* Setup the memory threshold events */
277     if (!MiInitializeMemoryEvents()) return FALSE;
278 
279     /*
280      * Unmap low memory
281      */
282     MiInitBalancerThread();
283 
284     /* Initialize the balance set manager */
285     MmInitBsmThread();
286 
287     /* Loop the boot loaded images (under lock) */
288     ExAcquireResourceExclusiveLite(&PsLoadedModuleResource, TRUE);
289     for (ListEntry = PsLoadedModuleList.Flink;
290          ListEntry != &PsLoadedModuleList;
291          ListEntry = ListEntry->Flink)
292     {
293         /* Get the data table entry */
294         DataTableEntry = CONTAINING_RECORD(ListEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
295 
296         /* Set up the image protection */
297         MiWriteProtectSystemImage(DataTableEntry->DllBase);
298     }
299     ExReleaseResourceLite(&PsLoadedModuleResource);
300 
301     return TRUE;
302 }
303 
304