[DNSAPI_APITEST] Add more tests for DnsQuery_A/W. By Peter Hater. ROSTESTS-242
[reactos.git] / reactos / 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 //
42 // Helper function to create initial memory areas.
43 // The created area is always read/write.
44 //
45 VOID
46 INIT_FUNCTION
47 NTAPI
48 MiCreateArm3StaticMemoryArea(PVOID BaseAddress, ULONG Size, BOOLEAN Executable)
49 {
50 const ULONG Protection = Executable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE;
51 PVOID pBaseAddress = BaseAddress;
52 PMEMORY_AREA MArea;
53 NTSTATUS Status;
54
55 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
56 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
57 &pBaseAddress,
58 Size,
59 Protection,
60 &MArea,
61 0,
62 PAGE_SIZE);
63 ASSERT(Status == STATUS_SUCCESS);
64 // TODO: Perhaps it would be prudent to bugcheck here, not only assert?
65 }
66
67 VOID
68 INIT_FUNCTION
69 NTAPI
70 MiInitSystemMemoryAreas(VOID)
71 {
72 //
73 // Create all the static memory areas.
74 //
75
76 // The loader mappings. The only Executable area.
77 MiCreateArm3StaticMemoryArea((PVOID)KSEG0_BASE, MmBootImageSize, TRUE);
78
79 // The PTE base
80 MiCreateArm3StaticMemoryArea((PVOID)PTE_BASE, PTE_TOP - PTE_BASE + 1, FALSE);
81
82 // Hyperspace
83 MiCreateArm3StaticMemoryArea((PVOID)HYPER_SPACE, HYPER_SPACE_END - HYPER_SPACE + 1, FALSE);
84
85 // Protect the PFN database
86 MiCreateArm3StaticMemoryArea(MmPfnDatabase, (MxPfnAllocation << PAGE_SHIFT), FALSE);
87
88 // ReactOS requires a memory area to keep the initial NP area off-bounds
89 MiCreateArm3StaticMemoryArea(MmNonPagedPoolStart, MmSizeOfNonPagedPoolInBytes, FALSE);
90
91 // System NP
92 MiCreateArm3StaticMemoryArea(MmNonPagedSystemStart, MiNonPagedSystemSize, 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 VOID
121 NTAPI
122 INIT_FUNCTION
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 MmPagedPoolStart,
159 (ULONG_PTR)MmPagedPoolStart + MmSizeOfPagedPoolInBytes,
160 "ARM3 Paged Pool");
161 DPRINT1(" 0x%p - 0x%p\t%s\n",
162 MmNonPagedSystemStart, MmNonPagedPoolExpansionStart,
163 "System PTE Space");
164 DPRINT1(" 0x%p - 0x%p\t%s\n",
165 MmNonPagedPoolExpansionStart, MmNonPagedPoolEnd,
166 "Non Paged Pool Expansion PTE Space");
167 }
168
169 VOID
170 NTAPI
171 MmMpwThreadMain(PVOID Parameter)
172 {
173 NTSTATUS Status;
174 #ifndef NEWCC
175 ULONG PagesWritten;
176 #endif
177 LARGE_INTEGER Timeout;
178
179 UNREFERENCED_PARAMETER(Parameter);
180
181 Timeout.QuadPart = -50000000;
182
183 for(;;)
184 {
185 Status = KeWaitForSingleObject(&MpwThreadEvent,
186 0,
187 KernelMode,
188 FALSE,
189 &Timeout);
190 if (!NT_SUCCESS(Status))
191 {
192 DbgPrint("MpwThread: Wait failed\n");
193 KeBugCheck(MEMORY_MANAGEMENT);
194 return;
195 }
196
197 #ifndef NEWCC
198 PagesWritten = 0;
199
200 // XXX arty -- we flush when evicting pages or destorying cache
201 // sections.
202 CcRosFlushDirtyPages(128, &PagesWritten, FALSE);
203 #endif
204 }
205 }
206
207 NTSTATUS
208 NTAPI
209 INIT_FUNCTION
210 MmInitMpwThread(VOID)
211 {
212 KPRIORITY Priority;
213 NTSTATUS Status;
214 CLIENT_ID MpwThreadId;
215
216 KeInitializeEvent(&MpwThreadEvent, SynchronizationEvent, FALSE);
217
218 Status = PsCreateSystemThread(&MpwThreadHandle,
219 THREAD_ALL_ACCESS,
220 NULL,
221 NULL,
222 &MpwThreadId,
223 MmMpwThreadMain,
224 NULL);
225 if (!NT_SUCCESS(Status))
226 {
227 return(Status);
228 }
229
230 Priority = 27;
231 NtSetInformationThread(MpwThreadHandle,
232 ThreadPriority,
233 &Priority,
234 sizeof(Priority));
235
236 return(STATUS_SUCCESS);
237 }
238
239 NTSTATUS
240 NTAPI
241 INIT_FUNCTION
242 MmInitBsmThread(VOID)
243 {
244 NTSTATUS Status;
245 OBJECT_ATTRIBUTES ObjectAttributes;
246 HANDLE ThreadHandle;
247
248 /* Create the thread */
249 InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL);
250 Status = PsCreateSystemThread(&ThreadHandle,
251 THREAD_ALL_ACCESS,
252 &ObjectAttributes,
253 NULL,
254 NULL,
255 KeBalanceSetManager,
256 NULL);
257
258 /* Close the handle and return status */
259 ZwClose(ThreadHandle);
260 return Status;
261 }
262
263 BOOLEAN
264 NTAPI
265 INIT_FUNCTION
266 MmInitSystem(IN ULONG Phase,
267 IN PLOADER_PARAMETER_BLOCK LoaderBlock)
268 {
269 extern MMPTE ValidKernelPte;
270 PMMPTE PointerPte;
271 MMPTE TempPte = ValidKernelPte;
272 PFN_NUMBER PageFrameNumber;
273
274 /* Initialize the kernel address space */
275 ASSERT(Phase == 1);
276
277 InitializeListHead(&MiSegmentList);
278 ExInitializeFastMutex(&MiGlobalPageOperation);
279 KeInitializeEvent(&MmWaitPageEvent, SynchronizationEvent, FALSE);
280 // Until we're fully demand paged, we can do things the old way through
281 // the balance manager
282 MmInitializeMemoryConsumer(MC_CACHE, MiRosTrimCache);
283
284 MmKernelAddressSpace = &PsIdleProcess->Vm;
285
286 /* Intialize system memory areas */
287 MiInitSystemMemoryAreas();
288
289 /* Dump the address space */
290 MiDbgDumpAddressSpace();
291
292 MmInitGlobalKernelPageDirectory();
293 MiInitializeUserPfnBitmap();
294 MmInitializeMemoryConsumer(MC_USER, MmTrimUserMemory);
295 MmInitializeRmapList();
296 MmInitSectionImplementation();
297 MmInitPagingFile();
298
299 //
300 // Create a PTE to double-map the shared data section. We allocate it
301 // from paged pool so that we can't fault when trying to touch the PTE
302 // itself (to map it), since paged pool addresses will already be mapped
303 // by the fault handler.
304 //
305 MmSharedUserDataPte = ExAllocatePoolWithTag(PagedPool,
306 sizeof(MMPTE),
307 TAG_MM);
308 if (!MmSharedUserDataPte) return FALSE;
309
310 //
311 // Now get the PTE for shared data, and read the PFN that holds it
312 //
313 PointerPte = MiAddressToPte((PVOID)KI_USER_SHARED_DATA);
314 ASSERT(PointerPte->u.Hard.Valid == 1);
315 PageFrameNumber = PFN_FROM_PTE(PointerPte);
316
317 /* Build the PTE and write it */
318 MI_MAKE_HARDWARE_PTE_KERNEL(&TempPte,
319 PointerPte,
320 MM_READONLY,
321 PageFrameNumber);
322 *MmSharedUserDataPte = TempPte;
323
324 /* Initialize session working set support */
325 MiInitializeSessionWsSupport();
326
327 /* Setup session IDs */
328 MiInitializeSessionIds();
329
330 /* Setup the memory threshold events */
331 if (!MiInitializeMemoryEvents()) return FALSE;
332
333 /*
334 * Unmap low memory
335 */
336 MiInitBalancerThread();
337
338 /*
339 * Initialise the modified page writer.
340 */
341 MmInitMpwThread();
342
343 /* Initialize the balance set manager */
344 MmInitBsmThread();
345
346 return TRUE;
347 }
348