b1d392d22de996706c14182a31cabbb164b6b421
[reactos.git] / reactos / 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 loader mappings
81 //
82 BaseAddress = (PVOID)KSEG0_BASE;
83 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
84 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
85 &BaseAddress,
86 MmBootImageSize,
87 PAGE_EXECUTE_READWRITE,
88 &MArea,
89 TRUE,
90 0,
91 BoundaryAddressMultiple);
92 ASSERT(Status == STATUS_SUCCESS);
93
94 //
95 // Create the memory area to define the PTE base
96 //
97 BaseAddress = (PVOID)PTE_BASE;
98 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
99 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
100 &BaseAddress,
101 PTE_TOP - PTE_BASE + 1,
102 PAGE_READWRITE,
103 &MArea,
104 TRUE,
105 0,
106 BoundaryAddressMultiple);
107 ASSERT(Status == STATUS_SUCCESS);
108
109 //
110 // Create the memory area to define Hyperspace
111 //
112 BaseAddress = (PVOID)HYPER_SPACE;
113 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
114 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
115 &BaseAddress,
116 HYPER_SPACE_END - HYPER_SPACE + 1,
117 PAGE_READWRITE,
118 &MArea,
119 TRUE,
120 0,
121 BoundaryAddressMultiple);
122 ASSERT(Status == STATUS_SUCCESS);
123
124 //
125 // Protect the PFN database
126 //
127 BaseAddress = MmPfnDatabase;
128 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
129 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
130 &BaseAddress,
131 (MxPfnAllocation << PAGE_SHIFT),
132 PAGE_READWRITE,
133 &MArea,
134 TRUE,
135 0,
136 BoundaryAddressMultiple);
137 ASSERT(Status == STATUS_SUCCESS);
138
139 //
140 // ReactOS requires a memory area to keep the initial NP area off-bounds
141 //
142 BaseAddress = MmNonPagedPoolStart;
143 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
144 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
145 &BaseAddress,
146 MmSizeOfNonPagedPoolInBytes,
147 PAGE_READWRITE,
148 &MArea,
149 TRUE,
150 0,
151 BoundaryAddressMultiple);
152 ASSERT(Status == STATUS_SUCCESS);
153
154 //
155 // And we need one more for the system NP
156 //
157 BaseAddress = MmNonPagedSystemStart;
158 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
159 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
160 &BaseAddress,
161 (MmNumberOfSystemPtes + 1) * PAGE_SIZE,
162 PAGE_READWRITE,
163 &MArea,
164 TRUE,
165 0,
166 BoundaryAddressMultiple);
167 ASSERT(Status == STATUS_SUCCESS);
168
169 //
170 // We also need one for system view space
171 //
172 BaseAddress = MiSystemViewStart;
173 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
174 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
175 &BaseAddress,
176 MmSystemViewSize,
177 PAGE_READWRITE,
178 &MArea,
179 TRUE,
180 0,
181 BoundaryAddressMultiple);
182 ASSERT(Status == STATUS_SUCCESS);
183
184 //
185 // And another for session space
186 //
187 BaseAddress = MmSessionBase;
188 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
189 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
190 &BaseAddress,
191 (ULONG_PTR)MiSessionSpaceEnd -
192 (ULONG_PTR)MmSessionBase,
193 PAGE_READWRITE,
194 &MArea,
195 TRUE,
196 0,
197 BoundaryAddressMultiple);
198 ASSERT(Status == STATUS_SUCCESS);
199
200 //
201 // One more for ARM paged pool
202 //
203 BaseAddress = MmPagedPoolStart;
204 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
205 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
206 &BaseAddress,
207 MmSizeOfPagedPoolInBytes,
208 PAGE_READWRITE,
209 &MArea,
210 TRUE,
211 0,
212 BoundaryAddressMultiple);
213 ASSERT(Status == STATUS_SUCCESS);
214
215 //
216 // And now, ReactOS paged pool
217 //
218 BaseAddress = MmPagedPoolBase;
219 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
220 MEMORY_AREA_PAGED_POOL | MEMORY_AREA_STATIC,
221 &BaseAddress,
222 MmPagedPoolSize,
223 PAGE_READWRITE,
224 &MArea,
225 TRUE,
226 0,
227 BoundaryAddressMultiple);
228 ASSERT(Status == STATUS_SUCCESS);
229
230 //
231 // Next, the KPCR
232 //
233 BaseAddress = (PVOID)PCR;
234 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
235 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
236 &BaseAddress,
237 PAGE_SIZE * KeNumberProcessors,
238 PAGE_READWRITE,
239 &MArea,
240 TRUE,
241 0,
242 BoundaryAddressMultiple);
243 ASSERT(Status == STATUS_SUCCESS);
244
245 //
246 // Now the KUSER_SHARED_DATA
247 //
248 BaseAddress = (PVOID)KI_USER_SHARED_DATA;
249 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
250 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
251 &BaseAddress,
252 PAGE_SIZE,
253 PAGE_READWRITE,
254 &MArea,
255 TRUE,
256 0,
257 BoundaryAddressMultiple);
258 ASSERT(Status == STATUS_SUCCESS);
259
260 //
261 // And the debugger mapping
262 //
263 BaseAddress = MI_DEBUG_MAPPING;
264 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
265 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
266 &BaseAddress,
267 PAGE_SIZE,
268 PAGE_READWRITE,
269 &MArea,
270 TRUE,
271 0,
272 BoundaryAddressMultiple);
273 ASSERT(Status == STATUS_SUCCESS);
274
275 #if defined(_X86_)
276 //
277 // Finally, reserve the 2 pages we currently make use of for HAL mappings
278 //
279 BaseAddress = (PVOID)0xFFC00000;
280 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
281 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
282 &BaseAddress,
283 PAGE_SIZE * 2,
284 PAGE_READWRITE,
285 &MArea,
286 TRUE,
287 0,
288 BoundaryAddressMultiple);
289 ASSERT(Status == STATUS_SUCCESS);
290 #endif
291 }
292
293 VOID
294 NTAPI
295 MiDbgDumpAddressSpace(VOID)
296 {
297 //
298 // Print the memory layout
299 //
300 DPRINT1(" 0x%p - 0x%p\t%s\n",
301 KSEG0_BASE,
302 (ULONG_PTR)KSEG0_BASE + MmBootImageSize,
303 "Boot Loaded Image");
304 DPRINT1(" 0x%p - 0x%p\t%s\n",
305 MmPagedPoolBase,
306 (ULONG_PTR)MmPagedPoolBase + MmPagedPoolSize,
307 "Paged Pool");
308 DPRINT1(" 0x%p - 0x%p\t%s\n",
309 MmPfnDatabase,
310 (ULONG_PTR)MmPfnDatabase + (MxPfnAllocation << PAGE_SHIFT),
311 "PFN Database");
312 DPRINT1(" 0x%p - 0x%p\t%s\n",
313 MmNonPagedPoolStart,
314 (ULONG_PTR)MmNonPagedPoolStart + MmSizeOfNonPagedPoolInBytes,
315 "ARM³ Non Paged Pool");
316 DPRINT1(" 0x%p - 0x%p\t%s\n",
317 MiSystemViewStart,
318 (ULONG_PTR)MiSystemViewStart + MmSystemViewSize,
319 "System View Space");
320 DPRINT1(" 0x%p - 0x%p\t%s\n",
321 MmSessionBase,
322 MiSessionSpaceEnd,
323 "Session Space");
324 DPRINT1(" 0x%p - 0x%p\t%s\n",
325 PTE_BASE, PTE_TOP,
326 "Page Tables");
327 DPRINT1(" 0x%p - 0x%p\t%s\n",
328 PDE_BASE, PDE_TOP,
329 "Page Directories");
330 DPRINT1(" 0x%p - 0x%p\t%s\n",
331 HYPER_SPACE, HYPER_SPACE_END,
332 "Hyperspace");
333 DPRINT1(" 0x%p - 0x%p\t%s\n",
334 MmPagedPoolStart,
335 (ULONG_PTR)MmPagedPoolStart + MmSizeOfPagedPoolInBytes,
336 "ARM³ Paged Pool");
337 DPRINT1(" 0x%p - 0x%p\t%s\n",
338 MmNonPagedSystemStart, MmNonPagedPoolExpansionStart,
339 "System PTE Space");
340 DPRINT1(" 0x%p - 0x%p\t%s\n",
341 MmNonPagedPoolExpansionStart, MmNonPagedPoolEnd,
342 "Non Paged Pool Expansion PTE Space");
343 }
344
345 VOID
346 NTAPI
347 MiDbgDumpMemoryDescriptors(VOID)
348 {
349 PLIST_ENTRY NextEntry;
350 PMEMORY_ALLOCATION_DESCRIPTOR Md;
351 ULONG TotalPages = 0;
352
353 DPRINT1("Base\t\tLength\t\tType\n");
354 for (NextEntry = KeLoaderBlock->MemoryDescriptorListHead.Flink;
355 NextEntry != &KeLoaderBlock->MemoryDescriptorListHead;
356 NextEntry = NextEntry->Flink)
357 {
358 Md = CONTAINING_RECORD(NextEntry, MEMORY_ALLOCATION_DESCRIPTOR, ListEntry);
359 DPRINT1("%08lX\t%08lX\t%s\n", Md->BasePage, Md->PageCount, MemType[Md->MemoryType]);
360 TotalPages += Md->PageCount;
361 }
362
363 DPRINT1("Total: %08lX (%d MB)\n", TotalPages, (TotalPages * PAGE_SIZE) / 1024 / 1024);
364 }
365
366 BOOLEAN
367 NTAPI
368 MmInitSystem(IN ULONG Phase,
369 IN PLOADER_PARAMETER_BLOCK LoaderBlock)
370 {
371 extern MMPTE HyperTemplatePte;
372 PMMPTE PointerPte;
373 MMPTE TempPte = HyperTemplatePte;
374 PFN_NUMBER PageFrameNumber;
375
376 if (Phase == 0)
377 {
378 /* Initialize the kernel address space */
379 KeInitializeGuardedMutex(&PsGetCurrentProcess()->AddressCreationLock);
380 MmKernelAddressSpace = MmGetCurrentAddressSpace();
381 MmInitGlobalKernelPageDirectory();
382
383 /* Dump memory descriptors */
384 if (MiDbgEnableMdDump) MiDbgDumpMemoryDescriptors();
385
386 //
387 // Initialize ARM³ in phase 0
388 //
389 MmArmInitSystem(0, KeLoaderBlock);
390
391 /* Initialize the page list */
392 MmInitializePageList();
393
394 //
395 // Initialize ARM³ in phase 1
396 //
397 MmArmInitSystem(1, KeLoaderBlock);
398
399 #if defined(_WINKD_)
400 //
401 // Everything required for the debugger to read and write
402 // physical memory is now set up
403 //
404 MmDebugPte = MiAddressToPte(MiDebugMapping);
405 #endif
406
407 /* Put the paged pool after the loaded modules */
408 MmPagedPoolBase = (PVOID)PAGE_ROUND_UP((ULONG_PTR)MmSystemRangeStart +
409 MmBootImageSize);
410 MmPagedPoolSize = MM_PAGED_POOL_SIZE;
411
412 /* Intialize system memory areas */
413 MiInitSystemMemoryAreas();
414
415 //
416 // STEP 1: Allocate and free a single page, repeatedly
417 // We should always get the same address back
418 //
419 if (1)
420 {
421 PULONG Test, OldTest;
422 ULONG i;
423
424 OldTest = Test = MiAllocatePoolPages(PagedPool, PAGE_SIZE);
425 ASSERT(Test);
426 for (i = 0; i < 16; i++)
427 {
428 MiFreePoolPages(Test);
429 Test = MiAllocatePoolPages(PagedPool, PAGE_SIZE);
430 ASSERT(OldTest == Test);
431 }
432 MiFreePoolPages(Test);
433 }
434
435 //
436 // STEP 2: Allocate 2048 pages without freeing them
437 // We should run out of space at 1024 pages, since we don't support
438 // expansion yet.
439 //
440 if (1)
441 {
442 PULONG Test[2048];
443 ULONG i;
444
445 for (i = 0; i < 2048; i++)
446 {
447 Test[i] = MiAllocatePoolPages(PagedPool, PAGE_SIZE);
448 if (!Test[i])
449 {
450 ASSERT(i == PTE_PER_PAGE);
451 break;
452 }
453 }
454
455 //
456 // Cleanup
457 //
458 while (--i) if (Test[i]) MiFreePoolPages(Test[i]);
459 }
460
461 //
462 // STEP 3: Allocate a page and touch it.
463 // We should get an ARM3 page fault and it should handle the fault
464 //
465 if (1)
466 {
467 PULONG Test;
468
469 Test = MiAllocatePoolPages(PagedPool, PAGE_SIZE);
470 ASSERT(*Test == 0);
471 MiFreePoolPages(Test);
472 }
473
474 /* Dump the address space */
475 MiDbgDumpAddressSpace();
476
477 /* Initialize paged pool */
478 MmInitializePagedPool();
479
480 /* Initialize working sets */
481 MmInitializeMemoryConsumer(MC_USER, MmTrimUserMemory);
482
483 /* Initialize the user mode image list */
484 InitializeListHead(&MmLoadedUserImageList);
485
486 /* Initialize the Loader Lock */
487 KeInitializeMutant(&MmSystemLoadLock, FALSE);
488
489 /* Reload boot drivers */
490 MiReloadBootLoadedDrivers(LoaderBlock);
491
492 /* Initialize the loaded module list */
493 MiInitializeLoadedModuleList(LoaderBlock);
494
495 /* Setup shared user data settings that NT does as well */
496 ASSERT(SharedUserData->NumberOfPhysicalPages == 0);
497 SharedUserData->NumberOfPhysicalPages = MmNumberOfPhysicalPages;
498 SharedUserData->LargePageMinimum = 0;
499
500 /* For now, we assume that we're always Server */
501 SharedUserData->NtProductType = NtProductServer;
502 }
503 else if (Phase == 1)
504 {
505 MmInitializeRmapList();
506 MmInitializePageOp();
507 MmInitSectionImplementation();
508 MmInitPagingFile();
509
510 //
511 // Create a PTE to double-map the shared data section. We allocate it
512 // from paged pool so that we can't fault when trying to touch the PTE
513 // itself (to map it), since paged pool addresses will already be mapped
514 // by the fault handler.
515 //
516 MmSharedUserDataPte = ExAllocatePoolWithTag(PagedPool,
517 sizeof(MMPTE),
518 ' mM');
519 if (!MmSharedUserDataPte) return FALSE;
520
521 //
522 // Now get the PTE for shared data, and read the PFN that holds it
523 //
524 PointerPte = MiAddressToPte((PVOID)KI_USER_SHARED_DATA);
525 ASSERT(PointerPte->u.Hard.Valid == 1);
526 PageFrameNumber = PFN_FROM_PTE(PointerPte);
527
528 //
529 // Now write a copy of it
530 //
531 MI_MAKE_OWNER_PAGE(&TempPte);
532 TempPte.u.Hard.PageFrameNumber = PageFrameNumber;
533 *MmSharedUserDataPte = TempPte;
534
535 /*
536 * Unmap low memory
537 */
538 MiInitBalancerThread();
539
540 /*
541 * Initialise the modified page writer.
542 */
543 MmInitMpwThread();
544
545 /* Initialize the balance set manager */
546 MmInitBsmThread();
547 }
548 else if (Phase == 2)
549 {
550
551 }
552
553 return TRUE;
554 }
555