1 /* $Id: mminit.c,v 1.71 2004/10/22 20:38:22 ekohl Exp $
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 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
)&_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
)&_text_end__
));
155 ASSERT(BaseAddress
== (PVOID
)&_init_start__
);
156 Length
= PAGE_ROUND_UP(((ULONG
)&_init_end__
)) -
157 PAGE_ROUND_UP(((ULONG
)&_text_end__
));
158 ParamLength
= ParamLength
- Length
;
160 MmCreateMemoryArea(NULL
,
161 MmGetKernelAddressSpace(),
169 BoundaryAddressMultiple
);
171 Length
= PAGE_ROUND_UP(((ULONG
)&_bss_end__
)) -
172 PAGE_ROUND_UP(((ULONG
)&_init_end__
));
173 ParamLength
= ParamLength
- Length
;
174 DPRINT("Length %x\n",Length
);
175 BaseAddress
= (PVOID
)PAGE_ROUND_UP(((ULONG
)&_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
)&_bss_end__
));
194 Length
= LastKernelAddress
- (ULONG
)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 FirstKrnlPhysAddr
,
281 ULONG LastKrnlPhysAddr
,
282 ULONG LastKernelAddress
,
283 PADDRESS_RANGE BIOSMemoryMap
,
284 ULONG AddressRangeCount
,
287 * FUNCTION: Initalize memory managment
294 extern unsigned int unmap_me
, unmap_me2
, unmap_me3
;
297 DPRINT("MmInit1(FirstKrnlPhysAddr, %x, LastKrnlPhysAddr %x, LastKernelAddress %x)\n",
303 if ((BIOSMemoryMap
!= NULL
) && (AddressRangeCount
> 0))
305 // If we have a bios memory map, recalulate the memory size
307 for (i
= 0; i
< AddressRangeCount
; i
++)
309 if (BIOSMemoryMap
[i
].Type
== 1
310 && (BIOSMemoryMap
[i
].BaseAddrLow
+ BIOSMemoryMap
[i
].LengthLow
+ PAGE_SIZE
-1) / PAGE_SIZE
> last
)
312 last
= (BIOSMemoryMap
[i
].BaseAddrLow
+ BIOSMemoryMap
[i
].LengthLow
+ PAGE_SIZE
-1) / PAGE_SIZE
;
315 if ((last
- 256) * 4 > KeLoaderBlock
.MemHigher
)
317 KeLoaderBlock
.MemHigher
= (last
- 256) * 4;
321 if (KeLoaderBlock
.MemHigher
>= (MaxMem
- 1) * 1024)
323 KeLoaderBlock
.MemHigher
= (MaxMem
- 1) * 1024;
327 * FIXME: Set this based on the system command line
329 MmSystemRangeStart
= (PVOID
)KERNEL_BASE
; // 0xC0000000
330 MmUserProbeAddress
= (PVOID
)0x7fff0000;
331 MmHighestUserAddress
= (PVOID
)0x7ffeffff;
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();
384 DbgPrint("Used memory %dKb\n", (MmStats
.NrTotalPages
* PAGE_SIZE
) / 1024);
386 LastKernelAddress
= (ULONG
)MmInitializePageList((PVOID
)FirstKrnlPhysAddr
,
387 (PVOID
)LastKrnlPhysAddr
,
388 MmStats
.NrTotalPages
,
389 PAGE_ROUND_UP(LastKernelAddress
),
392 kernel_len
= LastKrnlPhysAddr
- FirstKrnlPhysAddr
;
398 /* In SMP mode we unmap the low memory in MmInit3.
399 The APIC needs the mapping of the first pages
400 while the processors are starting up. */
401 MmDeletePageTable(NULL
, 0);
406 DPRINT("Invalidating between %x and %x\n",
407 LastKernelAddress
, KERNEL_BASE
+ 0x00600000);
408 for (i
=(LastKernelAddress
); i
<KERNEL_BASE
+ 0x00600000; i
+=PAGE_SIZE
)
410 MmRawDeleteVirtualMapping((PVOID
)(i
));
413 extern unsigned int pagetable_start
, pagetable_end
;
414 for (i
= (ULONG_PTR
)&pagetable_start
; i
< (ULONG_PTR
)&pagetable_end
; i
+= PAGE_SIZE
)
416 MmDeleteVirtualMapping(NULL
, (PVOID
)i
, FALSE
, NULL
, NULL
);
419 DPRINT("Almost done MmInit()\n");
421 /* FIXME: This is broken in SMP mode */
422 MmDeleteVirtualMapping(NULL
, (PVOID
)&unmap_me
, TRUE
, NULL
, NULL
);
423 MmDeleteVirtualMapping(NULL
, (PVOID
)&unmap_me2
, TRUE
, NULL
, NULL
);
424 MmDeleteVirtualMapping(NULL
, (PVOID
)&unmap_me3
, TRUE
, NULL
, NULL
);
427 * Intialize memory areas
429 MmInitVirtualMemory(LastKernelAddress
, kernel_len
);
431 MmInitializeMdlImplementation();
437 MmInitializeRmapList();
438 MmInitializePageOp();
439 MmInitSectionImplementation();
450 /* In SMP mode we can unmap the low memory
451 if all processors are started. */
452 MmDeletePageTable(NULL
, 0);
455 MmInitZeroPageThread();
456 MmCreatePhysicalMemorySection();
457 MiInitBalancerThread();
460 * Initialise the modified page writer.
464 /* FIXME: Read parameters from memory */
468 MiFreeInitMemoryPage(PVOID Context
, MEMORY_AREA
* MemoryArea
, PVOID Address
,
469 PFN_TYPE Page
, SWAPENTRY SwapEntry
,
472 ASSERT(SwapEntry
== 0);
475 MmReleasePageMemoryConsumer(MC_NPPOOL
, Page
);
480 MiFreeInitMemory(VOID
)
482 MmLockAddressSpace(MmGetKernelAddressSpace());
483 MmFreeMemoryArea(MmGetKernelAddressSpace(),
484 (PVOID
)&_init_start__
,
485 PAGE_ROUND_UP((ULONG
)&_init_end__
) - (ULONG
)_init_start__
,
486 MiFreeInitMemoryPage
,
488 MmUnlockAddressSpace(MmGetKernelAddressSpace());