1 /* 2 * PROJECT: ReactOS Kernel 3 * LICENSE: BSD - See COPYING.ARM in the top level directory 4 * FILE: ntoskrnl/mm/ARM3/miarm.h 5 * PURPOSE: ARM Memory Manager Header 6 * PROGRAMMERS: ReactOS Portable Systems Group 7 */ 8 9 #pragma once 10 11 #define MI_LOWEST_VAD_ADDRESS (PVOID)MM_LOWEST_USER_ADDRESS 12 13 /* Make the code cleaner with some definitions for size multiples */ 14 #define _1KB (1024u) 15 #define _1MB (1024 * _1KB) 16 #define _1GB (1024 * _1MB) 17 18 /* Everyone loves 64K */ 19 #define _64K (64 * _1KB) 20 21 /* Area mapped by a PDE */ 22 #define PDE_MAPPED_VA (PTE_PER_PAGE * PAGE_SIZE) 23 24 /* Size of a page table */ 25 #define PT_SIZE (PTE_PER_PAGE * sizeof(MMPTE)) 26 27 /* Size of a page directory */ 28 #define PD_SIZE (PDE_PER_PAGE * sizeof(MMPDE)) 29 30 /* Size of all page directories for a process */ 31 #define SYSTEM_PD_SIZE (PPE_PER_PAGE * PD_SIZE) 32 #ifdef _M_IX86 33 C_ASSERT(SYSTEM_PD_SIZE == PAGE_SIZE); 34 #endif 35 36 // 37 // Protection Bits part of the internal memory manager Protection Mask, from: 38 // http://reactos.org/wiki/Techwiki:Memory_management_in_the_Windows_XP_kernel 39 // https://www.reactos.org/wiki/Techwiki:Memory_Protection_constants 40 // and public assertions. 41 // 42 #define MM_ZERO_ACCESS 0 43 #define MM_READONLY 1 44 #define MM_EXECUTE 2 45 #define MM_EXECUTE_READ 3 46 #define MM_READWRITE 4 47 #define MM_WRITECOPY 5 48 #define MM_EXECUTE_READWRITE 6 49 #define MM_EXECUTE_WRITECOPY 7 50 #define MM_PROTECT_ACCESS 7 51 52 // 53 // These are flags on top of the actual protection mask 54 // 55 #define MM_NOCACHE 0x08 56 #define MM_GUARDPAGE 0x10 57 #define MM_WRITECOMBINE 0x18 58 #define MM_PROTECT_SPECIAL 0x18 59 60 // 61 // These are special cases 62 // 63 #define MM_DECOMMIT (MM_ZERO_ACCESS | MM_GUARDPAGE) 64 #define MM_NOACCESS (MM_ZERO_ACCESS | MM_WRITECOMBINE) 65 #define MM_OUTSWAPPED_KSTACK (MM_EXECUTE_WRITECOPY | MM_WRITECOMBINE) 66 #define MM_INVALID_PROTECTION 0xFFFFFFFF 67 68 // 69 // Specific PTE Definitions that map to the Memory Manager's Protection Mask Bits 70 // The Memory Manager's definition define the attributes that must be preserved 71 // and these PTE definitions describe the attributes in the hardware sense. This 72 // helps deal with hardware differences between the actual boolean expression of 73 // the argument. 74 // 75 // For example, in the logical attributes, we want to express read-only as a flag 76 // but on x86, it is writability that must be set. On the other hand, on x86, just 77 // like in the kernel, it is disabling the caches that requires a special flag, 78 // while on certain architectures such as ARM, it is enabling the cache which 79 // requires a flag. 80 // 81 #if defined(_M_IX86) 82 // 83 // Access Flags 84 // 85 #define PTE_READONLY 0 // Doesn't exist on x86 86 #define PTE_EXECUTE 0 // Not worrying about NX yet 87 #define PTE_EXECUTE_READ 0 // Not worrying about NX yet 88 #define PTE_READWRITE 0x2 89 #define PTE_WRITECOPY 0x200 90 #define PTE_EXECUTE_READWRITE 0x2 // Not worrying about NX yet 91 #define PTE_EXECUTE_WRITECOPY 0x200 92 #define PTE_PROTOTYPE 0x400 93 94 // 95 // State Flags 96 // 97 #define PTE_VALID 0x1 98 #define PTE_ACCESSED 0x20 99 #define PTE_DIRTY 0x40 100 101 // 102 // Cache flags 103 // 104 #define PTE_ENABLE_CACHE 0 105 #define PTE_DISABLE_CACHE 0x10 106 #define PTE_WRITECOMBINED_CACHE 0x10 107 #define PTE_PROTECT_MASK 0x612 108 #elif defined(_M_AMD64) 109 // 110 // Access Flags 111 // 112 #define PTE_READONLY 0x8000000000000000ULL 113 #define PTE_EXECUTE 0x0000000000000000ULL 114 #define PTE_EXECUTE_READ PTE_EXECUTE /* EXECUTE implies READ on x64 */ 115 #define PTE_READWRITE 0x8000000000000002ULL 116 #define PTE_WRITECOPY 0x8000000000000200ULL 117 #define PTE_EXECUTE_READWRITE 0x0000000000000002ULL 118 #define PTE_EXECUTE_WRITECOPY 0x0000000000000200ULL 119 #define PTE_PROTOTYPE 0x0000000000000400ULL 120 121 // 122 // State Flags 123 // 124 #define PTE_VALID 0x0000000000000001ULL 125 #define PTE_ACCESSED 0x0000000000000020ULL 126 #define PTE_DIRTY 0x0000000000000040ULL 127 128 // 129 // Cache flags 130 // 131 #define PTE_ENABLE_CACHE 0x0000000000000000ULL 132 #define PTE_DISABLE_CACHE 0x0000000000000010ULL 133 #define PTE_WRITECOMBINED_CACHE 0x0000000000000010ULL 134 #define PTE_PROTECT_MASK 0x8000000000000612ULL 135 #elif defined(_M_ARM) 136 #define PTE_READONLY 0x200 137 #define PTE_EXECUTE 0 // Not worrying about NX yet 138 #define PTE_EXECUTE_READ 0 // Not worrying about NX yet 139 #define PTE_READWRITE 0 // Doesn't exist on ARM 140 #define PTE_WRITECOPY 0 // Doesn't exist on ARM 141 #define PTE_EXECUTE_READWRITE 0 // Not worrying about NX yet 142 #define PTE_EXECUTE_WRITECOPY 0 // Not worrying about NX yet 143 #define PTE_PROTOTYPE 0x400 // Using the Shared bit 144 145 // 146 // Cache flags 147 // 148 #define PTE_ENABLE_CACHE 0 149 #define PTE_DISABLE_CACHE 0x10 150 #define PTE_WRITECOMBINED_CACHE 0x10 151 #define PTE_PROTECT_MASK 0x610 152 #else 153 #error Define these please! 154 #endif 155 156 // 157 // Mask for image section page protection 158 // 159 #define IMAGE_SCN_PROTECTION_MASK (IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE) 160 161 extern const ULONG_PTR MmProtectToPteMask[32]; 162 extern const ULONG MmProtectToValue[32]; 163 164 // 165 // Assertions for session images, addresses, and PTEs 166 // 167 #define MI_IS_SESSION_IMAGE_ADDRESS(Address) \ 168 (((Address) >= MiSessionImageStart) && ((Address) < MiSessionImageEnd)) 169 170 #define MI_IS_SESSION_ADDRESS(Address) \ 171 (((Address) >= MmSessionBase) && ((Address) < MiSessionSpaceEnd)) 172 173 #define MI_IS_SESSION_PTE(Pte) \ 174 ((((PMMPTE)Pte) >= MiSessionBasePte) && (((PMMPTE)Pte) < MiSessionLastPte)) 175 176 #define MI_IS_PAGE_TABLE_ADDRESS(Address) \ 177 (((PVOID)(Address) >= (PVOID)PTE_BASE) && ((PVOID)(Address) <= (PVOID)PTE_TOP)) 178 179 #define MI_IS_SYSTEM_PAGE_TABLE_ADDRESS(Address) \ 180 (((Address) >= (PVOID)MiAddressToPte(MmSystemRangeStart)) && ((Address) <= (PVOID)PTE_TOP)) 181 182 #define MI_IS_PAGE_TABLE_OR_HYPER_ADDRESS(Address) \ 183 (((PVOID)(Address) >= (PVOID)PTE_BASE) && ((PVOID)(Address) <= (PVOID)MmHyperSpaceEnd)) 184 185 // 186 // Creates a software PTE with the given protection 187 // 188 #define MI_MAKE_SOFTWARE_PTE(p, x) ((p)->u.Long = (x << MM_PTE_SOFTWARE_PROTECTION_BITS)) 189 190 // 191 // Marks a PTE as deleted 192 // 193 #define MI_SET_PFN_DELETED(x) ((x)->PteAddress = (PMMPTE)((ULONG_PTR)(x)->PteAddress | 1)) 194 #define MI_IS_PFN_DELETED(x) ((ULONG_PTR)((x)->PteAddress) & 1) 195 196 // 197 // Special values for LoadedImports 198 // 199 #ifdef _WIN64 200 #define MM_SYSLDR_NO_IMPORTS (PVOID)0xFFFFFFFFFFFFFFFEULL 201 #define MM_SYSLDR_BOOT_LOADED (PVOID)0xFFFFFFFFFFFFFFFFULL 202 #else 203 #define MM_SYSLDR_NO_IMPORTS (PVOID)0xFFFFFFFE 204 #define MM_SYSLDR_BOOT_LOADED (PVOID)0xFFFFFFFF 205 #endif 206 #define MM_SYSLDR_SINGLE_ENTRY 0x1 207 208 // 209 // Number of initial session IDs 210 // 211 #define MI_INITIAL_SESSION_IDS 64 212 213 #if defined(_M_IX86) || defined(_M_ARM) 214 // 215 // PFN List Sentinel 216 // 217 #define LIST_HEAD 0xFFFFFFFF 218 219 // 220 // Because GCC cannot automatically downcast 0xFFFFFFFF to lesser-width bits, 221 // we need a manual definition suited to the number of bits in the PteFrame. 222 // This is used as a LIST_HEAD for the colored list 223 // 224 #define COLORED_LIST_HEAD ((1 << 25) - 1) // 0x1FFFFFF 225 #elif defined(_M_AMD64) 226 #define LIST_HEAD 0xFFFFFFFFFFFFFFFFLL 227 #define COLORED_LIST_HEAD ((1ULL << 57) - 1) // 0x1FFFFFFFFFFFFFFLL 228 #else 229 #error Define these please! 230 #endif 231 232 // 233 // Special IRQL value (found in assertions) 234 // 235 #define MM_NOIRQL (KIRQL)0xFFFFFFFF 236 237 // 238 // Returns the color of a page 239 // 240 #define MI_GET_PAGE_COLOR(x) ((x) & MmSecondaryColorMask) 241 #define MI_GET_NEXT_COLOR() (MI_GET_PAGE_COLOR(++MmSystemPageColor)) 242 #define MI_GET_NEXT_PROCESS_COLOR(x) (MI_GET_PAGE_COLOR(++(x)->NextPageColor)) 243 244 // 245 // Prototype PTEs that don't yet have a pagefile association 246 // 247 #ifdef _WIN64 248 #define MI_PTE_LOOKUP_NEEDED 0xffffffffULL 249 #else 250 #define MI_PTE_LOOKUP_NEEDED 0xFFFFF 251 #endif 252 253 // 254 // Number of session data and tag pages 255 // 256 #define MI_SESSION_DATA_PAGES_MAXIMUM (MM_ALLOCATION_GRANULARITY / PAGE_SIZE) 257 #define MI_SESSION_TAG_PAGES_MAXIMUM (MM_ALLOCATION_GRANULARITY / PAGE_SIZE) 258 259 // 260 // Used by MiCheckSecuredVad 261 // 262 #define MM_READ_WRITE_ALLOWED 11 263 #define MM_READ_ONLY_ALLOWED 10 264 #define MM_NO_ACCESS_ALLOWED 01 265 #define MM_DELETE_CHECK 85 266 267 // 268 // System views are binned into 64K chunks 269 // 270 #define MI_SYSTEM_VIEW_BUCKET_SIZE _64K 271 272 // 273 // FIXFIX: These should go in ex.h after the pool merge 274 // 275 #ifdef _WIN64 276 #define POOL_BLOCK_SIZE 16 277 #else 278 #define POOL_BLOCK_SIZE 8 279 #endif 280 #define POOL_LISTS_PER_PAGE (PAGE_SIZE / POOL_BLOCK_SIZE) 281 #define BASE_POOL_TYPE_MASK 1 282 #define POOL_MAX_ALLOC (PAGE_SIZE - (sizeof(POOL_HEADER) + POOL_BLOCK_SIZE)) 283 284 // 285 // Pool debugging/analysis/tracing flags 286 // 287 #define POOL_FLAG_CHECK_TIMERS 0x1 288 #define POOL_FLAG_CHECK_WORKERS 0x2 289 #define POOL_FLAG_CHECK_RESOURCES 0x4 290 #define POOL_FLAG_VERIFIER 0x8 291 #define POOL_FLAG_CHECK_DEADLOCK 0x10 292 #define POOL_FLAG_SPECIAL_POOL 0x20 293 #define POOL_FLAG_DBGPRINT_ON_FAILURE 0x40 294 #define POOL_FLAG_CRASH_ON_FAILURE 0x80 295 296 // 297 // BAD_POOL_HEADER codes during pool bugcheck 298 // 299 #define POOL_CORRUPTED_LIST 3 300 #define POOL_SIZE_OR_INDEX_MISMATCH 5 301 #define POOL_ENTRIES_NOT_ALIGNED_PREVIOUS 6 302 #define POOL_HEADER_NOT_ALIGNED 7 303 #define POOL_HEADER_IS_ZERO 8 304 #define POOL_ENTRIES_NOT_ALIGNED_NEXT 9 305 #define POOL_ENTRY_NOT_FOUND 10 306 307 // 308 // BAD_POOL_CALLER codes during pool bugcheck 309 // 310 #define POOL_ENTRY_CORRUPTED 1 311 #define POOL_ENTRY_ALREADY_FREE 6 312 #define POOL_ENTRY_NOT_ALLOCATED 7 313 #define POOL_ALLOC_IRQL_INVALID 8 314 #define POOL_FREE_IRQL_INVALID 9 315 #define POOL_BILLED_PROCESS_INVALID 13 316 #define POOL_HEADER_SIZE_INVALID 32 317 318 typedef struct _POOL_DESCRIPTOR 319 { 320 POOL_TYPE PoolType; 321 ULONG PoolIndex; 322 ULONG RunningAllocs; 323 ULONG RunningDeAllocs; 324 ULONG TotalPages; 325 ULONG TotalBigPages; 326 ULONG Threshold; 327 PVOID LockAddress; 328 PVOID PendingFrees; 329 LONG PendingFreeDepth; 330 SIZE_T TotalBytes; 331 SIZE_T Spare0; 332 LIST_ENTRY ListHeads[POOL_LISTS_PER_PAGE]; 333 } POOL_DESCRIPTOR, *PPOOL_DESCRIPTOR; 334 335 typedef struct _POOL_HEADER 336 { 337 union 338 { 339 struct 340 { 341 #ifdef _WIN64 342 USHORT PreviousSize:8; 343 USHORT PoolIndex:8; 344 USHORT BlockSize:8; 345 USHORT PoolType:8; 346 #else 347 USHORT PreviousSize:9; 348 USHORT PoolIndex:7; 349 USHORT BlockSize:9; 350 USHORT PoolType:7; 351 #endif 352 }; 353 ULONG Ulong1; 354 }; 355 #ifdef _WIN64 356 ULONG PoolTag; 357 #endif 358 union 359 { 360 #ifdef _WIN64 361 PEPROCESS ProcessBilled; 362 #else 363 ULONG PoolTag; 364 #endif 365 struct 366 { 367 USHORT AllocatorBackTraceIndex; 368 USHORT PoolTagHash; 369 }; 370 }; 371 } POOL_HEADER, *PPOOL_HEADER; 372 373 C_ASSERT(sizeof(POOL_HEADER) == POOL_BLOCK_SIZE); 374 C_ASSERT(POOL_BLOCK_SIZE == sizeof(LIST_ENTRY)); 375 376 typedef struct _POOL_TRACKER_TABLE 377 { 378 ULONG Key; 379 LONG NonPagedAllocs; 380 LONG NonPagedFrees; 381 SIZE_T NonPagedBytes; 382 LONG PagedAllocs; 383 LONG PagedFrees; 384 SIZE_T PagedBytes; 385 } POOL_TRACKER_TABLE, *PPOOL_TRACKER_TABLE; 386 387 typedef struct _POOL_TRACKER_BIG_PAGES 388 { 389 PVOID Va; 390 ULONG Key; 391 ULONG NumberOfPages; 392 PVOID QuotaObject; 393 } POOL_TRACKER_BIG_PAGES, *PPOOL_TRACKER_BIG_PAGES; 394 395 extern ULONG ExpNumberOfPagedPools; 396 extern POOL_DESCRIPTOR NonPagedPoolDescriptor; 397 extern PPOOL_DESCRIPTOR ExpPagedPoolDescriptor[16 + 1]; 398 extern PPOOL_TRACKER_TABLE PoolTrackTable; 399 400 // 401 // END FIXFIX 402 // 403 404 typedef struct _MI_LARGE_PAGE_DRIVER_ENTRY 405 { 406 LIST_ENTRY Links; 407 UNICODE_STRING BaseName; 408 } MI_LARGE_PAGE_DRIVER_ENTRY, *PMI_LARGE_PAGE_DRIVER_ENTRY; 409 410 typedef enum _MMSYSTEM_PTE_POOL_TYPE 411 { 412 SystemPteSpace, 413 NonPagedPoolExpansion, 414 MaximumPtePoolTypes 415 } MMSYSTEM_PTE_POOL_TYPE; 416 417 typedef enum _MI_PFN_CACHE_ATTRIBUTE 418 { 419 MiNonCached, 420 MiCached, 421 MiWriteCombined, 422 MiNotMapped 423 } MI_PFN_CACHE_ATTRIBUTE, *PMI_PFN_CACHE_ATTRIBUTE; 424 425 typedef struct _PHYSICAL_MEMORY_RUN 426 { 427 PFN_NUMBER BasePage; 428 PFN_NUMBER PageCount; 429 } PHYSICAL_MEMORY_RUN, *PPHYSICAL_MEMORY_RUN; 430 431 typedef struct _PHYSICAL_MEMORY_DESCRIPTOR 432 { 433 ULONG NumberOfRuns; 434 PFN_NUMBER NumberOfPages; 435 PHYSICAL_MEMORY_RUN Run[1]; 436 } PHYSICAL_MEMORY_DESCRIPTOR, *PPHYSICAL_MEMORY_DESCRIPTOR; 437 438 typedef struct _MMCOLOR_TABLES 439 { 440 PFN_NUMBER Flink; 441 PVOID Blink; 442 PFN_NUMBER Count; 443 } MMCOLOR_TABLES, *PMMCOLOR_TABLES; 444 445 typedef struct _MI_LARGE_PAGE_RANGES 446 { 447 PFN_NUMBER StartFrame; 448 PFN_NUMBER LastFrame; 449 } MI_LARGE_PAGE_RANGES, *PMI_LARGE_PAGE_RANGES; 450 451 typedef struct _MMVIEW 452 { 453 ULONG_PTR Entry; 454 PCONTROL_AREA ControlArea; 455 } MMVIEW, *PMMVIEW; 456 457 typedef struct _MMSESSION 458 { 459 KGUARDED_MUTEX SystemSpaceViewLock; 460 PKGUARDED_MUTEX SystemSpaceViewLockPointer; 461 PCHAR SystemSpaceViewStart; 462 PMMVIEW SystemSpaceViewTable; 463 ULONG SystemSpaceHashSize; 464 ULONG SystemSpaceHashEntries; 465 ULONG SystemSpaceHashKey; 466 ULONG BitmapFailures; 467 PRTL_BITMAP SystemSpaceBitMap; 468 } MMSESSION, *PMMSESSION; 469 470 typedef struct _MM_SESSION_SPACE_FLAGS 471 { 472 ULONG Initialized:1; 473 ULONG DeletePending:1; 474 ULONG Filler:30; 475 } MM_SESSION_SPACE_FLAGS; 476 477 typedef struct _MM_SESSION_SPACE 478 { 479 struct _MM_SESSION_SPACE *GlobalVirtualAddress; 480 LONG ReferenceCount; 481 union 482 { 483 ULONG LongFlags; 484 MM_SESSION_SPACE_FLAGS Flags; 485 } u; 486 ULONG SessionId; 487 LIST_ENTRY ProcessList; 488 LARGE_INTEGER LastProcessSwappedOutTime; 489 PFN_NUMBER SessionPageDirectoryIndex; 490 SIZE_T NonPageablePages; 491 SIZE_T CommittedPages; 492 PVOID PagedPoolStart; 493 PVOID PagedPoolEnd; 494 PMMPDE PagedPoolBasePde; 495 ULONG Color; 496 LONG ResidentProcessCount; 497 ULONG SessionPoolAllocationFailures[4]; 498 LIST_ENTRY ImageList; 499 LCID LocaleId; 500 ULONG AttachCount; 501 KEVENT AttachEvent; 502 PEPROCESS LastProcess; 503 LONG ProcessReferenceToSession; 504 LIST_ENTRY WsListEntry; 505 GENERAL_LOOKASIDE Lookaside[SESSION_POOL_LOOKASIDES]; 506 MMSESSION Session; 507 KGUARDED_MUTEX PagedPoolMutex; 508 MM_PAGED_POOL_INFO PagedPoolInfo; 509 MMSUPPORT Vm; 510 PMMWSLE Wsle; 511 PDRIVER_UNLOAD Win32KDriverUnload; 512 POOL_DESCRIPTOR PagedPool; 513 #if defined (_M_AMD64) 514 MMPDE PageDirectory; 515 #else 516 PMMPDE PageTables; 517 #endif 518 #if defined (_M_AMD64) 519 PMMPTE SpecialPoolFirstPte; 520 PMMPTE SpecialPoolLastPte; 521 PMMPTE NextPdeForSpecialPoolExpansion; 522 PMMPTE LastPdeForSpecialPoolExpansion; 523 PFN_NUMBER SpecialPagesInUse; 524 #endif 525 LONG ImageLoadingCount; 526 } MM_SESSION_SPACE, *PMM_SESSION_SPACE; 527 528 extern PMM_SESSION_SPACE MmSessionSpace; 529 extern MMPTE HyperTemplatePte; 530 extern MMPDE ValidKernelPde; 531 extern MMPTE ValidKernelPte; 532 extern MMPDE ValidKernelPdeLocal; 533 extern MMPTE ValidKernelPteLocal; 534 extern MMPDE DemandZeroPde; 535 extern MMPTE DemandZeroPte; 536 extern MMPTE PrototypePte; 537 extern MMPTE MmDecommittedPte; 538 extern BOOLEAN MmLargeSystemCache; 539 extern BOOLEAN MmZeroPageFile; 540 extern BOOLEAN MmProtectFreedNonPagedPool; 541 extern BOOLEAN MmTrackLockedPages; 542 extern BOOLEAN MmTrackPtes; 543 extern BOOLEAN MmDynamicPfn; 544 extern BOOLEAN MmMirroring; 545 extern BOOLEAN MmMakeLowMemory; 546 extern BOOLEAN MmEnforceWriteProtection; 547 extern SIZE_T MmAllocationFragment; 548 extern ULONG MmConsumedPoolPercentage; 549 extern ULONG MmVerifyDriverBufferType; 550 extern ULONG MmVerifyDriverLevel; 551 extern WCHAR MmVerifyDriverBuffer[512]; 552 extern WCHAR MmLargePageDriverBuffer[512]; 553 extern LIST_ENTRY MiLargePageDriverList; 554 extern BOOLEAN MiLargePageAllDrivers; 555 extern ULONG MmVerifyDriverBufferLength; 556 extern ULONG MmLargePageDriverBufferLength; 557 extern SIZE_T MmSizeOfNonPagedPoolInBytes; 558 extern SIZE_T MmMaximumNonPagedPoolInBytes; 559 extern PFN_NUMBER MmMaximumNonPagedPoolInPages; 560 extern PFN_NUMBER MmSizeOfPagedPoolInPages; 561 extern PVOID MmNonPagedSystemStart; 562 extern PVOID MmNonPagedPoolStart; 563 extern PVOID MmNonPagedPoolExpansionStart; 564 extern PVOID MmNonPagedPoolEnd; 565 extern SIZE_T MmSizeOfPagedPoolInBytes; 566 extern PVOID MmPagedPoolStart; 567 extern PVOID MmPagedPoolEnd; 568 extern PVOID MmSessionBase; 569 extern SIZE_T MmSessionSize; 570 extern PMMPTE MmFirstReservedMappingPte, MmLastReservedMappingPte; 571 extern PMMPTE MiFirstReservedZeroingPte; 572 extern MI_PFN_CACHE_ATTRIBUTE MiPlatformCacheAttributes[2][MmMaximumCacheType]; 573 extern PPHYSICAL_MEMORY_DESCRIPTOR MmPhysicalMemoryBlock; 574 extern SIZE_T MmBootImageSize; 575 extern PMMPTE MmSystemPtesStart[MaximumPtePoolTypes]; 576 extern PMMPTE MmSystemPtesEnd[MaximumPtePoolTypes]; 577 extern PMEMORY_ALLOCATION_DESCRIPTOR MxFreeDescriptor; 578 extern MEMORY_ALLOCATION_DESCRIPTOR MxOldFreeDescriptor; 579 extern ULONG_PTR MxPfnAllocation; 580 extern MM_PAGED_POOL_INFO MmPagedPoolInfo; 581 extern RTL_BITMAP MiPfnBitMap; 582 extern KGUARDED_MUTEX MmPagedPoolMutex; 583 extern KGUARDED_MUTEX MmSectionCommitMutex; 584 extern PVOID MmPagedPoolStart; 585 extern PVOID MmPagedPoolEnd; 586 extern PVOID MmNonPagedSystemStart; 587 extern PVOID MiSystemViewStart; 588 extern SIZE_T MmSystemViewSize; 589 extern PVOID MmSessionBase; 590 extern PVOID MiSessionSpaceEnd; 591 extern PMMPTE MiSessionImagePteStart; 592 extern PMMPTE MiSessionImagePteEnd; 593 extern PMMPTE MiSessionBasePte; 594 extern PMMPTE MiSessionLastPte; 595 extern SIZE_T MmSizeOfPagedPoolInBytes; 596 extern PMMPDE MmSystemPagePtes; 597 extern PVOID MmSystemCacheStart; 598 extern PVOID MmSystemCacheEnd; 599 extern MMSUPPORT MmSystemCacheWs; 600 extern SIZE_T MmAllocatedNonPagedPool; 601 extern ULONG MmSpecialPoolTag; 602 extern PVOID MmHyperSpaceEnd; 603 extern PMMWSL MmSystemCacheWorkingSetList; 604 extern SIZE_T MmMinimumNonPagedPoolSize; 605 extern ULONG MmMinAdditionNonPagedPoolPerMb; 606 extern SIZE_T MmDefaultMaximumNonPagedPool; 607 extern ULONG MmMaxAdditionNonPagedPoolPerMb; 608 extern ULONG MmSecondaryColors; 609 extern ULONG MmSecondaryColorMask; 610 extern ULONG MmNumberOfSystemPtes; 611 extern ULONG MmMaximumNonPagedPoolPercent; 612 extern ULONG MmLargeStackSize; 613 extern PMMCOLOR_TABLES MmFreePagesByColor[FreePageList + 1]; 614 extern MMPFNLIST MmStandbyPageListByPriority[8]; 615 extern ULONG MmProductType; 616 extern MM_SYSTEMSIZE MmSystemSize; 617 extern PKEVENT MiLowMemoryEvent; 618 extern PKEVENT MiHighMemoryEvent; 619 extern PKEVENT MiLowPagedPoolEvent; 620 extern PKEVENT MiHighPagedPoolEvent; 621 extern PKEVENT MiLowNonPagedPoolEvent; 622 extern PKEVENT MiHighNonPagedPoolEvent; 623 extern PFN_NUMBER MmLowMemoryThreshold; 624 extern PFN_NUMBER MmHighMemoryThreshold; 625 extern PFN_NUMBER MiLowPagedPoolThreshold; 626 extern PFN_NUMBER MiHighPagedPoolThreshold; 627 extern PFN_NUMBER MiLowNonPagedPoolThreshold; 628 extern PFN_NUMBER MiHighNonPagedPoolThreshold; 629 extern PFN_NUMBER MmMinimumFreePages; 630 extern PFN_NUMBER MmPlentyFreePages; 631 extern SIZE_T MmMinimumStackCommitInBytes; 632 extern PFN_COUNT MiExpansionPoolPagesInitialCharge; 633 extern PFN_NUMBER MmResidentAvailablePages; 634 extern PFN_NUMBER MmResidentAvailableAtInit; 635 extern ULONG MmTotalFreeSystemPtes[MaximumPtePoolTypes]; 636 extern PFN_NUMBER MmTotalSystemDriverPages; 637 extern ULONG MmCritsectTimeoutSeconds; 638 extern PVOID MiSessionImageStart; 639 extern PVOID MiSessionImageEnd; 640 extern PMMPTE MiHighestUserPte; 641 extern PMMPDE MiHighestUserPde; 642 extern PFN_NUMBER MmSystemPageDirectory[PPE_PER_PAGE]; 643 extern PMMPTE MmSharedUserDataPte; 644 extern LIST_ENTRY MmProcessList; 645 extern BOOLEAN MmZeroingPageThreadActive; 646 extern KEVENT MmZeroingPageEvent; 647 extern ULONG MmSystemPageColor; 648 extern ULONG MmProcessColorSeed; 649 extern PMMWSL MmWorkingSetList; 650 extern PFN_NUMBER MiNumberOfFreePages; 651 extern SIZE_T MmSessionViewSize; 652 extern SIZE_T MmSessionPoolSize; 653 extern SIZE_T MmSessionImageSize; 654 extern PVOID MiSystemViewStart; 655 extern PVOID MiSessionPoolEnd; // 0xBE000000 656 extern PVOID MiSessionPoolStart; // 0xBD000000 657 extern PVOID MiSessionViewStart; // 0xBE000000 658 extern PVOID MiSessionSpaceWs; 659 extern ULONG MmMaximumDeadKernelStacks; 660 extern SLIST_HEADER MmDeadStackSListHead; 661 extern MM_AVL_TABLE MmSectionBasedRoot; 662 extern KGUARDED_MUTEX MmSectionBasedMutex; 663 extern PVOID MmHighSectionBase; 664 extern SIZE_T MmSystemLockPagesCount; 665 extern ULONG_PTR MmSubsectionBase; 666 extern LARGE_INTEGER MmCriticalSectionTimeout; 667 extern LIST_ENTRY MmWorkingSetExpansionHead; 668 extern KSPIN_LOCK MmExpansionLock; 669 extern PETHREAD MiExpansionLockOwner; 670 671 FORCEINLINE 672 BOOLEAN 673 MiIsMemoryTypeFree(TYPE_OF_MEMORY MemoryType) 674 { 675 return ((MemoryType == LoaderFree) || 676 (MemoryType == LoaderLoadedProgram) || 677 (MemoryType == LoaderFirmwareTemporary) || 678 (MemoryType == LoaderOsloaderStack)); 679 } 680 681 FORCEINLINE 682 BOOLEAN 683 MiIsMemoryTypeInvisible(TYPE_OF_MEMORY MemoryType) 684 { 685 return ((MemoryType == LoaderFirmwarePermanent) || 686 (MemoryType == LoaderSpecialMemory) || 687 (MemoryType == LoaderHALCachedMemory) || 688 (MemoryType == LoaderBBTMemory)); 689 } 690 691 #ifdef _M_AMD64 692 FORCEINLINE 693 BOOLEAN 694 MiIsUserPxe(PVOID Address) 695 { 696 return ((ULONG_PTR)Address >> 7) == 0x1FFFFEDF6FB7DA0ULL; 697 } 698 699 FORCEINLINE 700 BOOLEAN 701 MiIsUserPpe(PVOID Address) 702 { 703 return ((ULONG_PTR)Address >> 16) == 0xFFFFF6FB7DA0ULL; 704 } 705 706 FORCEINLINE 707 BOOLEAN 708 MiIsUserPde(PVOID Address) 709 { 710 return ((ULONG_PTR)Address >> 25) == 0x7FFFFB7DA0ULL; 711 } 712 713 FORCEINLINE 714 BOOLEAN 715 MiIsUserPte(PVOID Address) 716 { 717 return ((ULONG_PTR)Address >> 34) == 0x3FFFFDA0ULL; 718 } 719 #else 720 FORCEINLINE 721 BOOLEAN 722 MiIsUserPde(PVOID Address) 723 { 724 return ((Address >= (PVOID)MiAddressToPde(NULL)) && 725 (Address <= (PVOID)MiHighestUserPde)); 726 } 727 728 FORCEINLINE 729 BOOLEAN 730 MiIsUserPte(PVOID Address) 731 { 732 return (Address <= (PVOID)MiHighestUserPte); 733 } 734 #endif 735 736 // 737 // Figures out the hardware bits for a PTE 738 // 739 FORCEINLINE 740 ULONG_PTR 741 MiDetermineUserGlobalPteMask(IN PVOID PointerPte) 742 { 743 MMPTE TempPte; 744 745 /* Start fresh */ 746 TempPte.u.Long = 0; 747 748 /* Make it valid and accessed */ 749 TempPte.u.Hard.Valid = TRUE; 750 MI_MAKE_ACCESSED_PAGE(&TempPte); 751 752 /* Is this for user-mode? */ 753 if ( 754 #if (_MI_PAGING_LEVELS == 4) 755 MiIsUserPxe(PointerPte) || 756 #endif 757 #if (_MI_PAGING_LEVELS >= 3) 758 MiIsUserPpe(PointerPte) || 759 #endif 760 MiIsUserPde(PointerPte) || 761 MiIsUserPte(PointerPte)) 762 { 763 /* Set the owner bit */ 764 MI_MAKE_OWNER_PAGE(&TempPte); 765 } 766 767 /* FIXME: We should also set the global bit */ 768 769 /* Return the protection */ 770 return TempPte.u.Long; 771 } 772 773 // 774 // Creates a valid kernel PTE with the given protection 775 // 776 FORCEINLINE 777 VOID 778 MI_MAKE_HARDWARE_PTE_KERNEL(IN PMMPTE NewPte, 779 IN PMMPTE MappingPte, 780 IN ULONG_PTR ProtectionMask, 781 IN PFN_NUMBER PageFrameNumber) 782 { 783 /* Only valid for kernel, non-session PTEs */ 784 ASSERT(MappingPte > MiHighestUserPte); 785 ASSERT(!MI_IS_SESSION_PTE(MappingPte)); 786 ASSERT((MappingPte < (PMMPTE)PDE_BASE) || (MappingPte > (PMMPTE)PDE_TOP)); 787 788 /* Start fresh */ 789 *NewPte = ValidKernelPte; 790 791 /* Set the protection and page */ 792 NewPte->u.Hard.PageFrameNumber = PageFrameNumber; 793 NewPte->u.Long |= MmProtectToPteMask[ProtectionMask]; 794 } 795 796 // 797 // Creates a valid PTE with the given protection 798 // 799 FORCEINLINE 800 VOID 801 MI_MAKE_HARDWARE_PTE(IN PMMPTE NewPte, 802 IN PMMPTE MappingPte, 803 IN ULONG_PTR ProtectionMask, 804 IN PFN_NUMBER PageFrameNumber) 805 { 806 /* Set the protection and page */ 807 NewPte->u.Long = MiDetermineUserGlobalPteMask(MappingPte); 808 NewPte->u.Long |= MmProtectToPteMask[ProtectionMask]; 809 NewPte->u.Hard.PageFrameNumber = PageFrameNumber; 810 } 811 812 // 813 // Creates a valid user PTE with the given protection 814 // 815 FORCEINLINE 816 VOID 817 MI_MAKE_HARDWARE_PTE_USER(IN PMMPTE NewPte, 818 IN PMMPTE MappingPte, 819 IN ULONG_PTR ProtectionMask, 820 IN PFN_NUMBER PageFrameNumber) 821 { 822 /* Only valid for kernel, non-session PTEs */ 823 ASSERT(MappingPte <= MiHighestUserPte); 824 825 /* Start fresh */ 826 NewPte->u.Long = 0; 827 828 /* Set the protection and page */ 829 NewPte->u.Hard.Valid = TRUE; 830 NewPte->u.Hard.Owner = TRUE; 831 NewPte->u.Hard.PageFrameNumber = PageFrameNumber; 832 NewPte->u.Long |= MmProtectToPteMask[ProtectionMask]; 833 } 834 835 #ifndef _M_AMD64 836 // 837 // Builds a Prototype PTE for the address of the PTE 838 // 839 FORCEINLINE 840 VOID 841 MI_MAKE_PROTOTYPE_PTE(IN PMMPTE NewPte, 842 IN PMMPTE PointerPte) 843 { 844 ULONG_PTR Offset; 845 846 /* Mark this as a prototype */ 847 NewPte->u.Long = 0; 848 NewPte->u.Proto.Prototype = 1; 849 850 /* 851 * Prototype PTEs are only valid in paged pool by design, this little trick 852 * lets us only use 30 bits for the adress of the PTE, as long as the area 853 * stays 1024MB At most. 854 */ 855 Offset = (ULONG_PTR)PointerPte - (ULONG_PTR)MmPagedPoolStart; 856 857 /* 858 * 7 bits go in the "low" (but we assume the bottom 2 are zero) 859 * and the other 21 bits go in the "high" 860 */ 861 NewPte->u.Proto.ProtoAddressLow = (Offset & 0x1FC) >> 2; 862 NewPte->u.Proto.ProtoAddressHigh = (Offset & 0x3FFFFE00) >> 9; 863 } 864 865 // 866 // Builds a Subsection PTE for the address of the Segment 867 // 868 FORCEINLINE 869 VOID 870 MI_MAKE_SUBSECTION_PTE(IN PMMPTE NewPte, 871 IN PVOID Segment) 872 { 873 ULONG_PTR Offset; 874 875 /* Mark this as a prototype */ 876 NewPte->u.Long = 0; 877 NewPte->u.Subsect.Prototype = 1; 878 879 /* 880 * Segments are only valid either in nonpaged pool. We store the 20 bit 881 * difference either from the top or bottom of nonpaged pool, giving a 882 * maximum of 128MB to each delta, meaning nonpaged pool cannot exceed 883 * 256MB. 884 */ 885 if ((ULONG_PTR)Segment < ((ULONG_PTR)MmSubsectionBase + (128 * _1MB))) 886 { 887 Offset = (ULONG_PTR)Segment - (ULONG_PTR)MmSubsectionBase; 888 NewPte->u.Subsect.WhichPool = PagedPool; 889 } 890 else 891 { 892 Offset = (ULONG_PTR)MmNonPagedPoolEnd - (ULONG_PTR)Segment; 893 NewPte->u.Subsect.WhichPool = NonPagedPool; 894 } 895 896 /* 897 * 4 bits go in the "low" (but we assume the bottom 3 are zero) 898 * and the other 20 bits go in the "high" 899 */ 900 NewPte->u.Subsect.SubsectionAddressLow = (Offset & 0x78) >> 3; 901 NewPte->u.Subsect.SubsectionAddressHigh = (Offset & 0xFFFFF80) >> 7; 902 } 903 904 FORCEINLINE 905 BOOLEAN 906 MI_IS_MAPPED_PTE(PMMPTE PointerPte) 907 { 908 /// \todo Make this reasonable code, this is UGLY! 909 return ((PointerPte->u.Long & 0xFFFFFC01) != 0); 910 } 911 912 #endif 913 914 FORCEINLINE 915 VOID 916 MI_MAKE_TRANSITION_PTE(_Out_ PMMPTE NewPte, 917 _In_ PFN_NUMBER Page, 918 _In_ ULONG Protection) 919 { 920 NewPte->u.Long = 0; 921 NewPte->u.Trans.Transition = 1; 922 NewPte->u.Trans.Protection = Protection; 923 NewPte->u.Trans.PageFrameNumber = Page; 924 } 925 926 // 927 // Returns if the page is physically resident (ie: a large page) 928 // FIXFIX: CISC/x86 only? 929 // 930 FORCEINLINE 931 BOOLEAN 932 MI_IS_PHYSICAL_ADDRESS(IN PVOID Address) 933 { 934 PMMPDE PointerPde; 935 936 /* Large pages are never paged out, always physically resident */ 937 PointerPde = MiAddressToPde(Address); 938 return ((PointerPde->u.Hard.LargePage) && (PointerPde->u.Hard.Valid)); 939 } 940 941 // 942 // Writes a valid PTE 943 // 944 FORCEINLINE 945 VOID 946 MI_WRITE_VALID_PTE(IN PMMPTE PointerPte, 947 IN MMPTE TempPte) 948 { 949 /* Write the valid PTE */ 950 ASSERT(PointerPte->u.Hard.Valid == 0); 951 ASSERT(TempPte.u.Hard.Valid == 1); 952 *PointerPte = TempPte; 953 } 954 955 // 956 // Updates a valid PTE 957 // 958 FORCEINLINE 959 VOID 960 MI_UPDATE_VALID_PTE(IN PMMPTE PointerPte, 961 IN MMPTE TempPte) 962 { 963 /* Write the valid PTE */ 964 ASSERT(PointerPte->u.Hard.Valid == 1); 965 ASSERT(TempPte.u.Hard.Valid == 1); 966 ASSERT(PointerPte->u.Hard.PageFrameNumber == TempPte.u.Hard.PageFrameNumber); 967 *PointerPte = TempPte; 968 } 969 970 // 971 // Writes an invalid PTE 972 // 973 FORCEINLINE 974 VOID 975 MI_WRITE_INVALID_PTE(IN PMMPTE PointerPte, 976 IN MMPTE InvalidPte) 977 { 978 /* Write the invalid PTE */ 979 ASSERT(InvalidPte.u.Hard.Valid == 0); 980 ASSERT(InvalidPte.u.Long != 0); 981 *PointerPte = InvalidPte; 982 } 983 984 // 985 // Erase the PTE completely 986 // 987 FORCEINLINE 988 VOID 989 MI_ERASE_PTE(IN PMMPTE PointerPte) 990 { 991 /* Zero out the PTE */ 992 ASSERT(PointerPte->u.Long != 0); 993 PointerPte->u.Long = 0; 994 } 995 996 // 997 // Writes a valid PDE 998 // 999 FORCEINLINE 1000 VOID 1001 MI_WRITE_VALID_PDE(IN PMMPDE PointerPde, 1002 IN MMPDE TempPde) 1003 { 1004 /* Write the valid PDE */ 1005 ASSERT(PointerPde->u.Hard.Valid == 0); 1006 ASSERT(TempPde.u.Hard.Valid == 1); 1007 *PointerPde = TempPde; 1008 } 1009 1010 // 1011 // Writes an invalid PDE 1012 // 1013 FORCEINLINE 1014 VOID 1015 MI_WRITE_INVALID_PDE(IN PMMPDE PointerPde, 1016 IN MMPDE InvalidPde) 1017 { 1018 /* Write the invalid PDE */ 1019 ASSERT(InvalidPde.u.Hard.Valid == 0); 1020 ASSERT(InvalidPde.u.Long != 0); 1021 *PointerPde = InvalidPde; 1022 } 1023 1024 // 1025 // Checks if the thread already owns a working set 1026 // 1027 FORCEINLINE 1028 BOOLEAN 1029 MM_ANY_WS_LOCK_HELD(IN PETHREAD Thread) 1030 { 1031 /* If any of these are held, return TRUE */ 1032 return ((Thread->OwnsProcessWorkingSetExclusive) || 1033 (Thread->OwnsProcessWorkingSetShared) || 1034 (Thread->OwnsSystemWorkingSetExclusive) || 1035 (Thread->OwnsSystemWorkingSetShared) || 1036 (Thread->OwnsSessionWorkingSetExclusive) || 1037 (Thread->OwnsSessionWorkingSetShared)); 1038 } 1039 1040 // 1041 // Checks if the process owns the working set lock 1042 // 1043 FORCEINLINE 1044 BOOLEAN 1045 MI_WS_OWNER(IN PEPROCESS Process) 1046 { 1047 /* Check if this process is the owner, and that the thread owns the WS */ 1048 if (PsGetCurrentThread()->OwnsProcessWorkingSetExclusive == 0) 1049 { 1050 DPRINT("Thread: %p is not an owner\n", PsGetCurrentThread()); 1051 } 1052 if (KeGetCurrentThread()->ApcState.Process != &Process->Pcb) 1053 { 1054 DPRINT("Current thread %p is attached to another process %p\n", PsGetCurrentThread(), Process); 1055 } 1056 return ((KeGetCurrentThread()->ApcState.Process == &Process->Pcb) && 1057 ((PsGetCurrentThread()->OwnsProcessWorkingSetExclusive) || 1058 (PsGetCurrentThread()->OwnsProcessWorkingSetShared))); 1059 } 1060 1061 // 1062 // New ARM3<->RosMM PAGE Architecture 1063 // 1064 FORCEINLINE 1065 BOOLEAN 1066 MiIsRosSectionObject(IN PVOID Section) 1067 { 1068 PROS_SECTION_OBJECT RosSection = Section; 1069 if ((RosSection->Type == 'SC') && (RosSection->Size == 'TN')) return TRUE; 1070 return FALSE; 1071 } 1072 1073 #define MI_IS_ROS_PFN(x) ((x)->u4.AweAllocation == TRUE) 1074 1075 VOID 1076 NTAPI 1077 MiDecrementReferenceCount( 1078 IN PMMPFN Pfn1, 1079 IN PFN_NUMBER PageFrameIndex 1080 ); 1081 1082 FORCEINLINE 1083 BOOLEAN 1084 MI_IS_WS_UNSAFE(IN PEPROCESS Process) 1085 { 1086 return (Process->Vm.Flags.AcquiredUnsafe == TRUE); 1087 } 1088 1089 // 1090 // Locks the working set for the given process 1091 // 1092 FORCEINLINE 1093 VOID 1094 MiLockProcessWorkingSet(IN PEPROCESS Process, 1095 IN PETHREAD Thread) 1096 { 1097 /* Shouldn't already be owning the process working set */ 1098 ASSERT(Thread->OwnsProcessWorkingSetShared == FALSE); 1099 ASSERT(Thread->OwnsProcessWorkingSetExclusive == FALSE); 1100 1101 /* Block APCs, make sure that still nothing is already held */ 1102 KeEnterGuardedRegion(); 1103 ASSERT(!MM_ANY_WS_LOCK_HELD(Thread)); 1104 1105 /* Lock the working set */ 1106 ExAcquirePushLockExclusive(&Process->Vm.WorkingSetMutex); 1107 1108 /* Now claim that we own the lock */ 1109 ASSERT(!MI_IS_WS_UNSAFE(Process)); 1110 ASSERT(Thread->OwnsProcessWorkingSetExclusive == FALSE); 1111 Thread->OwnsProcessWorkingSetExclusive = TRUE; 1112 } 1113 1114 FORCEINLINE 1115 VOID 1116 MiLockProcessWorkingSetShared(IN PEPROCESS Process, 1117 IN PETHREAD Thread) 1118 { 1119 /* Shouldn't already be owning the process working set */ 1120 ASSERT(Thread->OwnsProcessWorkingSetShared == FALSE); 1121 ASSERT(Thread->OwnsProcessWorkingSetExclusive == FALSE); 1122 1123 /* Block APCs, make sure that still nothing is already held */ 1124 KeEnterGuardedRegion(); 1125 ASSERT(!MM_ANY_WS_LOCK_HELD(Thread)); 1126 1127 /* Lock the working set */ 1128 ExAcquirePushLockShared(&Process->Vm.WorkingSetMutex); 1129 1130 /* Now claim that we own the lock */ 1131 ASSERT(!MI_IS_WS_UNSAFE(Process)); 1132 ASSERT(Thread->OwnsProcessWorkingSetShared == FALSE); 1133 ASSERT(Thread->OwnsProcessWorkingSetExclusive == FALSE); 1134 Thread->OwnsProcessWorkingSetShared = TRUE; 1135 } 1136 1137 FORCEINLINE 1138 VOID 1139 MiLockProcessWorkingSetUnsafe(IN PEPROCESS Process, 1140 IN PETHREAD Thread) 1141 { 1142 /* Shouldn't already be owning the process working set */ 1143 ASSERT(Thread->OwnsProcessWorkingSetExclusive == FALSE); 1144 1145 /* APCs must be blocked, make sure that still nothing is already held */ 1146 ASSERT(KeAreAllApcsDisabled() == TRUE); 1147 ASSERT(!MM_ANY_WS_LOCK_HELD(Thread)); 1148 1149 /* Lock the working set */ 1150 ExAcquirePushLockExclusive(&Process->Vm.WorkingSetMutex); 1151 1152 /* Now claim that we own the lock */ 1153 ASSERT(!MI_IS_WS_UNSAFE(Process)); 1154 Process->Vm.Flags.AcquiredUnsafe = 1; 1155 ASSERT(Thread->OwnsProcessWorkingSetExclusive == FALSE); 1156 Thread->OwnsProcessWorkingSetExclusive = TRUE; 1157 } 1158 1159 // 1160 // Unlocks the working set for the given process 1161 // 1162 FORCEINLINE 1163 VOID 1164 MiUnlockProcessWorkingSet(IN PEPROCESS Process, 1165 IN PETHREAD Thread) 1166 { 1167 /* Make sure we are the owner of a safe acquisition */ 1168 ASSERT(MI_WS_OWNER(Process)); 1169 ASSERT(!MI_IS_WS_UNSAFE(Process)); 1170 1171 /* The thread doesn't own it anymore */ 1172 ASSERT(Thread->OwnsProcessWorkingSetExclusive == TRUE); 1173 Thread->OwnsProcessWorkingSetExclusive = FALSE; 1174 1175 /* Release the lock and re-enable APCs */ 1176 ExReleasePushLockExclusive(&Process->Vm.WorkingSetMutex); 1177 KeLeaveGuardedRegion(); 1178 } 1179 1180 // 1181 // Unlocks the working set for the given process 1182 // 1183 FORCEINLINE 1184 VOID 1185 MiUnlockProcessWorkingSetShared(IN PEPROCESS Process, 1186 IN PETHREAD Thread) 1187 { 1188 /* Make sure we are the owner of a safe acquisition (because shared) */ 1189 ASSERT(MI_WS_OWNER(Process)); 1190 ASSERT(!MI_IS_WS_UNSAFE(Process)); 1191 1192 /* Ensure we are in a shared acquisition */ 1193 ASSERT(Thread->OwnsProcessWorkingSetShared == TRUE); 1194 ASSERT(Thread->OwnsProcessWorkingSetExclusive == FALSE); 1195 1196 /* Don't claim the lock anylonger */ 1197 Thread->OwnsProcessWorkingSetShared = FALSE; 1198 1199 /* Release the lock and re-enable APCs */ 1200 ExReleasePushLockShared(&Process->Vm.WorkingSetMutex); 1201 KeLeaveGuardedRegion(); 1202 } 1203 1204 // 1205 // Unlocks the working set for the given process 1206 // 1207 FORCEINLINE 1208 VOID 1209 MiUnlockProcessWorkingSetUnsafe(IN PEPROCESS Process, 1210 IN PETHREAD Thread) 1211 { 1212 /* Make sure we are the owner of an unsafe acquisition */ 1213 ASSERT(KeGetCurrentIrql() <= APC_LEVEL); 1214 ASSERT(KeAreAllApcsDisabled() == TRUE); 1215 ASSERT(MI_WS_OWNER(Process)); 1216 ASSERT(MI_IS_WS_UNSAFE(Process)); 1217 1218 /* No longer unsafe */ 1219 Process->Vm.Flags.AcquiredUnsafe = 0; 1220 1221 /* The thread doesn't own it anymore */ 1222 ASSERT(Thread->OwnsProcessWorkingSetExclusive == TRUE); 1223 Thread->OwnsProcessWorkingSetExclusive = FALSE; 1224 1225 /* Release the lock but don't touch APC state */ 1226 ExReleasePushLockExclusive(&Process->Vm.WorkingSetMutex); 1227 ASSERT(KeGetCurrentIrql() <= APC_LEVEL); 1228 } 1229 1230 // 1231 // Locks the working set 1232 // 1233 FORCEINLINE 1234 VOID 1235 MiLockWorkingSet(IN PETHREAD Thread, 1236 IN PMMSUPPORT WorkingSet) 1237 { 1238 /* Block APCs */ 1239 KeEnterGuardedRegion(); 1240 1241 /* Working set should be in global memory */ 1242 ASSERT(MI_IS_SESSION_ADDRESS((PVOID)WorkingSet) == FALSE); 1243 1244 /* Thread shouldn't already be owning something */ 1245 ASSERT(!MM_ANY_WS_LOCK_HELD(Thread)); 1246 1247 /* Lock this working set */ 1248 ExAcquirePushLockExclusive(&WorkingSet->WorkingSetMutex); 1249 1250 /* Which working set is this? */ 1251 if (WorkingSet == &MmSystemCacheWs) 1252 { 1253 /* Own the system working set */ 1254 ASSERT((Thread->OwnsSystemWorkingSetExclusive == FALSE) && 1255 (Thread->OwnsSystemWorkingSetShared == FALSE)); 1256 Thread->OwnsSystemWorkingSetExclusive = TRUE; 1257 } 1258 else if (WorkingSet->Flags.SessionSpace) 1259 { 1260 /* Own the session working set */ 1261 ASSERT((Thread->OwnsSessionWorkingSetExclusive == FALSE) && 1262 (Thread->OwnsSessionWorkingSetShared == FALSE)); 1263 Thread->OwnsSessionWorkingSetExclusive = TRUE; 1264 } 1265 else 1266 { 1267 /* Own the process working set */ 1268 ASSERT((Thread->OwnsProcessWorkingSetExclusive == FALSE) && 1269 (Thread->OwnsProcessWorkingSetShared == FALSE)); 1270 Thread->OwnsProcessWorkingSetExclusive = TRUE; 1271 } 1272 } 1273 1274 // 1275 // Unlocks the working set 1276 // 1277 FORCEINLINE 1278 VOID 1279 MiUnlockWorkingSet(IN PETHREAD Thread, 1280 IN PMMSUPPORT WorkingSet) 1281 { 1282 /* Working set should be in global memory */ 1283 ASSERT(MI_IS_SESSION_ADDRESS((PVOID)WorkingSet) == FALSE); 1284 1285 /* Which working set is this? */ 1286 if (WorkingSet == &MmSystemCacheWs) 1287 { 1288 /* Release the system working set */ 1289 ASSERT((Thread->OwnsSystemWorkingSetExclusive == TRUE) || 1290 (Thread->OwnsSystemWorkingSetShared == TRUE)); 1291 Thread->OwnsSystemWorkingSetExclusive = FALSE; 1292 } 1293 else if (WorkingSet->Flags.SessionSpace) 1294 { 1295 /* Release the session working set */ 1296 ASSERT((Thread->OwnsSessionWorkingSetExclusive == TRUE) || 1297 (Thread->OwnsSessionWorkingSetShared == TRUE)); 1298 Thread->OwnsSessionWorkingSetExclusive = 0; 1299 } 1300 else 1301 { 1302 /* Release the process working set */ 1303 ASSERT((Thread->OwnsProcessWorkingSetExclusive) || 1304 (Thread->OwnsProcessWorkingSetShared)); 1305 Thread->OwnsProcessWorkingSetExclusive = FALSE; 1306 } 1307 1308 /* Release the working set lock */ 1309 ExReleasePushLockExclusive(&WorkingSet->WorkingSetMutex); 1310 1311 /* Unblock APCs */ 1312 KeLeaveGuardedRegion(); 1313 } 1314 1315 FORCEINLINE 1316 VOID 1317 MiUnlockProcessWorkingSetForFault(IN PEPROCESS Process, 1318 IN PETHREAD Thread, 1319 OUT PBOOLEAN Safe, 1320 OUT PBOOLEAN Shared) 1321 { 1322 ASSERT(MI_WS_OWNER(Process)); 1323 1324 /* Check if the current owner is unsafe */ 1325 if (MI_IS_WS_UNSAFE(Process)) 1326 { 1327 /* Release unsafely */ 1328 MiUnlockProcessWorkingSetUnsafe(Process, Thread); 1329 *Safe = FALSE; 1330 *Shared = FALSE; 1331 } 1332 else if (Thread->OwnsProcessWorkingSetExclusive == 1) 1333 { 1334 /* Owner is safe and exclusive, release normally */ 1335 MiUnlockProcessWorkingSet(Process, Thread); 1336 *Safe = TRUE; 1337 *Shared = FALSE; 1338 } 1339 else 1340 { 1341 /* Owner is shared (implies safe), release normally */ 1342 MiUnlockProcessWorkingSetShared(Process, Thread); 1343 *Safe = TRUE; 1344 *Shared = TRUE; 1345 } 1346 } 1347 1348 FORCEINLINE 1349 VOID 1350 MiLockProcessWorkingSetForFault(IN PEPROCESS Process, 1351 IN PETHREAD Thread, 1352 IN BOOLEAN Safe, 1353 IN BOOLEAN Shared) 1354 { 1355 /* Check if this was a safe lock or not */ 1356 if (Safe) 1357 { 1358 if (Shared) 1359 { 1360 /* Reacquire safely & shared */ 1361 MiLockProcessWorkingSetShared(Process, Thread); 1362 } 1363 else 1364 { 1365 /* Reacquire safely */ 1366 MiLockProcessWorkingSet(Process, Thread); 1367 } 1368 } 1369 else 1370 { 1371 /* Unsafe lock cannot be shared */ 1372 ASSERT(Shared == FALSE); 1373 /* Reacquire unsafely */ 1374 MiLockProcessWorkingSetUnsafe(Process, Thread); 1375 } 1376 } 1377 1378 FORCEINLINE 1379 KIRQL 1380 MiAcquireExpansionLock(VOID) 1381 { 1382 KIRQL OldIrql; 1383 1384 ASSERT(KeGetCurrentIrql() <= APC_LEVEL); 1385 KeAcquireSpinLock(&MmExpansionLock, &OldIrql); 1386 ASSERT(MiExpansionLockOwner == NULL); 1387 MiExpansionLockOwner = PsGetCurrentThread(); 1388 return OldIrql; 1389 } 1390 1391 FORCEINLINE 1392 VOID 1393 MiReleaseExpansionLock(KIRQL OldIrql) 1394 { 1395 ASSERT(MiExpansionLockOwner == PsGetCurrentThread()); 1396 MiExpansionLockOwner = NULL; 1397 KeReleaseSpinLock(&MmExpansionLock, OldIrql); 1398 ASSERT(KeGetCurrentIrql() <= APC_LEVEL); 1399 } 1400 1401 // 1402 // Returns the ProtoPTE inside a VAD for the given VPN 1403 // 1404 FORCEINLINE 1405 PMMPTE 1406 MI_GET_PROTOTYPE_PTE_FOR_VPN(IN PMMVAD Vad, 1407 IN ULONG_PTR Vpn) 1408 { 1409 PMMPTE ProtoPte; 1410 1411 /* Find the offset within the VAD's prototype PTEs */ 1412 ProtoPte = Vad->FirstPrototypePte + (Vpn - Vad->StartingVpn); 1413 ASSERT(ProtoPte <= Vad->LastContiguousPte); 1414 return ProtoPte; 1415 } 1416 1417 // 1418 // Returns the PFN Database entry for the given page number 1419 // Warning: This is not necessarily a valid PFN database entry! 1420 // 1421 FORCEINLINE 1422 PMMPFN 1423 MI_PFN_ELEMENT(IN PFN_NUMBER Pfn) 1424 { 1425 /* Get the entry */ 1426 return &MmPfnDatabase[Pfn]; 1427 }; 1428 1429 // 1430 // Drops a locked page without dereferencing it 1431 // 1432 FORCEINLINE 1433 VOID 1434 MiDropLockCount(IN PMMPFN Pfn1) 1435 { 1436 /* This page shouldn't be locked, but it should be valid */ 1437 ASSERT(Pfn1->u3.e2.ReferenceCount != 0); 1438 ASSERT(Pfn1->u2.ShareCount == 0); 1439 1440 /* Is this the last reference to the page */ 1441 if (Pfn1->u3.e2.ReferenceCount == 1) 1442 { 1443 /* It better not be valid */ 1444 ASSERT(Pfn1->u3.e1.PageLocation != ActiveAndValid); 1445 1446 /* Is it a prototype PTE? */ 1447 if ((Pfn1->u3.e1.PrototypePte == 1) && 1448 (Pfn1->OriginalPte.u.Soft.Prototype == 1)) 1449 { 1450 /* FIXME: We should return commit */ 1451 DPRINT1("Not returning commit for prototype PTE\n"); 1452 } 1453 1454 /* Update the counter */ 1455 InterlockedDecrementSizeT(&MmSystemLockPagesCount); 1456 } 1457 } 1458 1459 // 1460 // Drops a locked page and dereferences it 1461 // 1462 FORCEINLINE 1463 VOID 1464 MiDereferencePfnAndDropLockCount(IN PMMPFN Pfn1) 1465 { 1466 USHORT RefCount, OldRefCount; 1467 PFN_NUMBER PageFrameIndex; 1468 1469 /* Loop while we decrement the page successfully */ 1470 do 1471 { 1472 /* There should be at least one reference */ 1473 OldRefCount = Pfn1->u3.e2.ReferenceCount; 1474 ASSERT(OldRefCount != 0); 1475 1476 /* Are we the last one */ 1477 if (OldRefCount == 1) 1478 { 1479 /* The page shoudln't be shared not active at this point */ 1480 ASSERT(Pfn1->u3.e2.ReferenceCount == 1); 1481 ASSERT(Pfn1->u3.e1.PageLocation != ActiveAndValid); 1482 ASSERT(Pfn1->u2.ShareCount == 0); 1483 1484 /* Is it a prototype PTE? */ 1485 if ((Pfn1->u3.e1.PrototypePte == 1) && 1486 (Pfn1->OriginalPte.u.Soft.Prototype == 1)) 1487 { 1488 /* FIXME: We should return commit */ 1489 DPRINT1("Not returning commit for prototype PTE\n"); 1490 } 1491 1492 /* Update the counter, and drop a reference the long way */ 1493 InterlockedDecrementSizeT(&MmSystemLockPagesCount); 1494 PageFrameIndex = MiGetPfnEntryIndex(Pfn1); 1495 MiDecrementReferenceCount(Pfn1, PageFrameIndex); 1496 return; 1497 } 1498 1499 /* Drop a reference the short way, and that's it */ 1500 RefCount = InterlockedCompareExchange16((PSHORT)&Pfn1->u3.e2.ReferenceCount, 1501 OldRefCount - 1, 1502 OldRefCount); 1503 ASSERT(RefCount != 0); 1504 } while (OldRefCount != RefCount); 1505 1506 /* If we got here, there should be more than one reference */ 1507 ASSERT(RefCount > 1); 1508 if (RefCount == 2) 1509 { 1510 /* Is it still being shared? */ 1511 if (Pfn1->u2.ShareCount >= 1) 1512 { 1513 /* Then it should be valid */ 1514 ASSERT(Pfn1->u3.e1.PageLocation == ActiveAndValid); 1515 1516 /* Is it a prototype PTE? */ 1517 if ((Pfn1->u3.e1.PrototypePte == 1) && 1518 (Pfn1->OriginalPte.u.Soft.Prototype == 1)) 1519 { 1520 /* We don't handle ethis */ 1521 ASSERT(FALSE); 1522 } 1523 1524 /* Update the counter */ 1525 InterlockedDecrementSizeT(&MmSystemLockPagesCount); 1526 } 1527 } 1528 } 1529 1530 // 1531 // References a locked page and updates the counter 1532 // Used in MmProbeAndLockPages to handle different edge cases 1533 // 1534 FORCEINLINE 1535 VOID 1536 MiReferenceProbedPageAndBumpLockCount(IN PMMPFN Pfn1) 1537 { 1538 USHORT RefCount, OldRefCount; 1539 1540 /* Sanity check */ 1541 ASSERT(Pfn1->u3.e2.ReferenceCount != 0); 1542 1543 /* Does ARM3 own the page? */ 1544 if (MI_IS_ROS_PFN(Pfn1)) 1545 { 1546 /* ReactOS Mm doesn't track share count */ 1547 ASSERT(Pfn1->u3.e1.PageLocation == ActiveAndValid); 1548 } 1549 else 1550 { 1551 /* On ARM3 pages, we should see a valid share count */ 1552 ASSERT((Pfn1->u2.ShareCount != 0) && (Pfn1->u3.e1.PageLocation == ActiveAndValid)); 1553 1554 /* Is it a prototype PTE? */ 1555 if ((Pfn1->u3.e1.PrototypePte == 1) && 1556 (Pfn1->OriginalPte.u.Soft.Prototype == 1)) 1557 { 1558 /* FIXME: We should charge commit */ 1559 DPRINT1("Not charging commit for prototype PTE\n"); 1560 } 1561 } 1562 1563 /* More locked pages! */ 1564 InterlockedIncrementSizeT(&MmSystemLockPagesCount); 1565 1566 /* Loop trying to update the reference count */ 1567 do 1568 { 1569 /* Get the current reference count, make sure it's valid */ 1570 OldRefCount = Pfn1->u3.e2.ReferenceCount; 1571 ASSERT(OldRefCount != 0); 1572 ASSERT(OldRefCount < 2500); 1573 1574 /* Bump it up by one */ 1575 RefCount = InterlockedCompareExchange16((PSHORT)&Pfn1->u3.e2.ReferenceCount, 1576 OldRefCount + 1, 1577 OldRefCount); 1578 ASSERT(RefCount != 0); 1579 } while (OldRefCount != RefCount); 1580 1581 /* Was this the first lock attempt? If not, undo our bump */ 1582 if (OldRefCount != 1) InterlockedDecrementSizeT(&MmSystemLockPagesCount); 1583 } 1584 1585 // 1586 // References a locked page and updates the counter 1587 // Used in all other cases except MmProbeAndLockPages 1588 // 1589 FORCEINLINE 1590 VOID 1591 MiReferenceUsedPageAndBumpLockCount(IN PMMPFN Pfn1) 1592 { 1593 USHORT NewRefCount; 1594 1595 /* Is it a prototype PTE? */ 1596 if ((Pfn1->u3.e1.PrototypePte == 1) && 1597 (Pfn1->OriginalPte.u.Soft.Prototype == 1)) 1598 { 1599 /* FIXME: We should charge commit */ 1600 DPRINT1("Not charging commit for prototype PTE\n"); 1601 } 1602 1603 /* More locked pages! */ 1604 InterlockedIncrementSizeT(&MmSystemLockPagesCount); 1605 1606 /* Update the reference count */ 1607 NewRefCount = InterlockedIncrement16((PSHORT)&Pfn1->u3.e2.ReferenceCount); 1608 if (NewRefCount == 2) 1609 { 1610 /* Is it locked or shared? */ 1611 if (Pfn1->u2.ShareCount) 1612 { 1613 /* It's shared, so make sure it's active */ 1614 ASSERT(Pfn1->u3.e1.PageLocation == ActiveAndValid); 1615 } 1616 else 1617 { 1618 /* It's locked, so we shouldn't lock again */ 1619 InterlockedDecrementSizeT(&MmSystemLockPagesCount); 1620 } 1621 } 1622 else 1623 { 1624 /* Someone had already locked the page, so undo our bump */ 1625 ASSERT(NewRefCount < 2500); 1626 InterlockedDecrementSizeT(&MmSystemLockPagesCount); 1627 } 1628 } 1629 1630 // 1631 // References a locked page and updates the counter 1632 // Used in all other cases except MmProbeAndLockPages 1633 // 1634 FORCEINLINE 1635 VOID 1636 MiReferenceUnusedPageAndBumpLockCount(IN PMMPFN Pfn1) 1637 { 1638 USHORT NewRefCount; 1639 1640 /* Make sure the page isn't used yet */ 1641 ASSERT(Pfn1->u2.ShareCount == 0); 1642 ASSERT(Pfn1->u3.e1.PageLocation != ActiveAndValid); 1643 1644 /* Is it a prototype PTE? */ 1645 if ((Pfn1->u3.e1.PrototypePte == 1) && 1646 (Pfn1->OriginalPte.u.Soft.Prototype == 1)) 1647 { 1648 /* FIXME: We should charge commit */ 1649 DPRINT1("Not charging commit for prototype PTE\n"); 1650 } 1651 1652 /* More locked pages! */ 1653 InterlockedIncrementSizeT(&MmSystemLockPagesCount); 1654 1655 /* Update the reference count */ 1656 NewRefCount = InterlockedIncrement16((PSHORT)&Pfn1->u3.e2.ReferenceCount); 1657 if (NewRefCount != 1) 1658 { 1659 /* Someone had already locked the page, so undo our bump */ 1660 ASSERT(NewRefCount < 2500); 1661 InterlockedDecrementSizeT(&MmSystemLockPagesCount); 1662 } 1663 } 1664 1665 FORCEINLINE 1666 VOID 1667 MiIncrementPageTableReferences(IN PVOID Address) 1668 { 1669 PUSHORT RefCount; 1670 1671 RefCount = &MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]; 1672 1673 *RefCount += 1; 1674 ASSERT(*RefCount <= PTE_PER_PAGE); 1675 } 1676 1677 FORCEINLINE 1678 VOID 1679 MiDecrementPageTableReferences(IN PVOID Address) 1680 { 1681 PUSHORT RefCount; 1682 1683 RefCount = &MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]; 1684 1685 *RefCount -= 1; 1686 ASSERT(*RefCount < PTE_PER_PAGE); 1687 } 1688 1689 FORCEINLINE 1690 USHORT 1691 MiQueryPageTableReferences(IN PVOID Address) 1692 { 1693 PUSHORT RefCount; 1694 1695 RefCount = &MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]; 1696 1697 return *RefCount; 1698 } 1699 1700 INIT_FUNCTION 1701 BOOLEAN 1702 NTAPI 1703 MmArmInitSystem( 1704 IN ULONG Phase, 1705 IN PLOADER_PARAMETER_BLOCK LoaderBlock 1706 ); 1707 1708 INIT_FUNCTION 1709 VOID 1710 NTAPI 1711 MiInitializeSessionSpaceLayout(VOID); 1712 1713 INIT_FUNCTION 1714 NTSTATUS 1715 NTAPI 1716 MiInitMachineDependent( 1717 IN PLOADER_PARAMETER_BLOCK LoaderBlock 1718 ); 1719 1720 INIT_FUNCTION 1721 VOID 1722 NTAPI 1723 MiComputeColorInformation( 1724 VOID 1725 ); 1726 1727 INIT_FUNCTION 1728 VOID 1729 NTAPI 1730 MiMapPfnDatabase( 1731 IN PLOADER_PARAMETER_BLOCK LoaderBlock 1732 ); 1733 1734 INIT_FUNCTION 1735 VOID 1736 NTAPI 1737 MiInitializeColorTables( 1738 VOID 1739 ); 1740 1741 INIT_FUNCTION 1742 VOID 1743 NTAPI 1744 MiInitializePfnDatabase( 1745 IN PLOADER_PARAMETER_BLOCK LoaderBlock 1746 ); 1747 1748 VOID 1749 NTAPI 1750 MiInitializeSessionWsSupport( 1751 VOID 1752 ); 1753 1754 VOID 1755 NTAPI 1756 MiInitializeSessionIds( 1757 VOID 1758 ); 1759 1760 INIT_FUNCTION 1761 BOOLEAN 1762 NTAPI 1763 MiInitializeMemoryEvents( 1764 VOID 1765 ); 1766 1767 INIT_FUNCTION 1768 PFN_NUMBER 1769 NTAPI 1770 MxGetNextPage( 1771 IN PFN_NUMBER PageCount 1772 ); 1773 1774 INIT_FUNCTION 1775 PPHYSICAL_MEMORY_DESCRIPTOR 1776 NTAPI 1777 MmInitializeMemoryLimits( 1778 IN PLOADER_PARAMETER_BLOCK LoaderBlock, 1779 IN PBOOLEAN IncludeType 1780 ); 1781 1782 PFN_NUMBER 1783 NTAPI 1784 MiPagesInLoaderBlock( 1785 IN PLOADER_PARAMETER_BLOCK LoaderBlock, 1786 IN PBOOLEAN IncludeType 1787 ); 1788 1789 VOID 1790 FASTCALL 1791 MiSyncARM3WithROS( 1792 IN PVOID AddressStart, 1793 IN PVOID AddressEnd 1794 ); 1795 1796 NTSTATUS 1797 NTAPI 1798 MiRosProtectVirtualMemory( 1799 IN PEPROCESS Process, 1800 IN OUT PVOID *BaseAddress, 1801 IN OUT PSIZE_T NumberOfBytesToProtect, 1802 IN ULONG NewAccessProtection, 1803 OUT PULONG OldAccessProtection OPTIONAL 1804 ); 1805 1806 NTSTATUS 1807 NTAPI 1808 MmArmAccessFault( 1809 IN ULONG FaultCode, 1810 IN PVOID Address, 1811 IN KPROCESSOR_MODE Mode, 1812 IN PVOID TrapInformation 1813 ); 1814 1815 NTSTATUS 1816 FASTCALL 1817 MiCheckPdeForPagedPool( 1818 IN PVOID Address 1819 ); 1820 1821 INIT_FUNCTION 1822 VOID 1823 NTAPI 1824 MiInitializeNonPagedPool( 1825 VOID 1826 ); 1827 1828 INIT_FUNCTION 1829 VOID 1830 NTAPI 1831 MiInitializeNonPagedPoolThresholds( 1832 VOID 1833 ); 1834 1835 INIT_FUNCTION 1836 VOID 1837 NTAPI 1838 MiInitializePoolEvents( 1839 VOID 1840 ); 1841 1842 INIT_FUNCTION 1843 VOID // 1844 NTAPI // 1845 InitializePool( // 1846 IN POOL_TYPE PoolType,// FIXFIX: This should go in ex.h after the pool merge 1847 IN ULONG Threshold // 1848 ); // 1849 1850 // FIXFIX: THIS ONE TOO 1851 INIT_FUNCTION 1852 VOID 1853 NTAPI 1854 ExInitializePoolDescriptor( 1855 IN PPOOL_DESCRIPTOR PoolDescriptor, 1856 IN POOL_TYPE PoolType, 1857 IN ULONG PoolIndex, 1858 IN ULONG Threshold, 1859 IN PVOID PoolLock 1860 ); 1861 1862 NTSTATUS 1863 NTAPI 1864 MiInitializeSessionPool( 1865 VOID 1866 ); 1867 1868 INIT_FUNCTION 1869 VOID 1870 NTAPI 1871 MiInitializeSystemPtes( 1872 IN PMMPTE StartingPte, 1873 IN ULONG NumberOfPtes, 1874 IN MMSYSTEM_PTE_POOL_TYPE PoolType 1875 ); 1876 1877 PMMPTE 1878 NTAPI 1879 MiReserveSystemPtes( 1880 IN ULONG NumberOfPtes, 1881 IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType 1882 ); 1883 1884 VOID 1885 NTAPI 1886 MiReleaseSystemPtes( 1887 IN PMMPTE StartingPte, 1888 IN ULONG NumberOfPtes, 1889 IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType 1890 ); 1891 1892 1893 PFN_NUMBER 1894 NTAPI 1895 MiFindContiguousPages( 1896 IN PFN_NUMBER LowestPfn, 1897 IN PFN_NUMBER HighestPfn, 1898 IN PFN_NUMBER BoundaryPfn, 1899 IN PFN_NUMBER SizeInPages, 1900 IN MEMORY_CACHING_TYPE CacheType 1901 ); 1902 1903 PVOID 1904 NTAPI 1905 MiCheckForContiguousMemory( 1906 IN PVOID BaseAddress, 1907 IN PFN_NUMBER BaseAddressPages, 1908 IN PFN_NUMBER SizeInPages, 1909 IN PFN_NUMBER LowestPfn, 1910 IN PFN_NUMBER HighestPfn, 1911 IN PFN_NUMBER BoundaryPfn, 1912 IN MI_PFN_CACHE_ATTRIBUTE CacheAttribute 1913 ); 1914 1915 PMDL 1916 NTAPI 1917 MiAllocatePagesForMdl( 1918 IN PHYSICAL_ADDRESS LowAddress, 1919 IN PHYSICAL_ADDRESS HighAddress, 1920 IN PHYSICAL_ADDRESS SkipBytes, 1921 IN SIZE_T TotalBytes, 1922 IN MI_PFN_CACHE_ATTRIBUTE CacheAttribute, 1923 IN ULONG Flags 1924 ); 1925 1926 VOID 1927 NTAPI 1928 MiInsertPageInList( 1929 IN PMMPFNLIST ListHead, 1930 IN PFN_NUMBER PageFrameIndex 1931 ); 1932 1933 VOID 1934 NTAPI 1935 MiUnlinkFreeOrZeroedPage( 1936 IN PMMPFN Entry 1937 ); 1938 1939 VOID 1940 NTAPI 1941 MiUnlinkPageFromList( 1942 IN PMMPFN Pfn 1943 ); 1944 1945 VOID 1946 NTAPI 1947 MiInitializePfn( 1948 IN PFN_NUMBER PageFrameIndex, 1949 IN PMMPTE PointerPte, 1950 IN BOOLEAN Modified 1951 ); 1952 1953 NTSTATUS 1954 NTAPI 1955 MiInitializeAndChargePfn( 1956 OUT PPFN_NUMBER PageFrameIndex, 1957 IN PMMPDE PointerPde, 1958 IN PFN_NUMBER ContainingPageFrame, 1959 IN BOOLEAN SessionAllocation 1960 ); 1961 1962 VOID 1963 NTAPI 1964 MiInitializePfnAndMakePteValid( 1965 IN PFN_NUMBER PageFrameIndex, 1966 IN PMMPTE PointerPte, 1967 IN MMPTE TempPte 1968 ); 1969 1970 VOID 1971 NTAPI 1972 MiInitializePfnForOtherProcess( 1973 IN PFN_NUMBER PageFrameIndex, 1974 IN PVOID PteAddress, 1975 IN PFN_NUMBER PteFrame 1976 ); 1977 1978 VOID 1979 NTAPI 1980 MiDecrementShareCount( 1981 IN PMMPFN Pfn1, 1982 IN PFN_NUMBER PageFrameIndex 1983 ); 1984 1985 PFN_NUMBER 1986 NTAPI 1987 MiRemoveAnyPage( 1988 IN ULONG Color 1989 ); 1990 1991 PFN_NUMBER 1992 NTAPI 1993 MiRemoveZeroPage( 1994 IN ULONG Color 1995 ); 1996 1997 VOID 1998 NTAPI 1999 MiZeroPhysicalPage( 2000 IN PFN_NUMBER PageFrameIndex 2001 ); 2002 2003 VOID 2004 NTAPI 2005 MiInsertPageInFreeList( 2006 IN PFN_NUMBER PageFrameIndex 2007 ); 2008 2009 PFN_COUNT 2010 NTAPI 2011 MiDeleteSystemPageableVm( 2012 IN PMMPTE PointerPte, 2013 IN PFN_NUMBER PageCount, 2014 IN ULONG Flags, 2015 OUT PPFN_NUMBER ValidPages 2016 ); 2017 2018 ULONG 2019 NTAPI 2020 MiGetPageProtection( 2021 IN PMMPTE PointerPte 2022 ); 2023 2024 PLDR_DATA_TABLE_ENTRY 2025 NTAPI 2026 MiLookupDataTableEntry( 2027 IN PVOID Address 2028 ); 2029 2030 INIT_FUNCTION 2031 VOID 2032 NTAPI 2033 MiInitializeDriverLargePageList( 2034 VOID 2035 ); 2036 2037 INIT_FUNCTION 2038 VOID 2039 NTAPI 2040 MiInitializeLargePageSupport( 2041 VOID 2042 ); 2043 2044 INIT_FUNCTION 2045 VOID 2046 NTAPI 2047 MiSyncCachedRanges( 2048 VOID 2049 ); 2050 2051 BOOLEAN 2052 NTAPI 2053 MiIsPfnInUse( 2054 IN PMMPFN Pfn1 2055 ); 2056 2057 PMMVAD 2058 NTAPI 2059 MiLocateAddress( 2060 IN PVOID VirtualAddress 2061 ); 2062 2063 TABLE_SEARCH_RESULT 2064 NTAPI 2065 MiCheckForConflictingNode( 2066 IN ULONG_PTR StartVpn, 2067 IN ULONG_PTR EndVpn, 2068 IN PMM_AVL_TABLE Table, 2069 OUT PMMADDRESS_NODE *NodeOrParent 2070 ); 2071 2072 TABLE_SEARCH_RESULT 2073 NTAPI 2074 MiFindEmptyAddressRangeDownTree( 2075 IN SIZE_T Length, 2076 IN ULONG_PTR BoundaryAddress, 2077 IN ULONG_PTR Alignment, 2078 IN PMM_AVL_TABLE Table, 2079 OUT PULONG_PTR Base, 2080 OUT PMMADDRESS_NODE *Parent 2081 ); 2082 2083 NTSTATUS 2084 NTAPI 2085 MiFindEmptyAddressRangeDownBasedTree( 2086 IN SIZE_T Length, 2087 IN ULONG_PTR BoundaryAddress, 2088 IN ULONG_PTR Alignment, 2089 IN PMM_AVL_TABLE Table, 2090 OUT PULONG_PTR Base 2091 ); 2092 2093 TABLE_SEARCH_RESULT 2094 NTAPI 2095 MiFindEmptyAddressRangeInTree( 2096 IN SIZE_T Length, 2097 IN ULONG_PTR Alignment, 2098 IN PMM_AVL_TABLE Table, 2099 OUT PMMADDRESS_NODE *PreviousVad, 2100 OUT PULONG_PTR Base 2101 ); 2102 2103 NTSTATUS 2104 NTAPI 2105 MiCheckSecuredVad( 2106 IN PMMVAD Vad, 2107 IN PVOID Base, 2108 IN SIZE_T Size, 2109 IN ULONG ProtectionMask 2110 ); 2111 2112 VOID 2113 NTAPI 2114 MiInsertVad( 2115 _Inout_ PMMVAD Vad, 2116 _Inout_ PMM_AVL_TABLE VadRoot); 2117 2118 NTSTATUS 2119 NTAPI 2120 MiInsertVadEx( 2121 _Inout_ PMMVAD Vad, 2122 _In_ ULONG_PTR *BaseAddress, 2123 _In_ SIZE_T ViewSize, 2124 _In_ ULONG_PTR HighestAddress, 2125 _In_ ULONG_PTR Alignment, 2126 _In_ ULONG AllocationType); 2127 2128 VOID 2129 NTAPI 2130 MiInsertBasedSection( 2131 IN PSECTION Section 2132 ); 2133 2134 NTSTATUS 2135 NTAPI 2136 MiUnmapViewOfSection( 2137 IN PEPROCESS Process, 2138 IN PVOID BaseAddress, 2139 IN ULONG Flags 2140 ); 2141 2142 NTSTATUS 2143 NTAPI 2144 MiRosUnmapViewOfSection( 2145 IN PEPROCESS Process, 2146 IN PVOID BaseAddress, 2147 IN BOOLEAN SkipDebuggerNotify 2148 ); 2149 2150 VOID 2151 NTAPI 2152 MiInsertNode( 2153 IN PMM_AVL_TABLE Table, 2154 IN PMMADDRESS_NODE NewNode, 2155 PMMADDRESS_NODE Parent, 2156 TABLE_SEARCH_RESULT Result 2157 ); 2158 2159 VOID 2160 NTAPI 2161 MiRemoveNode( 2162 IN PMMADDRESS_NODE Node, 2163 IN PMM_AVL_TABLE Table 2164 ); 2165 2166 PMMADDRESS_NODE 2167 NTAPI 2168 MiGetPreviousNode( 2169 IN PMMADDRESS_NODE Node 2170 ); 2171 2172 PMMADDRESS_NODE 2173 NTAPI 2174 MiGetNextNode( 2175 IN PMMADDRESS_NODE Node 2176 ); 2177 2178 BOOLEAN 2179 NTAPI 2180 MiInitializeSystemSpaceMap( 2181 IN PMMSESSION InputSession OPTIONAL 2182 ); 2183 2184 VOID 2185 NTAPI 2186 MiSessionRemoveProcess( 2187 VOID 2188 ); 2189 2190 VOID 2191 NTAPI 2192 MiReleaseProcessReferenceToSessionDataPage( 2193 IN PMM_SESSION_SPACE SessionGlobal 2194 ); 2195 2196 VOID 2197 NTAPI 2198 MiSessionAddProcess( 2199 IN PEPROCESS NewProcess 2200 ); 2201 2202 NTSTATUS 2203 NTAPI 2204 MiSessionCommitPageTables( 2205 IN PVOID StartVa, 2206 IN PVOID EndVa 2207 ); 2208 2209 ULONG 2210 NTAPI 2211 MiMakeProtectionMask( 2212 IN ULONG Protect 2213 ); 2214 2215 VOID 2216 NTAPI 2217 MiDeleteVirtualAddresses( 2218 IN ULONG_PTR Va, 2219 IN ULONG_PTR EndingAddress, 2220 IN PMMVAD Vad 2221 ); 2222 2223 VOID 2224 NTAPI 2225 MiDeletePte( 2226 IN PMMPTE PointerPte, 2227 IN PVOID VirtualAddress, 2228 IN PEPROCESS CurrentProcess, 2229 IN PMMPTE PrototypePte 2230 ); 2231 2232 ULONG 2233 NTAPI 2234 MiMakeSystemAddressValid( 2235 IN PVOID PageTableVirtualAddress, 2236 IN PEPROCESS CurrentProcess 2237 ); 2238 2239 ULONG 2240 NTAPI 2241 MiMakeSystemAddressValidPfn( 2242 IN PVOID VirtualAddress, 2243 IN KIRQL OldIrql 2244 ); 2245 2246 VOID 2247 NTAPI 2248 MiRemoveMappedView( 2249 IN PEPROCESS CurrentProcess, 2250 IN PMMVAD Vad 2251 ); 2252 2253 PSUBSECTION 2254 NTAPI 2255 MiLocateSubsection( 2256 IN PMMVAD Vad, 2257 IN ULONG_PTR Vpn 2258 ); 2259 2260 VOID 2261 NTAPI 2262 MiDeleteARM3Section( 2263 PVOID ObjectBody 2264 ); 2265 2266 NTSTATUS 2267 NTAPI 2268 MiQueryMemorySectionName( 2269 IN HANDLE ProcessHandle, 2270 IN PVOID BaseAddress, 2271 OUT PVOID MemoryInformation, 2272 IN SIZE_T MemoryInformationLength, 2273 OUT PSIZE_T ReturnLength 2274 ); 2275 2276 NTSTATUS 2277 NTAPI 2278 MiRosUnmapViewInSystemSpace( 2279 IN PVOID MappedBase 2280 ); 2281 2282 POOL_TYPE 2283 NTAPI 2284 MmDeterminePoolType( 2285 IN PVOID PoolAddress 2286 ); 2287 2288 VOID 2289 NTAPI 2290 MiMakePdeExistAndMakeValid( 2291 IN PMMPDE PointerPde, 2292 IN PEPROCESS TargetProcess, 2293 IN KIRQL OldIrql 2294 ); 2295 2296 VOID 2297 NTAPI 2298 MiWriteProtectSystemImage( 2299 _In_ PVOID ImageBase); 2300 2301 // 2302 // MiRemoveZeroPage will use inline code to zero out the page manually if only 2303 // free pages are available. In some scenarios, we don't/can't run that piece of 2304 // code and would rather only have a real zero page. If we can't have a zero page, 2305 // then we'd like to have our own code to grab a free page and zero it out, by 2306 // using MiRemoveAnyPage. This macro implements this. 2307 // 2308 FORCEINLINE 2309 PFN_NUMBER 2310 MiRemoveZeroPageSafe(IN ULONG Color) 2311 { 2312 if (MmFreePagesByColor[ZeroedPageList][Color].Flink != LIST_HEAD) return MiRemoveZeroPage(Color); 2313 return 0; 2314 } 2315 2316 #if (_MI_PAGING_LEVELS == 2) 2317 FORCEINLINE 2318 BOOLEAN 2319 MiSynchronizeSystemPde(PMMPDE PointerPde) 2320 { 2321 MMPDE SystemPde; 2322 ULONG Index; 2323 2324 /* Get the Index from the PDE */ 2325 Index = ((ULONG_PTR)PointerPde & (SYSTEM_PD_SIZE - 1)) / sizeof(MMPTE); 2326 2327 /* Copy the PDE from the double-mapped system page directory */ 2328 SystemPde = MmSystemPagePtes[Index]; 2329 *PointerPde = SystemPde; 2330 2331 /* Make sure we re-read the PDE and PTE */ 2332 KeMemoryBarrierWithoutFence(); 2333 2334 /* Return, if we had success */ 2335 return SystemPde.u.Hard.Valid != 0; 2336 } 2337 #endif 2338 2339 /* EOF */ 2340