2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/mm/mminit.c
5 * PURPOSE: Memory Manager Initialization
9 /* INCLUDES ******************************************************************/
15 /* GLOBALS *******************************************************************/
48 BOOLEAN IsThisAnNtAsSystem
= FALSE
;
49 MM_SYSTEMSIZE MmSystemSize
= MmSmallSystem
;
50 PVOID MiNonPagedPoolStart
;
51 ULONG MiNonPagedPoolLength
;
52 ULONG MmBootImageSize
;
53 ULONG MmNumberOfPhysicalPages
, MmHighestPhysicalPage
, MmLowestPhysicalPage
;
54 ULONG_PTR MiKSeg0Start
, MiKSeg0End
;
55 ULONG_PTR MmPfnDatabaseEnd
;
56 PMEMORY_ALLOCATION_DESCRIPTOR MiFreeDescriptor
;
57 MEMORY_ALLOCATION_DESCRIPTOR MiFreeDescriptorOrg
;
58 extern KMUTANT MmSystemLoadLock
;
59 extern HANDLE MpwThreadHandle
;
60 extern BOOLEAN MpwThreadShouldTerminate
;
61 extern KEVENT MpwThreadEvent
;
62 BOOLEAN MiDbgEnableMdDump
=
69 /* PRIVATE FUNCTIONS *********************************************************/
73 MiShutdownMemoryManager(VOID
)
79 /* Ask MPW thread to shutdown */
80 MpwThreadShouldTerminate
= TRUE
;
81 KeSetEvent(&MpwThreadEvent
, IO_NO_INCREMENT
, FALSE
);
84 ObReferenceObjectByHandle(MpwThreadHandle
,
91 KeWaitForSingleObject(Thread
,
97 ObDereferenceObject(Thread
);
99 /* Check if there are any dirty pages, and flush them.
100 There will be no other chance to do this later, since filesystems
101 are going to be shut down. */
102 CcRosFlushDirtyPages(128, &PagesWritten
);
109 MiInitSystemMemoryAreas()
112 PHYSICAL_ADDRESS BoundaryAddressMultiple
;
114 BoundaryAddressMultiple
.QuadPart
= 0;
117 // First initialize the page table and hyperspace memory areas
119 MiInitPageDirectoryMap();
124 BaseAddress
= (PVOID
)PCR
;
125 MmCreateMemoryArea(MmGetKernelAddressSpace(),
126 MEMORY_AREA_SYSTEM
| MEMORY_AREA_STATIC
,
128 PAGE_SIZE
* KeNumberProcessors
,
133 BoundaryAddressMultiple
);
136 // Now the KUSER_SHARED_DATA
138 BaseAddress
= (PVOID
)KI_USER_SHARED_DATA
;
139 MmCreateMemoryArea(MmGetKernelAddressSpace(),
140 MEMORY_AREA_SYSTEM
| MEMORY_AREA_STATIC
,
147 BoundaryAddressMultiple
);
152 MiCountFreePagesInLoaderBlock(PLOADER_PARAMETER_BLOCK LoaderBlock
)
154 PLIST_ENTRY NextEntry
;
155 PMEMORY_ALLOCATION_DESCRIPTOR Md
;
158 for (NextEntry
= KeLoaderBlock
->MemoryDescriptorListHead
.Flink
;
159 NextEntry
!= &KeLoaderBlock
->MemoryDescriptorListHead
;
160 NextEntry
= NextEntry
->Flink
)
162 Md
= CONTAINING_RECORD(NextEntry
, MEMORY_ALLOCATION_DESCRIPTOR
, ListEntry
);
164 /* Skip invisible memory */
165 if ((Md
->MemoryType
!= LoaderFirmwarePermanent
) &&
166 (Md
->MemoryType
!= LoaderSpecialMemory
) &&
167 (Md
->MemoryType
!= LoaderHALCachedMemory
) &&
168 (Md
->MemoryType
!= LoaderBBTMemory
))
170 /* Check if BURNMEM was used */
171 if (Md
->MemoryType
!= LoaderBad
)
173 /* Count this in the total of pages */
174 MmNumberOfPhysicalPages
+= Md
->PageCount
;
177 /* Check if this is the new lowest page */
178 if (Md
->BasePage
< MmLowestPhysicalPage
)
180 /* Update the lowest page */
181 MmLowestPhysicalPage
= Md
->BasePage
;
184 /* Check if this is the new highest page */
185 if ((Md
->BasePage
+ Md
->PageCount
) > MmHighestPhysicalPage
)
187 /* Update the highest page */
188 MmHighestPhysicalPage
= Md
->BasePage
+ Md
->PageCount
- 1;
191 /* Check if this is free memory */
192 if ((Md
->MemoryType
== LoaderFree
) ||
193 (Md
->MemoryType
== LoaderLoadedProgram
) ||
194 (Md
->MemoryType
== LoaderFirmwareTemporary
) ||
195 (Md
->MemoryType
== LoaderOsloaderStack
))
197 /* Check if this is the largest memory descriptor */
198 if (Md
->PageCount
> FreePages
)
201 FreePages
= Md
->PageCount
;
202 MiFreeDescriptor
= Md
;
208 /* Save original values of the free descriptor, since it'll be
209 altered by early allocations */
210 MiFreeDescriptorOrg
= *MiFreeDescriptor
;
215 MiDbgKernelLayout(VOID
)
217 DPRINT1("%8s%12s\t\t%s\n", "Start", "End", "Type");
218 DPRINT1("0x%p - 0x%p\t%s\n",
219 KSEG0_BASE
, MiKSeg0Start
,
221 DPRINT1("0x%p - 0x%p\t%s\n",
222 MiKSeg0Start
, MiKSeg0End
,
223 "FreeLDR Kernel mapping region");
224 DPRINT1("0x%p - 0x%p\t%s\n",
225 MmPfnDatabase
, MmPfnDatabaseEnd
,
226 "PFN Database region");
227 if (MmPfnDatabaseEnd
!= (ULONG_PTR
)MiNonPagedPoolStart
)
228 DPRINT1("0x%p - 0x%p\t%s\n",
229 MmPfnDatabaseEnd
, MiNonPagedPoolStart
,
230 "Remaining FreeLDR mapping");
231 DPRINT1("0x%p - 0x%p\t%s\n",
232 MiNonPagedPoolStart
, (ULONG_PTR
)MiNonPagedPoolStart
+ MiNonPagedPoolLength
,
233 "Non paged pool region");
234 DPRINT1("0x%p - 0x%p\t%s\n",
235 MmPagedPoolBase
, (ULONG_PTR
)MmPagedPoolBase
+ MmPagedPoolSize
,
236 "Paged pool region");
241 MiDbgDumpMemoryDescriptors(VOID
)
243 PLIST_ENTRY NextEntry
;
244 PMEMORY_ALLOCATION_DESCRIPTOR Md
;
245 ULONG TotalPages
= 0;
247 DPRINT1("Base\t\tLength\t\tType\n");
248 for (NextEntry
= KeLoaderBlock
->MemoryDescriptorListHead
.Flink
;
249 NextEntry
!= &KeLoaderBlock
->MemoryDescriptorListHead
;
250 NextEntry
= NextEntry
->Flink
)
252 Md
= CONTAINING_RECORD(NextEntry
, MEMORY_ALLOCATION_DESCRIPTOR
, ListEntry
);
253 DPRINT1("%08lX\t%08lX\t%s\n", Md
->BasePage
, Md
->PageCount
, MemType
[Md
->MemoryType
]);
254 TotalPages
+= Md
->PageCount
;
257 DPRINT1("Total: %08lX (%d MB)\n", TotalPages
, (TotalPages
* PAGE_SIZE
) / 1024 / 1024);
262 MiGetLastKernelAddress(VOID
)
264 PLIST_ENTRY NextEntry
;
265 PMEMORY_ALLOCATION_DESCRIPTOR Md
;
266 ULONG_PTR LastKrnlPhysAddr
= 0;
268 for (NextEntry
= KeLoaderBlock
->MemoryDescriptorListHead
.Flink
;
269 NextEntry
!= &KeLoaderBlock
->MemoryDescriptorListHead
;
270 NextEntry
= NextEntry
->Flink
)
272 Md
= CONTAINING_RECORD(NextEntry
, MEMORY_ALLOCATION_DESCRIPTOR
, ListEntry
);
274 if (Md
->MemoryType
!= LoaderFree
&&
275 Md
->MemoryType
!= LoaderFirmwareTemporary
&&
276 Md
->MemoryType
!= LoaderSpecialMemory
)
278 if (Md
->BasePage
+Md
->PageCount
> LastKrnlPhysAddr
)
279 LastKrnlPhysAddr
= Md
->BasePage
+Md
->PageCount
;
283 /* Convert to a physical address */
284 return LastKrnlPhysAddr
<< PAGE_SHIFT
;
290 MiInitHyperSpace(VOID
);
294 MmArmInitSystem(IN ULONG Phase
,
295 IN PLOADER_PARAMETER_BLOCK LoaderBlock
);
302 PLDR_DATA_TABLE_ENTRY LdrEntry
;
305 /* Dump memory descriptors */
306 if (MiDbgEnableMdDump
) MiDbgDumpMemoryDescriptors();
308 /* Set the page directory */
309 PsGetCurrentProcess()->Pcb
.DirectoryTableBase
[0] = (ULONG
)MmGetPageDirectory();
311 /* Get the size of FreeLDR's image allocations */
312 MmBootImageSize
= KeLoaderBlock
->Extension
->LoaderPagesSpanned
;
313 MmBootImageSize
*= PAGE_SIZE
;
315 /* Set memory limits */
316 MmSystemRangeStart
= (PVOID
)KSEG0_BASE
;
317 MmUserProbeAddress
= (ULONG_PTR
)MmSystemRangeStart
- 0x10000;
318 MmHighestUserAddress
= (PVOID
)(MmUserProbeAddress
- 1);
319 DPRINT("MmSystemRangeStart: %08x\n", MmSystemRangeStart
);
320 DPRINT("MmUserProbeAddress: %08x\n", MmUserProbeAddress
);
321 DPRINT("MmHighestUserAddress:%08x\n", MmHighestUserAddress
);
323 /* Initialize memory managment statistics */
324 RtlZeroMemory(&MmStats
, sizeof(MmStats
));
327 MiCountFreePagesInLoaderBlock(KeLoaderBlock
);
328 DbgPrint("Used memory %dKb\n", (MmNumberOfPhysicalPages
* PAGE_SIZE
) / 1024);
330 /* Initialize the kernel address space */
331 MmInitializeHandBuiltProcess(PsGetCurrentProcess(), Dummy
);
332 MmKernelAddressSpace
= MmGetCurrentAddressSpace();
333 MmInitGlobalKernelPageDirectory();
335 /* Get kernel address boundaries */
336 LdrEntry
= CONTAINING_RECORD(KeLoaderBlock
->LoadOrderListHead
.Flink
,
337 LDR_DATA_TABLE_ENTRY
,
339 MiKSeg0Start
= (ULONG_PTR
)LdrEntry
->DllBase
| KSEG0_BASE
;
340 MiKSeg0End
= PAGE_ROUND_UP(MiGetLastKernelAddress() | KSEG0_BASE
);
342 /* We'll put the PFN array right after the loaded modules */
343 MmPfnDatabase
= (PVOID
)MiKSeg0End
;
344 MmPfnDatabaseEnd
= (ULONG_PTR
)MmPfnDatabase
+ (MmHighestPhysicalPage
* sizeof(MMPFN
));
345 MmPfnDatabaseEnd
= PAGE_ROUND_UP(MmPfnDatabaseEnd
);
348 * FreeLDR maps 6MB starting at the kernel base address, followed by the
349 * PFN database. If the PFN database doesn't go over the FreeLDR allocation
350 * then choose the end of the FreeLDR block. If it does go past the FreeLDR
351 * allocation, then choose the next PAGE_SIZE boundary.
353 if ((ULONG_PTR
)MmPfnDatabaseEnd
< (MiKSeg0Start
+ 0x600000))
355 /* Use the first memory following FreeLDR's 6MB mapping */
356 MiNonPagedPoolStart
= (PVOID
)((ULONG_PTR
)MiKSeg0Start
+ 0x600000);
360 /* Use the next free available page */
361 MiNonPagedPoolStart
= (PVOID
)MmPfnDatabaseEnd
;
364 /* Length of non-paged pool */
365 MiNonPagedPoolLength
= MM_NONPAGED_POOL_SIZE
;
367 /* Put the paged pool after the non-paged pool */
368 MmPagedPoolBase
= (PVOID
)PAGE_ROUND_UP((ULONG_PTR
)MiNonPagedPoolStart
+
369 MiNonPagedPoolLength
);
370 MmPagedPoolSize
= MM_PAGED_POOL_SIZE
;
372 /* Dump kernel memory layout */
375 /* Intialize system memory areas */
376 MiInitSystemMemoryAreas();
378 /* Initialize the page list */
379 MmInitializePageList();
381 /* Unmap low memory */
382 MmDeletePageTable(NULL
, 0);
387 MmArmInitSystem(0, KeLoaderBlock
);
389 /* Initialize nonpaged pool */
390 MiInitializeNonPagedPool();
392 /* Initialize paged pool */
393 MmInitializePagedPool();
395 /* Initialize MDLs */
396 MmInitializeMdlImplementation();
398 /* Initialize working sets */
399 MmInitializeMemoryConsumer(MC_USER
, MmTrimUserMemory
);
404 MmInitSystem(IN ULONG Phase
,
405 IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
409 /* Initialize Mm bootstrap */
412 /* Initialize the Loader Lock */
413 KeInitializeMutant(&MmSystemLoadLock
, FALSE
);
415 /* Reload boot drivers */
416 MiReloadBootLoadedDrivers(LoaderBlock
);
418 /* Initialize the loaded module list */
419 MiInitializeLoadedModuleList(LoaderBlock
);
421 /* We're done, for now */
422 DPRINT("Mm0: COMPLETE\n");
426 MmInitializeRmapList();
427 MmInitializePageOp();
428 MmInitSectionImplementation();
430 MmCreatePhysicalMemorySection();
432 /* Setup shared user data settings that NT does as well */
433 ASSERT(SharedUserData
->NumberOfPhysicalPages
== 0);
434 SharedUserData
->NumberOfPhysicalPages
= MmStats
.NrTotalPages
;
435 SharedUserData
->LargePageMinimum
= 0;
437 /* For now, we assume that we're always Workstation */
438 SharedUserData
->NtProductType
= NtProductWinNt
;
445 MiInitBalancerThread();
448 * Initialise the modified page writer.
452 /* Initialize the balance set manager */
455 /* FIXME: Read parameters from memory */
462 /* PUBLIC FUNCTIONS **********************************************************/
469 MmIsThisAnNtAsSystem(VOID
)
471 return IsThisAnNtAsSystem
;
479 MmQuerySystemSize(VOID
)