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 MM_SYSTEMSIZE MmSystemSize
= MmSmallSystem
;
34 PHYSICAL_ADDRESS MmSharedDataPagePhysicalAddress
;
36 PVOID MiNonPagedPoolStart
;
37 ULONG MiNonPagedPoolLength
;
39 VOID INIT_FUNCTION NTAPI
MmInitVirtualMemory(ULONG_PTR LastKernelAddress
, ULONG KernelLength
);
41 #if defined (ALLOC_PRAGMA)
42 #pragma alloc_text(INIT, MmInitVirtualMemory)
43 #pragma alloc_text(INIT, MmInit1)
44 #pragma alloc_text(INIT, MmInit2)
45 #pragma alloc_text(INIT, MmInit3)
48 /* FUNCTIONS ****************************************************************/
53 BOOLEAN STDCALL
MmIsThisAnNtAsSystem(VOID
)
55 return(IsThisAnNtAsSystem
);
61 MM_SYSTEMSIZE STDCALL
MmQuerySystemSize(VOID
)
68 MiShutdownMemoryManager(VOID
)
74 MmInitVirtualMemory(ULONG_PTR LastKernelAddress
,
77 * FUNCTION: Intialize the memory areas list
79 * bp = Pointer to the boot parameters
80 * kernel_len = Length of the kernel
85 ULONG ParamLength
= KernelLength
;
87 PHYSICAL_ADDRESS BoundaryAddressMultiple
;
91 DPRINT("MmInitVirtualMemory(%x, %x)\n",LastKernelAddress
, KernelLength
);
93 BoundaryAddressMultiple
.QuadPart
= 0;
94 LastKernelAddress
= PAGE_ROUND_UP(LastKernelAddress
);
98 /* Start the paged and nonpaged pool at a 4MB boundary. */
99 MiNonPagedPoolStart
= (PVOID
)ROUND_UP((ULONG_PTR
)LastKernelAddress
+ PAGE_SIZE
, 0x400000);
100 MiNonPagedPoolLength
= MM_NONPAGED_POOL_SIZE
;
102 MmPagedPoolBase
= (PVOID
)ROUND_UP((ULONG_PTR
)MiNonPagedPoolStart
+ MiNonPagedPoolLength
+ PAGE_SIZE
, 0x400000);
103 MmPagedPoolSize
= MM_PAGED_POOL_SIZE
;
105 DPRINT("NonPagedPool %x - %x, PagedPool %x - %x\n", MiNonPagedPoolStart
, (ULONG_PTR
)MiNonPagedPoolStart
+ MiNonPagedPoolLength
- 1,
106 MmPagedPoolBase
, (ULONG_PTR
)MmPagedPoolBase
+ MmPagedPoolSize
- 1);
108 MiInitializeNonPagedPool();
111 * Setup the system area descriptor list
113 MiInitPageDirectoryMap();
115 BaseAddress
= (PVOID
)KPCR_BASE
;
116 MmCreateMemoryArea(MmGetKernelAddressSpace(),
119 PAGE_SIZE
* MAXIMUM_PROCESSORS
,
124 BoundaryAddressMultiple
);
126 /* Local APIC base */
127 BaseAddress
= (PVOID
)0xFEE00000;
128 MmCreateMemoryArea(MmGetKernelAddressSpace(),
136 BoundaryAddressMultiple
);
139 BaseAddress
= (PVOID
)0xFEC00000;
140 MmCreateMemoryArea(MmGetKernelAddressSpace(),
148 BoundaryAddressMultiple
);
150 BaseAddress
= (PVOID
)0xFF3A0000;
151 MmCreateMemoryArea(MmGetKernelAddressSpace(),
159 BoundaryAddressMultiple
);
161 extern unsigned int _image_base__
;
162 BaseAddress
= (PVOID
)&_image_base__
;
163 Length
= PAGE_ROUND_UP(((ULONG_PTR
)&_text_end__
)) - (ULONG_PTR
)&_image_base__
;
164 ParamLength
= ParamLength
- Length
;
167 * No need to lock the address space at this point since no
168 * other threads are running.
170 MmCreateMemoryArea(MmGetKernelAddressSpace(),
178 BoundaryAddressMultiple
);
180 BaseAddress
= (PVOID
)PAGE_ROUND_UP(((ULONG_PTR
)&_text_end__
));
181 ASSERT(BaseAddress
== (PVOID
)&_init_start__
);
182 Length
= PAGE_ROUND_UP(((ULONG_PTR
)&_init_end__
)) -
183 PAGE_ROUND_UP(((ULONG_PTR
)&_text_end__
));
184 ParamLength
= ParamLength
- Length
;
186 MmCreateMemoryArea(MmGetKernelAddressSpace(),
194 BoundaryAddressMultiple
);
196 Length
= PAGE_ROUND_UP(((ULONG_PTR
)&_bss_end__
)) -
197 PAGE_ROUND_UP(((ULONG_PTR
)&_init_end__
));
198 ParamLength
= ParamLength
- Length
;
199 DPRINT("Length %x\n",Length
);
200 BaseAddress
= (PVOID
)PAGE_ROUND_UP(((ULONG_PTR
)&_init_end__
));
201 DPRINT("BaseAddress %x\n",BaseAddress
);
204 * No need to lock the address space at this point since we are
205 * the only thread running.
207 MmCreateMemoryArea(MmGetKernelAddressSpace(),
215 BoundaryAddressMultiple
);
217 BaseAddress
= (PVOID
)PAGE_ROUND_UP(((ULONG_PTR
)&_bss_end__
));
218 Length
= LastKernelAddress
- (ULONG_PTR
)BaseAddress
;
219 MmCreateMemoryArea(MmGetKernelAddressSpace(),
227 BoundaryAddressMultiple
);
229 BaseAddress
= MiNonPagedPoolStart
;
230 MmCreateMemoryArea(MmGetKernelAddressSpace(),
233 MiNonPagedPoolLength
,
238 BoundaryAddressMultiple
);
240 BaseAddress
= MmPagedPoolBase
;
241 Status
= MmCreateMemoryArea(MmGetKernelAddressSpace(),
242 MEMORY_AREA_PAGED_POOL
,
249 BoundaryAddressMultiple
);
251 MmInitializePagedPool();
254 * Create the kernel mapping of the user/kernel shared memory.
256 BaseAddress
= (PVOID
)KI_USER_SHARED_DATA
;
258 MmCreateMemoryArea(MmGetKernelAddressSpace(),
266 BoundaryAddressMultiple
);
267 Status
= MmRequestPageMemoryConsumer(MC_NPPOOL
, TRUE
, &Pfn
);
268 MmSharedDataPagePhysicalAddress
.QuadPart
= Pfn
<< PAGE_SHIFT
;
269 Status
= MmCreateVirtualMapping(NULL
,
270 (PVOID
)KI_USER_SHARED_DATA
,
274 if (!NT_SUCCESS(Status
))
276 DbgPrint("Unable to create virtual mapping\n");
279 RtlZeroMemory(BaseAddress
, Length
);
284 MmInitializeMemoryConsumer(MC_USER
, MmTrimUserMemory
);
290 MmInit1(ULONG_PTR FirstKrnlPhysAddr
,
291 ULONG_PTR LastKrnlPhysAddr
,
292 ULONG_PTR LastKernelAddress
,
293 PADDRESS_RANGE BIOSMemoryMap
,
294 ULONG AddressRangeCount
,
297 * FUNCTION: Initalize memory managment
302 ULONG_PTR MappingAddress
;
303 PLDR_DATA_TABLE_ENTRY LdrEntry
;
305 DPRINT("MmInit1(FirstKrnlPhysAddr, %p, LastKrnlPhysAddr %p, LastKernelAddress %p)\n",
310 /* Set the page directory */
311 PsGetCurrentProcess()->Pcb
.DirectoryTableBase
.LowPart
= (ULONG
)MmGetPageDirectory();
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 > MmFreeLdrMemHigher
)
327 MmFreeLdrMemHigher
= (last
- 256) * 4;
332 if (!MmFreeLdrMemHigher
) MmFreeLdrMemHigher
= 65536;
333 if (!MmFreeLdrPageDirectoryEnd
) MmFreeLdrPageDirectoryEnd
= 0x40000;
334 if (!FirstKrnlPhysAddr
)
336 /* Get the kernel entry */
337 LdrEntry
= CONTAINING_RECORD(KeLoaderBlock
->LoadOrderListHead
.Flink
,
338 LDR_DATA_TABLE_ENTRY
,
341 /* Get the addresses */
342 FirstKrnlPhysAddr
= (ULONG_PTR
)LdrEntry
->DllBase
- KSEG0_BASE
;
344 /* FIXME: How do we get the last address? */
347 if (MmFreeLdrMemHigher
>= (MaxMem
- 1) * 1024)
349 MmFreeLdrMemHigher
= (MaxMem
- 1) * 1024;
352 /* Set memory limits */
353 MmUserProbeAddress
= (ULONG_PTR
)MmSystemRangeStart
- 0x10000;
354 MmHighestUserAddress
= (PVOID
)(MmUserProbeAddress
- 1);
357 * Initialize memory managment statistics
359 MmStats
.NrTotalPages
= 0;
360 MmStats
.NrSystemPages
= 0;
361 MmStats
.NrUserPages
= 0;
362 MmStats
.NrReservedPages
= 0;
363 MmStats
.NrUserPages
= 0;
364 MmStats
.NrFreePages
= 0;
365 MmStats
.NrLockedPages
= 0;
366 MmStats
.PagingRequestsInLastMinute
= 0;
367 MmStats
.PagingRequestsInLastFiveMinutes
= 0;
368 MmStats
.PagingRequestsInLastFifteenMinutes
= 0;
371 * Free all pages not used for kernel memory
372 * (we assume the kernel occupies a continuous range of physical
375 DPRINT("first krnl %x\nlast krnl %x\n",FirstKrnlPhysAddr
,
379 * Free physical memory not used by the kernel
381 MmStats
.NrTotalPages
= MmFreeLdrMemHigher
/4;
382 if (!MmStats
.NrTotalPages
)
384 DbgPrint("Memory not detected, default to 8 MB\n");
385 MmStats
.NrTotalPages
= 2048;
389 /* add 1MB for standard memory (not extended) */
390 MmStats
.NrTotalPages
+= 256;
393 MmStats
.NrTotalPages
+= 16;
397 * Initialize the kernel address space
399 MmInitializeKernelAddressSpace();
401 MmInitGlobalKernelPageDirectory();
403 DbgPrint("Used memory %dKb\n", (MmStats
.NrTotalPages
* PAGE_SIZE
) / 1024);
405 LastKernelAddress
= (ULONG_PTR
)MmInitializePageList(
408 MmStats
.NrTotalPages
,
409 PAGE_ROUND_UP(LastKernelAddress
),
412 kernel_len
= LastKrnlPhysAddr
- FirstKrnlPhysAddr
;
418 /* In SMP mode we unmap the low memory pagetable in MmInit3.
419 The APIC needs the mapping of the first pages
420 while the processors are starting up.
421 We unmap all pages except page 2 and 3. */
422 for (MappingAddress
= 0;
423 MappingAddress
< 1024 * PAGE_SIZE
;
424 MappingAddress
+= PAGE_SIZE
)
426 if (MappingAddress
!= 2 * PAGE_SIZE
&&
427 MappingAddress
!= 3 * PAGE_SIZE
)
429 MmRawDeleteVirtualMapping((PVOID
)MappingAddress
);
433 MmDeletePageTable(NULL
, 0);
436 DPRINT("Invalidating between %x and %x\n",
437 LastKernelAddress
, KSEG0_BASE
+ 0x00600000);
438 for (MappingAddress
= LastKernelAddress
;
439 MappingAddress
< KSEG0_BASE
+ 0x00600000;
440 MappingAddress
+= PAGE_SIZE
)
442 MmRawDeleteVirtualMapping((PVOID
)MappingAddress
);
445 DPRINT("Almost done MmInit()\n");
447 * Intialize memory areas
449 MmInitVirtualMemory(LastKernelAddress
, kernel_len
);
451 MmInitializeMdlImplementation();
459 MmInitializeRmapList();
460 MmInitializePageOp();
461 MmInitSectionImplementation();
474 /* In SMP mode we can unmap the low memory
475 if all processors are started. */
476 MmDeletePageTable(NULL
, 0);
479 MmCreatePhysicalMemorySection();
480 MiInitBalancerThread();
483 * Initialise the modified page writer.
487 /* FIXME: Read parameters from memory */
491 MiFreeInitMemoryPage(PVOID Context
, MEMORY_AREA
* MemoryArea
, PVOID Address
,
492 PFN_TYPE Page
, SWAPENTRY SwapEntry
,
495 ASSERT(SwapEntry
== 0);
498 MmReleasePageMemoryConsumer(MC_NPPOOL
, Page
);
504 MiFreeInitMemory(VOID
)
506 MmLockAddressSpace(MmGetKernelAddressSpace());
507 MmFreeMemoryAreaByPtr(MmGetKernelAddressSpace(),
508 (PVOID
)&_init_start__
,
509 MiFreeInitMemoryPage
,
511 MmUnlockAddressSpace(MmGetKernelAddressSpace());