Change the copyright year as well.
[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 PBOOLEAN 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 BOOLEAN
353 NTAPI
354 MmInitSystem(IN ULONG Phase,
355 IN PLOADER_PARAMETER_BLOCK LoaderBlock)
356 {
357 extern MMPTE HyperTemplatePte;
358 PMMPTE PointerPte;
359 MMPTE TempPte = HyperTemplatePte;
360 PFN_NUMBER PageFrameNumber;
361
362 if (Phase == 0)
363 {
364 /* Initialize the kernel address space */
365 KeInitializeGuardedMutex(&PsGetCurrentProcess()->AddressCreationLock);
366 MmKernelAddressSpace = MmGetCurrentAddressSpace();
367 MmInitGlobalKernelPageDirectory();
368
369 /* Dump memory descriptors */
370 if (MiDbgEnableMdDump) MiDbgDumpMemoryDescriptors();
371
372 //
373 // Initialize ARM³ in phase 0
374 //
375 MmArmInitSystem(0, KeLoaderBlock);
376
377 /* Initialize the page list */
378 MmInitializePageList();
379
380 //
381 // Initialize ARM³ in phase 1
382 //
383 MmArmInitSystem(1, KeLoaderBlock);
384
385 #if defined(_WINKD_)
386 //
387 // Everything required for the debugger to read and write
388 // physical memory is now set up
389 //
390 MiDbgReadyForPhysical = TRUE;
391 #endif
392
393 /* Put the paged pool after the loaded modules */
394 MmPagedPoolBase = (PVOID)PAGE_ROUND_UP((ULONG_PTR)MmSystemRangeStart +
395 MmBootImageSize);
396 MmPagedPoolSize = MM_PAGED_POOL_SIZE;
397
398 /* Intialize system memory areas */
399 MiInitSystemMemoryAreas();
400
401 //
402 // STEP 1: Allocate and free a single page, repeatedly
403 // We should always get the same address back
404 //
405 if (1)
406 {
407 PULONG Test, OldTest;
408 ULONG i;
409
410 OldTest = Test = MiAllocatePoolPages(PagedPool, PAGE_SIZE);
411 ASSERT(Test);
412 for (i = 0; i < 16; i++)
413 {
414 MiFreePoolPages(Test);
415 Test = MiAllocatePoolPages(PagedPool, PAGE_SIZE);
416 ASSERT(OldTest == Test);
417 }
418 MiFreePoolPages(Test);
419 }
420
421 //
422 // STEP 2: Allocate 2048 pages without freeing them
423 // We should run out of space at 1024 pages, since we don't support
424 // expansion yet.
425 //
426 if (1)
427 {
428 PULONG Test[2048];
429 ULONG i;
430
431 for (i = 0; i < 2048; i++)
432 {
433 Test[i] = MiAllocatePoolPages(PagedPool, PAGE_SIZE);
434 if (!Test[i])
435 {
436 ASSERT(i == 1024);
437 break;
438 }
439 }
440
441 //
442 // Cleanup
443 //
444 while (--i) if (Test[i]) MiFreePoolPages(Test[i]);
445 }
446
447 //
448 // STEP 3: Allocate a page and touch it.
449 // We should get an ARM3 page fault and it should handle the fault
450 //
451 if (1)
452 {
453 PULONG Test;
454
455 Test = MiAllocatePoolPages(PagedPool, PAGE_SIZE);
456 ASSERT(*Test == 0);
457 MiFreePoolPages(Test);
458 }
459
460 /* Dump the address space */
461 MiDbgDumpAddressSpace();
462
463 /* Initialize paged pool */
464 MmInitializePagedPool();
465
466 /* Initialize working sets */
467 MmInitializeMemoryConsumer(MC_USER, MmTrimUserMemory);
468
469 /* Initialize the user mode image list */
470 InitializeListHead(&MmLoadedUserImageList);
471
472 /* Initialize the Loader Lock */
473 KeInitializeMutant(&MmSystemLoadLock, FALSE);
474
475 /* Reload boot drivers */
476 MiReloadBootLoadedDrivers(LoaderBlock);
477
478 /* Initialize the loaded module list */
479 MiInitializeLoadedModuleList(LoaderBlock);
480
481 /* Setup shared user data settings that NT does as well */
482 ASSERT(SharedUserData->NumberOfPhysicalPages == 0);
483 SharedUserData->NumberOfPhysicalPages = MmNumberOfPhysicalPages;
484 SharedUserData->LargePageMinimum = 0;
485
486 /* For now, we assume that we're always Server */
487 SharedUserData->NtProductType = NtProductServer;
488 }
489 else if (Phase == 1)
490 {
491 MmInitializeRmapList();
492 MmInitializePageOp();
493 MmInitSectionImplementation();
494 MmInitPagingFile();
495
496 //
497 // Create a PTE to double-map the shared data section. We allocate it
498 // from paged pool so that we can't fault when trying to touch the PTE
499 // itself (to map it), since paged pool addresses will already be mapped
500 // by the fault handler.
501 //
502 MmSharedUserDataPte = ExAllocatePoolWithTag(PagedPool,
503 sizeof(MMPTE),
504 ' mM');
505 if (!MmSharedUserDataPte) return FALSE;
506
507 //
508 // Now get the PTE for shared data, and read the PFN that holds it
509 //
510 PointerPte = MiAddressToPte(KI_USER_SHARED_DATA);
511 ASSERT(PointerPte->u.Hard.Valid == 1);
512 PageFrameNumber = PFN_FROM_PTE(PointerPte);
513
514 //
515 // Now write a copy of it
516 //
517 MI_MAKE_OWNER_PAGE(&TempPte);
518 TempPte.u.Hard.PageFrameNumber = PageFrameNumber;
519 *MmSharedUserDataPte = TempPte;
520
521 /*
522 * Unmap low memory
523 */
524 MiInitBalancerThread();
525
526 /*
527 * Initialise the modified page writer.
528 */
529 MmInitMpwThread();
530
531 /* Initialize the balance set manager */
532 MmInitBsmThread();
533 }
534 else if (Phase == 2)
535 {
536
537 }
538
539 return TRUE;
540 }
541