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 /* Size of a page table */ 22 #define PT_SIZE (PTE_PER_PAGE * sizeof(MMPTE)) 23 24 /* Size of a page directory */ 25 #define PD_SIZE (PDE_PER_PAGE * sizeof(MMPDE)) 26 27 /* Size of all page directories for a process */ 28 #define SYSTEM_PD_SIZE (PPE_PER_PAGE * PD_SIZE) 29 #ifdef _M_IX86 30 C_ASSERT(SYSTEM_PD_SIZE == PAGE_SIZE); 31 #endif 32 33 // 34 // Protection Bits part of the internal memory manager Protection Mask, from: 35 // http://reactos.org/wiki/Techwiki:Memory_management_in_the_Windows_XP_kernel 36 // https://www.reactos.org/wiki/Techwiki:Memory_Protection_constants 37 // and public assertions. 38 // 39 #define MM_ZERO_ACCESS 0 40 #define MM_READONLY 1 41 #define MM_EXECUTE 2 42 #define MM_EXECUTE_READ 3 43 #define MM_READWRITE 4 44 #define MM_WRITECOPY 5 45 #define MM_EXECUTE_READWRITE 6 46 #define MM_EXECUTE_WRITECOPY 7 47 #define MM_PROTECT_ACCESS 7 48 49 // 50 // These are flags on top of the actual protection mask 51 // 52 #define MM_NOCACHE 0x08 53 #define MM_GUARDPAGE 0x10 54 #define MM_WRITECOMBINE 0x18 55 #define MM_PROTECT_SPECIAL 0x18 56 57 // 58 // These are special cases 59 // 60 #define MM_DECOMMIT (MM_ZERO_ACCESS | MM_GUARDPAGE) 61 #define MM_NOACCESS (MM_ZERO_ACCESS | MM_WRITECOMBINE) 62 #define MM_OUTSWAPPED_KSTACK (MM_EXECUTE_WRITECOPY | MM_WRITECOMBINE) 63 #define MM_INVALID_PROTECTION 0xFFFFFFFF 64 65 // 66 // Specific PTE Definitions that map to the Memory Manager's Protection Mask Bits 67 // The Memory Manager's definition define the attributes that must be preserved 68 // and these PTE definitions describe the attributes in the hardware sense. This 69 // helps deal with hardware differences between the actual boolean expression of 70 // the argument. 71 // 72 // For example, in the logical attributes, we want to express read-only as a flag 73 // but on x86, it is writability that must be set. On the other hand, on x86, just 74 // like in the kernel, it is disabling the caches that requires a special flag, 75 // while on certain architectures such as ARM, it is enabling the cache which 76 // requires a flag. 77 // 78 #if defined(_M_IX86) 79 // 80 // Access Flags 81 // 82 #define PTE_READONLY 0 // Doesn't exist on x86 83 #define PTE_EXECUTE 0 // Not worrying about NX yet 84 #define PTE_EXECUTE_READ 0 // Not worrying about NX yet 85 #define PTE_READWRITE 0x2 86 #define PTE_WRITECOPY 0x200 87 #define PTE_EXECUTE_READWRITE 0x2 // Not worrying about NX yet 88 #define PTE_EXECUTE_WRITECOPY 0x200 89 #define PTE_PROTOTYPE 0x400 90 91 // 92 // State Flags 93 // 94 #define PTE_VALID 0x1 95 #define PTE_ACCESSED 0x20 96 #define PTE_DIRTY 0x40 97 98 // 99 // Cache flags 100 // 101 #define PTE_ENABLE_CACHE 0 102 #define PTE_DISABLE_CACHE 0x10 103 #define PTE_WRITECOMBINED_CACHE 0x10 104 #define PTE_PROTECT_MASK 0x612 105 #elif defined(_M_AMD64) 106 // 107 // Access Flags 108 // 109 #define PTE_READONLY 0x8000000000000000ULL 110 #define PTE_EXECUTE 0x0000000000000000ULL 111 #define PTE_EXECUTE_READ PTE_EXECUTE /* EXECUTE implies READ on x64 */ 112 #define PTE_READWRITE 0x8000000000000002ULL 113 #define PTE_WRITECOPY 0x8000000000000200ULL 114 #define PTE_EXECUTE_READWRITE 0x0000000000000002ULL 115 #define PTE_EXECUTE_WRITECOPY 0x0000000000000200ULL 116 #define PTE_PROTOTYPE 0x0000000000000400ULL 117 118 // 119 // State Flags 120 // 121 #define PTE_VALID 0x0000000000000001ULL 122 #define PTE_ACCESSED 0x0000000000000020ULL 123 #define PTE_DIRTY 0x0000000000000040ULL 124 125 // 126 // Cache flags 127 // 128 #define PTE_ENABLE_CACHE 0x0000000000000000ULL 129 #define PTE_DISABLE_CACHE 0x0000000000000010ULL 130 #define PTE_WRITECOMBINED_CACHE 0x0000000000000010ULL 131 #define PTE_PROTECT_MASK 0x8000000000000612ULL 132 #elif defined(_M_ARM) 133 #define PTE_READONLY 0x200 134 #define PTE_EXECUTE 0 // Not worrying about NX yet 135 #define PTE_EXECUTE_READ 0 // Not worrying about NX yet 136 #define PTE_READWRITE 0 // Doesn't exist on ARM 137 #define PTE_WRITECOPY 0 // Doesn't exist on ARM 138 #define PTE_EXECUTE_READWRITE 0 // Not worrying about NX yet 139 #define PTE_EXECUTE_WRITECOPY 0 // Not worrying about NX yet 140 #define PTE_PROTOTYPE 0x400 // Using the Shared bit 141 142 // 143 // Cache flags 144 // 145 #define PTE_ENABLE_CACHE 0 146 #define PTE_DISABLE_CACHE 0x10 147 #define PTE_WRITECOMBINED_CACHE 0x10 148 #define PTE_PROTECT_MASK 0x610 149 #else 150 #error Define these please! 151 #endif 152 153 // 154 // Mask for image section page protection 155 // 156 #define IMAGE_SCN_PROTECTION_MASK (IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE) 157 158 extern const ULONG_PTR MmProtectToPteMask[32]; 159 extern const ULONG MmProtectToValue[32]; 160 161 // 162 // Assertions for session images, addresses, and PTEs 163 // 164 #define MI_IS_SESSION_IMAGE_ADDRESS(Address) \ 165 (((Address) >= MiSessionImageStart) && ((Address) < MiSessionImageEnd)) 166 167 #define MI_IS_SESSION_ADDRESS(Address) \ 168 (((Address) >= MmSessionBase) && ((Address) < MiSessionSpaceEnd)) 169 170 #define MI_IS_SESSION_PTE(Pte) \ 171 ((((PMMPTE)Pte) >= MiSessionBasePte) && (((PMMPTE)Pte) < MiSessionLastPte)) 172 173 #define MI_IS_PAGE_TABLE_ADDRESS(Address) \ 174 (((PVOID)(Address) >= (PVOID)PTE_BASE) && ((PVOID)(Address) <= (PVOID)PTE_TOP)) 175 176 #define MI_IS_SYSTEM_PAGE_TABLE_ADDRESS(Address) \ 177 (((Address) >= (PVOID)MiAddressToPte(MmSystemRangeStart)) && ((Address) <= (PVOID)PTE_TOP)) 178 179 #define MI_IS_PAGE_TABLE_OR_HYPER_ADDRESS(Address) \ 180 (((PVOID)(Address) >= (PVOID)PTE_BASE) && ((PVOID)(Address) <= (PVOID)MmHyperSpaceEnd)) 181 182 // 183 // Creates a software PTE with the given protection 184 // 185 #define MI_MAKE_SOFTWARE_PTE(p, x) ((p)->u.Long = (x << MM_PTE_SOFTWARE_PROTECTION_BITS)) 186 187 // 188 // Marks a PTE as deleted 189 // 190 #define MI_SET_PFN_DELETED(x) ((x)->PteAddress = (PMMPTE)((ULONG_PTR)(x)->PteAddress | 1)) 191 #define MI_IS_PFN_DELETED(x) ((ULONG_PTR)((x)->PteAddress) & 1) 192 193 // 194 // Special values for LoadedImports 195 // 196 #ifdef _WIN64 197 #define MM_SYSLDR_NO_IMPORTS (PVOID)0xFFFFFFFFFFFFFFFEULL 198 #define MM_SYSLDR_BOOT_LOADED (PVOID)0xFFFFFFFFFFFFFFFFULL 199 #else 200 #define MM_SYSLDR_NO_IMPORTS (PVOID)0xFFFFFFFE 201 #define MM_SYSLDR_BOOT_LOADED (PVOID)0xFFFFFFFF 202 #endif 203 #define MM_SYSLDR_SINGLE_ENTRY 0x1 204 205 // 206 // Number of initial session IDs 207 // 208 #define MI_INITIAL_SESSION_IDS 64 209 210 #if defined(_M_IX86) || defined(_M_ARM) 211 // 212 // PFN List Sentinel 213 // 214 #define LIST_HEAD 0xFFFFFFFF 215 216 // 217 // Because GCC cannot automatically downcast 0xFFFFFFFF to lesser-width bits, 218 // we need a manual definition suited to the number of bits in the PteFrame. 219 // This is used as a LIST_HEAD for the colored list 220 // 221 #define COLORED_LIST_HEAD ((1 << 25) - 1) // 0x1FFFFFF 222 #elif defined(_M_AMD64) 223 #define LIST_HEAD 0xFFFFFFFFFFFFFFFFLL 224 #define COLORED_LIST_HEAD ((1ULL << 57) - 1) // 0x1FFFFFFFFFFFFFFLL 225 #else 226 #error Define these please! 227 #endif 228 229 // 230 // Special IRQL value (found in assertions) 231 // 232 #define MM_NOIRQL (KIRQL)0xFFFFFFFF 233 234 // 235 // Returns the color of a page 236 // 237 #define MI_GET_PAGE_COLOR(x) ((x) & MmSecondaryColorMask) 238 #define MI_GET_NEXT_COLOR() (MI_GET_PAGE_COLOR(++MmSystemPageColor)) 239 #define MI_GET_NEXT_PROCESS_COLOR(x) (MI_GET_PAGE_COLOR(++(x)->NextPageColor)) 240 241 // 242 // Prototype PTEs that don't yet have a pagefile association 243 // 244 #ifdef _WIN64 245 #define MI_PTE_LOOKUP_NEEDED 0xffffffffULL 246 #else 247 #define MI_PTE_LOOKUP_NEEDED 0xFFFFF 248 #endif 249 250 // 251 // Number of session data and tag pages 252 // 253 #define MI_SESSION_DATA_PAGES_MAXIMUM (MM_ALLOCATION_GRANULARITY / PAGE_SIZE) 254 #define MI_SESSION_TAG_PAGES_MAXIMUM (MM_ALLOCATION_GRANULARITY / PAGE_SIZE) 255 256 // 257 // Used by MiCheckSecuredVad 258 // 259 #define MM_READ_WRITE_ALLOWED 11 260 #define MM_READ_ONLY_ALLOWED 10 261 #define MM_NO_ACCESS_ALLOWED 01 262 #define MM_DELETE_CHECK 85 263 264 // 265 // System views are binned into 64K chunks 266 // 267 #define MI_SYSTEM_VIEW_BUCKET_SIZE _64K 268 269 // 270 // FIXFIX: These should go in ex.h after the pool merge 271 // 272 #ifdef _WIN64 273 #define POOL_BLOCK_SIZE 16 274 #else 275 #define POOL_BLOCK_SIZE 8 276 #endif 277 #define POOL_LISTS_PER_PAGE (PAGE_SIZE / POOL_BLOCK_SIZE) 278 #define BASE_POOL_TYPE_MASK 1 279 #define POOL_MAX_ALLOC (PAGE_SIZE - (sizeof(POOL_HEADER) + POOL_BLOCK_SIZE)) 280 281 // 282 // Pool debugging/analysis/tracing flags 283 // 284 #define POOL_FLAG_CHECK_TIMERS 0x1 285 #define POOL_FLAG_CHECK_WORKERS 0x2 286 #define POOL_FLAG_CHECK_RESOURCES 0x4 287 #define POOL_FLAG_VERIFIER 0x8 288 #define POOL_FLAG_CHECK_DEADLOCK 0x10 289 #define POOL_FLAG_SPECIAL_POOL 0x20 290 #define POOL_FLAG_DBGPRINT_ON_FAILURE 0x40 291 #define POOL_FLAG_CRASH_ON_FAILURE 0x80 292 293 // 294 // BAD_POOL_HEADER codes during pool bugcheck 295 // 296 #define POOL_CORRUPTED_LIST 3 297 #define POOL_SIZE_OR_INDEX_MISMATCH 5 298 #define POOL_ENTRIES_NOT_ALIGNED_PREVIOUS 6 299 #define POOL_HEADER_NOT_ALIGNED 7 300 #define POOL_HEADER_IS_ZERO 8 301 #define POOL_ENTRIES_NOT_ALIGNED_NEXT 9 302 #define POOL_ENTRY_NOT_FOUND 10 303 304 // 305 // BAD_POOL_CALLER codes during pool bugcheck 306 // 307 #define POOL_ENTRY_CORRUPTED 1 308 #define POOL_ENTRY_ALREADY_FREE 6 309 #define POOL_ENTRY_NOT_ALLOCATED 7 310 #define POOL_ALLOC_IRQL_INVALID 8 311 #define POOL_FREE_IRQL_INVALID 9 312 #define POOL_BILLED_PROCESS_INVALID 13 313 #define POOL_HEADER_SIZE_INVALID 32 314 315 typedef struct _POOL_DESCRIPTOR 316 { 317 POOL_TYPE PoolType; 318 ULONG PoolIndex; 319 ULONG RunningAllocs; 320 ULONG RunningDeAllocs; 321 ULONG TotalPages; 322 ULONG TotalBigPages; 323 ULONG Threshold; 324 PVOID LockAddress; 325 PVOID PendingFrees; 326 LONG PendingFreeDepth; 327 SIZE_T TotalBytes; 328 SIZE_T Spare0; 329 LIST_ENTRY ListHeads[POOL_LISTS_PER_PAGE]; 330 } POOL_DESCRIPTOR, *PPOOL_DESCRIPTOR; 331 332 typedef struct _POOL_HEADER 333 { 334 union 335 { 336 struct 337 { 338 #ifdef _WIN64 339 USHORT PreviousSize:8; 340 USHORT PoolIndex:8; 341 USHORT BlockSize:8; 342 USHORT PoolType:8; 343 #else 344 USHORT PreviousSize:9; 345 USHORT PoolIndex:7; 346 USHORT BlockSize:9; 347 USHORT PoolType:7; 348 #endif 349 }; 350 ULONG Ulong1; 351 }; 352 #ifdef _WIN64 353 ULONG PoolTag; 354 #endif 355 union 356 { 357 #ifdef _WIN64 358 PEPROCESS ProcessBilled; 359 #else 360 ULONG PoolTag; 361 #endif 362 struct 363 { 364 USHORT AllocatorBackTraceIndex; 365 USHORT PoolTagHash; 366 }; 367 }; 368 } POOL_HEADER, *PPOOL_HEADER; 369 370 C_ASSERT(sizeof(POOL_HEADER) == POOL_BLOCK_SIZE); 371 C_ASSERT(POOL_BLOCK_SIZE == sizeof(LIST_ENTRY)); 372 373 typedef struct _POOL_TRACKER_TABLE 374 { 375 ULONG Key; 376 LONG NonPagedAllocs; 377 LONG NonPagedFrees; 378 SIZE_T NonPagedBytes; 379 LONG PagedAllocs; 380 LONG PagedFrees; 381 SIZE_T PagedBytes; 382 } POOL_TRACKER_TABLE, *PPOOL_TRACKER_TABLE; 383 384 typedef struct _POOL_TRACKER_BIG_PAGES 385 { 386 PVOID Va; 387 ULONG Key; 388 ULONG NumberOfPages; 389 PVOID QuotaObject; 390 } POOL_TRACKER_BIG_PAGES, *PPOOL_TRACKER_BIG_PAGES; 391 392 extern ULONG ExpNumberOfPagedPools; 393 extern POOL_DESCRIPTOR NonPagedPoolDescriptor; 394 extern PPOOL_DESCRIPTOR ExpPagedPoolDescriptor[16 + 1]; 395 extern PPOOL_TRACKER_TABLE PoolTrackTable; 396 397 // 398 // END FIXFIX 399 // 400 401 typedef struct _MI_LARGE_PAGE_DRIVER_ENTRY 402 { 403 LIST_ENTRY Links; 404 UNICODE_STRING BaseName; 405 } MI_LARGE_PAGE_DRIVER_ENTRY, *PMI_LARGE_PAGE_DRIVER_ENTRY; 406 407 typedef enum _MMSYSTEM_PTE_POOL_TYPE 408 { 409 SystemPteSpace, 410 NonPagedPoolExpansion, 411 MaximumPtePoolTypes 412 } MMSYSTEM_PTE_POOL_TYPE; 413 414 typedef enum _MI_PFN_CACHE_ATTRIBUTE 415 { 416 MiNonCached, 417 MiCached, 418 MiWriteCombined, 419 MiNotMapped 420 } MI_PFN_CACHE_ATTRIBUTE, *PMI_PFN_CACHE_ATTRIBUTE; 421 422 typedef struct _PHYSICAL_MEMORY_RUN 423 { 424 PFN_NUMBER BasePage; 425 PFN_NUMBER PageCount; 426 } PHYSICAL_MEMORY_RUN, *PPHYSICAL_MEMORY_RUN; 427 428 typedef struct _PHYSICAL_MEMORY_DESCRIPTOR 429 { 430 ULONG NumberOfRuns; 431 PFN_NUMBER NumberOfPages; 432 PHYSICAL_MEMORY_RUN Run[1]; 433 } PHYSICAL_MEMORY_DESCRIPTOR, *PPHYSICAL_MEMORY_DESCRIPTOR; 434 435 typedef struct _MMCOLOR_TABLES 436 { 437 PFN_NUMBER Flink; 438 PVOID Blink; 439 PFN_NUMBER Count; 440 } MMCOLOR_TABLES, *PMMCOLOR_TABLES; 441 442 typedef struct _MI_LARGE_PAGE_RANGES 443 { 444 PFN_NUMBER StartFrame; 445 PFN_NUMBER LastFrame; 446 } MI_LARGE_PAGE_RANGES, *PMI_LARGE_PAGE_RANGES; 447 448 typedef struct _MMVIEW 449 { 450 ULONG_PTR Entry; 451 PCONTROL_AREA ControlArea; 452 } MMVIEW, *PMMVIEW; 453 454 typedef struct _MMSESSION 455 { 456 KGUARDED_MUTEX SystemSpaceViewLock; 457 PKGUARDED_MUTEX SystemSpaceViewLockPointer; 458 PCHAR SystemSpaceViewStart; 459 PMMVIEW SystemSpaceViewTable; 460 ULONG SystemSpaceHashSize; 461 ULONG SystemSpaceHashEntries; 462 ULONG SystemSpaceHashKey; 463 ULONG BitmapFailures; 464 PRTL_BITMAP SystemSpaceBitMap; 465 } MMSESSION, *PMMSESSION; 466 467 typedef struct _MM_SESSION_SPACE_FLAGS 468 { 469 ULONG Initialized:1; 470 ULONG DeletePending:1; 471 ULONG Filler:30; 472 } MM_SESSION_SPACE_FLAGS; 473 474 typedef struct _MM_SESSION_SPACE 475 { 476 struct _MM_SESSION_SPACE *GlobalVirtualAddress; 477 LONG ReferenceCount; 478 union 479 { 480 ULONG LongFlags; 481 MM_SESSION_SPACE_FLAGS Flags; 482 } u; 483 ULONG SessionId; 484 LIST_ENTRY ProcessList; 485 LARGE_INTEGER LastProcessSwappedOutTime; 486 PFN_NUMBER SessionPageDirectoryIndex; 487 SIZE_T NonPageablePages; 488 SIZE_T CommittedPages; 489 PVOID PagedPoolStart; 490 PVOID PagedPoolEnd; 491 PMMPDE PagedPoolBasePde; 492 ULONG Color; 493 LONG ResidentProcessCount; 494 ULONG SessionPoolAllocationFailures[4]; 495 LIST_ENTRY ImageList; 496 LCID LocaleId; 497 ULONG AttachCount; 498 KEVENT AttachEvent; 499 PEPROCESS LastProcess; 500 LONG ProcessReferenceToSession; 501 LIST_ENTRY WsListEntry; 502 GENERAL_LOOKASIDE Lookaside[SESSION_POOL_LOOKASIDES]; 503 MMSESSION Session; 504 KGUARDED_MUTEX PagedPoolMutex; 505 MM_PAGED_POOL_INFO PagedPoolInfo; 506 MMSUPPORT Vm; 507 PMMWSLE Wsle; 508 PDRIVER_UNLOAD Win32KDriverUnload; 509 POOL_DESCRIPTOR PagedPool; 510 #if defined (_M_AMD64) 511 MMPDE PageDirectory; 512 #else 513 PMMPDE PageTables; 514 #endif 515 #if defined (_M_AMD64) 516 PMMPTE SpecialPoolFirstPte; 517 PMMPTE SpecialPoolLastPte; 518 PMMPTE NextPdeForSpecialPoolExpansion; 519 PMMPTE LastPdeForSpecialPoolExpansion; 520 PFN_NUMBER SpecialPagesInUse; 521 #endif 522 LONG ImageLoadingCount; 523 } MM_SESSION_SPACE, *PMM_SESSION_SPACE; 524 525 extern PMM_SESSION_SPACE MmSessionSpace; 526 extern MMPTE HyperTemplatePte; 527 extern MMPDE ValidKernelPde; 528 extern MMPTE ValidKernelPte; 529 extern MMPDE ValidKernelPdeLocal; 530 extern MMPTE ValidKernelPteLocal; 531 extern MMPDE DemandZeroPde; 532 extern MMPTE DemandZeroPte; 533 extern MMPTE PrototypePte; 534 extern MMPTE MmDecommittedPte; 535 extern BOOLEAN MmLargeSystemCache; 536 extern BOOLEAN MmZeroPageFile; 537 extern BOOLEAN MmProtectFreedNonPagedPool; 538 extern BOOLEAN MmTrackLockedPages; 539 extern BOOLEAN MmTrackPtes; 540 extern BOOLEAN MmDynamicPfn; 541 extern BOOLEAN MmMirroring; 542 extern BOOLEAN MmMakeLowMemory; 543 extern BOOLEAN MmEnforceWriteProtection; 544 extern SIZE_T MmAllocationFragment; 545 extern ULONG MmConsumedPoolPercentage; 546 extern ULONG MmVerifyDriverBufferType; 547 extern ULONG MmVerifyDriverLevel; 548 extern WCHAR MmVerifyDriverBuffer[512]; 549 extern WCHAR MmLargePageDriverBuffer[512]; 550 extern LIST_ENTRY MiLargePageDriverList; 551 extern BOOLEAN MiLargePageAllDrivers; 552 extern ULONG MmVerifyDriverBufferLength; 553 extern ULONG MmLargePageDriverBufferLength; 554 extern SIZE_T MmSizeOfNonPagedPoolInBytes; 555 extern SIZE_T MmMaximumNonPagedPoolInBytes; 556 extern PFN_NUMBER MmMaximumNonPagedPoolInPages; 557 extern PFN_NUMBER MmSizeOfPagedPoolInPages; 558 extern PVOID MmNonPagedSystemStart; 559 extern PVOID MmNonPagedPoolStart; 560 extern PVOID MmNonPagedPoolExpansionStart; 561 extern PVOID MmNonPagedPoolEnd; 562 extern SIZE_T MmSizeOfPagedPoolInBytes; 563 extern PVOID MmPagedPoolStart; 564 extern PVOID MmPagedPoolEnd; 565 extern PVOID MmSessionBase; 566 extern SIZE_T MmSessionSize; 567 extern PMMPTE MmFirstReservedMappingPte, MmLastReservedMappingPte; 568 extern PMMPTE MiFirstReservedZeroingPte; 569 extern MI_PFN_CACHE_ATTRIBUTE MiPlatformCacheAttributes[2][MmMaximumCacheType]; 570 extern PPHYSICAL_MEMORY_DESCRIPTOR MmPhysicalMemoryBlock; 571 extern SIZE_T MmBootImageSize; 572 extern PMMPTE MmSystemPtesStart[MaximumPtePoolTypes]; 573 extern PMMPTE MmSystemPtesEnd[MaximumPtePoolTypes]; 574 extern PMEMORY_ALLOCATION_DESCRIPTOR MxFreeDescriptor; 575 extern MEMORY_ALLOCATION_DESCRIPTOR MxOldFreeDescriptor; 576 extern ULONG_PTR MxPfnAllocation; 577 extern MM_PAGED_POOL_INFO MmPagedPoolInfo; 578 extern RTL_BITMAP MiPfnBitMap; 579 extern KGUARDED_MUTEX MmPagedPoolMutex; 580 extern KGUARDED_MUTEX MmSectionCommitMutex; 581 extern PVOID MmPagedPoolStart; 582 extern PVOID MmPagedPoolEnd; 583 extern PVOID MmNonPagedSystemStart; 584 extern PVOID MiSystemViewStart; 585 extern SIZE_T MmSystemViewSize; 586 extern PVOID MmSessionBase; 587 extern PVOID MiSessionSpaceEnd; 588 extern PMMPTE MiSessionImagePteStart; 589 extern PMMPTE MiSessionImagePteEnd; 590 extern PMMPTE MiSessionBasePte; 591 extern PMMPTE MiSessionLastPte; 592 extern SIZE_T MmSizeOfPagedPoolInBytes; 593 extern PMMPDE MmSystemPagePtes; 594 extern PVOID MmSystemCacheStart; 595 extern PVOID MmSystemCacheEnd; 596 extern MMSUPPORT MmSystemCacheWs; 597 extern SIZE_T MmAllocatedNonPagedPool; 598 extern ULONG MmSpecialPoolTag; 599 extern PVOID MmHyperSpaceEnd; 600 extern PMMWSL MmSystemCacheWorkingSetList; 601 extern SIZE_T MmMinimumNonPagedPoolSize; 602 extern ULONG MmMinAdditionNonPagedPoolPerMb; 603 extern SIZE_T MmDefaultMaximumNonPagedPool; 604 extern ULONG MmMaxAdditionNonPagedPoolPerMb; 605 extern ULONG MmSecondaryColors; 606 extern ULONG MmSecondaryColorMask; 607 extern ULONG MmNumberOfSystemPtes; 608 extern ULONG MmMaximumNonPagedPoolPercent; 609 extern ULONG MmLargeStackSize; 610 extern PMMCOLOR_TABLES MmFreePagesByColor[FreePageList + 1]; 611 extern MMPFNLIST MmStandbyPageListByPriority[8]; 612 extern ULONG MmProductType; 613 extern MM_SYSTEMSIZE MmSystemSize; 614 extern PKEVENT MiLowMemoryEvent; 615 extern PKEVENT MiHighMemoryEvent; 616 extern PKEVENT MiLowPagedPoolEvent; 617 extern PKEVENT MiHighPagedPoolEvent; 618 extern PKEVENT MiLowNonPagedPoolEvent; 619 extern PKEVENT MiHighNonPagedPoolEvent; 620 extern PFN_NUMBER MmLowMemoryThreshold; 621 extern PFN_NUMBER MmHighMemoryThreshold; 622 extern PFN_NUMBER MiLowPagedPoolThreshold; 623 extern PFN_NUMBER MiHighPagedPoolThreshold; 624 extern PFN_NUMBER MiLowNonPagedPoolThreshold; 625 extern PFN_NUMBER MiHighNonPagedPoolThreshold; 626 extern PFN_NUMBER MmMinimumFreePages; 627 extern PFN_NUMBER MmPlentyFreePages; 628 extern SIZE_T MmMinimumStackCommitInBytes; 629 extern PFN_COUNT MiExpansionPoolPagesInitialCharge; 630 extern PFN_NUMBER MmResidentAvailablePages; 631 extern PFN_NUMBER MmResidentAvailableAtInit; 632 extern ULONG MmTotalFreeSystemPtes[MaximumPtePoolTypes]; 633 extern PFN_NUMBER MmTotalSystemDriverPages; 634 extern ULONG MmCritsectTimeoutSeconds; 635 extern PVOID MiSessionImageStart; 636 extern PVOID MiSessionImageEnd; 637 extern PMMPTE MiHighestUserPte; 638 extern PMMPDE MiHighestUserPde; 639 extern PFN_NUMBER MmSystemPageDirectory[PPE_PER_PAGE]; 640 extern PMMPTE MmSharedUserDataPte; 641 extern LIST_ENTRY MmProcessList; 642 extern KEVENT MmZeroingPageEvent; 643 extern ULONG MmSystemPageColor; 644 extern ULONG MmProcessColorSeed; 645 extern PMMWSL MmWorkingSetList; 646 extern PFN_NUMBER MiNumberOfFreePages; 647 extern SIZE_T MmSessionViewSize; 648 extern SIZE_T MmSessionPoolSize; 649 extern SIZE_T MmSessionImageSize; 650 extern PVOID MiSystemViewStart; 651 extern PVOID MiSessionPoolEnd; // 0xBE000000 652 extern PVOID MiSessionPoolStart; // 0xBD000000 653 extern PVOID MiSessionViewStart; // 0xBE000000 654 extern PVOID MiSessionSpaceWs; 655 extern ULONG MmMaximumDeadKernelStacks; 656 extern SLIST_HEADER MmDeadStackSListHead; 657 extern MM_AVL_TABLE MmSectionBasedRoot; 658 extern KGUARDED_MUTEX MmSectionBasedMutex; 659 extern PVOID MmHighSectionBase; 660 extern SIZE_T MmSystemLockPagesCount; 661 extern ULONG_PTR MmSubsectionBase; 662 extern LARGE_INTEGER MmCriticalSectionTimeout; 663 extern LIST_ENTRY MmWorkingSetExpansionHead; 664 extern KSPIN_LOCK MmExpansionLock; 665 extern PETHREAD MiExpansionLockOwner; 666 667 FORCEINLINE 668 BOOLEAN 669 MiIsMemoryTypeFree(TYPE_OF_MEMORY MemoryType) 670 { 671 return ((MemoryType == LoaderFree) || 672 (MemoryType == LoaderLoadedProgram) || 673 (MemoryType == LoaderFirmwareTemporary) || 674 (MemoryType == LoaderOsloaderStack)); 675 } 676 677 FORCEINLINE 678 BOOLEAN 679 MiIsMemoryTypeInvisible(TYPE_OF_MEMORY MemoryType) 680 { 681 return ((MemoryType == LoaderFirmwarePermanent) || 682 (MemoryType == LoaderSpecialMemory) || 683 (MemoryType == LoaderHALCachedMemory) || 684 (MemoryType == LoaderBBTMemory)); 685 } 686 687 #ifdef _M_AMD64 688 FORCEINLINE 689 BOOLEAN 690 MiIsUserPxe(PVOID Address) 691 { 692 return ((ULONG_PTR)Address >> 7) == 0x1FFFFEDF6FB7DA0ULL; 693 } 694 695 FORCEINLINE 696 BOOLEAN 697 MiIsUserPpe(PVOID Address) 698 { 699 return ((ULONG_PTR)Address >> 16) == 0xFFFFF6FB7DA0ULL; 700 } 701 702 FORCEINLINE 703 BOOLEAN 704 MiIsUserPde(PVOID Address) 705 { 706 return ((ULONG_PTR)Address >> 25) == 0x7FFFFB7DA0ULL; 707 } 708 709 FORCEINLINE 710 BOOLEAN 711 MiIsUserPte(PVOID Address) 712 { 713 return ((ULONG_PTR)Address >> 34) == 0x3FFFFDA0ULL; 714 } 715 #else 716 FORCEINLINE 717 BOOLEAN 718 MiIsUserPde(PVOID Address) 719 { 720 return ((Address >= (PVOID)MiAddressToPde(NULL)) && 721 (Address <= (PVOID)MiHighestUserPde)); 722 } 723 724 FORCEINLINE 725 BOOLEAN 726 MiIsUserPte(PVOID Address) 727 { 728 return (Address <= (PVOID)MiHighestUserPte); 729 } 730 #endif 731 732 // 733 // Figures out the hardware bits for a PTE 734 // 735 FORCEINLINE 736 ULONG_PTR 737 MiDetermineUserGlobalPteMask(IN PVOID PointerPte) 738 { 739 MMPTE TempPte; 740 741 /* Start fresh */ 742 TempPte.u.Long = 0; 743 744 /* Make it valid and accessed */ 745 TempPte.u.Hard.Valid = TRUE; 746 MI_MAKE_ACCESSED_PAGE(&TempPte); 747 748 /* Is this for user-mode? */ 749 if ( 750 #if (_MI_PAGING_LEVELS == 4) 751 MiIsUserPxe(PointerPte) || 752 #endif 753 #if (_MI_PAGING_LEVELS >= 3) 754 MiIsUserPpe(PointerPte) || 755 #endif 756 MiIsUserPde(PointerPte) || 757 MiIsUserPte(PointerPte)) 758 { 759 /* Set the owner bit */ 760 MI_MAKE_OWNER_PAGE(&TempPte); 761 } 762 763 /* FIXME: We should also set the global bit */ 764 765 /* Return the protection */ 766 return TempPte.u.Long; 767 } 768 769 // 770 // Creates a valid kernel PTE with the given protection 771 // 772 FORCEINLINE 773 VOID 774 MI_MAKE_HARDWARE_PTE_KERNEL(IN PMMPTE NewPte, 775 IN PMMPTE MappingPte, 776 IN ULONG_PTR ProtectionMask, 777 IN PFN_NUMBER PageFrameNumber) 778 { 779 /* Only valid for kernel, non-session PTEs */ 780 ASSERT(MappingPte > MiHighestUserPte); 781 ASSERT(!MI_IS_SESSION_PTE(MappingPte)); 782 ASSERT((MappingPte < (PMMPTE)PDE_BASE) || (MappingPte > (PMMPTE)PDE_TOP)); 783 784 /* Start fresh */ 785 *NewPte = ValidKernelPte; 786 787 /* Set the protection and page */ 788 NewPte->u.Hard.PageFrameNumber = PageFrameNumber; 789 NewPte->u.Long |= MmProtectToPteMask[ProtectionMask]; 790 } 791 792 // 793 // Creates a valid PTE with the given protection 794 // 795 FORCEINLINE 796 VOID 797 MI_MAKE_HARDWARE_PTE(IN PMMPTE NewPte, 798 IN PMMPTE MappingPte, 799 IN ULONG_PTR ProtectionMask, 800 IN PFN_NUMBER PageFrameNumber) 801 { 802 /* Set the protection and page */ 803 NewPte->u.Long = MiDetermineUserGlobalPteMask(MappingPte); 804 NewPte->u.Long |= MmProtectToPteMask[ProtectionMask]; 805 NewPte->u.Hard.PageFrameNumber = PageFrameNumber; 806 } 807 808 // 809 // Creates a valid user PTE with the given protection 810 // 811 FORCEINLINE 812 VOID 813 MI_MAKE_HARDWARE_PTE_USER(IN PMMPTE NewPte, 814 IN PMMPTE MappingPte, 815 IN ULONG_PTR ProtectionMask, 816 IN PFN_NUMBER PageFrameNumber) 817 { 818 /* Only valid for kernel, non-session PTEs */ 819 ASSERT(MappingPte <= MiHighestUserPte); 820 821 /* Start fresh */ 822 NewPte->u.Long = 0; 823 824 /* Set the protection and page */ 825 NewPte->u.Hard.Valid = TRUE; 826 NewPte->u.Hard.Owner = TRUE; 827 NewPte->u.Hard.PageFrameNumber = PageFrameNumber; 828 NewPte->u.Long |= MmProtectToPteMask[ProtectionMask]; 829 } 830 831 #ifndef _M_AMD64 832 // 833 // Builds a Prototype PTE for the address of the PTE 834 // 835 FORCEINLINE 836 VOID 837 MI_MAKE_PROTOTYPE_PTE(IN PMMPTE NewPte, 838 IN PMMPTE PointerPte) 839 { 840 ULONG_PTR Offset; 841 842 /* Mark this as a prototype */ 843 NewPte->u.Long = 0; 844 NewPte->u.Proto.Prototype = 1; 845 846 /* 847 * Prototype PTEs are only valid in paged pool by design, this little trick 848 * lets us only use 30 bits for the adress of the PTE, as long as the area 849 * stays 1024MB At most. 850 */ 851 Offset = (ULONG_PTR)PointerPte - (ULONG_PTR)MmPagedPoolStart; 852 853 /* 854 * 7 bits go in the "low" (but we assume the bottom 2 are zero) 855 * and the other 21 bits go in the "high" 856 */ 857 NewPte->u.Proto.ProtoAddressLow = (Offset & 0x1FC) >> 2; 858 NewPte->u.Proto.ProtoAddressHigh = (Offset & 0x3FFFFE00) >> 9; 859 } 860 861 // 862 // Builds a Subsection PTE for the address of the Segment 863 // 864 FORCEINLINE 865 VOID 866 MI_MAKE_SUBSECTION_PTE(IN PMMPTE NewPte, 867 IN PVOID Segment) 868 { 869 ULONG_PTR Offset; 870 871 /* Mark this as a prototype */ 872 NewPte->u.Long = 0; 873 NewPte->u.Subsect.Prototype = 1; 874 875 /* 876 * Segments are only valid either in nonpaged pool. We store the 20 bit 877 * difference either from the top or bottom of nonpaged pool, giving a 878 * maximum of 128MB to each delta, meaning nonpaged pool cannot exceed 879 * 256MB. 880 */ 881 if ((ULONG_PTR)Segment < ((ULONG_PTR)MmSubsectionBase + (128 * _1MB))) 882 { 883 Offset = (ULONG_PTR)Segment - (ULONG_PTR)MmSubsectionBase; 884 NewPte->u.Subsect.WhichPool = PagedPool; 885 } 886 else 887 { 888 Offset = (ULONG_PTR)MmNonPagedPoolEnd - (ULONG_PTR)Segment; 889 NewPte->u.Subsect.WhichPool = NonPagedPool; 890 } 891 892 /* 893 * 4 bits go in the "low" (but we assume the bottom 3 are zero) 894 * and the other 20 bits go in the "high" 895 */ 896 NewPte->u.Subsect.SubsectionAddressLow = (Offset & 0x78) >> 3; 897 NewPte->u.Subsect.SubsectionAddressHigh = (Offset & 0xFFFFF80) >> 7; 898 } 899 900 FORCEINLINE 901 BOOLEAN 902 MI_IS_MAPPED_PTE(PMMPTE PointerPte) 903 { 904 /// \todo Make this reasonable code, this is UGLY! 905 return ((PointerPte->u.Long & 0xFFFFFC01) != 0); 906 } 907 908 #endif 909 910 FORCEINLINE 911 VOID 912 MI_MAKE_TRANSITION_PTE(_Out_ PMMPTE NewPte, 913 _In_ PFN_NUMBER Page, 914 _In_ ULONG Protection) 915 { 916 NewPte->u.Long = 0; 917 NewPte->u.Trans.Transition = 1; 918 NewPte->u.Trans.Protection = Protection; 919 NewPte->u.Trans.PageFrameNumber = Page; 920 } 921 922 // 923 // Returns if the page is physically resident (ie: a large page) 924 // FIXFIX: CISC/x86 only? 925 // 926 FORCEINLINE 927 BOOLEAN 928 MI_IS_PHYSICAL_ADDRESS(IN PVOID Address) 929 { 930 PMMPDE PointerPde; 931 932 /* Large pages are never paged out, always physically resident */ 933 PointerPde = MiAddressToPde(Address); 934 return ((PointerPde->u.Hard.LargePage) && (PointerPde->u.Hard.Valid)); 935 } 936 937 // 938 // Writes a valid PTE 939 // 940 FORCEINLINE 941 VOID 942 MI_WRITE_VALID_PTE(IN PMMPTE PointerPte, 943 IN MMPTE TempPte) 944 { 945 /* Write the valid PTE */ 946 ASSERT(PointerPte->u.Hard.Valid == 0); 947 ASSERT(TempPte.u.Hard.Valid == 1); 948 #if _M_AMD64 949 ASSERT(!MI_IS_PAGE_TABLE_ADDRESS(MiPteToAddress(PointerPte)) || 950 (TempPte.u.Hard.NoExecute == 0)); 951 #endif 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 #ifdef _M_AMD64 1007 ASSERT(PointerPde->u.Hard.NoExecute == 0); 1008 #endif 1009 ASSERT(TempPde.u.Hard.Valid == 1); 1010 *PointerPde = TempPde; 1011 } 1012 1013 // 1014 // Writes an invalid PDE 1015 // 1016 FORCEINLINE 1017 VOID 1018 MI_WRITE_INVALID_PDE(IN PMMPDE PointerPde, 1019 IN MMPDE InvalidPde) 1020 { 1021 /* Write the invalid PDE */ 1022 ASSERT(InvalidPde.u.Hard.Valid == 0); 1023 ASSERT(InvalidPde.u.Long != 0); 1024 #ifdef _M_AMD64 1025 ASSERT(InvalidPde.u.Soft.Protection == MM_EXECUTE_READWRITE); 1026 #endif 1027 *PointerPde = InvalidPde; 1028 } 1029 1030 // 1031 // Checks if the thread already owns a working set 1032 // 1033 FORCEINLINE 1034 BOOLEAN 1035 MM_ANY_WS_LOCK_HELD(IN PETHREAD Thread) 1036 { 1037 /* If any of these are held, return TRUE */ 1038 return ((Thread->OwnsProcessWorkingSetExclusive) || 1039 (Thread->OwnsProcessWorkingSetShared) || 1040 (Thread->OwnsSystemWorkingSetExclusive) || 1041 (Thread->OwnsSystemWorkingSetShared) || 1042 (Thread->OwnsSessionWorkingSetExclusive) || 1043 (Thread->OwnsSessionWorkingSetShared)); 1044 } 1045 1046 // 1047 // Checks if the process owns the working set lock 1048 // 1049 FORCEINLINE 1050 BOOLEAN 1051 MI_WS_OWNER(IN PEPROCESS Process) 1052 { 1053 /* Check if this process is the owner, and that the thread owns the WS */ 1054 if (PsGetCurrentThread()->OwnsProcessWorkingSetExclusive == 0) 1055 { 1056 DPRINT("Thread: %p is not an owner\n", PsGetCurrentThread()); 1057 } 1058 if (KeGetCurrentThread()->ApcState.Process != &Process->Pcb) 1059 { 1060 DPRINT("Current thread %p is attached to another process %p\n", PsGetCurrentThread(), Process); 1061 } 1062 return ((KeGetCurrentThread()->ApcState.Process == &Process->Pcb) && 1063 ((PsGetCurrentThread()->OwnsProcessWorkingSetExclusive) || 1064 (PsGetCurrentThread()->OwnsProcessWorkingSetShared))); 1065 } 1066 1067 // 1068 // New ARM3<->RosMM PAGE Architecture 1069 // 1070 FORCEINLINE 1071 BOOLEAN 1072 MiIsRosSectionObject(IN PVOID Section) 1073 { 1074 PSECTION RosSection = Section; 1075 return RosSection->u.Flags.filler; 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 BOOLEAN 1706 NTAPI 1707 MmArmInitSystem( 1708 IN ULONG Phase, 1709 IN PLOADER_PARAMETER_BLOCK LoaderBlock 1710 ); 1711 1712 VOID 1713 NTAPI 1714 MiInitializeSessionSpaceLayout(VOID); 1715 1716 NTSTATUS 1717 NTAPI 1718 MiInitMachineDependent( 1719 IN PLOADER_PARAMETER_BLOCK LoaderBlock 1720 ); 1721 1722 VOID 1723 NTAPI 1724 MiComputeColorInformation( 1725 VOID 1726 ); 1727 1728 VOID 1729 NTAPI 1730 MiMapPfnDatabase( 1731 IN PLOADER_PARAMETER_BLOCK LoaderBlock 1732 ); 1733 1734 VOID 1735 NTAPI 1736 MiInitializeColorTables( 1737 VOID 1738 ); 1739 1740 VOID 1741 NTAPI 1742 MiInitializePfnDatabase( 1743 IN PLOADER_PARAMETER_BLOCK LoaderBlock 1744 ); 1745 1746 VOID 1747 NTAPI 1748 MiInitializeSessionWsSupport( 1749 VOID 1750 ); 1751 1752 VOID 1753 NTAPI 1754 MiInitializeSessionIds( 1755 VOID 1756 ); 1757 1758 BOOLEAN 1759 NTAPI 1760 MiInitializeMemoryEvents( 1761 VOID 1762 ); 1763 1764 PFN_NUMBER 1765 NTAPI 1766 MxGetNextPage( 1767 IN PFN_NUMBER PageCount 1768 ); 1769 1770 PPHYSICAL_MEMORY_DESCRIPTOR 1771 NTAPI 1772 MmInitializeMemoryLimits( 1773 IN PLOADER_PARAMETER_BLOCK LoaderBlock, 1774 IN PBOOLEAN IncludeType 1775 ); 1776 1777 PFN_NUMBER 1778 NTAPI 1779 MiPagesInLoaderBlock( 1780 IN PLOADER_PARAMETER_BLOCK LoaderBlock, 1781 IN PBOOLEAN IncludeType 1782 ); 1783 1784 VOID 1785 FASTCALL 1786 MiSyncARM3WithROS( 1787 IN PVOID AddressStart, 1788 IN PVOID AddressEnd 1789 ); 1790 1791 NTSTATUS 1792 NTAPI 1793 MiRosProtectVirtualMemory( 1794 IN PEPROCESS Process, 1795 IN OUT PVOID *BaseAddress, 1796 IN OUT PSIZE_T NumberOfBytesToProtect, 1797 IN ULONG NewAccessProtection, 1798 OUT PULONG OldAccessProtection OPTIONAL 1799 ); 1800 1801 NTSTATUS 1802 NTAPI 1803 MmArmAccessFault( 1804 IN ULONG FaultCode, 1805 IN PVOID Address, 1806 IN KPROCESSOR_MODE Mode, 1807 IN PVOID TrapInformation 1808 ); 1809 1810 NTSTATUS 1811 FASTCALL 1812 MiCheckPdeForPagedPool( 1813 IN PVOID Address 1814 ); 1815 1816 VOID 1817 NTAPI 1818 MiInitializeNonPagedPool( 1819 VOID 1820 ); 1821 1822 VOID 1823 NTAPI 1824 MiInitializeNonPagedPoolThresholds( 1825 VOID 1826 ); 1827 1828 VOID 1829 NTAPI 1830 MiInitializePoolEvents( 1831 VOID 1832 ); 1833 1834 VOID // 1835 NTAPI // 1836 InitializePool( // 1837 IN POOL_TYPE PoolType,// FIXFIX: This should go in ex.h after the pool merge 1838 IN ULONG Threshold // 1839 ); // 1840 1841 // FIXFIX: THIS ONE TOO 1842 VOID 1843 NTAPI 1844 ExInitializePoolDescriptor( 1845 IN PPOOL_DESCRIPTOR PoolDescriptor, 1846 IN POOL_TYPE PoolType, 1847 IN ULONG PoolIndex, 1848 IN ULONG Threshold, 1849 IN PVOID PoolLock 1850 ); 1851 1852 NTSTATUS 1853 NTAPI 1854 MiInitializeSessionPool( 1855 VOID 1856 ); 1857 1858 VOID 1859 NTAPI 1860 MiInitializeSystemPtes( 1861 IN PMMPTE StartingPte, 1862 IN ULONG NumberOfPtes, 1863 IN MMSYSTEM_PTE_POOL_TYPE PoolType 1864 ); 1865 1866 PMMPTE 1867 NTAPI 1868 MiReserveSystemPtes( 1869 IN ULONG NumberOfPtes, 1870 IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType 1871 ); 1872 1873 VOID 1874 NTAPI 1875 MiReleaseSystemPtes( 1876 IN PMMPTE StartingPte, 1877 IN ULONG NumberOfPtes, 1878 IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType 1879 ); 1880 1881 1882 PFN_NUMBER 1883 NTAPI 1884 MiFindContiguousPages( 1885 IN PFN_NUMBER LowestPfn, 1886 IN PFN_NUMBER HighestPfn, 1887 IN PFN_NUMBER BoundaryPfn, 1888 IN PFN_NUMBER SizeInPages, 1889 IN MEMORY_CACHING_TYPE CacheType 1890 ); 1891 1892 PVOID 1893 NTAPI 1894 MiCheckForContiguousMemory( 1895 IN PVOID BaseAddress, 1896 IN PFN_NUMBER BaseAddressPages, 1897 IN PFN_NUMBER SizeInPages, 1898 IN PFN_NUMBER LowestPfn, 1899 IN PFN_NUMBER HighestPfn, 1900 IN PFN_NUMBER BoundaryPfn, 1901 IN MI_PFN_CACHE_ATTRIBUTE CacheAttribute 1902 ); 1903 1904 PMDL 1905 NTAPI 1906 MiAllocatePagesForMdl( 1907 IN PHYSICAL_ADDRESS LowAddress, 1908 IN PHYSICAL_ADDRESS HighAddress, 1909 IN PHYSICAL_ADDRESS SkipBytes, 1910 IN SIZE_T TotalBytes, 1911 IN MI_PFN_CACHE_ATTRIBUTE CacheAttribute, 1912 IN ULONG Flags 1913 ); 1914 1915 VOID 1916 NTAPI 1917 MiInsertPageInList( 1918 IN PMMPFNLIST ListHead, 1919 IN PFN_NUMBER PageFrameIndex 1920 ); 1921 1922 VOID 1923 NTAPI 1924 MiUnlinkFreeOrZeroedPage( 1925 IN PMMPFN Entry 1926 ); 1927 1928 VOID 1929 NTAPI 1930 MiUnlinkPageFromList( 1931 IN PMMPFN Pfn 1932 ); 1933 1934 VOID 1935 NTAPI 1936 MiInitializePfn( 1937 IN PFN_NUMBER PageFrameIndex, 1938 IN PMMPTE PointerPte, 1939 IN BOOLEAN Modified 1940 ); 1941 1942 NTSTATUS 1943 NTAPI 1944 MiInitializeAndChargePfn( 1945 OUT PPFN_NUMBER PageFrameIndex, 1946 IN PMMPDE PointerPde, 1947 IN PFN_NUMBER ContainingPageFrame, 1948 IN BOOLEAN SessionAllocation 1949 ); 1950 1951 VOID 1952 NTAPI 1953 MiInitializePfnAndMakePteValid( 1954 IN PFN_NUMBER PageFrameIndex, 1955 IN PMMPTE PointerPte, 1956 IN MMPTE TempPte 1957 ); 1958 1959 VOID 1960 NTAPI 1961 MiInitializePfnForOtherProcess( 1962 IN PFN_NUMBER PageFrameIndex, 1963 IN PVOID PteAddress, 1964 IN PFN_NUMBER PteFrame 1965 ); 1966 1967 VOID 1968 NTAPI 1969 MiDecrementShareCount( 1970 IN PMMPFN Pfn1, 1971 IN PFN_NUMBER PageFrameIndex 1972 ); 1973 1974 PFN_NUMBER 1975 NTAPI 1976 MiRemoveAnyPage( 1977 IN ULONG Color 1978 ); 1979 1980 PFN_NUMBER 1981 NTAPI 1982 MiRemoveZeroPage( 1983 IN ULONG Color 1984 ); 1985 1986 VOID 1987 NTAPI 1988 MiZeroPhysicalPage( 1989 IN PFN_NUMBER PageFrameIndex 1990 ); 1991 1992 VOID 1993 NTAPI 1994 MiInsertPageInFreeList( 1995 IN PFN_NUMBER PageFrameIndex 1996 ); 1997 1998 PFN_COUNT 1999 NTAPI 2000 MiDeleteSystemPageableVm( 2001 IN PMMPTE PointerPte, 2002 IN PFN_NUMBER PageCount, 2003 IN ULONG Flags, 2004 OUT PPFN_NUMBER ValidPages 2005 ); 2006 2007 ULONG 2008 NTAPI 2009 MiGetPageProtection( 2010 IN PMMPTE PointerPte 2011 ); 2012 2013 PLDR_DATA_TABLE_ENTRY 2014 NTAPI 2015 MiLookupDataTableEntry( 2016 IN PVOID Address 2017 ); 2018 2019 VOID 2020 NTAPI 2021 MiInitializeDriverLargePageList( 2022 VOID 2023 ); 2024 2025 VOID 2026 NTAPI 2027 MiInitializeLargePageSupport( 2028 VOID 2029 ); 2030 2031 VOID 2032 NTAPI 2033 MiSyncCachedRanges( 2034 VOID 2035 ); 2036 2037 BOOLEAN 2038 NTAPI 2039 MiIsPfnInUse( 2040 IN PMMPFN Pfn1 2041 ); 2042 2043 PMMVAD 2044 NTAPI 2045 MiLocateAddress( 2046 IN PVOID VirtualAddress 2047 ); 2048 2049 TABLE_SEARCH_RESULT 2050 NTAPI 2051 MiCheckForConflictingNode( 2052 IN ULONG_PTR StartVpn, 2053 IN ULONG_PTR EndVpn, 2054 IN PMM_AVL_TABLE Table, 2055 OUT PMMADDRESS_NODE *NodeOrParent 2056 ); 2057 2058 TABLE_SEARCH_RESULT 2059 NTAPI 2060 MiFindEmptyAddressRangeDownTree( 2061 IN SIZE_T Length, 2062 IN ULONG_PTR BoundaryAddress, 2063 IN ULONG_PTR Alignment, 2064 IN PMM_AVL_TABLE Table, 2065 OUT PULONG_PTR Base, 2066 OUT PMMADDRESS_NODE *Parent 2067 ); 2068 2069 NTSTATUS 2070 NTAPI 2071 MiFindEmptyAddressRangeDownBasedTree( 2072 IN SIZE_T Length, 2073 IN ULONG_PTR BoundaryAddress, 2074 IN ULONG_PTR Alignment, 2075 IN PMM_AVL_TABLE Table, 2076 OUT PULONG_PTR Base 2077 ); 2078 2079 TABLE_SEARCH_RESULT 2080 NTAPI 2081 MiFindEmptyAddressRangeInTree( 2082 IN SIZE_T Length, 2083 IN ULONG_PTR Alignment, 2084 IN PMM_AVL_TABLE Table, 2085 OUT PMMADDRESS_NODE *PreviousVad, 2086 OUT PULONG_PTR Base 2087 ); 2088 2089 NTSTATUS 2090 NTAPI 2091 MiCheckSecuredVad( 2092 IN PMMVAD Vad, 2093 IN PVOID Base, 2094 IN SIZE_T Size, 2095 IN ULONG ProtectionMask 2096 ); 2097 2098 VOID 2099 NTAPI 2100 MiInsertVad( 2101 _Inout_ PMMVAD Vad, 2102 _Inout_ PMM_AVL_TABLE VadRoot); 2103 2104 NTSTATUS 2105 NTAPI 2106 MiInsertVadEx( 2107 _Inout_ PMMVAD Vad, 2108 _In_ ULONG_PTR *BaseAddress, 2109 _In_ SIZE_T ViewSize, 2110 _In_ ULONG_PTR HighestAddress, 2111 _In_ ULONG_PTR Alignment, 2112 _In_ ULONG AllocationType); 2113 2114 VOID 2115 NTAPI 2116 MiInsertBasedSection( 2117 IN PSECTION Section 2118 ); 2119 2120 NTSTATUS 2121 NTAPI 2122 MiUnmapViewOfSection( 2123 IN PEPROCESS Process, 2124 IN PVOID BaseAddress, 2125 IN ULONG Flags 2126 ); 2127 2128 NTSTATUS 2129 NTAPI 2130 MiRosUnmapViewOfSection( 2131 IN PEPROCESS Process, 2132 IN PVOID BaseAddress, 2133 IN BOOLEAN SkipDebuggerNotify 2134 ); 2135 2136 VOID 2137 NTAPI 2138 MiInsertNode( 2139 IN PMM_AVL_TABLE Table, 2140 IN PMMADDRESS_NODE NewNode, 2141 PMMADDRESS_NODE Parent, 2142 TABLE_SEARCH_RESULT Result 2143 ); 2144 2145 VOID 2146 NTAPI 2147 MiRemoveNode( 2148 IN PMMADDRESS_NODE Node, 2149 IN PMM_AVL_TABLE Table 2150 ); 2151 2152 PMMADDRESS_NODE 2153 NTAPI 2154 MiGetPreviousNode( 2155 IN PMMADDRESS_NODE Node 2156 ); 2157 2158 PMMADDRESS_NODE 2159 NTAPI 2160 MiGetNextNode( 2161 IN PMMADDRESS_NODE Node 2162 ); 2163 2164 BOOLEAN 2165 NTAPI 2166 MiInitializeSystemSpaceMap( 2167 IN PMMSESSION InputSession OPTIONAL 2168 ); 2169 2170 VOID 2171 NTAPI 2172 MiSessionRemoveProcess( 2173 VOID 2174 ); 2175 2176 VOID 2177 NTAPI 2178 MiReleaseProcessReferenceToSessionDataPage( 2179 IN PMM_SESSION_SPACE SessionGlobal 2180 ); 2181 2182 VOID 2183 NTAPI 2184 MiSessionAddProcess( 2185 IN PEPROCESS NewProcess 2186 ); 2187 2188 NTSTATUS 2189 NTAPI 2190 MiSessionCommitPageTables( 2191 IN PVOID StartVa, 2192 IN PVOID EndVa 2193 ); 2194 2195 ULONG 2196 NTAPI 2197 MiMakeProtectionMask( 2198 IN ULONG Protect 2199 ); 2200 2201 VOID 2202 NTAPI 2203 MiDeleteVirtualAddresses( 2204 IN ULONG_PTR Va, 2205 IN ULONG_PTR EndingAddress, 2206 IN PMMVAD Vad 2207 ); 2208 2209 VOID 2210 NTAPI 2211 MiDeletePte( 2212 IN PMMPTE PointerPte, 2213 IN PVOID VirtualAddress, 2214 IN PEPROCESS CurrentProcess, 2215 IN PMMPTE PrototypePte 2216 ); 2217 2218 ULONG 2219 NTAPI 2220 MiMakeSystemAddressValid( 2221 IN PVOID PageTableVirtualAddress, 2222 IN PEPROCESS CurrentProcess 2223 ); 2224 2225 ULONG 2226 NTAPI 2227 MiMakeSystemAddressValidPfn( 2228 IN PVOID VirtualAddress, 2229 IN KIRQL OldIrql 2230 ); 2231 2232 VOID 2233 NTAPI 2234 MiRemoveMappedView( 2235 IN PEPROCESS CurrentProcess, 2236 IN PMMVAD Vad 2237 ); 2238 2239 PSUBSECTION 2240 NTAPI 2241 MiLocateSubsection( 2242 IN PMMVAD Vad, 2243 IN ULONG_PTR Vpn 2244 ); 2245 2246 VOID 2247 NTAPI 2248 MiDeleteARM3Section( 2249 PVOID ObjectBody 2250 ); 2251 2252 NTSTATUS 2253 NTAPI 2254 MiQueryMemorySectionName( 2255 IN HANDLE ProcessHandle, 2256 IN PVOID BaseAddress, 2257 OUT PVOID MemoryInformation, 2258 IN SIZE_T MemoryInformationLength, 2259 OUT PSIZE_T ReturnLength 2260 ); 2261 2262 NTSTATUS 2263 NTAPI 2264 MiRosUnmapViewInSystemSpace( 2265 IN PVOID MappedBase 2266 ); 2267 2268 POOL_TYPE 2269 NTAPI 2270 MmDeterminePoolType( 2271 IN PVOID PoolAddress 2272 ); 2273 2274 VOID 2275 NTAPI 2276 MiMakePdeExistAndMakeValid( 2277 IN PMMPDE PointerPde, 2278 IN PEPROCESS TargetProcess, 2279 IN KIRQL OldIrql 2280 ); 2281 2282 VOID 2283 NTAPI 2284 MiWriteProtectSystemImage( 2285 _In_ PVOID ImageBase); 2286 2287 // 2288 // MiRemoveZeroPage will use inline code to zero out the page manually if only 2289 // free pages are available. In some scenarios, we don't/can't run that piece of 2290 // code and would rather only have a real zero page. If we can't have a zero page, 2291 // then we'd like to have our own code to grab a free page and zero it out, by 2292 // using MiRemoveAnyPage. This macro implements this. 2293 // 2294 FORCEINLINE 2295 PFN_NUMBER 2296 MiRemoveZeroPageSafe(IN ULONG Color) 2297 { 2298 if (MmFreePagesByColor[ZeroedPageList][Color].Flink != LIST_HEAD) return MiRemoveZeroPage(Color); 2299 return 0; 2300 } 2301 2302 #if (_MI_PAGING_LEVELS == 2) 2303 FORCEINLINE 2304 BOOLEAN 2305 MiSynchronizeSystemPde(PMMPDE PointerPde) 2306 { 2307 MMPDE SystemPde; 2308 ULONG Index; 2309 2310 /* Get the Index from the PDE */ 2311 Index = ((ULONG_PTR)PointerPde & (SYSTEM_PD_SIZE - 1)) / sizeof(MMPTE); 2312 2313 /* Copy the PDE from the double-mapped system page directory */ 2314 SystemPde = MmSystemPagePtes[Index]; 2315 *PointerPde = SystemPde; 2316 2317 /* Make sure we re-read the PDE and PTE */ 2318 KeMemoryBarrierWithoutFence(); 2319 2320 /* Return, if we had success */ 2321 return SystemPde.u.Hard.Valid != 0; 2322 } 2323 #endif 2324 2325 /* EOF */ 2326