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