1 /* $Id: mminit.c,v 1.57 2003/11/30 17:17:02 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
* kernel_mapped_low_mem_desc
= NULL
;
56 static MEMORY_AREA
* MiKernelMapDescriptor
= NULL
;
57 static MEMORY_AREA
* MiPagedPoolDescriptor
= NULL
;
59 PHYSICAL_ADDRESS MmSharedDataPagePhysicalAddress
;
61 PVOID MiNonPagedPoolStart
;
62 ULONG MiNonPagedPoolLength
;
63 PVOID MiKernelMapStart
;
64 ULONG MiKernelMapLength
;
66 /* FUNCTIONS ****************************************************************/
71 BOOLEAN STDCALL
MmIsThisAnNtAsSystem(VOID
)
73 return(IsThisAnNtAsSystem
);
79 MM_SYSTEM_SIZE STDCALL
MmQuerySystemSize(VOID
)
84 VOID
MiShutdownMemoryManager(VOID
)
89 MmInitVirtualMemory(ULONG LastKernelAddress
,
92 * FUNCTION: Intialize the memory areas list
94 * bp = Pointer to the boot parameters
95 * kernel_len = Length of the kernel
100 ULONG ParamLength
= KernelLength
;
104 DPRINT("MmInitVirtualMemory(%x, %x)\n",LastKernelAddress
, KernelLength
);
106 LastKernelAddress
= PAGE_ROUND_UP(LastKernelAddress
);
110 /* Don't change the start of kernel map. Pte's must always exist for this region. */
111 MiKernelMapStart
= (PVOID
)LastKernelAddress
+ PAGE_SIZE
;
112 MiKernelMapLength
= MM_KERNEL_MAP_SIZE
;
114 MiNonPagedPoolStart
= MiKernelMapStart
+ MiKernelMapLength
+ PAGE_SIZE
;
115 MiNonPagedPoolLength
= MM_NONPAGED_POOL_SIZE
;
117 MmPagedPoolBase
= MiNonPagedPoolStart
+ MiNonPagedPoolLength
+ PAGE_SIZE
;
118 MmPagedPoolSize
= MM_PAGED_POOL_SIZE
;
122 MiInitializeNonPagedPool();
125 * Setup the system area descriptor list
127 BaseAddress
= (PVOID
)0xf0000000;
128 MmCreateMemoryArea(NULL
,
129 MmGetKernelAddressSpace(),
138 BaseAddress
= (PVOID
)KPCR_BASE
;
139 MmCreateMemoryArea(NULL
,
140 MmGetKernelAddressSpace(),
143 PAGE_SIZE
* MAXIMUM_PROCESSORS
,
149 BaseAddress
= (PVOID
)0xd0000000;
150 MmCreateMemoryArea(NULL
,
151 MmGetKernelAddressSpace(),
156 &kernel_mapped_low_mem_desc
,
160 BaseAddress
= (PVOID
)KERNEL_BASE
;
161 Length
= PAGE_ROUND_UP(((ULONG
)&_text_end__
)) - KERNEL_BASE
;
162 ParamLength
= ParamLength
- Length
;
165 * No need to lock the address space at this point since no
166 * other threads are running.
168 MmCreateMemoryArea(NULL
,
169 MmGetKernelAddressSpace(),
178 BaseAddress
= (PVOID
)PAGE_ROUND_UP(((ULONG
)&_text_end__
));
179 assert (BaseAddress
== (PVOID
)&_init_start__
);
180 Length
= PAGE_ROUND_UP(((ULONG
)&_init_end__
)) -
181 PAGE_ROUND_UP(((ULONG
)&_text_end__
));
182 ParamLength
= ParamLength
- Length
;
184 MmCreateMemoryArea(NULL
,
185 MmGetKernelAddressSpace(),
194 Length
= PAGE_ROUND_UP(((ULONG
)&_bss_end__
)) -
195 PAGE_ROUND_UP(((ULONG
)&_init_end__
));
196 ParamLength
= ParamLength
- Length
;
197 DPRINT("Length %x\n",Length
);
198 BaseAddress
= (PVOID
)PAGE_ROUND_UP(((ULONG
)&_init_end__
));
199 DPRINT("BaseAddress %x\n",BaseAddress
);
202 * No need to lock the address space at this point since we are
203 * the only thread running.
205 MmCreateMemoryArea(NULL
,
206 MmGetKernelAddressSpace(),
215 BaseAddress
= (PVOID
)PAGE_ROUND_UP(((ULONG
)&_bss_end__
));
216 Length
= LastKernelAddress
- (ULONG
)BaseAddress
;
217 MmCreateMemoryArea(NULL
,
218 MmGetKernelAddressSpace(),
227 BaseAddress
= MiNonPagedPoolStart
;
228 MmCreateMemoryArea(NULL
,
229 MmGetKernelAddressSpace(),
232 MiNonPagedPoolLength
,
238 BaseAddress
= MiKernelMapStart
;
239 Status
= MmCreateMemoryArea(NULL
,
240 MmGetKernelAddressSpace(),
245 &MiKernelMapDescriptor
,
249 BaseAddress
= MmPagedPoolBase
;
250 Status
= MmCreateMemoryArea(NULL
,
251 MmGetKernelAddressSpace(),
252 MEMORY_AREA_PAGED_POOL
,
256 &MiPagedPoolDescriptor
,
260 MmInitializePagedPool();
263 * Create the kernel mapping of the user/kernel shared memory.
265 BaseAddress
= (PVOID
)KI_USER_SHARED_DATA
;
267 MmCreateMemoryArea(NULL
,
268 MmGetKernelAddressSpace(),
273 &kernel_shared_data_desc
,
276 Status
= MmRequestPageMemoryConsumer(MC_NPPOOL
, TRUE
,
277 &MmSharedDataPagePhysicalAddress
);
278 Status
= MmCreateVirtualMapping(NULL
,
279 (PVOID
)KI_USER_SHARED_DATA
,
281 MmSharedDataPagePhysicalAddress
,
283 if (!NT_SUCCESS(Status
))
285 DbgPrint("Unable to create virtual mapping\n");
288 RtlZeroMemory(BaseAddress
, Length
);
293 MmInitializeMemoryConsumer(MC_USER
, MmTrimUserMemory
);
297 MmInit1(ULONG FirstKrnlPhysAddr
,
298 ULONG LastKrnlPhysAddr
,
299 ULONG LastKernelAddress
,
300 PADDRESS_RANGE BIOSMemoryMap
,
301 ULONG AddressRangeCount
,
304 * FUNCTION: Initalize memory managment
310 extern unsigned int unmap_me
, unmap_me2
, unmap_me3
;
313 DPRINT("MmInit1(FirstKrnlPhysAddr, %x, LastKrnlPhysAddr %x, LastKernelAddress %x)\n",
319 if ((BIOSMemoryMap
!= NULL
) && (AddressRangeCount
> 0))
321 // If we have a bios memory map, recalulate the memory size
323 for (i
= 0; i
< AddressRangeCount
; i
++)
325 if (BIOSMemoryMap
[i
].Type
== 1
326 && (BIOSMemoryMap
[i
].BaseAddrLow
+ BIOSMemoryMap
[i
].LengthLow
+ PAGE_SIZE
-1) / PAGE_SIZE
> last
)
328 last
= (BIOSMemoryMap
[i
].BaseAddrLow
+ BIOSMemoryMap
[i
].LengthLow
+ PAGE_SIZE
-1) / PAGE_SIZE
;
331 if ((last
- 256) * 4 > KeLoaderBlock
.MemHigher
)
333 KeLoaderBlock
.MemHigher
= (last
- 256) * 4;
337 if (KeLoaderBlock
.MemHigher
>= (MaxMem
- 1) * 1024)
339 KeLoaderBlock
.MemHigher
= (MaxMem
- 1) * 1024;
343 * FIXME: Set this based on the system command line
345 MmSystemRangeStart
= (PVOID
)KERNEL_BASE
; // 0xC0000000
346 MmUserProbeAddress
= (PVOID
)0x7fff0000;
347 MmHighestUserAddress
= (PVOID
)0x7ffeffff;
349 MmInitGlobalKernelPageDirectory();
352 * Initialize memory managment statistics
354 MmStats
.NrTotalPages
= 0;
355 MmStats
.NrSystemPages
= 0;
356 MmStats
.NrUserPages
= 0;
357 MmStats
.NrReservedPages
= 0;
358 MmStats
.NrUserPages
= 0;
359 MmStats
.NrFreePages
= 0;
360 MmStats
.NrLockedPages
= 0;
361 MmStats
.PagingRequestsInLastMinute
= 0;
362 MmStats
.PagingRequestsInLastFiveMinutes
= 0;
363 MmStats
.PagingRequestsInLastFifteenMinutes
= 0;
366 * Initialize the kernel address space
368 MmInitializeKernelAddressSpace();
374 /* In SMP mode we unmap the low memory in MmInit3.
375 The APIC needs the mapping of the first pages
376 while the processors are starting up. */
377 MmDeletePageTable(NULL
, 0);
380 * Free all pages not used for kernel memory
381 * (we assume the kernel occupies a continuous range of physical
384 DPRINT("first krnl %x\nlast krnl %x\n",FirstKrnlPhysAddr
,
388 * Free physical memory not used by the kernel
390 MmStats
.NrTotalPages
= KeLoaderBlock
.MemHigher
/4;
391 if (!MmStats
.NrTotalPages
)
393 DbgPrint("Memory not detected, default to 8 MB\n");
394 MmStats
.NrTotalPages
= 2048;
398 /* add 1MB for standard memory (not extended) */
399 MmStats
.NrTotalPages
+= 256;
402 MmStats
.NrTotalPages
+= 16;
404 DbgPrint("Used memory %dKb\n", (MmStats
.NrTotalPages
* PAGE_SIZE
) / 1024);
406 LastKernelAddress
= (ULONG
)MmInitializePageList((PVOID
)FirstKrnlPhysAddr
,
407 (PVOID
)LastKrnlPhysAddr
,
408 MmStats
.NrTotalPages
,
409 PAGE_ROUND_UP(LastKernelAddress
),
412 kernel_len
= LastKrnlPhysAddr
- FirstKrnlPhysAddr
;
415 * Create a trap for null pointer references and protect text
419 DPRINT("_text_start__ %x _init_end__ %x\n",(int)&_text_start__
,(int)&_init_end__
);
420 for (i
=PAGE_ROUND_DOWN(((int)&_text_start__
));
421 i
<PAGE_ROUND_UP(((int)&_init_end__
));i
=i
+PAGE_SIZE
)
423 MmSetPageProtect(NULL
,
428 DPRINT("Invalidating between %x and %x\n",
429 LastKernelAddress
, 0xc0600000);
430 for (i
=(LastKernelAddress
); i
<0xc0600000; i
+=PAGE_SIZE
)
432 MmRawDeleteVirtualMapping((PVOID
)(i
));
435 DPRINT("Invalidating between %x and %x\n",
436 0xd0100000, 0xd0400000);
437 for (i
=0xd0100000; i
<0xd0400000; i
+=PAGE_SIZE
)
439 MmRawDeleteVirtualMapping((PVOID
)(i
));
442 DPRINT("Almost done MmInit()\n");
444 /* FIXME: This is broken in SMP mode */
445 MmDeleteVirtualMapping(NULL
, (PVOID
)&unmap_me
, TRUE
, NULL
, NULL
);
446 MmDeleteVirtualMapping(NULL
, (PVOID
)&unmap_me2
, TRUE
, NULL
, NULL
);
447 MmDeleteVirtualMapping(NULL
, (PVOID
)&unmap_me3
, TRUE
, NULL
, NULL
);
450 * Intialize memory areas
452 MmInitVirtualMemory(LastKernelAddress
, kernel_len
);
454 MmInitializeMdlImplementation();
460 MmInitializeRmapList();
461 MmInitializePageOp();
462 MmInitSectionImplementation();
473 /* In SMP mode we can unmap the low memory
474 if all processors are started. */
475 MmDeletePageTable(NULL
, 0);
477 MmInitZeroPageThread();
478 MmCreatePhysicalMemorySection();
479 MiInitBalancerThread();
482 * Initialise the modified page writer.
486 /* FIXME: Read parameters from memory */
490 MiFreeInitMemoryPage(PVOID Context
, MEMORY_AREA
* MemoryArea
, PVOID Address
,
491 PHYSICAL_ADDRESS PhysAddr
, SWAPENTRY SwapEntry
,
494 assert(SwapEntry
== 0);
495 if (PhysAddr
.QuadPart
!= 0)
497 MmReleasePageMemoryConsumer(MC_NPPOOL
, PhysAddr
);
502 MiFreeInitMemory(VOID
)
504 MmLockAddressSpace(MmGetKernelAddressSpace());
505 MmFreeMemoryArea(MmGetKernelAddressSpace(),
506 (PVOID
)&_init_start__
,
507 PAGE_ROUND_UP((ULONG
)&_init_end__
) - (ULONG
)_init_start__
,
508 MiFreeInitMemoryPage
,
510 MmUnlockAddressSpace(MmGetKernelAddressSpace());