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)
12 /* INCLUDES *****************************************************************/
16 #include <internal/debug.h>
18 /* GLOBALS *****************************************************************/
21 * Compiler defined symbols
23 extern unsigned int _text_start__
;
24 extern unsigned int _text_end__
;
26 extern unsigned int _init_start__
;
27 extern unsigned int _init_end__
;
29 extern unsigned int _bss_end__
;
32 static BOOLEAN IsThisAnNtAsSystem
= FALSE
;
33 static MM_SYSTEM_SIZE MmSystemSize
= MmSmallSystem
;
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
;
46 PHYSICAL_ADDRESS MmSharedDataPagePhysicalAddress
;
48 PVOID MiNonPagedPoolStart
;
49 ULONG MiNonPagedPoolLength
;
50 //PVOID MiKernelMapStart;
53 /* FUNCTIONS ****************************************************************/
58 BOOLEAN STDCALL
MmIsThisAnNtAsSystem(VOID
)
60 return(IsThisAnNtAsSystem
);
66 MM_SYSTEM_SIZE STDCALL
MmQuerySystemSize(VOID
)
71 VOID
MiShutdownMemoryManager(VOID
)
75 MmInitVirtualMemory(ULONG_PTR LastKernelAddress
,
78 * FUNCTION: Intialize the memory areas list
80 * bp = Pointer to the boot parameters
81 * kernel_len = Length of the kernel
86 ULONG ParamLength
= KernelLength
;
88 PHYSICAL_ADDRESS BoundaryAddressMultiple
;
91 DPRINT("MmInitVirtualMemory(%x, %x)\n",LastKernelAddress
, KernelLength
);
93 BoundaryAddressMultiple
.QuadPart
= 0;
94 LastKernelAddress
= PAGE_ROUND_UP(LastKernelAddress
);
98 MiNonPagedPoolStart
= (char*)LastKernelAddress
+ PAGE_SIZE
;
99 MiNonPagedPoolLength
= MM_NONPAGED_POOL_SIZE
;
101 MmPagedPoolBase
= (char*)MiNonPagedPoolStart
+ MiNonPagedPoolLength
+ PAGE_SIZE
;
102 MmPagedPoolSize
= MM_PAGED_POOL_SIZE
;
104 MiInitializeNonPagedPool();
107 * Setup the system area descriptor list
109 MiInitPageDirectoryMap();
111 BaseAddress
= (PVOID
)KPCR_BASE
;
112 MmCreateMemoryArea(NULL
,
113 MmGetKernelAddressSpace(),
116 PAGE_SIZE
* MAXIMUM_PROCESSORS
,
121 BoundaryAddressMultiple
);
123 BaseAddress
= (PVOID
)0xFF3A0000;
124 MmCreateMemoryArea(NULL
,
125 MmGetKernelAddressSpace(),
130 &kernel_mapped_vga_framebuffer_desc
,
133 BoundaryAddressMultiple
);
135 BaseAddress
= (PVOID
)KERNEL_BASE
;
136 Length
= PAGE_ROUND_UP(((ULONG_PTR
)&_text_end__
)) - KERNEL_BASE
;
137 ParamLength
= ParamLength
- Length
;
140 * No need to lock the address space at this point since no
141 * other threads are running.
143 MmCreateMemoryArea(NULL
,
144 MmGetKernelAddressSpace(),
152 BoundaryAddressMultiple
);
154 BaseAddress
= (PVOID
)PAGE_ROUND_UP(((ULONG_PTR
)&_text_end__
));
155 ASSERT(BaseAddress
== (PVOID
)&_init_start__
);
156 Length
= PAGE_ROUND_UP(((ULONG_PTR
)&_init_end__
)) -
157 PAGE_ROUND_UP(((ULONG_PTR
)&_text_end__
));
158 ParamLength
= ParamLength
- Length
;
160 MmCreateMemoryArea(NULL
,
161 MmGetKernelAddressSpace(),
169 BoundaryAddressMultiple
);
171 Length
= PAGE_ROUND_UP(((ULONG_PTR
)&_bss_end__
)) -
172 PAGE_ROUND_UP(((ULONG_PTR
)&_init_end__
));
173 ParamLength
= ParamLength
- Length
;
174 DPRINT("Length %x\n",Length
);
175 BaseAddress
= (PVOID
)PAGE_ROUND_UP(((ULONG_PTR
)&_init_end__
));
176 DPRINT("BaseAddress %x\n",BaseAddress
);
179 * No need to lock the address space at this point since we are
180 * the only thread running.
182 MmCreateMemoryArea(NULL
,
183 MmGetKernelAddressSpace(),
191 BoundaryAddressMultiple
);
193 BaseAddress
= (PVOID
)PAGE_ROUND_UP(((ULONG_PTR
)&_bss_end__
));
194 Length
= LastKernelAddress
- (ULONG_PTR
)BaseAddress
;
195 MmCreateMemoryArea(NULL
,
196 MmGetKernelAddressSpace(),
204 BoundaryAddressMultiple
);
206 BaseAddress
= MiNonPagedPoolStart
;
207 MmCreateMemoryArea(NULL
,
208 MmGetKernelAddressSpace(),
211 MiNonPagedPoolLength
,
216 BoundaryAddressMultiple
);
218 BaseAddress
= (PVOID
)MM_KERNEL_MAP_BASE
;
219 Status
= MmCreateMemoryArea(NULL
,
220 MmGetKernelAddressSpace(),
225 &MiKernelMapDescriptor
,
228 BoundaryAddressMultiple
);
230 BaseAddress
= MmPagedPoolBase
;
231 Status
= MmCreateMemoryArea(NULL
,
232 MmGetKernelAddressSpace(),
233 MEMORY_AREA_PAGED_POOL
,
237 &MiPagedPoolDescriptor
,
240 BoundaryAddressMultiple
);
242 MmInitializePagedPool();
245 * Create the kernel mapping of the user/kernel shared memory.
247 BaseAddress
= (PVOID
)KI_USER_SHARED_DATA
;
249 MmCreateMemoryArea(NULL
,
250 MmGetKernelAddressSpace(),
255 &kernel_shared_data_desc
,
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
,
266 if (!NT_SUCCESS(Status
))
268 DbgPrint("Unable to create virtual mapping\n");
271 RtlZeroMemory(BaseAddress
, Length
);
276 MmInitializeMemoryConsumer(MC_USER
, MmTrimUserMemory
);
280 MmInit1(ULONG_PTR FirstKrnlPhysAddr
,
281 ULONG_PTR LastKrnlPhysAddr
,
282 ULONG_PTR LastKernelAddress
,
283 PADDRESS_RANGE BIOSMemoryMap
,
284 ULONG AddressRangeCount
,
287 * FUNCTION: Initalize memory managment
292 ULONG_PTR MappingAddress
;
294 extern unsigned int unmap_me
, unmap_me2
, unmap_me3
;
296 extern unsigned int pagetable_start
, pagetable_end
;
298 DPRINT("MmInit1(FirstKrnlPhysAddr, %p, LastKrnlPhysAddr %p, LastKernelAddress %p)\n",
304 if ((BIOSMemoryMap
!= NULL
) && (AddressRangeCount
> 0))
306 // If we have a bios memory map, recalulate the memory size
308 for (i
= 0; i
< AddressRangeCount
; i
++)
310 if (BIOSMemoryMap
[i
].Type
== 1
311 && (BIOSMemoryMap
[i
].BaseAddrLow
+ BIOSMemoryMap
[i
].LengthLow
+ PAGE_SIZE
-1) / PAGE_SIZE
> last
)
313 last
= (BIOSMemoryMap
[i
].BaseAddrLow
+ BIOSMemoryMap
[i
].LengthLow
+ PAGE_SIZE
-1) / PAGE_SIZE
;
316 if ((last
- 256) * 4 > KeLoaderBlock
.MemHigher
)
318 KeLoaderBlock
.MemHigher
= (last
- 256) * 4;
322 if (KeLoaderBlock
.MemHigher
>= (MaxMem
- 1) * 1024)
324 KeLoaderBlock
.MemHigher
= (MaxMem
- 1) * 1024;
328 * FIXME: Set this based on the system command line
330 MmSystemRangeStart
= (PVOID
)KERNEL_BASE
; // 0xC0000000
331 MmUserProbeAddress
= 0x7fff0000;
332 MmHighestUserAddress
= (PVOID
)0x7ffeffff;
335 * Initialize memory managment statistics
337 MmStats
.NrTotalPages
= 0;
338 MmStats
.NrSystemPages
= 0;
339 MmStats
.NrUserPages
= 0;
340 MmStats
.NrReservedPages
= 0;
341 MmStats
.NrUserPages
= 0;
342 MmStats
.NrFreePages
= 0;
343 MmStats
.NrLockedPages
= 0;
344 MmStats
.PagingRequestsInLastMinute
= 0;
345 MmStats
.PagingRequestsInLastFiveMinutes
= 0;
346 MmStats
.PagingRequestsInLastFifteenMinutes
= 0;
349 * Free all pages not used for kernel memory
350 * (we assume the kernel occupies a continuous range of physical
353 DPRINT("first krnl %x\nlast krnl %x\n",FirstKrnlPhysAddr
,
357 * Free physical memory not used by the kernel
359 MmStats
.NrTotalPages
= KeLoaderBlock
.MemHigher
/4;
360 if (!MmStats
.NrTotalPages
)
362 DbgPrint("Memory not detected, default to 8 MB\n");
363 MmStats
.NrTotalPages
= 2048;
367 /* add 1MB for standard memory (not extended) */
368 MmStats
.NrTotalPages
+= 256;
371 MmStats
.NrTotalPages
+= 16;
375 * Initialize the kernel address space
377 MmInitializeKernelAddressSpace();
379 MmInitGlobalKernelPageDirectory();
381 DbgPrint("Used memory %dKb\n", (MmStats
.NrTotalPages
* PAGE_SIZE
) / 1024);
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 in MmInit3.
397 The APIC needs the mapping of the first pages
398 while the processors are starting up. */
399 MmDeletePageTable(NULL
, 0);
404 DPRINT("Invalidating between %x and %x\n",
405 LastKernelAddress
, KERNEL_BASE
+ 0x00600000);
406 for (MappingAddress
= LastKernelAddress
;
407 MappingAddress
< KERNEL_BASE
+ 0x00600000;
408 MappingAddress
+= PAGE_SIZE
)
410 MmRawDeleteVirtualMapping((PVOID
)MappingAddress
);
413 for (MappingAddress
= (ULONG_PTR
)&pagetable_start
;
414 MappingAddress
< (ULONG_PTR
)&pagetable_end
;
415 MappingAddress
+= PAGE_SIZE
)
417 MmDeleteVirtualMapping(NULL
, (PVOID
)MappingAddress
, FALSE
, NULL
, NULL
);
420 DPRINT("Almost done MmInit()\n");
422 /* FIXME: This is broken in SMP mode */
423 MmDeleteVirtualMapping(NULL
, (PVOID
)&unmap_me
, TRUE
, NULL
, NULL
);
424 MmDeleteVirtualMapping(NULL
, (PVOID
)&unmap_me2
, TRUE
, NULL
, NULL
);
425 MmDeleteVirtualMapping(NULL
, (PVOID
)&unmap_me3
, TRUE
, NULL
, NULL
);
428 * Intialize memory areas
430 MmInitVirtualMemory(LastKernelAddress
, kernel_len
);
432 MmInitializeMdlImplementation();
438 MmInitializeRmapList();
439 MmInitializePageOp();
440 MmInitSectionImplementation();
451 /* In SMP mode we can unmap the low memory
452 if all processors are started. */
453 MmDeletePageTable(NULL
, 0);
456 MmInitZeroPageThread();
457 MmCreatePhysicalMemorySection();
458 MiInitBalancerThread();
461 * Initialise the modified page writer.
465 /* FIXME: Read parameters from memory */
469 MiFreeInitMemoryPage(PVOID Context
, MEMORY_AREA
* MemoryArea
, PVOID Address
,
470 PFN_TYPE Page
, SWAPENTRY SwapEntry
,
473 ASSERT(SwapEntry
== 0);
476 MmReleasePageMemoryConsumer(MC_NPPOOL
, Page
);
481 MiFreeInitMemory(VOID
)
483 MmLockAddressSpace(MmGetKernelAddressSpace());
484 MmFreeMemoryAreaByPtr(MmGetKernelAddressSpace(),
485 (PVOID
)&_init_start__
,
486 MiFreeInitMemoryPage
,
488 MmUnlockAddressSpace(MmGetKernelAddressSpace());