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 #define MODULE_INVOLVED_IN_ARM3
16 #include "ARM3/miarm.h"
18 /* GLOBALS *******************************************************************/
51 BOOLEAN Mm64BitPhysicalAddress
= FALSE
;
52 ULONG MmReadClusterSize
;
54 // 0 | 1 is on/off paging, 2 is undocumented
56 UCHAR MmDisablePagingExecutive
= 1; // Forced to off
57 PMMPTE MmSharedUserDataPte
;
58 PMMSUPPORT MmKernelAddressSpace
;
59 extern KMUTANT MmSystemLoadLock
;
60 BOOLEAN MiDbgEnableMdDump
=
67 /* PRIVATE FUNCTIONS *********************************************************/
72 MiInitSystemMemoryAreas()
75 PHYSICAL_ADDRESS BoundaryAddressMultiple
;
78 BoundaryAddressMultiple
.QuadPart
= 0;
81 // Create the memory area to define the loader mappings
83 BaseAddress
= (PVOID
)KSEG0_BASE
;
84 Status
= MmCreateMemoryArea(MmGetKernelAddressSpace(),
85 MEMORY_AREA_OWNED_BY_ARM3
| MEMORY_AREA_STATIC
,
88 PAGE_EXECUTE_READWRITE
,
92 BoundaryAddressMultiple
);
93 ASSERT(Status
== STATUS_SUCCESS
);
96 // Create the memory area to define the PTE base
98 BaseAddress
= (PVOID
)PTE_BASE
;
99 Status
= MmCreateMemoryArea(MmGetKernelAddressSpace(),
100 MEMORY_AREA_OWNED_BY_ARM3
| MEMORY_AREA_STATIC
,
102 PTE_TOP
- PTE_BASE
+ 1,
107 BoundaryAddressMultiple
);
108 ASSERT(Status
== STATUS_SUCCESS
);
111 // Create the memory area to define Hyperspace
113 BaseAddress
= (PVOID
)HYPER_SPACE
;
114 Status
= MmCreateMemoryArea(MmGetKernelAddressSpace(),
115 MEMORY_AREA_OWNED_BY_ARM3
| MEMORY_AREA_STATIC
,
117 HYPER_SPACE_END
- HYPER_SPACE
+ 1,
122 BoundaryAddressMultiple
);
123 ASSERT(Status
== STATUS_SUCCESS
);
126 // Protect the PFN database
128 BaseAddress
= MmPfnDatabase
;
129 Status
= MmCreateMemoryArea(MmGetKernelAddressSpace(),
130 MEMORY_AREA_OWNED_BY_ARM3
| MEMORY_AREA_STATIC
,
132 (MxPfnAllocation
<< PAGE_SHIFT
),
137 BoundaryAddressMultiple
);
138 ASSERT(Status
== STATUS_SUCCESS
);
141 // ReactOS requires a memory area to keep the initial NP area off-bounds
143 BaseAddress
= MmNonPagedPoolStart
;
144 Status
= MmCreateMemoryArea(MmGetKernelAddressSpace(),
145 MEMORY_AREA_OWNED_BY_ARM3
| MEMORY_AREA_STATIC
,
147 MmSizeOfNonPagedPoolInBytes
,
152 BoundaryAddressMultiple
);
153 ASSERT(Status
== STATUS_SUCCESS
);
156 // And we need one more for the system NP
158 BaseAddress
= MmNonPagedSystemStart
;
159 Status
= MmCreateMemoryArea(MmGetKernelAddressSpace(),
160 MEMORY_AREA_OWNED_BY_ARM3
| MEMORY_AREA_STATIC
,
162 (MmNumberOfSystemPtes
+ 1) * PAGE_SIZE
,
167 BoundaryAddressMultiple
);
168 ASSERT(Status
== STATUS_SUCCESS
);
171 // We also need one for system view space
173 BaseAddress
= MiSystemViewStart
;
174 Status
= MmCreateMemoryArea(MmGetKernelAddressSpace(),
175 MEMORY_AREA_OWNED_BY_ARM3
| MEMORY_AREA_STATIC
,
182 BoundaryAddressMultiple
);
183 ASSERT(Status
== STATUS_SUCCESS
);
186 // And another for session space
188 BaseAddress
= MmSessionBase
;
189 Status
= MmCreateMemoryArea(MmGetKernelAddressSpace(),
190 MEMORY_AREA_OWNED_BY_ARM3
| MEMORY_AREA_STATIC
,
192 (ULONG_PTR
)MiSessionSpaceEnd
-
193 (ULONG_PTR
)MmSessionBase
,
198 BoundaryAddressMultiple
);
199 ASSERT(Status
== STATUS_SUCCESS
);
202 // One more for ARM paged pool
204 BaseAddress
= MmPagedPoolStart
;
205 Status
= MmCreateMemoryArea(MmGetKernelAddressSpace(),
206 MEMORY_AREA_OWNED_BY_ARM3
| MEMORY_AREA_STATIC
,
208 MmSizeOfPagedPoolInBytes
,
213 BoundaryAddressMultiple
);
214 ASSERT(Status
== STATUS_SUCCESS
);
217 // And now, ReactOS paged pool
219 BaseAddress
= MmPagedPoolBase
;
220 Status
= MmCreateMemoryArea(MmGetKernelAddressSpace(),
221 MEMORY_AREA_PAGED_POOL
| MEMORY_AREA_STATIC
,
228 BoundaryAddressMultiple
);
229 ASSERT(Status
== STATUS_SUCCESS
);
234 BaseAddress
= (PVOID
)PCR
;
235 Status
= MmCreateMemoryArea(MmGetKernelAddressSpace(),
236 MEMORY_AREA_OWNED_BY_ARM3
| MEMORY_AREA_STATIC
,
238 PAGE_SIZE
* KeNumberProcessors
,
243 BoundaryAddressMultiple
);
244 ASSERT(Status
== STATUS_SUCCESS
);
247 // Now the KUSER_SHARED_DATA
249 BaseAddress
= (PVOID
)KI_USER_SHARED_DATA
;
250 Status
= MmCreateMemoryArea(MmGetKernelAddressSpace(),
251 MEMORY_AREA_OWNED_BY_ARM3
| MEMORY_AREA_STATIC
,
258 BoundaryAddressMultiple
);
259 ASSERT(Status
== STATUS_SUCCESS
);
262 // And the debugger mapping
264 BaseAddress
= MI_DEBUG_MAPPING
;
265 Status
= MmCreateMemoryArea(MmGetKernelAddressSpace(),
266 MEMORY_AREA_OWNED_BY_ARM3
| MEMORY_AREA_STATIC
,
273 BoundaryAddressMultiple
);
274 ASSERT(Status
== STATUS_SUCCESS
);
278 // Finally, reserve the 2 pages we currently make use of for HAL mappings
280 BaseAddress
= (PVOID
)0xFFC00000;
281 Status
= MmCreateMemoryArea(MmGetKernelAddressSpace(),
282 MEMORY_AREA_OWNED_BY_ARM3
| MEMORY_AREA_STATIC
,
289 BoundaryAddressMultiple
);
290 ASSERT(Status
== STATUS_SUCCESS
);
296 MiDbgDumpAddressSpace(VOID
)
299 // Print the memory layout
301 DPRINT1(" 0x%p - 0x%p\t%s\n",
303 (ULONG_PTR
)KSEG0_BASE
+ MmBootImageSize
,
304 "Boot Loaded Image");
305 DPRINT1(" 0x%p - 0x%p\t%s\n",
307 (ULONG_PTR
)MmPagedPoolBase
+ MmPagedPoolSize
,
309 DPRINT1(" 0x%p - 0x%p\t%s\n",
311 (ULONG_PTR
)MmPfnDatabase
+ (MxPfnAllocation
<< PAGE_SHIFT
),
313 DPRINT1(" 0x%p - 0x%p\t%s\n",
315 (ULONG_PTR
)MmNonPagedPoolStart
+ MmSizeOfNonPagedPoolInBytes
,
316 "ARM³ Non Paged Pool");
317 DPRINT1(" 0x%p - 0x%p\t%s\n",
319 (ULONG_PTR
)MiSystemViewStart
+ MmSystemViewSize
,
320 "System View Space");
321 DPRINT1(" 0x%p - 0x%p\t%s\n",
325 DPRINT1(" 0x%p - 0x%p\t%s\n",
328 DPRINT1(" 0x%p - 0x%p\t%s\n",
331 DPRINT1(" 0x%p - 0x%p\t%s\n",
332 HYPER_SPACE
, HYPER_SPACE_END
,
334 DPRINT1(" 0x%p - 0x%p\t%s\n",
336 (ULONG_PTR
)MmPagedPoolStart
+ MmSizeOfPagedPoolInBytes
,
338 DPRINT1(" 0x%p - 0x%p\t%s\n",
339 MmNonPagedSystemStart
, MmNonPagedPoolExpansionStart
,
341 DPRINT1(" 0x%p - 0x%p\t%s\n",
342 MmNonPagedPoolExpansionStart
, MmNonPagedPoolEnd
,
343 "Non Paged Pool Expansion PTE Space");
348 MiDbgDumpMemoryDescriptors(VOID
)
350 PLIST_ENTRY NextEntry
;
351 PMEMORY_ALLOCATION_DESCRIPTOR Md
;
352 ULONG TotalPages
= 0;
354 DPRINT1("Base\t\tLength\t\tType\n");
355 for (NextEntry
= KeLoaderBlock
->MemoryDescriptorListHead
.Flink
;
356 NextEntry
!= &KeLoaderBlock
->MemoryDescriptorListHead
;
357 NextEntry
= NextEntry
->Flink
)
359 Md
= CONTAINING_RECORD(NextEntry
, MEMORY_ALLOCATION_DESCRIPTOR
, ListEntry
);
360 DPRINT1("%08lX\t%08lX\t%s\n", Md
->BasePage
, Md
->PageCount
, MemType
[Md
->MemoryType
]);
361 TotalPages
+= Md
->PageCount
;
364 DPRINT1("Total: %08lX (%d MB)\n", TotalPages
, (TotalPages
* PAGE_SIZE
) / 1024 / 1024);
369 MmInitSystem(IN ULONG Phase
,
370 IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
372 extern MMPTE HyperTemplatePte
;
374 MMPTE TempPte
= HyperTemplatePte
;
375 PFN_NUMBER PageFrameNumber
;
379 /* Initialize the kernel address space */
380 KeInitializeGuardedMutex(&PsGetCurrentProcess()->AddressCreationLock
);
381 MmKernelAddressSpace
= MmGetCurrentAddressSpace();
382 MmInitGlobalKernelPageDirectory();
384 /* Dump memory descriptors */
385 if (MiDbgEnableMdDump
) MiDbgDumpMemoryDescriptors();
388 // Initialize ARM³ in phase 0
390 MmArmInitSystem(0, KeLoaderBlock
);
392 /* Initialize the page list */
393 MmInitializePageList();
396 // Initialize ARM³ in phase 1
398 MmArmInitSystem(1, KeLoaderBlock
);
402 // Everything required for the debugger to read and write
403 // physical memory is now set up
405 MmDebugPte
= MiAddressToPte(MiDebugMapping
);
408 /* Put the paged pool after the loaded modules */
409 MmPagedPoolBase
= (PVOID
)PAGE_ROUND_UP((ULONG_PTR
)MmSystemRangeStart
+
411 MmPagedPoolSize
= MM_PAGED_POOL_SIZE
;
413 /* Intialize system memory areas */
414 MiInitSystemMemoryAreas();
417 // STEP 1: Allocate and free a single page, repeatedly
418 // We should always get the same address back
422 PULONG Test
, OldTest
;
425 OldTest
= Test
= MiAllocatePoolPages(PagedPool
, PAGE_SIZE
);
427 for (i
= 0; i
< 16; i
++)
429 MiFreePoolPages(Test
);
430 Test
= MiAllocatePoolPages(PagedPool
, PAGE_SIZE
);
431 ASSERT(OldTest
== Test
);
433 MiFreePoolPages(Test
);
437 // STEP 2: Allocate 2048 pages without freeing them
438 // We should run out of space at 1024 pages, since we don't support
446 for (i
= 0; i
< 2048; i
++)
448 Test
[i
] = MiAllocatePoolPages(PagedPool
, PAGE_SIZE
);
451 ASSERT(i
== PTE_PER_PAGE
);
459 while (--i
) if (Test
[i
]) MiFreePoolPages(Test
[i
]);
463 // STEP 3: Allocate a page and touch it.
464 // We should get an ARM3 page fault and it should handle the fault
470 Test
= MiAllocatePoolPages(PagedPool
, PAGE_SIZE
);
472 MiFreePoolPages(Test
);
475 /* Dump the address space */
476 MiDbgDumpAddressSpace();
478 /* Initialize paged pool */
479 MmInitializePagedPool();
481 /* Initialize working sets */
482 MmInitializeMemoryConsumer(MC_USER
, MmTrimUserMemory
);
484 /* Initialize the user mode image list */
485 InitializeListHead(&MmLoadedUserImageList
);
487 /* Initialize the Loader Lock */
488 KeInitializeMutant(&MmSystemLoadLock
, FALSE
);
490 /* Reload boot drivers */
491 MiReloadBootLoadedDrivers(LoaderBlock
);
493 /* Initialize the loaded module list */
494 MiInitializeLoadedModuleList(LoaderBlock
);
496 /* Setup shared user data settings that NT does as well */
497 ASSERT(SharedUserData
->NumberOfPhysicalPages
== 0);
498 SharedUserData
->NumberOfPhysicalPages
= MmNumberOfPhysicalPages
;
499 SharedUserData
->LargePageMinimum
= 0;
501 /* For now, we assume that we're always Server */
502 SharedUserData
->NtProductType
= NtProductServer
;
506 MmInitializeRmapList();
507 MmInitializePageOp();
508 MmInitSectionImplementation();
512 // Create a PTE to double-map the shared data section. We allocate it
513 // from paged pool so that we can't fault when trying to touch the PTE
514 // itself (to map it), since paged pool addresses will already be mapped
515 // by the fault handler.
517 MmSharedUserDataPte
= ExAllocatePoolWithTag(PagedPool
,
520 if (!MmSharedUserDataPte
) return FALSE
;
523 // Now get the PTE for shared data, and read the PFN that holds it
525 PointerPte
= MiAddressToPte((PVOID
)KI_USER_SHARED_DATA
);
526 ASSERT(PointerPte
->u
.Hard
.Valid
== 1);
527 PageFrameNumber
= PFN_FROM_PTE(PointerPte
);
530 // Now write a copy of it
532 MI_MAKE_OWNER_PAGE(&TempPte
);
533 TempPte
.u
.Hard
.PageFrameNumber
= PageFrameNumber
;
534 *MmSharedUserDataPte
= TempPte
;
539 MiInitBalancerThread();
542 * Initialise the modified page writer.
546 /* Initialize the balance set manager */