- Fix a bug in memory area creation: Static memory areas had the static flag embedded...
[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 MM_STATS MmStats;
54 PMMPTE MmSharedUserDataPte;
55 PMMSUPPORT MmKernelAddressSpace;
56 extern KMUTANT MmSystemLoadLock;
57 extern ULONG MmBootImageSize;
58 BOOLEAN MiDbgEnableMdDump =
59 #ifdef _ARM_
60 TRUE;
61 #else
62 FALSE;
63 #endif
64
65 /* PRIVATE FUNCTIONS *********************************************************/
66
67 VOID
68 INIT_FUNCTION
69 NTAPI
70 MiInitSystemMemoryAreas()
71 {
72 PVOID BaseAddress;
73 PHYSICAL_ADDRESS BoundaryAddressMultiple;
74 PMEMORY_AREA MArea;
75 NTSTATUS Status;
76 BoundaryAddressMultiple.QuadPart = 0;
77
78 //
79 // Create the memory area to define the PTE base
80 //
81 BaseAddress = (PVOID)PTE_BASE;
82 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
83 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
84 &BaseAddress,
85 4 * 1024 * 1024,
86 PAGE_READWRITE,
87 &MArea,
88 TRUE,
89 0,
90 BoundaryAddressMultiple);
91 ASSERT(Status == STATUS_SUCCESS);
92
93 //
94 // Create the memory area to define Hyperspace
95 //
96 BaseAddress = (PVOID)HYPER_SPACE;
97 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
98 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
99 &BaseAddress,
100 4 * 1024 * 1024,
101 PAGE_READWRITE,
102 &MArea,
103 TRUE,
104 0,
105 BoundaryAddressMultiple);
106 ASSERT(Status == STATUS_SUCCESS);
107
108 //
109 // Protect the PFN database
110 //
111 BaseAddress = MmPfnDatabase;
112 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
113 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
114 &BaseAddress,
115 (MxPfnAllocation << PAGE_SHIFT),
116 PAGE_READWRITE,
117 &MArea,
118 TRUE,
119 0,
120 BoundaryAddressMultiple);
121 ASSERT(Status == STATUS_SUCCESS);
122
123 //
124 // ReactOS requires a memory area to keep the initial NP area off-bounds
125 //
126 BaseAddress = MmNonPagedPoolStart;
127 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
128 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
129 &BaseAddress,
130 MmSizeOfNonPagedPoolInBytes,
131 PAGE_READWRITE,
132 &MArea,
133 TRUE,
134 0,
135 BoundaryAddressMultiple);
136 ASSERT(Status == STATUS_SUCCESS);
137
138 //
139 // And we need one more for the system NP
140 //
141 BaseAddress = MmNonPagedSystemStart;
142 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
143 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
144 &BaseAddress,
145 (ULONG_PTR)MmNonPagedPoolEnd -
146 (ULONG_PTR)MmNonPagedSystemStart,
147 PAGE_READWRITE,
148 &MArea,
149 TRUE,
150 0,
151 BoundaryAddressMultiple);
152 ASSERT(Status == STATUS_SUCCESS);
153
154 //
155 // We also need one for system view space
156 //
157 BaseAddress = MiSystemViewStart;
158 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
159 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
160 &BaseAddress,
161 MmSystemViewSize,
162 PAGE_READWRITE,
163 &MArea,
164 TRUE,
165 0,
166 BoundaryAddressMultiple);
167 ASSERT(Status == STATUS_SUCCESS);
168
169 //
170 // And another for session space
171 //
172 BaseAddress = MmSessionBase;
173 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
174 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
175 &BaseAddress,
176 (ULONG_PTR)MiSessionSpaceEnd -
177 (ULONG_PTR)MmSessionBase,
178 PAGE_READWRITE,
179 &MArea,
180 TRUE,
181 0,
182 BoundaryAddressMultiple);
183 ASSERT(Status == STATUS_SUCCESS);
184
185 //
186 // One more for ARM paged pool
187 //
188 BaseAddress = MmPagedPoolStart;
189 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
190 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
191 &BaseAddress,
192 MmSizeOfPagedPoolInBytes,
193 PAGE_READWRITE,
194 &MArea,
195 TRUE,
196 0,
197 BoundaryAddressMultiple);
198 ASSERT(Status == STATUS_SUCCESS);
199
200 //
201 // And now, ReactOS paged pool
202 //
203 BaseAddress = MmPagedPoolBase;
204 MmCreateMemoryArea(MmGetKernelAddressSpace(),
205 MEMORY_AREA_PAGED_POOL | MEMORY_AREA_STATIC,
206 &BaseAddress,
207 MmPagedPoolSize,
208 PAGE_READWRITE,
209 &MArea,
210 TRUE,
211 0,
212 BoundaryAddressMultiple);
213
214 //
215 // Next, the KPCR
216 //
217 BaseAddress = (PVOID)PCR;
218 MmCreateMemoryArea(MmGetKernelAddressSpace(),
219 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
220 &BaseAddress,
221 PAGE_SIZE * KeNumberProcessors,
222 PAGE_READWRITE,
223 &MArea,
224 TRUE,
225 0,
226 BoundaryAddressMultiple);
227
228 //
229 // Now the KUSER_SHARED_DATA
230 //
231 BaseAddress = (PVOID)KI_USER_SHARED_DATA;
232 MmCreateMemoryArea(MmGetKernelAddressSpace(),
233 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
234 &BaseAddress,
235 PAGE_SIZE,
236 PAGE_READWRITE,
237 &MArea,
238 TRUE,
239 0,
240 BoundaryAddressMultiple);
241 }
242
243 VOID
244 NTAPI
245 MiDbgDumpAddressSpace(VOID)
246 {
247 //
248 // Print the memory layout
249 //
250 DPRINT1(" 0x%p - 0x%p\t%s\n",
251 MmSystemRangeStart,
252 (ULONG_PTR)MmSystemRangeStart + MmBootImageSize,
253 "Boot Loaded Image");
254 DPRINT1(" 0x%p - 0x%p\t%s\n",
255 MmPagedPoolBase,
256 (ULONG_PTR)MmPagedPoolBase + MmPagedPoolSize,
257 "Paged Pool");
258 DPRINT1(" 0x%p - 0x%p\t%s\n",
259 MmPfnDatabase,
260 (ULONG_PTR)MmPfnDatabase + (MxPfnAllocation << PAGE_SHIFT),
261 "PFN Database");
262 DPRINT1(" 0x%p - 0x%p\t%s\n",
263 MmNonPagedPoolStart,
264 (ULONG_PTR)MmNonPagedPoolStart + MmSizeOfNonPagedPoolInBytes,
265 "ARM³ Non Paged Pool");
266 DPRINT1(" 0x%p - 0x%p\t%s\n",
267 MiSystemViewStart,
268 (ULONG_PTR)MiSystemViewStart + MmSystemViewSize,
269 "System View Space");
270 DPRINT1(" 0x%p - 0x%p\t%s\n",
271 MmSessionBase,
272 MiSessionSpaceEnd,
273 "Session Space");
274 DPRINT1(" 0x%p - 0x%p\t%s\n",
275 PTE_BASE, PDE_BASE,
276 "Page Tables");
277 DPRINT1(" 0x%p - 0x%p\t%s\n",
278 PDE_BASE, HYPER_SPACE,
279 "Page Directories");
280 DPRINT1(" 0x%p - 0x%p\t%s\n",
281 HYPER_SPACE, HYPER_SPACE + (4 * 1024 * 1024),
282 "Hyperspace");
283 DPRINT1(" 0x%p - 0x%p\t%s\n",
284 MmPagedPoolStart,
285 (ULONG_PTR)MmPagedPoolStart + MmSizeOfPagedPoolInBytes,
286 "ARM³ Paged Pool");
287 DPRINT1(" 0x%p - 0x%p\t%s\n",
288 MmNonPagedSystemStart, MmNonPagedPoolExpansionStart,
289 "System PTE Space");
290 DPRINT1(" 0x%p - 0x%p\t%s\n",
291 MmNonPagedPoolExpansionStart, MmNonPagedPoolEnd,
292 "Non Paged Pool Expansion PTE Space");
293 }
294
295 VOID
296 NTAPI
297 MiDbgDumpMemoryDescriptors(VOID)
298 {
299 PLIST_ENTRY NextEntry;
300 PMEMORY_ALLOCATION_DESCRIPTOR Md;
301 ULONG TotalPages = 0;
302
303 DPRINT1("Base\t\tLength\t\tType\n");
304 for (NextEntry = KeLoaderBlock->MemoryDescriptorListHead.Flink;
305 NextEntry != &KeLoaderBlock->MemoryDescriptorListHead;
306 NextEntry = NextEntry->Flink)
307 {
308 Md = CONTAINING_RECORD(NextEntry, MEMORY_ALLOCATION_DESCRIPTOR, ListEntry);
309 DPRINT1("%08lX\t%08lX\t%s\n", Md->BasePage, Md->PageCount, MemType[Md->MemoryType]);
310 TotalPages += Md->PageCount;
311 }
312
313 DPRINT1("Total: %08lX (%d MB)\n", TotalPages, (TotalPages * PAGE_SIZE) / 1024 / 1024);
314 }
315
316 NTSTATUS
317 NTAPI
318 MmArmInitSystem(IN ULONG Phase,
319 IN PLOADER_PARAMETER_BLOCK LoaderBlock);
320
321 VOID
322 INIT_FUNCTION
323 NTAPI
324 MmInit1(VOID)
325 {
326 /* Initialize the kernel address space */
327 KeInitializeGuardedMutex(&PsGetCurrentProcess()->AddressCreationLock);
328 MmKernelAddressSpace = MmGetCurrentAddressSpace();
329 MmInitGlobalKernelPageDirectory();
330
331 /* Dump memory descriptors */
332 if (MiDbgEnableMdDump) MiDbgDumpMemoryDescriptors();
333
334 //
335 // Initialize ARM³ in phase 0
336 //
337 MmArmInitSystem(0, KeLoaderBlock);
338
339 /* Initialize the page list */
340 MmInitializePageList();
341
342 //
343 // Initialize ARM³ in phase 1
344 //
345 MmArmInitSystem(1, KeLoaderBlock);
346
347 /* Put the paged pool after the loaded modules */
348 MmPagedPoolBase = (PVOID)PAGE_ROUND_UP((ULONG_PTR)MmSystemRangeStart +
349 MmBootImageSize);
350 MmPagedPoolSize = MM_PAGED_POOL_SIZE;
351
352 /* Intialize system memory areas */
353 MiInitSystemMemoryAreas();
354
355 /* Dump the address space */
356 MiDbgDumpAddressSpace();
357
358 /* Initialize paged pool */
359 MmInitializePagedPool();
360
361 /* Initialize working sets */
362 MmInitializeMemoryConsumer(MC_USER, MmTrimUserMemory);
363 }
364
365 BOOLEAN
366 NTAPI
367 MmInitSystem(IN ULONG Phase,
368 IN PLOADER_PARAMETER_BLOCK LoaderBlock)
369 {
370 extern MMPTE HyperTemplatePte;
371 PMMPTE PointerPte;
372 MMPTE TempPte = HyperTemplatePte;
373 PFN_NUMBER PageFrameNumber;
374
375 if (Phase == 0)
376 {
377 /* Initialize Mm bootstrap */
378 MmInit1();
379
380 /* Initialize the Loader Lock */
381 KeInitializeMutant(&MmSystemLoadLock, FALSE);
382
383 /* Reload boot drivers */
384 MiReloadBootLoadedDrivers(LoaderBlock);
385
386 /* Initialize the loaded module list */
387 MiInitializeLoadedModuleList(LoaderBlock);
388
389 /* Setup shared user data settings that NT does as well */
390 ASSERT(SharedUserData->NumberOfPhysicalPages == 0);
391 SharedUserData->NumberOfPhysicalPages = MmStats.NrTotalPages;
392 SharedUserData->LargePageMinimum = 0;
393
394 /* For now, we assume that we're always Server */
395 SharedUserData->NtProductType = NtProductServer;
396 }
397 else if (Phase == 1)
398 {
399 MmInitializeRmapList();
400 MmInitializePageOp();
401 MmInitSectionImplementation();
402 MmInitPagingFile();
403
404 //
405 // Create a PTE to double-map the shared data section. We allocate it
406 // from paged pool so that we can't fault when trying to touch the PTE
407 // itself (to map it), since paged pool addresses will already be mapped
408 // by the fault handler.
409 //
410 MmSharedUserDataPte = ExAllocatePoolWithTag(PagedPool,
411 sizeof(MMPTE),
412 ' mM');
413 if (!MmSharedUserDataPte) return FALSE;
414
415 //
416 // Now get the PTE for shared data, and read the PFN that holds it
417 //
418 PointerPte = MiAddressToPte(KI_USER_SHARED_DATA);
419 ASSERT(PointerPte->u.Hard.Valid == 1);
420 PageFrameNumber = PFN_FROM_PTE(PointerPte);
421
422 //
423 // Now write a copy of it
424 //
425 TempPte.u.Hard.Owner = 1;
426 TempPte.u.Hard.PageFrameNumber = PageFrameNumber;
427 *MmSharedUserDataPte = TempPte;
428
429 /*
430 * Unmap low memory
431 */
432 MiInitBalancerThread();
433
434 /*
435 * Initialise the modified page writer.
436 */
437 MmInitMpwThread();
438
439 /* Initialize the balance set manager */
440 MmInitBsmThread();
441 }
442 else if (Phase == 2)
443 {
444
445 }
446
447 return TRUE;
448 }
449