1 /* $Id: mminit.c,v 1.56 2003/11/16 15:19:28 hbirr 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 extern unsigned int _init_start__
;
40 extern unsigned int _init_end__
;
42 static BOOLEAN IsThisAnNtAsSystem
= FALSE
;
43 static MM_SYSTEM_SIZE MmSystemSize
= MmSmallSystem
;
45 extern unsigned int _bss_end__
;
47 static MEMORY_AREA
* kernel_text_desc
= NULL
;
48 static MEMORY_AREA
* kernel_init_desc
= NULL
;
49 static MEMORY_AREA
* kernel_map_desc
= NULL
;
50 static MEMORY_AREA
* kernel_kpcr_desc
= NULL
;
51 static MEMORY_AREA
* kernel_data_desc
= NULL
;
52 static MEMORY_AREA
* kernel_param_desc
= NULL
;
53 static MEMORY_AREA
* kernel_pool_desc
= NULL
;
54 static MEMORY_AREA
* kernel_shared_data_desc
= NULL
;
55 static MEMORY_AREA
* MiKernelMapDescriptor
= NULL
;
56 static MEMORY_AREA
* MiPagedPoolDescriptor
= NULL
;
58 PHYSICAL_ADDRESS MmSharedDataPagePhysicalAddress
;
60 PVOID MiNonPagedPoolStart
;
61 ULONG MiNonPagedPoolLength
;
62 PVOID MiKernelMapStart
;
63 ULONG MiKernelMapLength
;
65 /* FUNCTIONS ****************************************************************/
70 BOOLEAN STDCALL
MmIsThisAnNtAsSystem(VOID
)
72 return(IsThisAnNtAsSystem
);
78 MM_SYSTEM_SIZE STDCALL
MmQuerySystemSize(VOID
)
83 VOID
MiShutdownMemoryManager(VOID
)
88 MmInitVirtualMemory(ULONG LastKernelAddress
,
91 * FUNCTION: Intialize the memory areas list
93 * bp = Pointer to the boot parameters
94 * kernel_len = Length of the kernel
99 ULONG ParamLength
= KernelLength
;
103 DPRINT("MmInitVirtualMemory(%x, %x)\n",LastKernelAddress
, KernelLength
);
105 LastKernelAddress
= PAGE_ROUND_UP(LastKernelAddress
);
109 /* Don't change the start of kernel map. Pte's must always exist for this region. */
110 MiKernelMapStart
= (PVOID
)LastKernelAddress
+ PAGE_SIZE
;
111 MiKernelMapLength
= MM_KERNEL_MAP_SIZE
;
113 MiNonPagedPoolStart
= MiKernelMapStart
+ MiKernelMapLength
+ PAGE_SIZE
;
114 MiNonPagedPoolLength
= MM_NONPAGED_POOL_SIZE
;
116 MmPagedPoolBase
= MiNonPagedPoolStart
+ MiNonPagedPoolLength
+ PAGE_SIZE
;
117 MmPagedPoolSize
= MM_PAGED_POOL_SIZE
;
121 MiInitializeNonPagedPool();
124 * Setup the system area descriptor list
126 BaseAddress
= (PVOID
)0xf0000000;
127 MmCreateMemoryArea(NULL
,
128 MmGetKernelAddressSpace(),
137 BaseAddress
= (PVOID
)KPCR_BASE
;
138 MmCreateMemoryArea(NULL
,
139 MmGetKernelAddressSpace(),
142 PAGE_SIZE
* MAXIMUM_PROCESSORS
,
147 BaseAddress
= (PVOID
)KERNEL_BASE
;
148 Length
= PAGE_ROUND_UP(((ULONG
)&_text_end__
)) - KERNEL_BASE
;
149 ParamLength
= ParamLength
- Length
;
152 * No need to lock the address space at this point since no
153 * other threads are running.
155 MmCreateMemoryArea(NULL
,
156 MmGetKernelAddressSpace(),
165 BaseAddress
= (PVOID
)PAGE_ROUND_UP(((ULONG
)&_text_end__
));
166 assert (BaseAddress
== (PVOID
)&_init_start__
);
167 Length
= PAGE_ROUND_UP(((ULONG
)&_init_end__
)) -
168 PAGE_ROUND_UP(((ULONG
)&_text_end__
));
169 ParamLength
= ParamLength
- Length
;
171 MmCreateMemoryArea(NULL
,
172 MmGetKernelAddressSpace(),
181 Length
= PAGE_ROUND_UP(((ULONG
)&_bss_end__
)) -
182 PAGE_ROUND_UP(((ULONG
)&_init_end__
));
183 ParamLength
= ParamLength
- Length
;
184 DPRINT("Length %x\n",Length
);
185 BaseAddress
= (PVOID
)PAGE_ROUND_UP(((ULONG
)&_init_end__
));
186 DPRINT("BaseAddress %x\n",BaseAddress
);
189 * No need to lock the address space at this point since we are
190 * the only thread running.
192 MmCreateMemoryArea(NULL
,
193 MmGetKernelAddressSpace(),
202 BaseAddress
= (PVOID
)PAGE_ROUND_UP(((ULONG
)&_bss_end__
));
203 Length
= LastKernelAddress
- (ULONG
)BaseAddress
;
204 MmCreateMemoryArea(NULL
,
205 MmGetKernelAddressSpace(),
214 BaseAddress
= MiNonPagedPoolStart
;
215 MmCreateMemoryArea(NULL
,
216 MmGetKernelAddressSpace(),
219 MiNonPagedPoolLength
,
225 BaseAddress
= MiKernelMapStart
;
226 Status
= MmCreateMemoryArea(NULL
,
227 MmGetKernelAddressSpace(),
232 &MiKernelMapDescriptor
,
236 BaseAddress
= MmPagedPoolBase
;
237 Status
= MmCreateMemoryArea(NULL
,
238 MmGetKernelAddressSpace(),
239 MEMORY_AREA_PAGED_POOL
,
243 &MiPagedPoolDescriptor
,
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 Status
= MmRequestPageMemoryConsumer(MC_NPPOOL
, TRUE
,
264 &MmSharedDataPagePhysicalAddress
);
265 Status
= MmCreateVirtualMapping(NULL
,
266 (PVOID
)KI_USER_SHARED_DATA
,
268 MmSharedDataPagePhysicalAddress
,
270 if (!NT_SUCCESS(Status
))
272 DbgPrint("Unable to create virtual mapping\n");
275 RtlZeroMemory(BaseAddress
, Length
);
280 MmInitializeMemoryConsumer(MC_USER
, MmTrimUserMemory
);
284 MmInit1(ULONG FirstKrnlPhysAddr
,
285 ULONG LastKrnlPhysAddr
,
286 ULONG LastKernelAddress
,
287 PADDRESS_RANGE BIOSMemoryMap
,
288 ULONG AddressRangeCount
,
291 * FUNCTION: Initalize memory managment
297 extern unsigned int unmap_me
, unmap_me2
, unmap_me3
;
300 DPRINT("MmInit1(FirstKrnlPhysAddr, %x, LastKrnlPhysAddr %x, LastKernelAddress %x)\n",
306 if ((BIOSMemoryMap
!= NULL
) && (AddressRangeCount
> 0))
308 // If we have a bios memory map, recalulate the 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;
330 * FIXME: Set this based on the system command line
332 MmSystemRangeStart
= (PVOID
)KERNEL_BASE
; // 0xC0000000
333 MmUserProbeAddress
= (PVOID
)0x7fff0000;
334 MmHighestUserAddress
= (PVOID
)0x7ffeffff;
336 MmInitGlobalKernelPageDirectory();
339 * Initialize memory managment statistics
341 MmStats
.NrTotalPages
= 0;
342 MmStats
.NrSystemPages
= 0;
343 MmStats
.NrUserPages
= 0;
344 MmStats
.NrReservedPages
= 0;
345 MmStats
.NrUserPages
= 0;
346 MmStats
.NrFreePages
= 0;
347 MmStats
.NrLockedPages
= 0;
348 MmStats
.PagingRequestsInLastMinute
= 0;
349 MmStats
.PagingRequestsInLastFiveMinutes
= 0;
350 MmStats
.PagingRequestsInLastFifteenMinutes
= 0;
353 * Initialize the kernel address space
355 MmInitializeKernelAddressSpace();
361 /* In SMP mode we unmap the low memory in MmInit3.
362 The APIC needs the mapping of the first pages
363 while the processors are starting up. */
364 MmDeletePageTable(NULL
, 0);
367 * Free all pages not used for kernel memory
368 * (we assume the kernel occupies a continuous range of physical
371 DPRINT("first krnl %x\nlast krnl %x\n",FirstKrnlPhysAddr
,
375 * Free physical memory not used by the kernel
377 MmStats
.NrTotalPages
= KeLoaderBlock
.MemHigher
/4;
378 if (!MmStats
.NrTotalPages
)
380 DbgPrint("Memory not detected, default to 8 MB\n");
381 MmStats
.NrTotalPages
= 2048;
385 /* add 1MB for standard memory (not extended) */
386 MmStats
.NrTotalPages
+= 256;
389 MmStats
.NrTotalPages
+= 16;
391 DbgPrint("Used memory %dKb\n", (MmStats
.NrTotalPages
* PAGE_SIZE
) / 1024);
393 LastKernelAddress
= (ULONG
)MmInitializePageList((PVOID
)FirstKrnlPhysAddr
,
394 (PVOID
)LastKrnlPhysAddr
,
395 MmStats
.NrTotalPages
,
396 PAGE_ROUND_UP(LastKernelAddress
),
399 kernel_len
= LastKrnlPhysAddr
- FirstKrnlPhysAddr
;
402 * Create a trap for null pointer references and protect text
406 DPRINT("_text_start__ %x _init_end__ %x\n",(int)&_text_start__
,(int)&_init_end__
);
407 for (i
=PAGE_ROUND_DOWN(((int)&_text_start__
));
408 i
<PAGE_ROUND_UP(((int)&_init_end__
));i
=i
+PAGE_SIZE
)
410 MmSetPageProtect(NULL
,
415 DPRINT("Invalidating between %x and %x\n",
418 for (i
=(LastKernelAddress
); i
<0xc0600000; i
+=PAGE_SIZE
)
420 MmRawDeleteVirtualMapping((PVOID
)(i
));
422 DPRINT("Almost done MmInit()\n");
424 /* FIXME: This is broken in SMP mode */
425 MmDeleteVirtualMapping(NULL
, (PVOID
)&unmap_me
, TRUE
, NULL
, NULL
);
426 MmDeleteVirtualMapping(NULL
, (PVOID
)&unmap_me2
, TRUE
, NULL
, NULL
);
427 MmDeleteVirtualMapping(NULL
, (PVOID
)&unmap_me3
, TRUE
, NULL
, NULL
);
430 * Intialize memory areas
432 MmInitVirtualMemory(LastKernelAddress
, kernel_len
);
434 MmInitializeMdlImplementation();
440 MmInitializeRmapList();
441 MmInitializePageOp();
442 MmInitSectionImplementation();
453 /* In SMP mode we can unmap the low memory
454 if all processors are started. */
455 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 PHYSICAL_ADDRESS PhysAddr
, SWAPENTRY SwapEntry
,
474 assert(SwapEntry
== 0);
475 if (PhysAddr
.QuadPart
!= 0)
477 MmReleasePageMemoryConsumer(MC_NPPOOL
, PhysAddr
);
482 MiFreeInitMemory(VOID
)
484 MmLockAddressSpace(MmGetKernelAddressSpace());
485 MmFreeMemoryArea(MmGetKernelAddressSpace(),
486 (PVOID
)&_init_start__
,
487 PAGE_ROUND_UP((ULONG
)&_init_end__
) - (ULONG
)_init_start__
,
488 MiFreeInitMemoryPage
,
490 MmUnlockAddressSpace(MmGetKernelAddressSpace());