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 static MEMORY_AREA
* kernel_text_desc
= NULL
;
35 static MEMORY_AREA
* kernel_init_desc
= NULL
;
36 static MEMORY_AREA
* kernel_kpcr_desc
= NULL
;
37 static MEMORY_AREA
* kernel_data_desc
= NULL
;
38 static MEMORY_AREA
* kernel_param_desc
= NULL
;
39 static MEMORY_AREA
* kernel_pool_desc
= NULL
;
40 static MEMORY_AREA
* kernel_shared_data_desc
= NULL
;
41 static MEMORY_AREA
* kernel_mapped_vga_framebuffer_desc
= NULL
;
42 static MEMORY_AREA
* MiKernelMapDescriptor
= NULL
;
43 static MEMORY_AREA
* MiPagedPoolDescriptor
= NULL
;
45 PHYSICAL_ADDRESS MmSharedDataPagePhysicalAddress
;
47 PVOID MiNonPagedPoolStart
;
48 ULONG MiNonPagedPoolLength
;
49 //PVOID MiKernelMapStart;
51 extern ULONG init_stack
;
52 extern ULONG init_stack_top
;
54 /* FUNCTIONS ****************************************************************/
59 BOOLEAN STDCALL
MmIsThisAnNtAsSystem(VOID
)
61 return(IsThisAnNtAsSystem
);
67 MM_SYSTEM_SIZE STDCALL
MmQuerySystemSize(VOID
)
74 MiShutdownMemoryManager(VOID
)
80 MmInitVirtualMemory(ULONG_PTR LastKernelAddress
,
83 * FUNCTION: Intialize the memory areas list
85 * bp = Pointer to the boot parameters
86 * kernel_len = Length of the kernel
91 ULONG ParamLength
= KernelLength
;
93 PHYSICAL_ADDRESS BoundaryAddressMultiple
;
96 DPRINT("MmInitVirtualMemory(%x, %x)\n",LastKernelAddress
, KernelLength
);
98 BoundaryAddressMultiple
.QuadPart
= 0;
99 LastKernelAddress
= PAGE_ROUND_UP(LastKernelAddress
);
103 MiNonPagedPoolStart
= (char*)LastKernelAddress
+ PAGE_SIZE
;
104 MiNonPagedPoolLength
= MM_NONPAGED_POOL_SIZE
;
106 MmPagedPoolBase
= (char*)MiNonPagedPoolStart
+ MiNonPagedPoolLength
+ PAGE_SIZE
;
107 MmPagedPoolSize
= MM_PAGED_POOL_SIZE
;
109 MiInitializeNonPagedPool();
112 * Setup the system area descriptor list
114 MiInitPageDirectoryMap();
116 BaseAddress
= (PVOID
)KPCR_BASE
;
117 MmCreateMemoryArea(NULL
,
118 MmGetKernelAddressSpace(),
121 PAGE_SIZE
* MAXIMUM_PROCESSORS
,
126 BoundaryAddressMultiple
);
128 BaseAddress
= (PVOID
)0xFF3A0000;
129 MmCreateMemoryArea(NULL
,
130 MmGetKernelAddressSpace(),
135 &kernel_mapped_vga_framebuffer_desc
,
138 BoundaryAddressMultiple
);
140 BaseAddress
= (PVOID
)KERNEL_BASE
;
141 Length
= PAGE_ROUND_UP(((ULONG_PTR
)&_text_end__
)) - KERNEL_BASE
;
142 ParamLength
= ParamLength
- Length
;
145 * No need to lock the address space at this point since no
146 * other threads are running.
148 MmCreateMemoryArea(NULL
,
149 MmGetKernelAddressSpace(),
157 BoundaryAddressMultiple
);
159 BaseAddress
= (PVOID
)PAGE_ROUND_UP(((ULONG_PTR
)&_text_end__
));
160 ASSERT(BaseAddress
== (PVOID
)&_init_start__
);
161 Length
= PAGE_ROUND_UP(((ULONG_PTR
)&_init_end__
)) -
162 PAGE_ROUND_UP(((ULONG_PTR
)&_text_end__
));
163 ParamLength
= ParamLength
- Length
;
165 MmCreateMemoryArea(NULL
,
166 MmGetKernelAddressSpace(),
174 BoundaryAddressMultiple
);
176 Length
= PAGE_ROUND_UP(((ULONG_PTR
)&_bss_end__
)) -
177 PAGE_ROUND_UP(((ULONG_PTR
)&_init_end__
));
178 ParamLength
= ParamLength
- Length
;
179 DPRINT("Length %x\n",Length
);
180 BaseAddress
= (PVOID
)PAGE_ROUND_UP(((ULONG_PTR
)&_init_end__
));
181 DPRINT("BaseAddress %x\n",BaseAddress
);
184 * No need to lock the address space at this point since we are
185 * the only thread running.
187 MmCreateMemoryArea(NULL
,
188 MmGetKernelAddressSpace(),
196 BoundaryAddressMultiple
);
198 BaseAddress
= (PVOID
)PAGE_ROUND_UP(((ULONG_PTR
)&_bss_end__
));
199 Length
= LastKernelAddress
- (ULONG_PTR
)BaseAddress
;
200 MmCreateMemoryArea(NULL
,
201 MmGetKernelAddressSpace(),
209 BoundaryAddressMultiple
);
211 BaseAddress
= MiNonPagedPoolStart
;
212 MmCreateMemoryArea(NULL
,
213 MmGetKernelAddressSpace(),
216 MiNonPagedPoolLength
,
221 BoundaryAddressMultiple
);
223 BaseAddress
= (PVOID
)MM_KERNEL_MAP_BASE
;
224 Status
= MmCreateMemoryArea(NULL
,
225 MmGetKernelAddressSpace(),
230 &MiKernelMapDescriptor
,
233 BoundaryAddressMultiple
);
235 BaseAddress
= MmPagedPoolBase
;
236 Status
= MmCreateMemoryArea(NULL
,
237 MmGetKernelAddressSpace(),
238 MEMORY_AREA_PAGED_POOL
,
242 &MiPagedPoolDescriptor
,
245 BoundaryAddressMultiple
);
247 MmInitializePagedPool();
250 * Create the kernel mapping of the user/kernel shared memory.
252 BaseAddress
= (PVOID
)KI_USER_SHARED_DATA
;
254 MmCreateMemoryArea(NULL
,
255 MmGetKernelAddressSpace(),
260 &kernel_shared_data_desc
,
263 BoundaryAddressMultiple
);
264 Status
= MmRequestPageMemoryConsumer(MC_NPPOOL
, TRUE
, &Pfn
);
265 MmSharedDataPagePhysicalAddress
.QuadPart
= Pfn
<< PAGE_SHIFT
;
266 Status
= MmCreateVirtualMapping(NULL
,
267 (PVOID
)KI_USER_SHARED_DATA
,
271 if (!NT_SUCCESS(Status
))
273 DbgPrint("Unable to create virtual mapping\n");
276 RtlZeroMemory(BaseAddress
, Length
);
281 MmInitializeMemoryConsumer(MC_USER
, MmTrimUserMemory
);
287 MmInit1(ULONG_PTR FirstKrnlPhysAddr
,
288 ULONG_PTR LastKrnlPhysAddr
,
289 ULONG_PTR LastKernelAddress
,
290 PADDRESS_RANGE BIOSMemoryMap
,
291 ULONG AddressRangeCount
,
294 * FUNCTION: Initalize memory managment
299 ULONG_PTR MappingAddress
;
301 DPRINT("MmInit1(FirstKrnlPhysAddr, %p, LastKrnlPhysAddr %p, LastKernelAddress %p)\n",
306 if ((BIOSMemoryMap
!= NULL
) && (AddressRangeCount
> 0))
308 // If we have a bios memory map, recalulate the memory size
310 for (i
= 0; i
< AddressRangeCount
; i
++)
312 if (BIOSMemoryMap
[i
].Type
== 1
313 && (BIOSMemoryMap
[i
].BaseAddrLow
+ BIOSMemoryMap
[i
].LengthLow
+ PAGE_SIZE
-1) / PAGE_SIZE
> last
)
315 last
= (BIOSMemoryMap
[i
].BaseAddrLow
+ BIOSMemoryMap
[i
].LengthLow
+ PAGE_SIZE
-1) / PAGE_SIZE
;
318 if ((last
- 256) * 4 > KeLoaderBlock
.MemHigher
)
320 KeLoaderBlock
.MemHigher
= (last
- 256) * 4;
324 if (KeLoaderBlock
.MemHigher
>= (MaxMem
- 1) * 1024)
326 KeLoaderBlock
.MemHigher
= (MaxMem
- 1) * 1024;
329 /* Set memory limits */
330 MmUserProbeAddress
= (ULONG_PTR
)MmSystemRangeStart
- 0x10000;
331 MmHighestUserAddress
= (PVOID
)(MmUserProbeAddress
- 1);
334 * Initialize memory managment statistics
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;
348 * Free all pages not used for kernel memory
349 * (we assume the kernel occupies a continuous range of physical
352 DPRINT("first krnl %x\nlast krnl %x\n",FirstKrnlPhysAddr
,
356 * Free physical memory not used by the kernel
358 MmStats
.NrTotalPages
= KeLoaderBlock
.MemHigher
/4;
359 if (!MmStats
.NrTotalPages
)
361 DbgPrint("Memory not detected, default to 8 MB\n");
362 MmStats
.NrTotalPages
= 2048;
366 /* add 1MB for standard memory (not extended) */
367 MmStats
.NrTotalPages
+= 256;
370 MmStats
.NrTotalPages
+= 16;
374 * Initialize the kernel address space
376 MmInitializeKernelAddressSpace();
378 MmInitGlobalKernelPageDirectory();
380 DbgPrint("Used memory %dKb\n", (MmStats
.NrTotalPages
* PAGE_SIZE
) / 1024);
381 DPRINT1("Kernel Stack Limits. InitTop = 0x%x, Init = 0x%x\n", init_stack_top
, init_stack
);
383 LastKernelAddress
= (ULONG_PTR
)MmInitializePageList(
386 MmStats
.NrTotalPages
,
387 PAGE_ROUND_UP(LastKernelAddress
),
390 kernel_len
= LastKrnlPhysAddr
- FirstKrnlPhysAddr
;
396 /* In SMP mode we unmap the low memory pagetable in MmInit3.
397 The APIC needs the mapping of the first pages
398 while the processors are starting up.
399 We unmap all pages except page 2 and 3. */
400 for (MappingAddress
= 0;
401 MappingAddress
< 1024 * PAGE_SIZE
;
402 MappingAddress
+= PAGE_SIZE
)
404 if (MappingAddress
!= 2 * PAGE_SIZE
&&
405 MappingAddress
!= 3 * PAGE_SIZE
)
407 MmRawDeleteVirtualMapping((PVOID
)MappingAddress
);
411 MmDeletePageTable(NULL
, 0);
414 DPRINT("Invalidating between %x and %x\n",
415 LastKernelAddress
, KERNEL_BASE
+ 0x00600000);
416 for (MappingAddress
= LastKernelAddress
;
417 MappingAddress
< KERNEL_BASE
+ 0x00600000;
418 MappingAddress
+= PAGE_SIZE
)
420 MmRawDeleteVirtualMapping((PVOID
)MappingAddress
);
423 DPRINT("Almost done MmInit()\n");
425 * Intialize memory areas
427 MmInitVirtualMemory(LastKernelAddress
, kernel_len
);
429 MmInitializeMdlImplementation();
437 MmInitializeRmapList();
438 MmInitializePageOp();
439 MmInitSectionImplementation();
452 /* In SMP mode we can unmap the low memory
453 if all processors are started. */
454 MmDeletePageTable(NULL
, 0);
457 MmInitZeroPageThread();
458 MmCreatePhysicalMemorySection();
459 MiInitBalancerThread();
462 * Initialise the modified page writer.
466 /* FIXME: Read parameters from memory */
470 MiFreeInitMemoryPage(PVOID Context
, MEMORY_AREA
* MemoryArea
, PVOID Address
,
471 PFN_TYPE Page
, SWAPENTRY SwapEntry
,
474 ASSERT(SwapEntry
== 0);
477 MmReleasePageMemoryConsumer(MC_NPPOOL
, Page
);
483 MiFreeInitMemory(VOID
)
485 MmLockAddressSpace(MmGetKernelAddressSpace());
486 MmFreeMemoryAreaByPtr(MmGetKernelAddressSpace(),
487 (PVOID
)&_init_start__
,
488 MiFreeInitMemoryPage
,
490 MmUnlockAddressSpace(MmGetKernelAddressSpace());