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