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