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

mmsup.c File Reference

#include "mi.h"

Go to the source code of this file.

Functions

ULONG FASTCALL MiIsPteDecommittedPage (IN PMMPTE PointerPte)
ULONG FASTCALL MiIsProtectionCompatible (IN ULONG OldProtect, IN ULONG NewProtect)
ULONG FASTCALL MiMakeProtectionMask (IN ULONG Protect)
ULONG MiDoesPdeExistAndMakeValid (IN PMMPTE PointerPde, IN PEPROCESS TargetProcess, IN ULONG PfnMutexHeld, OUT PULONG Waited)
ULONG MiMakePdeExistAndMakeValid (IN PMMPTE PointerPde, IN PEPROCESS TargetProcess, IN ULONG PfnMutexHeld)
ULONG FASTCALL MiMakeSystemAddressValid (IN PVOID VirtualAddress, IN PEPROCESS CurrentProcess)
ULONG FASTCALL MiMakeSystemAddressValidPfnWs (IN PVOID VirtualAddress, IN PEPROCESS CurrentProcess OPTIONAL)
ULONG FASTCALL MiMakeSystemAddressValidPfnSystemWs (IN PVOID VirtualAddress)
ULONG FASTCALL MiMakeSystemAddressValidPfn (IN PVOID VirtualAddress)
ULONG FASTCALL MiLockPagedAddress (IN PVOID VirtualAddress, IN ULONG PfnLockHeld)
VOID FASTCALL MiUnlockPagedAddress (IN PVOID VirtualAddress, IN ULONG PfnLockHeld)
VOID FASTCALL MiZeroPhysicalPage (IN PFN_NUMBER PageFrameIndex, IN ULONG PageColor)
VOID FASTCALL MiRestoreTransitionPte (IN PFN_NUMBER PageFrameIndex)
PSUBSECTION MiGetSubsectionAndProtoFromPte (IN PMMPTE PointerPte, OUT PMMPTE *ProtoPte, IN PEPROCESS Process)
BOOLEAN MmIsNonPagedSystemAddressValid (IN PVOID VirtualAddress)
VOID MmHibernateInformation (IN PVOID MemoryMap, OUT PULONG_PTR HiberVa, OUT PPHYSICAL_ADDRESS HiberPte)

Variables

ULONG MmCompatibleProtectionMask [8]
CCHAR MmUserProtectionToMask1 [16]
CCHAR MmUserProtectionToMask2 [16]


Function Documentation

ULONG MiDoesPdeExistAndMakeValid IN PMMPTE  PointerPde,
IN PEPROCESS  TargetProcess,
IN ULONG  PfnMutexHeld,
OUT PULONG  Waited
 

Definition at line 437 of file mmsup.c.

References APC_LEVEL, FALSE, LOCK_PFN, MiGetVirtualAddressMappedByPte, MiMakeSystemAddressValid(), TRUE, and UNLOCK_PFN.

Referenced by MiCalculatePageCommitment(), MiCloneProcessAddressSpace(), MiDeletePte(), MiDeleteVirtualAddresses(), MiFlushDirtyBitsToPfn(), MiIsEntireRangeCommitted(), MiProtectVirtualMemory(), MiQueryAddressState(), MiResetVirtualMemory(), MiSetProtectionOnSection(), MmFlushVirtualMemory(), MmSecureVirtualMemory(), and NtLockVirtualMemory().

