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