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
8 * PROGRAMMERS: David Welch (welch@cwcom.net)
11 /* INCLUDES *****************************************************************/
15 #include <internal/debug.h>
17 /* GLOBALS *****************************************************************/
20 * Compiler defined symbols
22 extern unsigned int _text_start__
;
23 extern unsigned int _text_end__
;
25 extern unsigned int _init_start__
;
26 extern unsigned int _init_end__
;
28 extern unsigned int _bss_end__
;
31 static BOOLEAN IsThisAnNtAsSystem
= FALSE
;
32 static MM_SYSTEM_SIZE MmSystemSize
= MmSmallSystem
;
34 PHYSICAL_ADDRESS MmSharedDataPagePhysicalAddress
;
36 PVOID MiNonPagedPoolStart
;
37 ULONG MiNonPagedPoolLength
;
39 extern ULONG init_stack
;
40 extern ULONG init_stack_top
;
42 /* FUNCTIONS ****************************************************************/
47 BOOLEAN STDCALL
MmIsThisAnNtAsSystem(VOID
)
49 return(IsThisAnNtAsSystem
);
55 MM_SYSTEM_SIZE STDCALL
MmQuerySystemSize(VOID
)
62 MiShutdownMemoryManager(VOID
)
68 MmInitVirtualMemory(ULONG_PTR LastKernelAddress
,
71 * FUNCTION: Intialize the memory areas list
73 * bp = Pointer to the boot parameters
74 * kernel_len = Length of the kernel
79 ULONG ParamLength
= KernelLength
;
81 PHYSICAL_ADDRESS BoundaryAddressMultiple
;
85 DPRINT("MmInitVirtualMemory(%x, %x)\n",LastKernelAddress
, KernelLength
);
87 BoundaryAddressMultiple
.QuadPart
= 0;
88 LastKernelAddress
= PAGE_ROUND_UP(LastKernelAddress
);
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
;
96 MmPagedPoolBase
= (PVOID
)ROUND_UP((ULONG_PTR
)MiNonPagedPoolStart
+ MiNonPagedPoolLength
+ PAGE_SIZE
, 0x400000);
97 MmPagedPoolSize
= MM_PAGED_POOL_SIZE
;
99 DPRINT("NonPagedPool %x - %x, PagedPool %x - %x\n", MiNonPagedPoolStart
, (ULONG_PTR
)MiNonPagedPoolStart
+ MiNonPagedPoolLength
- 1,
100 MmPagedPoolBase
, (ULONG_PTR
)MmPagedPoolBase
+ MmPagedPoolSize
- 1);
102 MiInitializeNonPagedPool();
105 * Setup the system area descriptor list
107 MiInitPageDirectoryMap();
109 BaseAddress
= (PVOID
)KPCR_BASE
;
110 MmCreateMemoryArea(NULL
,
111 MmGetKernelAddressSpace(),
114 PAGE_SIZE
* MAXIMUM_PROCESSORS
,
119 BoundaryAddressMultiple
);
121 /* Local APIC base */
122 BaseAddress
= (PVOID
)0xFEE00000;
123 MmCreateMemoryArea(NULL
,
124 MmGetKernelAddressSpace(),
132 BoundaryAddressMultiple
);
135 BaseAddress
= (PVOID
)0xFEC00000;
136 MmCreateMemoryArea(NULL
,
137 MmGetKernelAddressSpace(),
145 BoundaryAddressMultiple
);
147 BaseAddress
= (PVOID
)0xFF3A0000;
148 MmCreateMemoryArea(NULL
,
149 MmGetKernelAddressSpace(),
157 BoundaryAddressMultiple
);
159 BaseAddress
= (PVOID
)KERNEL_BASE
;
160 Length
= PAGE_ROUND_UP(((ULONG_PTR
)&_text_end__
)) - KERNEL_BASE
;
161 ParamLength
= ParamLength
- Length
;
164 * No need to lock the address space at this point since no
165 * other threads are running.
167 MmCreateMemoryArea(NULL
,
168 MmGetKernelAddressSpace(),
176 BoundaryAddressMultiple
);
178 BaseAddress
= (PVOID
)PAGE_ROUND_UP(((ULONG_PTR
)&_text_end__
));
179 ASSERT(BaseAddress
== (PVOID
)&_init_start__
);
180 Length
= PAGE_ROUND_UP(((ULONG_PTR
)&_init_end__
)) -
181 PAGE_ROUND_UP(((ULONG_PTR
)&_text_end__
));
182 ParamLength
= ParamLength
- Length
;
184 MmCreateMemoryArea(NULL
,
185 MmGetKernelAddressSpace(),
193 BoundaryAddressMultiple
);
195 Length
= PAGE_ROUND_UP(((ULONG_PTR
)&_bss_end__
)) -
196 PAGE_ROUND_UP(((ULONG_PTR
)&_init_end__
));
197 ParamLength
= ParamLength
- Length
;
198 DPRINT("Length %x\n",Length
);
199 BaseAddress
= (PVOID
)PAGE_ROUND_UP(((ULONG_PTR
)&_init_end__
));
200 DPRINT("BaseAddress %x\n",BaseAddress
);
203 * No need to lock the address space at this point since we are
204 * the only thread running.
206 MmCreateMemoryArea(NULL
,
207 MmGetKernelAddressSpace(),
215 BoundaryAddressMultiple
);
217 BaseAddress
= (PVOID
)PAGE_ROUND_UP(((ULONG_PTR
)&_bss_end__
));
218 Length
= LastKernelAddress
- (ULONG_PTR
)BaseAddress
;
219 MmCreateMemoryArea(NULL
,
220 MmGetKernelAddressSpace(),
228 BoundaryAddressMultiple
);
230 BaseAddress
= MiNonPagedPoolStart
;
231 MmCreateMemoryArea(NULL
,
232 MmGetKernelAddressSpace(),
235 MiNonPagedPoolLength
,
240 BoundaryAddressMultiple
);
242 BaseAddress
= MmPagedPoolBase
;
243 Status
= MmCreateMemoryArea(NULL
,
244 MmGetKernelAddressSpace(),
245 MEMORY_AREA_PAGED_POOL
,
252 BoundaryAddressMultiple
);
254 MmInitializePagedPool();
257 * Create the kernel mapping of the user/kernel shared memory.
259 BaseAddress
= (PVOID
)KI_USER_SHARED_DATA
;
261 MmCreateMemoryArea(NULL
,
262 MmGetKernelAddressSpace(),
270 BoundaryAddressMultiple
);
271 Status
= MmRequestPageMemoryConsumer(MC_NPPOOL
, TRUE
, &Pfn
);
272 MmSharedDataPagePhysicalAddress
.QuadPart
= Pfn
<< PAGE_SHIFT
;
273 Status
= MmCreateVirtualMapping(NULL
,
274 (PVOID
)KI_USER_SHARED_DATA
,
278 if (!NT_SUCCESS(Status
))
280 DbgPrint("Unable to create virtual mapping\n");
283 RtlZeroMemory(BaseAddress
, Length
);
288 MmInitializeMemoryConsumer(MC_USER
, MmTrimUserMemory
);
294 MmInit1(ULONG_PTR FirstKrnlPhysAddr
,
295 ULONG_PTR LastKrnlPhysAddr
,
296 ULONG_PTR LastKernelAddress
,
297 PADDRESS_RANGE BIOSMemoryMap
,
298 ULONG AddressRangeCount
,
301 * FUNCTION: Initalize memory managment
306 ULONG_PTR MappingAddress
;
308 DPRINT("MmInit1(FirstKrnlPhysAddr, %p, LastKrnlPhysAddr %p, LastKernelAddress %p)\n",
313 if ((BIOSMemoryMap
!= NULL
) && (AddressRangeCount
> 0))
315 // If we have a bios memory map, recalulate the memory size
317 for (i
= 0; i
< AddressRangeCount
; i
++)
319 if (BIOSMemoryMap
[i
].Type
== 1
320 && (BIOSMemoryMap
[i
].BaseAddrLow
+ BIOSMemoryMap
[i
].LengthLow
+ PAGE_SIZE
-1) / PAGE_SIZE
> last
)
322 last
= (BIOSMemoryMap
[i
].BaseAddrLow
+ BIOSMemoryMap
[i
].LengthLow
+ PAGE_SIZE
-1) / PAGE_SIZE
;
325 if ((last
- 256) * 4 > KeLoaderBlock
.MemHigher
)
327 KeLoaderBlock
.MemHigher
= (last
- 256) * 4;
331 if (KeLoaderBlock
.MemHigher
>= (MaxMem
- 1) * 1024)
333 KeLoaderBlock
.MemHigher
= (MaxMem
- 1) * 1024;
336 /* Set memory limits */
337 MmUserProbeAddress
= (ULONG_PTR
)MmSystemRangeStart
- 0x10000;
338 MmHighestUserAddress
= (PVOID
)(MmUserProbeAddress
- 1);
341 * Initialize memory managment statistics
343 MmStats
.NrTotalPages
= 0;
344 MmStats
.NrSystemPages
= 0;
345 MmStats
.NrUserPages
= 0;
346 MmStats
.NrReservedPages
= 0;
347 MmStats
.NrUserPages
= 0;
348 MmStats
.NrFreePages
= 0;
349 MmStats
.NrLockedPages
= 0;
350 MmStats
.PagingRequestsInLastMinute
= 0;
351 MmStats
.PagingRequestsInLastFiveMinutes
= 0;
352 MmStats
.PagingRequestsInLastFifteenMinutes
= 0;
355 * Free all pages not used for kernel memory
356 * (we assume the kernel occupies a continuous range of physical
359 DPRINT("first krnl %x\nlast krnl %x\n",FirstKrnlPhysAddr
,
363 * Free physical memory not used by the kernel
365 MmStats
.NrTotalPages
= KeLoaderBlock
.MemHigher
/4;
366 if (!MmStats
.NrTotalPages
)
368 DbgPrint("Memory not detected, default to 8 MB\n");
369 MmStats
.NrTotalPages
= 2048;
373 /* add 1MB for standard memory (not extended) */
374 MmStats
.NrTotalPages
+= 256;
377 MmStats
.NrTotalPages
+= 16;
381 * Initialize the kernel address space
383 MmInitializeKernelAddressSpace();
385 MmInitGlobalKernelPageDirectory();
387 DbgPrint("Used memory %dKb\n", (MmStats
.NrTotalPages
* PAGE_SIZE
) / 1024);
388 DPRINT1("Kernel Stack Limits. InitTop = 0x%x, Init = 0x%x\n", init_stack_top
, init_stack
);
390 LastKernelAddress
= (ULONG_PTR
)MmInitializePageList(
393 MmStats
.NrTotalPages
,
394 PAGE_ROUND_UP(LastKernelAddress
),
397 kernel_len
= LastKrnlPhysAddr
- FirstKrnlPhysAddr
;
403 /* In SMP mode we unmap the low memory pagetable in MmInit3.
404 The APIC needs the mapping of the first pages
405 while the processors are starting up.
406 We unmap all pages except page 2 and 3. */
407 for (MappingAddress
= 0;
408 MappingAddress
< 1024 * PAGE_SIZE
;
409 MappingAddress
+= PAGE_SIZE
)
411 if (MappingAddress
!= 2 * PAGE_SIZE
&&
412 MappingAddress
!= 3 * PAGE_SIZE
)
414 MmRawDeleteVirtualMapping((PVOID
)MappingAddress
);
418 MmDeletePageTable(NULL
, 0);
421 DPRINT("Invalidating between %x and %x\n",
422 LastKernelAddress
, KERNEL_BASE
+ 0x00600000);
423 for (MappingAddress
= LastKernelAddress
;
424 MappingAddress
< KERNEL_BASE
+ 0x00600000;
425 MappingAddress
+= PAGE_SIZE
)
427 MmRawDeleteVirtualMapping((PVOID
)MappingAddress
);
430 DPRINT("Almost done MmInit()\n");
432 * Intialize memory areas
434 MmInitVirtualMemory(LastKernelAddress
, kernel_len
);
436 MmInitializeMdlImplementation();
444 MmInitializeRmapList();
445 MmInitializePageOp();
446 MmInitSectionImplementation();
459 /* In SMP mode we can unmap the low memory
460 if all processors are started. */
461 MmDeletePageTable(NULL
, 0);
464 MmInitZeroPageThread();
465 MmCreatePhysicalMemorySection();
466 MiInitBalancerThread();
469 * Initialise the modified page writer.
473 /* FIXME: Read parameters from memory */
477 MiFreeInitMemoryPage(PVOID Context
, MEMORY_AREA
* MemoryArea
, PVOID Address
,
478 PFN_TYPE Page
, SWAPENTRY SwapEntry
,
481 ASSERT(SwapEntry
== 0);
484 MmReleasePageMemoryConsumer(MC_NPPOOL
, Page
);
490 MiFreeInitMemory(VOID
)
492 MmLockAddressSpace(MmGetKernelAddressSpace());
493 MmFreeMemoryAreaByPtr(MmGetKernelAddressSpace(),
494 (PVOID
)&_init_start__
,
495 MiFreeInitMemoryPage
,
497 MmUnlockAddressSpace(MmGetKernelAddressSpace());