xref: /reactos/ntoskrnl/mm/mminit.c (revision 65dbfc28)
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 BOOLEAN Mm64BitPhysicalAddress = FALSE;
23 ULONG MmReadClusterSize;
24 //
25 // 0 | 1 is on/off paging, 2 is undocumented
26 //
27 UCHAR MmDisablePagingExecutive = 1; // Forced to off
28 PMMPTE MmSharedUserDataPte;
29 PMMSUPPORT MmKernelAddressSpace;
30 
31 extern KEVENT MmWaitPageEvent;
32 extern FAST_MUTEX MiGlobalPageOperation;
33 extern LIST_ENTRY MiSegmentList;
34 extern NTSTATUS MiRosTrimCache(ULONG Target, ULONG Priority, PULONG NrFreed);
35 
36 /* PRIVATE FUNCTIONS *********************************************************/
37 
38 //
39 // Helper function to create initial memory areas.
40 // The created area is always read/write.
41 //
42 INIT_FUNCTION
43 VOID
44 NTAPI
45 MiCreateArm3StaticMemoryArea(PVOID BaseAddress, SIZE_T Size, BOOLEAN Executable)
46 {
47     const ULONG Protection = Executable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE;
48     PVOID pBaseAddress = BaseAddress;
49     PMEMORY_AREA MArea;
50     NTSTATUS Status;
51 
52     Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
53                                 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
54                                 &pBaseAddress,
55                                 Size,
56                                 Protection,
57                                 &MArea,
58                                 0,
59                                 PAGE_SIZE);
60     ASSERT(Status == STATUS_SUCCESS);
61     // TODO: Perhaps it would be  prudent to bugcheck here, not only assert?
62 }
63 
64 INIT_FUNCTION
65 VOID
66 NTAPI
67 MiInitSystemMemoryAreas(VOID)
68 {
69     //
70     // Create all the static memory areas.
71     //
72 
73     // The loader mappings. The only Executable area.
74     MiCreateArm3StaticMemoryArea((PVOID)KSEG0_BASE, MmBootImageSize, TRUE);
75 
76     // The PTE base
77     MiCreateArm3StaticMemoryArea((PVOID)PTE_BASE, PTE_TOP - PTE_BASE + 1, FALSE);
78 
79     // Hyperspace
80     MiCreateArm3StaticMemoryArea((PVOID)HYPER_SPACE, HYPER_SPACE_END - HYPER_SPACE + 1, FALSE);
81 
82     // Protect the PFN database
83     MiCreateArm3StaticMemoryArea(MmPfnDatabase, (MxPfnAllocation << PAGE_SHIFT), FALSE);
84 
85     // ReactOS requires a memory area to keep the initial NP area off-bounds
86     MiCreateArm3StaticMemoryArea(MmNonPagedPoolStart, MmSizeOfNonPagedPoolInBytes, FALSE);
87 
88     // System PTE space
89     MiCreateArm3StaticMemoryArea(MmNonPagedSystemStart, (MmNumberOfSystemPtes + 1) * PAGE_SIZE, FALSE);
90 
91     // Nonpaged pool expansion space
92     MiCreateArm3StaticMemoryArea(MmNonPagedPoolExpansionStart, (ULONG_PTR)MmNonPagedPoolEnd - (ULONG_PTR)MmNonPagedPoolExpansionStart, FALSE);
93 
94     // System view space
95     MiCreateArm3StaticMemoryArea(MiSystemViewStart, MmSystemViewSize, FALSE);
96 
97     // Session space
98     MiCreateArm3StaticMemoryArea(MmSessionBase, (ULONG_PTR)MiSessionSpaceEnd - (ULONG_PTR)MmSessionBase, FALSE);
99 
100     // Paged pool
101     MiCreateArm3StaticMemoryArea(MmPagedPoolStart, MmSizeOfPagedPoolInBytes, FALSE);
102 
103     // Debugger mapping
104     MiCreateArm3StaticMemoryArea(MI_DEBUG_MAPPING, PAGE_SIZE, FALSE);
105 
106 #if defined(_X86_)
107     // Reserved HAL area (includes KUSER_SHARED_DATA and KPCR)
108     MiCreateArm3StaticMemoryArea((PVOID)MM_HAL_VA_START, MM_HAL_VA_END - MM_HAL_VA_START + 1, FALSE);
109 #else /* _X86_ */
110 #ifndef _M_AMD64
111     // KPCR, one page per CPU. Only for 32-bit kernel.
112     MiCreateArm3StaticMemoryArea(PCR, PAGE_SIZE * KeNumberProcessors, FALSE);
113 #endif /* _M_AMD64 */
114 
115     // KUSER_SHARED_DATA
116     MiCreateArm3StaticMemoryArea((PVOID)KI_USER_SHARED_DATA, PAGE_SIZE, FALSE);
117 #endif /* _X86_ */
118 }
119 
120 INIT_FUNCTION
121 VOID
122 NTAPI
123 MiDbgDumpAddressSpace(VOID)
124 {
125     //
126     // Print the memory layout
127     //
128     DPRINT1("          0x%p - 0x%p\t%s\n",
129             KSEG0_BASE,
130             (ULONG_PTR)KSEG0_BASE + MmBootImageSize,
131             "Boot Loaded Image");
132     DPRINT1("          0x%p - 0x%p\t%s\n",
133             MmPfnDatabase,
134             (ULONG_PTR)MmPfnDatabase + (MxPfnAllocation << PAGE_SHIFT),
135             "PFN Database");
136     DPRINT1("          0x%p - 0x%p\t%s\n",
137             MmNonPagedPoolStart,
138             (ULONG_PTR)MmNonPagedPoolStart + MmSizeOfNonPagedPoolInBytes,
139             "ARM3 Non Paged Pool");
140     DPRINT1("          0x%p - 0x%p\t%s\n",
141             MiSystemViewStart,
142             (ULONG_PTR)MiSystemViewStart + MmSystemViewSize,
143             "System View Space");
144     DPRINT1("          0x%p - 0x%p\t%s\n",
145             MmSessionBase,
146             MiSessionSpaceEnd,
147             "Session Space");
148     DPRINT1("          0x%p - 0x%p\t%s\n",
149             PTE_BASE, PTE_TOP,
150             "Page Tables");
151     DPRINT1("          0x%p - 0x%p\t%s\n",
152             PDE_BASE, PDE_TOP,
153             "Page Directories");
154     DPRINT1("          0x%p - 0x%p\t%s\n",
155             HYPER_SPACE, HYPER_SPACE_END,
156             "Hyperspace");
157     DPRINT1("          0x%p - 0x%p\t%s\n",
158             MmSystemCacheStart, MmSystemCacheEnd,
159             "System Cache");
160     DPRINT1("          0x%p - 0x%p\t%s\n",
161             MmPagedPoolStart,
162             (ULONG_PTR)MmPagedPoolStart + MmSizeOfPagedPoolInBytes,
163             "ARM3 Paged Pool");
164     DPRINT1("          0x%p - 0x%p\t%s\n",
165             MmNonPagedSystemStart, MmNonPagedPoolExpansionStart,
166             "System PTE Space");
167     DPRINT1("          0x%p - 0x%p\t%s\n",
168             MmNonPagedPoolExpansionStart, MmNonPagedPoolEnd,
169             "Non Paged Pool Expansion PTE Space");
170 }
171 
172 INIT_FUNCTION
173 NTSTATUS
174 NTAPI
175 MmInitBsmThread(VOID)
176 {
177     NTSTATUS Status;
178     OBJECT_ATTRIBUTES ObjectAttributes;
179     HANDLE ThreadHandle;
180 
181     /* Create the thread */
182     InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL);
183     Status = PsCreateSystemThread(&ThreadHandle,
184                                   THREAD_ALL_ACCESS,
185                                   &ObjectAttributes,
186                                   NULL,
187                                   NULL,
188                                   KeBalanceSetManager,
189                                   NULL);
190 
191     /* Close the handle and return status */
192     ZwClose(ThreadHandle);
193     return Status;
194 }
195 
196 INIT_FUNCTION
197 BOOLEAN
198 NTAPI
199 MmInitSystem(IN ULONG Phase,
200              IN PLOADER_PARAMETER_BLOCK LoaderBlock)
201 {
202     extern MMPTE ValidKernelPte;
203     PMMPTE PointerPte;
204     MMPTE TempPte = ValidKernelPte;
205     PFN_NUMBER PageFrameNumber;
206     PLIST_ENTRY ListEntry;
207     PLDR_DATA_TABLE_ENTRY DataTableEntry;
208 
209     /* Initialize the kernel address space */
210     ASSERT(Phase == 1);
211 
212     InitializeListHead(&MiSegmentList);
213     ExInitializeFastMutex(&MiGlobalPageOperation);
214     KeInitializeEvent(&MmWaitPageEvent, SynchronizationEvent, FALSE);
215     // Until we're fully demand paged, we can do things the old way through
216     // the balance manager
217     MmInitializeMemoryConsumer(MC_CACHE, MiRosTrimCache);
218 
219     MmKernelAddressSpace = &PsIdleProcess->Vm;
220 
221     /* Intialize system memory areas */
222     MiInitSystemMemoryAreas();
223 
224     /* Dump the address space */
225     MiDbgDumpAddressSpace();
226 
227     MmInitGlobalKernelPageDirectory();
228     MiInitializeUserPfnBitmap();
229     MmInitializeMemoryConsumer(MC_USER, MmTrimUserMemory);
230     MmInitializeRmapList();
231     MmInitSectionImplementation();
232     MmInitPagingFile();
233 
234     //
235     // Create a PTE to double-map the shared data section. We allocate it
236     // from paged pool so that we can't fault when trying to touch the PTE
237     // itself (to map it), since paged pool addresses will already be mapped
238     // by the fault handler.
239     //
240     MmSharedUserDataPte = ExAllocatePoolWithTag(PagedPool,
241                           sizeof(MMPTE),
242                           TAG_MM);
243     if (!MmSharedUserDataPte) return FALSE;
244 
245     //
246     // Now get the PTE for shared data, and read the PFN that holds it
247     //
248     PointerPte = MiAddressToPte((PVOID)KI_USER_SHARED_DATA);
249     ASSERT(PointerPte->u.Hard.Valid == 1);
250     PageFrameNumber = PFN_FROM_PTE(PointerPte);
251 
252     /* Build the PTE and write it */
253     MI_MAKE_HARDWARE_PTE_KERNEL(&TempPte,
254                                 PointerPte,
255                                 MM_READONLY,
256                                 PageFrameNumber);
257     *MmSharedUserDataPte = TempPte;
258 
259     /* Initialize session working set support */
260     MiInitializeSessionWsSupport();
261 
262     /* Setup session IDs */
263     MiInitializeSessionIds();
264 
265     /* Setup the memory threshold events */
266     if (!MiInitializeMemoryEvents()) return FALSE;
267 
268     /*
269      * Unmap low memory
270      */
271     MiInitBalancerThread();
272 
273     /* Initialize the balance set manager */
274     MmInitBsmThread();
275 
276     /* Loop the boot loaded images */
277     for (ListEntry = PsLoadedModuleList.Flink;
278          ListEntry != &PsLoadedModuleList;
279          ListEntry = ListEntry->Flink)
280     {
281         /* Get the data table entry */
282         DataTableEntry = CONTAINING_RECORD(ListEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
283 
284         /* Set up the image protection */
285         MiWriteProtectSystemImage(DataTableEntry->DllBase);
286     }
287 
288     return TRUE;
289 }
290 
291