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