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 *******************************************************************/
20 VOID NTAPI
MiInitializeUserPfnBitmap(VOID
);
53 HANDLE MpwThreadHandle
;
54 KEVENT MpwThreadEvent
;
56 BOOLEAN Mm64BitPhysicalAddress
= FALSE
;
57 ULONG MmReadClusterSize
;
59 // 0 | 1 is on/off paging, 2 is undocumented
61 UCHAR MmDisablePagingExecutive
= 1; // Forced to off
62 PMMPTE MmSharedUserDataPte
;
63 PMMSUPPORT MmKernelAddressSpace
;
64 BOOLEAN MiDbgEnableMdDump
=
71 /* PRIVATE FUNCTIONS *********************************************************/
76 MiInitSystemMemoryAreas()
79 PHYSICAL_ADDRESS BoundaryAddressMultiple
;
82 BoundaryAddressMultiple
.QuadPart
= 0;
85 // Create the memory area to define the PTE base
87 BaseAddress
= (PVOID
)PTE_BASE
;
88 Status
= MmCreateMemoryArea(MmGetKernelAddressSpace(),
89 MEMORY_AREA_OWNED_BY_ARM3
| MEMORY_AREA_STATIC
,
96 BoundaryAddressMultiple
);
97 ASSERT(Status
== STATUS_SUCCESS
);
100 // Create the memory area to define Hyperspace
102 BaseAddress
= (PVOID
)HYPER_SPACE
;
103 Status
= MmCreateMemoryArea(MmGetKernelAddressSpace(),
104 MEMORY_AREA_OWNED_BY_ARM3
| MEMORY_AREA_STATIC
,
111 BoundaryAddressMultiple
);
112 ASSERT(Status
== STATUS_SUCCESS
);
115 // Protect the PFN database
117 BaseAddress
= MmPfnDatabase
;
118 Status
= MmCreateMemoryArea(MmGetKernelAddressSpace(),
119 MEMORY_AREA_OWNED_BY_ARM3
| MEMORY_AREA_STATIC
,
121 (MxPfnAllocation
<< PAGE_SHIFT
),
126 BoundaryAddressMultiple
);
127 ASSERT(Status
== STATUS_SUCCESS
);
130 // ReactOS requires a memory area to keep the initial NP area off-bounds
132 BaseAddress
= MmNonPagedPoolStart
;
133 Status
= MmCreateMemoryArea(MmGetKernelAddressSpace(),
134 MEMORY_AREA_OWNED_BY_ARM3
| MEMORY_AREA_STATIC
,
136 MmSizeOfNonPagedPoolInBytes
,
141 BoundaryAddressMultiple
);
142 ASSERT(Status
== STATUS_SUCCESS
);
145 // And we need one more for the system NP
147 BaseAddress
= MmNonPagedSystemStart
;
148 Status
= MmCreateMemoryArea(MmGetKernelAddressSpace(),
149 MEMORY_AREA_OWNED_BY_ARM3
| MEMORY_AREA_STATIC
,
151 (ULONG_PTR
)MmNonPagedPoolEnd
-
152 (ULONG_PTR
)MmNonPagedSystemStart
,
157 BoundaryAddressMultiple
);
158 ASSERT(Status
== STATUS_SUCCESS
);
161 // We also need one for system view space
163 BaseAddress
= MiSystemViewStart
;
164 Status
= MmCreateMemoryArea(MmGetKernelAddressSpace(),
165 MEMORY_AREA_OWNED_BY_ARM3
| MEMORY_AREA_STATIC
,
172 BoundaryAddressMultiple
);
173 ASSERT(Status
== STATUS_SUCCESS
);
176 // And another for session space
178 BaseAddress
= MmSessionBase
;
179 Status
= MmCreateMemoryArea(MmGetKernelAddressSpace(),
180 MEMORY_AREA_OWNED_BY_ARM3
| MEMORY_AREA_STATIC
,
182 (ULONG_PTR
)MiSessionSpaceEnd
-
183 (ULONG_PTR
)MmSessionBase
,
188 BoundaryAddressMultiple
);
189 ASSERT(Status
== STATUS_SUCCESS
);
192 // One more for ARM paged pool
194 BaseAddress
= MmPagedPoolStart
;
195 Status
= MmCreateMemoryArea(MmGetKernelAddressSpace(),
196 MEMORY_AREA_OWNED_BY_ARM3
| MEMORY_AREA_STATIC
,
198 MmSizeOfPagedPoolInBytes
,
203 BoundaryAddressMultiple
);
204 ASSERT(Status
== STATUS_SUCCESS
);
209 BaseAddress
= (PVOID
)PCR
;
210 Status
= MmCreateMemoryArea(MmGetKernelAddressSpace(),
211 MEMORY_AREA_OWNED_BY_ARM3
| MEMORY_AREA_STATIC
,
213 PAGE_SIZE
* KeNumberProcessors
,
218 BoundaryAddressMultiple
);
219 ASSERT(Status
== STATUS_SUCCESS
);
222 // Now the KUSER_SHARED_DATA
224 BaseAddress
= (PVOID
)KI_USER_SHARED_DATA
;
225 Status
= MmCreateMemoryArea(MmGetKernelAddressSpace(),
226 MEMORY_AREA_OWNED_BY_ARM3
| MEMORY_AREA_STATIC
,
233 BoundaryAddressMultiple
);
234 ASSERT(Status
== STATUS_SUCCESS
);
237 // And the debugger mapping
239 BaseAddress
= MI_DEBUG_MAPPING
;
240 Status
= MmCreateMemoryArea(MmGetKernelAddressSpace(),
241 MEMORY_AREA_OWNED_BY_ARM3
| MEMORY_AREA_STATIC
,
248 BoundaryAddressMultiple
);
249 ASSERT(Status
== STATUS_SUCCESS
);
253 // Finally, reserve the 2 pages we currently make use of for HAL mappings
255 BaseAddress
= (PVOID
)0xFFC00000;
256 Status
= MmCreateMemoryArea(MmGetKernelAddressSpace(),
257 MEMORY_AREA_OWNED_BY_ARM3
| MEMORY_AREA_STATIC
,
264 BoundaryAddressMultiple
);
265 ASSERT(Status
== STATUS_SUCCESS
);
271 MiDbgDumpAddressSpace(VOID
)
274 // Print the memory layout
276 DPRINT1(" 0x%p - 0x%p\t%s\n",
278 (ULONG_PTR
)MmSystemRangeStart
+ MmBootImageSize
,
279 "Boot Loaded Image");
280 DPRINT1(" 0x%p - 0x%p\t%s\n",
282 (ULONG_PTR
)MmPfnDatabase
+ (MxPfnAllocation
<< PAGE_SHIFT
),
284 DPRINT1(" 0x%p - 0x%p\t%s\n",
286 (ULONG_PTR
)MmNonPagedPoolStart
+ MmSizeOfNonPagedPoolInBytes
,
287 "ARM³ Non Paged Pool");
288 DPRINT1(" 0x%p - 0x%p\t%s\n",
290 (ULONG_PTR
)MiSystemViewStart
+ MmSystemViewSize
,
291 "System View Space");
292 DPRINT1(" 0x%p - 0x%p\t%s\n",
296 DPRINT1(" 0x%p - 0x%p\t%s\n",
299 DPRINT1(" 0x%p - 0x%p\t%s\n",
300 PDE_BASE
, HYPER_SPACE
,
302 DPRINT1(" 0x%p - 0x%p\t%s\n",
303 HYPER_SPACE
, HYPER_SPACE
+ (4 * 1024 * 1024),
305 DPRINT1(" 0x%p - 0x%p\t%s\n",
307 (ULONG_PTR
)MmPagedPoolStart
+ MmSizeOfPagedPoolInBytes
,
309 DPRINT1(" 0x%p - 0x%p\t%s\n",
310 MmNonPagedSystemStart
, MmNonPagedPoolExpansionStart
,
312 DPRINT1(" 0x%p - 0x%p\t%s\n",
313 MmNonPagedPoolExpansionStart
, MmNonPagedPoolEnd
,
314 "Non Paged Pool Expansion PTE Space");
319 MiDbgDumpMemoryDescriptors(VOID
)
321 PLIST_ENTRY NextEntry
;
322 PMEMORY_ALLOCATION_DESCRIPTOR Md
;
323 ULONG TotalPages
= 0;
325 DPRINT1("Base\t\tLength\t\tType\n");
326 for (NextEntry
= KeLoaderBlock
->MemoryDescriptorListHead
.Flink
;
327 NextEntry
!= &KeLoaderBlock
->MemoryDescriptorListHead
;
328 NextEntry
= NextEntry
->Flink
)
330 Md
= CONTAINING_RECORD(NextEntry
, MEMORY_ALLOCATION_DESCRIPTOR
, ListEntry
);
331 DPRINT1("%08lX\t%08lX\t%s\n", Md
->BasePage
, Md
->PageCount
, MemType
[Md
->MemoryType
]);
332 TotalPages
+= Md
->PageCount
;
335 DPRINT1("Total: %08lX (%d MB)\n", TotalPages
, (TotalPages
* PAGE_SIZE
) / 1024 / 1024);
339 MmMpwThreadMain(PVOID Ignored
)
343 LARGE_INTEGER Timeout
;
345 Timeout
.QuadPart
= -50000000;
349 Status
= KeWaitForSingleObject(&MpwThreadEvent
,
354 if (!NT_SUCCESS(Status
))
356 DbgPrint("MpwThread: Wait failed\n");
357 KeBugCheck(MEMORY_MANAGEMENT
);
358 return(STATUS_UNSUCCESSFUL
);
363 CcRosFlushDirtyPages(128, &PagesWritten
);
369 MmInitMpwThread(VOID
)
373 CLIENT_ID MpwThreadId
;
375 KeInitializeEvent(&MpwThreadEvent
, SynchronizationEvent
, FALSE
);
377 Status
= PsCreateSystemThread(&MpwThreadHandle
,
382 (PKSTART_ROUTINE
) MmMpwThreadMain
,
384 if (!NT_SUCCESS(Status
))
390 NtSetInformationThread(MpwThreadHandle
,
395 return(STATUS_SUCCESS
);
400 MmInitBsmThread(VOID
)
403 OBJECT_ATTRIBUTES ObjectAttributes
;
406 /* Create the thread */
407 InitializeObjectAttributes(&ObjectAttributes
, NULL
, 0, NULL
, NULL
);
408 Status
= PsCreateSystemThread(&ThreadHandle
,
416 /* Close the handle and return status */
417 ZwClose(ThreadHandle
);
423 MmInitSystem(IN ULONG Phase
,
424 IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
426 extern MMPTE ValidKernelPte
;
428 MMPTE TempPte
= ValidKernelPte
;
429 PFN_NUMBER PageFrameNumber
;
433 /* Initialize the kernel address space */
434 KeInitializeGuardedMutex(&PsGetCurrentProcess()->AddressCreationLock
);
435 MmKernelAddressSpace
= MmGetCurrentAddressSpace();
436 MmInitGlobalKernelPageDirectory();
438 /* Dump memory descriptors */
439 if (MiDbgEnableMdDump
) MiDbgDumpMemoryDescriptors();
441 /* Initialize ARM³ in phase 0 */
442 MmArmInitSystem(0, KeLoaderBlock
);
444 /* Intialize system memory areas */
445 MiInitSystemMemoryAreas();
447 /* Dump the address space */
448 MiDbgDumpAddressSpace();
452 MiInitializeUserPfnBitmap();
453 MmInitializeMemoryConsumer(MC_USER
, MmTrimUserMemory
);
454 MmInitializeRmapList();
455 MmInitializePageOp();
456 MmInitSectionImplementation();
460 // Create a PTE to double-map the shared data section. We allocate it
461 // from paged pool so that we can't fault when trying to touch the PTE
462 // itself (to map it), since paged pool addresses will already be mapped
463 // by the fault handler.
465 MmSharedUserDataPte
= ExAllocatePoolWithTag(PagedPool
,
468 if (!MmSharedUserDataPte
) return FALSE
;
471 // Now get the PTE for shared data, and read the PFN that holds it
473 PointerPte
= MiAddressToPte((PVOID
)KI_USER_SHARED_DATA
);
474 ASSERT(PointerPte
->u
.Hard
.Valid
== 1);
475 PageFrameNumber
= PFN_FROM_PTE(PointerPte
);
477 /* Build the PTE and write it */
478 MI_MAKE_HARDWARE_PTE_KERNEL(&TempPte
,
482 *MmSharedUserDataPte
= TempPte
;
484 /* Setup the memory threshold events */
485 if (!MiInitializeMemoryEvents()) return FALSE
;
490 MiInitBalancerThread();
493 * Initialise the modified page writer.
497 /* Initialize the balance set manager */