1 /* $Id: mminit.c,v 1.54 2003/07/21 21:53:53 royce 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 *****************************************************************/
14 #include <ddk/ntddk.h>
16 #include <internal/i386/segment.h>
17 #include <internal/mm.h>
18 #include <internal/ntoskrnl.h>
19 #include <internal/io.h>
20 #include <internal/ps.h>
21 #include <internal/pool.h>
24 #include <internal/debug.h>
26 /* GLOBALS *****************************************************************/
29 * Size of extended memory (kb) (fixed for now)
31 #define EXTENDED_MEMORY_SIZE (3*1024*1024)
34 * Compiler defined symbols
36 extern unsigned int _text_start__
;
37 extern unsigned int _text_end__
;
39 static BOOLEAN IsThisAnNtAsSystem
= FALSE
;
40 static MM_SYSTEM_SIZE MmSystemSize
= MmSmallSystem
;
42 extern unsigned int _bss_end__
;
44 static MEMORY_AREA
* kernel_text_desc
= NULL
;
45 static MEMORY_AREA
* kernel_map_desc
= NULL
;
46 static MEMORY_AREA
* kernel_data_desc
= NULL
;
47 static MEMORY_AREA
* kernel_param_desc
= NULL
;
48 static MEMORY_AREA
* kernel_pool_desc
= NULL
;
49 static MEMORY_AREA
* kernel_shared_data_desc
= NULL
;
50 static MEMORY_AREA
* MiKernelMapDescriptor
= NULL
;
51 static MEMORY_AREA
* MiPagedPoolDescriptor
= NULL
;
53 PHYSICAL_ADDRESS MmSharedDataPagePhysicalAddress
;
55 PVOID MiNonPagedPoolStart
;
56 ULONG MiNonPagedPoolLength
;
57 PVOID MiKernelMapStart
;
58 ULONG MiKernelMapLength
;
60 /* FUNCTIONS ****************************************************************/
65 BOOLEAN STDCALL
MmIsThisAnNtAsSystem(VOID
)
67 return(IsThisAnNtAsSystem
);
73 MM_SYSTEM_SIZE STDCALL
MmQuerySystemSize(VOID
)
78 VOID
MiShutdownMemoryManager(VOID
)
82 VOID
MmInitVirtualMemory(ULONG LastKernelAddress
,
85 * FUNCTION: Intialize the memory areas list
87 * bp = Pointer to the boot parameters
88 * kernel_len = Length of the kernel
93 ULONG ParamLength
= KernelLength
;
97 DPRINT("MmInitVirtualMemory(%x, %x)\n",LastKernelAddress
, KernelLength
);
99 LastKernelAddress
= PAGE_ROUND_UP(LastKernelAddress
);
103 /* Don't change the start of kernel map. Pte's must always exist for this region. */
104 MiKernelMapStart
= (PVOID
)LastKernelAddress
+ PAGE_SIZE
;
105 MiKernelMapLength
= MM_KERNEL_MAP_SIZE
;
107 MiNonPagedPoolStart
= MiKernelMapStart
+ MiKernelMapLength
+ PAGE_SIZE
;
108 MiNonPagedPoolLength
= MM_NONPAGED_POOL_SIZE
;
110 MmPagedPoolBase
= MiNonPagedPoolStart
+ MiNonPagedPoolLength
+ PAGE_SIZE
;
111 MmPagedPoolSize
= MM_PAGED_POOL_SIZE
;
115 MiInitializeNonPagedPool();
118 * Setup the system area descriptor list
120 BaseAddress
= (PVOID
)0xf0000000;
121 MmCreateMemoryArea(NULL
,
122 MmGetKernelAddressSpace(),
131 BaseAddress
= (PVOID
)KERNEL_BASE
;
132 Length
= PAGE_ROUND_UP(((ULONG
)&_text_end__
)) - KERNEL_BASE
;
133 ParamLength
= ParamLength
- Length
;
136 * No need to lock the address space at this point since no
137 * other threads are running.
139 MmCreateMemoryArea(NULL
,
140 MmGetKernelAddressSpace(),
148 Length
= PAGE_ROUND_UP(((ULONG
)&_bss_end__
)) -
149 PAGE_ROUND_UP(((ULONG
)&_text_end__
));
150 ParamLength
= ParamLength
- Length
;
151 DPRINT("Length %x\n",Length
);
152 BaseAddress
= (PVOID
)PAGE_ROUND_UP(((ULONG
)&_text_end__
));
153 DPRINT("BaseAddress %x\n",BaseAddress
);
156 * No need to lock the address space at this point since we are
157 * the only thread running.
159 MmCreateMemoryArea(NULL
,
160 MmGetKernelAddressSpace(),
169 BaseAddress
= (PVOID
)PAGE_ROUND_UP(((ULONG
)&_bss_end__
));
170 Length
= LastKernelAddress
- (ULONG
)BaseAddress
;
171 MmCreateMemoryArea(NULL
,
172 MmGetKernelAddressSpace(),
181 BaseAddress
= MiNonPagedPoolStart
;
182 MmCreateMemoryArea(NULL
,
183 MmGetKernelAddressSpace(),
186 MiNonPagedPoolLength
,
192 BaseAddress
= MiKernelMapStart
;
193 Status
= MmCreateMemoryArea(NULL
,
194 MmGetKernelAddressSpace(),
199 &MiKernelMapDescriptor
,
203 BaseAddress
= MmPagedPoolBase
;
204 Status
= MmCreateMemoryArea(NULL
,
205 MmGetKernelAddressSpace(),
206 MEMORY_AREA_PAGED_POOL
,
210 &MiPagedPoolDescriptor
,
214 MmInitializePagedPool();
217 * Create the kernel mapping of the user/kernel shared memory.
219 BaseAddress
= (PVOID
)KI_USER_SHARED_DATA
;
221 MmCreateMemoryArea(NULL
,
222 MmGetKernelAddressSpace(),
227 &kernel_shared_data_desc
,
230 Status
= MmRequestPageMemoryConsumer(MC_NPPOOL
, TRUE
,
231 &MmSharedDataPagePhysicalAddress
);
232 Status
= MmCreateVirtualMapping(NULL
,
233 (PVOID
)KI_USER_SHARED_DATA
,
235 MmSharedDataPagePhysicalAddress
,
237 if (!NT_SUCCESS(Status
))
239 DbgPrint("Unable to create virtual mapping\n");
242 RtlZeroMemory(BaseAddress
, Length
);
247 MmInitializeMemoryConsumer(MC_USER
, MmTrimUserMemory
);
250 VOID
MmInit1(ULONG FirstKrnlPhysAddr
,
251 ULONG LastKrnlPhysAddr
,
252 ULONG LastKernelAddress
,
253 PADDRESS_RANGE BIOSMemoryMap
,
254 ULONG AddressRangeCount
,
257 * FUNCTION: Initalize memory managment
263 extern unsigned int unmap_me
, unmap_me2
, unmap_me3
;
266 DPRINT("MmInit1(FirstKrnlPhysAddr, %x, LastKrnlPhysAddr %x, LastKernelAddress %x)\n",
272 if ((BIOSMemoryMap
!= NULL
) && (AddressRangeCount
> 0))
274 // If we have a bios memory map, recalulate the the memory size
276 for (i
= 0; i
< AddressRangeCount
; i
++)
278 if (BIOSMemoryMap
[i
].Type
== 1
279 && (BIOSMemoryMap
[i
].BaseAddrLow
+ BIOSMemoryMap
[i
].LengthLow
+ PAGE_SIZE
-1) / PAGE_SIZE
> last
)
281 last
= (BIOSMemoryMap
[i
].BaseAddrLow
+ BIOSMemoryMap
[i
].LengthLow
+ PAGE_SIZE
-1) / PAGE_SIZE
;
284 if ((last
- 256) * 4 > KeLoaderBlock
.MemHigher
)
286 KeLoaderBlock
.MemHigher
= (last
- 256) * 4;
290 if (KeLoaderBlock
.MemHigher
>= (MaxMem
- 1) * 1024)
292 KeLoaderBlock
.MemHigher
= (MaxMem
- 1) * 1024;
296 * FIXME: Set this based on the system command line
298 MmSystemRangeStart
= (PVOID
)KERNEL_BASE
; // 0xC0000000
299 MmUserProbeAddress
= (PVOID
)0x7fff0000;
300 MmHighestUserAddress
= (PVOID
)0x7ffeffff;
302 MmInitGlobalKernelPageDirectory();
305 * Initialize memory managment statistics
307 MmStats
.NrTotalPages
= 0;
308 MmStats
.NrSystemPages
= 0;
309 MmStats
.NrUserPages
= 0;
310 MmStats
.NrReservedPages
= 0;
311 MmStats
.NrUserPages
= 0;
312 MmStats
.NrFreePages
= 0;
313 MmStats
.NrLockedPages
= 0;
314 MmStats
.PagingRequestsInLastMinute
= 0;
315 MmStats
.PagingRequestsInLastFiveMinutes
= 0;
316 MmStats
.PagingRequestsInLastFifteenMinutes
= 0;
319 * Initialize the kernel address space
321 MmInitializeKernelAddressSpace();
327 /* In SMP mode we unmap the low memory in MmInit3.
328 The APIC needs the mapping of the first pages
329 while the processors are starting up. */
330 MmDeletePageTable(NULL
, 0);
333 * Free all pages not used for kernel memory
334 * (we assume the kernel occupies a continuous range of physical
337 DPRINT("first krnl %x\nlast krnl %x\n",FirstKrnlPhysAddr
,
341 * Free physical memory not used by the kernel
343 MmStats
.NrTotalPages
= KeLoaderBlock
.MemHigher
/4;
344 if (!MmStats
.NrTotalPages
)
346 DbgPrint("Memory not detected, default to 8 MB\n");
347 MmStats
.NrTotalPages
= 2048;
351 /* add 1MB for standard memory (not extended) */
352 MmStats
.NrTotalPages
+= 256;
355 MmStats
.NrTotalPages
+= 16;
357 DbgPrint("Used memory %dKb\n", (MmStats
.NrTotalPages
* PAGE_SIZE
) / 1024);
359 LastKernelAddress
= (ULONG
)MmInitializePageList(
360 (PVOID
)FirstKrnlPhysAddr
,
361 (PVOID
)LastKrnlPhysAddr
,
362 MmStats
.NrTotalPages
,
363 PAGE_ROUND_UP(LastKernelAddress
),
366 kernel_len
= LastKrnlPhysAddr
- FirstKrnlPhysAddr
;
369 * Create a trap for null pointer references and protect text
373 DPRINT("_text_start__ %x _text_end__ %x\n",(int)&_text_start__
,(int)&_text_end__
);
374 for (i
=PAGE_ROUND_UP(((int)&_text_start__
));
375 i
<PAGE_ROUND_DOWN(((int)&_text_end__
));i
=i
+PAGE_SIZE
)
377 MmSetPageProtect(NULL
,
382 DPRINT("Invalidating between %x and %x\n",
384 KERNEL_BASE
+ 2 * PAGE_TABLE_SIZE
);
385 for (i
=(LastKernelAddress
);
386 i
<(KERNEL_BASE
+ 2 * PAGE_TABLE_SIZE
);
389 MmRawDeleteVirtualMapping((PVOID
)(i
));
391 DPRINT("Almost done MmInit()\n");
393 /* FIXME: This is broken in SMP mode */
394 MmDeleteVirtualMapping(NULL
, (PVOID
)&unmap_me
, FALSE
, NULL
, NULL
);
395 MmDeleteVirtualMapping(NULL
, (PVOID
)&unmap_me2
, FALSE
, NULL
, NULL
);
396 MmDeleteVirtualMapping(NULL
, (PVOID
)&unmap_me3
, FALSE
, NULL
, NULL
);
399 * Intialize memory areas
401 MmInitVirtualMemory(LastKernelAddress
, kernel_len
);
403 MmInitializeMdlImplementation();
408 MmInitSectionImplementation();
418 /* In SMP mode we can unmap the low memory
419 if all processors are started. */
420 MmDeletePageTable(NULL
, 0);
422 MmInitZeroPageThread();
424 MmCreatePhysicalMemorySection();
425 MmInitializeRmapList();
426 MmInitializePageOp();
429 * Initialise the modified page writer.
433 /* FIXME: Read parameters from memory */