Merge from amd64-branch:
[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 /* Dump the address space */
402 MiDbgDumpAddressSpace();
403
404 /* Initialize paged pool */
405 MmInitializePagedPool();
406
407 /* Initialize working sets */
408 MmInitializeMemoryConsumer(MC_USER, MmTrimUserMemory);
409
410 /* Initialize the user mode image list */
411 InitializeListHead(&MmLoadedUserImageList);
412
413 /* Initialize the Loader Lock */
414 KeInitializeMutant(&MmSystemLoadLock, FALSE);
415
416 /* Reload boot drivers */
417 MiReloadBootLoadedDrivers(LoaderBlock);
418
419 /* Initialize the loaded module list */
420 MiInitializeLoadedModuleList(LoaderBlock);
421
422 /* Setup shared user data settings that NT does as well */
423 ASSERT(SharedUserData->NumberOfPhysicalPages == 0);
424 SharedUserData->NumberOfPhysicalPages = MmNumberOfPhysicalPages;
425 SharedUserData->LargePageMinimum = 0;
426
427 /* For now, we assume that we're always Server */
428 SharedUserData->NtProductType = NtProductServer;
429 }
430 else if (Phase == 1)
431 {
432 MmInitializeRmapList();
433 MmInitializePageOp();
434 MmInitSectionImplementation();
435 MmInitPagingFile();
436
437 //
438 // Create a PTE to double-map the shared data section. We allocate it
439 // from paged pool so that we can't fault when trying to touch the PTE
440 // itself (to map it), since paged pool addresses will already be mapped
441 // by the fault handler.
442 //
443 MmSharedUserDataPte = ExAllocatePoolWithTag(PagedPool,
444 sizeof(MMPTE),
445 ' mM');
446 if (!MmSharedUserDataPte) return FALSE;
447
448 //
449 // Now get the PTE for shared data, and read the PFN that holds it
450 //
451 PointerPte = MiAddressToPte(KI_USER_SHARED_DATA);
452 ASSERT(PointerPte->u.Hard.Valid == 1);
453 PageFrameNumber = PFN_FROM_PTE(PointerPte);
454
455 //
456 // Now write a copy of it
457 //
458 MI_MAKE_OWNER_PAGE(&TempPte);
459 TempPte.u.Hard.PageFrameNumber = PageFrameNumber;
460 *MmSharedUserDataPte = TempPte;
461
462 /*
463 * Unmap low memory
464 */
465 MiInitBalancerThread();
466
467 /*
468 * Initialise the modified page writer.
469 */
470 MmInitMpwThread();
471
472 /* Initialize the balance set manager */
473 MmInitBsmThread();
474 }
475 else if (Phase == 2)
476 {
477
478 }
479
480 return TRUE;
481 }
482