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