Merge trunk HEAD (r46369)
[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 #ifndef _M_AMD64
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 #endif
246
247 //
248 // Now the KUSER_SHARED_DATA
249 //
250 BaseAddress = (PVOID)KI_USER_SHARED_DATA;
251 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
252 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
253 &BaseAddress,
254 PAGE_SIZE,
255 PAGE_READWRITE,
256 &MArea,
257 TRUE,
258 0,
259 BoundaryAddressMultiple);
260 ASSERT(Status == STATUS_SUCCESS);
261
262 //
263 // And the debugger mapping
264 //
265 BaseAddress = MI_DEBUG_MAPPING;
266 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
267 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
268 &BaseAddress,
269 PAGE_SIZE,
270 PAGE_READWRITE,
271 &MArea,
272 TRUE,
273 0,
274 BoundaryAddressMultiple);
275 ASSERT(Status == STATUS_SUCCESS);
276
277 #if defined(_X86_)
278 //
279 // Finally, reserve the 2 pages we currently make use of for HAL mappings
280 //
281 BaseAddress = (PVOID)0xFFC00000;
282 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
283 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
284 &BaseAddress,
285 PAGE_SIZE * 2,
286 PAGE_READWRITE,
287 &MArea,
288 TRUE,
289 0,
290 BoundaryAddressMultiple);
291 ASSERT(Status == STATUS_SUCCESS);
292 #endif
293 }
294
295 VOID
296 NTAPI
297 MiDbgDumpAddressSpace(VOID)
298 {
299 //
300 // Print the memory layout
301 //
302 DPRINT1(" 0x%p - 0x%p\t%s\n",
303 KSEG0_BASE,
304 (ULONG_PTR)KSEG0_BASE + MmBootImageSize,
305 "Boot Loaded Image");
306 DPRINT1(" 0x%p - 0x%p\t%s\n",
307 MmPagedPoolBase,
308 (ULONG_PTR)MmPagedPoolBase + MmPagedPoolSize,
309 "Paged Pool");
310 DPRINT1(" 0x%p - 0x%p\t%s\n",
311 MmPfnDatabase,
312 (ULONG_PTR)MmPfnDatabase + (MxPfnAllocation << PAGE_SHIFT),
313 "PFN Database");
314 DPRINT1(" 0x%p - 0x%p\t%s\n",
315 MmNonPagedPoolStart,
316 (ULONG_PTR)MmNonPagedPoolStart + MmSizeOfNonPagedPoolInBytes,
317 "ARM³ Non Paged Pool");
318 DPRINT1(" 0x%p - 0x%p\t%s\n",
319 MiSystemViewStart,
320 (ULONG_PTR)MiSystemViewStart + MmSystemViewSize,
321 "System View Space");
322 DPRINT1(" 0x%p - 0x%p\t%s\n",
323 MmSessionBase,
324 MiSessionSpaceEnd,
325 "Session Space");
326 DPRINT1(" 0x%p - 0x%p\t%s\n",
327 PTE_BASE, PTE_TOP,
328 "Page Tables");
329 DPRINT1(" 0x%p - 0x%p\t%s\n",
330 PDE_BASE, PDE_TOP,
331 "Page Directories");
332 DPRINT1(" 0x%p - 0x%p\t%s\n",
333 HYPER_SPACE, HYPER_SPACE_END,
334 "Hyperspace");
335 DPRINT1(" 0x%p - 0x%p\t%s\n",
336 MmPagedPoolStart,
337 (ULONG_PTR)MmPagedPoolStart + MmSizeOfPagedPoolInBytes,
338 "ARM³ Paged Pool");
339 DPRINT1(" 0x%p - 0x%p\t%s\n",
340 MmNonPagedSystemStart, MmNonPagedPoolExpansionStart,
341 "System PTE Space");
342 DPRINT1(" 0x%p - 0x%p\t%s\n",
343 MmNonPagedPoolExpansionStart, MmNonPagedPoolEnd,
344 "Non Paged Pool Expansion PTE Space");
345 }
346
347 VOID
348 NTAPI
349 MiDbgDumpMemoryDescriptors(VOID)
350 {
351 PLIST_ENTRY NextEntry;
352 PMEMORY_ALLOCATION_DESCRIPTOR Md;
353 ULONG TotalPages = 0;
354
355 DPRINT1("Base\t\tLength\t\tType\n");
356 for (NextEntry = KeLoaderBlock->MemoryDescriptorListHead.Flink;
357 NextEntry != &KeLoaderBlock->MemoryDescriptorListHead;
358 NextEntry = NextEntry->Flink)
359 {
360 Md = CONTAINING_RECORD(NextEntry, MEMORY_ALLOCATION_DESCRIPTOR, ListEntry);
361 DPRINT1("%08lX\t%08lX\t%s\n", Md->BasePage, Md->PageCount, MemType[Md->MemoryType]);
362 TotalPages += Md->PageCount;
363 }
364
365 DPRINT1("Total: %08lX (%d MB)\n", TotalPages, (TotalPages * PAGE_SIZE) / 1024 / 1024);
366 }
367
368 BOOLEAN
369 NTAPI
370 MmInitSystem(IN ULONG Phase,
371 IN PLOADER_PARAMETER_BLOCK LoaderBlock)
372 {
373 extern MMPTE HyperTemplatePte;
374 PMMPTE PointerPte;
375 MMPTE TempPte = HyperTemplatePte;
376 PFN_NUMBER PageFrameNumber;
377
378 if (Phase == 0)
379 {
380 /* Initialize the kernel address space */
381 KeInitializeGuardedMutex(&PsGetCurrentProcess()->AddressCreationLock);
382 MmKernelAddressSpace = MmGetCurrentAddressSpace();
383 MmInitGlobalKernelPageDirectory();
384
385 /* Dump memory descriptors */
386 if (MiDbgEnableMdDump) MiDbgDumpMemoryDescriptors();
387
388 //
389 // Initialize ARM³ in phase 0
390 //
391 MmArmInitSystem(0, KeLoaderBlock);
392
393 /* Initialize the page list */
394 MmInitializePageList();
395
396 //
397 // Initialize ARM³ in phase 1
398 //
399 MmArmInitSystem(1, KeLoaderBlock);
400
401 #if defined(_WINKD_)
402 //
403 // Everything required for the debugger to read and write
404 // physical memory is now set up
405 //
406 MmDebugPte = MiAddressToPte(MiDebugMapping);
407 #endif
408
409 /* Put the paged pool after the loaded modules */
410 MmPagedPoolBase = (PVOID)PAGE_ROUND_UP((ULONG_PTR)MmSystemRangeStart +
411 MmBootImageSize);
412 MmPagedPoolSize = MM_PAGED_POOL_SIZE;
413
414 /* Intialize system memory areas */
415 MiInitSystemMemoryAreas();
416
417 /* Dump the address space */
418 MiDbgDumpAddressSpace();
419
420 #ifndef _M_AMD64 // skip old paged pool
421 /* Initialize paged pool */
422 MmInitializePagedPool();
423 #endif
424
425 /* Initialize working sets */
426 MmInitializeMemoryConsumer(MC_USER, MmTrimUserMemory);
427
428 /* Initialize the user mode image list */
429 InitializeListHead(&MmLoadedUserImageList);
430
431 /* Initialize the Loader Lock */
432 KeInitializeMutant(&MmSystemLoadLock, FALSE);
433
434 /* Reload boot drivers */
435 MiReloadBootLoadedDrivers(LoaderBlock);
436
437 /* Initialize the loaded module list */
438 MiInitializeLoadedModuleList(LoaderBlock);
439
440 /* Setup shared user data settings that NT does as well */
441 ASSERT(SharedUserData->NumberOfPhysicalPages == 0);
442 SharedUserData->NumberOfPhysicalPages = MmNumberOfPhysicalPages;
443 SharedUserData->LargePageMinimum = 0;
444
445 /* For now, we assume that we're always Server */
446 SharedUserData->NtProductType = NtProductServer;
447 }
448 else if (Phase == 1)
449 {
450 MmInitializeRmapList();
451 MmInitializePageOp();
452 MmInitSectionImplementation();
453 MmInitPagingFile();
454
455 //
456 // Create a PTE to double-map the shared data section. We allocate it
457 // from paged pool so that we can't fault when trying to touch the PTE
458 // itself (to map it), since paged pool addresses will already be mapped
459 // by the fault handler.
460 //
461 MmSharedUserDataPte = ExAllocatePoolWithTag(PagedPool,
462 sizeof(MMPTE),
463 ' mM');
464 if (!MmSharedUserDataPte) return FALSE;
465
466 //
467 // Now get the PTE for shared data, and read the PFN that holds it
468 //
469 PointerPte = MiAddressToPte((PVOID)KI_USER_SHARED_DATA);
470 ASSERT(PointerPte->u.Hard.Valid == 1);
471 PageFrameNumber = PFN_FROM_PTE(PointerPte);
472
473 //
474 // Now write a copy of it
475 //
476 MI_MAKE_OWNER_PAGE(&TempPte);
477 TempPte.u.Hard.PageFrameNumber = PageFrameNumber;
478 *MmSharedUserDataPte = TempPte;
479
480 /*
481 * Unmap low memory
482 */
483 MiInitBalancerThread();
484
485 /*
486 * Initialise the modified page writer.
487 */
488 MmInitMpwThread();
489
490 /* Initialize the balance set manager */
491 MmInitBsmThread();
492 }
493 else if (Phase == 2)
494 {
495
496 }
497
498 return TRUE;
499 }
500