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