[NTOSKRNL/FREELDR/NDK]
[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 VOID NTAPI MiInitializeUserPfnBitmap(VOID);
21
22 HANDLE MpwThreadHandle;
23 KEVENT MpwThreadEvent;
24
25 BOOLEAN Mm64BitPhysicalAddress = FALSE;
26 ULONG MmReadClusterSize;
27 //
28 // 0 | 1 is on/off paging, 2 is undocumented
29 //
30 UCHAR MmDisablePagingExecutive = 1; // Forced to off
31 PMMPTE MmSharedUserDataPte;
32 PMMSUPPORT MmKernelAddressSpace;
33
34 extern KEVENT MmWaitPageEvent;
35 extern FAST_MUTEX MiGlobalPageOperation;
36 extern LIST_ENTRY MiSegmentList;
37 extern NTSTATUS MiRosTrimCache(ULONG Target, ULONG Priority, PULONG NrFreed);
38
39 /* PRIVATE FUNCTIONS *********************************************************/
40
41 VOID
42 INIT_FUNCTION
43 NTAPI
44 MiInitSystemMemoryAreas()
45 {
46 PVOID BaseAddress;
47 PMEMORY_AREA MArea;
48 NTSTATUS Status;
49
50 //
51 // Create the memory area to define the loader mappings
52 //
53 BaseAddress = (PVOID)KSEG0_BASE;
54 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
55 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
56 &BaseAddress,
57 MmBootImageSize,
58 PAGE_EXECUTE_READWRITE,
59 &MArea,
60 TRUE,
61 0,
62 PAGE_SIZE);
63 ASSERT(Status == STATUS_SUCCESS);
64
65 //
66 // Create the memory area to define the PTE base
67 //
68 BaseAddress = (PVOID)PTE_BASE;
69 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
70 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
71 &BaseAddress,
72 PTE_TOP - PTE_BASE + 1,
73 PAGE_READWRITE,
74 &MArea,
75 TRUE,
76 0,
77 PAGE_SIZE);
78 ASSERT(Status == STATUS_SUCCESS);
79
80 //
81 // Create the memory area to define Hyperspace
82 //
83 BaseAddress = (PVOID)HYPER_SPACE;
84 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
85 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
86 &BaseAddress,
87 HYPER_SPACE_END - HYPER_SPACE + 1,
88 PAGE_READWRITE,
89 &MArea,
90 TRUE,
91 0,
92 PAGE_SIZE);
93 ASSERT(Status == STATUS_SUCCESS);
94
95 //
96 // Protect the PFN database
97 //
98 BaseAddress = MmPfnDatabase;
99 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
100 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
101 &BaseAddress,
102 (MxPfnAllocation << PAGE_SHIFT),
103 PAGE_READWRITE,
104 &MArea,
105 TRUE,
106 0,
107 PAGE_SIZE);
108 ASSERT(Status == STATUS_SUCCESS);
109
110 //
111 // ReactOS requires a memory area to keep the initial NP area off-bounds
112 //
113 BaseAddress = MmNonPagedPoolStart;
114 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
115 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
116 &BaseAddress,
117 MmSizeOfNonPagedPoolInBytes,
118 PAGE_READWRITE,
119 &MArea,
120 TRUE,
121 0,
122 PAGE_SIZE);
123 ASSERT(Status == STATUS_SUCCESS);
124
125 //
126 // And we need one more for the system NP
127 //
128 BaseAddress = MmNonPagedSystemStart;
129 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
130 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
131 &BaseAddress,
132 MiNonPagedSystemSize,
133 PAGE_READWRITE,
134 &MArea,
135 TRUE,
136 0,
137 PAGE_SIZE);
138 ASSERT(Status == STATUS_SUCCESS);
139
140 //
141 // We also need one for system view space
142 //
143 BaseAddress = MiSystemViewStart;
144 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
145 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
146 &BaseAddress,
147 MmSystemViewSize,
148 PAGE_READWRITE,
149 &MArea,
150 TRUE,
151 0,
152 PAGE_SIZE);
153 ASSERT(Status == STATUS_SUCCESS);
154
155 //
156 // And another for session space
157 //
158 BaseAddress = MmSessionBase;
159 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
160 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
161 &BaseAddress,
162 (ULONG_PTR)MiSessionSpaceEnd -
163 (ULONG_PTR)MmSessionBase,
164 PAGE_READWRITE,
165 &MArea,
166 TRUE,
167 0,
168 PAGE_SIZE);
169 ASSERT(Status == STATUS_SUCCESS);
170
171 //
172 // One more for ARM paged pool
173 //
174 BaseAddress = MmPagedPoolStart;
175 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
176 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
177 &BaseAddress,
178 MmSizeOfPagedPoolInBytes,
179 PAGE_READWRITE,
180 &MArea,
181 TRUE,
182 0,
183 PAGE_SIZE);
184 ASSERT(Status == STATUS_SUCCESS);
185 #ifndef _M_AMD64
186 //
187 // Next, the KPCR
188 //
189 BaseAddress = (PVOID)PCR;
190 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
191 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
192 &BaseAddress,
193 PAGE_SIZE * KeNumberProcessors,
194 PAGE_READWRITE,
195 &MArea,
196 TRUE,
197 0,
198 PAGE_SIZE);
199 ASSERT(Status == STATUS_SUCCESS);
200 #endif
201 //
202 // Now the KUSER_SHARED_DATA
203 //
204 BaseAddress = (PVOID)KI_USER_SHARED_DATA;
205 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
206 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
207 &BaseAddress,
208 PAGE_SIZE,
209 PAGE_READWRITE,
210 &MArea,
211 TRUE,
212 0,
213 PAGE_SIZE);
214 ASSERT(Status == STATUS_SUCCESS);
215
216 //
217 // And the debugger mapping
218 //
219 BaseAddress = MI_DEBUG_MAPPING;
220 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
221 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
222 &BaseAddress,
223 PAGE_SIZE,
224 PAGE_READWRITE,
225 &MArea,
226 TRUE,
227 0,
228 PAGE_SIZE);
229 ASSERT(Status == STATUS_SUCCESS);
230
231 #if defined(_X86_)
232 //
233 // Finally, reserve the 2 pages we currently make use of for HAL mappings
234 //
235 BaseAddress = (PVOID)0xFFC00000;
236 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
237 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
238 &BaseAddress,
239 PAGE_SIZE * 2,
240 PAGE_READWRITE,
241 &MArea,
242 TRUE,
243 0,
244 PAGE_SIZE);
245 ASSERT(Status == STATUS_SUCCESS);
246 #endif
247 }
248
249 VOID
250 NTAPI
251 INIT_FUNCTION
252 MiDbgDumpAddressSpace(VOID)
253 {
254 //
255 // Print the memory layout
256 //
257 DPRINT1(" 0x%p - 0x%p\t%s\n",
258 KSEG0_BASE,
259 (ULONG_PTR)KSEG0_BASE + MmBootImageSize,
260 "Boot Loaded Image");
261 DPRINT1(" 0x%p - 0x%p\t%s\n",
262 MmPfnDatabase,
263 (ULONG_PTR)MmPfnDatabase + (MxPfnAllocation << PAGE_SHIFT),
264 "PFN Database");
265 DPRINT1(" 0x%p - 0x%p\t%s\n",
266 MmNonPagedPoolStart,
267 (ULONG_PTR)MmNonPagedPoolStart + MmSizeOfNonPagedPoolInBytes,
268 "ARM3 Non Paged Pool");
269 DPRINT1(" 0x%p - 0x%p\t%s\n",
270 MiSystemViewStart,
271 (ULONG_PTR)MiSystemViewStart + MmSystemViewSize,
272 "System View Space");
273 DPRINT1(" 0x%p - 0x%p\t%s\n",
274 MmSessionBase,
275 MiSessionSpaceEnd,
276 "Session Space");
277 DPRINT1(" 0x%p - 0x%p\t%s\n",
278 PTE_BASE, PTE_TOP,
279 "Page Tables");
280 DPRINT1(" 0x%p - 0x%p\t%s\n",
281 PDE_BASE, PDE_TOP,
282 "Page Directories");
283 DPRINT1(" 0x%p - 0x%p\t%s\n",
284 HYPER_SPACE, HYPER_SPACE_END,
285 "Hyperspace");
286 DPRINT1(" 0x%p - 0x%p\t%s\n",
287 MmPagedPoolStart,
288 (ULONG_PTR)MmPagedPoolStart + MmSizeOfPagedPoolInBytes,
289 "ARM3 Paged Pool");
290 DPRINT1(" 0x%p - 0x%p\t%s\n",
291 MmNonPagedSystemStart, MmNonPagedPoolExpansionStart,
292 "System PTE Space");
293 DPRINT1(" 0x%p - 0x%p\t%s\n",
294 MmNonPagedPoolExpansionStart, MmNonPagedPoolEnd,
295 "Non Paged Pool Expansion PTE Space");
296 }
297
298 VOID
299 NTAPI
300 MmMpwThreadMain(PVOID Parameter)
301 {
302 NTSTATUS Status;
303 #ifndef NEWCC
304 ULONG PagesWritten;
305 #endif
306 LARGE_INTEGER Timeout;
307
308 UNREFERENCED_PARAMETER(Parameter);
309
310 Timeout.QuadPart = -50000000;
311
312 for(;;)
313 {
314 Status = KeWaitForSingleObject(&MpwThreadEvent,
315 0,
316 KernelMode,
317 FALSE,
318 &Timeout);
319 if (!NT_SUCCESS(Status))
320 {
321 DbgPrint("MpwThread: Wait failed\n");
322 KeBugCheck(MEMORY_MANAGEMENT);
323 return;
324 }
325
326 #ifndef NEWCC
327 PagesWritten = 0;
328
329 // XXX arty -- we flush when evicting pages or destorying cache
330 // sections.
331 CcRosFlushDirtyPages(128, &PagesWritten, FALSE);
332 #endif
333 }
334 }
335
336 NTSTATUS
337 NTAPI
338 INIT_FUNCTION
339 MmInitMpwThread(VOID)
340 {
341 KPRIORITY Priority;
342 NTSTATUS Status;
343 CLIENT_ID MpwThreadId;
344
345 KeInitializeEvent(&MpwThreadEvent, SynchronizationEvent, FALSE);
346
347 Status = PsCreateSystemThread(&MpwThreadHandle,
348 THREAD_ALL_ACCESS,
349 NULL,
350 NULL,
351 &MpwThreadId,
352 MmMpwThreadMain,
353 NULL);
354 if (!NT_SUCCESS(Status))
355 {
356 return(Status);
357 }
358
359 Priority = 27;
360 NtSetInformationThread(MpwThreadHandle,
361 ThreadPriority,
362 &Priority,
363 sizeof(Priority));
364
365 return(STATUS_SUCCESS);
366 }
367
368 NTSTATUS
369 NTAPI
370 INIT_FUNCTION
371 MmInitBsmThread(VOID)
372 {
373 NTSTATUS Status;
374 OBJECT_ATTRIBUTES ObjectAttributes;
375 HANDLE ThreadHandle;
376
377 /* Create the thread */
378 InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL);
379 Status = PsCreateSystemThread(&ThreadHandle,
380 THREAD_ALL_ACCESS,
381 &ObjectAttributes,
382 NULL,
383 NULL,
384 KeBalanceSetManager,
385 NULL);
386
387 /* Close the handle and return status */
388 ZwClose(ThreadHandle);
389 return Status;
390 }
391
392 BOOLEAN
393 NTAPI
394 INIT_FUNCTION
395 MmInitSystem(IN ULONG Phase,
396 IN PLOADER_PARAMETER_BLOCK LoaderBlock)
397 {
398 extern MMPTE ValidKernelPte;
399 PMMPTE PointerPte;
400 MMPTE TempPte = ValidKernelPte;
401 PFN_NUMBER PageFrameNumber;
402
403 /* Initialize the kernel address space */
404 ASSERT(Phase == 1);
405
406 InitializeListHead(&MiSegmentList);
407 ExInitializeFastMutex(&MiGlobalPageOperation);
408 KeInitializeEvent(&MmWaitPageEvent, SynchronizationEvent, FALSE);
409 // Until we're fully demand paged, we can do things the old way through
410 // the balance manager
411 MmInitializeMemoryConsumer(MC_CACHE, MiRosTrimCache);
412
413 MmKernelAddressSpace = &PsIdleProcess->Vm;
414
415 /* Intialize system memory areas */
416 MiInitSystemMemoryAreas();
417
418 /* Dump the address space */
419 MiDbgDumpAddressSpace();
420
421 MmInitGlobalKernelPageDirectory();
422 MiInitializeUserPfnBitmap();
423 MmInitializeMemoryConsumer(MC_USER, MmTrimUserMemory);
424 MmInitializeRmapList();
425 MmInitSectionImplementation();
426 MmInitPagingFile();
427
428 //
429 // Create a PTE to double-map the shared data section. We allocate it
430 // from paged pool so that we can't fault when trying to touch the PTE
431 // itself (to map it), since paged pool addresses will already be mapped
432 // by the fault handler.
433 //
434 MmSharedUserDataPte = ExAllocatePoolWithTag(PagedPool,
435 sizeof(MMPTE),
436 ' mM');
437 if (!MmSharedUserDataPte) return FALSE;
438
439 //
440 // Now get the PTE for shared data, and read the PFN that holds it
441 //
442 PointerPte = MiAddressToPte((PVOID)KI_USER_SHARED_DATA);
443 ASSERT(PointerPte->u.Hard.Valid == 1);
444 PageFrameNumber = PFN_FROM_PTE(PointerPte);
445
446 /* Build the PTE and write it */
447 MI_MAKE_HARDWARE_PTE_KERNEL(&TempPte,
448 PointerPte,
449 MM_READONLY,
450 PageFrameNumber);
451 *MmSharedUserDataPte = TempPte;
452
453 /* Initialize session working set support */
454 MiInitializeSessionWsSupport();
455
456 /* Setup session IDs */
457 MiInitializeSessionIds();
458
459 /* Setup the memory threshold events */
460 if (!MiInitializeMemoryEvents()) return FALSE;
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 return TRUE;
476 }
477