Sync with trunk r47129
[reactos.git] / 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 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[0];
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[0],
296 (ULONG_PTR)MmPfnDatabase[0] + (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 VOID NTAPI MiInitializeUserPfnBitmap(VOID);
353
354 BOOLEAN
355 NTAPI
356 MmInitSystem(IN ULONG Phase,
357 IN PLOADER_PARAMETER_BLOCK LoaderBlock)
358 {
359 extern MMPTE ValidKernelPte;
360 PMMPTE PointerPte;
361 MMPTE TempPte = ValidKernelPte;
362 PFN_NUMBER PageFrameNumber;
363
364 if (Phase == 0)
365 {
366 /* Initialize the kernel address space */
367 KeInitializeGuardedMutex(&PsGetCurrentProcess()->AddressCreationLock);
368 MmKernelAddressSpace = MmGetCurrentAddressSpace();
369 MmInitGlobalKernelPageDirectory();
370
371 /* Dump memory descriptors */
372 if (MiDbgEnableMdDump) MiDbgDumpMemoryDescriptors();
373
374 //
375 // Initialize ARM³ in phase 0
376 //
377 MmArmInitSystem(0, KeLoaderBlock);
378
379 #if defined(_WINKD_)
380 //
381 // Everything required for the debugger to read and write
382 // physical memory is now set up
383 //
384 MiDbgReadyForPhysical = TRUE;
385 #endif
386
387 /* Put the paged pool after the loaded modules */
388 MmPagedPoolBase = (PVOID)PAGE_ROUND_UP((ULONG_PTR)MmSystemRangeStart +
389 MmBootImageSize);
390 MmPagedPoolSize = MM_PAGED_POOL_SIZE;
391
392 /* Intialize system memory areas */
393 MiInitSystemMemoryAreas();
394
395 /* Dump the address space */
396 MiDbgDumpAddressSpace();
397
398 /* Initialize paged pool */
399 MmInitializePagedPool();
400
401 /* Initialize the loaded module list */
402 MiInitializeLoadedModuleList(LoaderBlock);
403
404 /* Initialize working sets */
405 MiInitializeUserPfnBitmap();
406 MmInitializeMemoryConsumer(MC_USER, MmTrimUserMemory);
407 }
408 else if (Phase == 1)
409 {
410 MmInitializeRmapList();
411 MmInitializePageOp();
412 MmInitSectionImplementation();
413 MmInitPagingFile();
414
415 //
416 // Create a PTE to double-map the shared data section. We allocate it
417 // from paged pool so that we can't fault when trying to touch the PTE
418 // itself (to map it), since paged pool addresses will already be mapped
419 // by the fault handler.
420 //
421 MmSharedUserDataPte = ExAllocatePoolWithTag(PagedPool,
422 sizeof(MMPTE),
423 ' mM');
424 if (!MmSharedUserDataPte) return FALSE;
425
426 //
427 // Now get the PTE for shared data, and read the PFN that holds it
428 //
429 PointerPte = MiAddressToPte(KI_USER_SHARED_DATA);
430 ASSERT(PointerPte->u.Hard.Valid == 1);
431 PageFrameNumber = PFN_FROM_PTE(PointerPte);
432
433 //
434 // Now write a copy of it
435 //
436 MI_MAKE_OWNER_PAGE(&TempPte);
437 TempPte.u.Hard.PageFrameNumber = PageFrameNumber;
438 *MmSharedUserDataPte = TempPte;
439
440 /* Setup the memory threshold events */
441 if (!MiInitializeMemoryEvents()) return FALSE;
442
443 /*
444 * Unmap low memory
445 */
446 MiInitBalancerThread();
447
448 /*
449 * Initialise the modified page writer.
450 */
451 MmInitMpwThread();
452
453 /* Initialize the balance set manager */
454 MmInitBsmThread();
455 }
456 else if (Phase == 2)
457 {
458
459 }
460
461 return TRUE;
462 }
463