Sync to trunk head (r47736)
[reactos.git] / ntoskrnl / mm / mminit.c
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 PCHAR
21 MemType[] =
22 {
23 "ExceptionBlock ",
24 "SystemBlock ",
25 "Free ",
26 "Bad ",
27 "LoadedProgram ",
28 "FirmwareTemporary ",
29 "FirmwarePermanent ",
30 "OsloaderHeap ",
31 "OsloaderStack ",
32 "SystemCode ",
33 "HalCode ",
34 "BootDriver ",
35 "ConsoleInDriver ",
36 "ConsoleOutDriver ",
37 "StartupDpcStack ",
38 "StartupKernelStack",
39 "StartupPanicStack ",
40 "StartupPcrPage ",
41 "StartupPdrPage ",
42 "RegistryData ",
43 "MemoryData ",
44 "NlsData ",
45 "SpecialMemory ",
46 "BBTMemory ",
47 "LoaderReserve ",
48 "LoaderXIPRom "
49 };
50
51 BOOLEAN Mm64BitPhysicalAddress = FALSE;
52 ULONG MmReadClusterSize;
53 //
54 // 0 | 1 is on/off paging, 2 is undocumented
55 //
56 UCHAR MmDisablePagingExecutive = 1; // Forced to off
57 PMMPTE MmSharedUserDataPte;
58 PMMSUPPORT MmKernelAddressSpace;
59 BOOLEAN MiDbgEnableMdDump =
60 #ifdef _ARM_
61 TRUE;
62 #else
63 FALSE;
64 #endif
65
66 /* PRIVATE FUNCTIONS *********************************************************/
67
68 VOID
69 INIT_FUNCTION
70 NTAPI
71 MiInitSystemMemoryAreas()
72 {
73 PVOID BaseAddress;
74 PHYSICAL_ADDRESS BoundaryAddressMultiple;
75 PMEMORY_AREA MArea;
76 NTSTATUS Status;
77 BoundaryAddressMultiple.QuadPart = 0;
78
79 //
80 // Create the memory area to define the PTE base
81 //
82 BaseAddress = (PVOID)PTE_BASE;
83 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
84 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
85 &BaseAddress,
86 4 * 1024 * 1024,
87 PAGE_READWRITE,
88 &MArea,
89 TRUE,
90 0,
91 BoundaryAddressMultiple);
92 ASSERT(Status == STATUS_SUCCESS);
93
94 //
95 // Create the memory area to define Hyperspace
96 //
97 BaseAddress = (PVOID)HYPER_SPACE;
98 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
99 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
100 &BaseAddress,
101 4 * 1024 * 1024,
102 PAGE_READWRITE,
103 &MArea,
104 TRUE,
105 0,
106 BoundaryAddressMultiple);
107 ASSERT(Status == STATUS_SUCCESS);
108
109 //
110 // Protect the PFN database
111 //
112 BaseAddress = MmPfnDatabase;
113 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
114 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
115 &BaseAddress,
116 (MxPfnAllocation << PAGE_SHIFT),
117 PAGE_READWRITE,
118 &MArea,
119 TRUE,
120 0,
121 BoundaryAddressMultiple);
122 ASSERT(Status == STATUS_SUCCESS);
123
124 //
125 // ReactOS requires a memory area to keep the initial NP area off-bounds
126 //
127 BaseAddress = MmNonPagedPoolStart;
128 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
129 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
130 &BaseAddress,
131 MmSizeOfNonPagedPoolInBytes,
132 PAGE_READWRITE,
133 &MArea,
134 TRUE,
135 0,
136 BoundaryAddressMultiple);
137 ASSERT(Status == STATUS_SUCCESS);
138
139 //
140 // And we need one more for the system NP
141 //
142 BaseAddress = MmNonPagedSystemStart;
143 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
144 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
145 &BaseAddress,
146 (ULONG_PTR)MmNonPagedPoolEnd -
147 (ULONG_PTR)MmNonPagedSystemStart,
148 PAGE_READWRITE,
149 &MArea,
150 TRUE,
151 0,
152 BoundaryAddressMultiple);
153 ASSERT(Status == STATUS_SUCCESS);
154
155 //
156 // We also need one for system view space
157 //
158 BaseAddress = MiSystemViewStart;
159 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
160 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
161 &BaseAddress,
162 MmSystemViewSize,
163 PAGE_READWRITE,
164 &MArea,
165 TRUE,
166 0,
167 BoundaryAddressMultiple);
168 ASSERT(Status == STATUS_SUCCESS);
169
170 //
171 // And another for session space
172 //
173 BaseAddress = MmSessionBase;
174 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
175 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
176 &BaseAddress,
177 (ULONG_PTR)MiSessionSpaceEnd -
178 (ULONG_PTR)MmSessionBase,
179 PAGE_READWRITE,
180 &MArea,
181 TRUE,
182 0,
183 BoundaryAddressMultiple);
184 ASSERT(Status == STATUS_SUCCESS);
185
186 //
187 // One more for ARM paged pool
188 //
189 BaseAddress = MmPagedPoolStart;
190 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
191 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
192 &BaseAddress,
193 MmSizeOfPagedPoolInBytes,
194 PAGE_READWRITE,
195 &MArea,
196 TRUE,
197 0,
198 BoundaryAddressMultiple);
199 ASSERT(Status == STATUS_SUCCESS);
200
201 //
202 // And now, ReactOS paged pool
203 //
204 BaseAddress = MmPagedPoolBase;
205 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
206 MEMORY_AREA_PAGED_POOL | MEMORY_AREA_STATIC,
207 &BaseAddress,
208 MmPagedPoolSize,
209 PAGE_READWRITE,
210 &MArea,
211 TRUE,
212 0,
213 BoundaryAddressMultiple);
214 ASSERT(Status == STATUS_SUCCESS);
215
216 //
217 // Next, the KPCR
218 //
219 BaseAddress = (PVOID)PCR;
220 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
221 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
222 &BaseAddress,
223 PAGE_SIZE * KeNumberProcessors,
224 PAGE_READWRITE,
225 &MArea,
226 TRUE,
227 0,
228 BoundaryAddressMultiple);
229 ASSERT(Status == STATUS_SUCCESS);
230
231 //
232 // Now the KUSER_SHARED_DATA
233 //
234 BaseAddress = (PVOID)KI_USER_SHARED_DATA;
235 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
236 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
237 &BaseAddress,
238 PAGE_SIZE,
239 PAGE_READWRITE,
240 &MArea,
241 TRUE,
242 0,
243 BoundaryAddressMultiple);
244 ASSERT(Status == STATUS_SUCCESS);
245
246 //
247 // And the debugger mapping
248 //
249 BaseAddress = MI_DEBUG_MAPPING;
250 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
251 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
252 &BaseAddress,
253 PAGE_SIZE,
254 PAGE_READWRITE,
255 &MArea,
256 TRUE,
257 0,
258 BoundaryAddressMultiple);
259 ASSERT(Status == STATUS_SUCCESS);
260
261 #if defined(_X86_)
262 //
263 // Finally, reserve the 2 pages we currently make use of for HAL mappings
264 //
265 BaseAddress = (PVOID)0xFFC00000;
266 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
267 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
268 &BaseAddress,
269 PAGE_SIZE * 2,
270 PAGE_READWRITE,
271 &MArea,
272 TRUE,
273 0,
274 BoundaryAddressMultiple);
275 ASSERT(Status == STATUS_SUCCESS);
276 #endif
277 }
278
279 VOID
280 NTAPI
281 MiDbgDumpAddressSpace(VOID)
282 {
283 //
284 // Print the memory layout
285 //
286 DPRINT1(" 0x%p - 0x%p\t%s\n",
287 MmSystemRangeStart,
288 (ULONG_PTR)MmSystemRangeStart + MmBootImageSize,
289 "Boot Loaded Image");
290 DPRINT1(" 0x%p - 0x%p\t%s\n",
291 MmPagedPoolBase,
292 (ULONG_PTR)MmPagedPoolBase + MmPagedPoolSize,
293 "Paged Pool");
294 DPRINT1(" 0x%p - 0x%p\t%s\n",
295 MmPfnDatabase,
296 (ULONG_PTR)MmPfnDatabase + (MxPfnAllocation << PAGE_SHIFT),
297 "PFN Database");
298 DPRINT1(" 0x%p - 0x%p\t%s\n",
299 MmNonPagedPoolStart,
300 (ULONG_PTR)MmNonPagedPoolStart + MmSizeOfNonPagedPoolInBytes,
301 "ARM³ Non Paged Pool");
302 DPRINT1(" 0x%p - 0x%p\t%s\n",
303 MiSystemViewStart,
304 (ULONG_PTR)MiSystemViewStart + MmSystemViewSize,
305 "System View Space");
306 DPRINT1(" 0x%p - 0x%p\t%s\n",
307 MmSessionBase,
308 MiSessionSpaceEnd,
309 "Session Space");
310 DPRINT1(" 0x%p - 0x%p\t%s\n",
311 PTE_BASE, PDE_BASE,
312 "Page Tables");
313 DPRINT1(" 0x%p - 0x%p\t%s\n",
314 PDE_BASE, HYPER_SPACE,
315 "Page Directories");
316 DPRINT1(" 0x%p - 0x%p\t%s\n",
317 HYPER_SPACE, HYPER_SPACE + (4 * 1024 * 1024),
318 "Hyperspace");
319 DPRINT1(" 0x%p - 0x%p\t%s\n",
320 MmPagedPoolStart,
321 (ULONG_PTR)MmPagedPoolStart + MmSizeOfPagedPoolInBytes,
322 "ARM³ Paged Pool");
323 DPRINT1(" 0x%p - 0x%p\t%s\n",
324 MmNonPagedSystemStart, MmNonPagedPoolExpansionStart,
325 "System PTE Space");
326 DPRINT1(" 0x%p - 0x%p\t%s\n",
327 MmNonPagedPoolExpansionStart, MmNonPagedPoolEnd,
328 "Non Paged Pool Expansion PTE Space");
329 }
330
331 VOID
332 NTAPI
333 MiDbgDumpMemoryDescriptors(VOID)
334 {
335 PLIST_ENTRY NextEntry;
336 PMEMORY_ALLOCATION_DESCRIPTOR Md;
337 ULONG TotalPages = 0;
338
339 DPRINT1("Base\t\tLength\t\tType\n");
340 for (NextEntry = KeLoaderBlock->MemoryDescriptorListHead.Flink;
341 NextEntry != &KeLoaderBlock->MemoryDescriptorListHead;
342 NextEntry = NextEntry->Flink)
343 {
344 Md = CONTAINING_RECORD(NextEntry, MEMORY_ALLOCATION_DESCRIPTOR, ListEntry);
345 DPRINT1("%08lX\t%08lX\t%s\n", Md->BasePage, Md->PageCount, MemType[Md->MemoryType]);
346 TotalPages += Md->PageCount;
347 }
348
349 DPRINT1("Total: %08lX (%d MB)\n", TotalPages, (TotalPages * PAGE_SIZE) / 1024 / 1024);
350 }
351
352 VOID NTAPI MiInitializeUserPfnBitmap(VOID);
353
354 BOOLEAN
355 NTAPI
356 MmInitSystem(IN ULONG Phase,
357 IN PLOADER_PARAMETER_BLOCK LoaderBlock)
358 {
359 extern MMPTE ValidKernelPte;
360 PMMPTE PointerPte;
361 MMPTE TempPte = ValidKernelPte;
362 PFN_NUMBER PageFrameNumber;
363
364 if (Phase == 0)
365 {
366 /* Initialize the kernel address space */
367 KeInitializeGuardedMutex(&PsGetCurrentProcess()->AddressCreationLock);
368 MmKernelAddressSpace = MmGetCurrentAddressSpace();
369 MmInitGlobalKernelPageDirectory();
370
371 /* Dump memory descriptors */
372 if (MiDbgEnableMdDump) MiDbgDumpMemoryDescriptors();
373
374 /* Initialize ARM³ in phase 0 */
375 MmArmInitSystem(0, KeLoaderBlock);
376
377 /* Put the paged pool after the loaded modules */
378 MmPagedPoolBase = (PVOID)PAGE_ROUND_UP((ULONG_PTR)MmSystemRangeStart +
379 MmBootImageSize);
380 MmPagedPoolSize = MM_PAGED_POOL_SIZE;
381
382 /* Intialize system memory areas */
383 MiInitSystemMemoryAreas();
384
385 /* Dump the address space */
386 MiDbgDumpAddressSpace();
387 }
388 else if (Phase == 1)
389 {
390 MmInitializePagedPool();
391 MiInitializeUserPfnBitmap();
392 MmInitializeMemoryConsumer(MC_USER, MmTrimUserMemory);
393 MmInitializeRmapList();
394 MmInitializePageOp();
395 MmInitSectionImplementation();
396 MmInitPagingFile();
397
398 //
399 // Create a PTE to double-map the shared data section. We allocate it
400 // from paged pool so that we can't fault when trying to touch the PTE
401 // itself (to map it), since paged pool addresses will already be mapped
402 // by the fault handler.
403 //
404 MmSharedUserDataPte = ExAllocatePoolWithTag(PagedPool,
405 sizeof(MMPTE),
406 ' mM');
407 if (!MmSharedUserDataPte) return FALSE;
408
409 //
410 // Now get the PTE for shared data, and read the PFN that holds it
411 //
412 PointerPte = MiAddressToPte(KI_USER_SHARED_DATA);
413 ASSERT(PointerPte->u.Hard.Valid == 1);
414 PageFrameNumber = PFN_FROM_PTE(PointerPte);
415
416 //
417 // Now write a copy of it
418 //
419 MI_MAKE_OWNER_PAGE(&TempPte);
420 TempPte.u.Hard.PageFrameNumber = PageFrameNumber;
421 *MmSharedUserDataPte = TempPte;
422
423 /* Setup the memory threshold events */
424 if (!MiInitializeMemoryEvents()) return FALSE;
425
426 /*
427 * Unmap low memory
428 */
429 MiInitBalancerThread();
430
431 /*
432 * Initialise the modified page writer.
433 */
434 MmInitMpwThread();
435
436 /* Initialize the balance set manager */
437 MmInitBsmThread();
438 }
439 else if (Phase == 2)
440 {
441 /* Enough fun for now */
442 extern BOOLEAN AllowPagedPool;
443 AllowPagedPool = FALSE;
444 }
445
446 return TRUE;
447 }
448