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
)
72 VOID
MiShutdownMemoryManager(VOID
)
76 MmInitVirtualMemory(ULONG_PTR LastKernelAddress
,
79 * FUNCTION: Intialize the memory areas list
81 * bp = Pointer to the boot parameters
82 * kernel_len = Length of the kernel
87 ULONG ParamLength
= KernelLength
;
89 PHYSICAL_ADDRESS BoundaryAddressMultiple
;
92 DPRINT("MmInitVirtualMemory(%x, %x)\n",LastKernelAddress
, KernelLength
);
94 BoundaryAddressMultiple
.QuadPart
= 0;
95 LastKernelAddress
= PAGE_ROUND_UP(LastKernelAddress
);
99 MiNonPagedPoolStart
= (char*)LastKernelAddress
+ PAGE_SIZE
;
100 MiNonPagedPoolLength
= MM_NONPAGED_POOL_SIZE
;
102 MmPagedPoolBase
= (char*)MiNonPagedPoolStart
+ MiNonPagedPoolLength
+ PAGE_SIZE
;
103 MmPagedPoolSize
= MM_PAGED_POOL_SIZE
;
105 MiInitializeNonPagedPool();
108 * Setup the system area descriptor list
110 MiInitPageDirectoryMap();
112 BaseAddress
= (PVOID
)KPCR_BASE
;
113 MmCreateMemoryArea(NULL
,
114 MmGetKernelAddressSpace(),
117 PAGE_SIZE
* MAXIMUM_PROCESSORS
,
122 BoundaryAddressMultiple
);
124 BaseAddress
= (PVOID
)0xFF3A0000;
125 MmCreateMemoryArea(NULL
,
126 MmGetKernelAddressSpace(),
131 &kernel_mapped_vga_framebuffer_desc
,
134 BoundaryAddressMultiple
);
136 BaseAddress
= (PVOID
)KERNEL_BASE
;
137 Length
= PAGE_ROUND_UP(((ULONG_PTR
)&_text_end__
)) - KERNEL_BASE
;
138 ParamLength
= ParamLength
- Length
;
141 * No need to lock the address space at this point since no
142 * other threads are running.
144 MmCreateMemoryArea(NULL
,
145 MmGetKernelAddressSpace(),
153 BoundaryAddressMultiple
);
155 BaseAddress
= (PVOID
)PAGE_ROUND_UP(((ULONG_PTR
)&_text_end__
));
156 ASSERT(BaseAddress
== (PVOID
)&_init_start__
);
157 Length
= PAGE_ROUND_UP(((ULONG_PTR
)&_init_end__
)) -
158 PAGE_ROUND_UP(((ULONG_PTR
)&_text_end__
));
159 ParamLength
= ParamLength
- Length
;
161 MmCreateMemoryArea(NULL
,
162 MmGetKernelAddressSpace(),
170 BoundaryAddressMultiple
);
172 Length
= PAGE_ROUND_UP(((ULONG_PTR
)&_bss_end__
)) -
173 PAGE_ROUND_UP(((ULONG_PTR
)&_init_end__
));
174 ParamLength
= ParamLength
- Length
;
175 DPRINT("Length %x\n",Length
);
176 BaseAddress
= (PVOID
)PAGE_ROUND_UP(((ULONG_PTR
)&_init_end__
));
177 DPRINT("BaseAddress %x\n",BaseAddress
);
180 * No need to lock the address space at this point since we are
181 * the only thread running.
183 MmCreateMemoryArea(NULL
,
184 MmGetKernelAddressSpace(),
192 BoundaryAddressMultiple
);
194 BaseAddress
= (PVOID
)PAGE_ROUND_UP(((ULONG_PTR
)&_bss_end__
));
195 Length
= LastKernelAddress
- (ULONG_PTR
)BaseAddress
;
196 MmCreateMemoryArea(NULL
,
197 MmGetKernelAddressSpace(),
205 BoundaryAddressMultiple
);
207 BaseAddress
= MiNonPagedPoolStart
;
208 MmCreateMemoryArea(NULL
,
209 MmGetKernelAddressSpace(),
212 MiNonPagedPoolLength
,
217 BoundaryAddressMultiple
);
219 BaseAddress
= (PVOID
)MM_KERNEL_MAP_BASE
;
220 Status
= MmCreateMemoryArea(NULL
,
221 MmGetKernelAddressSpace(),
226 &MiKernelMapDescriptor
,
229 BoundaryAddressMultiple
);
231 BaseAddress
= MmPagedPoolBase
;
232 Status
= MmCreateMemoryArea(NULL
,
233 MmGetKernelAddressSpace(),
234 MEMORY_AREA_PAGED_POOL
,
238 &MiPagedPoolDescriptor
,
241 BoundaryAddressMultiple
);
243 MmInitializePagedPool();
246 * Create the kernel mapping of the user/kernel shared memory.
248 BaseAddress
= (PVOID
)KI_USER_SHARED_DATA
;
250 MmCreateMemoryArea(NULL
,
251 MmGetKernelAddressSpace(),
256 &kernel_shared_data_desc
,
259 BoundaryAddressMultiple
);
260 Status
= MmRequestPageMemoryConsumer(MC_NPPOOL
, TRUE
, &Pfn
);
261 MmSharedDataPagePhysicalAddress
.QuadPart
= Pfn
<< PAGE_SHIFT
;
262 Status
= MmCreateVirtualMapping(NULL
,
263 (PVOID
)KI_USER_SHARED_DATA
,
267 if (!NT_SUCCESS(Status
))
269 DbgPrint("Unable to create virtual mapping\n");
272 RtlZeroMemory(BaseAddress
, Length
);
277 MmInitializeMemoryConsumer(MC_USER
, MmTrimUserMemory
);
281 MmInit1(ULONG_PTR FirstKrnlPhysAddr
,
282 ULONG_PTR LastKrnlPhysAddr
,
283 ULONG_PTR LastKernelAddress
,
284 PADDRESS_RANGE BIOSMemoryMap
,
285 ULONG AddressRangeCount
,
288 * FUNCTION: Initalize memory managment
293 ULONG_PTR MappingAddress
;
295 DPRINT("MmInit1(FirstKrnlPhysAddr, %p, LastKrnlPhysAddr %p, LastKernelAddress %p)\n",
300 if ((BIOSMemoryMap
!= NULL
) && (AddressRangeCount
> 0))
302 // If we have a bios memory map, recalulate the memory size
304 for (i
= 0; i
< AddressRangeCount
; i
++)
306 if (BIOSMemoryMap
[i
].Type
== 1
307 && (BIOSMemoryMap
[i
].BaseAddrLow
+ BIOSMemoryMap
[i
].LengthLow
+ PAGE_SIZE
-1) / PAGE_SIZE
> last
)
309 last
= (BIOSMemoryMap
[i
].BaseAddrLow
+ BIOSMemoryMap
[i
].LengthLow
+ PAGE_SIZE
-1) / PAGE_SIZE
;
312 if ((last
- 256) * 4 > KeLoaderBlock
.MemHigher
)
314 KeLoaderBlock
.MemHigher
= (last
- 256) * 4;
318 if (KeLoaderBlock
.MemHigher
>= (MaxMem
- 1) * 1024)
320 KeLoaderBlock
.MemHigher
= (MaxMem
- 1) * 1024;
323 /* Set memory limits */
324 MmUserProbeAddress
= 0x7fff0000;
325 MmHighestUserAddress
= (PVOID
)0x7ffeffff;
328 * Initialize memory managment statistics
330 MmStats
.NrTotalPages
= 0;
331 MmStats
.NrSystemPages
= 0;
332 MmStats
.NrUserPages
= 0;
333 MmStats
.NrReservedPages
= 0;
334 MmStats
.NrUserPages
= 0;
335 MmStats
.NrFreePages
= 0;
336 MmStats
.NrLockedPages
= 0;
337 MmStats
.PagingRequestsInLastMinute
= 0;
338 MmStats
.PagingRequestsInLastFiveMinutes
= 0;
339 MmStats
.PagingRequestsInLastFifteenMinutes
= 0;
342 * Free all pages not used for kernel memory
343 * (we assume the kernel occupies a continuous range of physical
346 DPRINT("first krnl %x\nlast krnl %x\n",FirstKrnlPhysAddr
,
350 * Free physical memory not used by the kernel
352 MmStats
.NrTotalPages
= KeLoaderBlock
.MemHigher
/4;
353 if (!MmStats
.NrTotalPages
)
355 DbgPrint("Memory not detected, default to 8 MB\n");
356 MmStats
.NrTotalPages
= 2048;
360 /* add 1MB for standard memory (not extended) */
361 MmStats
.NrTotalPages
+= 256;
364 MmStats
.NrTotalPages
+= 16;
368 * Initialize the kernel address space
370 MmInitializeKernelAddressSpace();
372 MmInitGlobalKernelPageDirectory();
374 DbgPrint("Used memory %dKb\n", (MmStats
.NrTotalPages
* PAGE_SIZE
) / 1024);
375 DPRINT1("Kernel Stack Limits. InitTop = 0x%x, Init = 0x%x\n", init_stack_top
, init_stack
);
377 LastKernelAddress
= (ULONG_PTR
)MmInitializePageList(
380 MmStats
.NrTotalPages
,
381 PAGE_ROUND_UP(LastKernelAddress
),
384 kernel_len
= LastKrnlPhysAddr
- FirstKrnlPhysAddr
;
390 /* In SMP mode we unmap the low memory pagetable in MmInit3.
391 The APIC needs the mapping of the first pages
392 while the processors are starting up.
393 We unmap all pages except page 2 and 3. */
394 for (MappingAddress
= 0;
395 MappingAddress
< 1024 * PAGE_SIZE
;
396 MappingAddress
+= PAGE_SIZE
)
398 if (MappingAddress
!= 2 * PAGE_SIZE
&&
399 MappingAddress
!= 3 * PAGE_SIZE
)
401 MmRawDeleteVirtualMapping((PVOID
)MappingAddress
);
405 MmDeletePageTable(NULL
, 0);
408 DPRINT("Invalidating between %x and %x\n",
409 LastKernelAddress
, KERNEL_BASE
+ 0x00600000);
410 for (MappingAddress
= LastKernelAddress
;
411 MappingAddress
< KERNEL_BASE
+ 0x00600000;
412 MappingAddress
+= PAGE_SIZE
)
414 MmRawDeleteVirtualMapping((PVOID
)MappingAddress
);
417 DPRINT("Almost done MmInit()\n");
419 * Intialize memory areas
421 MmInitVirtualMemory(LastKernelAddress
, kernel_len
);
423 MmInitializeMdlImplementation();
429 MmInitializeRmapList();
430 MmInitializePageOp();
431 MmInitSectionImplementation();
442 /* In SMP mode we can unmap the low memory
443 if all processors are started. */
444 MmDeletePageTable(NULL
, 0);
447 MmInitZeroPageThread();
448 MmCreatePhysicalMemorySection();
449 MiInitBalancerThread();
452 * Initialise the modified page writer.
456 /* FIXME: Read parameters from memory */
460 MiFreeInitMemoryPage(PVOID Context
, MEMORY_AREA
* MemoryArea
, PVOID Address
,
461 PFN_TYPE Page
, SWAPENTRY SwapEntry
,
464 ASSERT(SwapEntry
== 0);
467 MmReleasePageMemoryConsumer(MC_NPPOOL
, Page
);
472 MiFreeInitMemory(VOID
)
474 MmLockAddressSpace(MmGetKernelAddressSpace());
475 MmFreeMemoryAreaByPtr(MmGetKernelAddressSpace(),
476 (PVOID
)&_init_start__
,
477 MiFreeInitMemoryPage
,
479 MmUnlockAddressSpace(MmGetKernelAddressSpace());