[SHELL/EXPERIMENTS]
[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 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 ULONG PagesWritten;
304 LARGE_INTEGER Timeout;
305
306 UNREFERENCED_PARAMETER(Parameter);
307
308 Timeout.QuadPart = -50000000;
309
310 for(;;)
311 {
312 Status = KeWaitForSingleObject(&MpwThreadEvent,
313 0,
314 KernelMode,
315 FALSE,
316 &Timeout);
317 if (!NT_SUCCESS(Status))
318 {
319 DbgPrint("MpwThread: Wait failed\n");
320 KeBugCheck(MEMORY_MANAGEMENT);
321 return;
322 }
323
324 PagesWritten = 0;
325
326 #ifndef NEWCC
327 // XXX arty -- we flush when evicting pages or destorying cache
328 // sections.
329 CcRosFlushDirtyPages(128, &PagesWritten, FALSE);
330 #endif
331 }
332 }
333
334 NTSTATUS
335 NTAPI
336 INIT_FUNCTION
337 MmInitMpwThread(VOID)
338 {
339 KPRIORITY Priority;
340 NTSTATUS Status;
341 CLIENT_ID MpwThreadId;
342
343 KeInitializeEvent(&MpwThreadEvent, SynchronizationEvent, FALSE);
344
345 Status = PsCreateSystemThread(&MpwThreadHandle,
346 THREAD_ALL_ACCESS,
347 NULL,
348 NULL,
349 &MpwThreadId,
350 MmMpwThreadMain,
351 NULL);
352 if (!NT_SUCCESS(Status))
353 {
354 return(Status);
355 }
356
357 Priority = 27;
358 NtSetInformationThread(MpwThreadHandle,
359 ThreadPriority,
360 &Priority,
361 sizeof(Priority));
362
363 return(STATUS_SUCCESS);
364 }
365
366 NTSTATUS
367 NTAPI
368 INIT_FUNCTION
369 MmInitBsmThread(VOID)
370 {
371 NTSTATUS Status;
372 OBJECT_ATTRIBUTES ObjectAttributes;
373 HANDLE ThreadHandle;
374
375 /* Create the thread */
376 InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL);
377 Status = PsCreateSystemThread(&ThreadHandle,
378 THREAD_ALL_ACCESS,
379 &ObjectAttributes,
380 NULL,
381 NULL,
382 KeBalanceSetManager,
383 NULL);
384
385 /* Close the handle and return status */
386 ZwClose(ThreadHandle);
387 return Status;
388 }
389
390 BOOLEAN
391 NTAPI
392 INIT_FUNCTION
393 MmInitSystem(IN ULONG Phase,
394 IN PLOADER_PARAMETER_BLOCK LoaderBlock)
395 {
396 extern MMPTE ValidKernelPte;
397 PMMPTE PointerPte;
398 MMPTE TempPte = ValidKernelPte;
399 PFN_NUMBER PageFrameNumber;
400
401 /* Initialize the kernel address space */
402 ASSERT(Phase == 1);
403
404 InitializeListHead(&MiSegmentList);
405 ExInitializeFastMutex(&MiGlobalPageOperation);
406 KeInitializeEvent(&MmWaitPageEvent, SynchronizationEvent, FALSE);
407 // Until we're fully demand paged, we can do things the old way through
408 // the balance manager
409 MmInitializeMemoryConsumer(MC_CACHE, MiRosTrimCache);
410
411 MmKernelAddressSpace = &PsIdleProcess->Vm;
412
413 /* Intialize system memory areas */
414 MiInitSystemMemoryAreas();
415
416 /* Dump the address space */
417 MiDbgDumpAddressSpace();
418
419 MmInitGlobalKernelPageDirectory();
420 MiInitializeUserPfnBitmap();
421 MmInitializeMemoryConsumer(MC_USER, MmTrimUserMemory);
422 MmInitializeRmapList();
423 MmInitSectionImplementation();
424 MmInitPagingFile();
425
426 //
427 // Create a PTE to double-map the shared data section. We allocate it
428 // from paged pool so that we can't fault when trying to touch the PTE
429 // itself (to map it), since paged pool addresses will already be mapped
430 // by the fault handler.
431 //
432 MmSharedUserDataPte = ExAllocatePoolWithTag(PagedPool,
433 sizeof(MMPTE),
434 ' mM');
435 if (!MmSharedUserDataPte) return FALSE;
436
437 //
438 // Now get the PTE for shared data, and read the PFN that holds it
439 //
440 PointerPte = MiAddressToPte((PVOID)KI_USER_SHARED_DATA);
441 ASSERT(PointerPte->u.Hard.Valid == 1);
442 PageFrameNumber = PFN_FROM_PTE(PointerPte);
443
444 /* Build the PTE and write it */
445 MI_MAKE_HARDWARE_PTE_KERNEL(&TempPte,
446 PointerPte,
447 MM_READONLY,
448 PageFrameNumber);
449 *MmSharedUserDataPte = TempPte;
450
451 /* Initialize session working set support */
452 MiInitializeSessionWsSupport();
453
454 /* Setup session IDs */
455 MiInitializeSessionIds();
456
457 /* Setup the memory threshold events */
458 if (!MiInitializeMemoryEvents()) return FALSE;
459
460 /*
461 * Unmap low memory
462 */
463 MiInitBalancerThread();
464
465 /*
466 * Initialise the modified page writer.
467 */
468 MmInitMpwThread();
469
470 /* Initialize the balance set manager */
471 MmInitBsmThread();
472
473 return TRUE;
474 }
475