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 VOID INIT_FUNCTION NTAPI
MmInitVirtualMemory(ULONG_PTR LastKernelAddress
, ULONG KernelLength
);
44 #if defined (ALLOC_PRAGMA)
45 #pragma alloc_text(INIT, MmInitVirtualMemory)
46 #pragma alloc_text(INIT, MmInit1)
47 #pragma alloc_text(INIT, MmInit2)
48 #pragma alloc_text(INIT, MmInit3)
51 /* FUNCTIONS ****************************************************************/
56 BOOLEAN STDCALL
MmIsThisAnNtAsSystem(VOID
)
58 return(IsThisAnNtAsSystem
);
64 MM_SYSTEM_SIZE STDCALL
MmQuerySystemSize(VOID
)
71 MiShutdownMemoryManager(VOID
)
77 MmInitVirtualMemory(ULONG_PTR LastKernelAddress
,
80 * FUNCTION: Intialize the memory areas list
82 * bp = Pointer to the boot parameters
83 * kernel_len = Length of the kernel
88 ULONG ParamLength
= KernelLength
;
90 PHYSICAL_ADDRESS BoundaryAddressMultiple
;
94 DPRINT("MmInitVirtualMemory(%x, %x)\n",LastKernelAddress
, KernelLength
);
96 BoundaryAddressMultiple
.QuadPart
= 0;
97 LastKernelAddress
= PAGE_ROUND_UP(LastKernelAddress
);
101 /* Start the paged and nonpaged pool at a 4MB boundary. */
102 MiNonPagedPoolStart
= (PVOID
)ROUND_UP((ULONG_PTR
)LastKernelAddress
+ PAGE_SIZE
, 0x400000);
103 MiNonPagedPoolLength
= MM_NONPAGED_POOL_SIZE
;
105 MmPagedPoolBase
= (PVOID
)ROUND_UP((ULONG_PTR
)MiNonPagedPoolStart
+ MiNonPagedPoolLength
+ PAGE_SIZE
, 0x400000);
106 MmPagedPoolSize
= MM_PAGED_POOL_SIZE
;
108 DPRINT("NonPagedPool %x - %x, PagedPool %x - %x\n", MiNonPagedPoolStart
, (ULONG_PTR
)MiNonPagedPoolStart
+ MiNonPagedPoolLength
- 1,
109 MmPagedPoolBase
, (ULONG_PTR
)MmPagedPoolBase
+ MmPagedPoolSize
- 1);
111 MiInitializeNonPagedPool();
114 * Setup the system area descriptor list
116 MiInitPageDirectoryMap();
118 BaseAddress
= (PVOID
)KPCR_BASE
;
119 MmCreateMemoryArea(MmGetKernelAddressSpace(),
122 PAGE_SIZE
* MAXIMUM_PROCESSORS
,
127 BoundaryAddressMultiple
);
129 /* Local APIC base */
130 BaseAddress
= (PVOID
)0xFEE00000;
131 MmCreateMemoryArea(MmGetKernelAddressSpace(),
139 BoundaryAddressMultiple
);
142 BaseAddress
= (PVOID
)0xFEC00000;
143 MmCreateMemoryArea(MmGetKernelAddressSpace(),
151 BoundaryAddressMultiple
);
153 BaseAddress
= (PVOID
)0xFF3A0000;
154 MmCreateMemoryArea(MmGetKernelAddressSpace(),
162 BoundaryAddressMultiple
);
164 BaseAddress
= (PVOID
)KERNEL_BASE
;
165 Length
= PAGE_ROUND_UP(((ULONG_PTR
)&_text_end__
)) - KERNEL_BASE
;
166 ParamLength
= ParamLength
- Length
;
169 * No need to lock the address space at this point since no
170 * other threads are running.
172 MmCreateMemoryArea(MmGetKernelAddressSpace(),
180 BoundaryAddressMultiple
);
182 BaseAddress
= (PVOID
)PAGE_ROUND_UP(((ULONG_PTR
)&_text_end__
));
183 ASSERT(BaseAddress
== (PVOID
)&_init_start__
);
184 Length
= PAGE_ROUND_UP(((ULONG_PTR
)&_init_end__
)) -
185 PAGE_ROUND_UP(((ULONG_PTR
)&_text_end__
));
186 ParamLength
= ParamLength
- Length
;
188 MmCreateMemoryArea(MmGetKernelAddressSpace(),
196 BoundaryAddressMultiple
);
198 Length
= PAGE_ROUND_UP(((ULONG_PTR
)&_bss_end__
)) -
199 PAGE_ROUND_UP(((ULONG_PTR
)&_init_end__
));
200 ParamLength
= ParamLength
- Length
;
201 DPRINT("Length %x\n",Length
);
202 BaseAddress
= (PVOID
)PAGE_ROUND_UP(((ULONG_PTR
)&_init_end__
));
203 DPRINT("BaseAddress %x\n",BaseAddress
);
206 * No need to lock the address space at this point since we are
207 * the only thread running.
209 MmCreateMemoryArea(MmGetKernelAddressSpace(),
217 BoundaryAddressMultiple
);
219 BaseAddress
= (PVOID
)PAGE_ROUND_UP(((ULONG_PTR
)&_bss_end__
));
220 Length
= LastKernelAddress
- (ULONG_PTR
)BaseAddress
;
221 MmCreateMemoryArea(MmGetKernelAddressSpace(),
229 BoundaryAddressMultiple
);
231 BaseAddress
= MiNonPagedPoolStart
;
232 MmCreateMemoryArea(MmGetKernelAddressSpace(),
235 MiNonPagedPoolLength
,
240 BoundaryAddressMultiple
);
242 BaseAddress
= MmPagedPoolBase
;
243 Status
= MmCreateMemoryArea(MmGetKernelAddressSpace(),
244 MEMORY_AREA_PAGED_POOL
,
251 BoundaryAddressMultiple
);
253 MmInitializePagedPool();
256 * Create the kernel mapping of the user/kernel shared memory.
258 BaseAddress
= (PVOID
)KI_USER_SHARED_DATA
;
260 MmCreateMemoryArea(MmGetKernelAddressSpace(),
268 BoundaryAddressMultiple
);
269 Status
= MmRequestPageMemoryConsumer(MC_NPPOOL
, TRUE
, &Pfn
);
270 MmSharedDataPagePhysicalAddress
.QuadPart
= Pfn
<< PAGE_SHIFT
;
271 Status
= MmCreateVirtualMapping(NULL
,
272 (PVOID
)KI_USER_SHARED_DATA
,
276 if (!NT_SUCCESS(Status
))
278 DbgPrint("Unable to create virtual mapping\n");
281 RtlZeroMemory(BaseAddress
, Length
);
286 MmInitializeMemoryConsumer(MC_USER
, MmTrimUserMemory
);
292 MmInit1(ULONG_PTR FirstKrnlPhysAddr
,
293 ULONG_PTR LastKrnlPhysAddr
,
294 ULONG_PTR LastKernelAddress
,
295 PADDRESS_RANGE BIOSMemoryMap
,
296 ULONG AddressRangeCount
,
299 * FUNCTION: Initalize memory managment
304 ULONG_PTR MappingAddress
;
306 DPRINT("MmInit1(FirstKrnlPhysAddr, %p, LastKrnlPhysAddr %p, LastKernelAddress %p)\n",
311 if ((BIOSMemoryMap
!= NULL
) && (AddressRangeCount
> 0))
313 // If we have a bios memory map, recalulate the memory size
315 for (i
= 0; i
< AddressRangeCount
; i
++)
317 if (BIOSMemoryMap
[i
].Type
== 1
318 && (BIOSMemoryMap
[i
].BaseAddrLow
+ BIOSMemoryMap
[i
].LengthLow
+ PAGE_SIZE
-1) / PAGE_SIZE
> last
)
320 last
= (BIOSMemoryMap
[i
].BaseAddrLow
+ BIOSMemoryMap
[i
].LengthLow
+ PAGE_SIZE
-1) / PAGE_SIZE
;
323 if ((last
- 256) * 4 > KeLoaderBlock
.MemHigher
)
325 KeLoaderBlock
.MemHigher
= (last
- 256) * 4;
329 if (KeLoaderBlock
.MemHigher
>= (MaxMem
- 1) * 1024)
331 KeLoaderBlock
.MemHigher
= (MaxMem
- 1) * 1024;
334 /* Set memory limits */
335 MmUserProbeAddress
= (ULONG_PTR
)MmSystemRangeStart
- 0x10000;
336 MmHighestUserAddress
= (PVOID
)(MmUserProbeAddress
- 1);
339 * Initialize memory managment statistics
341 MmStats
.NrTotalPages
= 0;
342 MmStats
.NrSystemPages
= 0;
343 MmStats
.NrUserPages
= 0;
344 MmStats
.NrReservedPages
= 0;
345 MmStats
.NrUserPages
= 0;
346 MmStats
.NrFreePages
= 0;
347 MmStats
.NrLockedPages
= 0;
348 MmStats
.PagingRequestsInLastMinute
= 0;
349 MmStats
.PagingRequestsInLastFiveMinutes
= 0;
350 MmStats
.PagingRequestsInLastFifteenMinutes
= 0;
353 * Free all pages not used for kernel memory
354 * (we assume the kernel occupies a continuous range of physical
357 DPRINT("first krnl %x\nlast krnl %x\n",FirstKrnlPhysAddr
,
361 * Free physical memory not used by the kernel
363 MmStats
.NrTotalPages
= KeLoaderBlock
.MemHigher
/4;
364 if (!MmStats
.NrTotalPages
)
366 DbgPrint("Memory not detected, default to 8 MB\n");
367 MmStats
.NrTotalPages
= 2048;
371 /* add 1MB for standard memory (not extended) */
372 MmStats
.NrTotalPages
+= 256;
375 MmStats
.NrTotalPages
+= 16;
379 * Initialize the kernel address space
381 MmInitializeKernelAddressSpace();
383 MmInitGlobalKernelPageDirectory();
385 DbgPrint("Used memory %dKb\n", (MmStats
.NrTotalPages
* PAGE_SIZE
) / 1024);
386 DPRINT1("Kernel Stack Limits. InitTop = 0x%x, Init = 0x%x\n", init_stack_top
, init_stack
);
388 LastKernelAddress
= (ULONG_PTR
)MmInitializePageList(
391 MmStats
.NrTotalPages
,
392 PAGE_ROUND_UP(LastKernelAddress
),
395 kernel_len
= LastKrnlPhysAddr
- FirstKrnlPhysAddr
;
401 /* In SMP mode we unmap the low memory pagetable in MmInit3.
402 The APIC needs the mapping of the first pages
403 while the processors are starting up.
404 We unmap all pages except page 2 and 3. */
405 for (MappingAddress
= 0;
406 MappingAddress
< 1024 * PAGE_SIZE
;
407 MappingAddress
+= PAGE_SIZE
)
409 if (MappingAddress
!= 2 * PAGE_SIZE
&&
410 MappingAddress
!= 3 * PAGE_SIZE
)
412 MmRawDeleteVirtualMapping((PVOID
)MappingAddress
);
416 MmDeletePageTable(NULL
, 0);
419 DPRINT("Invalidating between %x and %x\n",
420 LastKernelAddress
, KERNEL_BASE
+ 0x00600000);
421 for (MappingAddress
= LastKernelAddress
;
422 MappingAddress
< KERNEL_BASE
+ 0x00600000;
423 MappingAddress
+= PAGE_SIZE
)
425 MmRawDeleteVirtualMapping((PVOID
)MappingAddress
);
428 DPRINT("Almost done MmInit()\n");
430 * Intialize memory areas
432 MmInitVirtualMemory(LastKernelAddress
, kernel_len
);
434 MmInitializeMdlImplementation();
442 MmInitializeRmapList();
443 MmInitializePageOp();
444 MmInitSectionImplementation();
457 /* In SMP mode we can unmap the low memory
458 if all processors are started. */
459 MmDeletePageTable(NULL
, 0);
462 MmInitZeroPageThread();
463 MmCreatePhysicalMemorySection();
464 MiInitBalancerThread();
467 * Initialise the modified page writer.
471 /* FIXME: Read parameters from memory */
475 MiFreeInitMemoryPage(PVOID Context
, MEMORY_AREA
* MemoryArea
, PVOID Address
,
476 PFN_TYPE Page
, SWAPENTRY SwapEntry
,
479 ASSERT(SwapEntry
== 0);
482 MmReleasePageMemoryConsumer(MC_NPPOOL
, Page
);
488 MiFreeInitMemory(VOID
)
490 MmLockAddressSpace(MmGetKernelAddressSpace());
491 MmFreeMemoryAreaByPtr(MmGetKernelAddressSpace(),
492 (PVOID
)&_init_start__
,
493 MiFreeInitMemoryPage
,
495 MmUnlockAddressSpace(MmGetKernelAddressSpace());