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 HANDLE MpwThreadHandle; 23 KEVENT MpwThreadEvent; 24 25 BOOLEAN Mm64BitPhysicalAddress = FALSE; 26 ULONG MmReadClusterSize; 27 // 28 // 0 | 1 is on/off paging, 2 is undocumented 29 // 30 UCHAR MmDisablePagingExecutive = 1; // Forced to off 31 PMMPTE MmSharedUserDataPte; 32 PMMSUPPORT MmKernelAddressSpace; 33 34 extern KEVENT MmWaitPageEvent; 35 extern FAST_MUTEX MiGlobalPageOperation; 36 extern LIST_ENTRY MiSegmentList; 37 extern NTSTATUS MiRosTrimCache(ULONG Target, ULONG Priority, PULONG NrFreed); 38 39 /* PRIVATE FUNCTIONS *********************************************************/ 40 41 VOID 42 INIT_FUNCTION 43 NTAPI 44 MiInitSystemMemoryAreas() 45 { 46 PVOID BaseAddress; 47 PHYSICAL_ADDRESS BoundaryAddressMultiple; 48 PMEMORY_AREA MArea; 49 NTSTATUS Status; 50 BoundaryAddressMultiple.QuadPart = 0; 51 52 // 53 // Create the memory area to define the loader mappings 54 // 55 BaseAddress = (PVOID)KSEG0_BASE; 56 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(), 57 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC, 58 &BaseAddress, 59 MmBootImageSize, 60 PAGE_EXECUTE_READWRITE, 61 &MArea, 62 TRUE, 63 0, 64 BoundaryAddressMultiple); 65 ASSERT(Status == STATUS_SUCCESS); 66 67 // 68 // Create the memory area to define the PTE base 69 // 70 BaseAddress = (PVOID)PTE_BASE; 71 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(), 72 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC, 73 &BaseAddress, 74 PTE_TOP - PTE_BASE + 1, 75 PAGE_READWRITE, 76 &MArea, 77 TRUE, 78 0, 79 BoundaryAddressMultiple); 80 ASSERT(Status == STATUS_SUCCESS); 81 82 // 83 // Create the memory area to define Hyperspace 84 // 85 BaseAddress = (PVOID)HYPER_SPACE; 86 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(), 87 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC, 88 &BaseAddress, 89 HYPER_SPACE_END - HYPER_SPACE + 1, 90 PAGE_READWRITE, 91 &MArea, 92 TRUE, 93 0, 94 BoundaryAddressMultiple); 95 ASSERT(Status == STATUS_SUCCESS); 96 97 // 98 // Protect the PFN database 99 // 100 BaseAddress = MmPfnDatabase; 101 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(), 102 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC, 103 &BaseAddress, 104 (MxPfnAllocation << PAGE_SHIFT), 105 PAGE_READWRITE, 106 &MArea, 107 TRUE, 108 0, 109 BoundaryAddressMultiple); 110 ASSERT(Status == STATUS_SUCCESS); 111 112 // 113 // ReactOS requires a memory area to keep the initial NP area off-bounds 114 // 115 BaseAddress = MmNonPagedPoolStart; 116 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(), 117 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC, 118 &BaseAddress, 119 MmSizeOfNonPagedPoolInBytes, 120 PAGE_READWRITE, 121 &MArea, 122 TRUE, 123 0, 124 BoundaryAddressMultiple); 125 ASSERT(Status == STATUS_SUCCESS); 126 127 // 128 // And we need one more for the system NP 129 // 130 BaseAddress = MmNonPagedSystemStart; 131 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(), 132 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC, 133 &BaseAddress, 134 MiNonPagedSystemSize, 135 PAGE_READWRITE, 136 &MArea, 137 TRUE, 138 0, 139 BoundaryAddressMultiple); 140 ASSERT(Status == STATUS_SUCCESS); 141 142 // 143 // We also need one for system view space 144 // 145 BaseAddress = MiSystemViewStart; 146 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(), 147 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC, 148 &BaseAddress, 149 MmSystemViewSize, 150 PAGE_READWRITE, 151 &MArea, 152 TRUE, 153 0, 154 BoundaryAddressMultiple); 155 ASSERT(Status == STATUS_SUCCESS); 156 157 // 158 // And another for session space 159 // 160 BaseAddress = MmSessionBase; 161 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(), 162 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC, 163 &BaseAddress, 164 (ULONG_PTR)MiSessionSpaceEnd - 165 (ULONG_PTR)MmSessionBase, 166 PAGE_READWRITE, 167 &MArea, 168 TRUE, 169 0, 170 BoundaryAddressMultiple); 171 ASSERT(Status == STATUS_SUCCESS); 172 173 // 174 // One more for ARM paged pool 175 // 176 BaseAddress = MmPagedPoolStart; 177 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(), 178 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC, 179 &BaseAddress, 180 MmSizeOfPagedPoolInBytes, 181 PAGE_READWRITE, 182 &MArea, 183 TRUE, 184 0, 185 BoundaryAddressMultiple); 186 ASSERT(Status == STATUS_SUCCESS); 187 #ifndef _M_AMD64 188 // 189 // Next, the KPCR 190 // 191 BaseAddress = (PVOID)PCR; 192 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(), 193 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC, 194 &BaseAddress, 195 PAGE_SIZE * KeNumberProcessors, 196 PAGE_READWRITE, 197 &MArea, 198 TRUE, 199 0, 200 BoundaryAddressMultiple); 201 ASSERT(Status == STATUS_SUCCESS); 202 #endif 203 // 204 // Now the KUSER_SHARED_DATA 205 // 206 BaseAddress = (PVOID)KI_USER_SHARED_DATA; 207 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(), 208 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC, 209 &BaseAddress, 210 PAGE_SIZE, 211 PAGE_READWRITE, 212 &MArea, 213 TRUE, 214 0, 215 BoundaryAddressMultiple); 216 ASSERT(Status == STATUS_SUCCESS); 217 218 // 219 // And the debugger mapping 220 // 221 BaseAddress = MI_DEBUG_MAPPING; 222 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(), 223 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC, 224 &BaseAddress, 225 PAGE_SIZE, 226 PAGE_READWRITE, 227 &MArea, 228 TRUE, 229 0, 230 BoundaryAddressMultiple); 231 ASSERT(Status == STATUS_SUCCESS); 232 233 #if defined(_X86_) 234 // 235 // Finally, reserve the 2 pages we currently make use of for HAL mappings 236 // 237 BaseAddress = (PVOID)0xFFC00000; 238 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(), 239 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC, 240 &BaseAddress, 241 PAGE_SIZE * 2, 242 PAGE_READWRITE, 243 &MArea, 244 TRUE, 245 0, 246 BoundaryAddressMultiple); 247 ASSERT(Status == STATUS_SUCCESS); 248 #endif 249 } 250 251 VOID 252 NTAPI 253 INIT_FUNCTION 254 MiDbgDumpAddressSpace(VOID) 255 { 256 // 257 // Print the memory layout 258 // 259 DPRINT1(" 0x%p - 0x%p\t%s\n", 260 KSEG0_BASE, 261 (ULONG_PTR)KSEG0_BASE + MmBootImageSize, 262 "Boot Loaded Image"); 263 DPRINT1(" 0x%p - 0x%p\t%s\n", 264 MmPfnDatabase, 265 (ULONG_PTR)MmPfnDatabase + (MxPfnAllocation << PAGE_SHIFT), 266 "PFN Database"); 267 DPRINT1(" 0x%p - 0x%p\t%s\n", 268 MmNonPagedPoolStart, 269 (ULONG_PTR)MmNonPagedPoolStart + MmSizeOfNonPagedPoolInBytes, 270 "ARM3 Non Paged Pool"); 271 DPRINT1(" 0x%p - 0x%p\t%s\n", 272 MiSystemViewStart, 273 (ULONG_PTR)MiSystemViewStart + MmSystemViewSize, 274 "System View Space"); 275 DPRINT1(" 0x%p - 0x%p\t%s\n", 276 MmSessionBase, 277 MiSessionSpaceEnd, 278 "Session Space"); 279 DPRINT1(" 0x%p - 0x%p\t%s\n", 280 PTE_BASE, PTE_TOP, 281 "Page Tables"); 282 DPRINT1(" 0x%p - 0x%p\t%s\n", 283 PDE_BASE, PDE_TOP, 284 "Page Directories"); 285 DPRINT1(" 0x%p - 0x%p\t%s\n", 286 HYPER_SPACE, HYPER_SPACE_END, 287 "Hyperspace"); 288 DPRINT1(" 0x%p - 0x%p\t%s\n", 289 MmPagedPoolStart, 290 (ULONG_PTR)MmPagedPoolStart + MmSizeOfPagedPoolInBytes, 291 "ARM3 Paged Pool"); 292 DPRINT1(" 0x%p - 0x%p\t%s\n", 293 MmNonPagedSystemStart, MmNonPagedPoolExpansionStart, 294 "System PTE Space"); 295 DPRINT1(" 0x%p - 0x%p\t%s\n", 296 MmNonPagedPoolExpansionStart, MmNonPagedPoolEnd, 297 "Non Paged Pool Expansion PTE Space"); 298 } 299 300 NTSTATUS NTAPI 301 MmMpwThreadMain(PVOID Ignored) 302 { 303 NTSTATUS Status; 304 ULONG PagesWritten; 305 LARGE_INTEGER Timeout; 306 307 Timeout.QuadPart = -50000000; 308 309 for(;;) 310 { 311 Status = KeWaitForSingleObject(&MpwThreadEvent, 312 0, 313 KernelMode, 314 FALSE, 315 &Timeout); 316 if (!NT_SUCCESS(Status)) 317 { 318 DbgPrint("MpwThread: Wait failed\n"); 319 KeBugCheck(MEMORY_MANAGEMENT); 320 return(STATUS_UNSUCCESSFUL); 321 } 322 323 PagesWritten = 0; 324 325 #ifndef NEWCC 326 // XXX arty -- we flush when evicting pages or destorying cache 327 // sections. 328 CcRosFlushDirtyPages(128, &PagesWritten, FALSE); 329 #endif 330 } 331 } 332 333 NTSTATUS 334 NTAPI 335 INIT_FUNCTION 336 MmInitMpwThread(VOID) 337 { 338 KPRIORITY Priority; 339 NTSTATUS Status; 340 CLIENT_ID MpwThreadId; 341 342 KeInitializeEvent(&MpwThreadEvent, SynchronizationEvent, FALSE); 343 344 Status = PsCreateSystemThread(&MpwThreadHandle, 345 THREAD_ALL_ACCESS, 346 NULL, 347 NULL, 348 &MpwThreadId, 349 (PKSTART_ROUTINE) MmMpwThreadMain, 350 NULL); 351 if (!NT_SUCCESS(Status)) 352 { 353 return(Status); 354 } 355 356 Priority = 27; 357 NtSetInformationThread(MpwThreadHandle, 358 ThreadPriority, 359 &Priority, 360 sizeof(Priority)); 361 362 return(STATUS_SUCCESS); 363 } 364 365 NTSTATUS 366 NTAPI 367 INIT_FUNCTION 368 MmInitBsmThread(VOID) 369 { 370 NTSTATUS Status; 371 OBJECT_ATTRIBUTES ObjectAttributes; 372 HANDLE ThreadHandle; 373 374 /* Create the thread */ 375 InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL); 376 Status = PsCreateSystemThread(&ThreadHandle, 377 THREAD_ALL_ACCESS, 378 &ObjectAttributes, 379 NULL, 380 NULL, 381 KeBalanceSetManager, 382 NULL); 383 384 /* Close the handle and return status */ 385 ZwClose(ThreadHandle); 386 return Status; 387 } 388 389 BOOLEAN 390 NTAPI 391 INIT_FUNCTION 392 MmInitSystem(IN ULONG Phase, 393 IN PLOADER_PARAMETER_BLOCK LoaderBlock) 394 { 395 extern MMPTE ValidKernelPte; 396 PMMPTE PointerPte; 397 MMPTE TempPte = ValidKernelPte; 398 PFN_NUMBER PageFrameNumber; 399 400 /* Initialize the kernel address space */ 401 ASSERT(Phase == 1); 402 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); 409 410 MmKernelAddressSpace = &PsIdleProcess->Vm; 411 412 /* Intialize system memory areas */ 413 MiInitSystemMemoryAreas(); 414 415 /* Dump the address space */ 416 MiDbgDumpAddressSpace(); 417 418 MmInitGlobalKernelPageDirectory(); 419 MiInitializeUserPfnBitmap(); 420 MmInitializeMemoryConsumer(MC_USER, MmTrimUserMemory); 421 MmInitializeRmapList(); 422 MmInitSectionImplementation(); 423 MmInitPagingFile(); 424 425 // 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. 430 // 431 MmSharedUserDataPte = ExAllocatePoolWithTag(PagedPool, 432 sizeof(MMPTE), 433 ' mM'); 434 if (!MmSharedUserDataPte) return FALSE; 435 436 // 437 // Now get the PTE for shared data, and read the PFN that holds it 438 // 439 PointerPte = MiAddressToPte((PVOID)KI_USER_SHARED_DATA); 440 ASSERT(PointerPte->u.Hard.Valid == 1); 441 PageFrameNumber = PFN_FROM_PTE(PointerPte); 442 443 /* Build the PTE and write it */ 444 MI_MAKE_HARDWARE_PTE_KERNEL(&TempPte, 445 PointerPte, 446 MM_READONLY, 447 PageFrameNumber); 448 *MmSharedUserDataPte = TempPte; 449 450 /* Setup session IDs */ 451 MiInitializeSessionIds(); 452 453 /* Setup the memory threshold events */ 454 if (!MiInitializeMemoryEvents()) return FALSE; 455 456 /* 457 * Unmap low memory 458 */ 459 MiInitBalancerThread(); 460 461 /* 462 * Initialise the modified page writer. 463 */ 464 MmInitMpwThread(); 465 466 /* Initialize the balance set manager */ 467 MmInitBsmThread(); 468 469 return TRUE; 470 } 471 472