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
);
22 HANDLE MpwThreadHandle
;
23 KEVENT MpwThreadEvent
;
25 BOOLEAN Mm64BitPhysicalAddress
= FALSE
;
26 ULONG MmReadClusterSize
;
28 // 0 | 1 is on/off paging, 2 is undocumented
30 UCHAR MmDisablePagingExecutive
= 1; // Forced to off
31 PMMPTE MmSharedUserDataPte
;
32 PMMSUPPORT MmKernelAddressSpace
;
34 extern KEVENT MmWaitPageEvent
;
35 extern FAST_MUTEX MiGlobalPageOperation
;
36 extern LIST_ENTRY MiSegmentList
;
37 extern NTSTATUS
MiRosTrimCache(ULONG Target
, ULONG Priority
, PULONG NrFreed
);
39 /* PRIVATE FUNCTIONS *********************************************************/
44 MiInitSystemMemoryAreas()
47 PHYSICAL_ADDRESS BoundaryAddressMultiple
;
50 BoundaryAddressMultiple
.QuadPart
= 0;
53 // Create the memory area to define the loader mappings
55 BaseAddress
= (PVOID
)KSEG0_BASE
;
56 Status
= MmCreateMemoryArea(MmGetKernelAddressSpace(),
57 MEMORY_AREA_OWNED_BY_ARM3
| MEMORY_AREA_STATIC
,
60 PAGE_EXECUTE_READWRITE
,
64 BoundaryAddressMultiple
);
65 ASSERT(Status
== STATUS_SUCCESS
);
68 // Create the memory area to define the PTE base
70 BaseAddress
= (PVOID
)PTE_BASE
;
71 Status
= MmCreateMemoryArea(MmGetKernelAddressSpace(),
72 MEMORY_AREA_OWNED_BY_ARM3
| MEMORY_AREA_STATIC
,
74 PTE_TOP
- PTE_BASE
+ 1,
79 BoundaryAddressMultiple
);
80 ASSERT(Status
== STATUS_SUCCESS
);
83 // Create the memory area to define Hyperspace
85 BaseAddress
= (PVOID
)HYPER_SPACE
;
86 Status
= MmCreateMemoryArea(MmGetKernelAddressSpace(),
87 MEMORY_AREA_OWNED_BY_ARM3
| MEMORY_AREA_STATIC
,
89 HYPER_SPACE_END
- HYPER_SPACE
+ 1,
94 BoundaryAddressMultiple
);
95 ASSERT(Status
== STATUS_SUCCESS
);
98 // Protect the PFN database
100 BaseAddress
= MmPfnDatabase
;
101 Status
= MmCreateMemoryArea(MmGetKernelAddressSpace(),
102 MEMORY_AREA_OWNED_BY_ARM3
| MEMORY_AREA_STATIC
,
104 (MxPfnAllocation
<< PAGE_SHIFT
),
109 BoundaryAddressMultiple
);
110 ASSERT(Status
== STATUS_SUCCESS
);
113 // ReactOS requires a memory area to keep the initial NP area off-bounds
115 BaseAddress
= MmNonPagedPoolStart
;
116 Status
= MmCreateMemoryArea(MmGetKernelAddressSpace(),
117 MEMORY_AREA_OWNED_BY_ARM3
| MEMORY_AREA_STATIC
,
119 MmSizeOfNonPagedPoolInBytes
,
124 BoundaryAddressMultiple
);
125 ASSERT(Status
== STATUS_SUCCESS
);
128 // And we need one more for the system NP
130 BaseAddress
= MmNonPagedSystemStart
;
131 Status
= MmCreateMemoryArea(MmGetKernelAddressSpace(),
132 MEMORY_AREA_OWNED_BY_ARM3
| MEMORY_AREA_STATIC
,
134 MiNonPagedSystemSize
,
139 BoundaryAddressMultiple
);
140 ASSERT(Status
== STATUS_SUCCESS
);
143 // We also need one for system view space
145 BaseAddress
= MiSystemViewStart
;
146 Status
= MmCreateMemoryArea(MmGetKernelAddressSpace(),
147 MEMORY_AREA_OWNED_BY_ARM3
| MEMORY_AREA_STATIC
,
154 BoundaryAddressMultiple
);
155 ASSERT(Status
== STATUS_SUCCESS
);
158 // And another for session space
160 BaseAddress
= MmSessionBase
;
161 Status
= MmCreateMemoryArea(MmGetKernelAddressSpace(),
162 MEMORY_AREA_OWNED_BY_ARM3
| MEMORY_AREA_STATIC
,
164 (ULONG_PTR
)MiSessionSpaceEnd
-
165 (ULONG_PTR
)MmSessionBase
,
170 BoundaryAddressMultiple
);
171 ASSERT(Status
== STATUS_SUCCESS
);
174 // One more for ARM paged pool
176 BaseAddress
= MmPagedPoolStart
;
177 Status
= MmCreateMemoryArea(MmGetKernelAddressSpace(),
178 MEMORY_AREA_OWNED_BY_ARM3
| MEMORY_AREA_STATIC
,
180 MmSizeOfPagedPoolInBytes
,
185 BoundaryAddressMultiple
);
186 ASSERT(Status
== STATUS_SUCCESS
);
191 BaseAddress
= (PVOID
)PCR
;
192 Status
= MmCreateMemoryArea(MmGetKernelAddressSpace(),
193 MEMORY_AREA_OWNED_BY_ARM3
| MEMORY_AREA_STATIC
,
195 PAGE_SIZE
* KeNumberProcessors
,
200 BoundaryAddressMultiple
);
201 ASSERT(Status
== STATUS_SUCCESS
);
204 // Now the KUSER_SHARED_DATA
206 BaseAddress
= (PVOID
)KI_USER_SHARED_DATA
;
207 Status
= MmCreateMemoryArea(MmGetKernelAddressSpace(),
208 MEMORY_AREA_OWNED_BY_ARM3
| MEMORY_AREA_STATIC
,
215 BoundaryAddressMultiple
);
216 ASSERT(Status
== STATUS_SUCCESS
);
219 // And the debugger mapping
221 BaseAddress
= MI_DEBUG_MAPPING
;
222 Status
= MmCreateMemoryArea(MmGetKernelAddressSpace(),
223 MEMORY_AREA_OWNED_BY_ARM3
| MEMORY_AREA_STATIC
,
230 BoundaryAddressMultiple
);
231 ASSERT(Status
== STATUS_SUCCESS
);
235 // Finally, reserve the 2 pages we currently make use of for HAL mappings
237 BaseAddress
= (PVOID
)0xFFC00000;
238 Status
= MmCreateMemoryArea(MmGetKernelAddressSpace(),
239 MEMORY_AREA_OWNED_BY_ARM3
| MEMORY_AREA_STATIC
,
246 BoundaryAddressMultiple
);
247 ASSERT(Status
== STATUS_SUCCESS
);
254 MiDbgDumpAddressSpace(VOID
)
257 // Print the memory layout
259 DPRINT1(" 0x%p - 0x%p\t%s\n",
261 (ULONG_PTR
)KSEG0_BASE
+ MmBootImageSize
,
262 "Boot Loaded Image");
263 DPRINT1(" 0x%p - 0x%p\t%s\n",
265 (ULONG_PTR
)MmPfnDatabase
+ (MxPfnAllocation
<< PAGE_SHIFT
),
267 DPRINT1(" 0x%p - 0x%p\t%s\n",
269 (ULONG_PTR
)MmNonPagedPoolStart
+ MmSizeOfNonPagedPoolInBytes
,
270 "ARM3 Non Paged Pool");
271 DPRINT1(" 0x%p - 0x%p\t%s\n",
273 (ULONG_PTR
)MiSystemViewStart
+ MmSystemViewSize
,
274 "System View Space");
275 DPRINT1(" 0x%p - 0x%p\t%s\n",
279 DPRINT1(" 0x%p - 0x%p\t%s\n",
282 DPRINT1(" 0x%p - 0x%p\t%s\n",
285 DPRINT1(" 0x%p - 0x%p\t%s\n",
286 HYPER_SPACE
, HYPER_SPACE_END
,
288 DPRINT1(" 0x%p - 0x%p\t%s\n",
290 (ULONG_PTR
)MmPagedPoolStart
+ MmSizeOfPagedPoolInBytes
,
292 DPRINT1(" 0x%p - 0x%p\t%s\n",
293 MmNonPagedSystemStart
, MmNonPagedPoolExpansionStart
,
295 DPRINT1(" 0x%p - 0x%p\t%s\n",
296 MmNonPagedPoolExpansionStart
, MmNonPagedPoolEnd
,
297 "Non Paged Pool Expansion PTE Space");
301 MmMpwThreadMain(PVOID Ignored
)
305 LARGE_INTEGER Timeout
;
307 Timeout
.QuadPart
= -50000000;
311 Status
= KeWaitForSingleObject(&MpwThreadEvent
,
316 if (!NT_SUCCESS(Status
))
318 DbgPrint("MpwThread: Wait failed\n");
319 KeBugCheck(MEMORY_MANAGEMENT
);
320 return(STATUS_UNSUCCESSFUL
);
326 // XXX arty -- we flush when evicting pages or destorying cache
328 CcRosFlushDirtyPages(128, &PagesWritten
, FALSE
);
336 MmInitMpwThread(VOID
)
340 CLIENT_ID MpwThreadId
;
342 KeInitializeEvent(&MpwThreadEvent
, SynchronizationEvent
, FALSE
);
344 Status
= PsCreateSystemThread(&MpwThreadHandle
,
349 (PKSTART_ROUTINE
) MmMpwThreadMain
,
351 if (!NT_SUCCESS(Status
))
357 NtSetInformationThread(MpwThreadHandle
,
362 return(STATUS_SUCCESS
);
368 MmInitBsmThread(VOID
)
371 OBJECT_ATTRIBUTES ObjectAttributes
;
374 /* Create the thread */
375 InitializeObjectAttributes(&ObjectAttributes
, NULL
, 0, NULL
, NULL
);
376 Status
= PsCreateSystemThread(&ThreadHandle
,
384 /* Close the handle and return status */
385 ZwClose(ThreadHandle
);
392 MmInitSystem(IN ULONG Phase
,
393 IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
395 extern MMPTE ValidKernelPte
;
397 MMPTE TempPte
= ValidKernelPte
;
398 PFN_NUMBER PageFrameNumber
;
400 /* Initialize the kernel address space */
403 InitializeListHead(&MiSegmentList
);
404 ExInitializeFastMutex(&MiGlobalPageOperation
);
405 KeInitializeEvent(&MmWaitPageEvent
, SynchronizationEvent
, FALSE
);
406 // Until we're fully demand paged, we can do things the old way through
407 // the balance manager
408 MmInitializeMemoryConsumer(MC_CACHE
, MiRosTrimCache
);
410 MmKernelAddressSpace
= &PsIdleProcess
->Vm
;
412 /* Intialize system memory areas */
413 MiInitSystemMemoryAreas();
415 /* Dump the address space */
416 MiDbgDumpAddressSpace();
418 MmInitGlobalKernelPageDirectory();
419 MiInitializeUserPfnBitmap();
420 MmInitializeMemoryConsumer(MC_USER
, MmTrimUserMemory
);
421 MmInitializeRmapList();
422 MmInitSectionImplementation();
426 // Create a PTE to double-map the shared data section. We allocate it
427 // from paged pool so that we can't fault when trying to touch the PTE
428 // itself (to map it), since paged pool addresses will already be mapped
429 // by the fault handler.
431 MmSharedUserDataPte
= ExAllocatePoolWithTag(PagedPool
,
434 if (!MmSharedUserDataPte
) return FALSE
;
437 // Now get the PTE for shared data, and read the PFN that holds it
439 PointerPte
= MiAddressToPte((PVOID
)KI_USER_SHARED_DATA
);
440 ASSERT(PointerPte
->u
.Hard
.Valid
== 1);
441 PageFrameNumber
= PFN_FROM_PTE(PointerPte
);
443 /* Build the PTE and write it */
444 MI_MAKE_HARDWARE_PTE_KERNEL(&TempPte
,
448 *MmSharedUserDataPte
= TempPte
;
450 /* Setup session IDs */
451 MiInitializeSessionIds();
453 /* Setup the memory threshold events */
454 if (!MiInitializeMemoryEvents()) return FALSE
;
459 MiInitBalancerThread();
462 * Initialise the modified page writer.
466 /* Initialize the balance set manager */