1 /* 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 6 * PROGRAMMERS: 7 */ 8 9 /* INCLUDES ******************************************************************/ 10 11 #include <ntoskrnl.h> 12 #define NDEBUG 13 #include <debug.h> 14 15 #define MODULE_INVOLVED_IN_ARM3 16 #include "ARM3/miarm.h" 17 18 /* GLOBALS *******************************************************************/ 19 20 VOID NTAPI MiInitializeUserPfnBitmap(VOID); 21 22 BOOLEAN Mm64BitPhysicalAddress = FALSE; 23 ULONG MmReadClusterSize; 24 // 25 // 0 | 1 is on/off paging, 2 is undocumented 26 // 27 UCHAR MmDisablePagingExecutive = 1; // Forced to off 28 PMMPTE MmSharedUserDataPte; 29 PMMSUPPORT MmKernelAddressSpace; 30 31 extern KEVENT MmWaitPageEvent; 32 extern FAST_MUTEX MiGlobalPageOperation; 33 extern LIST_ENTRY MiSegmentList; 34 extern NTSTATUS MiRosTrimCache(ULONG Target, ULONG Priority, PULONG NrFreed); 35 36 /* PRIVATE FUNCTIONS *********************************************************/ 37 38 // 39 // Helper function to create initial memory areas. 40 // The created area is always read/write. 41 // 42 INIT_FUNCTION 43 VOID 44 NTAPI 45 MiCreateArm3StaticMemoryArea(PVOID BaseAddress, SIZE_T Size, BOOLEAN Executable) 46 { 47 const ULONG Protection = Executable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE; 48 PVOID pBaseAddress = BaseAddress; 49 PMEMORY_AREA MArea; 50 NTSTATUS Status; 51 52 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(), 53 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC, 54 &pBaseAddress, 55 Size, 56 Protection, 57 &MArea, 58 0, 59 PAGE_SIZE); 60 ASSERT(Status == STATUS_SUCCESS); 61 // TODO: Perhaps it would be prudent to bugcheck here, not only assert? 62 } 63 64 INIT_FUNCTION 65 VOID 66 NTAPI 67 MiInitSystemMemoryAreas(VOID) 68 { 69 // 70 // Create all the static memory areas. 71 // 72 73 // The loader mappings. The only Executable area. 74 MiCreateArm3StaticMemoryArea((PVOID)KSEG0_BASE, MmBootImageSize, TRUE); 75 76 // The PTE base 77 MiCreateArm3StaticMemoryArea((PVOID)PTE_BASE, PTE_TOP - PTE_BASE + 1, FALSE); 78 79 // Hyperspace 80 MiCreateArm3StaticMemoryArea((PVOID)HYPER_SPACE, HYPER_SPACE_END - HYPER_SPACE + 1, FALSE); 81 82 // Protect the PFN database 83 MiCreateArm3StaticMemoryArea(MmPfnDatabase, (MxPfnAllocation << PAGE_SHIFT), FALSE); 84 85 // ReactOS requires a memory area to keep the initial NP area off-bounds 86 MiCreateArm3StaticMemoryArea(MmNonPagedPoolStart, MmSizeOfNonPagedPoolInBytes, FALSE); 87 88 // System PTE space 89 MiCreateArm3StaticMemoryArea(MmNonPagedSystemStart, (MmNumberOfSystemPtes + 1) * PAGE_SIZE, FALSE); 90 91 // Nonpaged pool expansion space 92 MiCreateArm3StaticMemoryArea(MmNonPagedPoolExpansionStart, (ULONG_PTR)MmNonPagedPoolEnd - (ULONG_PTR)MmNonPagedPoolExpansionStart, FALSE); 93 94 // System view space 95 MiCreateArm3StaticMemoryArea(MiSystemViewStart, MmSystemViewSize, FALSE); 96 97 // Session space 98 MiCreateArm3StaticMemoryArea(MmSessionBase, (ULONG_PTR)MiSessionSpaceEnd - (ULONG_PTR)MmSessionBase, FALSE); 99 100 // Paged pool 101 MiCreateArm3StaticMemoryArea(MmPagedPoolStart, MmSizeOfPagedPoolInBytes, FALSE); 102 103 // Debugger mapping 104 MiCreateArm3StaticMemoryArea(MI_DEBUG_MAPPING, PAGE_SIZE, FALSE); 105 106 #if defined(_X86_) 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); 109 #else /* _X86_ */ 110 #ifndef _M_AMD64 111 // KPCR, one page per CPU. Only for 32-bit kernel. 112 MiCreateArm3StaticMemoryArea(PCR, PAGE_SIZE * KeNumberProcessors, FALSE); 113 #endif /* _M_AMD64 */ 114 115 // KUSER_SHARED_DATA 116 MiCreateArm3StaticMemoryArea((PVOID)KI_USER_SHARED_DATA, PAGE_SIZE, FALSE); 117 #endif /* _X86_ */ 118 } 119 120 INIT_FUNCTION 121 VOID 122 NTAPI 123 MiDbgDumpAddressSpace(VOID) 124 { 125 // 126 // Print the memory layout 127 // 128 DPRINT1(" 0x%p - 0x%p\t%s\n", 129 KSEG0_BASE, 130 (ULONG_PTR)KSEG0_BASE + MmBootImageSize, 131 "Boot Loaded Image"); 132 DPRINT1(" 0x%p - 0x%p\t%s\n", 133 MmPfnDatabase, 134 (ULONG_PTR)MmPfnDatabase + (MxPfnAllocation << PAGE_SHIFT), 135 "PFN Database"); 136 DPRINT1(" 0x%p - 0x%p\t%s\n", 137 MmNonPagedPoolStart, 138 (ULONG_PTR)MmNonPagedPoolStart + MmSizeOfNonPagedPoolInBytes, 139 "ARM3 Non Paged Pool"); 140 DPRINT1(" 0x%p - 0x%p\t%s\n", 141 MiSystemViewStart, 142 (ULONG_PTR)MiSystemViewStart + MmSystemViewSize, 143 "System View Space"); 144 DPRINT1(" 0x%p - 0x%p\t%s\n", 145 MmSessionBase, 146 MiSessionSpaceEnd, 147 "Session Space"); 148 DPRINT1(" 0x%p - 0x%p\t%s\n", 149 PTE_BASE, PTE_TOP, 150 "Page Tables"); 151 DPRINT1(" 0x%p - 0x%p\t%s\n", 152 PDE_BASE, PDE_TOP, 153 "Page Directories"); 154 DPRINT1(" 0x%p - 0x%p\t%s\n", 155 HYPER_SPACE, HYPER_SPACE_END, 156 "Hyperspace"); 157 DPRINT1(" 0x%p - 0x%p\t%s\n", 158 MmSystemCacheStart, MmSystemCacheEnd, 159 "System Cache"); 160 DPRINT1(" 0x%p - 0x%p\t%s\n", 161 MmPagedPoolStart, 162 (ULONG_PTR)MmPagedPoolStart + MmSizeOfPagedPoolInBytes, 163 "ARM3 Paged Pool"); 164 DPRINT1(" 0x%p - 0x%p\t%s\n", 165 MmNonPagedSystemStart, MmNonPagedPoolExpansionStart, 166 "System PTE Space"); 167 DPRINT1(" 0x%p - 0x%p\t%s\n", 168 MmNonPagedPoolExpansionStart, MmNonPagedPoolEnd, 169 "Non Paged Pool Expansion PTE Space"); 170 } 171 172 INIT_FUNCTION 173 NTSTATUS 174 NTAPI 175 MmInitBsmThread(VOID) 176 { 177 NTSTATUS Status; 178 OBJECT_ATTRIBUTES ObjectAttributes; 179 HANDLE ThreadHandle; 180 181 /* Create the thread */ 182 InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL); 183 Status = PsCreateSystemThread(&ThreadHandle, 184 THREAD_ALL_ACCESS, 185 &ObjectAttributes, 186 NULL, 187 NULL, 188 KeBalanceSetManager, 189 NULL); 190 191 /* Close the handle and return status */ 192 ZwClose(ThreadHandle); 193 return Status; 194 } 195 196 INIT_FUNCTION 197 BOOLEAN 198 NTAPI 199 MmInitSystem(IN ULONG Phase, 200 IN PLOADER_PARAMETER_BLOCK LoaderBlock) 201 { 202 extern MMPTE ValidKernelPte; 203 PMMPTE PointerPte; 204 MMPTE TempPte = ValidKernelPte; 205 PFN_NUMBER PageFrameNumber; 206 PLIST_ENTRY ListEntry; 207 PLDR_DATA_TABLE_ENTRY DataTableEntry; 208 209 /* Initialize the kernel address space */ 210 ASSERT(Phase == 1); 211 212 InitializeListHead(&MiSegmentList); 213 ExInitializeFastMutex(&MiGlobalPageOperation); 214 KeInitializeEvent(&MmWaitPageEvent, SynchronizationEvent, FALSE); 215 // Until we're fully demand paged, we can do things the old way through 216 // the balance manager 217 MmInitializeMemoryConsumer(MC_CACHE, MiRosTrimCache); 218 219 MmKernelAddressSpace = &PsIdleProcess->Vm; 220 221 /* Intialize system memory areas */ 222 MiInitSystemMemoryAreas(); 223 224 /* Dump the address space */ 225 MiDbgDumpAddressSpace(); 226 227 MmInitGlobalKernelPageDirectory(); 228 MiInitializeUserPfnBitmap(); 229 MmInitializeMemoryConsumer(MC_USER, MmTrimUserMemory); 230 MmInitializeRmapList(); 231 MmInitSectionImplementation(); 232 MmInitPagingFile(); 233 234 // 235 // Create a PTE to double-map the shared data section. We allocate it 236 // from paged pool so that we can't fault when trying to touch the PTE 237 // itself (to map it), since paged pool addresses will already be mapped 238 // by the fault handler. 239 // 240 MmSharedUserDataPte = ExAllocatePoolWithTag(PagedPool, 241 sizeof(MMPTE), 242 TAG_MM); 243 if (!MmSharedUserDataPte) return FALSE; 244 245 // 246 // Now get the PTE for shared data, and read the PFN that holds it 247 // 248 PointerPte = MiAddressToPte((PVOID)KI_USER_SHARED_DATA); 249 ASSERT(PointerPte->u.Hard.Valid == 1); 250 PageFrameNumber = PFN_FROM_PTE(PointerPte); 251 252 /* Build the PTE and write it */ 253 MI_MAKE_HARDWARE_PTE_KERNEL(&TempPte, 254 PointerPte, 255 MM_READONLY, 256 PageFrameNumber); 257 *MmSharedUserDataPte = TempPte; 258 259 /* Initialize session working set support */ 260 MiInitializeSessionWsSupport(); 261 262 /* Setup session IDs */ 263 MiInitializeSessionIds(); 264 265 /* Setup the memory threshold events */ 266 if (!MiInitializeMemoryEvents()) return FALSE; 267 268 /* 269 * Unmap low memory 270 */ 271 MiInitBalancerThread(); 272 273 /* Initialize the balance set manager */ 274 MmInitBsmThread(); 275 276 /* Loop the boot loaded images */ 277 for (ListEntry = PsLoadedModuleList.Flink; 278 ListEntry != &PsLoadedModuleList; 279 ListEntry = ListEntry->Flink) 280 { 281 /* Get the data table entry */ 282 DataTableEntry = CONTAINING_RECORD(ListEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); 283 284 /* Set up the image protection */ 285 MiWriteProtectSystemImage(DataTableEntry->DllBase); 286 } 287 288 return TRUE; 289 } 290 291