- Removed the process from the parameter list of MmCreateMemoryArea.
[reactos.git] / reactos / ntoskrnl / mm / mminit.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/mm/mminit.c
6 * PURPOSE: Kernel memory managment initialization functions
7 *
8 * PROGRAMMERS: David Welch (welch@cwcom.net)
9 */
10
11 /* INCLUDES *****************************************************************/
12
13 #include <ntoskrnl.h>
14 #define NDEBUG
15 #include <internal/debug.h>
16
17 /* GLOBALS *****************************************************************/
18
19 /*
20 * Compiler defined symbols
21 */
22 extern unsigned int _text_start__;
23 extern unsigned int _text_end__;
24
25 extern unsigned int _init_start__;
26 extern unsigned int _init_end__;
27
28 extern unsigned int _bss_end__;
29
30
31 static BOOLEAN IsThisAnNtAsSystem = FALSE;
32 static MM_SYSTEM_SIZE MmSystemSize = MmSmallSystem;
33
34 PHYSICAL_ADDRESS MmSharedDataPagePhysicalAddress;
35
36 PVOID MiNonPagedPoolStart;
37 ULONG MiNonPagedPoolLength;
38
39 extern ULONG init_stack;
40 extern ULONG init_stack_top;
41
42 /* FUNCTIONS ****************************************************************/
43
44 /*
45 * @implemented
46 */
47 BOOLEAN STDCALL MmIsThisAnNtAsSystem(VOID)
48 {
49 return(IsThisAnNtAsSystem);
50 }
51
52 /*
53 * @implemented
54 */
55 MM_SYSTEM_SIZE STDCALL MmQuerySystemSize(VOID)
56 {
57 return(MmSystemSize);
58 }
59
60 VOID
61 NTAPI
62 MiShutdownMemoryManager(VOID)
63 {}
64
65 VOID
66 INIT_FUNCTION
67 NTAPI
68 MmInitVirtualMemory(ULONG_PTR LastKernelAddress,
69 ULONG KernelLength)
70 /*
71 * FUNCTION: Intialize the memory areas list
72 * ARGUMENTS:
73 * bp = Pointer to the boot parameters
74 * kernel_len = Length of the kernel
75 */
76 {
77 PVOID BaseAddress;
78 ULONG Length;
79 ULONG ParamLength = KernelLength;
80 NTSTATUS Status;
81 PHYSICAL_ADDRESS BoundaryAddressMultiple;
82 PFN_TYPE Pfn;
83 PMEMORY_AREA MArea;
84
85 DPRINT("MmInitVirtualMemory(%x, %x)\n",LastKernelAddress, KernelLength);
86
87 BoundaryAddressMultiple.QuadPart = 0;
88 LastKernelAddress = PAGE_ROUND_UP(LastKernelAddress);
89
90 MmInitMemoryAreas();
91
92 /* Start the paged and nonpaged pool at a 4MB boundary. */
93 MiNonPagedPoolStart = (PVOID)ROUND_UP((ULONG_PTR)LastKernelAddress + PAGE_SIZE, 0x400000);
94 MiNonPagedPoolLength = MM_NONPAGED_POOL_SIZE;
95
96 MmPagedPoolBase = (PVOID)ROUND_UP((ULONG_PTR)MiNonPagedPoolStart + MiNonPagedPoolLength + PAGE_SIZE, 0x400000);
97 MmPagedPoolSize = MM_PAGED_POOL_SIZE;
98
99 DPRINT("NonPagedPool %x - %x, PagedPool %x - %x\n", MiNonPagedPoolStart, (ULONG_PTR)MiNonPagedPoolStart + MiNonPagedPoolLength - 1,
100 MmPagedPoolBase, (ULONG_PTR)MmPagedPoolBase + MmPagedPoolSize - 1);
101
102 MiInitializeNonPagedPool();
103
104 /*
105 * Setup the system area descriptor list
106 */
107 MiInitPageDirectoryMap();
108
109 BaseAddress = (PVOID)KPCR_BASE;
110 MmCreateMemoryArea(MmGetKernelAddressSpace(),
111 MEMORY_AREA_SYSTEM,
112 &BaseAddress,
113 PAGE_SIZE * MAXIMUM_PROCESSORS,
114 PAGE_READWRITE,
115 &MArea,
116 TRUE,
117 0,
118 BoundaryAddressMultiple);
119
120 /* Local APIC base */
121 BaseAddress = (PVOID)0xFEE00000;
122 MmCreateMemoryArea(MmGetKernelAddressSpace(),
123 MEMORY_AREA_SYSTEM,
124 &BaseAddress,
125 PAGE_SIZE,
126 PAGE_READWRITE,
127 &MArea,
128 TRUE,
129 0,
130 BoundaryAddressMultiple);
131
132 /* i/o APIC base */
133 BaseAddress = (PVOID)0xFEC00000;
134 MmCreateMemoryArea(MmGetKernelAddressSpace(),
135 MEMORY_AREA_SYSTEM,
136 &BaseAddress,
137 PAGE_SIZE,
138 PAGE_READWRITE,
139 &MArea,
140 TRUE,
141 0,
142 BoundaryAddressMultiple);
143
144 BaseAddress = (PVOID)0xFF3A0000;
145 MmCreateMemoryArea(MmGetKernelAddressSpace(),
146 MEMORY_AREA_SYSTEM,
147 &BaseAddress,
148 0x20000,
149 PAGE_READWRITE,
150 &MArea,
151 TRUE,
152 0,
153 BoundaryAddressMultiple);
154
155 BaseAddress = (PVOID)KERNEL_BASE;
156 Length = PAGE_ROUND_UP(((ULONG_PTR)&_text_end__)) - KERNEL_BASE;
157 ParamLength = ParamLength - Length;
158
159 /*
160 * No need to lock the address space at this point since no
161 * other threads are running.
162 */
163 MmCreateMemoryArea(MmGetKernelAddressSpace(),
164 MEMORY_AREA_SYSTEM,
165 &BaseAddress,
166 Length,
167 PAGE_EXECUTE_READ,
168 &MArea,
169 TRUE,
170 0,
171 BoundaryAddressMultiple);
172
173 BaseAddress = (PVOID)PAGE_ROUND_UP(((ULONG_PTR)&_text_end__));
174 ASSERT(BaseAddress == (PVOID)&_init_start__);
175 Length = PAGE_ROUND_UP(((ULONG_PTR)&_init_end__)) -
176 PAGE_ROUND_UP(((ULONG_PTR)&_text_end__));
177 ParamLength = ParamLength - Length;
178
179 MmCreateMemoryArea(MmGetKernelAddressSpace(),
180 MEMORY_AREA_SYSTEM,
181 &BaseAddress,
182 Length,
183 PAGE_EXECUTE_READ,
184 &MArea,
185 TRUE,
186 0,
187 BoundaryAddressMultiple);
188
189 Length = PAGE_ROUND_UP(((ULONG_PTR)&_bss_end__)) -
190 PAGE_ROUND_UP(((ULONG_PTR)&_init_end__));
191 ParamLength = ParamLength - Length;
192 DPRINT("Length %x\n",Length);
193 BaseAddress = (PVOID)PAGE_ROUND_UP(((ULONG_PTR)&_init_end__));
194 DPRINT("BaseAddress %x\n",BaseAddress);
195
196 /*
197 * No need to lock the address space at this point since we are
198 * the only thread running.
199 */
200 MmCreateMemoryArea(MmGetKernelAddressSpace(),
201 MEMORY_AREA_SYSTEM,
202 &BaseAddress,
203 Length,
204 PAGE_READWRITE,
205 &MArea,
206 TRUE,
207 0,
208 BoundaryAddressMultiple);
209
210 BaseAddress = (PVOID)PAGE_ROUND_UP(((ULONG_PTR)&_bss_end__));
211 Length = LastKernelAddress - (ULONG_PTR)BaseAddress;
212 MmCreateMemoryArea(MmGetKernelAddressSpace(),
213 MEMORY_AREA_SYSTEM,
214 &BaseAddress,
215 Length,
216 PAGE_READWRITE,
217 &MArea,
218 TRUE,
219 0,
220 BoundaryAddressMultiple);
221
222 BaseAddress = MiNonPagedPoolStart;
223 MmCreateMemoryArea(MmGetKernelAddressSpace(),
224 MEMORY_AREA_SYSTEM,
225 &BaseAddress,
226 MiNonPagedPoolLength,
227 PAGE_READWRITE,
228 &MArea,
229 TRUE,
230 0,
231 BoundaryAddressMultiple);
232
233 BaseAddress = MmPagedPoolBase;
234 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
235 MEMORY_AREA_PAGED_POOL,
236 &BaseAddress,
237 MmPagedPoolSize,
238 PAGE_READWRITE,
239 &MArea,
240 TRUE,
241 0,
242 BoundaryAddressMultiple);
243
244 MmInitializePagedPool();
245
246 /*
247 * Create the kernel mapping of the user/kernel shared memory.
248 */
249 BaseAddress = (PVOID)KI_USER_SHARED_DATA;
250 Length = PAGE_SIZE;
251 MmCreateMemoryArea(MmGetKernelAddressSpace(),
252 MEMORY_AREA_SYSTEM,
253 &BaseAddress,
254 Length,
255 PAGE_READWRITE,
256 &MArea,
257 TRUE,
258 0,
259 BoundaryAddressMultiple);
260 Status = MmRequestPageMemoryConsumer(MC_NPPOOL, TRUE, &Pfn);
261 MmSharedDataPagePhysicalAddress.QuadPart = Pfn << PAGE_SHIFT;
262 Status = MmCreateVirtualMapping(NULL,
263 (PVOID)KI_USER_SHARED_DATA,
264 PAGE_READWRITE,
265 &Pfn,
266 1);
267 if (!NT_SUCCESS(Status))
268 {
269 DbgPrint("Unable to create virtual mapping\n");
270 KEBUGCHECK(0);
271 }
272 RtlZeroMemory(BaseAddress, Length);
273
274 /*
275 *
276 */
277 MmInitializeMemoryConsumer(MC_USER, MmTrimUserMemory);
278 }
279
280 VOID
281 INIT_FUNCTION
282 NTAPI
283 MmInit1(ULONG_PTR FirstKrnlPhysAddr,
284 ULONG_PTR LastKrnlPhysAddr,
285 ULONG_PTR LastKernelAddress,
286 PADDRESS_RANGE BIOSMemoryMap,
287 ULONG AddressRangeCount,
288 ULONG MaxMem)
289 /*
290 * FUNCTION: Initalize memory managment
291 */
292 {
293 ULONG i;
294 ULONG kernel_len;
295 ULONG_PTR MappingAddress;
296
297 DPRINT("MmInit1(FirstKrnlPhysAddr, %p, LastKrnlPhysAddr %p, LastKernelAddress %p)\n",
298 FirstKrnlPhysAddr,
299 LastKrnlPhysAddr,
300 LastKernelAddress);
301
302 if ((BIOSMemoryMap != NULL) && (AddressRangeCount > 0))
303 {
304 // If we have a bios memory map, recalulate the memory size
305 ULONG last = 0;
306 for (i = 0; i < AddressRangeCount; i++)
307 {
308 if (BIOSMemoryMap[i].Type == 1
309 && (BIOSMemoryMap[i].BaseAddrLow + BIOSMemoryMap[i].LengthLow + PAGE_SIZE -1) / PAGE_SIZE > last)
310 {
311 last = (BIOSMemoryMap[i].BaseAddrLow + BIOSMemoryMap[i].LengthLow + PAGE_SIZE -1) / PAGE_SIZE;
312 }
313 }
314 if ((last - 256) * 4 > KeLoaderBlock.MemHigher)
315 {
316 KeLoaderBlock.MemHigher = (last - 256) * 4;
317 }
318 }
319
320 if (KeLoaderBlock.MemHigher >= (MaxMem - 1) * 1024)
321 {
322 KeLoaderBlock.MemHigher = (MaxMem - 1) * 1024;
323 }
324
325 /* Set memory limits */
326 MmUserProbeAddress = (ULONG_PTR)MmSystemRangeStart - 0x10000;
327 MmHighestUserAddress = (PVOID)(MmUserProbeAddress - 1);
328
329 /*
330 * Initialize memory managment statistics
331 */
332 MmStats.NrTotalPages = 0;
333 MmStats.NrSystemPages = 0;
334 MmStats.NrUserPages = 0;
335 MmStats.NrReservedPages = 0;
336 MmStats.NrUserPages = 0;
337 MmStats.NrFreePages = 0;
338 MmStats.NrLockedPages = 0;
339 MmStats.PagingRequestsInLastMinute = 0;
340 MmStats.PagingRequestsInLastFiveMinutes = 0;
341 MmStats.PagingRequestsInLastFifteenMinutes = 0;
342
343 /*
344 * Free all pages not used for kernel memory
345 * (we assume the kernel occupies a continuous range of physical
346 * memory)
347 */
348 DPRINT("first krnl %x\nlast krnl %x\n",FirstKrnlPhysAddr,
349 LastKrnlPhysAddr);
350
351 /*
352 * Free physical memory not used by the kernel
353 */
354 MmStats.NrTotalPages = KeLoaderBlock.MemHigher/4;
355 if (!MmStats.NrTotalPages)
356 {
357 DbgPrint("Memory not detected, default to 8 MB\n");
358 MmStats.NrTotalPages = 2048;
359 }
360 else
361 {
362 /* add 1MB for standard memory (not extended) */
363 MmStats.NrTotalPages += 256;
364 }
365 #ifdef BIOS_MEM_FIX
366 MmStats.NrTotalPages += 16;
367 #endif
368
369 /*
370 * Initialize the kernel address space
371 */
372 MmInitializeKernelAddressSpace();
373
374 MmInitGlobalKernelPageDirectory();
375
376 DbgPrint("Used memory %dKb\n", (MmStats.NrTotalPages * PAGE_SIZE) / 1024);
377 DPRINT1("Kernel Stack Limits. InitTop = 0x%x, Init = 0x%x\n", init_stack_top, init_stack);
378
379 LastKernelAddress = (ULONG_PTR)MmInitializePageList(
380 FirstKrnlPhysAddr,
381 LastKrnlPhysAddr,
382 MmStats.NrTotalPages,
383 PAGE_ROUND_UP(LastKernelAddress),
384 BIOSMemoryMap,
385 AddressRangeCount);
386 kernel_len = LastKrnlPhysAddr - FirstKrnlPhysAddr;
387
388 /*
389 * Unmap low memory
390 */
391 #ifdef CONFIG_SMP
392 /* In SMP mode we unmap the low memory pagetable in MmInit3.
393 The APIC needs the mapping of the first pages
394 while the processors are starting up.
395 We unmap all pages except page 2 and 3. */
396 for (MappingAddress = 0;
397 MappingAddress < 1024 * PAGE_SIZE;
398 MappingAddress += PAGE_SIZE)
399 {
400 if (MappingAddress != 2 * PAGE_SIZE &&
401 MappingAddress != 3 * PAGE_SIZE)
402 {
403 MmRawDeleteVirtualMapping((PVOID)MappingAddress);
404 }
405 }
406 #else
407 MmDeletePageTable(NULL, 0);
408 #endif
409
410 DPRINT("Invalidating between %x and %x\n",
411 LastKernelAddress, KERNEL_BASE + 0x00600000);
412 for (MappingAddress = LastKernelAddress;
413 MappingAddress < KERNEL_BASE + 0x00600000;
414 MappingAddress += PAGE_SIZE)
415 {
416 MmRawDeleteVirtualMapping((PVOID)MappingAddress);
417 }
418
419 DPRINT("Almost done MmInit()\n");
420 /*
421 * Intialize memory areas
422 */
423 MmInitVirtualMemory(LastKernelAddress, kernel_len);
424
425 MmInitializeMdlImplementation();
426 }
427
428 VOID
429 NTAPI
430 INIT_FUNCTION
431 MmInit2(VOID)
432 {
433 MmInitializeRmapList();
434 MmInitializePageOp();
435 MmInitSectionImplementation();
436 MmInitPagingFile();
437 }
438
439 VOID
440 INIT_FUNCTION
441 NTAPI
442 MmInit3(VOID)
443 {
444 /*
445 * Unmap low memory
446 */
447 #ifdef CONFIG_SMP
448 /* In SMP mode we can unmap the low memory
449 if all processors are started. */
450 MmDeletePageTable(NULL, 0);
451 #endif
452
453 MmInitZeroPageThread();
454 MmCreatePhysicalMemorySection();
455 MiInitBalancerThread();
456
457 /*
458 * Initialise the modified page writer.
459 */
460 MmInitMpwThread();
461
462 /* FIXME: Read parameters from memory */
463 }
464
465 VOID STATIC
466 MiFreeInitMemoryPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
467 PFN_TYPE Page, SWAPENTRY SwapEntry,
468 BOOLEAN Dirty)
469 {
470 ASSERT(SwapEntry == 0);
471 if (Page != 0)
472 {
473 MmReleasePageMemoryConsumer(MC_NPPOOL, Page);
474 }
475 }
476
477 VOID
478 NTAPI
479 MiFreeInitMemory(VOID)
480 {
481 MmLockAddressSpace(MmGetKernelAddressSpace());
482 MmFreeMemoryAreaByPtr(MmGetKernelAddressSpace(),
483 (PVOID)&_init_start__,
484 MiFreeInitMemoryPage,
485 NULL);
486 MmUnlockAddressSpace(MmGetKernelAddressSpace());
487 }