Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

mi.h

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1989 Microsoft Corporation 00004 00005 Module Name: 00006 00007 mi.h 00008 00009 Abstract: 00010 00011 This module contains the private data structures and procedure 00012 prototypes for the memory management system. 00013 00014 Author: 00015 00016 Lou Perazzoli (loup) 20-Mar-1989 00017 Landy Wang (landyw) 02-Jun-1997 00018 00019 Revision History: 00020 00021 --*/ 00022 00023 #ifndef _MI_ 00024 #define _MI_ 00025 00026 #include "ntos.h" 00027 #include "ntimage.h" 00028 #include "ki.h" 00029 #include "fsrtl.h" 00030 #include "zwapi.h" 00031 #include "pool.h" 00032 #include "ntiodump.h" 00033 #include "stdio.h" 00034 #include "string.h" 00035 #include "safeboot.h" 00036 #include "triage.h" 00037 00038 #if defined(_X86_) 00039 #include "..\mm\i386\mi386.h" 00040 00041 #elif defined(_AXP64_) 00042 #include "..\mm\axp64\mialpha.h" 00043 00044 #elif defined(_ALPHA_) 00045 #include "..\mm\alpha\mialpha.h" 00046 00047 #elif defined(_IA64_) 00048 #include "..\mm\ia64\miia64.h" 00049 00050 #else 00051 #error "mm: a target architecture must be defined." 00052 #endif 00053 00054 #if defined (_WIN64) 00055 #define ASSERT32(exp) 00056 #define ASSERT64(exp) ASSERT(exp) 00057 #else 00058 #define ASSERT32(exp) ASSERT(exp) 00059 #define ASSERT64(exp) 00060 #endif 00061 00062 // 00063 // Special pool constants 00064 // 00065 #define MI_SPECIAL_POOL_PAGABLE 0x8000 00066 #define MI_SPECIAL_POOL_VERIFIER 0x4000 00067 #define MI_SPECIAL_POOL_PTE_PAGABLE 0x0002 00068 #define MI_SPECIAL_POOL_PTE_NONPAGABLE 0x0004 00069 00070 00071 #define _2gb 0x80000000 // 2 gigabytes 00072 #define _4gb 0x100000000 // 4 gigabytes 00073 00074 #define MM_FLUSH_COUNTER_MASK (0xFFFFF) 00075 00076 #define MM_FREE_WSLE_SHIFT 4 00077 00078 #define WSLE_NULL_INDEX ((ULONG)0xFFFFFFF) 00079 00080 #define MM_FREE_POOL_SIGNATURE (0x50554F4C) 00081 00082 #define MM_MINIMUM_PAGED_POOL_NTAS ((SIZE_T)(48*1024*1024)) 00083 00084 #define MM_ALLOCATION_FILLS_VAD ((PMMPTE)(ULONG_PTR)~3) 00085 00086 #define MM_WORKING_SET_LIST_SEARCH 17 00087 00088 #define MM_FLUID_WORKING_SET 8 00089 00090 #define MM_FLUID_PHYSICAL_PAGES 32 //see MmResidentPages below. 00091 00092 #define MM_USABLE_PAGES_FREE 32 00093 00094 #define X64K (ULONG)65536 00095 00096 #define MM_HIGHEST_VAD_ADDRESS ((PVOID)((ULONG_PTR)MM_HIGHEST_USER_ADDRESS - (64 * 1024))) 00097 00098 00099 #define MM_NO_WS_EXPANSION ((PLIST_ENTRY)0) 00100 #define MM_WS_EXPANSION_IN_PROGRESS ((PLIST_ENTRY)35) 00101 #define MM_WS_SWAPPED_OUT ((PLIST_ENTRY)37) 00102 #define MM_IO_IN_PROGRESS ((PLIST_ENTRY)97) // MUST HAVE THE HIGHEST VALUE 00103 00104 #define MM_PAGES_REQUIRED_FOR_MAPPED_IO 7 00105 00106 #define MM4K_SHIFT 12 //MUST BE LESS THAN OR EQUAL TO PAGE_SHIFT 00107 #define MM4K_MASK 0xfff 00108 00109 #define MMSECTOR_SHIFT 9 //MUST BE LESS THAN OR EQUAL TO PAGE_SHIFT 00110 00111 #define MMSECTOR_MASK 0x1ff 00112 00113 #define MM_LOCK_BY_REFCOUNT 0 00114 00115 #define MM_LOCK_BY_NONPAGE 1 00116 00117 #define MM_FORCE_TRIM 6 00118 00119 #define MM_GROW_WSLE_HASH 20 00120 00121 #define MM_MAXIMUM_WRITE_CLUSTER (MM_MAXIMUM_DISK_IO_SIZE / PAGE_SIZE) 00122 00123 // 00124 // Number of PTEs to flush singularly before flushing the entire TB. 00125 // 00126 00127 #define MM_MAXIMUM_FLUSH_COUNT (FLUSH_MULTIPLE_MAXIMUM-1) 00128 00129 // 00130 // Page protections 00131 // 00132 00133 #define MM_ZERO_ACCESS 0 // this value is not used. 00134 #define MM_READONLY 1 00135 #define MM_EXECUTE 2 00136 #define MM_EXECUTE_READ 3 00137 #define MM_READWRITE 4 // bit 2 is set if this is writable. 00138 #define MM_WRITECOPY 5 00139 #define MM_EXECUTE_READWRITE 6 00140 #define MM_EXECUTE_WRITECOPY 7 00141 00142 #define MM_NOCACHE 0x8 00143 #define MM_GUARD_PAGE 0x10 00144 #define MM_DECOMMIT 0x10 //NO_ACCESS, Guard page 00145 #define MM_NOACCESS 0x18 //NO_ACCESS, Guard_page, nocache. 00146 #define MM_UNKNOWN_PROTECTION 0x100 //bigger than 5 bits! 00147 #define MM_LARGE_PAGES 0x111 00148 00149 #define PROTECT_KSTACKS 1 00150 00151 #define MM_KSTACK_OUTSWAPPED 0x1F //Debug marking for kernel stacks 00152 00153 #define MM_PROTECTION_WRITE_MASK 4 00154 #define MM_PROTECTION_COPY_MASK 1 00155 #define MM_PROTECTION_OPERATION_MASK 7 // mask off guard page and nocache. 00156 #define MM_PROTECTION_EXECUTE_MASK 2 00157 00158 #define MM_SECURE_DELETE_CHECK 0x55 00159 00160 // 00161 // Debug flags 00162 // 00163 00164 #define MM_DBG_WRITEFAULT 0x1 00165 #define MM_DBG_PTE_UPDATE 0x2 00166 #define MM_DBG_DUMP_WSL 0x4 00167 #define MM_DBG_PAGEFAULT 0x8 00168 #define MM_DBG_WS_EXPANSION 0x10 00169 #define MM_DBG_MOD_WRITE 0x20 00170 #define MM_DBG_CHECK_PTE 0x40 00171 #define MM_DBG_VAD_CONFLICT 0x80 00172 #define MM_DBG_SECTIONS 0x100 00173 #define MM_DBG_SYS_PTES 0x400 00174 #define MM_DBG_CLEAN_PROCESS 0x800 00175 #define MM_DBG_COLLIDED_PAGE 0x1000 00176 #define MM_DBG_DUMP_BOOT_PTES 0x2000 00177 #define MM_DBG_FORK 0x4000 00178 #define MM_DBG_DIR_BASE 0x8000 00179 #define MM_DBG_FLUSH_SECTION 0x10000 00180 #define MM_DBG_PRINTS_MODWRITES 0x20000 00181 #define MM_DBG_PAGE_IN_LIST 0x40000 00182 #define MM_DBG_CHECK_PFN_LOCK 0x80000 00183 #define MM_DBG_PRIVATE_PAGES 0x100000 00184 #define MM_DBG_WALK_VAD_TREE 0x200000 00185 #define MM_DBG_SWAP_PROCESS 0x400000 00186 #define MM_DBG_LOCK_CODE 0x800000 00187 #define MM_DBG_STOP_ON_ACCVIO 0x1000000 00188 #define MM_DBG_PAGE_REF_COUNT 0x2000000 00189 #define MM_DBG_SHOW_NT_CALLS 0x10000000 00190 #define MM_DBG_SHOW_FAULTS 0x40000000 00191 #define MM_DBG_SESSIONS 0x80000000 00192 00193 // 00194 // if the PTE.protection & MM_COPY_ON_WRITE_MASK == MM_COPY_ON_WRITE_MASK 00195 // then the pte is copy on write. 00196 // 00197 00198 #define MM_COPY_ON_WRITE_MASK 5 00199 00200 extern ULONG MmProtectToValue[32]; 00201 extern ULONG MmProtectToPteMask[32]; 00202 extern ULONG MmMakeProtectNotWriteCopy[32]; 00203 extern ACCESS_MASK MmMakeSectionAccess[8]; 00204 extern ACCESS_MASK MmMakeFileAccess[8]; 00205 00206 00207 // 00208 // Time constants 00209 // 00210 00211 extern LARGE_INTEGER MmSevenMinutes; 00212 extern LARGE_INTEGER MmWorkingSetProtectionTime; 00213 extern LARGE_INTEGER MmOneSecond; 00214 extern LARGE_INTEGER MmTwentySeconds; 00215 extern LARGE_INTEGER MmShortTime; 00216 extern LARGE_INTEGER MmHalfSecond; 00217 extern LARGE_INTEGER Mm30Milliseconds; 00218 extern LARGE_INTEGER MmCriticalSectionTimeout; 00219 00220 // 00221 // A month's worth 00222 // 00223 00224 extern ULONG MmCritsectTimeoutSeconds; 00225 00226 // 00227 // this is the csrss process ! 00228 // 00229 00230 extern PEPROCESS ExpDefaultErrorPortProcess; 00231 00232 extern SIZE_T MmExtendedCommit; 00233 00234 // 00235 // The total number of pages needed for the loader to successfully hibernate. 00236 // 00237 00238 extern PFN_NUMBER MmHiberPages; 00239 00240 // 00241 // The counters and reasons to retry IO to protect against verifier induced 00242 // failures and temporary conditions. 00243 // 00244 00245 extern ULONG MiIoRetryLevel; 00246 extern ULONG MiFaultRetries; 00247 extern ULONG MiUserIoRetryLevel; 00248 extern ULONG MiUserFaultRetries; 00249 00250 #define MmIsRetryIoStatus(S) (((S) == STATUS_INSUFFICIENT_RESOURCES) || \ 00251 ((S) == STATUS_WORKING_SET_QUOTA) || \ 00252 ((S) == STATUS_NO_MEMORY)) 00253 00254 //++ 00255 // 00256 // ULONG 00257 // MI_CONVERT_FROM_PTE_PROTECTION ( 00258 // IN ULONG PROTECTION_MASK 00259 // ) 00260 // 00261 // Routine Description: 00262 // 00263 // This routine converts a PTE protection into a Protect value. 00264 // 00265 // Arguments: 00266 // 00267 // 00268 // Return Value: 00269 // 00270 // Returns the 00271 // 00272 //-- 00273 00274 #define MI_CONVERT_FROM_PTE_PROTECTION(PROTECTION_MASK) \ 00275 (MmProtectToValue[PROTECTION_MASK]) 00276 00277 #define MI_MASK_TO_PTE(PROTECTION_MASK) MmProtectToPteMask[PROTECTION_MASK] 00278 00279 00280 #define MI_IS_PTE_PROTECTION_COPY_WRITE(PROTECTION_MASK) \ 00281 (((PROTECTION_MASK) & MM_COPY_ON_WRITE_MASK) == MM_COPY_ON_WRITE_MASK) 00282 00283 //++ 00284 // 00285 // ULONG 00286 // MI_ROUND_TO_64K ( 00287 // IN ULONG LENGTH 00288 // ) 00289 // 00290 // Routine Description: 00291 // 00292 // 00293 // The ROUND_TO_64k macro takes a LENGTH in bytes and rounds it up to a multiple 00294 // of 64K. 00295 // 00296 // Arguments: 00297 // 00298 // LENGTH - LENGTH in bytes to round up to 64k. 00299 // 00300 // Return Value: 00301 // 00302 // Returns the LENGTH rounded up to a multiple of 64k. 00303 // 00304 //-- 00305 00306 #define MI_ROUND_TO_64K(LENGTH) (((LENGTH) + X64K - 1) & ~(X64K - 1)) 00307 00308 //++ 00309 // 00310 // ULONG 00311 // MI_ROUND_TO_SIZE ( 00312 // IN ULONG LENGTH, 00313 // IN ULONG ALIGNMENT 00314 // ) 00315 // 00316 // Routine Description: 00317 // 00318 // 00319 // The ROUND_TO_SIZE macro takes a LENGTH in bytes and rounds it up to a 00320 // multiple of the alignment. 00321 // 00322 // Arguments: 00323 // 00324 // LENGTH - LENGTH in bytes to round up to. 00325 // 00326 // ALIGNMENT - alignment to round to, must be a power of 2, e.g, 2**n. 00327 // 00328 // Return Value: 00329 // 00330 // Returns the LENGTH rounded up to a multiple of the alignment. 00331 // 00332 //-- 00333 00334 #define MI_ROUND_TO_SIZE(LENGTH,ALIGNMENT) \ 00335 (((LENGTH) + ((ALIGNMENT) - 1)) & ~((ALIGNMENT) - 1)) 00336 00337 //++ 00338 // 00339 // PVOID 00340 // MI_64K_ALIGN ( 00341 // IN PVOID VA 00342 // ) 00343 // 00344 // Routine Description: 00345 // 00346 // 00347 // The MI_64K_ALIGN macro takes a virtual address and returns a 64k-aligned 00348 // virtual address for that page. 00349 // 00350 // Arguments: 00351 // 00352 // VA - Virtual address. 00353 // 00354 // Return Value: 00355 // 00356 // Returns the 64k aligned virtual address. 00357 // 00358 //-- 00359 00360 #define MI_64K_ALIGN(VA) ((PVOID)((ULONG_PTR)(VA) & ~((LONG)X64K - 1))) 00361 00362 00363 //++ 00364 // 00365 // PVOID 00366 // MI_ALIGN_TO_SIZE ( 00367 // IN PVOID VA 00368 // IN ULONG ALIGNMENT 00369 // ) 00370 // 00371 // Routine Description: 00372 // 00373 // 00374 // The MI_ALIGN_TO_SIZE macro takes a virtual address and returns a 00375 // virtual address for that page with the specified alignment. 00376 // 00377 // Arguments: 00378 // 00379 // VA - Virtual address. 00380 // 00381 // ALIGNMENT - alignment to round to, must be a power of 2, e.g, 2**n. 00382 // 00383 // Return Value: 00384 // 00385 // Returns the aligned virtual address. 00386 // 00387 //-- 00388 00389 #define MI_ALIGN_TO_SIZE(VA,ALIGNMENT) ((PVOID)((ULONG_PTR)(VA) & ~((ULONG_PTR) ALIGNMENT - 1))) 00390 00391 //++ 00392 // 00393 // LONGLONG 00394 // MI_STARTING_OFFSET ( 00395 // IN PSUBSECTION SUBSECT 00396 // IN PMMPTE PTE 00397 // ) 00398 // 00399 // Routine Description: 00400 // 00401 // This macro takes a pointer to a PTE within a subsection and a pointer 00402 // to that subsection and calculates the offset for that PTE within the 00403 // file. 00404 // 00405 // Arguments: 00406 // 00407 // PTE - PTE within subsection. 00408 // 00409 // SUBSECT - Subsection 00410 // 00411 // Return Value: 00412 // 00413 // Offset for issuing I/O from. 00414 // 00415 //-- 00416 00417 #define MI_STARTING_OFFSET(SUBSECT,PTE) \ 00418 (((LONGLONG)((ULONG_PTR)((PTE) - ((SUBSECT)->SubsectionBase))) << PAGE_SHIFT) + \ 00419 ((LONGLONG)((SUBSECT)->StartingSector) << MMSECTOR_SHIFT)); 00420 00421 00422 // PVOID 00423 // MiFindEmptyAddressRangeDown ( 00424 // IN ULONG_PTR SizeOfRange, 00425 // IN PVOID HighestAddressToEndAt, 00426 // IN ULONG_PTR Alignment 00427 // ) 00428 // 00429 // 00430 // Routine Description: 00431 // 00432 // The function examines the virtual address descriptors to locate 00433 // an unused range of the specified size and returns the starting 00434 // address of the range. This routine looks from the top down. 00435 // 00436 // Arguments: 00437 // 00438 // SizeOfRange - Supplies the size in bytes of the range to locate. 00439 // 00440 // HighestAddressToEndAt - Supplies the virtual address to begin looking 00441 // at. 00442 // 00443 // Alignment - Supplies the alignment for the address. Must be 00444 // a power of 2 and greater than the page_size. 00445 // 00446 //Return Value: 00447 // 00448 // Returns the starting address of a suitable range. 00449 // 00450 00451 #define MiFindEmptyAddressRangeDown(SizeOfRange,HighestAddressToEndAt,Alignment) \ 00452 (MiFindEmptyAddressRangeDownTree( \ 00453 (SizeOfRange), \ 00454 (HighestAddressToEndAt), \ 00455 (Alignment), \ 00456 (PMMADDRESS_NODE)(PsGetCurrentProcess()->VadRoot))) 00457 00458 // PMMVAD 00459 // MiGetPreviousVad ( 00460 // IN PMMVAD Vad 00461 // ) 00462 // 00463 // Routine Description: 00464 // 00465 // This function locates the virtual address descriptor which contains 00466 // the address range which logically precedes the specified virtual 00467 // address descriptor. 00468 // 00469 // Arguments: 00470 // 00471 // Vad - Supplies a pointer to a virtual address descriptor. 00472 // 00473 // Return Value: 00474 // 00475 // Returns a pointer to the virtual address descriptor containing the 00476 // next address range, NULL if none. 00477 // 00478 // 00479 00480 #define MiGetPreviousVad(VAD) ((PMMVAD)MiGetPreviousNode((PMMADDRESS_NODE)(VAD))) 00481 00482 00483 // PMMVAD 00484 // MiGetNextVad ( 00485 // IN PMMVAD Vad 00486 // ) 00487 // 00488 // Routine Description: 00489 // 00490 // This function locates the virtual address descriptor which contains 00491 // the address range which logically follows the specified address range. 00492 // 00493 // Arguments: 00494 // 00495 // VAD - Supplies a pointer to a virtual address descriptor. 00496 // 00497 // Return Value: 00498 // 00499 // Returns a pointer to the virtual address descriptor containing the 00500 // next address range, NULL if none. 00501 // 00502 00503 #define MiGetNextVad(VAD) ((PMMVAD)MiGetNextNode((PMMADDRESS_NODE)(VAD))) 00504 00505 00506 00507 // PMMVAD 00508 // MiGetFirstVad ( 00509 // Process 00510 // ) 00511 // 00512 // Routine Description: 00513 // 00514 // This function locates the virtual address descriptor which contains 00515 // the address range which logically is first within the address space. 00516 // 00517 // Arguments: 00518 // 00519 // Process - Specifies the process in which to locate the VAD. 00520 // 00521 // Return Value: 00522 // 00523 // Returns a pointer to the virtual address descriptor containing the 00524 // first address range, NULL if none. 00525 00526 #define MiGetFirstVad(Process) \ 00527 ((PMMVAD)MiGetFirstNode((PMMADDRESS_NODE)(Process->VadRoot))) 00528 00529 00530 00531 // PMMVAD 00532 // MiCheckForConflictingVad ( 00533 // IN PVOID StartingAddress, 00534 // IN PVOID EndingAddress 00535 // ) 00536 // 00537 // Routine Description: 00538 // 00539 // The function determines if any addresses between a given starting and 00540 // ending address is contained within a virtual address descriptor. 00541 // 00542 // Arguments: 00543 // 00544 // StartingAddress - Supplies the virtual address to locate a containing 00545 // descriptor. 00546 // 00547 // EndingAddress - Supplies the virtual address to locate a containing 00548 // descriptor. 00549 // 00550 // Return Value: 00551 // 00552 // Returns a pointer to the first conflicting virtual address descriptor 00553 // if one is found, otherwise a NULL value is returned. 00554 // 00555 00556 #define MiCheckForConflictingVad(StartingAddress,EndingAddress) \ 00557 ((PMMVAD)MiCheckForConflictingNode( \ 00558 MI_VA_TO_VPN(StartingAddress), \ 00559 MI_VA_TO_VPN(EndingAddress), \ 00560 (PMMADDRESS_NODE)(PsGetCurrentProcess()->VadRoot))) 00561 00562 // PMMCLONE_DESCRIPTOR 00563 // MiGetNextClone ( 00564 // IN PMMCLONE_DESCRIPTOR Clone 00565 // ) 00566 // 00567 // Routine Description: 00568 // 00569 // This function locates the virtual address descriptor which contains 00570 // the address range which logically follows the specified address range. 00571 // 00572 // Arguments: 00573 // 00574 // Clone - Supplies a pointer to a virtual address descriptor. 00575 // 00576 // Return Value: 00577 // 00578 // Returns a pointer to the virtual address descriptor containing the 00579 // next address range, NULL if none. 00580 // 00581 // 00582 00583 #define MiGetNextClone(CLONE) \ 00584 ((PMMCLONE_DESCRIPTOR)MiGetNextNode((PMMADDRESS_NODE)(CLONE))) 00585 00586 00587 00588 // PMMCLONE_DESCRIPTOR 00589 // MiGetPreviousClone ( 00590 // IN PMMCLONE_DESCRIPTOR Clone 00591 // ) 00592 // 00593 // Routine Description: 00594 // 00595 // This function locates the virtual address descriptor which contains 00596 // the address range which logically precedes the specified virtual 00597 // address descriptor. 00598 // 00599 // Arguments: 00600 // 00601 // Clone - Supplies a pointer to a virtual address descriptor. 00602 // 00603 // Return Value: 00604 // 00605 // Returns a pointer to the virtual address descriptor containing the 00606 // next address range, NULL if none. 00607 00608 00609 #define MiGetPreviousClone(CLONE) \ 00610 ((PMMCLONE_DESCRIPTOR)MiGetPreviousNode((PMMADDRESS_NODE)(CLONE))) 00611 00612 00613 00614 // PMMCLONE_DESCRIPTOR 00615 // MiGetFirstClone ( 00616 // ) 00617 // 00618 // Routine Description: 00619 // 00620 // This function locates the virtual address descriptor which contains 00621 // the address range which logically is first within the address space. 00622 // 00623 // Arguments: 00624 // 00625 // None. 00626 // 00627 // Return Value: 00628 // 00629 // Returns a pointer to the virtual address descriptor containing the 00630 // first address range, NULL if none. 00631 // 00632 00633 00634 #define MiGetFirstClone() \ 00635 ((PMMCLONE_DESCRIPTOR)MiGetFirstNode((PMMADDRESS_NODE)(PsGetCurrentProcess()->CloneRoot))) 00636 00637 00638 00639 // VOID 00640 // MiInsertClone ( 00641 // IN PMMCLONE_DESCRIPTOR Clone 00642 // ) 00643 // 00644 // Routine Description: 00645 // 00646 // This function inserts a virtual address descriptor into the tree and 00647 // reorders the splay tree as appropriate. 00648 // 00649 // Arguments: 00650 // 00651 // Clone - Supplies a pointer to a virtual address descriptor 00652 // 00653 // 00654 // Return Value: 00655 // 00656 // None. 00657 // 00658 00659 #define MiInsertClone(CLONE) \ 00660 { \ 00661 ASSERT ((CLONE)->NumberOfPtes != 0); \ 00662 MiInsertNode(((PMMADDRESS_NODE)(CLONE)),(PMMADDRESS_NODE *)&(PsGetCurrentProcess()->CloneRoot)); \ 00663 } 00664 00665 00666 00667 00668 // VOID 00669 // MiRemoveClone ( 00670 // IN PMMCLONE_DESCRIPTOR Clone 00671 // ) 00672 // 00673 // Routine Description: 00674 // 00675 // This function removes a virtual address descriptor from the tree and 00676 // reorders the splay tree as appropriate. 00677 // 00678 // Arguments: 00679 // 00680 // Clone - Supplies a pointer to a virtual address descriptor. 00681 // 00682 // Return Value: 00683 // 00684 // None. 00685 // 00686 00687 #define MiRemoveClone(CLONE) \ 00688 MiRemoveNode((PMMADDRESS_NODE)(CLONE),(PMMADDRESS_NODE *)&(PsGetCurrentProcess()->CloneRoot)); 00689 00690 00691 00692 // PMMCLONE_DESCRIPTOR 00693 // MiLocateCloneAddress ( 00694 // IN PVOID VirtualAddress 00695 // ) 00696 // 00697 // /*++ 00698 // 00699 // Routine Description: 00700 // 00701 // The function locates the virtual address descriptor which describes 00702 // a given address. 00703 // 00704 // Arguments: 00705 // 00706 // VirtualAddress - Supplies the virtual address to locate a descriptor 00707 // for. 00708 // 00709 // Return Value: 00710 // 00711 // Returns a pointer to the virtual address descriptor which contains 00712 // the supplied virtual address or NULL if none was located. 00713 // 00714 00715 #define MiLocateCloneAddress(VA) \ 00716 (PsGetCurrentProcess()->CloneRoot ? \ 00717 ((PMMCLONE_DESCRIPTOR)MiLocateAddressInTree(((ULONG_PTR)VA), \ 00718 (PMMADDRESS_NODE *)&(PsGetCurrentProcess()->CloneRoot))) : \ 00719 ((PMMCLONE_DESCRIPTOR)NULL)) 00720 00721 00722 // PMMCLONE_DESCRIPTOR 00723 // MiCheckForConflictingClone ( 00724 // IN PVOID StartingAddress, 00725 // IN PVOID EndingAddress 00726 // ) 00727 // 00728 // Routine Description: 00729 // 00730 // The function determines if any addresses between a given starting and 00731 // ending address is contained within a virtual address descriptor. 00732 // 00733 // Arguments: 00734 // 00735 // StartingAddress - Supplies the virtual address to locate a containing 00736 // descriptor. 00737 // 00738 // EndingAddress - Supplies the virtual address to locate a containing 00739 // descriptor. 00740 // 00741 // Return Value: 00742 // 00743 // Returns a pointer to the first conflicting virtual address descriptor 00744 // if one is found, otherwise a NULL value is returned. 00745 // 00746 00747 #define MiCheckForConflictingClone(START,END) \ 00748 ((PMMCLONE_DESCRIPTOR)(MiCheckForConflictingNode(START,END, \ 00749 (PMMADDRESS_NODE)(PsGetCurrentProcess()->CloneRoot)))) 00750 00751 00752 // 00753 // MiGetVirtualPageNumber returns the virtual page number 00754 // for a given address. 00755 // 00756 00757 //#define MiGetVirtualPageNumber(va) ((ULONG_PTR)(va) >> PAGE_SHIFT) 00758 00759 #define MI_VA_TO_PAGE(va) ((ULONG_PTR)(va) >> PAGE_SHIFT) 00760 00761 #define MI_VA_TO_VPN(va) ((ULONG_PTR)(va) >> PAGE_SHIFT) 00762 00763 #define MI_VPN_TO_VA(vpn) (PVOID)((vpn) << PAGE_SHIFT) 00764 00765 #define MI_VPN_TO_VA_ENDING(vpn) (PVOID)(((vpn) << PAGE_SHIFT) | (PAGE_SIZE - 1)) 00766 00767 #define MiGetByteOffset(va) ((ULONG_PTR)(va) & (PAGE_SIZE - 1)) 00768 00769 #define MI_PFN_ELEMENT(index) (&MmPfnDatabase[index]) 00770 00771 // 00772 // Make a write-copy PTE, only writable. 00773 // 00774 00775 #define MI_MAKE_PROTECT_NOT_WRITE_COPY(PROTECT) \ 00776 (MmMakeProtectNotWriteCopy[PROTECT]) 00777 00778 // 00779 // Define macros to lock and unlock the PFN database. 00780 // 00781 00782 #if defined(_ALPHA_) || defined(_X86_) 00783 00784 #define MiLockPfnDatabase(OldIrql) \ 00785 OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock) 00786 00787 #define MiUnlockPfnDatabase(OldIrql) \ 00788 KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql) 00789 00790 #define MiTryToLockPfnDatabase(OldIrql) \ 00791 KeTryToAcquireQueuedSpinLock(LockQueuePfnLock, &OldIrql) 00792 00793 #define MiReleasePfnLock() \ 00794 KiReleaseQueuedSpinLock(&KeGetCurrentPrcb()->LockQueue[LockQueuePfnLock]) 00795 00796 #define MiLockSystemSpace(OldIrql) \ 00797 OldIrql = KeAcquireQueuedSpinLock(LockQueueSystemSpaceLock) 00798 00799 #define MiUnlockSystemSpace(OldIrql) \ 00800 KeReleaseQueuedSpinLock(LockQueueSystemSpaceLock, OldIrql) 00801 00802 #define MiLockSystemSpaceAtDpcLevel() \ 00803 KiAcquireQueuedSpinLock(&KeGetCurrentPrcb()->LockQueue[LockQueueSystemSpaceLock]) 00804 00805 #define MiUnlockSystemSpaceFromDpcLevel() \ 00806 KiReleaseQueuedSpinLock(&KeGetCurrentPrcb()->LockQueue[LockQueueSystemSpaceLock]) 00807 00808 #else 00809 00810 #define MiLockPfnDatabase(OldIrql) \ 00811 ExAcquireSpinLock(&MmPfnLock, &OldIrql) 00812 00813 #define MiUnlockPfnDatabase(OldIrql) \ 00814 ExReleaseSpinLock(&MmPfnLock, OldIrql) 00815 00816 #define MiTryToLockPfnDatabase(OldIrql) \ 00817 KeTryToAcquireSpinLock(&MmPfnLock, &OldIrql) 00818 00819 #define MiReleasePfnLock() \ 00820 KiReleaseSpinLock(&MmPfnLock) 00821 00822 #define MiLockSystemSpace(OldIrql) \ 00823 ExAcquireSpinLock(&MmSystemSpaceLock, &OldIrql) 00824 00825 #define MiUnlockSystemSpace(OldIrql) \ 00826 ExReleaseSpinLock(&MmSystemSpaceLock, OldIrql) 00827 00828 #define MiLockSystemSpaceAtDpcLevel() \ 00829 ExAcquireSpinLockAtDpcLevel(&MmSystemSpaceLock) 00830 00831 #define MiUnlockSystemSpaceFromDpcLevel() \ 00832 ExReleaseSpinLockFromDpcLevel(&MmSystemSpaceLock) 00833 00834 #endif 00835 00836 #if PFN_CONSISTENCY 00837 00838 #define CONSISTENCY_LOCK_PFN(OLDIRQL) LOCK_PFN(OLDIRQL) 00839 #define CONSISTENCY_UNLOCK_PFN(OLDIRQL) UNLOCK_PFN(OLDIRQL) 00840 00841 #define CONSISTENCY_LOCK_PFN2(OLDIRQL) LOCK_PFN2(OLDIRQL) 00842 #define CONSISTENCY_UNLOCK_PFN2(OLDIRQL) UNLOCK_PFN2(OLDIRQL) 00843 00844 #define PFN_CONSISTENCY_SET \ 00845 (MiPfnLockOwner = PsGetCurrentThread(), MiMapInPfnDatabase()) 00846 #define PFN_CONSISTENCY_UNSET \ 00847 (MiUnMapPfnDatabase(), MiPfnLockOwner = (PETHREAD)0) 00848 00849 VOID 00850 MiMapInPfnDatabase ( 00851 VOID 00852 ); 00853 00854 VOID 00855 MiUnMapPfnDatabase ( 00856 VOID 00857 ); 00858 00859 VOID 00860 MiSetModified ( 00861 IN PMMPFN Pfn1, 00862 IN ULONG Dirty 00863 ); 00864 00865 extern PMMPTE MiPfnStartPte; 00866 extern PFN_NUMBER MiPfnPtes; 00867 extern BOOLEAN MiPfnProtectionEnabled; 00868 extern PETHREAD MiPfnLockOwner; 00869 00870 #define PFN_LOCK_OWNED_BY_ME() (MiPfnLockOwner == PsGetCurrentThread()) 00871 00872 00873 #else // PFN_CONSISTENCY 00874 00875 #define CONSISTENCY_LOCK_PFN(OLDIRQL) 00876 #define CONSISTENCY_UNLOCK_PFN(OLDIRQL) 00877 00878 #define CONSISTENCY_LOCK_PFN2(OLDIRQL) 00879 #define CONSISTENCY_UNLOCK_PFN2(OLDIRQL) 00880 00881 #define PFN_CONSISTENCY_SET 00882 #define PFN_CONSISTENCY_UNSET 00883 00884 #endif // PFN_CONSISTENCY 00885 00886 #define LOCK_PFN(OLDIRQL) ASSERT (KeGetCurrentIrql() <= APC_LEVEL); \ 00887 MiLockPfnDatabase(OLDIRQL); \ 00888 PFN_CONSISTENCY_SET; 00889 00890 #define LOCK_PFN_WITH_TRY(OLDIRQL) \ 00891 ASSERT (KeGetCurrentIrql() <= APC_LEVEL); \ 00892 do { \ 00893 } while (MiTryToLockPfnDatabase(OLDIRQL) == FALSE); \ 00894 PFN_CONSISTENCY_SET; 00895 00896 #define UNLOCK_PFN(OLDIRQL) \ 00897 PFN_CONSISTENCY_UNSET; \ 00898 MiUnlockPfnDatabase(OLDIRQL); \ 00899 ASSERT(KeGetCurrentIrql() <= APC_LEVEL); 00900 00901 #define LOCK_PFN2(OLDIRQL) ASSERT (KeGetCurrentIrql() <= DISPATCH_LEVEL); \ 00902 MiLockPfnDatabase(OLDIRQL); \ 00903 PFN_CONSISTENCY_SET; 00904 00905 #define UNLOCK_PFN2(OLDIRQL) \ 00906 PFN_CONSISTENCY_UNSET; \ 00907 MiUnlockPfnDatabase(OLDIRQL); \ 00908 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL); 00909 00910 #define UNLOCK_PFN_AND_THEN_WAIT(OLDIRQL) \ 00911 { \ 00912 KIRQL XXX; \ 00913 ASSERT (KeGetCurrentIrql() == 2); \ 00914 ASSERT (OLDIRQL <= APC_LEVEL); \ 00915 KiLockDispatcherDatabase (&XXX); \ 00916 PFN_CONSISTENCY_UNSET; \ 00917 MiReleasePfnLock(); \ 00918 (KeGetCurrentThread())->WaitIrql = OLDIRQL; \ 00919 (KeGetCurrentThread())->WaitNext = TRUE; \ 00920 } 00921 00922 #define LOCK_AWE(PROCESS,OldIrql) \ 00923 ExAcquireSpinLock(&((PROCESS)->AweLock), &OldIrql) 00924 00925 #define UNLOCK_AWE(PROCESS,OldIrql) \ 00926 ExReleaseSpinLock(&((PROCESS)->AweLock), OldIrql) 00927 00928 extern KMUTANT MmSystemLoadLock; 00929 00930 #if DBG 00931 #define SYSLOAD_LOCK_OWNED_BY_ME() ((PETHREAD)MmSystemLoadLock.OwnerThread == PsGetCurrentThread()) 00932 #else 00933 #define SYSLOAD_LOCK_OWNED_BY_ME() 00934 #endif 00935 00936 #if DBG 00937 #define MM_PFN_LOCK_ASSERT() \ 00938 if (MmDebug & 0x80000) { \ 00939 ASSERT (KeGetCurrentIrql() == 2); \ 00940 } 00941 00942 extern PETHREAD MiExpansionLockOwner; 00943 00944 #define MM_SET_EXPANSION_OWNER() ASSERT (MiExpansionLockOwner == NULL); \ 00945 MiExpansionLockOwner = PsGetCurrentThread(); 00946 00947 #define MM_CLEAR_EXPANSION_OWNER() ASSERT (MiExpansionLockOwner == PsGetCurrentThread()); \ 00948 MiExpansionLockOwner = NULL; 00949 00950 #else 00951 #define MM_PFN_LOCK_ASSERT() 00952 #define MM_SET_EXPANSION_OWNER() 00953 #define MM_CLEAR_EXPANSION_OWNER() 00954 #endif //DBG 00955 00956 00957 #define LOCK_EXPANSION(OLDIRQL) ASSERT (KeGetCurrentIrql() <= APC_LEVEL); \ 00958 ExAcquireSpinLock (&MmExpansionLock, &OLDIRQL);\ 00959 MM_SET_EXPANSION_OWNER (); 00960 00961 #define UNLOCK_EXPANSION(OLDIRQL) MM_CLEAR_EXPANSION_OWNER (); \ 00962 ExReleaseSpinLock (&MmExpansionLock, OLDIRQL); \ 00963 ASSERT (KeGetCurrentIrql() <= APC_LEVEL); 00964 00965 #define UNLOCK_EXPANSION_AND_THEN_WAIT(OLDIRQL) \ 00966 { \ 00967 KIRQL XXX; \ 00968 ASSERT (KeGetCurrentIrql() == 2); \ 00969 ASSERT (OLDIRQL <= APC_LEVEL); \ 00970 KiLockDispatcherDatabase (&XXX); \ 00971 MM_CLEAR_EXPANSION_OWNER (); \ 00972 KiReleaseSpinLock (&MmExpansionLock); \ 00973 (KeGetCurrentThread())->WaitIrql = OLDIRQL; \ 00974 (KeGetCurrentThread())->WaitNext = TRUE; \ 00975 } 00976 00977 #if defined(_ALPHA_) && !defined(_AXP64_) 00978 #define LOCK_EXPANSION_IF_ALPHA(OLDIRQL) \ 00979 ExAcquireSpinLock (&MmExpansionLock, &OLDIRQL); \ 00980 MM_SET_EXPANSION_OWNER (); 00981 #else 00982 #define LOCK_EXPANSION_IF_ALPHA(OLDIRQL) 00983 #endif //ALPHA 00984 00985 00986 #if defined(_ALPHA_) && !defined(_AXP64_) 00987 #define UNLOCK_EXPANSION_IF_ALPHA(OLDIRQL) \ 00988 MM_CLEAR_EXPANSION_OWNER (); \ 00989 ExReleaseSpinLock ( &MmExpansionLock, OLDIRQL ) 00990 #else 00991 #define UNLOCK_EXPANSION_IF_ALPHA(OLDIRQL) 00992 #endif //ALPHA 00993 00994 00995 extern LIST_ENTRY MmLockConflictList; 00996 extern PETHREAD MmSystemLockOwner; 00997 00998 #define LOCK_SYSTEM_WS(OLDIRQL) \ 00999 ASSERT (KeGetCurrentIrql() <= APC_LEVEL); \ 01000 KeRaiseIrql(APC_LEVEL,&OLDIRQL); \ 01001 ExAcquireResourceExclusive(&MmSystemWsLock,TRUE); \ 01002 ASSERT (MmSystemLockOwner == NULL); \ 01003 MmSystemLockOwner = PsGetCurrentThread(); 01004 01005 #define UNLOCK_SYSTEM_WS(OLDIRQL) \ 01006 ASSERT (MmSystemLockOwner == PsGetCurrentThread()); \ 01007 MmSystemLockOwner = NULL; \ 01008 ExReleaseResource (&MmSystemWsLock); \ 01009 KeLowerIrql (OLDIRQL); \ 01010 ASSERT (KeGetCurrentIrql() <= APC_LEVEL); 01011 01012 #define UNLOCK_SYSTEM_WS_NO_IRQL() \ 01013 ASSERT (MmSystemLockOwner == PsGetCurrentThread()); \ 01014 MmSystemLockOwner = NULL; \ 01015 ExReleaseResource (&MmSystemWsLock); 01016 01017 #define MM_SYSTEM_WS_LOCK_ASSERT() \ 01018 ASSERT (PsGetCurrentThread() == MmSystemLockOwner); 01019 01020 #define LOCK_HYPERSPACE(OLDIRQL) \ 01021 ExAcquireSpinLock ( &(PsGetCurrentProcess())->HyperSpaceLock, OLDIRQL ); 01022 01023 01024 #define UNLOCK_HYPERSPACE(OLDIRQL) \ 01025 ExReleaseSpinLock ( &(PsGetCurrentProcess())->HyperSpaceLock, OLDIRQL ); 01026 01027 #if defined (_AXP64_) 01028 #define MI_WS_OWNER(PROCESS) ((PROCESS)->WorkingSetLock.Owner == KeGetCurrentThread()) 01029 #define MI_NOT_WS_OWNER(PROCESS) (!MI_WS_OWNER(PROCESS)) 01030 #else 01031 #define MI_WS_OWNER(PROCESS) 1 01032 #define MI_NOT_WS_OWNER(PROCESS) 1 01033 #endif 01034 01035 #define MI_MUTEX_ACQUIRED_UNSAFE 0x88 01036 01037 #define MI_IS_WS_UNSAFE(PROCESS) ((PROCESS)->WorkingSetLock.OldIrql == MI_MUTEX_ACQUIRED_UNSAFE) 01038 01039 #define LOCK_WS(PROCESS) \ 01040 ASSERT (MI_NOT_WS_OWNER(PROCESS)); \ 01041 ExAcquireFastMutex( &((PROCESS)->WorkingSetLock)); \ 01042 ASSERT (!MI_IS_WS_UNSAFE(PROCESS)); 01043 01044 #define LOCK_WS_UNSAFE(PROCESS) \ 01045 ASSERT (MI_NOT_WS_OWNER(PROCESS)); \ 01046 ASSERT (KeGetCurrentIrql() == APC_LEVEL); \ 01047 ExAcquireFastMutexUnsafe( &((PROCESS)->WorkingSetLock));\ 01048 (PROCESS)->WorkingSetLock.OldIrql = MI_MUTEX_ACQUIRED_UNSAFE; 01049 01050 #define MI_MUST_BE_UNSAFE(PROCESS) \ 01051 ASSERT (KeGetCurrentIrql() == APC_LEVEL); \ 01052 ASSERT (MI_WS_OWNER(PROCESS)); \ 01053 ASSERT (MI_IS_WS_UNSAFE(PROCESS)); 01054 01055 #define MI_MUST_BE_SAFE(PROCESS) \ 01056 ASSERT (MI_WS_OWNER(PROCESS)); \ 01057 ASSERT (!MI_IS_WS_UNSAFE(PROCESS)); 01058 #if 0 01059 01060 #define MI_MUST_BE_UNSAFE(PROCESS) \ 01061 if (KeGetCurrentIrql() != APC_LEVEL) { \ 01062 KeBugCheckEx(MEMORY_MANAGEMENT, 0x32, (ULONG_PTR)PROCESS, KeGetCurrentIrql(), 0); \ 01063 } \ 01064 if (!MI_WS_OWNER(PROCESS)) { \ 01065 KeBugCheckEx(MEMORY_MANAGEMENT, 0x33, (ULONG_PTR)PROCESS, 0, 0); \ 01066 } \ 01067 if (!MI_IS_WS_UNSAFE(PROCESS)) { \ 01068 KeBugCheckEx(MEMORY_MANAGEMENT, 0x34, (ULONG_PTR)PROCESS, 0, 0); \ 01069 } 01070 01071 #define MI_MUST_BE_SAFE(PROCESS) \ 01072 if (!MI_WS_OWNER(PROCESS)) { \ 01073 KeBugCheckEx(MEMORY_MANAGEMENT, 0x42, (ULONG_PTR)PROCESS, 0, 0); \ 01074 } \ 01075 if (MI_IS_WS_UNSAFE(PROCESS)) { \ 01076 KeBugCheckEx(MEMORY_MANAGEMENT, 0x43, (ULONG_PTR)PROCESS, 0, 0); \ 01077 } 01078 #endif 01079 01080 01081 #define UNLOCK_WS(PROCESS) \ 01082 MI_MUST_BE_SAFE(PROCESS); \ 01083 ExReleaseFastMutex(&((PROCESS)->WorkingSetLock)); 01084 01085 #define UNLOCK_WS_UNSAFE(PROCESS) \ 01086 MI_MUST_BE_UNSAFE(PROCESS); \ 01087 ExReleaseFastMutexUnsafe(&((PROCESS)->WorkingSetLock)); \ 01088 ASSERT (KeGetCurrentIrql() == APC_LEVEL); 01089 01090 #define LOCK_ADDRESS_SPACE(PROCESS) \ 01091 ExAcquireFastMutex( &((PROCESS)->AddressCreationLock)) 01092 01093 #define LOCK_WS_AND_ADDRESS_SPACE(PROCESS) \ 01094 LOCK_ADDRESS_SPACE(PROCESS); \ 01095 LOCK_WS_UNSAFE(PROCESS); 01096 01097 #define UNLOCK_WS_AND_ADDRESS_SPACE(PROCESS) \ 01098 UNLOCK_WS_UNSAFE(PROCESS); \ 01099 UNLOCK_ADDRESS_SPACE(PROCESS); 01100 01101 #define UNLOCK_ADDRESS_SPACE(PROCESS) \ 01102 ExReleaseFastMutex( &((PROCESS)->AddressCreationLock)) 01103 01104 // 01105 // The working set lock may have been acquired safely or unsafely. 01106 // Release and reacquire it regardless. 01107 // 01108 01109 #define UNLOCK_WS_REGARDLESS(PROCESS, WSHELDSAFE) \ 01110 ASSERT (MI_WS_OWNER (PROCESS)); \ 01111 if (MI_IS_WS_UNSAFE (PROCESS)) { \ 01112 UNLOCK_WS_UNSAFE (PROCESS); \ 01113 WSHELDSAFE = FALSE; \ 01114 } \ 01115 else { \ 01116 UNLOCK_WS (PROCESS); \ 01117 WSHELDSAFE = TRUE; \ 01118 } 01119 01120 #define LOCK_WS_REGARDLESS(PROCESS, WSHELDSAFE) \ 01121 if (WSHELDSAFE == TRUE) { \ 01122 LOCK_WS (PROCESS); \ 01123 } \ 01124 else { \ 01125 LOCK_WS_UNSAFE (PROCESS); \ 01126 } 01127 01128 #define ZERO_LARGE(LargeInteger) \ 01129 (LargeInteger).LowPart = 0; \ 01130 (LargeInteger).HighPart = 0; 01131 01132 //++ 01133 // 01134 // ULONG 01135 // MI_CHECK_BIT ( 01136 // IN PULONG ARRAY 01137 // IN ULONG BIT 01138 // ) 01139 // 01140 // Routine Description: 01141 // 01142 // The MI_CHECK_BIT macro checks to see if the specified bit is 01143 // set within the specified array. 01144 // 01145 // Arguments: 01146 // 01147 // ARRAY - First element of the array to check. 01148 // 01149 // BIT - bit number (first bit is 0) to check. 01150 // 01151 // Return Value: 01152 // 01153 // Returns the value of the bit (0 or 1). 01154 // 01155 //-- 01156 01157 #define MI_CHECK_BIT(ARRAY,BIT) \ 01158 (((ULONG)ARRAY[(BIT) / (sizeof(ULONG)*8)] >> ((BIT) & 0x1F)) & 1) 01159 01160 01161 //++ 01162 // 01163 // VOID 01164 // MI_SET_BIT ( 01165 // IN PULONG ARRAY 01166 // IN ULONG BIT 01167 // ) 01168 // 01169 // Routine Description: 01170 // 01171 // The MI_SET_BIT macro sets the specified bit within the 01172 // specified array. 01173 // 01174 // Arguments: 01175 // 01176 // ARRAY - First element of the array to set. 01177 // 01178 // BIT - bit number. 01179 // 01180 // Return Value: 01181 // 01182 // None. 01183 // 01184 //-- 01185 01186 #define MI_SET_BIT(ARRAY,BIT) \ 01187 (ULONG)ARRAY[(BIT) / (sizeof(ULONG)*8)] |= (1 << ((BIT) & 0x1F)) 01188 01189 01190 //++ 01191 // 01192 // VOID 01193 // MI_CLEAR_BIT ( 01194 // IN PULONG ARRAY 01195 // IN ULONG BIT 01196 // ) 01197 // 01198 // Routine Description: 01199 // 01200 // The MI_CLEAR_BIT macro sets the specified bit within the 01201 // specified array. 01202 // 01203 // Arguments: 01204 // 01205 // ARRAY - First element of the array to clear. 01206 // 01207 // BIT - bit number. 01208 // 01209 // Return Value: 01210 // 01211 // None. 01212 // 01213 //-- 01214 01215 #define MI_CLEAR_BIT(ARRAY,BIT) \ 01216 (ULONG)ARRAY[(BIT) / (sizeof(ULONG)*8)] &= ~(1 << ((BIT) & 0x1F)) 01217 01218 01219 #define MI_MAGIC_AWE_PTEFRAME 0xffffedcb 01220 01221 #define MI_PFN_IS_AWE(Pfn1) \ 01222 ((Pfn1->u2.ShareCount <= 3) && \ 01223 (Pfn1->u3.e1.PageLocation == ActiveAndValid) && \ 01224 (Pfn1->u3.e1.VerifierAllocation == 0) && \ 01225 (Pfn1->u3.e1.LargeSessionAllocation == 0) && \ 01226 (Pfn1->u3.e1.StartOfAllocation == 1) && \ 01227 (Pfn1->u3.e1.EndOfAllocation == 1) && \ 01228 (Pfn1->PteFrame == MI_MAGIC_AWE_PTEFRAME)) 01229 01230 01231 typedef ULONG WSLE_NUMBER, *PWSLE_NUMBER; 01232 01233 // 01234 // PFN database element. 01235 // 01236 01237 // 01238 // Define pseudo fields for start and end of allocation. 01239 // 01240 01241 #define StartOfAllocation ReadInProgress 01242 01243 #define EndOfAllocation WriteInProgress 01244 01245 #define LargeSessionAllocation PrototypePte 01246 01247 // 01248 // The PteFrame field size determines the largest physical page that 01249 // can be supported on the system. On a 4k page sized machine, 20 bits 01250 // limits it to 4GBs. 01251 // 01252 01253 typedef struct _MMPFNENTRY { 01254 ULONG Modified : 1; 01255 ULONG ReadInProgress : 1; 01256 ULONG WriteInProgress : 1; 01257 ULONG PrototypePte: 1; 01258 ULONG PageColor : 3; 01259 ULONG ParityError : 1; 01260 ULONG PageLocation : 3; 01261 ULONG InPageError : 1; 01262 ULONG VerifierAllocation : 1; 01263 ULONG RemovalRequested : 1; 01264 ULONG Reserved : 1; 01265 ULONG LockCharged : 1; 01266 ULONG DontUse : 16; //overlays USHORT for reference count field. 01267 } MMPFNENTRY; 01268 01269 #if defined (_X86PAE_) 01270 #pragma pack(1) 01271 #endif 01272 01273 typedef struct _MMPFN { 01274 union { 01275 PFN_NUMBER Flink; 01276 WSLE_NUMBER WsIndex; 01277 PKEVENT Event; 01278 NTSTATUS ReadStatus; 01279 struct _MMPFN *NextStackPfn; 01280 } u1; 01281 PMMPTE PteAddress; 01282 union { 01283 PFN_NUMBER Blink; 01284 ULONG ShareCount; 01285 ULONG SecondaryColorFlink; 01286 } u2; 01287 union { 01288 MMPFNENTRY e1; 01289 struct { 01290 USHORT ShortFlags; 01291 USHORT ReferenceCount; 01292 } e2; 01293 } u3; 01294 #if defined (_WIN64) 01295 ULONG UsedPageTableEntries; 01296 #endif 01297 MMPTE OriginalPte; 01298 PFN_NUMBER PteFrame; 01299 } MMPFN, *PMMPFN; 01300 01301 #if defined (_X86PAE_) 01302 #pragma pack() 01303 #endif 01304 01305 #if defined (_WIN64) 01306 01307 // 01308 // Note there are some places where these portable macros are not currently 01309 // used because we are not in the correct address space required. 01310 // 01311 01312 #define MI_CAPTURE_USED_PAGETABLE_ENTRIES(PFN) \ 01313 ASSERT ((PFN)->UsedPageTableEntries <= PTE_PER_PAGE); \ 01314 (PFN)->OriginalPte.u.Soft.UsedPageTableEntries = (PFN)->UsedPageTableEntries; 01315 01316 #define MI_RETRIEVE_USED_PAGETABLE_ENTRIES_FROM_PTE(RBL, PTE) \ 01317 ASSERT ((PTE)->u.Soft.UsedPageTableEntries <= PTE_PER_PAGE); \ 01318 (RBL)->UsedPageTableEntries = (ULONG)(((PMMPTE)(PTE))->u.Soft.UsedPageTableEntries); 01319 01320 #define MI_ZERO_USED_PAGETABLE_ENTRIES_IN_INPAGE_SUPPORT(INPAGE_SUPPORT) \ 01321 (INPAGE_SUPPORT)->UsedPageTableEntries = 0; 01322 01323 #define MI_ZERO_USED_PAGETABLE_ENTRIES_IN_PFN(PFN) (PFN)->UsedPageTableEntries = 0; 01324 01325 #define MI_INSERT_USED_PAGETABLE_ENTRIES_IN_PFN(PFN, INPAGE_SUPPORT) \ 01326 ASSERT ((INPAGE_SUPPORT)->UsedPageTableEntries <= PTE_PER_PAGE); \ 01327 (PFN)->UsedPageTableEntries = (INPAGE_SUPPORT)->UsedPageTableEntries; 01328 01329 #define MI_ZERO_USED_PAGETABLE_ENTRIES(PFN) \ 01330 (PFN)->UsedPageTableEntries = 0; 01331 01332 #define MI_GET_USED_PTES_HANDLE(VA) \ 01333 ((PVOID)MI_PFN_ELEMENT((PFN_NUMBER)MiGetPdeAddress(VA)->u.Hard.PageFrameNumber)) 01334 01335 #define MI_GET_USED_PTES_FROM_HANDLE(PFN) \ 01336 ((ULONG)(((PMMPFN)(PFN))->UsedPageTableEntries)) 01337 01338 #define MI_INCREMENT_USED_PTES_BY_HANDLE(PFN) \ 01339 (((PMMPFN)(PFN))->UsedPageTableEntries += 1); \ 01340 ASSERT (((PMMPFN)(PFN))->UsedPageTableEntries <= PTE_PER_PAGE) 01341 01342 #define MI_DECREMENT_USED_PTES_BY_HANDLE(PFN) \ 01343 (((PMMPFN)(PFN))->UsedPageTableEntries -= 1); \ 01344 ASSERT (((PMMPFN)(PFN))->UsedPageTableEntries < PTE_PER_PAGE) 01345 01346 #else 01347 01348 #define MI_CAPTURE_USED_PAGETABLE_ENTRIES(PFN) 01349 #define MI_RETRIEVE_USED_PAGETABLE_ENTRIES_FROM_PTE(RBL, PTE) 01350 #define MI_ZERO_USED_PAGETABLE_ENTRIES_IN_INPAGE_SUPPORT(INPAGE_SUPPORT) 01351 #define MI_ZERO_USED_PAGETABLE_ENTRIES_IN_PFN(PFN) 01352 01353 #define MI_INSERT_USED_PAGETABLE_ENTRIES_IN_PFN(PFN, INPAGE_SUPPORT) 01354 01355 #define MI_GET_USED_PTES_HANDLE(VA) ((PVOID)&MmWorkingSetList->UsedPageTableEntries[MiGetPpePdeOffset(VA)]) 01356 01357 #define MI_GET_USED_PTES_FROM_HANDLE(PDSHORT) ((ULONG)(*(PUSHORT)(PDSHORT))) 01358 01359 #define MI_INCREMENT_USED_PTES_BY_HANDLE(PDSHORT) ((*(PUSHORT)(PDSHORT)) += 1); \ 01360 ASSERT (((*(PUSHORT)(PDSHORT)) <= PTE_PER_PAGE)) 01361 01362 #define MI_DECREMENT_USED_PTES_BY_HANDLE(PDSHORT) ((*(PUSHORT)(PDSHORT)) -= 1); \ 01363 ASSERT (((*(PUSHORT)(PDSHORT)) < PTE_PER_PAGE)) 01364 01365 #endif 01366 01367 extern LOGICAL MmDynamicPfn; 01368 01369 extern FAST_MUTEX MmDynamicMemoryMutex; 01370 01371 extern PFN_NUMBER MmSystemLockPagesCount; 01372 01373 #if DBG 01374 01375 #define MI_LOCK_ID_COUNTER_MAX 64 01376 ULONG MiLockIds[MI_LOCK_ID_COUNTER_MAX]; 01377 01378 #define MI_MARK_PFN_AS_LOCK_CHARGED(Pfn, CallerId) \ 01379 ASSERT (Pfn->u3.e1.LockCharged == 0); \ 01380 ASSERT (CallerId < MI_LOCK_ID_COUNTER_MAX); \ 01381 MiLockIds[CallerId] += 1; \ 01382 Pfn->u3.e1.LockCharged = 1; 01383 01384 #define MI_UNMARK_PFN_AS_LOCK_CHARGED(Pfn, CallerId) \ 01385 ASSERT (Pfn->u3.e1.LockCharged == 1); \ 01386 ASSERT (CallerId < MI_LOCK_ID_COUNTER_MAX); \ 01387 MiLockIds[CallerId] += 1; \ 01388 Pfn->u3.e1.LockCharged = 0; 01389 01390 #else 01391 #define MI_MARK_PFN_AS_LOCK_CHARGED(Pfn, CallerId) 01392 #define MI_UNMARK_PFN_AS_LOCK_CHARGED(Pfn, CallerId) 01393 #endif 01394 01395 //++ 01396 // 01397 // VOID 01398 // MI_ADD_LOCKED_PAGE_CHARGE ( 01399 // IN PMMPFN Pfn 01400 // ) 01401 // 01402 // Routine Description: 01403 // 01404 // Charge the systemwide count of locked pages if this is the initial 01405 // lock for this page (multiple concurrent locks are only charged once). 01406 // 01407 // Arguments: 01408 // 01409 // Pfn - the PFN index to operate on. 01410 // 01411 // Return Value: 01412 // 01413 // None. 01414 // 01415 //-- 01416 // 01417 #define MI_ADD_LOCKED_PAGE_CHARGE(Pfn, CallerId) \ 01418 ASSERT (Pfn->u3.e2.ReferenceCount != 0); \ 01419 if (Pfn->u3.e2.ReferenceCount == 1) { \ 01420 if (Pfn->u2.ShareCount != 0) { \ 01421 ASSERT (Pfn->u3.e1.PageLocation == ActiveAndValid); \ 01422 MI_MARK_PFN_AS_LOCK_CHARGED(Pfn, CallerId); \ 01423 MmSystemLockPagesCount += 1; \ 01424 } \ 01425 else { \ 01426 ASSERT (Pfn->u3.e1.LockCharged == 1); \ 01427 } \ 01428 } 01429 01430 #define MI_ADD_LOCKED_PAGE_CHARGE_FOR_MODIFIED_PAGE(Pfn, CallerId) \ 01431 ASSERT (Pfn->u3.e1.PageLocation != ActiveAndValid); \ 01432 ASSERT (Pfn->u2.ShareCount == 0); \ 01433 if (Pfn->u3.e2.ReferenceCount == 0) { \ 01434 MI_MARK_PFN_AS_LOCK_CHARGED(Pfn, CallerId); \ 01435 MmSystemLockPagesCount += 1; \ 01436 } 01437 01438 #define MI_ADD_LOCKED_PAGE_CHARGE_FOR_TRANSITION_PAGE(Pfn, CallerId) \ 01439 ASSERT (Pfn->u3.e1.PageLocation == ActiveAndValid); \ 01440 ASSERT (Pfn->u2.ShareCount == 0); \ 01441 ASSERT (Pfn->u3.e2.ReferenceCount != 0); \ 01442 if (Pfn->u3.e2.ReferenceCount == 1) { \ 01443 MI_MARK_PFN_AS_LOCK_CHARGED(Pfn, CallerId); \ 01444 MmSystemLockPagesCount += 1; \ 01445 } 01446 01447 //++ 01448 // 01449 // VOID 01450 // MI_REMOVE_LOCKED_PAGE_CHARGE ( 01451 // IN PMMPFN Pfn 01452 // ) 01453 // 01454 // Routine Description: 01455 // 01456 // Remove the charge from the systemwide count of locked pages if this 01457 // is the last lock for this page (multiple concurrent locks are only 01458 // charged once). 01459 // 01460 // Arguments: 01461 // 01462 // Pfn - the PFN index to operate on. 01463 // 01464 // Return Value: 01465 // 01466 // None. 01467 // 01468 //-- 01469 // 01470 #define MI_REMOVE_LOCKED_PAGE_CHARGE(Pfn, CallerId) \ 01471 ASSERT (Pfn->u3.e2.ReferenceCount != 0); \ 01472 if (Pfn->u3.e2.ReferenceCount == 2) { \ 01473 if (Pfn->u2.ShareCount >= 1) { \ 01474 ASSERT (Pfn->u3.e1.PageLocation == ActiveAndValid); \ 01475 MI_UNMARK_PFN_AS_LOCK_CHARGED(Pfn, CallerId); \ 01476 MmSystemLockPagesCount -= 1; \ 01477 } \ 01478 else { \ 01479 /* \ 01480 * There are multiple referencers to this page and the \ 01481 * page is no longer valid in any process address space. \ 01482 * The systemwide lock count can only be decremented \ 01483 * by the last dereference. \ 01484 */ \ 01485 NOTHING; \ 01486 } \ 01487 } \ 01488 else if (Pfn->u3.e2.ReferenceCount == 1) { \ 01489 /* \ 01490 * This page has already been deleted from all process address \ 01491 * spaces. It is sitting in limbo (not on any list) awaiting \ 01492 * this last dereference. \ 01493 */ \ 01494 ASSERT (Pfn->u3.e1.PageLocation != ActiveAndValid); \ 01495 ASSERT (Pfn->u2.ShareCount == 0); \ 01496 MI_UNMARK_PFN_AS_LOCK_CHARGED(Pfn, CallerId); \ 01497 MmSystemLockPagesCount -= 1; \ 01498 } \ 01499 else { \ 01500 /* \ 01501 * There are still multiple referencers to this page (it may \ 01502 * or may not be resident in any process address space). \ 01503 * Since the systemwide lock count can only be decremented \ 01504 * by the last dereference (and this is not it), no action \ 01505 * is taken here. \ 01506 */ \ 01507 NOTHING; \ 01508 } 01509 01510 01511 //++ 01512 // 01513 // VOID 01514 // MI_ZERO_WSINDEX ( 01515 // IN PMMPFN Pfn 01516 // ) 01517 // 01518 // Routine Description: 01519 // 01520 // Zero the Working Set Index field of the argument PFN entry. 01521 // There is a subtlety here on systems where the WsIndex ULONG is 01522 // overlaid with an Event pointer and sizeof(ULONG) != sizeof(PKEVENT). 01523 // Note this will need to be updated if we ever decide to allocate bodies of 01524 // thread objects on 4GB boundaries. 01525 // 01526 // Arguments: 01527 // 01528 // Pfn - the PFN index to operate on. 01529 // 01530 // Return Value: 01531 // 01532 // None. 01533 // 01534 //-- 01535 // 01536 #define MI_ZERO_WSINDEX(Pfn) \ 01537 Pfn->u1.Event = NULL; 01538 01539 typedef enum _MMSHARE_TYPE { 01540 Normal, 01541 ShareCountOnly, 01542 AndValid 01543 } MMSHARE_TYPE; 01544 01545 typedef struct _MMWSLE_HASH { 01546 ULONG_PTR Key; 01547 WSLE_NUMBER Index; 01548 } MMWSLE_HASH, *PMMWSLE_HASH; 01549 01550 //++ 01551 // 01552 // WSLE_NUMBER 01553 // MI_WSLE_HASH ( 01554 // IN ULONG_PTR VirtualAddress, 01555 // IN PMMWSL WorkingSetList 01556 // ) 01557 // 01558 // Routine Description: 01559 // 01560 // Hash the address 01561 // 01562 // Arguments: 01563 // 01564 // VirtualAddress - the address to hash. 01565 // 01566 // WorkingSetList - the working set to hash the address into. 01567 // 01568 // Return Value: 01569 // 01570 // The hash key. 01571 // 01572 //-- 01573 // 01574 #define MI_WSLE_HASH(Address, Wsl) \ 01575 ((WSLE_NUMBER)(((ULONG_PTR)PAGE_ALIGN(Address) >> (PAGE_SHIFT - 2)) % \ 01576 ((Wsl)->HashTableSize - 1))) 01577 01578 // 01579 // Working Set List Entry. 01580 // 01581 01582 typedef struct _MMWSLENTRY { 01583 ULONG_PTR Valid : 1; 01584 ULONG_PTR LockedInWs : 1; 01585 ULONG_PTR LockedInMemory : 1; 01586 ULONG_PTR Protection : 5; 01587 ULONG_PTR SameProtectAsProto : 1; 01588 ULONG_PTR Direct : 1; 01589 ULONG_PTR Age : 2; 01590 #if MM_VIRTUAL_PAGE_FILLER 01591 ULONG_PTR Filler : MM_VIRTUAL_PAGE_FILLER; 01592 #endif 01593 ULONG_PTR VirtualPageNumber : MM_VIRTUAL_PAGE_SIZE; 01594 } MMWSLENTRY; 01595 01596 typedef struct _MMWSLE { 01597 union { 01598 PVOID VirtualAddress; 01599 ULONG_PTR Long; 01600 MMWSLENTRY e1; 01601 } u1; 01602 } MMWSLE; 01603 01604 #define MI_GET_PROTECTION_FROM_WSLE(Wsl) ((Wsl)->u1.e1.Protection) 01605 01606 typedef MMWSLE *PMMWSLE; 01607 01608 // 01609 // Working Set List. Must be quadword sized. 01610 // 01611 01612 typedef struct _MMWSL { 01613 SIZE_T Quota; 01614 WSLE_NUMBER FirstFree; 01615 WSLE_NUMBER FirstDynamic; 01616 WSLE_NUMBER LastEntry; 01617 WSLE_NUMBER NextSlot; // The next slot to trim 01618 PMMWSLE Wsle; 01619 SIZE_T NumberOfCommittedPageTables; 01620 WSLE_NUMBER LastInitializedWsle; 01621 WSLE_NUMBER NonDirectCount; 01622 PMMWSLE_HASH HashTable; 01623 ULONG HashTableSize; 01624 PKEVENT WaitingForImageMapping; 01625 PVOID HashTableStart; 01626 PVOID HighestPermittedHashAddress; 01627 01628 //MUST BE QUADWORD ALIGNED AT THIS POINT! 01629 01630 #if !defined (_WIN64) 01631 PVOID Align1; // to quadword align 01632 PVOID Align2; // to quadword align 01633 // 01634 // This must be at the end. 01635 // not used in system cache or session working set lists. 01636 // 01637 USHORT UsedPageTableEntries[MM_USER_PAGE_TABLE_PAGES]; 01638 #endif 01639 01640 #ifndef _WIN64 01641 ULONG CommittedPageTables[MM_USER_PAGE_TABLE_PAGES/(sizeof(ULONG)*8)]; 01642 #endif 01643 01644 } MMWSL, *PMMWSL; 01645 01646 #ifdef _MI_USE_CLAIMS_ 01647 01648 // 01649 // The claim estimate of unused pages in a working set is limited 01650 // to grow by this amount per estimation period. 01651 // 01652 01653 #define MI_CLAIM_INCR 30 01654 01655 #endif 01656 01657 // 01658 // The maximum number of different ages a page can be. 01659 // 01660 01661 #define MI_USE_AGE_COUNT 4 01662 #define MI_USE_AGE_MAX (MI_USE_AGE_COUNT - 1) 01663 01664 // 01665 // If more than this "percentage" of the working set is estimated to 01666 // be used then allow it to grow freely. 01667 // 01668 01669 #define MI_REPLACEMENT_FREE_GROWTH_SHIFT 5 01670 01671 // 01672 // If more than this "percentage" of the working set has been claimed 01673 // then force replacement in low memory. 01674 // 01675 01676 #define MI_REPLACEMENT_CLAIM_THRESHOLD_SHIFT 3 01677 01678 // 01679 // If more than this "percentage" of the working set is estimated to 01680 // be available then force replacement in low memory. 01681 // 01682 01683 #define MI_REPLACEMENT_EAVAIL_THRESHOLD_SHIFT 3 01684 01685 // 01686 // If while doing replacement a page is found of this age or older then 01687 // replace it. Otherwise the oldest is selected. 01688 // 01689 01690 #define MI_IMMEDIATE_REPLACEMENT_AGE 2 01691 01692 // 01693 // When trimming, use these ages for different passes. 01694 // 01695 01696 #define MI_MAX_TRIM_PASSES 4 01697 #define MI_PASS0_TRIM_AGE 2 01698 #define MI_PASS1_TRIM_AGE 1 01699 #define MI_PASS2_TRIM_AGE 1 01700 #define MI_PASS3_TRIM_AGE 1 01701 #define MI_PASS4_TRIM_AGE 0 01702 01703 // 01704 // If not a forced trim, trim pages older than this age. 01705 // 01706 01707 #define MI_TRIM_AGE_THRESHOLD 2 01708 01709 // 01710 // This "percentage" of a claim is up for grabs in a foreground process. 01711 // 01712 01713 #define MI_FOREGROUND_CLAIM_AVAILABLE_SHIFT 3 01714 01715 // 01716 // This "percentage" of a claim is up for grabs in a background process. 01717 // 01718 01719 #define MI_BACKGROUND_CLAIM_AVAILABLE_SHIFT 1 01720 01721 //++ 01722 // 01723 // DWORD 01724 // MI_CALC_NEXT_VALID_ESTIMATION_SLOT ( 01725 // DWORD Previous, 01726 // DWORD Minimum, 01727 // DWORD Maximum, 01728 // MI_NEXT_ESTIMATION_SLOT_CONST NextEstimationSlotConst, 01729 // PMMWSLE Wsle 01730 // ) 01731 // 01732 // Routine Description: 01733 // 01734 // We iterate through the working set array in a non-sequential 01735 // manner so that the sample is independent of any aging or trimming. 01736 // 01737 // This algorithm walks through the working set with a stride of 01738 // 2^MiEstimationShift elements. 01739 // 01740 // Arguments: 01741 // 01742 // Previous - Last slot used 01743 // 01744 // Minimum - Minimum acceptable slot (ie. the first dynamic one) 01745 // 01746 // Maximum - max slot number + 1 01747 // 01748 // NextEstimationSlotConst - for this algorithm it contains the stride 01749 // 01750 // Wsle - the working set array 01751 // 01752 // Return Value: 01753 // 01754 // Next slot. 01755 // 01756 // Environment: 01757 // 01758 // Kernel mode, APCs disabled, working set lock held and PFN lock held. 01759 // 01760 //-- 01761 01762 typedef struct _MI_NEXT_ESTIMATION_SLOT_CONST { 01763 WSLE_NUMBER Stride; 01764 } MI_NEXT_ESTIMATION_SLOT_CONST; 01765 01766 01767 #define MI_CALC_NEXT_ESTIMATION_SLOT_CONST(NextEstimationSlotConst, WorkingSetList) \ 01768 (NextEstimationSlotConst).Stride = 1 << MiEstimationShift; 01769 01770 #define MI_NEXT_VALID_ESTIMATION_SLOT(Previous, StartEntry, Minimum, Maximum, NextEstimationSlotConst, Wsle) \ 01771 ASSERT(((Previous) >= Minimum) && ((Previous) <= Maximum)); \ 01772 ASSERT(((StartEntry) >= Minimum) && ((StartEntry) <= Maximum)); \ 01773 do { \ 01774 (Previous) += (NextEstimationSlotConst).Stride; \ 01775 if ((Previous) > Maximum) { \ 01776 (Previous) = Minimum + ((Previous + 1) & (NextEstimationSlotConst.Stride - 1)); \ 01777 StartEntry += 1; \ 01778 (Previous) = StartEntry; \ 01779 } \ 01780 if ((Previous) > Maximum || (Previous) < Minimum) { \ 01781 StartEntry = Minimum; \ 01782 (Previous) = StartEntry; \ 01783 } \ 01784 } while (Wsle[Previous].u1.e1.Valid == 0); 01785 01786 //++ 01787 // 01788 // WSLE_NUMBER 01789 // MI_NEXT_VALID_AGING_SLOT ( 01790 // DWORD Previous, 01791 // DWORD Minimum, 01792 // DWORD Maximum, 01793 // PMMWSLE Wsle 01794 // ) 01795 // 01796 // Routine Description: 01797 // 01798 // This finds the next slot to valid slot to age. It walks 01799 // through the slots sequentialy. 01800 // 01801 // Arguments: 01802 // 01803 // Previous - Last slot used 01804 // 01805 // Minimum - Minimum acceptable slot (ie. the first dynamic one) 01806 // 01807 // Maximum - Max slot number + 1 01808 // 01809 // Wsle - the working set array 01810 // 01811 // Return Value: 01812 // 01813 // None. 01814 // 01815 // Environment: 01816 // 01817 // Kernel mode, APCs disabled, working set lock held and PFN lock held. 01818 // 01819 //-- 01820 01821 #define MI_NEXT_VALID_AGING_SLOT(Previous, Minimum, Maximum, Wsle) \ 01822 ASSERT(((Previous) >= Minimum) && ((Previous) <= Maximum)); \ 01823 do { \ 01824 (Previous) += 1; \ 01825 if ((Previous) > Maximum) { \ 01826 Previous = Minimum; \ 01827 } \ 01828 } while ((Wsle[Previous].u1.e1.Valid == 0)); 01829 01830 //++ 01831 // 01832 // ULONG 01833 // MI_CALCULATE_USAGE_ESTIMATE ( 01834 // IN ULONG *SampledAgeCounts 01835 // ) 01836 // 01837 // Routine Description: 01838 // 01839 // In Usage Estimation, we count the number of pages of each age in 01840 // a sample. The function turns the SampledAgeCounts into an 01841 // estimate of the unused pages. 01842 // 01843 // Arguments: 01844 // 01845 // SampledAgeCounts - counts of pages of each different age in the sample 01846 // 01847 // Return Value: 01848 // 01849 // The number of pages to walk in the working set to get a good 01850 // estimate of the number available. 01851 // 01852 //-- 01853 01854 #define MI_CALCULATE_USAGE_ESTIMATE(SampledAgeCounts) \ 01855 (((SampledAgeCounts)[1] + \ 01856 (SampledAgeCounts)[2] + (SampledAgeCounts)[3]) \ 01857 << MiEstimationShift) 01858 01859 //++ 01860 // 01861 // VOID 01862 // MI_RESET_WSLE_AGE ( 01863 // IN PMMPTE PointerPte, 01864 // IN PMMWSLE Wsle 01865 // ) 01866 // 01867 // Routine Description: 01868 // 01869 // Clear the age counter for the working set entry. 01870 // 01871 // Arguments: 01872 // 01873 // PointerPte - pointer to the working set list entry's PTE. 01874 // 01875 // Wsle - pointer to the working set list entry. 01876 // 01877 // Return Value: 01878 // 01879 // None. 01880 // 01881 //-- 01882 #define MI_RESET_WSLE_AGE(PointerPte, Wsle) \ 01883 (Wsle)->u1.e1.Age = 0; 01884 01885 //++ 01886 // 01887 // ULONG 01888 // MI_GET_WSLE_AGE ( 01889 // IN PMMPTE PointerPte, 01890 // IN PMMWSLE Wsle 01891 // ) 01892 // 01893 // Routine Description: 01894 // 01895 // Clear the age counter for the working set entry. 01896 // 01897 // Arguments: 01898 // 01899 // PointerPte - pointer to the working set list entry's pte 01900 // Wsle - pointer to the working set list entry 01901 // 01902 // Return Value: 01903 // 01904 // Age group of the working set entry 01905 // 01906 //-- 01907 #define MI_GET_WSLE_AGE(PointerPte, Wsle) \ 01908 ((Wsle)->u1.e1.Age) 01909 01910 //++ 01911 // 01912 // VOID 01913 // MI_INC_WSLE_AGE ( 01914 // IN PMMPTE PointerPte, 01915 // IN PMMWSLE Wsle, 01916 // ) 01917 // 01918 // Routine Description: 01919 // 01920 // Increment the age counter for the working set entry. 01921 // 01922 // Arguments: 01923 // 01924 // PointerPte - pointer to the working set list entry's PTE. 01925 // 01926 // Wsle - pointer to the working set list entry. 01927 // 01928 // Return Value: 01929 // 01930 // None 01931 // 01932 //-- 01933 01934 #define MI_INC_WSLE_AGE(PointerPte, Wsle) \ 01935 if ((Wsle)->u1.e1.Age < 3) { \ 01936 (Wsle)->u1.e1.Age += 1; \ 01937 } 01938 01939 //++ 01940 // 01941 // VOID 01942 // MI_UPDATE_USE_ESTIMATE ( 01943 // IN PMMPTE PointerPte, 01944 // IN PMMWSLE Wsle, 01945 // IN ULONG *SampledAgeCounts 01946 // ) 01947 // 01948 // Routine Description: 01949 // 01950 // Update the sampled age counts. 01951 // 01952 // Arguments: 01953 // 01954 // PointerPte - pointer to the working set list entry's PTE. 01955 // 01956 // Wsle - pointer to the working set list entry. 01957 // 01958 // SampledAgeCounts - array of age counts to be updated. 01959 // 01960 // Return Value: 01961 // 01962 // None 01963 // 01964 //-- 01965 01966 #define MI_UPDATE_USE_ESTIMATE(PointerPte, Wsle, SampledAgeCounts) \ 01967 (SampledAgeCounts)[(Wsle)->u1.e1.Age] += 1; 01968 01969 //++ 01970 // 01971 // BOOLEAN 01972 // MI_WS_GROWING_TOO_FAST ( 01973 // IN PMMSUPPORT VmSupport 01974 // ) 01975 // 01976 // Routine Description: 01977 // 01978 // Limit the growth rate of processes as the 01979 // available memory approaches zero. Note the caller must ensure that 01980 // MmAvailablePages is low enough so this calculation does not wrap. 01981 // 01982 // Arguments: 01983 // 01984 // VmSupport - a working set. 01985 // 01986 // Return Value: 01987 // 01988 // TRUE if the growth rate is too fast, FALSE otherwise. 01989 // 01990 //-- 01991 01992 #define MI_WS_GROWING_TOO_FAST(VmSupport) \ 01993 ((VmSupport)->GrowthSinceLastEstimate > \ 01994 (((MI_CLAIM_INCR * (MmAvailablePages*MmAvailablePages)) / (64*64)) + 1)) 01995 01996 // 01997 // Memory Management Object structures. 01998 // 01999 02000 #define SECTION_BASE_ADDRESS(_NtSection) \ 02001 (*((PVOID *)&(_NtSection)->PointerToRelocations)) 02002 02003 typedef enum _SECTION_CHECK_TYPE { 02004 CheckDataSection, 02005 CheckImageSection, 02006 CheckUserDataSection, 02007 CheckBothSection 02008 } SECTION_CHECK_TYPE; 02009 02010 typedef struct _MMEXTEND_INFO { 02011 UINT64 CommittedSize; 02012 ULONG ReferenceCount; 02013 } MMEXTEND_INFO, *PMMEXTEND_INFO; 02014 02015 typedef struct _SEGMENT { 02016 struct _CONTROL_AREA *ControlArea; 02017 PVOID SegmentBaseAddress; 02018 ULONG TotalNumberOfPtes; 02019 ULONG NonExtendedPtes; 02020 UINT64 SizeOfSegment; 02021 SIZE_T ImageCommitment; 02022 PSECTION_IMAGE_INFORMATION ImageInformation; 02023 PVOID SystemImageBase; 02024 SIZE_T NumberOfCommittedPages; 02025 MMPTE SegmentPteTemplate; 02026 PVOID BasedAddress; 02027 PMMEXTEND_INFO ExtendInfo; 02028 PMMPTE PrototypePte; 02029 MMPTE ThePtes[MM_PROTO_PTE_ALIGNMENT / PAGE_SIZE]; 02030 02031 } SEGMENT, *PSEGMENT; 02032 02033 typedef struct _EVENT_COUNTER { 02034 ULONG RefCount; 02035 KEVENT Event; 02036 LIST_ENTRY ListEntry; 02037 } EVENT_COUNTER, *PEVENT_COUNTER; 02038 02039 typedef struct _MMSECTION_FLAGS { 02040 unsigned BeingDeleted : 1; 02041 unsigned BeingCreated : 1; 02042 unsigned BeingPurged : 1; 02043 unsigned NoModifiedWriting : 1; 02044 unsigned FailAllIo : 1; 02045 unsigned Image : 1; 02046 unsigned Based : 1; 02047 unsigned File : 1; 02048 unsigned Networked : 1; 02049 unsigned NoCache : 1; 02050 unsigned PhysicalMemory : 1; 02051 unsigned CopyOnWrite : 1; 02052 unsigned Reserve : 1; // not a spare bit! 02053 unsigned Commit : 1; 02054 unsigned FloppyMedia : 1; 02055 unsigned WasPurged : 1; 02056 unsigned UserReference : 1; 02057 unsigned GlobalMemory : 1; 02058 unsigned DeleteOnClose : 1; 02059 unsigned FilePointerNull : 1; 02060 unsigned DebugSymbolsLoaded : 1; 02061 unsigned SetMappedFileIoComplete : 1; 02062 unsigned CollidedFlush : 1; 02063 unsigned NoChange : 1; 02064 unsigned HadUserReference : 1; 02065 unsigned ImageMappedInSystemSpace : 1; 02066 unsigned filler0 : 1; 02067 unsigned Accessed : 1; 02068 unsigned GlobalOnlyPerSession : 1; 02069 unsigned filler : 3; 02070 } MMSECTION_FLAGS; 02071 02072 typedef struct _CONTROL_AREA { // must be quadword sized. 02073 PSEGMENT Segment; 02074 LIST_ENTRY DereferenceList; 02075 ULONG NumberOfSectionReferences; 02076 ULONG NumberOfPfnReferences; 02077 ULONG NumberOfMappedViews; 02078 USHORT NumberOfSubsections; 02079 USHORT FlushInProgressCount; 02080 ULONG NumberOfUserReferences; 02081 union { 02082 ULONG LongFlags; 02083 MMSECTION_FLAGS Flags; 02084 } u; 02085 PFILE_OBJECT FilePointer; 02086 PEVENT_COUNTER WaitingForDeletion; 02087 USHORT ModifiedWriteCount; 02088 USHORT NumberOfSystemCacheViews; 02089 SIZE_T PagedPoolUsage; 02090 SIZE_T NonPagedPoolUsage; 02091 } CONTROL_AREA, *PCONTROL_AREA; 02092 02093 typedef struct _LARGE_CONTROL_AREA { // must be quadword sized. 02094 PSEGMENT Segment; 02095 LIST_ENTRY DereferenceList; 02096 ULONG NumberOfSectionReferences; 02097 ULONG NumberOfPfnReferences; 02098 ULONG NumberOfMappedViews; 02099 USHORT NumberOfSubsections; 02100 USHORT FlushInProgressCount; 02101 ULONG NumberOfUserReferences; 02102 union { 02103 ULONG LongFlags; 02104 MMSECTION_FLAGS Flags; 02105 } u; 02106 PFILE_OBJECT FilePointer; 02107 PEVENT_COUNTER WaitingForDeletion; 02108 USHORT ModifiedWriteCount; 02109 USHORT NumberOfSystemCacheViews; 02110 SIZE_T PagedPoolUsage; 02111 SIZE_T NonPagedPoolUsage; 02112 LIST_ENTRY UserGlobalList; 02113 ULONG SessionId; 02114 ULONG Pad; 02115 } LARGE_CONTROL_AREA, *PLARGE_CONTROL_AREA; 02116 02117 typedef struct _MMSUBSECTION_FLAGS { 02118 unsigned ReadOnly : 1; 02119 unsigned ReadWrite : 1; 02120 unsigned CopyOnWrite : 1; 02121 unsigned GlobalMemory: 1; 02122 unsigned Protection : 5; 02123 unsigned LargePages : 1; 02124 unsigned StartingSector4132 : 10; // 2 ** (42+12) == 4MB*4GB == 16K TB 02125 unsigned SectorEndOffset : 12; 02126 } MMSUBSECTION_FLAGS; 02127 02128 typedef struct _SUBSECTION { // Must start on quadword boundary and be quad sized 02129 PCONTROL_AREA ControlArea; 02130 union { 02131 ULONG LongFlags; 02132 MMSUBSECTION_FLAGS SubsectionFlags; 02133 } u; 02134 ULONG StartingSector; 02135 ULONG NumberOfFullSectors; // (4GB-1) * 4K == 16TB-4K limit per subsection 02136 PMMPTE SubsectionBase; 02137 ULONG UnusedPtes; 02138 ULONG PtesInSubsection; 02139 struct _SUBSECTION *NextSubsection; 02140 } SUBSECTION, *PSUBSECTION; 02141 02142 #define MI_MAXIMUM_SECTION_SIZE ((UINT64)16*1024*1024*1024*1024*1024 - (1<<MM4K_SHIFT)) 02143 02144 #if DBG 02145 VOID 02146 MiSubsectionConsistent( 02147 IN PSUBSECTION Subsection 02148 ); 02149 #endif 02150 02151 //++ 02152 //ULONG 02153 //Mi4KStartForSubsection ( 02154 // IN PLARGE_INTEGER address, 02155 // IN OUT PSUBSECTION subsection 02156 // ); 02157 // 02158 // Routine Description: 02159 // 02160 // This macro sets into the specified subsection the supplied information 02161 // indicating the start address (in 4K units) of this portion of the file. 02162 // 02163 // Arguments 02164 // 02165 // address - Supplies the 64-bit address (in 4K units) of the start of this 02166 // portion of the file. 02167 // 02168 // subsection - Supplies the subsection address to store the address in. 02169 // 02170 // Return Value: 02171 // 02172 // None. 02173 // 02174 //-- 02175 02176 #define Mi4KStartForSubsection(address, subsection) \ 02177 subsection->StartingSector = ((PLARGE_INTEGER)address)->LowPart; \ 02178 subsection->u.SubsectionFlags.StartingSector4132 = \ 02179 (((PLARGE_INTEGER)(address))->HighPart & 0x3ff); 02180 02181 //++ 02182 //ULONG 02183 //Mi4KStartFromSubsection ( 02184 // IN OUT PLARGE_INTEGER address, 02185 // IN PSUBSECTION subsection 02186 // ); 02187 // 02188 // Routine Description: 02189 // 02190 // This macro gets the start 4K offset from the specified subsection. 02191 // 02192 // Arguments 02193 // 02194 // address - Supplies the 64-bit address (in 4K units) to place the 02195 // start of this subsection into. 02196 // 02197 // subsection - Supplies the subsection address to get the address from. 02198 // 02199 // Return Value: 02200 // 02201 // None. 02202 // 02203 //-- 02204 02205 #define Mi4KStartFromSubsection(address, subsection) \ 02206 ((PLARGE_INTEGER)address)->LowPart = subsection->StartingSector; \ 02207 ((PLARGE_INTEGER)address)->HighPart = subsection->u.SubsectionFlags.StartingSector4132; 02208 02209 typedef struct _MMDEREFERENCE_SEGMENT_HEADER { 02210 KSPIN_LOCK Lock; 02211 KSEMAPHORE Semaphore; 02212 LIST_ENTRY ListHead; 02213 } MMDEREFERENCE_SEGMENT_HEADER; 02214 02215 // 02216 // This entry is used for calling the segment dereference thread 02217 // to perform page file expansion. It has a similar structure 02218 // to a control area to allow either a control area or a page file 02219 // expansion entry to be placed on the list. Note that for a control 02220 // area the segment pointer is valid whereas for page file expansion 02221 // it is null. 02222 // 02223 02224 typedef struct _MMPAGE_FILE_EXPANSION { 02225 PSEGMENT Segment; 02226 LIST_ENTRY DereferenceList; 02227 SIZE_T RequestedExpansionSize; 02228 SIZE_T ActualExpansion; 02229 KEVENT Event; 02230 ULONG InProgress; 02231 ULONG PageFileNumber; 02232 } MMPAGE_FILE_EXPANSION, *PMMPAGE_FILE_EXPANSION; 02233 02234 #define MI_EXTEND_ANY_PAGEFILE ((ULONG)-1) 02235 02236 typedef struct _MMWORKING_SET_EXPANSION_HEAD { 02237 LIST_ENTRY ListHead; 02238 } MMWORKING_SET_EXPANSION_HEAD; 02239 02240 #define SUBSECTION_READ_ONLY 1L 02241 #define SUBSECTION_READ_WRITE 2L 02242 #define SUBSECTION_COPY_ON_WRITE 4L 02243 #define SUBSECTION_SHARE_ALLOW 8L 02244 02245 typedef struct _MMFLUSH_BLOCK { 02246 LARGE_INTEGER ErrorOffset; 02247 IO_STATUS_BLOCK IoStatus; 02248 KEVENT IoEvent; 02249 ULONG IoCount; 02250 } MMFLUSH_BLOCK, *PMMFLUSH_BLOCK; 02251 02252 typedef struct _MMINPAGE_SUPPORT { 02253 KEVENT Event; 02254 IO_STATUS_BLOCK IoStatus; 02255 LARGE_INTEGER ReadOffset; 02256 ULONG WaitCount; 02257 #if defined (_WIN64) 02258 ULONG UsedPageTableEntries; 02259 #endif 02260 union { 02261 PETHREAD Thread; 02262 PMMFLUSH_BLOCK Flush; 02263 } u; 02264 PFILE_OBJECT FilePointer; 02265 PMMPTE BasePte; 02266 PMMPFN Pfn; 02267 LOGICAL Completed; 02268 MDL Mdl; 02269 PFN_NUMBER Page[MM_MAXIMUM_READ_CLUSTER_SIZE + 1]; 02270 LIST_ENTRY ListEntry; 02271 #if defined (_PREFETCH_) 02272 PMDL PrefetchMdl; 02273 #endif 02274 } MMINPAGE_SUPPORT, *PMMINPAGE_SUPPORT; 02275 02276 #if defined (_PREFETCH_) 02277 #define MI_PF_DUMMY_PAGE_PTE ((PMMPTE)0x23452345) 02278 #endif 02279 02280 typedef struct _MMPAGE_READ { 02281 LARGE_INTEGER ReadOffset; 02282 PFILE_OBJECT FilePointer; 02283 PMMPTE BasePte; 02284 PMMPFN Pfn; 02285 MDL Mdl; 02286 PFN_NUMBER Page[MM_MAXIMUM_READ_CLUSTER_SIZE + 1]; 02287 } MMPAGE_READ, *PMMPAGE_READ; 02288 02289 // 02290 // Address Node. 02291 // 02292 02293 typedef struct _MMADDRESS_NODE { 02294 ULONG_PTR StartingVpn; 02295 ULONG_PTR EndingVpn; 02296 struct _MMADDRESS_NODE *Parent; 02297 struct _MMADDRESS_NODE *LeftChild; 02298 struct _MMADDRESS_NODE *RightChild; 02299 } MMADDRESS_NODE, *PMMADDRESS_NODE; 02300 02301 typedef struct _SECTION { 02302 MMADDRESS_NODE Address; 02303 PSEGMENT Segment; 02304 LARGE_INTEGER SizeOfSection; 02305 union { 02306 ULONG LongFlags; 02307 MMSECTION_FLAGS Flags; 02308 } u; 02309 ULONG InitialPageProtection; 02310 } SECTION, *PSECTION; 02311 02312 // 02313 // Banked memory descriptor. Pointed to by VAD which has 02314 // the PhysicalMemory flags set and the Banked pointer field as 02315 // non-NULL. 02316 // 02317 02318 typedef struct _MMBANKED_SECTION { 02319 PFN_NUMBER BasePhysicalPage; 02320 PMMPTE BasedPte; 02321 ULONG BankSize; 02322 ULONG BankShift; //shift for PTEs to calculate bank number 02323 PBANKED_SECTION_ROUTINE BankedRoutine; 02324 PVOID Context; 02325 PMMPTE CurrentMappedPte; 02326 MMPTE BankTemplate[1]; 02327 } MMBANKED_SECTION, *PMMBANKED_SECTION; 02328 02329 02330 // 02331 // Virtual address descriptor 02332 // 02333 // ***** NOTE ********** 02334 // The first part of a virtual address descriptor is a MMADDRESS_NODE!!! 02335 // 02336 02337 #if defined (_WIN64) 02338 02339 #define COMMIT_SIZE 51 02340 02341 #if ((COMMIT_SIZE + PAGE_SHIFT) < 63) 02342 #error COMMIT_SIZE too small 02343 #endif 02344 02345 #else 02346 #define COMMIT_SIZE 19 02347 02348 #if ((COMMIT_SIZE + PAGE_SHIFT) < 31) 02349 #error COMMIT_SIZE too small 02350 #endif 02351 #endif 02352 02353 #define MM_MAX_COMMIT (((ULONG_PTR) 1 << COMMIT_SIZE) - 1) 02354 02355 #define MM_VIEW_UNMAP 0 02356 #define MM_VIEW_SHARE 1 02357 02358 typedef struct _MMVAD_FLAGS { 02359 ULONG_PTR CommitCharge : COMMIT_SIZE; //limits system to 4k pages or bigger! 02360 ULONG_PTR PhysicalMapping : 1; 02361 ULONG_PTR ImageMap : 1; 02362 ULONG_PTR UserPhysicalPages : 1; 02363 ULONG_PTR NoChange : 1; 02364 ULONG_PTR WriteWatch : 1; 02365 ULONG_PTR Protection : 5; 02366 ULONG_PTR LargePages : 1; 02367 ULONG_PTR MemCommit: 1; 02368 ULONG_PTR PrivateMemory : 1; //used to tell VAD from VAD_SHORT 02369 } MMVAD_FLAGS; 02370 02371 typedef struct _MMVAD_FLAGS2 { 02372 unsigned FileOffset : 24; // number of 64k units into file 02373 unsigned SecNoChange : 1; // set if SEC_NOCHANGE specified 02374 unsigned OneSecured : 1; // set if u3 field is a range 02375 unsigned MultipleSecured : 1; // set if u3 field is a list head 02376 unsigned ReadOnly : 1; // protected as ReadOnly 02377 unsigned StoredInVad : 1; // set if secure is stored in VAD 02378 unsigned ExtendableFile : 1; 02379 unsigned Inherit : 1; //1 = ViewShare, 0 = ViewUnmap 02380 unsigned CopyOnWrite : 1; 02381 } MMVAD_FLAGS2; 02382 02383 typedef struct _MMADDRESS_LIST { 02384 ULONG_PTR StartVpn; 02385 ULONG_PTR EndVpn; 02386 } MMADDRESS_LIST, *PMMADDRESS_LIST; 02387 02388 typedef struct _MMSECURE_ENTRY { 02389 union { 02390 ULONG_PTR LongFlags2; 02391 MMVAD_FLAGS2 VadFlags2; 02392 } u2; 02393 ULONG_PTR StartVpn; 02394 ULONG_PTR EndVpn; 02395 LIST_ENTRY List; 02396 } MMSECURE_ENTRY, *PMMSECURE_ENTRY; 02397 02398 typedef struct _MMVAD { 02399 ULONG_PTR StartingVpn; 02400 ULONG_PTR EndingVpn; 02401 struct _MMVAD *Parent; 02402 struct _MMVAD *LeftChild; 02403 struct _MMVAD *RightChild; 02404 union { 02405 ULONG_PTR LongFlags; 02406 MMVAD_FLAGS VadFlags; 02407 } u; 02408 PCONTROL_AREA ControlArea; 02409 PMMPTE FirstPrototypePte; 02410 PMMPTE LastContiguousPte; 02411 union { 02412 ULONG LongFlags2; 02413 MMVAD_FLAGS2 VadFlags2; 02414 } u2; 02415 union { 02416 LIST_ENTRY List; 02417 MMADDRESS_LIST Secured; 02418 } u3; 02419 union { 02420 PMMBANKED_SECTION Banked; 02421 PMMEXTEND_INFO ExtendedInfo; 02422 } u4; 02423 } MMVAD, *PMMVAD; 02424 02425 02426 typedef struct _MMVAD_SHORT { 02427 ULONG_PTR StartingVpn; 02428 ULONG_PTR EndingVpn; 02429 struct _MMVAD *Parent; 02430 struct _MMVAD *LeftChild; 02431 struct _MMVAD *RightChild; 02432 union { 02433 ULONG_PTR LongFlags; 02434 MMVAD_FLAGS VadFlags; 02435 } u; 02436 } MMVAD_SHORT, *PMMVAD_SHORT; 02437 02438 #define MI_GET_PROTECTION_FROM_VAD(_Vad) ((ULONG)(_Vad)->u.VadFlags.Protection) 02439 02440 typedef struct _MI_PHYSICAL_VIEW { 02441 LIST_ENTRY ListEntry; 02442 PMMVAD Vad; 02443 PCHAR StartVa; 02444 PCHAR EndVa; 02445 PRTL_BITMAP BitMap; // Only initialized if Vad->u.VadFlags.WriteWatch == 1 02446 } MI_PHYSICAL_VIEW, *PMI_PHYSICAL_VIEW; 02447 02448 #define MI_PHYSICAL_VIEW_KEY 'vpmM' 02449 #define MI_WRITEWATCH_VIEW_KEY 'wWmM' 02450 02451 // 02452 // Stuff for support of Write Watch. 02453 // 02454 02455 extern ULONG_PTR MiActiveWriteWatch; 02456 02457 VOID 02458 MiCaptureWriteWatchDirtyBit ( 02459 IN PEPROCESS Process, 02460 IN PVOID VirtualAddress 02461 ); 02462 02463 VOID 02464 MiMarkProcessAsWriteWatch ( 02465 IN PEPROCESS Process 02466 ); 02467 02468 // 02469 // Stuff for support of POSIX Fork. 02470 // 02471 02472 02473 typedef struct _MMCLONE_BLOCK { 02474 MMPTE ProtoPte; 02475 LONG CloneRefCount; 02476 } MMCLONE_BLOCK; 02477 02478 typedef MMCLONE_BLOCK *PMMCLONE_BLOCK; 02479 02480 typedef struct _MMCLONE_HEADER { 02481 ULONG NumberOfPtes; 02482 ULONG NumberOfProcessReferences; 02483 PMMCLONE_BLOCK ClonePtes; 02484 } MMCLONE_HEADER, *PMMCLONE_HEADER; 02485 02486 02487 typedef struct _MMCLONE_DESCRIPTOR { 02488 ULONG_PTR StartingVpn; 02489 ULONG_PTR EndingVpn; 02490 struct _MMCLONE_DESCRIPTOR *Parent; 02491 struct _MMCLONE_DESCRIPTOR *LeftChild; 02492 struct _MMCLONE_DESCRIPTOR *RightChild; 02493 PMMCLONE_HEADER CloneHeader; 02494 ULONG NumberOfPtes; 02495 ULONG NumberOfReferences; 02496 SIZE_T PagedPoolQuotaCharge; 02497 } MMCLONE_DESCRIPTOR, *PMMCLONE_DESCRIPTOR; 02498 02499 // 02500 // The following macro will allocate and initialize a bitmap from the 02501 // specified pool of the specified size 02502 // 02503 // VOID 02504 // MiCreateBitMap ( 02505 // OUT PRTL_BITMAP *BitMapHeader, 02506 // IN SIZE_T SizeOfBitMap, 02507 // IN POOL_TYPE PoolType 02508 // ); 02509 // 02510 02511 #define MiCreateBitMap(BMH,S,P) { \ 02512 ULONG _S; \ 02513 _S = sizeof(RTL_BITMAP) + (ULONG)((((S) + 31) / 32) * 4); \ 02514 *(BMH) = (PRTL_BITMAP)ExAllocatePoolWithTag( (P), _S, ' mM'); \ 02515 if (*(BMH)) { \ 02516 RtlInitializeBitMap( *(BMH), (PULONG)((*(BMH))+1), (ULONG)S); \ 02517 } \ 02518 } 02519 02520 #define MiRemoveBitMap(BMH) { \ 02521 ExFreePool(*(BMH)); \ 02522 *(BMH) = NULL; \ 02523 } 02524 02525 #define MI_INITIALIZE_ZERO_MDL(MDL) { \ 02526 MDL->Next = (PMDL) NULL; \ 02527 MDL->MdlFlags = 0; \ 02528 MDL->StartVa = NULL; \ 02529 MDL->ByteOffset = 0; \ 02530 MDL->ByteCount = 0; \ 02531 } 02532 02533 // 02534 // Page File structures. 02535 // 02536 02537 typedef struct _MMMOD_WRITER_LISTHEAD { 02538 LIST_ENTRY ListHead; 02539 KEVENT Event; 02540 } MMMOD_WRITER_LISTHEAD, *PMMMOD_WRITER_LISTHEAD; 02541 02542 typedef struct _MMMOD_WRITER_MDL_ENTRY { 02543 LIST_ENTRY Links; 02544 LARGE_INTEGER WriteOffset; 02545 union { 02546 IO_STATUS_BLOCK IoStatus; 02547 LARGE_INTEGER LastByte; 02548 } u; 02549 PIRP Irp; 02550 ULONG_PTR LastPageToWrite; 02551 PMMMOD_WRITER_LISTHEAD PagingListHead; 02552 PLIST_ENTRY CurrentList; 02553 struct _MMPAGING_FILE *PagingFile; 02554 PFILE_OBJECT File; 02555 PCONTROL_AREA ControlArea; 02556 PERESOURCE FileResource; 02557 MDL Mdl; 02558 PFN_NUMBER Page[1]; 02559 } MMMOD_WRITER_MDL_ENTRY, *PMMMOD_WRITER_MDL_ENTRY; 02560 02561 02562 #define MM_PAGING_FILE_MDLS 2 02563 02564 typedef struct _MMPAGING_FILE { 02565 PFN_NUMBER Size; 02566 PFN_NUMBER MaximumSize; 02567 PFN_NUMBER MinimumSize; 02568 PFN_NUMBER FreeSpace; 02569 PFN_NUMBER CurrentUsage; 02570 PFN_NUMBER PeakUsage; 02571 PFN_NUMBER Hint; 02572 PFN_NUMBER HighestPage; 02573 PMMMOD_WRITER_MDL_ENTRY Entry[MM_PAGING_FILE_MDLS]; 02574 PRTL_BITMAP Bitmap; 02575 PFILE_OBJECT File; 02576 UNICODE_STRING PageFileName; 02577 ULONG PageFileNumber; 02578 BOOLEAN Extended; 02579 BOOLEAN HintSetToZero; 02580 } MMPAGING_FILE, *PMMPAGING_FILE; 02581 02582 typedef struct _MMINPAGE_SUPPORT_LIST { 02583 LIST_ENTRY ListHead; 02584 ULONG Count; 02585 } MMINPAGE_SUPPORT_LIST, *PMMINPAGE_SUPPORT_LIST; 02586 02587 typedef struct _MMEVENT_COUNT_LIST { 02588 LIST_ENTRY ListHead; 02589 ULONG Count; 02590 } MMEVENT_COUNT_LIST, *PMMEVENT_COUNT_LIST; 02591 02592 // 02593 // System PTE structures. 02594 // 02595 02596 #define MM_SYS_PTE_TABLES_MAX 5 02597 02598 typedef enum _MMSYSTEM_PTE_POOL_TYPE { 02599 SystemPteSpace, 02600 NonPagedPoolExpansion, 02601 MaximumPtePoolTypes 02602 } MMSYSTEM_PTE_POOL_TYPE; 02603 02604 typedef struct _MMFREE_POOL_ENTRY { 02605 LIST_ENTRY List; 02606 PFN_NUMBER Size; 02607 ULONG Signature; 02608 struct _MMFREE_POOL_ENTRY *Owner; 02609 } MMFREE_POOL_ENTRY, *PMMFREE_POOL_ENTRY; 02610 02611 02612 typedef struct _MMLOCK_CONFLICT { 02613 LIST_ENTRY List; 02614 PETHREAD Thread; 02615 } MMLOCK_CONFLICT, *PMMLOCK_CONFLICT; 02616 02617 // 02618 // System view structures 02619 // 02620 02621 typedef struct _MMVIEW { 02622 ULONG_PTR Entry; 02623 PCONTROL_AREA ControlArea; 02624 } MMVIEW, *PMMVIEW; 02625 02626 // 02627 // The MMSESSION structure represents kernel memory that is only valid on a 02628 // per-session basis, thus the calling thread must be in the proper session 02629 // to access this structure. 02630 // 02631 02632 typedef struct _MMSESSION { 02633 02634 // 02635 // Never refer to the SystemSpaceViewLock directly - always use the pointer 02636 // following it or you will break support for multiple concurrent sessions. 02637 // 02638 02639 FAST_MUTEX SystemSpaceViewLock; 02640 02641 // 02642 // This points to the mutex above and is needed because the MMSESSION 02643 // is mapped in session space on Hydra and the mutex needs to be globally 02644 // visible for proper KeWaitForSingleObject & KeSetEvent operation. 02645 // 02646 02647 PFAST_MUTEX SystemSpaceViewLockPointer; 02648 PCHAR SystemSpaceViewStart; 02649 PMMVIEW SystemSpaceViewTable; 02650 ULONG SystemSpaceHashSize; 02651 ULONG SystemSpaceHashEntries; 02652 ULONG SystemSpaceHashKey; 02653 PRTL_BITMAP SystemSpaceBitMap; 02654 02655 } MMSESSION, *PMMSESSION; 02656 02657 extern MMSESSION MmSession; 02658 02659 #define LOCK_SYSTEM_VIEW_SPACE(_Session) \ 02660 ExAcquireFastMutex (_Session->SystemSpaceViewLockPointer) 02661 02662 #define UNLOCK_SYSTEM_VIEW_SPACE(_Session) \ 02663 ExReleaseFastMutex (_Session->SystemSpaceViewLockPointer) 02664 02665 // 02666 // List for flushing TBs singularly. 02667 // 02668 02669 typedef struct _MMPTE_FLUSH_LIST { 02670 ULONG Count; 02671 PMMPTE FlushPte[MM_MAXIMUM_FLUSH_COUNT]; 02672 PVOID FlushVa[MM_MAXIMUM_FLUSH_COUNT]; 02673 } MMPTE_FLUSH_LIST, *PMMPTE_FLUSH_LIST; 02674 02675 typedef struct _LOCK_TRACKER { 02676 LIST_ENTRY ListEntry; 02677 PMDL Mdl; 02678 PVOID StartVa; 02679 PFN_NUMBER Count; 02680 ULONG Offset; 02681 ULONG Length; 02682 PFN_NUMBER Page; 02683 PVOID CallingAddress; 02684 PVOID CallersCaller; 02685 LIST_ENTRY GlobalListEntry; 02686 ULONG Who; 02687 PEPROCESS Process; 02688 } LOCK_TRACKER, *PLOCK_TRACKER; 02689 02690 extern LOGICAL MmTrackLockedPages; 02691 extern BOOLEAN MiTrackingAborted; 02692 02693 typedef struct _LOCK_HEADER { 02694 LIST_ENTRY ListHead; 02695 PFN_NUMBER Count; 02696 } LOCK_HEADER, *PLOCK_HEADER; 02697 02698 extern LOGICAL MmSnapUnloads; 02699 02700 #define MI_UNLOADED_DRIVERS 50 02701 02702 typedef struct _UNLOADED_DRIVERS { 02703 UNICODE_STRING Name; 02704 PVOID StartAddress; 02705 PVOID EndAddress; 02706 LARGE_INTEGER CurrentTime; 02707 } UNLOADED_DRIVERS, *PUNLOADED_DRIVERS; 02708 02709 extern PUNLOADED_DRIVERS MiUnloadedDrivers; 02710 02711 VOID 02712 MiRemoveConflictFromList ( 02713 IN PMMLOCK_CONFLICT Conflict 02714 ); 02715 02716 VOID 02717 MiInsertConflictInList ( 02718 IN PMMLOCK_CONFLICT Conflict 02719 ); 02720 02721 02722 VOID 02723 MiInitMachineDependent ( 02724 IN PLOADER_PARAMETER_BLOCK LoaderBlock 02725 ); 02726 02727 VOID 02728 MiBuildPagedPool ( 02729 VOID 02730 ); 02731 02732 VOID 02733 MiInitializeNonPagedPool ( 02734 VOID 02735 ); 02736 02737 BOOLEAN 02738 MiInitializeSystemSpaceMap ( 02739 PVOID Session OPTIONAL 02740 ); 02741 02742 VOID 02743 MiFindInitializationCode ( 02744 OUT PVOID *StartVa, 02745 OUT PVOID *EndVa 02746 ); 02747 02748 VOID 02749 MiFreeInitializationCode ( 02750 IN PVOID StartVa, 02751 IN PVOID EndVa 02752 ); 02753 02754 02755 ULONG 02756 MiSectionInitialization ( 02757 VOID 02758 ); 02759 02760 VOID 02761 FASTCALL 02762 MiDecrementReferenceCount ( 02763 IN PFN_NUMBER PageFrameIndex 02764 ); 02765 02766 VOID 02767 FASTCALL 02768 MiDecrementShareCount ( 02769 IN PFN_NUMBER PageFrameIndex 02770 ); 02771 02772 #define MiDecrementShareCountOnly(P) MiDecrementShareCount(P) 02773 02774 #define MiDecrementShareAndValidCount(P) MiDecrementShareCount(P) 02775 02776 // 02777 // Routines which operate on the Page Frame Database Lists 02778 // 02779 02780 VOID 02781 FASTCALL 02782 MiInsertPageInList ( 02783 IN PMMPFNLIST ListHead, 02784 IN PFN_NUMBER PageFrameIndex 02785 ); 02786 02787 VOID 02788 FASTCALL 02789 MiInsertStandbyListAtFront ( 02790 IN PFN_NUMBER PageFrameIndex 02791 ); 02792 02793 PFN_NUMBER //PageFrameIndex 02794 FASTCALL 02795 MiRemovePageFromList ( 02796 IN PMMPFNLIST ListHead 02797 ); 02798 02799 VOID 02800 FASTCALL 02801 MiUnlinkPageFromList ( 02802 IN PMMPFN Pfn 02803 ); 02804 02805 VOID 02806 MiUnlinkFreeOrZeroedPage ( 02807 IN PFN_NUMBER Page 02808 ); 02809 02810 VOID 02811 FASTCALL 02812 MiInsertFrontModifiedNoWrite ( 02813 IN PFN_NUMBER PageFrameIndex 02814 ); 02815 02816 ULONG 02817 FASTCALL 02818 MiEnsureAvailablePageOrWait ( 02819 IN PEPROCESS Process, 02820 IN PVOID VirtualAddress 02821 ); 02822 02823 PFN_NUMBER 02824 FASTCALL 02825 MiRemoveZeroPage ( 02826 IN ULONG PageColor 02827 ); 02828 02829 #define MiRemoveZeroPageIfAny(COLOR) \ 02830 (MmFreePagesByColor[ZeroedPageList][COLOR].Flink != MM_EMPTY_LIST) ? \ 02831 MiRemoveZeroPage(COLOR) : 0 02832 02833 02834 PFN_NUMBER //PageFrameIndex 02835 FASTCALL 02836 MiRemoveAnyPage ( 02837 IN ULONG PageColor 02838 ); 02839 02840 PVOID 02841 MiFindContiguousMemory ( 02842 IN PFN_NUMBER LowestPfn, 02843 IN PFN_NUMBER HighestPfn, 02844 IN PFN_NUMBER BoundaryPfn, 02845 IN PFN_NUMBER SizeInPages, 02846 IN PVOID CallingAddress 02847 ); 02848 02849 PVOID 02850 MiCheckForContiguousMemory ( 02851 IN PVOID BaseAddress, 02852 IN PFN_NUMBER BaseAddressPages, 02853 IN PFN_NUMBER SizeInPages, 02854 IN PFN_NUMBER LowestPfn, 02855 IN PFN_NUMBER HighestPfn, 02856 IN PFN_NUMBER BoundaryPfn 02857 ); 02858 02859 // 02860 // Routines which operate on the page frame database entry. 02861 // 02862 02863 VOID 02864 MiInitializePfn ( 02865 IN PFN_NUMBER PageFrameIndex, 02866 IN PMMPTE PointerPte, 02867 IN ULONG ModifiedState 02868 ); 02869 02870 VOID 02871 MiInitializePfnForOtherProcess ( 02872 IN PFN_NUMBER PageFrameIndex, 02873 IN PMMPTE PointerPte, 02874 IN PFN_NUMBER ContainingPageFrame 02875 ); 02876 02877 VOID 02878 MiInitializeCopyOnWritePfn ( 02879 IN PFN_NUMBER PageFrameIndex, 02880 IN PMMPTE PointerPte, 02881 IN WSLE_NUMBER WorkingSetIndex, 02882 IN PVOID SessionSpace 02883 ); 02884 02885 VOID 02886 MiInitializeTransitionPfn ( 02887 IN PFN_NUMBER PageFrameIndex, 02888 IN PMMPTE PointerPte, 02889 IN WSLE_NUMBER WorkingSetIndex 02890 ); 02891 02892 VOID 02893 MiFlushInPageSupportBlock ( 02894 ); 02895 02896 VOID 02897 MiFreeInPageSupportBlock ( 02898 IN PMMINPAGE_SUPPORT Support 02899 ); 02900 02901 PMMINPAGE_SUPPORT 02902 MiGetInPageSupportBlock ( 02903 VOID 02904 ); 02905 02906 // 02907 // Routines which require a physical page to be mapped into hyperspace 02908 // within the current process. 02909 // 02910 02911 VOID 02912 FASTCALL 02913 MiZeroPhysicalPage ( 02914 IN PFN_NUMBER PageFrameIndex, 02915 IN ULONG Color 02916 ); 02917 02918 VOID 02919 FASTCALL 02920 MiRestoreTransitionPte ( 02921 IN PFN_NUMBER PageFrameIndex 02922 ); 02923 02924 PSUBSECTION 02925 MiGetSubsectionAndProtoFromPte ( 02926 IN PMMPTE PointerPte, 02927 IN PMMPTE *ProtoPte, 02928 IN PEPROCESS Process 02929 ); 02930 02931 PVOID 02932 MiMapPageInHyperSpace ( 02933 IN PFN_NUMBER PageFrameIndex, 02934 OUT PKIRQL OldIrql 02935 ); 02936 02937 #define MiUnmapPageInHyperSpace(OLDIRQL) UNLOCK_HYPERSPACE(OLDIRQL) 02938 02939 02940 PVOID 02941 MiMapImageHeaderInHyperSpace ( 02942 IN PFN_NUMBER PageFrameIndex 02943 ); 02944 02945 VOID 02946 MiUnmapImageHeaderInHyperSpace ( 02947 VOID 02948 ); 02949 02950 VOID 02951 MiUpdateImageHeaderPage ( 02952 IN PMMPTE PointerPte, 02953 IN PFN_NUMBER PageFrameNumber, 02954 IN PCONTROL_AREA ControlArea 02955 ); 02956 02957 PFN_NUMBER 02958 MiGetPageForHeader ( 02959 VOID 02960 ); 02961 02962 VOID 02963 MiRemoveImageHeaderPage ( 02964 IN PFN_NUMBER PageFrameNumber 02965 ); 02966 02967 PVOID 02968 MiMapPageToZeroInHyperSpace ( 02969 IN PFN_NUMBER PageFrameIndex 02970 ); 02971 02972 02973 NTSTATUS 02974 MiGetWritablePagesInSection( 02975 IN PSECTION Section, 02976 OUT PULONG WritablePages 02977 ); 02978 02979 // 02980 // Routines to obtain and release system PTEs. 02981 // 02982 02983 PMMPTE 02984 MiReserveSystemPtes ( 02985 IN ULONG NumberOfPtes, 02986 IN MMSYSTEM_PTE_POOL_TYPE SystemPteType, 02987 IN ULONG Alignment, 02988 IN ULONG Offset, 02989 IN ULONG BugCheckOnFailure 02990 ); 02991 02992 VOID 02993 MiReleaseSystemPtes ( 02994 IN PMMPTE StartingPte, 02995 IN ULONG NumberOfPtes, 02996 IN MMSYSTEM_PTE_POOL_TYPE SystemPteType 02997 ); 02998 02999 VOID 03000 MiInitializeSystemPtes ( 03001 IN PMMPTE StartingPte, 03002 IN ULONG NumberOfPtes, 03003 IN MMSYSTEM_PTE_POOL_TYPE SystemPteType 03004 ); 03005 03006 VOID 03007 MiAddMappedPtes ( 03008 IN PMMPTE FirstPte, 03009 IN ULONG NumberOfPtes, 03010 IN PCONTROL_AREA ControlArea 03011 ); 03012 03013 VOID 03014 MiInitializeIoTrackers ( 03015 VOID 03016 ); 03017 03018 PVOID 03019 MiMapSinglePage ( 03020 IN PVOID VirtualAddress OPTIONAL, 03021 IN PFN_NUMBER PageFrameIndex, 03022 IN MEMORY_CACHING_TYPE CacheType, 03023 IN MM_PAGE_PRIORITY Priority 03024 ); 03025 03026 VOID 03027 MiUnmapSinglePage ( 03028 IN PVOID BaseAddress 03029 ); 03030 03031 // 03032 // Access Fault routines. 03033 // 03034 03035 NTSTATUS 03036 MiDispatchFault ( 03037 IN BOOLEAN StoreInstrution, 03038 IN PVOID VirtualAdress, 03039 IN PMMPTE PointerPte, 03040 IN PMMPTE PointerProtoPte, 03041 IN PEPROCESS Process, 03042 OUT PLOGICAL ApcNeeded 03043 ); 03044 03045 NTSTATUS 03046 MiResolveDemandZeroFault ( 03047 IN PVOID VirtualAddress, 03048 IN PMMPTE PointerPte, 03049 IN PEPROCESS Process, 03050 IN ULONG PrototypePte 03051 ); 03052 03053 NTSTATUS 03054 MiResolveTransitionFault ( 03055 IN PVOID FaultingAddress, 03056 IN PMMPTE PointerPte, 03057 IN PEPROCESS Process, 03058 IN ULONG PfnLockHeld, 03059 OUT PLOGICAL ApcNeeded 03060 ); 03061 03062 NTSTATUS 03063 MiResolvePageFileFault ( 03064 IN PVOID FaultingAddress, 03065 IN PMMPTE PointerPte, 03066 IN PMMINPAGE_SUPPORT *ReadBlock, 03067 IN PEPROCESS Process 03068 ); 03069 03070 NTSTATUS 03071 MiResolveProtoPteFault ( 03072 IN BOOLEAN StoreInstruction, 03073 IN PVOID VirtualAddress, 03074 IN PMMPTE PointerPte, 03075 IN PMMPTE PointerProtoPte, 03076 IN PMMINPAGE_SUPPORT *ReadBlock, 03077 IN PEPROCESS Process, 03078 OUT PLOGICAL ApcNeeded 03079 ); 03080 03081 03082 NTSTATUS 03083 MiResolveMappedFileFault ( 03084 IN PVOID FaultingAddress, 03085 IN PMMPTE PointerPte, 03086 IN PMMINPAGE_SUPPORT *ReadBlock, 03087 IN PEPROCESS Process 03088 ); 03089 03090 VOID 03091 MiAddValidPageToWorkingSet ( 03092 IN PVOID VirtualAddress, 03093 IN PMMPTE PointerPte, 03094 IN PMMPFN Pfn1, 03095 IN ULONG WsleMask 03096 ); 03097 03098 NTSTATUS 03099 MiWaitForInPageComplete ( 03100 IN PMMPFN Pfn, 03101 IN PMMPTE PointerPte, 03102 IN PVOID FaultingAddress, 03103 IN PMMPTE PointerPteContents, 03104 IN PMMINPAGE_SUPPORT InPageSupport, 03105 IN PEPROCESS CurrentProcess 03106 ); 03107 03108 NTSTATUS 03109 FASTCALL 03110 MiCopyOnWrite ( 03111 IN PVOID FaultingAddress, 03112 IN PMMPTE PointerPte 03113 ); 03114 03115 VOID 03116 MiSetDirtyBit ( 03117 IN PVOID FaultingAddress, 03118 IN PMMPTE PointerPte, 03119 IN ULONG PfnHeld 03120 ); 03121 03122 VOID 03123 MiSetModifyBit ( 03124 IN PMMPFN Pfn 03125 ); 03126 03127 PMMPTE 03128 MiFindActualFaultingPte ( 03129 IN PVOID FaultingAddress 03130 ); 03131 03132 VOID 03133 MiInitializeReadInProgressPfn ( 03134 IN PMDL Mdl, 03135 IN PMMPTE BasePte, 03136 IN PKEVENT Event, 03137 IN WSLE_NUMBER WorkingSetIndex 03138 ); 03139 03140 NTSTATUS 03141 MiAccessCheck ( 03142 IN PMMPTE PointerPte, 03143 IN BOOLEAN WriteOperation, 03144 IN KPROCESSOR_MODE PreviousMode, 03145 IN ULONG Protection, 03146 IN BOOLEAN CallerHoldsPfnLock 03147 ); 03148 03149 NTSTATUS 03150 FASTCALL 03151 MiCheckForUserStackOverflow ( 03152 IN PVOID FaultingAddress 03153 ); 03154 03155 PMMPTE 03156 MiCheckVirtualAddress ( 03157 IN PVOID VirtualAddress, 03158 OUT PULONG ProtectCode 03159 ); 03160 03161 NTSTATUS 03162 FASTCALL 03163 MiCheckPdeForPagedPool ( 03164 IN PVOID VirtualAddress 03165 ); 03166 03167 VOID 03168 MiInitializeMustSucceedPool ( 03169 VOID 03170 ); 03171 03172 // 03173 // Routines which operate on an address tree. 03174 // 03175 03176 PMMADDRESS_NODE 03177 FASTCALL 03178 MiGetNextNode ( 03179 IN PMMADDRESS_NODE Node 03180 ); 03181 03182 PMMADDRESS_NODE 03183 FASTCALL 03184 MiGetPreviousNode ( 03185 IN PMMADDRESS_NODE Node 03186 ); 03187 03188 03189 PMMADDRESS_NODE 03190 FASTCALL 03191 MiGetFirstNode ( 03192 IN PMMADDRESS_NODE Root 03193 ); 03194 03195 PMMADDRESS_NODE 03196 MiGetLastNode ( 03197 IN PMMADDRESS_NODE Root 03198 ); 03199 03200 VOID 03201 FASTCALL 03202 MiInsertNode ( 03203 IN PMMADDRESS_NODE Node, 03204 IN OUT PMMADDRESS_NODE *Root 03205 ); 03206 03207 VOID 03208 FASTCALL 03209 MiRemoveNode ( 03210 IN PMMADDRESS_NODE Node, 03211 IN OUT PMMADDRESS_NODE *Root 03212 ); 03213 03214 PMMADDRESS_NODE 03215 FASTCALL 03216 MiLocateAddressInTree ( 03217 IN ULONG_PTR Vpn, 03218 IN PMMADDRESS_NODE *Root 03219 ); 03220 03221 PMMADDRESS_NODE 03222 MiCheckForConflictingNode ( 03223 IN ULONG_PTR StartVpn, 03224 IN ULONG_PTR EndVpn, 03225 IN PMMADDRESS_NODE Root 03226 ); 03227 03228 PVOID 03229 MiFindEmptyAddressRangeInTree ( 03230 IN SIZE_T SizeOfRange, 03231 IN ULONG_PTR Alignment, 03232 IN PMMADDRESS_NODE Root, 03233 OUT PMMADDRESS_NODE *PreviousVad 03234 ); 03235 03236 PVOID 03237 MiFindEmptyAddressRangeDownTree ( 03238 IN SIZE_T SizeOfRange, 03239 IN PVOID HighestAddressToEndAt, 03240 IN ULONG_PTR Alignment, 03241 IN PMMADDRESS_NODE Root 03242 ); 03243 03244 VOID 03245 NodeTreeWalk ( 03246 PMMADDRESS_NODE Start 03247 ); 03248 03249 // 03250 // Routines which operate on the tree of virtual address descriptors. 03251 // 03252 03253 VOID 03254 MiInsertVad ( 03255 IN PMMVAD Vad 03256 ); 03257 03258 VOID 03259 MiRemoveVad ( 03260 IN PMMVAD Vad 03261 ); 03262 03263 PMMVAD 03264 FASTCALL 03265 MiLocateAddress ( 03266 IN PVOID Vad 03267 ); 03268 03269 PVOID 03270 MiFindEmptyAddressRange ( 03271 IN SIZE_T SizeOfRange, 03272 IN ULONG_PTR Alignment, 03273 IN ULONG QuickCheck 03274 ); 03275 03276 // 03277 // Routines which operate on the clone tree structure. 03278 // 03279 03280 03281 NTSTATUS 03282 MiCloneProcessAddressSpace ( 03283 IN PEPROCESS ProcessToClone, 03284 IN PEPROCESS ProcessToInitialize, 03285 IN PFN_NUMBER PdePhysicalPage, 03286 IN PFN_NUMBER HyperPhysicalPage 03287 ); 03288 03289 03290 ULONG 03291 MiDecrementCloneBlockReference ( 03292 IN PMMCLONE_DESCRIPTOR CloneDescriptor, 03293 IN PMMCLONE_BLOCK CloneBlock, 03294 IN PEPROCESS CurrentProcess 03295 ); 03296 03297 VOID 03298 MiWaitForForkToComplete ( 03299 IN PEPROCESS CurrentProcess 03300 ); 03301 03302 // 03303 // Routines which operate on the working set list. 03304 // 03305 03306 WSLE_NUMBER 03307 MiLocateAndReserveWsle ( 03308 IN PMMSUPPORT WsInfo 03309 ); 03310 03311 VOID 03312 MiReleaseWsle ( 03313 IN WSLE_NUMBER WorkingSetIndex, 03314 IN PMMSUPPORT WsInfo 03315 ); 03316 03317 VOID 03318 MiUpdateWsle ( 03319 IN PWSLE_NUMBER DesiredIndex, 03320 IN PVOID VirtualAddress, 03321 IN PMMWSL WorkingSetList, 03322 IN PMMPFN Pfn 03323 ); 03324 03325 VOID 03326 MiInitializeWorkingSetList ( 03327 IN PEPROCESS CurrentProcess 03328 ); 03329 03330 VOID 03331 MiGrowWsleHash ( 03332 IN PMMSUPPORT WsInfo 03333 ); 03334 03335 ULONG 03336 MiTrimWorkingSet ( 03337 ULONG Reduction, 03338 IN PMMSUPPORT WsInfo, 03339 IN ULONG ForcedReduction 03340 ); 03341 03342 VOID 03343 MiRemoveWorkingSetPages ( 03344 IN PMMWSL WorkingSetList, 03345 IN PMMSUPPORT WsInfo 03346 ); 03347 03348 #ifdef _MI_USE_CLAIMS_ 03349 VOID 03350 MiAgeAndEstimateAvailableInWorkingSet( 03351 IN PMMSUPPORT VmSupport, 03352 IN BOOLEAN DoAging, 03353 IN OUT PULONG TotalClaim, 03354 IN OUT PULONG TotalEstimatedAvailable 03355 ); 03356 #endif 03357 03358 VOID 03359 FASTCALL 03360 MiInsertWsle ( 03361 IN WSLE_NUMBER Entry, 03362 IN PMMWSL WorkingSetList 03363 ); 03364 03365 VOID 03366 FASTCALL 03367 MiRemoveWsle ( 03368 IN WSLE_NUMBER Entry, 03369 IN PMMWSL WorkingSetList 03370 ); 03371 03372 VOID 03373 MiFreeWorkingSetRange ( 03374 IN PVOID StartVa, 03375 IN PVOID EndVa, 03376 IN PMMSUPPORT WsInfo 03377 ); 03378 03379 WSLE_NUMBER 03380 FASTCALL 03381 MiLocateWsle ( 03382 IN PVOID VirtualAddress, 03383 IN PMMWSL WorkingSetList, 03384 IN WSLE_NUMBER WsPfnIndex 03385 ); 03386 03387 ULONG 03388 MiFreeWsle ( 03389 IN WSLE_NUMBER WorkingSetIndex, 03390 IN PMMSUPPORT WsInfo, 03391 IN PMMPTE PointerPte 03392 ); 03393 03394 VOID 03395 MiSwapWslEntries ( 03396 IN WSLE_NUMBER SwapEntry, 03397 IN WSLE_NUMBER Entry, 03398 IN PMMSUPPORT WsInfo 03399 ); 03400 03401 VOID 03402 MiRemoveWsleFromFreeList ( 03403 IN ULONG Entry, 03404 IN PMMWSLE Wsle, 03405 IN PMMWSL WorkingSetList 03406 ); 03407 03408 ULONG 03409 MiRemovePageFromWorkingSet ( 03410 IN PMMPTE PointerPte, 03411 IN PMMPFN Pfn1, 03412 IN PMMSUPPORT WsInfo 03413 ); 03414 03415 VOID 03416 MiTakePageFromWorkingSet ( 03417 IN ULONG Entry, 03418 IN PMMSUPPORT WsInfo, 03419 IN PMMPTE PointerPte 03420 ); 03421 03422 PFN_NUMBER 03423 MiDeleteSystemPagableVm ( 03424 IN PMMPTE PointerPte, 03425 IN PFN_NUMBER NumberOfPtes, 03426 IN MMPTE NewPteValue, 03427 IN LOGICAL SessionAllocation, 03428 OUT PPFN_NUMBER ResidentPages OPTIONAL 03429 ); 03430 03431 VOID 03432 MiLockCode ( 03433 IN PMMPTE FirstPte, 03434 IN PMMPTE LastPte, 03435 IN ULONG LockType 03436 ); 03437 03438 PLDR_DATA_TABLE_ENTRY 03439 MiLookupDataTableEntry ( 03440 IN PVOID AddressWithinSection, 03441 IN ULONG ResourceHeld 03442 ); 03443 03444 VOID 03445 MiFlushTb ( 03446 VOID 03447 ); 03448 03449 // 03450 // Routines which perform working set management. 03451 // 03452 03453 VOID 03454 MiObtainFreePages ( 03455 VOID 03456 ); 03457 03458 VOID 03459 MiModifiedPageWriter ( 03460 IN PVOID StartContext 03461 ); 03462 03463 VOID 03464 MiMappedPageWriter ( 03465 IN PVOID StartContext 03466 ); 03467 03468 LOGICAL 03469 MiIssuePageExtendRequest ( 03470 IN PMMPAGE_FILE_EXPANSION PageExtend 03471 ); 03472 03473 VOID 03474 MiIssuePageExtendRequestNoWait ( 03475 IN PFN_NUMBER SizeInPages 03476 ); 03477 03478 SIZE_T 03479 MiExtendPagingFiles ( 03480 IN PMMPAGE_FILE_EXPANSION PageExpand 03481 ); 03482 03483 VOID 03484 MiContractPagingFiles ( 03485 VOID 03486 ); 03487 03488 VOID 03489 MiAttemptPageFileReduction ( 03490 VOID 03491 ); 03492 03493 LOGICAL 03494 MiCancelWriteOfMappedPfn ( 03495 IN PFN_NUMBER PageToStop 03496 ); 03497 03498 // 03499 // Routines to delete address space. 03500 // 03501 03502 VOID 03503 MiDeleteVirtualAddresses ( 03504 IN PUCHAR StartingAddress, 03505 IN PUCHAR EndingAddress, 03506 IN ULONG AddressSpaceDeletion, 03507 IN PMMVAD Vad 03508 ); 03509 03510 VOID 03511 MiDeletePte ( 03512 IN PMMPTE PointerPte, 03513 IN PVOID VirtualAddress, 03514 IN ULONG AddressSpaceDeletion, 03515 IN PEPROCESS CurrentProcess, 03516 IN PMMPTE PrototypePte, 03517 IN PMMPTE_FLUSH_LIST PteFlushList OPTIONAL 03518 ); 03519 03520 VOID 03521 MiDeletePageTablesForPhysicalRange ( 03522 IN PVOID StartingAddress, 03523 IN PVOID EndingAddress 03524 ); 03525 03526 VOID 03527 MiFlushPteList ( 03528 IN PMMPTE_FLUSH_LIST PteFlushList, 03529 IN ULONG AllProcessors, 03530 IN MMPTE FillPte 03531 ); 03532 03533 03534 ULONG 03535 FASTCALL 03536 MiReleasePageFileSpace ( 03537 IN MMPTE PteContents 03538 ); 03539 03540 VOID 03541 FASTCALL 03542 MiUpdateModifiedWriterMdls ( 03543 IN ULONG PageFileNumber 03544 ); 03545 03546 VOID 03547 MiRemoveUserPhysicalPagesVad ( 03548 IN PMMVAD_SHORT FoundVad 03549 ); 03550 03551 VOID 03552 MiCleanPhysicalProcessPages ( 03553 IN PEPROCESS Process 03554 ); 03555 03556 VOID 03557 MiPhysicalViewRemover ( 03558 IN PEPROCESS Process, 03559 IN PMMVAD Vad 03560 ); 03561 03562 VOID 03563 MiPhysicalViewAdjuster ( 03564 IN PEPROCESS Process, 03565 IN PMMVAD OldVad, 03566 IN PMMVAD NewVad 03567 ); 03568 03569 // 03570 // General support routines. 03571 // 03572 03573 ULONG 03574 MiDoesPdeExistAndMakeValid ( 03575 IN PMMPTE PointerPde, 03576 IN PEPROCESS TargetProcess, 03577 IN ULONG PfnMutexHeld, 03578 OUT PULONG Waited 03579 ); 03580 03581 #if defined (_WIN64) 03582 LOGICAL 03583 MiDoesPpeExistAndMakeValid ( 03584 IN PMMPTE PointerPpe, 03585 IN PEPROCESS TargetProcess, 03586 IN ULONG PfnMutexHeld, 03587 OUT PULONG Waited 03588 ); 03589 #endif 03590 03591 ULONG 03592 MiMakePdeExistAndMakeValid ( 03593 IN PMMPTE PointerPde, 03594 IN PEPROCESS TargetProcess, 03595 IN ULONG PfnMutexHeld 03596 ); 03597 03598 #if defined (_WIN64) 03599 ULONG 03600 MiMakePpeExistAndMakeValid ( 03601 IN PMMPTE PointerPde, 03602 IN PEPROCESS TargetProcess, 03603 IN ULONG PfnMutexHeld 03604 ); 03605 #else 03606 #define MiMakePpeExistAndMakeValid(PDE, PROCESS, PFNMUTEXHELD) 03607 #endif 03608 03609 ULONG 03610 FASTCALL 03611 MiMakeSystemAddressValid ( 03612 IN PVOID VirtualAddress, 03613 IN PEPROCESS CurrentProcess 03614 ); 03615 03616 ULONG 03617 FASTCALL 03618 MiMakeSystemAddressValidPfnWs ( 03619 IN PVOID VirtualAddress, 03620 IN PEPROCESS CurrentProcess OPTIONAL 03621 ); 03622 03623 ULONG 03624 FASTCALL 03625 MiMakeSystemAddressValidPfnSystemWs ( 03626 IN PVOID VirtualAddress 03627 ); 03628 03629 ULONG 03630 FASTCALL 03631 MiMakeSystemAddressValidPfn ( 03632 IN PVOID VirtualAddress 03633 ); 03634 03635 ULONG 03636 FASTCALL 03637 MiLockPagedAddress ( 03638 IN PVOID VirtualAddress, 03639 IN ULONG PfnLockHeld 03640 ); 03641 03642 VOID 03643 FASTCALL 03644 MiUnlockPagedAddress ( 03645 IN PVOID VirtualAddress, 03646 IN ULONG PfnLockHeld 03647 ); 03648 03649 ULONG 03650 FASTCALL 03651 MiIsPteDecommittedPage ( 03652 IN PMMPTE PointerPte 03653 ); 03654 03655 ULONG 03656 FASTCALL 03657 MiIsProtectionCompatible ( 03658 IN ULONG OldProtect, 03659 IN ULONG NewProtect 03660 ); 03661 03662 ULONG 03663 FASTCALL 03664 MiMakeProtectionMask ( 03665 IN ULONG Protect 03666 ); 03667 03668 ULONG 03669 MiIsEntireRangeCommitted ( 03670 IN PVOID StartingAddress, 03671 IN PVOID EndingAddress, 03672 IN PMMVAD Vad, 03673 IN PEPROCESS Process 03674 ); 03675 03676 ULONG 03677 MiIsEntireRangeDecommitted ( 03678 IN PVOID StartingAddress, 03679 IN PVOID EndingAddress, 03680 IN PMMVAD Vad, 03681 IN PEPROCESS Process 03682 ); 03683 03684 //++ 03685 //PMMPTE 03686 //MiGetProtoPteAddress ( 03687 // IN PMMPTE VAD, 03688 // IN PVOID VA 03689 // ); 03690 // 03691 // Routine Description: 03692 // 03693 // MiGetProtoPteAddress returns a pointer to the prototype PTE which 03694 // is mapped by the given virtual address descriptor and address within 03695 // the virtual address descriptor. 03696 // 03697 // Arguments 03698 // 03699 // VAD - Supplies a pointer to the virtual address descriptor that contains 03700 // the VA. 03701 // 03702 // VPN - Supplies the virtual page number. 03703 // 03704 // Return Value: 03705 // 03706 // A pointer to the proto PTE which corresponds to the VA. 03707 // 03708 //-- 03709 03710 03711 #define MiGetProtoPteAddress(VAD,VPN) \ 03712 ((((((VPN) - (VAD)->StartingVpn) << PTE_SHIFT) + \ 03713 (ULONG_PTR)(VAD)->FirstPrototypePte) <= (ULONG_PTR)(VAD)->LastContiguousPte) ? \ 03714 ((PMMPTE)(((((VPN) - (VAD)->StartingVpn) << PTE_SHIFT) + \ 03715 (ULONG_PTR)(VAD)->FirstPrototypePte))) : \ 03716 MiGetProtoPteAddressExtended ((VAD),(VPN))) 03717 03718 PMMPTE 03719 FASTCALL 03720 MiGetProtoPteAddressExtended ( 03721 IN PMMVAD Vad, 03722 IN ULONG_PTR Vpn 03723 ); 03724 03725 PSUBSECTION 03726 FASTCALL 03727 MiLocateSubsection ( 03728 IN PMMVAD Vad, 03729 IN ULONG_PTR Vpn 03730 ); 03731 03732 VOID 03733 MiInitializeSystemCache ( 03734 IN ULONG MinimumWorkingSet, 03735 IN ULONG MaximumWorkingSet 03736 ); 03737 03738 VOID 03739 MiAdjustWorkingSetManagerParameters( 03740 BOOLEAN WorkStation 03741 ); 03742 03743 // 03744 // Section support 03745 // 03746 03747 VOID 03748 FASTCALL 03749 MiInsertBasedSection ( 03750 IN PSECTION Section 03751 ); 03752 03753 NTSTATUS 03754 MiMapViewOfPhysicalSection ( 03755 IN PCONTROL_AREA ControlArea, 03756 IN PEPROCESS Process, 03757 IN PVOID *CapturedBase, 03758 IN PLARGE_INTEGER SectionOffset, 03759 IN PSIZE_T CapturedViewSize, 03760 IN ULONG ProtectionMask, 03761 IN ULONG_PTR ZeroBits, 03762 IN ULONG AllocationType, 03763 IN BOOLEAN WriteCombined, 03764 OUT PBOOLEAN ReleasedWsMutex 03765 ); 03766 03767 VOID 03768 MiRemoveImageSectionObject( 03769 IN PFILE_OBJECT File, 03770 IN PCONTROL_AREA ControlArea 03771 ); 03772 03773 VOID 03774 MiAddSystemPtes( 03775 IN PMMPTE StartingPte, 03776 IN ULONG NumberOfPtes, 03777 IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType 03778 ); 03779 03780 VOID 03781 MiRemoveMappedView ( 03782 IN PEPROCESS CurrentProcess, 03783 IN PMMVAD Vad 03784 ); 03785 03786 PVOID 03787 MiFindEmptySectionBaseDown ( 03788 IN ULONG SizeOfRange, 03789 IN PVOID HighestAddressToEndAt 03790 ); 03791 03792 VOID 03793 MiSegmentDelete ( 03794 PSEGMENT Segment 03795 ); 03796 03797 VOID 03798 MiSectionDelete ( 03799 PVOID Object 03800 ); 03801 03802 VOID 03803 MiDereferenceSegmentThread ( 03804 IN PVOID StartContext 03805 ); 03806 03807 NTSTATUS 03808 MiCreateImageFileMap ( 03809 IN PFILE_OBJECT File, 03810 OUT PSEGMENT *Segment 03811 ); 03812 03813 NTSTATUS 03814 MiCreateDataFileMap ( 03815 IN PFILE_OBJECT File, 03816 OUT PSEGMENT *Segment, 03817 IN PUINT64 MaximumSize, 03818 IN ULONG SectionPageProtection, 03819 IN ULONG AllocationAttributes, 03820 IN ULONG IgnoreFileSizing 03821 ); 03822 03823 NTSTATUS 03824 MiCreatePagingFileMap ( 03825 OUT PSEGMENT *Segment, 03826 IN PUINT64 MaximumSize, 03827 IN ULONG ProtectionMask, 03828 IN ULONG AllocationAttributes 03829 ); 03830 03831 VOID 03832 MiPurgeSubsectionInternal ( 03833 IN PSUBSECTION Subsection, 03834 IN ULONG PteOffset 03835 ); 03836 03837 VOID 03838 MiPurgeImageSection ( 03839 IN PCONTROL_AREA ControlArea, 03840 IN PEPROCESS Process 03841 ); 03842 03843 VOID 03844 MiCleanSection ( 03845 IN PCONTROL_AREA ControlArea, 03846 IN LOGICAL DirtyDataPagesOk 03847 ); 03848 03849 VOID 03850 MiCheckControlArea ( 03851 IN PCONTROL_AREA ControlArea, 03852 IN PEPROCESS CurrentProcess, 03853 IN KIRQL PreviousIrql 03854 ); 03855 03856 LOGICAL 03857 MiCheckPurgeAndUpMapCount ( 03858 IN PCONTROL_AREA ControlArea 03859 ); 03860 03861 VOID 03862 MiCheckForControlAreaDeletion ( 03863 IN PCONTROL_AREA ControlArea 03864 ); 03865 03866 BOOLEAN 03867 MiCheckControlAreaStatus ( 03868 IN SECTION_CHECK_TYPE SectionCheckType, 03869 IN PSECTION_OBJECT_POINTERS SectionObjectPointers, 03870 IN ULONG DelayClose, 03871 OUT PCONTROL_AREA *ControlArea, 03872 OUT PKIRQL OldIrql 03873 ); 03874 03875 PEVENT_COUNTER 03876 MiGetEventCounter ( 03877 ); 03878 03879 VOID 03880 MiFlushEventCounter ( 03881 ); 03882 03883 VOID 03884 MiFreeEventCounter ( 03885 IN PEVENT_COUNTER Support, 03886 IN ULONG Flush 03887 ); 03888 03889 ULONG 03890 MiCanFileBeTruncatedInternal ( 03891 IN PSECTION_OBJECT_POINTERS SectionPointer, 03892 IN PLARGE_INTEGER NewFileSize OPTIONAL, 03893 IN LOGICAL BlockNewViews, 03894 OUT PKIRQL PreviousIrql 03895 ); 03896 03897 #define STATUS_MAPPED_WRITER_COLLISION (0xC0033333) 03898 03899 NTSTATUS 03900 MiFlushSectionInternal ( 03901 IN PMMPTE StartingPte, 03902 IN PMMPTE FinalPte, 03903 IN PSUBSECTION FirstSubsection, 03904 IN PSUBSECTION LastSubsection, 03905 IN ULONG Synchronize, 03906 IN LOGICAL WriteInProgressOk, 03907 OUT PIO_STATUS_BLOCK IoStatus 03908 ); 03909 03910 // 03911 // protection stuff... 03912 // 03913 03914 NTSTATUS 03915 MiProtectVirtualMemory ( 03916 IN PEPROCESS Process, 03917 IN PVOID *CapturedBase, 03918 IN PSIZE_T CapturedRegionSize, 03919 IN ULONG Protect, 03920 IN PULONG LastProtect 03921 ); 03922 03923 ULONG 03924 MiGetPageProtection ( 03925 IN PMMPTE PointerPte, 03926 IN PEPROCESS Process 03927 ); 03928 03929 ULONG 03930 MiSetProtectionOnSection ( 03931 IN PEPROCESS Process, 03932 IN PMMVAD Vad, 03933 IN PVOID StartingAddress, 03934 IN PVOID EndingAddress, 03935 IN ULONG NewProtect, 03936 OUT PULONG CapturedOldProtect, 03937 IN ULONG DontCharge 03938 ); 03939 03940 NTSTATUS 03941 MiCheckSecuredVad ( 03942 IN PMMVAD Vad, 03943 IN PVOID Base, 03944 IN ULONG_PTR Size, 03945 IN ULONG ProtectionMask 03946 ); 03947 03948 ULONG 03949 MiChangeNoAccessForkPte ( 03950 IN PMMPTE PointerPte, 03951 IN ULONG ProtectionMask 03952 ); 03953 03954 VOID 03955 MiSetImageProtect ( 03956 IN PSEGMENT Segment, 03957 IN ULONG Protection 03958 ); 03959 03960 // 03961 // Routines for charging quota and commitment. 03962 // 03963 03964 ULONG 03965 FASTCALL 03966 MiChargePageFileQuota ( 03967 IN SIZE_T QuotaCharge, 03968 IN PEPROCESS CurrentProcess 03969 ); 03970 03971 VOID 03972 MiReturnPageFileQuota ( 03973 IN SIZE_T QuotaCharge, 03974 IN PEPROCESS CurrentProcess 03975 ); 03976 03977 LOGICAL 03978 FASTCALL 03979 MiChargeCommitment ( 03980 IN SIZE_T QuotaCharge, 03981 IN PEPROCESS Process OPTIONAL 03982 ); 03983 03984 LOGICAL 03985 FASTCALL 03986 MiChargeCommitmentCantExpand ( 03987 IN SIZE_T QuotaCharge, 03988 IN ULONG MustSucceed 03989 ); 03990 03991 VOID 03992 FASTCALL 03993 MiReturnCommitment ( 03994 IN SIZE_T QuotaCharge 03995 ); 03996 03997 extern SIZE_T MmPeakCommitment; 03998 03999 extern SIZE_T MmTotalCommitLimitMaximum; 04000 04001 SIZE_T 04002 MiCalculatePageCommitment ( 04003 IN PVOID StartingAddress, 04004 IN PVOID EndingAddress, 04005 IN PMMVAD Vad, 04006 IN PEPROCESS Process 04007 ); 04008 04009 VOID 04010 MiReturnPageTablePageCommitment ( 04011 IN PVOID StartingAddress, 04012 IN PVOID EndingAddress, 04013 IN PEPROCESS CurrentProcess, 04014 IN PMMVAD PreviousVad, 04015 IN PMMVAD NextVad 04016 ); 04017 04018 VOID 04019 MiEmptyAllWorkingSets ( 04020 VOID 04021 ); 04022 04023 VOID 04024 MiFlushAllPages ( 04025 VOID 04026 ); 04027 04028 VOID 04029 MiModifiedPageWriterTimerDispatch ( 04030 IN PKDPC Dpc, 04031 IN PVOID DeferredContext, 04032 IN PVOID SystemArgument1, 04033 IN PVOID SystemArgument2 04034 ); 04035 04036 LONGLONG 04037 MiStartingOffset( 04038 IN PSUBSECTION Subsection, 04039 IN PMMPTE PteAddress 04040 ); 04041 04042 LARGE_INTEGER 04043 MiEndingOffset( 04044 IN PSUBSECTION Subsection 04045 ); 04046 04047 VOID 04048 MiReloadBootLoadedDrivers ( 04049 IN PLOADER_PARAMETER_BLOCK LoaderBlock 04050 ); 04051 04052 LOGICAL 04053 MiInitializeLoadedModuleList ( 04054 IN PLOADER_PARAMETER_BLOCK LoaderBlock 04055 ); 04056 04057 VOID 04058 MiEnableRandomSpecialPool ( 04059 IN LOGICAL Enable 04060 ); 04061 04062 LOGICAL 04063 MiTriageSystem ( 04064 IN PLOADER_PARAMETER_BLOCK LoaderBlock 04065 ); 04066 04067 LOGICAL 04068 MiTriageAddDrivers ( 04069 IN PLOADER_PARAMETER_BLOCK LoaderBlock 04070 ); 04071 04072 LOGICAL 04073 MiTriageVerifyDriver ( 04074 IN PLDR_DATA_TABLE_ENTRY DataTableEntry 04075 ); 04076 04077 #if defined (_WIN64) 04078 #define MM_SPECIAL_POOL_PTES ((1024 * 1024) / sizeof (MMPTE)) 04079 #else 04080 #define MM_SPECIAL_POOL_PTES 25000 04081 #endif 04082 04083 #define MI_SUSPECT_DRIVER_BUFFER_LENGTH 512 04084 04085 extern WCHAR MmVerifyDriverBuffer[]; 04086 extern ULONG MmVerifyDriverBufferLength; 04087 extern ULONG MmVerifyDriverLevel; 04088 04089 extern LOGICAL MmDontVerifyRandomDrivers; 04090 extern LOGICAL MmSnapUnloads; 04091 extern LOGICAL MmProtectFreedNonPagedPool; 04092 extern ULONG MmEnforceWriteProtection; 04093 extern LOGICAL MmTrackLockedPages; 04094 extern LOGICAL MmTrackPtes; 04095 04096 #define VI_POOL_FREELIST_END ((ULONG_PTR)-1) 04097 04098 typedef struct _VI_POOL_ENTRY_INUSE { 04099 PVOID VirtualAddress; 04100 PVOID CallingAddress; 04101 SIZE_T NumberOfBytes; 04102 ULONG_PTR Tag; 04103 } VI_POOL_ENTRY_INUSE, *PVI_POOL_ENTRY_INUSE; 04104 04105 typedef struct _VI_POOL_ENTRY { 04106 union { 04107 VI_POOL_ENTRY_INUSE InUse; 04108 ULONG_PTR FreeListNext; 04109 }; 04110 } VI_POOL_ENTRY, *PVI_POOL_ENTRY; 04111 04112 #define MI_VERIFIER_ENTRY_SIGNATURE 0x98761940 04113 04114 typedef struct _MI_VERIFIER_DRIVER_ENTRY { 04115 LIST_ENTRY Links; 04116 ULONG Loads; 04117 ULONG Unloads; 04118 04119 UNICODE_STRING BaseName; 04120 PVOID StartAddress; 04121 PVOID EndAddress; 04122 04123 #define VI_VERIFYING_DIRECTLY 0x1 04124 #define VI_VERIFYING_INVERSELY 0x2 04125 04126 ULONG Flags; 04127 ULONG_PTR Signature; 04128 ULONG_PTR Reserved; 04129 KSPIN_LOCK VerifierPoolLock; 04130 04131 PVI_POOL_ENTRY PoolHash; 04132 ULONG_PTR PoolHashSize; 04133 ULONG_PTR PoolHashFree; 04134 ULONG_PTR PoolHashReserved; 04135 04136 ULONG CurrentPagedPoolAllocations; 04137 ULONG CurrentNonPagedPoolAllocations; 04138 ULONG PeakPagedPoolAllocations; 04139 ULONG PeakNonPagedPoolAllocations; 04140 04141 SIZE_T PagedBytes; 04142 SIZE_T NonPagedBytes; 04143 SIZE_T PeakPagedBytes; 04144 SIZE_T PeakNonPagedBytes; 04145 04146 } MI_VERIFIER_DRIVER_ENTRY, *PMI_VERIFIER_DRIVER_ENTRY; 04147 04148 typedef struct _MI_VERIFIER_POOL_HEADER { 04149 ULONG_PTR ListIndex; 04150 PMI_VERIFIER_DRIVER_ENTRY Verifier; 04151 } MI_VERIFIER_POOL_HEADER, *PMI_VERIFIER_POOL_HEADER; 04152 04153 typedef struct _MM_DRIVER_VERIFIER_DATA { 04154 ULONG Level; 04155 ULONG RaiseIrqls; 04156 ULONG AcquireSpinLocks; 04157 ULONG SynchronizeExecutions; 04158 04159 ULONG AllocationsAttempted; 04160 ULONG AllocationsSucceeded; 04161 ULONG AllocationsSucceededSpecialPool; 04162 ULONG AllocationsWithNoTag; 04163 04164 ULONG TrimRequests; 04165 ULONG Trims; 04166 ULONG AllocationsFailed; 04167 ULONG AllocationsFailedDeliberately; 04168 04169 ULONG Loads; 04170 ULONG Unloads; 04171 ULONG UnTrackedPool; 04172 ULONG Fill; 04173 04174 ULONG CurrentPagedPoolAllocations; 04175 ULONG CurrentNonPagedPoolAllocations; 04176 ULONG PeakPagedPoolAllocations; 04177 ULONG PeakNonPagedPoolAllocations; 04178 04179 SIZE_T PagedBytes; 04180 SIZE_T NonPagedBytes; 04181 SIZE_T PeakPagedBytes; 04182 SIZE_T PeakNonPagedBytes; 04183 04184 } MM_DRIVER_VERIFIER_DATA, *PMM_DRIVER_VERIFIER_DATA; 04185 04186 LOGICAL 04187 MiInitializeDriverVerifierList ( 04188 IN PLOADER_PARAMETER_BLOCK LoaderBlock 04189 ); 04190 04191 LOGICAL 04192 MiApplyDriverVerifier ( 04193 IN PLDR_DATA_TABLE_ENTRY, 04194 IN PMI_VERIFIER_DRIVER_ENTRY Verifier 04195 ); 04196 04197 VOID 04198 MiVerifyingDriverUnloading ( 04199 IN PLDR_DATA_TABLE_ENTRY DataTableEntry 04200 ); 04201 04202 VOID 04203 MiVerifierCheckThunks ( 04204 IN PLDR_DATA_TABLE_ENTRY DataTableEntry 04205 ); 04206 04207 extern ULONG MiActiveVerifierThunks; 04208 extern LIST_ENTRY MiSuspectDriverList; 04209 04210 extern LOGICAL KernelVerifier; 04211 04212 extern MM_DRIVER_VERIFIER_DATA MmVerifierData; 04213 04214 VOID 04215 MiEnableKernelVerifier ( 04216 VOID 04217 ); 04218 04219 #if 0 04220 04221 #define MM_COMMIT_COUNTER_MAX 70 04222 04223 #define MM_TRACK_COMMIT(_index, bump) \ 04224 if (_index >= MM_COMMIT_COUNTER_MAX) { \ 04225 DbgPrint("Mm: Invalid commit counter %d %d\n", _index, MM_COMMIT_COUNTER_MAX); \ 04226 DbgBreakPoint(); \ 04227 } \ 04228 else { \ 04229 MmTrackCommit[_index] += (bump); \ 04230 } 04231 04232 extern SIZE_T MmTrackCommit[MM_COMMIT_COUNTER_MAX]; 04233 04234 #else 04235 04236 #define MM_TRACK_COMMIT(_index, bump) 04237 04238 #endif 04239 04240 #define MI_FREED_SPECIAL_POOL_SIGNATURE 0x98764321 04241 04242 #define MI_STACK_BYTES 1024 04243 04244 typedef struct _MI_FREED_SPECIAL_POOL { 04245 POOL_HEADER OverlaidPoolHeader; 04246 MI_VERIFIER_POOL_HEADER OverlaidVerifierPoolHeader; 04247 04248 ULONG Signature; 04249 ULONG TickCount; 04250 ULONG NumberOfBytesRequested; 04251 ULONG Pagable; 04252 04253 PVOID VirtualAddress; 04254 PVOID StackPointer; 04255 ULONG StackBytes; 04256 PETHREAD Thread; 04257 04258 UCHAR StackData[MI_STACK_BYTES]; 04259 } MI_FREED_SPECIAL_POOL, *PMI_FREED_SPECIAL_POOL; 04260 04261 #define MM_DBG_COMMIT_NONPAGED_POOL_EXPANSION 0 04262 #define MM_DBG_COMMIT_PAGED_POOL_PAGETABLE 1 04263 #define MM_DBG_COMMIT_PAGED_POOL_PAGES 2 04264 #define MM_DBG_COMMIT_SESSION_POOL_PAGE_TABLES 3 04265 #define MM_DBG_COMMIT_ALLOCVM1 4 04266 #define MM_DBG_COMMIT_ALLOCVM2 5 04267 #define MM_DBG_COMMIT_IMAGE 6 04268 #define MM_DBG_COMMIT_PAGEFILE_BACKED_SHMEM 7 04269 #define MM_DBG_COMMIT_INDEPENDENT_PAGES 8 04270 #define MM_DBG_COMMIT_CONTIGUOUS_PAGES 9 04271 #define MM_DBG_COMMIT_MDL_PAGES 10 04272 #define MM_DBG_COMMIT_NONCACHED_PAGES 11 04273 #define MM_DBG_COMMIT_MAPVIEW_DATA 12 04274 #define MM_DBG_COMMIT_FILL_SYSTEM_DIRECTORY 13 04275 #define MM_DBG_COMMIT_EXTRA_SYSTEM_PTES 14 04276 #define MM_DBG_COMMIT_DRIVER_PAGING_AT_INIT 15 04277 #define MM_DBG_COMMIT_PAGEFILE_FULL 16 04278 #define MM_DBG_COMMIT_PROCESS_CREATE 17 04279 #define MM_DBG_COMMIT_KERNEL_STACK_CREATE 18 04280 #define MM_DBG_COMMIT_SET_PROTECTION 19 04281 #define MM_DBG_COMMIT_SESSION_CREATE 20 04282 #define MM_DBG_COMMIT_SESSION_IMAGE_PAGES 21 04283 #define MM_DBG_COMMIT_SESSION_PAGETABLE_PAGES 22 04284 #define MM_DBG_COMMIT_SESSION_SHARED_IMAGE 23 04285 #define MM_DBG_COMMIT_DRIVER_PAGES 24 04286 #define MM_DBG_COMMIT_INSERT_VAD 25 04287 #define MM_DBG_COMMIT_SESSION_WS_INIT 26 04288 #define MM_DBG_COMMIT_SESSION_ADDITIONAL_WS_PAGES 27 04289 #define MM_DBG_COMMIT_SESSION_ADDITIONAL_WS_HASHPAGES 28 04290 04291 #define MM_DBG_COMMIT_RETURN_NONPAGED_POOL_EXPANSION 29 04292 #define MM_DBG_COMMIT_RETURN_PAGED_POOL_PAGES 30 04293 #define MM_DBG_COMMIT_RETURN_SESSION_POOL_PAGE_TABLES 31 04294 #define MM_DBG_COMMIT_RETURN_ALLOCVM1 32 04295 #define MM_DBG_COMMIT_RETURN_ALLOCVM2 33 04296 #define MM_DBG_COMMIT_RETURN_ALLOCVM3 34 04297 #define MM_DBG_COMMIT_RETURN_IMAGE_NO_LARGE_CA 35 04298 #define MM_DBG_COMMIT_RETURN_PAGEFILE_BACKED_SHMEM 36 04299 #define MM_DBG_COMMIT_RETURN_NTFREEVM1 37 04300 #define MM_DBG_COMMIT_RETURN_NTFREEVM2 38 04301 #define MM_DBG_COMMIT_RETURN_NTFREEVM3 39 04302 #define MM_DBG_COMMIT_RETURN_NTFREEVM4 40 04303 #define MM_DBG_COMMIT_RETURN_MDL_PAGES 41 04304 #define MM_DBG_COMMIT_RETURN_NONCACHED_PAGES 42 04305 #define MM_DBG_COMMIT_RETURN_MAPVIEW_DATA 43 04306 #define MM_DBG_COMMIT_RETURN_PAGETABLES 44 04307 #define MM_DBG_COMMIT_RETURN_PROTECTION 45 04308 #define MM_DBG_COMMIT_RETURN_SEGMENT_DELETE1 46 04309 #define MM_DBG_COMMIT_RETURN_SEGMENT_DELETE2 47 04310 #define MM_DBG_COMMIT_RETURN_SESSION_CREATE_FAILURE1 48 04311 #define MM_DBG_COMMIT_RETURN_SESSION_DEREFERENCE 49 04312 #define MM_DBG_COMMIT_RETURN_SESSION_IMAGE_FAILURE1 50 04313 #define MM_DBG_COMMIT_RETURN_SESSION_PAGETABLE_PAGES 51 04314 #define MM_DBG_COMMIT_RETURN_VAD 52 04315 #define MM_DBG_COMMIT_RETURN_SESSION_WSL_FAILURE 54 04316 #define MM_DBG_COMMIT_RETURN_PROCESS_CREATE_FAILURE1 55 04317 #define MM_DBG_COMMIT_RETURN_PROCESS_DELETE 56 04318 #define MM_DBG_COMMIT_RETURN_PROCESS_CLEAN_PAGETABLES 57 04319 #define MM_DBG_COMMIT_RETURN_KERNEL_STACK_FAILURE1 58 04320 #define MM_DBG_COMMIT_RETURN_KERNEL_STACK_FAILURE2 59 04321 #define MM_DBG_COMMIT_RETURN_KERNEL_STACK_DELETE 60 04322 #define MM_DBG_COMMIT_RETURN_SESSION_DRIVER_LOAD_FAILURE1 61 04323 #define MM_DBG_COMMIT_RETURN_DRIVER_INIT_CODE 62 04324 #define MM_DBG_COMMIT_RETURN_DRIVER_UNLOAD 63 04325 #define MM_DBG_COMMIT_RETURN_DRIVER_UNLOAD1 64 04326 04327 04328 #if 1 // LWFIX - TEMP TEMP TEMP 04329 04330 #define MM_BUMP_COUNTER_MAX 60 04331 04332 #define MM_BUMP_COUNTER(_index, bump) \ 04333 if (_index >= MM_BUMP_COUNTER_MAX) { \ 04334 DbgPrint("Mm: Invalid bump counter %d %d\n", _index, MM_BUMP_COUNTER_MAX); \ 04335 DbgBreakPoint(); \ 04336 } \ 04337 else { \ 04338 MmResTrack[_index] += (bump); \ 04339 } 04340 #else 04341 04342 #define MM_BUMP_COUNTER(_index, bump) 04343 04344 #endif 04345 04346 extern ULONG MiSpecialPagesNonPaged; 04347 extern ULONG MiSpecialPagesNonPagedMaximum; 04348 04349 extern ULONG MmLockPagesPercentage; 04350 04351 //++ 04352 //PFN_NUMBER 04353 //MI_NONPAGABLE_MEMORY_AVAILABLE( 04354 // VOID 04355 // ); 04356 // 04357 // Routine Description: 04358 // 04359 // This routine lets callers know how many pages can be charged against 04360 // the resident available, factoring in earlier Mm promises that 04361 // may not have been redeemed at this point (ie: nonpaged pool expansion, 04362 // etc, that must be honored at a later point if requested). 04363 // 04364 // Arguments 04365 // 04366 // None. 04367 // 04368 // Return Value: 04369 // 04370 // The number of currently available pages in the resident available. 04371 // 04372 // N.B. This is a signed quantity and can be negative. 04373 // 04374 //-- 04375 #define MI_NONPAGABLE_MEMORY_AVAILABLE() \ 04376 ((SPFN_NUMBER) \ 04377 (MmResidentAvailablePages - \ 04378 MmTotalFreeSystemPtes[NonPagedPoolExpansion] - \ 04379 (MiSpecialPagesNonPagedMaximum - MiSpecialPagesNonPaged) - \ 04380 MmSystemLockPagesCount)) 04381 04382 extern ULONG MmLargePageMinimum; 04383 04384 // 04385 // hack stuff for testing. 04386 // 04387 04388 VOID 04389 MiDumpValidAddresses ( 04390 VOID 04391 ); 04392 04393 VOID 04394 MiDumpPfn ( VOID ); 04395 04396 VOID 04397 MiDumpWsl ( VOID ); 04398 04399 04400 VOID 04401 MiFormatPte ( 04402 IN PMMPTE PointerPte 04403 ); 04404 04405 VOID 04406 MiCheckPfn ( VOID ); 04407 04408 VOID 04409 MiCheckPte ( VOID ); 04410 04411 VOID 04412 MiFormatPfn ( 04413 IN PMMPFN PointerPfn 04414 ); 04415 04416 04417 04418 04419 extern MMPTE ZeroPte; 04420 04421 extern MMPTE ZeroKernelPte; 04422 04423 extern MMPTE ValidKernelPteLocal; 04424 04425 extern MMPTE ValidKernelPte; 04426 04427 extern MMPTE ValidKernelPde; 04428 04429 extern MMPTE ValidKernelPdeLocal; 04430 04431 extern MMPTE ValidUserPte; 04432 04433 extern MMPTE ValidPtePte; 04434 04435 extern MMPTE ValidPdePde; 04436 04437 extern MMPTE DemandZeroPde; 04438 04439 extern MMPTE DemandZeroPte; 04440 04441 extern MMPTE KernelPrototypePte; 04442 04443 extern MMPTE TransitionPde; 04444 04445 extern MMPTE PrototypePte; 04446 04447 extern MMPTE NoAccessPte; 04448 04449 extern ULONG_PTR MmSubsectionBase; 04450 04451 extern ULONG_PTR MmSubsectionTopPage; 04452 04453 extern BOOLEAN MiHydra; 04454 04455 extern ULONG ExpMultiUserTS; 04456 04457 // extern MMPTE UserNoCommitPte; 04458 04459 // 04460 // Virtual alignment for PTEs (machine specific) minimum value is 04461 // 4k maximum value is 64k. The maximum value can be raised by 04462 // changing the MM_PROTO_PTE_ALIGNMENT constant and adding more 04463 // reserved mapping PTEs in hyperspace. 04464 // 04465 04466 // 04467 // Total number of physical pages on the system. 04468 // 04469 04470 extern PFN_COUNT MmNumberOfPhysicalPages; 04471 04472 // 04473 // Lowest physical page number on the system. 04474 // 04475 04476 extern PFN_NUMBER MmLowestPhysicalPage; 04477 04478 // 04479 // Highest physical page number on the system. 04480 // 04481 04482 extern PFN_NUMBER MmHighestPhysicalPage; 04483 04484 // 04485 // Highest possible physical page number in the system. 04486 // 04487 04488 extern PFN_NUMBER MmHighestPossiblePhysicalPage; 04489 04490 // 04491 // Total number of available pages on the system. This 04492 // is the sum of the pages on the zeroed, free and standby lists. 04493 // 04494 04495 extern PFN_COUNT MmAvailablePages; 04496 04497 // 04498 // Total number of free pages to base working set trimming on. 04499 // 04500 04501 extern PFN_NUMBER MmMoreThanEnoughFreePages; 04502 04503 // 04504 // Total number physical pages which would be usable if every process 04505 // was at it's minimum working set size. This value is initialized 04506 // at system initialization to MmAvailablePages - MM_FLUID_PHYSICAL_PAGES. 04507 // Everytime a thread is created, the kernel stack is subtracted from 04508 // this and every time a process is created, the minimum working set 04509 // is subtracted from this. If the value would become negative, the 04510 // operation (create process/kernel stack/ adjust working set) fails. 04511 // The PFN LOCK must be owned to manipulate this value. 04512 // 04513 04514 extern SPFN_NUMBER MmResidentAvailablePages; 04515 04516 // 04517 // The total number of pages which would be removed from working sets 04518 // if every working set was at its minimum. 04519 // 04520 04521 extern PFN_NUMBER MmPagesAboveWsMinimum; 04522 04523 // 04524 // The total number of pages which would be removed from working sets 04525 // if every working set above its maximum was at its maximum. 04526 // 04527 04528 extern PFN_NUMBER MmPagesAboveWsMaximum; 04529 04530 // 04531 // If memory is becoming short and MmPagesAboveWsMinimum is 04532 // greater than MmPagesAboveWsThreshold, trim working sets. 04533 // 04534 04535 extern PFN_NUMBER MmPagesAboveWsThreshold; 04536 04537 // 04538 // The number of pages to add to a working set if there are ample 04539 // available pages and the working set is below its maximum. 04540 // 04541 04542 extern PFN_NUMBER MmWorkingSetSizeIncrement; 04543 04544 // 04545 // The number of pages to extend the maximum working set size by 04546 // if the working set at its maximum and there are ample available pages. 04547 04548 extern PFN_NUMBER MmWorkingSetSizeExpansion; 04549 04550 // 04551 // The number of pages required to be freed by working set reduction 04552 // before working set reduction is attempted. 04553 // 04554 04555 extern PFN_NUMBER MmWsAdjustThreshold; 04556 04557 // 04558 // The number of pages available to allow the working set to be 04559 // expanded above its maximum. 04560 // 04561 04562 extern PFN_NUMBER MmWsExpandThreshold; 04563 04564 // 04565 // The total number of pages to reduce by working set trimming. 04566 // 04567 04568 extern PFN_NUMBER MmWsTrimReductionGoal; 04569 04570 extern ULONG MiDelayPageFaults; 04571 04572 extern PMMPFN MmPfnDatabase; 04573 04574 extern MMPFNLIST MmZeroedPageListHead; 04575 04576 extern MMPFNLIST MmFreePageListHead; 04577 04578 extern MMPFNLIST MmStandbyPageListHead; 04579 04580 extern MMPFNLIST MmModifiedPageListHead; 04581 04582 extern MMPFNLIST MmModifiedNoWritePageListHead; 04583 04584 extern MMPFNLIST MmBadPageListHead; 04585 04586 extern PMMPFNLIST MmPageLocationList[NUMBER_OF_PAGE_LISTS]; 04587 04588 extern MMPFNLIST MmModifiedPageListByColor[MM_MAXIMUM_NUMBER_OF_COLORS]; 04589 04590 extern ULONG MmModNoWriteInsert; 04591 04592 // 04593 // Event for available pages, set means pages are available. 04594 // 04595 04596 extern KEVENT MmAvailablePagesEvent; 04597 04598 extern KEVENT MmAvailablePagesEventHigh; 04599 04600 // 04601 // Event for the zeroing page thread. 04602 // 04603 04604 extern KEVENT MmZeroingPageEvent; 04605 04606 // 04607 // Boolean to indicate if the zeroing page thread is currently 04608 // active. This is set to true when the zeroing page event is 04609 // set and set to false when the zeroing page thread is done 04610 // zeroing all the pages on the free list. 04611 // 04612 04613 extern BOOLEAN MmZeroingPageThreadActive; 04614 04615 // 04616 // Minimum number of free pages before zeroing page thread starts. 04617 // 04618 04619 extern PFN_NUMBER MmMinimumFreePagesToZero; 04620 04621 // 04622 // Global event to synchronize mapped writing with cleaning segments. 04623 // 04624 04625 extern KEVENT MmMappedFileIoComplete; 04626 04627 // 04628 // Hyper space items. 04629 // 04630 04631 extern PMMPTE MmFirstReservedMappingPte; 04632 04633 extern PMMPTE MmLastReservedMappingPte; 04634 04635 // 04636 // System space sizes - MmNonPagedSystemStart to MM_NON_PAGED_SYSTEM_END 04637 // defines the ranges of PDEs which must be copied into a new process's 04638 // address space. 04639 // 04640 04641 extern PVOID MmNonPagedSystemStart; 04642 04643 extern PCHAR MmSystemSpaceViewStart; 04644 04645 extern LOGICAL MmProtectFreedNonPagedPool; 04646 04647 // 04648 // Pool sizes. 04649 // 04650 04651 extern SIZE_T MmSizeOfNonPagedPoolInBytes; 04652 04653 extern SIZE_T MmMinimumNonPagedPoolSize; 04654 04655 extern SIZE_T MmDefaultMaximumNonPagedPool; 04656 04657 extern ULONG MmMinAdditionNonPagedPoolPerMb; 04658 04659 extern ULONG MmMaxAdditionNonPagedPoolPerMb; 04660 04661 extern SIZE_T MmSizeOfPagedPoolInBytes; 04662 04663 extern SIZE_T MmMaximumNonPagedPoolInBytes; 04664 04665 extern PFN_NUMBER MmAllocatedNonPagedPool; 04666 04667 extern PFN_NUMBER MmSizeOfNonPagedMustSucceed; 04668 04669 extern PVOID MmNonPagedPoolExpansionStart; 04670 04671 extern ULONG MmExpandedPoolBitPosition; 04672 04673 extern PFN_NUMBER MmNumberOfFreeNonPagedPool; 04674 04675 extern ULONG MmMustSucceedPoolBitPosition; 04676 04677 extern ULONG MmNumberOfSystemPtes; 04678 04679 extern ULONG MiRequestedSystemPtes; 04680 04681 extern ULONG MmTotalFreeSystemPtes[MaximumPtePoolTypes]; 04682 04683 extern SIZE_T MmLockPagesLimit; 04684 04685 extern PMMPTE MmSystemPagePtes; 04686 04687 #if !defined (_X86PAE_) 04688 extern ULONG MmSystemPageDirectory; 04689 #else 04690 extern ULONG MmSystemPageDirectory[]; 04691 #endif 04692 04693 extern PMMPTE MmPagedPoolBasePde; 04694 04695 extern SIZE_T MmHeapSegmentReserve; 04696 04697 extern SIZE_T MmHeapSegmentCommit; 04698 04699 extern SIZE_T MmHeapDeCommitTotalFreeThreshold; 04700 04701 extern SIZE_T MmHeapDeCommitFreeBlockThreshold; 04702 04703 #define MI_MAX_FREE_LIST_HEADS 4 04704 04705 extern LIST_ENTRY MmNonPagedPoolFreeListHead[MI_MAX_FREE_LIST_HEADS]; 04706 04707 // 04708 // Counter for flushes of the entire TB. 04709 // 04710 04711 extern ULONG MmFlushCounter; 04712 04713 // 04714 // Pool start and end. 04715 // 04716 04717 extern PVOID MmNonPagedPoolStart; 04718 04719 extern PVOID MmNonPagedPoolEnd; 04720 04721 extern PVOID MmPagedPoolStart; 04722 04723 extern PVOID MmPagedPoolEnd; 04724 04725 extern PVOID MmNonPagedMustSucceed; 04726 04727 // 04728 // Pool bit maps and other related structures. 04729 // 04730 04731 typedef struct _MM_PAGED_POOL_INFO { 04732 04733 PRTL_BITMAP PagedPoolAllocationMap; 04734 PRTL_BITMAP EndOfPagedPoolBitmap; 04735 PRTL_BITMAP PagedPoolLargeSessionAllocationMap; // HYDRA only 04736 PMMPTE FirstPteForPagedPool; 04737 PMMPTE LastPteForPagedPool; 04738 PMMPTE NextPdeForPagedPoolExpansion; 04739 ULONG PagedPoolHint; 04740 SIZE_T PagedPoolCommit; 04741 SIZE_T AllocatedPagedPool; 04742 04743 } MM_PAGED_POOL_INFO, *PMM_PAGED_POOL_INFO; 04744 04745 extern MM_PAGED_POOL_INFO MmPagedPoolInfo; 04746 04747 extern PVOID MmPageAlignedPoolBase[2]; 04748 04749 extern PRTL_BITMAP VerifierLargePagedPoolMap; 04750 04751 // 04752 // MmFirstFreeSystemPte contains the offset from the 04753 // Nonpaged system base to the first free system PTE. 04754 // Note, that an offset of zero indicates an empty list. 04755 // 04756 04757 extern MMPTE MmFirstFreeSystemPte[MaximumPtePoolTypes]; 04758 04759 extern ULONG_PTR MiSystemViewStart; 04760 04761 // 04762 // System cache sizes. 04763 // 04764 04765 //extern MMSUPPORT MmSystemCacheWs; 04766 04767 extern PMMWSL MmSystemCacheWorkingSetList; 04768 04769 extern PMMWSLE MmSystemCacheWsle; 04770 04771 extern PVOID MmSystemCacheStart; 04772 04773 extern PVOID MmSystemCacheEnd; 04774 04775 extern PRTL_BITMAP MmSystemCacheAllocationMap; 04776 04777 extern PRTL_BITMAP MmSystemCacheEndingMap; 04778 04779 extern PFN_NUMBER MmSystemCacheWsMinimum; 04780 04781 extern PFN_NUMBER MmSystemCacheWsMaximum; 04782 04783 // 04784 // Virtual alignment for PTEs (machine specific) minimum value is 04785 // 0 (no alignment) maximum value is 64k. The maximum value can be raised by 04786 // changing the MM_PROTO_PTE_ALIGNMENT constant and adding more 04787 // reserved mapping PTEs in hyperspace. 04788 // 04789 04790 extern ULONG MmAliasAlignment; 04791 04792 // 04793 // Mask to AND with virtual address to get an offset to go 04794 // with the alignment. This value is page aligned. 04795 // 04796 04797 extern ULONG MmAliasAlignmentOffset; 04798 04799 // 04800 // Mask to and with PTEs to determine if the alias mapping is compatible. 04801 // This value is usually (MmAliasAlignment - 1) 04802 // 04803 04804 extern ULONG MmAliasAlignmentMask; 04805 04806 // 04807 // Cells to track unused thread kernel stacks to avoid TB flushes 04808 // every time a thread terminates. 04809 // 04810 04811 extern ULONG MmNumberDeadKernelStacks; 04812 extern ULONG MmMaximumDeadKernelStacks; 04813 extern PMMPFN MmFirstDeadKernelStack; 04814 04815 // 04816 // MmSystemPteBase contains the address of 1 PTE before 04817 // the first free system PTE (zero indicates an empty list). 04818 // The value of this field does not change once set. 04819 // 04820 04821 extern PMMPTE MmSystemPteBase; 04822 04823 extern PMMWSL MmWorkingSetList; 04824 04825 extern PMMWSLE MmWsle; 04826 04827 // 04828 // Root of system space virtual address descriptors. These define 04829 // the pagable portion of the system. 04830 // 04831 04832 extern PMMVAD MmVirtualAddressDescriptorRoot; 04833 04834 extern PMMADDRESS_NODE MmSectionBasedRoot; 04835 04836 extern PVOID MmHighSectionBase; 04837 04838 // 04839 // Section commit mutex. 04840 // 04841 04842 extern FAST_MUTEX MmSectionCommitMutex; 04843 04844 // 04845 // Section base address mutex. 04846 // 04847 04848 extern FAST_MUTEX MmSectionBasedMutex; 04849 04850 // 04851 // Resource for section extension. 04852 // 04853 04854 extern ERESOURCE MmSectionExtendResource; 04855 extern ERESOURCE MmSectionExtendSetResource; 04856 04857 // 04858 // Event to synchronize threads within process mapping images via hyperspace. 04859 // 04860 04861 extern KEVENT MmImageMappingPteEvent; 04862 04863 // 04864 // Inpage cluster sizes for executable pages (set based on memory size). 04865 // 04866 04867 extern ULONG MmDataClusterSize; 04868 04869 extern ULONG MmCodeClusterSize; 04870 04871 // 04872 // Pagefile creation mutex. 04873 // 04874 04875 extern FAST_MUTEX MmPageFileCreationLock; 04876 04877 // 04878 // Event to set when first paging file is created. 04879 // 04880 04881 extern PKEVENT MmPagingFileCreated; 04882 04883 // 04884 // Paging file debug information. 04885 // 04886 04887 extern ULONG_PTR MmPagingFileDebug[]; 04888 04889 // 04890 // Spinlock which guards PFN database. This spinlock is used by 04891 // memory management for accessing the PFN database. The I/O 04892 // system makes use of it for unlocking pages during I/O complete. 04893 // 04894 04895 extern KSPIN_LOCK MmPfnLock; 04896 04897 // 04898 // Spinlock which guards the working set list for the system shared 04899 // address space (paged pool, system cache, pagable drivers). 04900 // 04901 04902 extern ERESOURCE MmSystemWsLock; 04903 04904 // 04905 // Spin lock for allocating non-paged PTEs from system space. 04906 // 04907 04908 extern KSPIN_LOCK MmSystemSpaceLock; 04909 04910 // 04911 // Spin lock for operating on page file commit charges. 04912 // 04913 04914 extern KSPIN_LOCK MmChargeCommitmentLock; 04915 04916 // 04917 // Spin lock for allowing working set expansion. 04918 // 04919 04920 extern KSPIN_LOCK MmExpansionLock; 04921 04922 // 04923 // To prevent optimizations. 04924 // 04925 04926 extern MMPTE GlobalPte; 04927 04928 // 04929 // Page color for system working set. 04930 // 04931 04932 extern ULONG MmSystemPageColor; 04933 04934 extern ULONG MmSecondaryColors; 04935 04936 extern ULONG MmProcessColorSeed; 04937 04938 // 04939 // Set from ntos\config\CMDAT3.C Used by customers to disable paging 04940 // of executive on machines with lots of memory. Worth a few TPS on a 04941 // data base server. 04942 // 04943 04944 extern ULONG MmDisablePagingExecutive; 04945 04946 04947 // 04948 // For debugging. 04949 04950 04951 #if DBG 04952 extern ULONG MmDebug; 04953 #endif 04954 04955 // 04956 // Unused segment management 04957 // 04958 04959 extern MMDEREFERENCE_SEGMENT_HEADER MmDereferenceSegmentHeader; 04960 04961 extern LIST_ENTRY MmUnusedSegmentList; 04962 04963 extern KEVENT MmUnusedSegmentCleanup; 04964 04965 extern SIZE_T MmMaxUnusedSegmentPagedPoolUsage; 04966 04967 extern SIZE_T MmUnusedSegmentPagedPoolUsage; 04968 extern SIZE_T MiUnusedSegmentPagedPoolUsage; 04969 04970 extern SIZE_T MmUnusedSegmentPagedPoolReduction; 04971 04972 extern SIZE_T MmMaxUnusedSegmentNonPagedPoolUsage; 04973 04974 extern SIZE_T MmUnusedSegmentNonPagedPoolUsage; 04975 extern SIZE_T MiUnusedSegmentNonPagedPoolUsage; 04976 04977 extern SIZE_T MmUnusedSegmentNonPagedPoolReduction; 04978 04979 extern ULONG MmUnusedSegmentTrimLevel; 04980 04981 extern ULONG MmUnusedSegmentCount; 04982 04983 #define MI_UNUSED_SEGMENTS_COUNT_UPDATE(_count) \ 04984 MmUnusedSegmentCount += (_count); 04985 04986 #define MI_FILESYSTEM_NONPAGED_POOL_CHARGE 150 04987 04988 #define MI_FILESYSTEM_PAGED_POOL_CHARGE 1024 04989 04990 //++ 04991 //LOGICAL 04992 //MI_UNUSED_SEGMENTS_SURPLUS ( 04993 // IN PVOID va 04994 // ); 04995 // 04996 // Routine Description: 04997 // 04998 // This routine determines whether a surplus of unused 04999 // segments exist. If so, the caller can initiate a trim to free pool. 05000 // 05001 // Arguments 05002 // 05003 // None. 05004 // 05005 // Return Value: 05006 // 05007 // TRUE if unused segment trimming should be initiated, FALSE if not. 05008 // 05009 //-- 05010 #define MI_UNUSED_SEGMENTS_SURPLUS() \ 05011 (MmUnusedSegmentPagedPoolUsage > MmMaxUnusedSegmentPagedPoolUsage) || \ 05012 (MmUnusedSegmentNonPagedPoolUsage > MmMaxUnusedSegmentNonPagedPoolUsage) 05013 05014 //++ 05015 //VOID 05016 //MI_UNUSED_SEGMENTS_INSERT_CHARGE ( 05017 // IN PCONTROL_AREA _ControlArea 05018 // ); 05019 // 05020 // Routine Description: 05021 // 05022 // This routine manages pool charges during insertions of segments to 05023 // the unused segment list. 05024 // 05025 // Arguments 05026 // 05027 // _ControlArea - Supplies the control area to obtain the pool charges from. 05028 // 05029 // Return Value: 05030 // 05031 // None. 05032 // 05033 //-- 05034 #define MI_UNUSED_SEGMENTS_INSERT_CHARGE(_ControlArea) \ 05035 { \ 05036 MM_PFN_LOCK_ASSERT(); \ 05037 ASSERT (_ControlArea->PagedPoolUsage >= sizeof(SEGMENT)); \ 05038 ASSERT (_ControlArea->NonPagedPoolUsage >= sizeof(CONTROL_AREA) + sizeof(SUBSECTION)); \ 05039 ASSERT (MiUnusedSegmentNonPagedPoolUsage + _ControlArea->NonPagedPoolUsage > MiUnusedSegmentNonPagedPoolUsage); \ 05040 ASSERT (MiUnusedSegmentPagedPoolUsage + _ControlArea->PagedPoolUsage > MiUnusedSegmentPagedPoolUsage); \ 05041 MiUnusedSegmentPagedPoolUsage += _ControlArea->PagedPoolUsage; \ 05042 MiUnusedSegmentNonPagedPoolUsage += _ControlArea->NonPagedPoolUsage;\ 05043 MmUnusedSegmentPagedPoolUsage += (_ControlArea->PagedPoolUsage + MI_FILESYSTEM_PAGED_POOL_CHARGE); \ 05044 MmUnusedSegmentNonPagedPoolUsage += (_ControlArea->NonPagedPoolUsage + MI_FILESYSTEM_NONPAGED_POOL_CHARGE);\ 05045 MI_UNUSED_SEGMENTS_COUNT_UPDATE(1); \ 05046 } 05047 05048 //++ 05049 //VOID 05050 //MI_UNUSED_SEGMENTS_REMOVE_CHARGE ( 05051 // IN PCONTROL_AREA _ControlArea 05052 // ); 05053 // 05054 // Routine Description: 05055 // 05056 // This routine manages pool charges during removals of segments from 05057 // the unused segment list. 05058 // 05059 // Arguments 05060 // 05061 // _ControlArea - Supplies the control area to obtain the pool charges from. 05062 // 05063 // Return Value: 05064 // 05065 // None. 05066 // 05067 //-- 05068 #define MI_UNUSED_SEGMENTS_REMOVE_CHARGE(_ControlArea) \ 05069 { \ 05070 MM_PFN_LOCK_ASSERT(); \ 05071 ASSERT (_ControlArea->PagedPoolUsage >= sizeof(SEGMENT)); \ 05072 ASSERT (_ControlArea->NonPagedPoolUsage >= sizeof(CONTROL_AREA) + sizeof(SUBSECTION)); \ 05073 ASSERT (MmUnusedSegmentNonPagedPoolUsage - _ControlArea->NonPagedPoolUsage < MmUnusedSegmentNonPagedPoolUsage); \ 05074 ASSERT (MmUnusedSegmentPagedPoolUsage - _ControlArea->PagedPoolUsage < MmUnusedSegmentPagedPoolUsage); \ 05075 MiUnusedSegmentPagedPoolUsage -= _ControlArea->PagedPoolUsage; \ 05076 MiUnusedSegmentNonPagedPoolUsage -= _ControlArea->NonPagedPoolUsage;\ 05077 MmUnusedSegmentPagedPoolUsage -= (_ControlArea->PagedPoolUsage + MI_FILESYSTEM_PAGED_POOL_CHARGE); \ 05078 MmUnusedSegmentNonPagedPoolUsage -= (_ControlArea->NonPagedPoolUsage + MI_FILESYSTEM_NONPAGED_POOL_CHARGE);\ 05079 MI_UNUSED_SEGMENTS_COUNT_UPDATE(-1); \ 05080 } 05081 05082 // 05083 // List heads 05084 // 05085 05086 extern MMWORKING_SET_EXPANSION_HEAD MmWorkingSetExpansionHead; 05087 05088 extern MMPAGE_FILE_EXPANSION MmAttemptForCantExtend; 05089 05090 // 05091 // Paging files 05092 // 05093 05094 extern MMMOD_WRITER_LISTHEAD MmPagingFileHeader; 05095 05096 extern MMMOD_WRITER_LISTHEAD MmMappedFileHeader; 05097 05098 extern PMMPAGING_FILE MmPagingFile[MAX_PAGE_FILES]; 05099 05100 #define MM_MAPPED_FILE_MDLS 4 05101 05102 05103 extern PMMMOD_WRITER_MDL_ENTRY MmMappedFileMdl[MM_MAPPED_FILE_MDLS]; 05104 05105 extern LIST_ENTRY MmFreePagingSpaceLow; 05106 05107 extern ULONG MmNumberOfActiveMdlEntries; 05108 05109 extern ULONG MmNumberOfPagingFiles; 05110 05111 extern KEVENT MmModifiedPageWriterEvent; 05112 05113 extern KEVENT MmCollidedFlushEvent; 05114 05115 extern KEVENT MmCollidedLockEvent; 05116 05117 // 05118 // Total number of committed pages. 05119 // 05120 05121 extern SIZE_T MmTotalCommittedPages; 05122 05123 extern SIZE_T MmTotalCommitLimit; 05124 05125 extern SIZE_T MmOverCommit; 05126 05127 extern SIZE_T MmSharedCommit; 05128 05129 // 05130 // Modified page writer. 05131 // 05132 05133 extern PFN_NUMBER MmMinimumFreePages; 05134 05135 extern PFN_NUMBER MmFreeGoal; 05136 05137 extern PFN_NUMBER MmModifiedPageMaximum; 05138 05139 extern PFN_NUMBER MmModifiedPageMinimum; 05140 05141 extern ULONG MmModifiedWriteClusterSize; 05142 05143 extern ULONG MmMinimumFreeDiskSpace; 05144 05145 extern ULONG MmPageFileExtension; 05146 05147 extern ULONG MmMinimumPageFileReduction; 05148 05149 extern LARGE_INTEGER MiModifiedPageLife; 05150 05151 extern BOOLEAN MiTimerPending; 05152 05153 extern KEVENT MiMappedPagesTooOldEvent; 05154 05155 extern KDPC MiModifiedPageWriterTimerDpc; 05156 05157 extern KTIMER MiModifiedPageWriterTimer; 05158 05159 // 05160 // System process working set sizes. 05161 // 05162 05163 extern PFN_NUMBER MmSystemProcessWorkingSetMin; 05164 05165 extern PFN_NUMBER MmSystemProcessWorkingSetMax; 05166 05167 extern PFN_NUMBER MmMinimumWorkingSetSize; 05168 05169 // 05170 // Support for debugger's mapping physical memory. 05171 // 05172 05173 extern PMMPTE MmDebugPte; 05174 05175 extern PMMPTE MmCrashDumpPte; 05176 05177 extern ULONG MiOverCommitCallCount; 05178 05179 extern SIZE_T MmResTrack[MM_BUMP_COUNTER_MAX]; 05180 05181 // 05182 // Event tracing routines 05183 // 05184 05185 extern PPAGE_FAULT_NOTIFY_ROUTINE MmPageFaultNotifyRoutine; 05186 extern PHARD_FAULT_NOTIFY_ROUTINE MmHardFaultNotifyRoutine; 05187 05188 // 05189 // This is a special value loaded into an EPROCESS pointer to indicate that 05190 // the action underway is for a Hydra session, not really the current process. 05191 // (Any value could be used here that is not a valid system pointer or NULL). 05192 // 05193 05194 #define HYDRA_PROCESS ((PEPROCESS)1) 05195 05196 /*++ 05197 05198 Virtual Memory Layout of the 48MB Session space when loaded at 0xA0000000 05199 05200 +------------------------------------+ 05201 A0000000 | | 05202 | win32k.sys, video drivers and any | 05203 | rebased NT4 printer drivers. | 05204 | | 05205 | (8MB) | 05206 | | 05207 +------------------------------------+ 05208 A0800000 | | 05209 | MM_SESSION_SPACE & Session WSLs | 05210 | (4MB) | 05211 | | 05212 +------------------------------------+ 05213 A0C00000 | | 05214 | Mapped Views for this session | 05215 | (20MB) | 05216 | | 05217 +------------------------------------+ 05218 A2000000 | | 05219 | Paged Pool for this session | 05220 | (16MB) | 05221 | | 05222 A3000000 +------------------------------------+ 05223 05224 --*/ 05225 05226 extern ULONG_PTR MmSessionBase; 05227 05228 // 05229 // Sizes of Session fields. 05230 // 05231 05232 #define MI_SESSION_SPACE_STRUCT_SIZE MM_ALLOCATION_GRANULARITY 05233 05234 #define MI_SESSION_SPACE_WS_SIZE (4*1024*1024 - MI_SESSION_SPACE_STRUCT_SIZE) 05235 05236 #define MI_SESSION_IMAGE_SIZE (8*1024*1024) 05237 05238 #define MI_SESSION_VIEW_SIZE (20*1024*1024) 05239 05240 #define MI_SESSION_POOL_SIZE (16*1024*1024) 05241 05242 #define MM_SESSION_SPACE_DATA_SIZE PAGE_SIZE 05243 05244 #define MI_SESSION_SPACE_TOTAL_SIZE \ 05245 (MI_SESSION_IMAGE_SIZE + \ 05246 MI_SESSION_SPACE_STRUCT_SIZE + \ 05247 MI_SESSION_SPACE_WS_SIZE + \ 05248 MI_SESSION_VIEW_SIZE + \ 05249 MI_SESSION_POOL_SIZE) 05250 05251 // 05252 // Actually this is a little larger due to page table pages, etc, but this is 05253 // all handled ok. 05254 // 05255 05256 #define MI_SESSION_MAXIMUM_WORKING_SET \ 05257 ((ULONG)(MI_SESSION_SPACE_TOTAL_SIZE >> PAGE_SHIFT)) 05258 05259 // 05260 // The number of page table pages required to map all of session space. 05261 // 05262 05263 #define MI_SESSION_SPACE_PAGE_TABLES \ 05264 (MI_SESSION_SPACE_TOTAL_SIZE / MM_VA_MAPPED_BY_PDE) 05265 05266 05267 // 05268 // Offsets from MmSessionBase. 05269 // 05270 05271 #define MI_SESSION_IMAGE_OFFSET (0) 05272 05273 #define MI_SESSION_DATA_OFFSET (8*1024*1024) 05274 05275 #define MI_SESSION_WS_OFFSET (8*1024*1024 + MI_SESSION_SPACE_STRUCT_SIZE) 05276 05277 #define MI_SESSION_VIEW_OFFSET (12*1024*1024) 05278 05279 #define MI_SESSION_POOL_OFFSET (32*1024*1024) 05280 05281 05282 05283 // 05284 // Virtual addresses of various session fields. 05285 // 05286 05287 #define MI_SESSION_IMAGE_START ((ULONG_PTR)MmSessionBase) 05288 05289 #define MI_SESSION_SPACE_WS (MmSessionBase + MI_SESSION_WS_OFFSET) 05290 05291 #define MI_SESSION_VIEW_START (MmSessionBase + MI_SESSION_VIEW_OFFSET) 05292 05293 #define MI_SESSION_POOL (MmSessionBase + MI_SESSION_POOL_OFFSET) 05294 05295 #define MI_SESSION_SPACE_END ((ULONG_PTR)MmSessionBase + \ 05296 MI_SESSION_SPACE_TOTAL_SIZE) 05297 05298 // 05299 // Macros to determine if a given address lies in the specified session range. 05300 // 05301 05302 #define MI_IS_SESSION_IMAGE_ADDRESS(VirtualAddress) \ 05303 (MiHydra == TRUE && (PVOID)(VirtualAddress) >= (PVOID)MI_SESSION_IMAGE_START && (PVOID)(VirtualAddress) < (PVOID)(MI_SESSION_IMAGE_START + MI_SESSION_IMAGE_SIZE)) 05304 05305 #define MI_IS_SESSION_POOL_ADDRESS(VirtualAddress) \ 05306 (MiHydra == TRUE && (PVOID)(VirtualAddress) >= (PVOID)MI_SESSION_POOL && (PVOID)(VirtualAddress) < (PVOID)(MI_SESSION_POOL + MI_SESSION_POOL_SIZE)) 05307 05308 #define MI_IS_SESSION_ADDRESS(_VirtualAddress) \ 05309 (MiHydra == TRUE && (PVOID)(_VirtualAddress) >= (PVOID)MmSessionBase && (PVOID)(_VirtualAddress) < (PVOID)(MI_SESSION_SPACE_END)) 05310 05311 #define MI_IS_SESSION_PTE(_Pte) \ 05312 (MiHydra == TRUE && (PMMPTE)(_Pte) >= MiSessionBasePte && (PMMPTE)(_Pte) < MiSessionLastPte) 05313 05314 05315 #define SESSION_GLOBAL(_Session) (_Session->GlobalVirtualAddress) 05316 05317 #define MM_DBG_SESSION_INITIAL_PAGETABLE_ALLOC 0 05318 #define MM_DBG_SESSION_INITIAL_PAGETABLE_FREE_RACE 1 05319 #define MM_DBG_SESSION_INITIAL_PAGE_ALLOC 2 05320 #define MM_DBG_SESSION_INITIAL_PAGE_FREE_FAIL1 3 05321 #define MM_DBG_SESSION_INITIAL_PAGETABLE_FREE_FAIL1 4 05322 #define MM_DBG_SESSION_WS_PAGE_FREE 5 05323 #define MM_DBG_SESSION_PAGETABLE_ALLOC 6 05324 #define MM_DBG_SESSION_SYSMAPPED_PAGES_ALLOC 7 05325 #define MM_DBG_SESSION_WS_PAGETABLE_ALLOC 8 05326 #define MM_DBG_SESSION_PAGEDPOOL_PAGETABLE_ALLOC 9 05327 #define MM_DBG_SESSION_PAGEDPOOL_PAGETABLE_FREE_FAIL1 10 05328 #define MM_DBG_SESSION_WS_PAGE_ALLOC 11 05329 #define MM_DBG_SESSION_WS_PAGE_ALLOC_GROWTH 12 05330 #define MM_DBG_SESSION_INITIAL_PAGE_FREE 13 05331 #define MM_DBG_SESSION_PAGETABLE_FREE 14 05332 #define MM_DBG_SESSION_PAGEDPOOL_PAGETABLE_ALLOC1 15 05333 #define MM_DBG_SESSION_DRIVER_PAGES_LOCKED 16 05334 #define MM_DBG_SESSION_DRIVER_PAGES_UNLOCKED 17 05335 #define MM_DBG_SESSION_WS_HASHPAGE_ALLOC 18 05336 #define MM_DBG_SESSION_SYSMAPPED_PAGES_COMMITTED 19 05337 05338 #define MM_DBG_SESSION_COMMIT_PAGEDPOOL_PAGES 30 05339 #define MM_DBG_SESSION_COMMIT_DELETE_VM_RETURN 31 05340 #define MM_DBG_SESSION_COMMIT_POOL_FREED 32 05341 #define MM_DBG_SESSION_COMMIT_IMAGE_UNLOAD 33 05342 #define MM_DBG_SESSION_COMMIT_IMAGELOAD_FAILED1 34 05343 #define MM_DBG_SESSION_COMMIT_IMAGELOAD_FAILED2 35 05344 #define MM_DBG_SESSION_COMMIT_IMAGELOAD_NOACCESS 36 05345 05346 #if DBG 05347 #define MM_SESS_COUNTER_MAX 40 05348 05349 #define MM_BUMP_SESS_COUNTER(_index, bump) \ 05350 if (_index >= MM_SESS_COUNTER_MAX) { \ 05351 DbgPrint("Mm: Invalid bump counter %d %d\n", _index, MM_SESS_COUNTER_MAX); \ 05352 DbgBreakPoint(); \ 05353 } \ 05354 else if (MiHydra == TRUE) { \ 05355 MmSessionSpace->Debug[_index] += (bump); \ 05356 } 05357 05358 typedef struct _MM_SESSION_MEMORY_COUNTERS { 05359 SIZE_T NonPagablePages; 05360 SIZE_T CommittedPages; 05361 } MM_SESSION_MEMORY_COUNTERS, *PMM_SESSION_MEMORY_COUNTERS; 05362 05363 #define MM_SESS_MEMORY_COUNTER_MAX 8 05364 05365 #define MM_SNAP_SESS_MEMORY_COUNTERS(_index) \ 05366 if (_index >= MM_SESS_MEMORY_COUNTER_MAX) { \ 05367 DbgPrint("Mm: Invalid session mem counter %d %d\n", _index, MM_SESS_MEMORY_COUNTER_MAX); \ 05368 DbgBreakPoint(); \ 05369 } \ 05370 else { \ 05371 MmSessionSpace->Debug2[_index].NonPagablePages = MmSessionSpace->NonPagablePages; \ 05372 MmSessionSpace->Debug2[_index].CommittedPages = MmSessionSpace->CommittedPages; \ 05373 } 05374 05375 #else 05376 #define MM_BUMP_SESS_COUNTER(_index, bump) 05377 #define MM_SNAP_SESS_MEMORY_COUNTERS(_index) 05378 #endif 05379 05380 05381 #define MM_SESSION_FAILURE_NO_IDS 0 05382 #define MM_SESSION_FAILURE_NO_COMMIT 1 05383 #define MM_SESSION_FAILURE_NO_RESIDENT 2 05384 #define MM_SESSION_FAILURE_RACE_DETECTED 3 05385 #define MM_SESSION_FAILURE_NO_SYSPTES 4 05386 #define MM_SESSION_FAILURE_NO_PAGED_POOL 5 05387 #define MM_SESSION_FAILURE_NO_NONPAGED_POOL 6 05388 #define MM_SESSION_FAILURE_NO_IMAGE_VA_SPACE 7 05389 #define MM_SESSION_FAILURE_NO_SESSION_PAGED_POOL 8 05390 05391 #define MM_SESSION_FAILURE_CAUSES 9 05392 05393 ULONG MmSessionFailureCauses[MM_SESSION_FAILURE_CAUSES]; 05394 05395 #define MM_BUMP_SESSION_FAILURES(_index) MmSessionFailureCauses[_index] += 1; 05396 05397 // 05398 // Note that modifying session space flag bits must be synchronized on Alpha. 05399 // 05400 05401 typedef struct _MM_SESSION_SPACE_FLAGS { 05402 ULONG Initialized : 1; 05403 ULONG BeingDeleted : 1; 05404 ULONG WorkingSetInserted : 1; 05405 ULONG SessionListInserted : 1; 05406 ULONG HasWsLock : 1; 05407 ULONG DeletePending : 1; 05408 ULONG Filler : 26; 05409 } MM_SESSION_SPACE_FLAGS; 05410 05411 // 05412 // The session space data structure - allocated per session and only visible at 05413 // MM_SESSION_SPACE_BASE when in the context of a process from the session. 05414 // This virtual address space is rotated at context switch time when switching 05415 // from a process in session A to a process in session B. This rotation is 05416 // useful for things like providing paged pool per session so many sessions 05417 // won't exhaust the VA space which backs the system global pool. 05418 // 05419 // A kernel PTE is also allocated to double map this page so that global 05420 // pointers can be maintained to provide system access from any process context. 05421 // This is needed for things like mutexes and WSL chains. 05422 // 05423 05424 typedef struct _MM_SESSION_SPACE { 05425 05426 ULONG ReferenceCount; 05427 union { 05428 ULONG LongFlags; 05429 MM_SESSION_SPACE_FLAGS Flags; 05430 } u; 05431 ULONG SessionId; 05432 05433 // 05434 // All the page tables for session space use this as their parent. 05435 // Note that it's not really a page directory - it's really a page 05436 // table page itself (the one used to map this very structure). 05437 // 05438 // This provides a reference to something that won't go away and 05439 // is relevant regardless of which process within the session is current. 05440 // 05441 05442 PFN_NUMBER SessionPageDirectoryIndex; 05443 05444 // 05445 // This is a pointer in global system address space, used to make various 05446 // fields that can be referenced from any process visible from any process 05447 // context. This is for things like mutexes, WSL chains, etc. 05448 // 05449 05450 struct _MM_SESSION_SPACE *GlobalVirtualAddress; 05451 05452 KSPIN_LOCK SpinLock; 05453 05454 // 05455 // This is the list of the processes in this group that have 05456 // session space entries. 05457 // 05458 05459 LIST_ENTRY ProcessList; 05460 05461 // 05462 // Pool allocation counts - these are always valid. 05463 // 05464 05465 SIZE_T NonPagedPoolBytes; 05466 SIZE_T PagedPoolBytes; 05467 ULONG NonPagedPoolAllocations; 05468 ULONG PagedPoolAllocations; 05469 05470 // 05471 // This is the count of non paged allocations to support this session 05472 // space. This includes the session structure page table and data pages, 05473 // WSL page table and data pages, session pool page table pages and session 05474 // image page table pages. These are all charged against 05475 // MmResidentAvailable. 05476 // 05477 05478 SIZE_T NonPagablePages; 05479 05480 // 05481 // This is the count of pages in this session that have been charged against 05482 // the systemwide commit. This includes all the NonPagablePages plus the 05483 // data pages they typically map. 05484 // 05485 05486 SIZE_T CommittedPages; 05487 05488 LARGE_INTEGER LastProcessSwappedOutTime; 05489 05490 #if defined (_WIN64) 05491 05492 // 05493 // The page directory that maps session space is saved here so 05494 // trimmers can attach. 05495 // 05496 05497 MMPTE PageDirectory; 05498 05499 #else 05500 05501 // 05502 // The second level page tables that map session space are shared 05503 // by all processes in the session. 05504 // 05505 05506 MMPTE PageTables[MI_SESSION_SPACE_PAGE_TABLES]; 05507 05508 #endif 05509 05510 // 05511 // Session space paged pool support. 05512 // 05513 05514 FAST_MUTEX PagedPoolMutex; 05515 05516 // 05517 // Start of session paged pool virtual space. 05518 // 05519 05520 PVOID PagedPoolStart; 05521 05522 // 05523 // Current end of pool virtual space. Can be extended to the 05524 // end of the session space. 05525 // 05526 05527 PVOID PagedPoolEnd; 05528 05529 // 05530 // PTE pointers for pool. 05531 // 05532 05533 PMMPTE PagedPoolBasePde; 05534 05535 MM_PAGED_POOL_INFO PagedPoolInfo; 05536 05537 ULONG Color; 05538 05539 ULONG ProcessOutSwapCount; 05540 05541 // 05542 // This is the list of system images currently valid in 05543 // this session space. This information is in addition 05544 // to the module global information in PsLoadedModuleList. 05545 // 05546 05547 LIST_ENTRY ImageList; 05548 05549 // 05550 // The system PTE self-map entry. 05551 // 05552 05553 PMMPTE GlobalPteEntry; 05554 05555 ULONG CopyOnWriteCount; 05556 05557 // 05558 // The count of "known attachers and the associated event. 05559 // 05560 05561 ULONG AttachCount; 05562 05563 KEVENT AttachEvent; 05564 05565 PEPROCESS LastProcess; 05566 05567 // 05568 // Working set information. 05569 // 05570 05571 MMSUPPORT Vm; 05572 PMMWSLE Wsle; 05573 05574 ERESOURCE WsLock; // owned by WorkingSetLockOwner 05575 05576 // 05577 // This chain is in global system addresses (not session VAs) and can 05578 // be walked from any system context, ie: for WSL trimming. 05579 // 05580 05581 LIST_ENTRY WsListEntry; 05582 05583 // 05584 // Support for mapping system views into session space. Each desktop 05585 // allocates a 3MB heap and the global system view space is only 48M 05586 // total. This would limit us to only 20-30 users - rotating the 05587 // system view space with each session removes this limitation. 05588 // 05589 05590 MMSESSION Session; 05591 05592 // 05593 // This is the driver object entry for WIN32K.SYS 05594 // 05595 // It is not a real driver object, but contained here 05596 // for information such as the DriverUnload routine. 05597 // 05598 05599 DRIVER_OBJECT Win32KDriverObject; 05600 05601 PETHREAD WorkingSetLockOwner; 05602 05603 // 05604 // Pool descriptor for less than 1 page allocations. 05605 // 05606 05607 POOL_DESCRIPTOR PagedPool; 05608 05609 #if defined(_IA64_) 05610 REGION_MAP_INFO SessionMapInfo; 05611 #endif 05612 05613 #if DBG 05614 PETHREAD SessionLockOwner; 05615 ULONG WorkingSetLockOwnerCount; 05616 05617 ULONG_PTR Debug[MM_SESS_COUNTER_MAX]; 05618 05619 MM_SESSION_MEMORY_COUNTERS Debug2[MM_SESS_MEMORY_COUNTER_MAX]; 05620 #endif 05621 05622 } MM_SESSION_SPACE, *PMM_SESSION_SPACE; 05623 05624 extern PMM_SESSION_SPACE MmSessionSpace; 05625 05626 extern ULONG MiSessionCount; 05627 05628 // 05629 // This could be improved to just flush the non-global TB entries. 05630 // 05631 05632 #define MI_FLUSH_SESSION_TB(OLDIRQL) KeRaiseIrql (DISPATCH_LEVEL, &OLDIRQL); \ 05633 KeFlushEntireTb (TRUE, TRUE); \ 05634 KeLowerIrql (OLDIRQL); 05635 05636 #if DBG 05637 #define MM_SET_SESSION_LOCK_OWNER() ASSERT (MmSessionSpace->SessionLockOwner == NULL); \ 05638 MmSessionSpace->SessionLockOwner = PsGetCurrentThread(); 05639 05640 #define MM_CLEAR_SESSION_LOCK_OWNER() ASSERT (MmSessionSpace->SessionLockOwner == PsGetCurrentThread()); \ 05641 MmSessionSpace->SessionLockOwner = NULL; 05642 #else 05643 #define MM_SET_SESSION_LOCK_OWNER() 05644 #define MM_CLEAR_SESSION_LOCK_OWNER() 05645 #endif 05646 05647 #define LOCK_SESSION(OLDIRQL) ExAcquireSpinLock (&((SESSION_GLOBAL(MmSessionSpace))->SpinLock), &OLDIRQL); \ 05648 MM_SET_SESSION_LOCK_OWNER (); 05649 05650 #define UNLOCK_SESSION(OLDIRQL) MM_CLEAR_SESSION_LOCK_OWNER (); \ 05651 ExReleaseSpinLock (&((SESSION_GLOBAL(MmSessionSpace))->SpinLock), OLDIRQL); 05652 05653 // 05654 // The default number of pages for the session working set minimum & maximum. 05655 // 05656 05657 #define MI_SESSION_SPACE_WORKING_SET_MINIMUM 20 05658 05659 #define MI_SESSION_SPACE_WORKING_SET_MAXIMUM 384 05660 05661 NTSTATUS 05662 MiSessionCommitPageTables( 05663 PVOID StartVa, 05664 PVOID EndVa 05665 ); 05666 05667 NTSTATUS 05668 MiInitializeSessionPool( 05669 VOID 05670 ); 05671 05672 VOID 05673 MiCheckSessionPoolAllocations( 05674 VOID 05675 ); 05676 05677 VOID 05678 MiFreeSessionPoolBitMaps( 05679 VOID 05680 ); 05681 05682 VOID 05683 MiDetachSession( 05684 VOID 05685 ); 05686 05687 VOID 05688 MiAttachSession( 05689 IN PMM_SESSION_SPACE SessionGlobal 05690 ); 05691 05692 #define MM_SET_SESSION_RESOURCE_OWNER() \ 05693 ASSERT (MmSessionSpace->WorkingSetLockOwner == NULL); \ 05694 MmSessionSpace->WorkingSetLockOwner = PsGetCurrentThread(); 05695 05696 #define MM_CLEAR_SESSION_RESOURCE_OWNER() \ 05697 ASSERT (MmSessionSpace->WorkingSetLockOwner == PsGetCurrentThread()); \ 05698 MmSessionSpace->WorkingSetLockOwner = NULL; 05699 05700 #define MM_SESSION_SPACE_WS_LOCK_ASSERT() \ 05701 ASSERT (MmSessionSpace->WorkingSetLockOwner == PsGetCurrentThread()) 05702 05703 #define LOCK_SESSION_SPACE_WS(OLDIRQL) \ 05704 ASSERT (KeGetCurrentIrql() <= APC_LEVEL); \ 05705 KeRaiseIrql(APC_LEVEL,&OLDIRQL); \ 05706 ExAcquireResourceExclusive(&MmSessionSpace->WsLock, TRUE); \ 05707 MM_SET_SESSION_RESOURCE_OWNER (); 05708 05709 #define UNLOCK_SESSION_SPACE_WS(OLDIRQL) \ 05710 MM_CLEAR_SESSION_RESOURCE_OWNER (); \ 05711 ExReleaseResource (&MmSessionSpace->WsLock); \ 05712 KeLowerIrql (OLDIRQL); \ 05713 ASSERT (KeGetCurrentIrql() <= APC_LEVEL); 05714 05715 extern PMMPTE MiHighestUserPte; 05716 extern PMMPTE MiHighestUserPde; 05717 05718 extern PMMPTE MiSessionBasePte; 05719 extern PMMPTE MiSessionLastPte; 05720 05721 NTSTATUS 05722 MiEmptyWorkingSet ( 05723 IN PMMSUPPORT WsInfo, 05724 IN LOGICAL WaitOk 05725 ); 05726 05727 //++ 05728 //ULONG 05729 //MiGetPdeSessionIndex ( 05730 // IN PVOID va 05731 // ); 05732 // 05733 // Routine Description: 05734 // 05735 // MiGetPdeSessionIndex returns the session structure index for the PDE 05736 // will (or does) map the given virtual address. 05737 // 05738 // Arguments 05739 // 05740 // Va - Supplies the virtual address to locate the PDE index for. 05741 // 05742 // Return Value: 05743 // 05744 // The index of the PDE entry. 05745 // 05746 //-- 05747 05748 #define MiGetPdeSessionIndex(va) ((ULONG)(((ULONG_PTR)(va) - (ULONG_PTR)MmSessionBase) >> PDI_SHIFT)) 05749 05750 // 05751 // Session space contains the image loader and tracker, virtual 05752 // address allocator, paged pool allocator, system view image mappings, 05753 // and working set for kernel mode virtual addresses that are instanced 05754 // for groups of processes in a Session process group. This 05755 // process group is identified by a SessionId. 05756 // 05757 // Each Session process group's loaded kernel modules, paged pool 05758 // allocations, working set, and mapped system views are separate from 05759 // other Session process groups, even though they have the same 05760 // virtual addresses. 05761 // 05762 // This is to support the Hydra multi-user Windows NT system by 05763 // replicating WIN32K.SYS, and its complement of video and printer drivers, 05764 // desktop heaps, memory allocations, etc. 05765 // 05766 05767 // 05768 // Structure linked into a session space structure to describe 05769 // which system images in PsLoadedModuleTable and 05770 // SESSION_DRIVER_GLOBAL_LOAD_ADDRESS's 05771 // have been allocated for the current session space. 05772 // 05773 // The reference count tracks the number of loads of this image within 05774 // this session. 05775 // 05776 05777 typedef struct _IMAGE_ENTRY_IN_SESSION { 05778 LIST_ENTRY Link; 05779 PVOID Address; 05780 PVOID LastAddress; 05781 ULONG ImageCountInThisSession; 05782 PMMPTE PrototypePtes; 05783 PLDR_DATA_TABLE_ENTRY DataTableEntry; 05784 } IMAGE_ENTRY_IN_SESSION, *PIMAGE_ENTRY_IN_SESSION; 05785 05786 extern LIST_ENTRY MiSessionWsList; 05787 05788 NTSTATUS 05789 FASTCALL 05790 MiCheckPdeForSessionSpace( 05791 IN PVOID VirtualAddress 05792 ); 05793 05794 NTSTATUS 05795 MiShareSessionImage ( 05796 IN PSECTION Section, 05797 IN OUT PSIZE_T ViewSize 05798 ); 05799 05800 VOID 05801 MiSessionWideInitializeAddresses ( 05802 VOID 05803 ); 05804 05805 NTSTATUS 05806 MiSessionWideReserveImageAddress ( 05807 IN PUNICODE_STRING pImageName, 05808 IN PSECTION Section, 05809 IN ULONG_PTR Alignment, 05810 OUT PVOID *ppAddr, 05811 OUT PBOOLEAN pAlreadyLoaded 05812 ); 05813 05814 VOID 05815 MiInitializeSessionIds ( 05816 VOID 05817 ); 05818 05819 VOID 05820 MiInitializeSessionWsSupport( 05821 VOID 05822 ); 05823 05824 VOID 05825 MiSessionAddProcess ( 05826 IN PEPROCESS NewProcess 05827 ); 05828 05829 VOID 05830 MiSessionRemoveProcess ( 05831 VOID 05832 ); 05833 05834 NTSTATUS 05835 MiRemovePsLoadedModule( 05836 PLDR_DATA_TABLE_ENTRY DataTableEntry 05837 ); 05838 05839 NTSTATUS 05840 MiRemoveImageSessionWide( 05841 IN PVOID BaseAddr 05842 ); 05843 05844 NTSTATUS 05845 MiDeleteSessionVirtualAddresses( 05846 IN PVOID VirtualAddress, 05847 IN SIZE_T NumberOfBytes 05848 ); 05849 05850 NTSTATUS 05851 MiUnloadSessionImageByForce ( 05852 IN SIZE_T NumberOfPtes, 05853 IN PVOID ImageBase 05854 ); 05855 05856 NTSTATUS 05857 MiSessionWideGetImageSize( 05858 IN PVOID BaseAddress, 05859 OUT PSIZE_T NumberOfBytes OPTIONAL, 05860 OUT PSIZE_T CommitPages OPTIONAL 05861 ); 05862 05863 PIMAGE_ENTRY_IN_SESSION 05864 MiSessionLookupImage ( 05865 IN PVOID BaseAddress 05866 ); 05867 05868 NTSTATUS 05869 MiSessionCommitImagePages( 05870 PVOID BaseAddr, 05871 SIZE_T Size 05872 ); 05873 05874 VOID 05875 MiSessionUnloadAllImages ( 05876 VOID 05877 ); 05878 05879 VOID 05880 MiFreeSessionSpaceMap ( 05881 VOID 05882 ); 05883 05884 NTSTATUS 05885 MiSessionInitializeWorkingSetList ( 05886 VOID 05887 ); 05888 05889 VOID 05890 MiSessionUnlinkWorkingSet ( 05891 VOID 05892 ); 05893 05894 NTSTATUS 05895 MiSessionCopyOnWrite ( 05896 IN PMM_SESSION_SPACE SessionSpace, 05897 IN PVOID FaultingAddress, 05898 IN PMMPTE PointerPte 05899 ); 05900 05901 VOID 05902 MiSessionOutSwapProcess ( 05903 IN PEPROCESS Process 05904 ); 05905 05906 VOID 05907 MiSessionInSwapProcess ( 05908 IN PEPROCESS Process 05909 ); 05910 05911 #if !defined (_X86PAE_) 05912 05913 #define MI_GET_DIRECTORY_FRAME_FROM_PROCESS(_Process) \ 05914 MI_GET_PAGE_FRAME_FROM_PTE((PMMPTE)(&((_Process)->Pcb.DirectoryTableBase[0]))) 05915 05916 #else 05917 05918 #define MI_GET_DIRECTORY_FRAME_FROM_PROCESS(_Process) \ 05919 ((_Process)->PaePageDirectoryPage) 05920 #endif 05921 05922 PERFINFO_MIH_DECL 05923 05924 #if defined(_MIALT4K_) 05925 NTSTATUS 05926 MiSetCopyPagesFor4kPage( 05927 IN PEPROCESS Process, 05928 IN OUT PMMVAD *Vad, 05929 IN OUT PVOID *StartingAddress, 05930 IN OUT PVOID *EndingAddress, 05931 IN ULONG ProtectionMask); 05932 #endif 05933 05934 #endif // MI

Generated on Sat May 15 19:40:48 2004 for test by doxygen 1.3.7