00446 : 00447 00448 This routine examines the specified Page Directory Entry to determine 00449 if the page table page mapped by the PDE exists. 00450 00451 If the page table page exists and is not currently in memory, the 00452 working set mutex and, if held, the PFN mutex are released and the 00453 page table page is faulted into the working set. The mutexes are 00454 reacquired. 00455 00456 If the PDE exists, the function returns true. 00457 00458 Arguments: 00459 00460 PointerPde - Supplies a pointer to the PDE to examine and potentially 00461 bring into the working set. 00462 00463 TargetProcess - Supplies a pointer to the current process. 00464 00465 PfnMutexHeld - Supplies the value TRUE if the PFN mutex is held, FALSE 00466 otherwise. 00467 00468 Waited - Supplies a pointer to a ULONG to increment if the mutex is released 00469 and reacquired. Note this value may be incremented more than once. 00470 00471 Return Value: 00472 00473 TRUE if the PDE exists, FALSE if the PDE is zero. 00474 00475 Environment: 00476 00477 Kernel mode, APCs disabled, WorkingSetLock held. 00478 00479 --*/ 00480 00481 { 00482 PMMPTE PointerPte; 00483 KIRQL OldIrql; 00484 00485 OldIrql = APC_LEVEL; 00486 00487 if (PointerPde->u.Long == 0) { 00488 00489 // 00490 // This page directory entry doesn't exist, return FALSE. 00491 // 00492 00493 return FALSE; 00494 } 00495 00496 if (PointerPde->u.Hard.Valid == 1) { 00497 00498 // 00499 // Already valid. 00500 // 00501 00502 return TRUE; 00503 } 00504 00505 // 00506 // Page directory entry exists, it is either valid, in transition 00507 // or in the paging file. Fault it in. 00508 // 00509 00510 if (PfnMutexHeld) { 00511 UNLOCK_PFN (OldIrql); 00512 *Waited += 1; 00513 } 00514 00515 PointerPte = MiGetVirtualAddressMappedByPte (PointerPde); 00516 00517 *Waited += MiMakeSystemAddressValid (PointerPte, TargetProcess); 00518 00519 if (PfnMutexHeld) { 00520 LOCK_PFN (OldIrql); 00521 } 00522 return TRUE; 00523 }

PSUBSECTION MiGetSubsectionAndProtoFromPte IN PMMPTE  PointerPte,
OUT PMMPTE ProtoPte,
IN PEPROCESS  Process
 

Definition at line 1385 of file mmsup.c.

References ASSERT, MI_PFN_ELEMENT, MiGetSubsectionAddress, MiMakeSystemAddressValidPfnWs(), MiPteToProto, _MMPFN::OriginalPte, and _MMPFN::PteAddress.

Referenced by MiGetSystemCacheSubsection().

01393 : 01394 01395 This routine examines the contents of the supplied PTE (which must 01396 map a page within a section) and determines the address of the 01397 subsection in which the PTE is contained. 01398 01399 Arguments: 01400 01401 PointerPte - Supplies a pointer to the PTE. 01402 01403 ProtoPte - Supplies a pointer to a PMMPTE which receives the 01404 address of the prototype PTE which is mapped by the supplied 01405 PointerPte. 01406 01407 Process - Supplies a pointer to the current process. 01408 01409 Return Value: 01410 01411 Returns the pointer to the subsection for this PTE. 01412 01413 Environment: 01414 01415 Kernel mode - Must be holding the PFN database lock and 01416 working set mutex (acquired safely) with APCs disabled. 01417 01418 --*/ 01419 01420 { 01421 PMMPTE PointerProto; 01422 PMMPFN Pfn1; 01423 01424 if (PointerPte->u.Hard.Valid == 1) { 01425 Pfn1 = MI_PFN_ELEMENT (PointerPte->u.Hard.PageFrameNumber); 01426 *ProtoPte = Pfn1->PteAddress; 01427 return MiGetSubsectionAddress (&Pfn1->OriginalPte); 01428 } 01429 01430 PointerProto = MiPteToProto (PointerPte); 01431 *ProtoPte = PointerProto; 01432 01433 MiMakeSystemAddressValidPfnWs (PointerProto, Process); 01434 01435 if (PointerProto->u.Hard.Valid == 1) { 01436 // 01437 // Prototype Pte is valid. 01438 // 01439 01440 Pfn1 = MI_PFN_ELEMENT (PointerProto->u.Hard.PageFrameNumber); 01441 return MiGetSubsectionAddress (&Pfn1->OriginalPte); 01442 } 01443 01444 if ((PointerProto->u.Soft.Transition == 1) && 01445 (PointerProto->u.Soft.Prototype == 0)) { 01446 01447 // 01448 // Prototype Pte is in transition. 01449 // 01450 01451 Pfn1 = MI_PFN_ELEMENT (PointerProto->u.Trans.PageFrameNumber); 01452 return MiGetSubsectionAddress (&Pfn1->OriginalPte); 01453 } 01454 01455 ASSERT (PointerProto->u.Soft.Prototype == 1); 01456 return MiGetSubsectionAddress (PointerProto); 01457 }

ULONG FASTCALL MiIsProtectionCompatible IN ULONG  OldProtect,
IN ULONG  NewProtect
 

Definition at line 139 of file mmsup.c.

References EXCEPTION_EXECUTE_HANDLER, FALSE, MiMakeProtectionMask(), MmCompatibleProtectionMask, and TRUE.

Referenced by NtMapViewOfSection().

00146 : 00147 00148 This function takes two user supplied page protections and checks 00149 to see if the new protection is compatible with the old protection. 00150 00151 protection compatible protections 00152 NoAccess NoAccess 00153 ReadOnly NoAccess, ReadOnly, ReadWriteCopy 00154 ReadWriteCopy NoAccess, ReadOnly, ReadWriteCopy 00155 ReadWrite NoAccess, ReadOnly, ReadWriteCopy, ReadWrite 00156 Execute NoAccess, Execute 00157 ExecuteRead NoAccess, ReadOnly, ReadWriteCopy, Execute, ExecuteRead, 00158 ExecuteWriteCopy 00159 ExecuteWrite NoAccess, ReadOnly, ReadWriteCopy, Execute, ExecuteRead, 00160 ExecuteWriteCopy, ReadWrite, ExecuteWrite 00161 ExecuteWriteCopy NoAccess, ReadOnly, ReadWriteCopy, Execute, ExecuteRead, 00162 ExecuteWriteCopy 00163 00164 Arguments: 00165 00166 OldProtect - Supplies the protection to be compatible with. 00167 00168 NewProtect - Supplies the protection to check out. 00169 00170 00171 Return Value: 00172 00173 Returns TRUE if the protection is compatible, FALSE if not. 00174 00175 Environment: 00176 00177 Kernel Mode. 00178 00179 --*/ 00180 00181 { 00182 ULONG Mask; 00183 ULONG ProtectMask; 00184 00185 try { 00186 Mask = MiMakeProtectionMask (OldProtect) & 0x7; 00187 } except (EXCEPTION_EXECUTE_HANDLER) { 00188 return FALSE; 00189 } 00190 00191 ProtectMask = MmCompatibleProtectionMask[Mask] | PAGE_GUARD | PAGE_NOCACHE; 00192 00193 if ((ProtectMask | NewProtect) != ProtectMask) { 00194 return FALSE; 00195 } 00196 return TRUE; 00197 }

ULONG FASTCALL MiIsPteDecommittedPage IN PMMPTE  PointerPte  ) 
 

Definition at line 42 of file mmsup.c.

References FALSE, MI_PTE_LOOKUP_NEEDED, MM_DECOMMIT, TRUE, and _MMPTE::u.

Referenced by MiCalculatePageCommitment(), MiIsEntireRangeCommitted(), and MiQueryAddressState().

00048 : 00049 00050 This function checks the contents of a PTE to determine if the 00051 PTE is explicitly decommitted. 00052 00053 If the PTE is a prototype PTE and the protection is not in the 00054 prototype PTE, the value FALSE is returned. 00055 00056 Arguments: 00057 00058 PointerPte - Supplies a pointer to the PTE to examine. 00059 00060 Return Value: 00061 00062 TRUE if the PTE is in the explicit decommitted state. 00063 FALSE if the PTE is not in the explicit decommitted state. 00064 00065 Environment: 00066 00067 Kernel mode, APCs disabled, WorkingSetLock held. 00068 00069 --*/ 00070 00071 { 00072 MMPTE PteContents; 00073 00074 PteContents = *PointerPte; 00075 00076 // 00077 // If the protection in the PTE is not decommitted, return false. 00078 // 00079 00080 if (PteContents.u.Soft.Protection != MM_DECOMMIT) { 00081 return FALSE; 00082 } 00083 00084 // 00085 // Check to make sure the protection field is really being interpreted 00086 // correctly. 00087 // 00088 00089 if (PteContents.u.Hard.Valid == 1) { 00090 00091 // 00092 // The PTE is valid and therefore cannot be decommitted. 00093 // 00094 00095 return FALSE; 00096 } 00097 00098 if ((PteContents.u.Soft.Prototype == 1) && 00099 (PteContents.u.Soft.PageFileHigh != MI_PTE_LOOKUP_NEEDED)) { 00100 00101 // 00102 // The PTE's protection is not known as it is in 00103 // prototype PTE format. Return FALSE. 00104 // 00105 00106 return FALSE; 00107 } 00108 00109 // 00110 // It is a decommitted PTE. 00111 // 00112 00113 return TRUE; 00114 }

ULONG FASTCALL MiLockPagedAddress IN PVOID  VirtualAddress,
IN ULONG  PfnLockHeld
 

Definition at line 1058 of file mmsup.c.

References FALSE, LOCK_PFN2, MI_ADD_LOCKED_PAGE_CHARGE, MI_PFN_ELEMENT, MiGetPteAddress, MiGetVirtualAddressMappedByPte, MiMakeSystemAddressValidPfn(), _MMPTE::u, _MMPFN::u3, and UNLOCK_PFN2.

Referenced by MiCloneProcessAddressSpace().

01065 : 01066 01067 This routine checks to see if the virtual address is valid, and if 01068 not makes it valid. 01069 01070 Arguments: 01071 01072 VirtualAddress - Supplies the virtual address to make valid. 01073 01074 CurrentProcess - Supplies a pointer to the current process. 01075 01076 Return Value: 01077 01078 Returns TRUE if lock released and wait performed, FALSE otherwise. 01079 01080 Environment: 01081 01082 Kernel mode. 01083 01084 --*/ 01085 01086 { 01087 01088 PMMPTE PointerPte; 01089 PMMPFN Pfn1; 01090 KIRQL OldIrql; 01091 ULONG Waited = FALSE; 01092 01093 PointerPte = MiGetPteAddress(VirtualAddress); 01094 01095 // 01096 // The address must be within paged pool. 01097 // 01098 01099 if (PfnLockHeld == FALSE) { 01100 LOCK_PFN2 (OldIrql); 01101 } 01102 01103 if (PointerPte->u.Hard.Valid == 0) { 01104 01105 Waited = MiMakeSystemAddressValidPfn ( 01106 MiGetVirtualAddressMappedByPte(PointerPte)); 01107 01108 } 01109 01110 Pfn1 = MI_PFN_ELEMENT (PointerPte->u.Hard.PageFrameNumber); 01111 MI_ADD_LOCKED_PAGE_CHARGE(Pfn1, 6); 01112 Pfn1->u3.e2.ReferenceCount += 1; 01113 01114 if (PfnLockHeld == FALSE) { 01115 UNLOCK_PFN2 (OldIrql); 01116 } 01117 return Waited; 01118 }

ULONG MiMakePdeExistAndMakeValid IN PMMPTE  PointerPde,
IN PEPROCESS  TargetProcess,
IN ULONG  PfnMutexHeld
 

Definition at line 624 of file mmsup.c.

References APC_LEVEL, ASSERT, FALSE, LOCK_PFN, MiGetPteAddress, MiGetVirtualAddressMappedByPte, MiMakeSystemAddressValid(), TRUE, _MMPTE::u, and UNLOCK_PFN.

Referenced by MiCreatePageTablesForPhysicalRange(), MiDecommitPages(), MiMapLockedPagesInUserSpace(), MiMapViewOfPhysicalSection(), MiProtectVirtualMemory(), MiSetProtectionOnSection(), and NtAllocateVirtualMemory().

00632 : 00633 00634 This routine examines the specified Page Directory Parent Entry to 00635 determine if the page directory page mapped by the PPE exists. If it does, 00636 then it examines the specified Page Directory Entry to determine if 00637 the page table page mapped by the PDE exists. 00638 00639 If the page table page exists and is not currently in memory, the 00640 working set mutex and, if held, the PFN mutex are released and the 00641 page table page is faulted into the working set. The mutexes are 00642 reacquired. 00643 00644 If the PDE exists, the function returns true. 00645 00646 If the PDE does not exist, a zero filled PTE is created and it 00647 too is brought into the working set. In this case the return 00648 value is FALSE. 00649 00650 Arguments: 00651 00652 PointerPde - Supplies a pointer to the PDE to examine and bring 00653 into the working set. 00654 00655 TargetProcess - Supplies a pointer to the current process. 00656 00657 PfnMutexHeld - Supplies the value TRUE if the PFN mutex is held, FALSE 00658 otherwise. 00659 00660 Return Value: 00661 00662 TRUE if the PDE exists, FALSE if the PDE was created. 00663 00664 Environment: 00665 00666 Kernel mode, APCs disabled, WorkingSetLock held. 00667 00668 --*/ 00669 00670 { 00671 PMMPTE PointerPte; 00672 PMMPTE PointerPpe; 00673 KIRQL OldIrql; 00674 ULONG ReturnValue; 00675 00676 PointerPpe = MiGetPteAddress (PointerPde); 00677 00678 if (PointerPpe->u.Hard.Valid == 1 && PointerPde->u.Hard.Valid == 1) { 00679 00680 // 00681 // Already valid. 00682 // 00683 00684 return TRUE; 00685 } 00686 00687 // 00688 // Deal with the page directory page first. 00689 // 00690 00691 if (PointerPpe->u.Long == 0) { 00692 ReturnValue = FALSE; 00693 } else { 00694 ReturnValue = TRUE; 00695 } 00696 00697 // 00698 // Page directory parent entry not valid, make it valid. 00699 // 00700 00701 OldIrql = APC_LEVEL; 00702 00703 do { 00704 00705 if (PfnMutexHeld) { 00706 UNLOCK_PFN (OldIrql); 00707 } 00708 00709 // 00710 // Fault it in. 00711 // 00712 00713 MiMakeSystemAddressValid (PointerPde, TargetProcess); 00714 00715 ASSERT (PointerPpe->u.Hard.Valid == 1); 00716 00717 if (PfnMutexHeld) { 00718 LOCK_PFN (OldIrql); 00719 } 00720 00721 // 00722 // Now deal with the page table page. 00723 // 00724 00725 if (ReturnValue == TRUE) { 00726 if (PointerPde->u.Long == 0) { 00727 ReturnValue = FALSE; 00728 } else { 00729 ReturnValue = TRUE; 00730 } 00731 } 00732 00733 // 00734 // Page directory entry not valid, make it valid. 00735 // 00736 00737 OldIrql = APC_LEVEL; 00738 00739 if (PfnMutexHeld) { 00740 UNLOCK_PFN (OldIrql); 00741 } 00742 00743 PointerPte = MiGetVirtualAddressMappedByPte (PointerPde); 00744 00745 // 00746 // Fault it in. 00747 // 00748 00749 MiMakeSystemAddressValid (PointerPte, TargetProcess); 00750 00751 ASSERT (PointerPde->u.Hard.Valid == 1); 00752 00753 if (PfnMutexHeld) { 00754 LOCK_PFN (OldIrql); 00755 } 00756 00757 } while (PointerPpe->u.Hard.Valid == 0 || PointerPde->u.Hard.Valid == 0); 00758 00759 return ReturnValue; 00760 }

ULONG FASTCALL MiMakeProtectionMask IN ULONG  Protect  ) 
 

Definition at line 243 of file mmsup.c.

References ExRaiseStatus(), MM_GUARD_PAGE, MM_NOACCESS, MM_NOCACHE, MmUserProtectionToMask1, and MmUserProtectionToMask2.

Referenced by MiIsProtectionCompatible(), MiProtectSpecialPool(), MiProtectVirtualMemory(), MiSetProtectionOnSection(), MmCreateSection(), MmMapViewOfSection(), MmSetPageProtection(), NtAllocateVirtualMemory(), NtMapViewOfSection(), and NtProtectVirtualMemory().

00249 : 00250 00251 This function takes a user supplied protection and converts it 00252 into a 5-bit protection code for the PTE. 00253 00254 Arguments: 00255 00256 Protect - Supplies the protection. 00257 00258 00259 Return Value: 00260 00261 Returns the protection code for use in the PTE. 00262 An exception is raised if the user supplied protection is invalid. 00263 00264 Environment: 00265 00266 Kernel Mode. 00267 00268 --*/ 00269 00270 { 00271 ULONG Field1; 00272 ULONG Field2; 00273 ULONG ProtectCode; 00274 00275 if (Protect >= (PAGE_NOCACHE * 2)) { 00276 ExRaiseStatus (STATUS_INVALID_PAGE_PROTECTION); 00277 } 00278 00279 Field1 = Protect & 0xF; 00280 Field2 = (Protect >> 4) & 0xF; 00281 00282 // 00283 // Make sure at least one field is set. 00284 // 00285 00286 if (Field1 == 0) { 00287 if (Field2 == 0) { 00288 00289 // 00290 // Both fields are zero, raise exception. 00291 // 00292 00293 ExRaiseStatus (STATUS_INVALID_PAGE_PROTECTION); 00294 return 0; 00295 } 00296 ProtectCode = MmUserProtectionToMask2[Field2]; 00297 } else { 00298 if (Field2 != 0) { 00299 // 00300 // Both fields are non-zero, raise exception. 00301 // 00302 00303 ExRaiseStatus (STATUS_INVALID_PAGE_PROTECTION); 00304 return 0; 00305 } 00306 ProtectCode = MmUserProtectionToMask1[Field1]; 00307 } 00308 00309 if (ProtectCode == -1) { 00310 ExRaiseStatus (STATUS_INVALID_PAGE_PROTECTION); 00311 } 00312 00313 if (Protect & PAGE_GUARD) { 00314 if (ProtectCode == MM_NOACCESS) { 00315 00316 // 00317 // Invalid protection, no access and no_cache. 00318 // 00319 00320 ExRaiseStatus (STATUS_INVALID_PAGE_PROTECTION); 00321 } 00322 00323 ProtectCode |= MM_GUARD_PAGE; 00324 } 00325 00326 if (Protect & PAGE_NOCACHE) { 00327 00328 if (ProtectCode == MM_NOACCESS) { 00329 00330 // 00331 // Invalid protection, no access and no cache. 00332 // 00333 00334 ExRaiseStatus (STATUS_INVALID_PAGE_PROTECTION); 00335 } 00336 00337 ProtectCode |= MM_NOCACHE; 00338 } 00339 00340 return ProtectCode; 00341 }

ULONG FASTCALL MiMakeSystemAddressValid IN PVOID  VirtualAddress,
IN PEPROCESS  CurrentProcess
 

Definition at line 764 of file mmsup.c.

References ASSERT, FALSE, KeBugCheckEx(), KernelMode, LOCK_WS_REGARDLESS, MM_PAGED_POOL_START, MmAccessFault(), MmIsAddressValid(), MmPagedPoolEnd, NT_SUCCESS, NTSTATUS(), TRUE, and UNLOCK_WS_REGARDLESS.

Referenced by MiCloneProcessAddressSpace(), MiDoesPdeExistAndMakeValid(), and MiMakePdeExistAndMakeValid().

00771 : 00772 00773 This routine checks to see if the virtual address is valid, and if 00774 not makes it valid. 00775 00776 Arguments: 00777 00778 VirtualAddress - Supplies the virtual address to make valid. 00779 00780 CurrentProcess - Supplies a pointer to the current process. 00781 00782 Return Value: 00783 00784 Returns TRUE if lock released and wait performed, FALSE otherwise. 00785 00786 Environment: 00787 00788 Kernel mode, APCs disabled, WorkingSetLock held. 00789 00790 --*/ 00791 00792 { 00793 NTSTATUS status; 00794 LOGICAL WsHeldSafe; 00795 ULONG Waited; 00796 00797 Waited = FALSE; 00798 00799 ASSERT (VirtualAddress > MM_HIGHEST_USER_ADDRESS); 00800 00801 ASSERT ((VirtualAddress < MM_PAGED_POOL_START) || 00802 (VirtualAddress > MmPagedPoolEnd)); 00803 00804 while (!MmIsAddressValid(VirtualAddress)) { 00805 00806 // 00807 // The virtual address is not present. Release 00808 // the working set mutex and fault it in. 00809 // 00810 // The working set lock may have been acquired safely or unsafely 00811 // by our caller. Handle both cases here and below. 00812 // 00813 00814 UNLOCK_WS_REGARDLESS(CurrentProcess, WsHeldSafe); 00815 00816 status = MmAccessFault (FALSE, VirtualAddress, KernelMode, (PVOID)0); 00817 if (!NT_SUCCESS(status)) { 00818 KdPrint (("MM:page fault status %lx\n",status)); 00819 KeBugCheckEx (KERNEL_DATA_INPAGE_ERROR, 00820 1, 00821 (ULONG)status, 00822 (ULONG_PTR)CurrentProcess, 00823 (ULONG_PTR)VirtualAddress); 00824 } 00825 00826 LOCK_WS_REGARDLESS(CurrentProcess, WsHeldSafe); 00827 00828 Waited = TRUE; 00829 } 00830 00831 return Waited; 00832 }

ULONG FASTCALL MiMakeSystemAddressValidPfn IN PVOID  VirtualAddress  ) 
 

Definition at line 996 of file mmsup.c.

References APC_LEVEL, ASSERT, FALSE, KeBugCheckEx(), KernelMode, LOCK_PFN, MmAccessFault(), MmIsAddressValid(), NT_SUCCESS, NTSTATUS(), TRUE, and UNLOCK_PFN.

Referenced by MiCheckProtoPtePageState(), MiCleanSection(), MiFlushSectionInternal(), MiLockPagedAddress(), MiSegmentDelete(), MiSetSystemCodeProtection(), MiUpdateImageHeaderPage(), MmAccessFault(), MmCheckCachedPageState(), MmCopyToCachedPage(), and MmPurgeSection().

01002 : 01003 01004 This routine checks to see if the virtual address is valid, and if 01005 not makes it valid. 01006 01007 Arguments: 01008 01009 VirtualAddress - Supplies the virtual address to make valid. 01010 01011 Return Value: 01012 01013 Returns TRUE if lock released and wait performed, FALSE otherwise. 01014 01015 Environment: 01016 01017 Kernel mode, APCs disabled, only the PFN Lock held. 01018 01019 --*/ 01020 01021 { 01022 NTSTATUS status; 01023 KIRQL OldIrql = APC_LEVEL; 01024 01025 ULONG Waited = FALSE; 01026 01027 ASSERT (VirtualAddress > MM_HIGHEST_USER_ADDRESS); 01028 01029 while (!MmIsAddressValid(VirtualAddress)) { 01030 01031 // 01032 // The virtual address is not present. Release 01033 // the working set mutex and fault it in. 01034 // 01035 01036 UNLOCK_PFN (OldIrql); 01037 01038 status = MmAccessFault (FALSE, VirtualAddress, KernelMode, (PVOID)0); 01039 if (!NT_SUCCESS(status)) { 01040 KdPrint (("MM:page fault status %lx\n",status)); 01041 KeBugCheckEx (KERNEL_DATA_INPAGE_ERROR, 01042 3, 01043 (ULONG)status, 01044 (ULONG_PTR)VirtualAddress, 01045 0); 01046 } 01047 01048 LOCK_PFN (OldIrql); 01049 01050 Waited = TRUE; 01051 } 01052 01053 return Waited; 01054 }

ULONG FASTCALL MiMakeSystemAddressValidPfnSystemWs IN PVOID  VirtualAddress  ) 
 

Definition at line 916 of file mmsup.c.

References APC_LEVEL, ASSERT, FALSE, KeBugCheckEx(), KernelMode, LOCK_PFN, LOCK_SESSION_SPACE_WS, LOCK_SYSTEM_WS, MI_IS_SESSION_IMAGE_ADDRESS, MmAccessFault(), MmIsAddressValid(), NT_SUCCESS, NTSTATUS(), TRUE, UNLOCK_PFN, UNLOCK_SESSION_SPACE_WS, and UNLOCK_SYSTEM_WS.

Referenced by MiLockCode(), and MmLockPagableSectionByHandle().

00922 : 00923 00924 This routine checks to see if the virtual address is valid, and if 00925 not makes it valid. 00926 00927 Arguments: 00928 00929 VirtualAddress - Supplies the virtual address to make valid. 00930 00931 Return Value: 00932 00933 Returns TRUE if lock released and wait performed, FALSE otherwise. 00934 00935 Environment: 00936 00937 Kernel mode, APCs disabled, PFN lock held, system working set lock held. 00938 00939 --*/ 00940 00941 { 00942 NTSTATUS status; 00943 ULONG Waited; 00944 KIRQL OldIrql; 00945 KIRQL OldIrqlWs; 00946 LOGICAL SessionSpace; 00947 00948 Waited = FALSE; 00949 OldIrql = APC_LEVEL; 00950 OldIrqlWs = APC_LEVEL; 00951 00952 ASSERT (VirtualAddress > MM_HIGHEST_USER_ADDRESS); 00953 00954 SessionSpace = MI_IS_SESSION_IMAGE_ADDRESS (VirtualAddress); 00955 00956 while (!MmIsAddressValid(VirtualAddress)) { 00957 00958 // 00959 // The virtual address is not present. Release 00960 // the working set mutex and fault it in. 00961 // 00962 00963 UNLOCK_PFN (OldIrql); 00964 00965 if (SessionSpace == TRUE) { 00966 UNLOCK_SESSION_SPACE_WS (OldIrqlWs); 00967 } 00968 else { 00969 UNLOCK_SYSTEM_WS (OldIrqlWs); 00970 } 00971 00972 status = MmAccessFault (FALSE, VirtualAddress, KernelMode, (PVOID)0); 00973 if (!NT_SUCCESS(status)) { 00974 KdPrint (("MM:page fault status %lx\n",status)); 00975 KeBugCheckEx (KERNEL_DATA_INPAGE_ERROR, 00976 2, 00977 (ULONG)status, 00978 (ULONG_PTR)0, 00979 (ULONG_PTR)VirtualAddress); 00980 } 00981 if (SessionSpace == TRUE) { 00982 LOCK_SESSION_SPACE_WS (OldIrqlWs); 00983 } 00984 else { 00985 LOCK_SYSTEM_WS (OldIrqlWs); 00986 } 00987 LOCK_PFN (OldIrql); 00988 00989 Waited = TRUE; 00990 } 00991 return Waited; 00992 }

ULONG FASTCALL MiMakeSystemAddressValidPfnWs IN PVOID  VirtualAddress,
IN PEPROCESS CurrentProcess  OPTIONAL
 

Definition at line 837 of file mmsup.c.

References APC_LEVEL, ASSERT, FALSE, KeBugCheckEx(), KernelMode, LOCK_PFN, LOCK_WS_REGARDLESS, MmAccessFault(), MmIsAddressValid(), NT_SUCCESS, NTSTATUS(), NULL, TRUE, UNLOCK_PFN, and UNLOCK_WS_REGARDLESS.

Referenced by MiCaptureSystemPte(), MiDecrementCloneBlockReference(), MiGetSubsectionAndProtoFromPte(), MiPurgeImageSection(), MiResetVirtualMemory(), and MiUpCloneProtoRefCount().

00844 : 00845 00846 This routine checks to see if the virtual address is valid, and if 00847 not makes it valid. 00848 00849 Arguments: 00850 00851 VirtualAddress - Supplies the virtual address to make valid. 00852 00853 CurrentProcess - Supplies a pointer to the current process, if the 00854 working set lock is not held, this value is NULL. 00855 00856 Return Value: 00857 00858 Returns TRUE if lock released and wait performed, FALSE otherwise. 00859 00860 Environment: 00861 00862 Kernel mode, APCs disabled, PFN lock held, working set lock held 00863 if CurrentProcess != NULL. 00864 00865 --*/ 00866 00867 { 00868 NTSTATUS status; 00869 ULONG Waited; 00870 KIRQL OldIrql; 00871 LOGICAL WsHeldSafe; 00872 00873 Waited = FALSE; 00874 OldIrql = APC_LEVEL; 00875 00876 ASSERT (VirtualAddress > MM_HIGHEST_USER_ADDRESS); 00877 00878 while (!MmIsAddressValid(VirtualAddress)) { 00879 00880 // 00881 // The virtual address is not present. Release 00882 // the working set mutex and fault it in. 00883 // 00884 00885 UNLOCK_PFN (OldIrql); 00886 if (CurrentProcess != NULL) { 00887 00888 // 00889 // The working set lock may have been acquired safely or unsafely 00890 // by our caller. Handle both cases here and below. 00891 // 00892 00893 UNLOCK_WS_REGARDLESS(CurrentProcess, WsHeldSafe); 00894 } 00895 status = MmAccessFault (FALSE, VirtualAddress, KernelMode, (PVOID)0); 00896 if (!NT_SUCCESS(status)) { 00897 KdPrint (("MM:page fault status %lx\n",status)); 00898 KeBugCheckEx (KERNEL_DATA_INPAGE_ERROR, 00899 2, 00900 (ULONG)status, 00901 (ULONG_PTR)CurrentProcess, 00902 (ULONG_PTR)VirtualAddress); 00903 } 00904 if (CurrentProcess != NULL) { 00905 LOCK_WS_REGARDLESS(CurrentProcess, WsHeldSafe); 00906 } 00907 LOCK_PFN (OldIrql); 00908 00909 Waited = TRUE; 00910 } 00911 return Waited; 00912 }

VOID FASTCALL MiRestoreTransitionPte IN PFN_NUMBER  PageFrameIndex  ) 
 

Definition at line 1245 of file mmsup.c.

References ASSERT, _SUBSECTION::ControlArea, MI_CAPTURE_USED_PAGETABLE_ENTRIES, MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE, MI_IS_SESSION_PTE, MI_PFN_ELEMENT, MI_WRITE_INVALID_PTE, MiCheckForControlAreaDeletion(), MiDecrementShareCount(), MiGetByteOffset, MiGetPteAddress, MiGetSubsectionAddress, MiMapPageInHyperSpace(), MiUnmapPageInHyperSpace, MM_SYSTEM_SPACE_START, MmIsAddressValid(), _CONTROL_AREA::NumberOfPfnReferences, _MMPFN::OriginalPte, _MMPFN::PteAddress, _MMPFN::PteFrame, StandbyPageList, _MMPTE::u, and _MMPFN::u3.

Referenced by MiDecrementReferenceCount(), MiDispatchFault(), MiFindContiguousMemory(), MiInsertPageInList(), MiRemovePageFromList(), MiRemovePhysicalPages(), MiResolveTransitionFault(), and MmAllocatePagesForMdl().

01251 : 01252 01253 This procedure restores the original contents into the PTE (which could 01254 be a prototype PTE) referred to by the PFN database for the specified 01255 physical page. It also updates all necessary data structures to 01256 reflect the fact that the referenced PTE is no longer in transition. 01257 01258 The physical address of the referenced PTE is mapped into hyper space 01259 of the current process and the PTE is then updated. 01260 01261 Arguments: 01262 01263 PageFrameIndex - Supplies the physical page number which refers to a 01264 transition PTE. 01265 01266 Return Value: 01267 01268 none. 01269 01270 Environment: 01271 01272 Must be holding the PFN database mutex with APCs disabled. 01273 01274 --*/ 01275 01276 { 01277 PMMPFN Pfn1; 01278 PMMPTE PointerPte; 01279 PSUBSECTION Subsection; 01280 PCONTROL_AREA ControlArea; 01281 KIRQL OldIrql = 99; 01282 01283 Pfn1 = MI_PFN_ELEMENT (PageFrameIndex); 01284 01285 ASSERT (Pfn1->u3.e1.PageLocation == StandbyPageList); 01286 01287 if (Pfn1->u3.e1.PrototypePte) { 01288 01289 if (MmIsAddressValid (Pfn1->PteAddress)) { 01290 PointerPte = Pfn1->PteAddress; 01291 } else { 01292 01293 // 01294 // The page containing the prototype PTE is not valid, 01295 // map the page into hyperspace and reference it that way. 01296 // 01297 01298 PointerPte = MiMapPageInHyperSpace (Pfn1->PteFrame, &OldIrql); 01299 PointerPte = (PMMPTE)((PCHAR)PointerPte + 01300 MiGetByteOffset(Pfn1->PteAddress)); 01301 } 01302 01303 ASSERT ((MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE (PointerPte) == PageFrameIndex) && 01304 (PointerPte->u.Hard.Valid == 0)); 01305 01306 // 01307 // This page is referenced by a prototype PTE. The 01308 // segment structures need to be updated when the page 01309 // is removed from the transition state. 01310 // 01311 01312 if (Pfn1->OriginalPte.u.Soft.Prototype) { 01313 01314 // 01315 // The prototype PTE is in subsection format, calculate the 01316 // address of the control area for the subsection and decrement 01317 // the number of PFN references to the control area. 01318 // 01319 // Calculate address of subsection for this prototype PTE. 01320 // 01321 01322 Subsection = MiGetSubsectionAddress (&Pfn1->OriginalPte); 01323 ControlArea = Subsection->ControlArea; 01324 ControlArea->NumberOfPfnReferences -= 1; 01325 ASSERT ((LONG)ControlArea->NumberOfPfnReferences >= 0); 01326 01327 MiCheckForControlAreaDeletion (ControlArea); 01328 } 01329 01330 } else { 01331 01332 // 01333 // The page points to a page or page table page which may not be 01334 // for the current process. Map the page into hyperspace and 01335 // reference it through hyperspace. If the page resides in 01336 // system space (but not session space), it does not need to be 01337 // mapped as all PTEs for system space must be resident. Session 01338 // space PTEs are only mapped per session so access to them must 01339 // also go through hyperspace. 01340 // 01341 01342 PointerPte = Pfn1->PteAddress; 01343 01344 if (PointerPte < MiGetPteAddress (MM_SYSTEM_SPACE_START) || 01345 MI_IS_SESSION_PTE (PointerPte)) { 01346 01347 PointerPte = MiMapPageInHyperSpace (Pfn1->PteFrame, &OldIrql); 01348 PointerPte = (PMMPTE)((PCHAR)PointerPte + 01349 MiGetByteOffset(Pfn1->PteAddress)); 01350 } 01351 ASSERT ((MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE (PointerPte) == PageFrameIndex) && 01352 (PointerPte->u.Hard.Valid == 0)); 01353 01354 MI_CAPTURE_USED_PAGETABLE_ENTRIES (Pfn1); 01355 01356 #if _WIN64 01357 #if DBGXX 01358 MiCheckPageTableTrim(PointerPte); 01359 #endif 01360 #endif 01361 } 01362 01363 ASSERT (Pfn1->OriginalPte.u.Hard.Valid == 0); 01364 ASSERT (!((Pfn1->OriginalPte.u.Soft.Prototype == 0) && 01365 (Pfn1->OriginalPte.u.Soft.Transition == 1))); 01366 01367 MI_WRITE_INVALID_PTE (PointerPte, Pfn1->OriginalPte); 01368 01369 if (OldIrql != 99) { 01370 MiUnmapPageInHyperSpace (OldIrql); 01371 } 01372 01373 // 01374 // The PTE has been restored to its original contents and is 01375 // no longer in transition. Decrement the share count on 01376 // the page table page which contains the PTE. 01377 // 01378 01379 MiDecrementShareCount (Pfn1->PteFrame); 01380 01381 return; 01382 }

VOID FASTCALL MiUnlockPagedAddress IN PVOID  VirtualAddress,
IN ULONG  PfnLockHeld
 

Definition at line 1123 of file mmsup.c.

References ASSERT, FALSE, LOCK_PFN2, MI_GET_PAGE_FRAME_FROM_PTE, MI_PFN_ELEMENT, MI_REMOVE_LOCKED_PAGE_CHARGE, MiDecrementReferenceCount(), MiGetPteAddress, _MMPTE::u, _MMPFN::u3, and UNLOCK_PFN2.

Referenced by MiCloneProcessAddressSpace().

01130 : 01131 01132 This routine checks to see if the virtual address is valid, and if 01133 not makes it valid. 01134 01135 Arguments: 01136 01137 VirtualAddress - Supplies the virtual address to make valid. 01138 01139 01140 Return Value: 01141 01142 None. 01143 01144 Environment: 01145 01146 Kernel mode. PFN LOCK MUST NOT BE HELD. 01147 01148 --*/ 01149 01150 { 01151 PMMPFN Pfn1; 01152 PMMPTE PointerPte; 01153 KIRQL OldIrql; 01154 PFN_NUMBER PageFrameIndex; 01155 01156 PointerPte = MiGetPteAddress(VirtualAddress); 01157 01158 // 01159 // Address must be within paged pool. 01160 // 01161 01162 if (PfnLockHeld == FALSE) { 01163 LOCK_PFN2 (OldIrql); 01164 } 01165 01166 ASSERT (PointerPte->u.Hard.Valid == 1); 01167 PageFrameIndex = MI_GET_PAGE_FRAME_FROM_PTE (PointerPte); 01168 Pfn1 = MI_PFN_ELEMENT (PageFrameIndex); 01169 01170 ASSERT (Pfn1->u3.e2.ReferenceCount > 1); 01171 01172 MI_REMOVE_LOCKED_PAGE_CHARGE(Pfn1, 7); 01173 01174 MiDecrementReferenceCount (PageFrameIndex); 01175 01176 if (PfnLockHeld == FALSE) { 01177 UNLOCK_PFN2 (OldIrql); 01178 } 01179 return; 01180 }

VOID FASTCALL MiZeroPhysicalPage IN PFN_NUMBER  PageFrameIndex,
IN ULONG  PageColor
 

Definition at line 1184 of file mmsup.c.

References KeZeroPage, MiMapPageInHyperSpace(), MiUnmapPageInHyperSpace, MM_COLOR_MASK, PAGE_SHIFT, and PAGE_SIZE.

Referenced by MiInitMachineDependent(), MiRemoveZeroPage(), MiResolveDemandZeroFault(), MiSessionCommitImagePages(), MiSessionCommitPageTables(), MiSessionCreateInternal(), MiSessionInitializeWorkingSetList(), MiWaitForInPageComplete(), MmAccessFault(), MmAllocatePagesForMdl(), and MmCreateProcessAddressSpace().

01191 : 01192 01193 This procedure maps the specified physical page into hyper space 01194 and fills the page with zeros. 01195 01196 Arguments: 01197 01198 PageFrameIndex - Supplies the physical page number to fill with 01199 zeroes. 01200 01201 Return Value: 01202 01203 none. 01204 01205 Environment: 01206 01207 Kernel mode. 01208 01209 --*/ 01210 01211 { 01212 PULONG va; 01213 KIRQL OldIrql; 01214 01215 #if defined(_ALPHA_) 01216 01217 HalZeroPage((PVOID)ULongToPtr((PageColor & MM_COLOR_MASK) << PAGE_SHIFT), 01218 (PVOID)ULongToPtr((PageColor & MM_COLOR_MASK) << PAGE_SHIFT), 01219 PageFrameIndex); 01220 #else 01221 01222 UNREFERENCED_PARAMETER (PageColor); 01223 01224 va = (PULONG)MiMapPageInHyperSpace (PageFrameIndex, &OldIrql); 01225 01226 #if defined(_X86_) 01227 01228 KeZeroPage(va); 01229 01230 #else 01231 01232 RtlZeroMemory (va, PAGE_SIZE); 01233 01234 #endif // X86 01235 01236 MiUnmapPageInHyperSpace (OldIrql); 01237 01238 #endif // ALPHA 01239 01240 return; 01241 }

VOID MmHibernateInformation IN PVOID  MemoryMap,
OUT PULONG_PTR  HiberVa,
OUT PPHYSICAL_ADDRESS  HiberPte
 

Definition at line 1503 of file mmsup.c.

References MiGetVirtualAddressMappedByPte, MmCrashDumpPte, MmGetPhysicalAddress(), PO_MEM_CLONE, and PoSetHiberRange().

01508 { 01509 // 01510 // Mark PTE page where the 16 dump PTEs reside as needing cloned 01511 // 01512 01513 PoSetHiberRange ( 01514 MemoryMap, 01515 PO_MEM_CLONE, 01516 MmCrashDumpPte, 01517 1, 01518 ' etP' 01519 ); 01520 01521 // 01522 // Return the dump PTEs to the loader (as it needs to use them 01523 // to map it's relocation code into the kernel space on the 01524 // final bit of restoring memory) 01525 // 01526 01527 *HiberVa = (ULONG_PTR) MiGetVirtualAddressMappedByPte(MmCrashDumpPte); 01528 *HiberPte = MmGetPhysicalAddress(MmCrashDumpPte); 01529 }

BOOLEAN MmIsNonPagedSystemAddressValid IN PVOID  VirtualAddress  ) 
 

Definition at line 1460 of file mmsup.c.

References FALSE, MmPagedPoolEnd, MmPagedPoolStart, and TRUE.

Referenced by MmBuildMdlForNonPagedPool().

01466 : 01467 01468 For a given virtual address this function returns TRUE if the address 01469 is within the nonpagable portion of the system's address space, 01470 FALSE otherwise. 01471 01472 Arguments: 01473 01474 VirtualAddress - Supplies the virtual address to check. 01475 01476 Return Value: 01477 01478 TRUE if the address is within the nonpagable portion of the system 01479 address space, FALSE otherwise. 01480 01481 Environment: 01482 01483 Kernel mode. 01484 01485 --*/ 01486 01487 { 01488 // 01489 // Return TRUE if address is within the nonpagable portion 01490 // of the system. Check limits for paged pool and if not within 01491 // those limits, return TRUE. 01492 // 01493 01494 if ((VirtualAddress >= MmPagedPoolStart) && 01495 (VirtualAddress <= MmPagedPoolEnd)) { 01496 return FALSE; 01497 } 01498 01499 return TRUE; 01500 }


Variable Documentation

ULONG MmCompatibleProtectionMask[8]
 

Initial value:

{ PAGE_NOACCESS, PAGE_NOACCESS | PAGE_READONLY | PAGE_WRITECOPY, PAGE_NOACCESS | PAGE_EXECUTE, PAGE_NOACCESS | PAGE_READONLY | PAGE_WRITECOPY | PAGE_EXECUTE | PAGE_EXECUTE_READ, PAGE_NOACCESS | PAGE_READONLY | PAGE_WRITECOPY | PAGE_READWRITE, PAGE_NOACCESS | PAGE_READONLY | PAGE_WRITECOPY, PAGE_NOACCESS | PAGE_READONLY | PAGE_WRITECOPY | PAGE_READWRITE | PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY, PAGE_NOACCESS | PAGE_READONLY | PAGE_WRITECOPY | PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_WRITECOPY }

Definition at line 120 of file mmsup.c.

Referenced by MiIsProtectionCompatible().

CCHAR MmUserProtectionToMask1[16]
 

Initial value:

{ 0, MM_NOACCESS, MM_READONLY, -1, MM_READWRITE, -1, -1, -1, MM_WRITECOPY, -1, -1, -1, -1, -1, -1, -1 }

Definition at line 204 of file mmsup.c.

Referenced by MiMakeProtectionMask().

CCHAR MmUserProtectionToMask2[16]
 

Initial value:

{ 0, MM_EXECUTE, MM_EXECUTE_READ, -1, MM_EXECUTE_READWRITE, -1, -1, -1, MM_EXECUTE_WRITECOPY, -1, -1, -1, -1, -1, -1, -1 }

Definition at line 222 of file mmsup.c.

Referenced by MiMakeProtectionMask().


Generated on Sat May 15 19:44:47 2004 for test by doxygen 1.3.7