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 *********************************************************/
42 // Helper function to create initial memory areas.
43 // The created area is always read/write.
48 MiCreateArm3StaticMemoryArea(PVOID BaseAddress
, ULONG Size
, BOOLEAN Executable
)
50 const ULONG Protection
= Executable
? PAGE_EXECUTE_READWRITE
: PAGE_READWRITE
;
51 PVOID pBaseAddress
= BaseAddress
;
55 Status
= MmCreateMemoryArea(MmGetKernelAddressSpace(),
56 MEMORY_AREA_OWNED_BY_ARM3
| MEMORY_AREA_STATIC
,
63 ASSERT(Status
== STATUS_SUCCESS
);
64 // TODO: Perhaps it would be prudent to bugcheck here, not only assert?
70 MiInitSystemMemoryAreas(VOID
)
73 // Create all the static memory areas.
76 // The loader mappings. The only Executable area.
77 MiCreateArm3StaticMemoryArea((PVOID
)KSEG0_BASE
, MmBootImageSize
, TRUE
);
80 MiCreateArm3StaticMemoryArea((PVOID
)PTE_BASE
, PTE_TOP
- PTE_BASE
+ 1, FALSE
);
83 MiCreateArm3StaticMemoryArea((PVOID
)HYPER_SPACE
, HYPER_SPACE_END
- HYPER_SPACE
+ 1, FALSE
);
85 // Protect the PFN database
86 MiCreateArm3StaticMemoryArea(MmPfnDatabase
, (MxPfnAllocation
<< PAGE_SHIFT
), FALSE
);
88 // ReactOS requires a memory area to keep the initial NP area off-bounds
89 MiCreateArm3StaticMemoryArea(MmNonPagedPoolStart
, MmSizeOfNonPagedPoolInBytes
, FALSE
);
92 MiCreateArm3StaticMemoryArea(MmNonPagedSystemStart
, MiNonPagedSystemSize
, FALSE
);
95 MiCreateArm3StaticMemoryArea(MiSystemViewStart
, MmSystemViewSize
, FALSE
);
98 MiCreateArm3StaticMemoryArea(MmSessionBase
, (ULONG_PTR
)MiSessionSpaceEnd
- (ULONG_PTR
)MmSessionBase
, FALSE
);
101 MiCreateArm3StaticMemoryArea(MmPagedPoolStart
, MmSizeOfPagedPoolInBytes
, FALSE
);
104 MiCreateArm3StaticMemoryArea(MI_DEBUG_MAPPING
, PAGE_SIZE
, FALSE
);
107 // Reserved HAL area (includes KUSER_SHARED_DATA and KPCR)
108 MiCreateArm3StaticMemoryArea((PVOID
)MM_HAL_VA_START
, MM_HAL_VA_END
- MM_HAL_VA_START
+ 1, FALSE
);
111 // KPCR, one page per CPU. Only for 32-bit kernel.
112 MiCreateArm3StaticMemoryArea(PCR
, PAGE_SIZE
* KeNumberProcessors
, FALSE
);
113 #endif /* _M_AMD64 */
116 MiCreateArm3StaticMemoryArea((PVOID
)KI_USER_SHARED_DATA
, PAGE_SIZE
, FALSE
);
123 MiDbgDumpAddressSpace(VOID
)
126 // Print the memory layout
128 DPRINT1(" 0x%p - 0x%p\t%s\n",
130 (ULONG_PTR
)KSEG0_BASE
+ MmBootImageSize
,
131 "Boot Loaded Image");
132 DPRINT1(" 0x%p - 0x%p\t%s\n",
134 (ULONG_PTR
)MmPfnDatabase
+ (MxPfnAllocation
<< PAGE_SHIFT
),
136 DPRINT1(" 0x%p - 0x%p\t%s\n",
138 (ULONG_PTR
)MmNonPagedPoolStart
+ MmSizeOfNonPagedPoolInBytes
,
139 "ARM3 Non Paged Pool");
140 DPRINT1(" 0x%p - 0x%p\t%s\n",
142 (ULONG_PTR
)MiSystemViewStart
+ MmSystemViewSize
,
143 "System View Space");
144 DPRINT1(" 0x%p - 0x%p\t%s\n",
148 DPRINT1(" 0x%p - 0x%p\t%s\n",
151 DPRINT1(" 0x%p - 0x%p\t%s\n",
154 DPRINT1(" 0x%p - 0x%p\t%s\n",
155 HYPER_SPACE
, HYPER_SPACE_END
,
157 DPRINT1(" 0x%p - 0x%p\t%s\n",
159 (ULONG_PTR
)MmPagedPoolStart
+ MmSizeOfPagedPoolInBytes
,
161 DPRINT1(" 0x%p - 0x%p\t%s\n",
162 MmNonPagedSystemStart
, MmNonPagedPoolExpansionStart
,
164 DPRINT1(" 0x%p - 0x%p\t%s\n",
165 MmNonPagedPoolExpansionStart
, MmNonPagedPoolEnd
,
166 "Non Paged Pool Expansion PTE Space");
171 MmMpwThreadMain(PVOID Parameter
)
177 LARGE_INTEGER Timeout
;
179 UNREFERENCED_PARAMETER(Parameter
);
181 Timeout
.QuadPart
= -50000000;
185 Status
= KeWaitForSingleObject(&MpwThreadEvent
,
190 if (!NT_SUCCESS(Status
))
192 DbgPrint("MpwThread: Wait failed\n");
193 KeBugCheck(MEMORY_MANAGEMENT
);
200 // XXX arty -- we flush when evicting pages or destorying cache
202 CcRosFlushDirtyPages(128, &PagesWritten
, FALSE
);
210 MmInitMpwThread(VOID
)
214 CLIENT_ID MpwThreadId
;
216 KeInitializeEvent(&MpwThreadEvent
, SynchronizationEvent
, FALSE
);
218 Status
= PsCreateSystemThread(&MpwThreadHandle
,
225 if (!NT_SUCCESS(Status
))
231 NtSetInformationThread(MpwThreadHandle
,
236 return(STATUS_SUCCESS
);
242 MmInitBsmThread(VOID
)
245 OBJECT_ATTRIBUTES ObjectAttributes
;
248 /* Create the thread */
249 InitializeObjectAttributes(&ObjectAttributes
, NULL
, 0, NULL
, NULL
);
250 Status
= PsCreateSystemThread(&ThreadHandle
,
258 /* Close the handle and return status */
259 ZwClose(ThreadHandle
);
266 MmInitSystem(IN ULONG Phase
,
267 IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
269 extern MMPTE ValidKernelPte
;
271 MMPTE TempPte
= ValidKernelPte
;
272 PFN_NUMBER PageFrameNumber
;
274 /* Initialize the kernel address space */
277 InitializeListHead(&MiSegmentList
);
278 ExInitializeFastMutex(&MiGlobalPageOperation
);
279 KeInitializeEvent(&MmWaitPageEvent
, SynchronizationEvent
, FALSE
);
280 // Until we're fully demand paged, we can do things the old way through
281 // the balance manager
282 MmInitializeMemoryConsumer(MC_CACHE
, MiRosTrimCache
);
284 MmKernelAddressSpace
= &PsIdleProcess
->Vm
;
286 /* Intialize system memory areas */
287 MiInitSystemMemoryAreas();
289 /* Dump the address space */
290 MiDbgDumpAddressSpace();
292 MmInitGlobalKernelPageDirectory();
293 MiInitializeUserPfnBitmap();
294 MmInitializeMemoryConsumer(MC_USER
, MmTrimUserMemory
);
295 MmInitializeRmapList();
296 MmInitSectionImplementation();
300 // Create a PTE to double-map the shared data section. We allocate it
301 // from paged pool so that we can't fault when trying to touch the PTE
302 // itself (to map it), since paged pool addresses will already be mapped
303 // by the fault handler.
305 MmSharedUserDataPte
= ExAllocatePoolWithTag(PagedPool
,
308 if (!MmSharedUserDataPte
) return FALSE
;
311 // Now get the PTE for shared data, and read the PFN that holds it
313 PointerPte
= MiAddressToPte((PVOID
)KI_USER_SHARED_DATA
);
314 ASSERT(PointerPte
->u
.Hard
.Valid
== 1);
315 PageFrameNumber
= PFN_FROM_PTE(PointerPte
);
317 /* Build the PTE and write it */
318 MI_MAKE_HARDWARE_PTE_KERNEL(&TempPte
,
322 *MmSharedUserDataPte
= TempPte
;
324 /* Initialize session working set support */
325 MiInitializeSessionWsSupport();
327 /* Setup session IDs */
328 MiInitializeSessionIds();
330 /* Setup the memory threshold events */
331 if (!MiInitializeMemoryEvents()) return FALSE
;
336 MiInitBalancerThread();
339 * Initialise the modified page writer.
343 /* Initialize the balance set manager */