ReactOS 0.4.15-dev-8614-gbc76250
miarm.h File Reference
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  _POOL_DESCRIPTOR
 
struct  _POOL_HEADER
 
struct  _POOL_TRACKER_TABLE
 
struct  _POOL_TRACKER_BIG_PAGES
 
struct  _MI_LARGE_PAGE_DRIVER_ENTRY
 
struct  _PHYSICAL_MEMORY_RUN
 
struct  _PHYSICAL_MEMORY_DESCRIPTOR
 
struct  _MMCOLOR_TABLES
 
struct  _MI_LARGE_PAGE_RANGES
 
struct  _MMVIEW
 
struct  _MMSESSION
 
struct  _MM_SESSION_SPACE_FLAGS
 
struct  _MM_SESSION_SPACE
 

Macros

#define MI_LOWEST_VAD_ADDRESS   (PVOID)MM_LOWEST_USER_ADDRESS
 
#define _1KB   (1024u)
 
#define _1MB   (1024 * _1KB)
 
#define _1GB   (1024 * _1MB)
 
#define _64K   (64 * _1KB)
 
#define PT_SIZE   (PTE_PER_PAGE * sizeof(MMPTE))
 
#define PD_SIZE   (PDE_PER_PAGE * sizeof(MMPDE))
 
#define SYSTEM_PD_SIZE   (PPE_PER_PAGE * PD_SIZE)
 
#define MM_ZERO_ACCESS   0
 
#define MM_READONLY   1
 
#define MM_EXECUTE   2
 
#define MM_EXECUTE_READ   3
 
#define MM_READWRITE   4
 
#define MM_WRITECOPY   5
 
#define MM_EXECUTE_READWRITE   6
 
#define MM_EXECUTE_WRITECOPY   7
 
#define MM_PROTECT_ACCESS   7
 
#define MM_NOCACHE   0x08
 
#define MM_GUARDPAGE   0x10
 
#define MM_WRITECOMBINE   0x18
 
#define MM_PROTECT_SPECIAL   0x18
 
#define MM_DECOMMIT   (MM_ZERO_ACCESS | MM_GUARDPAGE)
 
#define MM_NOACCESS   (MM_ZERO_ACCESS | MM_WRITECOMBINE)
 
#define MM_OUTSWAPPED_KSTACK   (MM_EXECUTE_WRITECOPY | MM_WRITECOMBINE)
 
#define MM_INVALID_PROTECTION   0xFFFFFFFF
 
#define IMAGE_SCN_PROTECTION_MASK   (IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE)
 
#define MI_IS_SESSION_IMAGE_ADDRESS(Address)    (((Address) >= MiSessionImageStart) && ((Address) < MiSessionImageEnd))
 
#define MI_IS_SESSION_ADDRESS(Address)    (((Address) >= MmSessionBase) && ((Address) < MiSessionSpaceEnd))
 
#define MI_IS_SESSION_PTE(Pte)    ((((PMMPTE)Pte) >= MiSessionBasePte) && (((PMMPTE)Pte) < MiSessionLastPte))
 
#define MI_IS_PAGE_TABLE_ADDRESS(Address)    (((PVOID)(Address) >= (PVOID)PTE_BASE) && ((PVOID)(Address) <= (PVOID)PTE_TOP))
 
#define MI_IS_SYSTEM_PAGE_TABLE_ADDRESS(Address)    (((Address) >= (PVOID)MiAddressToPte(MmSystemRangeStart)) && ((Address) <= (PVOID)PTE_TOP))
 
#define MI_IS_PAGE_TABLE_OR_HYPER_ADDRESS(Address)    (((PVOID)(Address) >= (PVOID)PTE_BASE) && ((PVOID)(Address) <= (PVOID)MmHyperSpaceEnd))
 
#define MI_MAKE_SOFTWARE_PTE(p, x)   ((p)->u.Long = (x << MM_PTE_SOFTWARE_PROTECTION_BITS))
 
#define MI_SET_PFN_DELETED(x)   ((x)->PteAddress = (PMMPTE)((ULONG_PTR)(x)->PteAddress | 1))
 
#define MI_IS_PFN_DELETED(x)   ((ULONG_PTR)((x)->PteAddress) & 1)
 
#define MM_SYSLDR_NO_IMPORTS   ((PVOID)(ULONG_PTR)-2)
 
#define MM_SYSLDR_BOOT_LOADED   ((PVOID)(ULONG_PTR)-1)
 
#define MM_SYSLDR_SINGLE_ENTRY   0x1
 
#define MI_INITIAL_SESSION_IDS   64
 
#define MI_GET_PAGE_COLOR(x)   ((x) & MmSecondaryColorMask)
 
#define MI_GET_NEXT_COLOR()   (MI_GET_PAGE_COLOR(++MmSystemPageColor))
 
#define MI_GET_NEXT_PROCESS_COLOR(x)   (MI_GET_PAGE_COLOR(++(x)->NextPageColor))
 
#define MI_PTE_LOOKUP_NEEDED   0xFFFFF
 
#define MI_SESSION_DATA_PAGES_MAXIMUM   (MM_ALLOCATION_GRANULARITY / PAGE_SIZE)
 
#define MI_SESSION_TAG_PAGES_MAXIMUM   (MM_ALLOCATION_GRANULARITY / PAGE_SIZE)
 
#define MM_READ_WRITE_ALLOWED   11
 
#define MM_READ_ONLY_ALLOWED   10
 
#define MM_NO_ACCESS_ALLOWED   01
 
#define MM_DELETE_CHECK   85
 
#define MI_SYSTEM_VIEW_BUCKET_SIZE   _64K
 
#define POOL_BLOCK_SIZE   8
 
#define POOL_LISTS_PER_PAGE   (PAGE_SIZE / POOL_BLOCK_SIZE)
 
#define BASE_POOL_TYPE_MASK   1
 
#define POOL_MAX_ALLOC   (PAGE_SIZE - (sizeof(POOL_HEADER) + POOL_BLOCK_SIZE))
 
#define POOL_FLAG_CHECK_TIMERS   0x1
 
#define POOL_FLAG_CHECK_WORKERS   0x2
 
#define POOL_FLAG_CHECK_RESOURCES   0x4
 
#define POOL_FLAG_VERIFIER   0x8
 
#define POOL_FLAG_CHECK_DEADLOCK   0x10
 
#define POOL_FLAG_SPECIAL_POOL   0x20
 
#define POOL_FLAG_DBGPRINT_ON_FAILURE   0x40
 
#define POOL_FLAG_CRASH_ON_FAILURE   0x80
 
#define POOL_CORRUPTED_LIST   3
 
#define POOL_SIZE_OR_INDEX_MISMATCH   5
 
#define POOL_ENTRIES_NOT_ALIGNED_PREVIOUS   6
 
#define POOL_HEADER_NOT_ALIGNED   7
 
#define POOL_HEADER_IS_ZERO   8
 
#define POOL_ENTRIES_NOT_ALIGNED_NEXT   9
 
#define POOL_ENTRY_NOT_FOUND   10
 
#define POOL_ENTRY_CORRUPTED   1
 
#define POOL_ENTRY_ALREADY_FREE   6
 
#define POOL_ENTRY_NOT_ALLOCATED   7
 
#define POOL_ALLOC_IRQL_INVALID   8
 
#define POOL_FREE_IRQL_INVALID   9
 
#define POOL_BILLED_PROCESS_INVALID   13
 
#define POOL_HEADER_SIZE_INVALID   32
 
#define MI_IS_ROS_PFN(x)   ((x)->u4.AweAllocation == TRUE)
 

Typedefs

typedef struct _POOL_DESCRIPTOR POOL_DESCRIPTOR
 
typedef struct _POOL_DESCRIPTORPPOOL_DESCRIPTOR
 
typedef struct _POOL_HEADER POOL_HEADER
 
typedef struct _POOL_HEADERPPOOL_HEADER
 
typedef struct _POOL_TRACKER_TABLE POOL_TRACKER_TABLE
 
typedef struct _POOL_TRACKER_TABLEPPOOL_TRACKER_TABLE
 
typedef struct _POOL_TRACKER_BIG_PAGES POOL_TRACKER_BIG_PAGES
 
typedef struct _POOL_TRACKER_BIG_PAGESPPOOL_TRACKER_BIG_PAGES
 
typedef struct _MI_LARGE_PAGE_DRIVER_ENTRY MI_LARGE_PAGE_DRIVER_ENTRY
 
typedef struct _MI_LARGE_PAGE_DRIVER_ENTRYPMI_LARGE_PAGE_DRIVER_ENTRY
 
typedef enum _MMSYSTEM_PTE_POOL_TYPE MMSYSTEM_PTE_POOL_TYPE
 
typedef enum _MI_PFN_CACHE_ATTRIBUTE MI_PFN_CACHE_ATTRIBUTE
 
typedef enum _MI_PFN_CACHE_ATTRIBUTEPMI_PFN_CACHE_ATTRIBUTE
 
typedef struct _PHYSICAL_MEMORY_RUN PHYSICAL_MEMORY_RUN
 
typedef struct _PHYSICAL_MEMORY_RUNPPHYSICAL_MEMORY_RUN
 
typedef struct _PHYSICAL_MEMORY_DESCRIPTOR PHYSICAL_MEMORY_DESCRIPTOR
 
typedef struct _PHYSICAL_MEMORY_DESCRIPTORPPHYSICAL_MEMORY_DESCRIPTOR
 
typedef struct _MMCOLOR_TABLES MMCOLOR_TABLES
 
typedef struct _MMCOLOR_TABLESPMMCOLOR_TABLES
 
typedef struct _MI_LARGE_PAGE_RANGES MI_LARGE_PAGE_RANGES
 
typedef struct _MI_LARGE_PAGE_RANGESPMI_LARGE_PAGE_RANGES
 
typedef struct _MMVIEW MMVIEW
 
typedef struct _MMVIEWPMMVIEW
 
typedef struct _MMSESSION MMSESSION
 
typedef struct _MMSESSIONPMMSESSION
 
typedef struct _MM_SESSION_SPACE_FLAGS MM_SESSION_SPACE_FLAGS
 
typedef struct _MM_SESSION_SPACE MM_SESSION_SPACE
 
typedef struct _MM_SESSION_SPACEPMM_SESSION_SPACE
 

Enumerations

enum  _MMSYSTEM_PTE_POOL_TYPE { SystemPteSpace , NonPagedPoolExpansion , MaximumPtePoolTypes }
 
enum  _MI_PFN_CACHE_ATTRIBUTE { MiNonCached , MiCached , MiWriteCombined , MiNotMapped }
 

Functions

 C_ASSERT (sizeof(POOL_HEADER)==POOL_BLOCK_SIZE)
 
 C_ASSERT (POOL_BLOCK_SIZE==sizeof(LIST_ENTRY))
 
FORCEINLINE BOOLEAN MI_IS_PROCESS_WORKING_SET (PMMSUPPORT WorkingSet)
 
FORCEINLINE BOOLEAN MiIsMemoryTypeFree (TYPE_OF_MEMORY MemoryType)
 
FORCEINLINE BOOLEAN MiIsMemoryTypeInvisible (TYPE_OF_MEMORY MemoryType)
 
FORCEINLINE BOOLEAN MiIsUserPde (PVOID Address)
 
FORCEINLINE BOOLEAN MiIsUserPte (PVOID Address)
 
FORCEINLINE ULONG_PTR MiDetermineUserGlobalPteMask (IN PVOID PointerPte)
 
FORCEINLINE VOID MI_MAKE_HARDWARE_PTE_KERNEL (IN PMMPTE NewPte, IN PMMPTE MappingPte, IN ULONG_PTR ProtectionMask, IN PFN_NUMBER PageFrameNumber)
 
FORCEINLINE VOID MI_MAKE_HARDWARE_PTE (IN PMMPTE NewPte, IN PMMPTE MappingPte, IN ULONG_PTR ProtectionMask, IN PFN_NUMBER PageFrameNumber)
 
FORCEINLINE VOID MI_MAKE_HARDWARE_PTE_USER (IN PMMPTE NewPte, IN PMMPTE MappingPte, IN ULONG_PTR ProtectionMask, IN PFN_NUMBER PageFrameNumber)
 
FORCEINLINE VOID MI_MAKE_PROTOTYPE_PTE (IN PMMPTE NewPte, IN PMMPTE PointerPte)
 
FORCEINLINE VOID MI_MAKE_SUBSECTION_PTE (IN PMMPTE NewPte, IN PVOID Segment)
 
FORCEINLINE BOOLEAN MI_IS_MAPPED_PTE (PMMPTE PointerPte)
 
FORCEINLINE VOID MI_MAKE_TRANSITION_PTE (_Out_ PMMPTE NewPte, _In_ PFN_NUMBER Page, _In_ ULONG Protection)
 
FORCEINLINE BOOLEAN MI_IS_PHYSICAL_ADDRESS (IN PVOID Address)
 
FORCEINLINE VOID MI_WRITE_VALID_PTE (IN PMMPTE PointerPte, IN MMPTE TempPte)
 
FORCEINLINE VOID MI_UPDATE_VALID_PTE (IN PMMPTE PointerPte, IN MMPTE TempPte)
 
FORCEINLINE VOID MI_WRITE_INVALID_PTE (IN PMMPTE PointerPte, IN MMPTE InvalidPte)
 
FORCEINLINE VOID MI_ERASE_PTE (IN PMMPTE PointerPte)
 
FORCEINLINE VOID MI_WRITE_VALID_PDE (IN PMMPDE PointerPde, IN MMPDE TempPde)
 
FORCEINLINE VOID MI_WRITE_INVALID_PDE (IN PMMPDE PointerPde, IN MMPDE InvalidPde)
 
FORCEINLINE BOOLEAN MM_ANY_WS_LOCK_HELD (IN PETHREAD Thread)
 
FORCEINLINE BOOLEAN MM_ANY_WS_LOCK_HELD_EXCLUSIVE (_In_ PETHREAD Thread)
 
FORCEINLINE BOOLEAN MI_WS_OWNER (IN PEPROCESS Process)
 
FORCEINLINE BOOLEAN MiIsRosSectionObject (IN PSECTION Section)
 
VOID NTAPI MiDecrementReferenceCount (IN PMMPFN Pfn1, IN PFN_NUMBER PageFrameIndex)
 
FORCEINLINE BOOLEAN MI_IS_WS_UNSAFE (IN PEPROCESS Process)
 
FORCEINLINE VOID MiLockProcessWorkingSet (IN PEPROCESS Process, IN PETHREAD Thread)
 
FORCEINLINE VOID MiLockProcessWorkingSetShared (IN PEPROCESS Process, IN PETHREAD Thread)
 
FORCEINLINE VOID MiLockProcessWorkingSetUnsafe (IN PEPROCESS Process, IN PETHREAD Thread)
 
FORCEINLINE VOID MiUnlockProcessWorkingSet (IN PEPROCESS Process, IN PETHREAD Thread)
 
FORCEINLINE VOID MiUnlockProcessWorkingSetShared (IN PEPROCESS Process, IN PETHREAD Thread)
 
FORCEINLINE VOID MiUnlockProcessWorkingSetUnsafe (IN PEPROCESS Process, IN PETHREAD Thread)
 
FORCEINLINE VOID MiLockWorkingSet (IN PETHREAD Thread, IN PMMSUPPORT WorkingSet)
 
FORCEINLINE VOID MiLockWorkingSetShared (_In_ PETHREAD Thread, _In_ PMMSUPPORT WorkingSet)
 
FORCEINLINE VOID MiUnlockWorkingSet (IN PETHREAD Thread, IN PMMSUPPORT WorkingSet)
 
FORCEINLINE VOID MiUnlockWorkingSetShared (_In_ PETHREAD Thread, _In_ PMMSUPPORT WorkingSet)
 
FORCEINLINE BOOLEAN MiConvertSharedWorkingSetLockToExclusive (_In_ PETHREAD Thread, _In_ PMMSUPPORT Vm)
 
FORCEINLINE VOID MiUnlockProcessWorkingSetForFault (IN PEPROCESS Process, IN PETHREAD Thread, OUT PBOOLEAN Safe, OUT PBOOLEAN Shared)
 
FORCEINLINE VOID MiLockProcessWorkingSetForFault (IN PEPROCESS Process, IN PETHREAD Thread, IN BOOLEAN Safe, IN BOOLEAN Shared)
 
FORCEINLINE KIRQL MiAcquireExpansionLock (VOID)
 
FORCEINLINE VOID MiReleaseExpansionLock (KIRQL OldIrql)
 
FORCEINLINE PMMPTE MI_GET_PROTOTYPE_PTE_FOR_VPN (IN PMMVAD Vad, IN ULONG_PTR Vpn)
 
FORCEINLINE PMMPFN MI_PFN_ELEMENT (IN PFN_NUMBER Pfn)
 
FORCEINLINE VOID MiDropLockCount (IN PMMPFN Pfn1)
 
FORCEINLINE VOID MiDereferencePfnAndDropLockCount (IN PMMPFN Pfn1)
 
FORCEINLINE VOID MiReferenceProbedPageAndBumpLockCount (IN PMMPFN Pfn1)
 
FORCEINLINE VOID MiReferenceUsedPageAndBumpLockCount (IN PMMPFN Pfn1)
 
FORCEINLINE VOID MiReferenceUnusedPageAndBumpLockCount (IN PMMPFN Pfn1)
 
BOOLEAN NTAPI MmArmInitSystem (IN ULONG Phase, IN PLOADER_PARAMETER_BLOCK LoaderBlock)
 
VOID NTAPI MiInitializeSessionSpaceLayout (VOID)
 
NTSTATUS NTAPI MiInitMachineDependent (IN PLOADER_PARAMETER_BLOCK LoaderBlock)
 
VOID NTAPI MiComputeColorInformation (VOID)
 
VOID NTAPI MiMapPfnDatabase (IN PLOADER_PARAMETER_BLOCK LoaderBlock)
 
VOID NTAPI MiInitializeColorTables (VOID)
 
VOID NTAPI MiInitializePfnDatabase (IN PLOADER_PARAMETER_BLOCK LoaderBlock)
 
VOID NTAPI MiInitializeSessionWsSupport (VOID)
 
VOID NTAPI MiInitializeSessionIds (VOID)
 
BOOLEAN NTAPI MiInitializeMemoryEvents (VOID)
 
PFN_NUMBER NTAPI MxGetNextPage (IN PFN_NUMBER PageCount)
 
PPHYSICAL_MEMORY_DESCRIPTOR NTAPI MmInitializeMemoryLimits (IN PLOADER_PARAMETER_BLOCK LoaderBlock, IN PBOOLEAN IncludeType)
 
PFN_NUMBER NTAPI MiPagesInLoaderBlock (IN PLOADER_PARAMETER_BLOCK LoaderBlock, IN PBOOLEAN IncludeType)
 
VOID FASTCALL MiSyncARM3WithROS (IN PVOID AddressStart, IN PVOID AddressEnd)
 
NTSTATUS NTAPI MiRosProtectVirtualMemory (IN PEPROCESS Process, IN OUT PVOID *BaseAddress, IN OUT PSIZE_T NumberOfBytesToProtect, IN ULONG NewAccessProtection, OUT PULONG OldAccessProtection OPTIONAL)
 
NTSTATUS NTAPI MmArmAccessFault (IN ULONG FaultCode, IN PVOID Address, IN KPROCESSOR_MODE Mode, IN PVOID TrapInformation)
 
NTSTATUS FASTCALL MiCheckPdeForPagedPool (IN PVOID Address)
 
VOID NTAPI MiInitializeNonPagedPoolThresholds (VOID)
 
VOID NTAPI MiInitializePoolEvents (VOID)
 
VOID NTAPI InitializePool (IN POOL_TYPE PoolType, IN ULONG Threshold)
 
VOID NTAPI ExInitializePoolDescriptor (IN PPOOL_DESCRIPTOR PoolDescriptor, IN POOL_TYPE PoolType, IN ULONG PoolIndex, IN ULONG Threshold, IN PVOID PoolLock)
 
NTSTATUS NTAPI MiInitializeSessionPool (VOID)
 
VOID NTAPI MiInitializeSystemPtes (IN PMMPTE StartingPte, IN ULONG NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE PoolType)
 
PMMPTE NTAPI MiReserveSystemPtes (IN ULONG NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType)
 
VOID NTAPI MiReleaseSystemPtes (IN PMMPTE StartingPte, IN ULONG NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType)
 
PFN_NUMBER NTAPI MiFindContiguousPages (IN PFN_NUMBER LowestPfn, IN PFN_NUMBER HighestPfn, IN PFN_NUMBER BoundaryPfn, IN PFN_NUMBER SizeInPages, IN MEMORY_CACHING_TYPE CacheType)
 
PVOID NTAPI MiCheckForContiguousMemory (IN PVOID BaseAddress, IN PFN_NUMBER BaseAddressPages, IN PFN_NUMBER SizeInPages, IN PFN_NUMBER LowestPfn, IN PFN_NUMBER HighestPfn, IN PFN_NUMBER BoundaryPfn, IN MI_PFN_CACHE_ATTRIBUTE CacheAttribute)
 
PMDL NTAPI MiAllocatePagesForMdl (IN PHYSICAL_ADDRESS LowAddress, IN PHYSICAL_ADDRESS HighAddress, IN PHYSICAL_ADDRESS SkipBytes, IN SIZE_T TotalBytes, IN MI_PFN_CACHE_ATTRIBUTE CacheAttribute, IN ULONG Flags)
 
VOID NTAPI MiInsertPageInList (IN PMMPFNLIST ListHead, IN PFN_NUMBER PageFrameIndex)
 
VOID NTAPI MiUnlinkFreeOrZeroedPage (IN PMMPFN Entry)
 
VOID NTAPI MiUnlinkPageFromList (IN PMMPFN Pfn)
 
VOID NTAPI MiInitializePfn (IN PFN_NUMBER PageFrameIndex, IN PMMPTE PointerPte, IN BOOLEAN Modified)
 
NTSTATUS NTAPI MiInitializeAndChargePfn (OUT PPFN_NUMBER PageFrameIndex, IN PMMPDE PointerPde, IN PFN_NUMBER ContainingPageFrame, IN BOOLEAN SessionAllocation)
 
VOID NTAPI MiInitializePfnAndMakePteValid (IN PFN_NUMBER PageFrameIndex, IN PMMPTE PointerPte, IN MMPTE TempPte)
 
VOID NTAPI MiInitializePfnForOtherProcess (IN PFN_NUMBER PageFrameIndex, IN PVOID PteAddress, IN PFN_NUMBER PteFrame)
 
VOID NTAPI MiDecrementShareCount (IN PMMPFN Pfn1, IN PFN_NUMBER PageFrameIndex)
 
PFN_NUMBER NTAPI MiRemoveAnyPage (IN ULONG Color)
 
PFN_NUMBER NTAPI MiRemoveZeroPage (IN ULONG Color)
 
VOID NTAPI MiZeroPhysicalPage (IN PFN_NUMBER PageFrameIndex)
 
VOID NTAPI MiInsertPageInFreeList (IN PFN_NUMBER PageFrameIndex)
 
PFN_COUNT NTAPI MiDeleteSystemPageableVm (IN PMMPTE PointerPte, IN PFN_NUMBER PageCount, IN ULONG Flags, OUT PPFN_NUMBER ValidPages)
 
ULONG NTAPI MiGetPageProtection (IN PMMPTE PointerPte)
 
PLDR_DATA_TABLE_ENTRY NTAPI MiLookupDataTableEntry (IN PVOID Address)
 
VOID NTAPI MiInitializeDriverLargePageList (VOID)
 
VOID NTAPI MiInitializeLargePageSupport (VOID)
 
VOID NTAPI MiSyncCachedRanges (VOID)
 
BOOLEAN NTAPI MiIsPfnInUse (IN PMMPFN Pfn1)
 
PMMVAD NTAPI MiLocateAddress (IN PVOID VirtualAddress)
 
TABLE_SEARCH_RESULT NTAPI MiCheckForConflictingNode (IN ULONG_PTR StartVpn, IN ULONG_PTR EndVpn, IN PMM_AVL_TABLE Table, OUT PMMADDRESS_NODE *NodeOrParent)
 
TABLE_SEARCH_RESULT NTAPI MiFindEmptyAddressRangeDownTree (IN SIZE_T Length, IN ULONG_PTR BoundaryAddress, IN ULONG_PTR Alignment, IN PMM_AVL_TABLE Table, OUT PULONG_PTR Base, OUT PMMADDRESS_NODE *Parent)
 
NTSTATUS NTAPI MiFindEmptyAddressRangeDownBasedTree (IN SIZE_T Length, IN ULONG_PTR BoundaryAddress, IN ULONG_PTR Alignment, IN PMM_AVL_TABLE Table, OUT PULONG_PTR Base)
 
TABLE_SEARCH_RESULT NTAPI MiFindEmptyAddressRangeInTree (IN SIZE_T Length, IN ULONG_PTR Alignment, IN PMM_AVL_TABLE Table, OUT PMMADDRESS_NODE *PreviousVad, OUT PULONG_PTR Base)
 
NTSTATUS NTAPI MiCheckSecuredVad (IN PMMVAD Vad, IN PVOID Base, IN SIZE_T Size, IN ULONG ProtectionMask)
 
VOID NTAPI MiInsertVad (_Inout_ PMMVAD Vad, _Inout_ PMM_AVL_TABLE VadRoot)
 
NTSTATUS NTAPI MiInsertVadEx (_Inout_ PMMVAD Vad, _In_ ULONG_PTR *BaseAddress, _In_ SIZE_T ViewSize, _In_ ULONG_PTR HighestAddress, _In_ ULONG_PTR Alignment, _In_ ULONG AllocationType)
 
VOID NTAPI MiInsertBasedSection (IN PSECTION Section)
 
NTSTATUS NTAPI MiRosUnmapViewOfSection (IN PEPROCESS Process, IN PVOID BaseAddress, IN BOOLEAN SkipDebuggerNotify)
 
VOID NTAPI MiInsertNode (IN PMM_AVL_TABLE Table, IN PMMADDRESS_NODE NewNode, PMMADDRESS_NODE Parent, TABLE_SEARCH_RESULT Result)
 
VOID NTAPI MiRemoveNode (IN PMMADDRESS_NODE Node, IN PMM_AVL_TABLE Table)
 
PMMADDRESS_NODE NTAPI MiGetPreviousNode (IN PMMADDRESS_NODE Node)
 
PMMADDRESS_NODE NTAPI MiGetNextNode (IN PMMADDRESS_NODE Node)
 
BOOLEAN NTAPI MiInitializeSystemSpaceMap (IN PMMSESSION InputSession OPTIONAL)
 
VOID NTAPI MiSessionRemoveProcess (VOID)
 
VOID NTAPI MiReleaseProcessReferenceToSessionDataPage (IN PMM_SESSION_SPACE SessionGlobal)
 
VOID NTAPI MiSessionAddProcess (IN PEPROCESS NewProcess)
 
ULONG NTAPI MiMakeProtectionMask (IN ULONG Protect)
 
VOID NTAPI MiDeleteVirtualAddresses (IN ULONG_PTR Va, IN ULONG_PTR EndingAddress, IN PMMVAD Vad)
 
VOID NTAPI MiDeletePte (IN PMMPTE PointerPte, IN PVOID VirtualAddress, IN PEPROCESS CurrentProcess, IN PMMPTE PrototypePte)
 
ULONG NTAPI MiMakeSystemAddressValid (IN PVOID PageTableVirtualAddress, IN PEPROCESS CurrentProcess)
 
ULONG NTAPI MiMakeSystemAddressValidPfn (IN PVOID VirtualAddress, IN KIRQL OldIrql)
 
VOID NTAPI MiRemoveMappedView (IN PEPROCESS CurrentProcess, IN PMMVAD Vad)
 
PSUBSECTION NTAPI MiLocateSubsection (IN PMMVAD Vad, IN ULONG_PTR Vpn)
 
VOID NTAPI MiDeleteARM3Section (PVOID ObjectBody)
 
NTSTATUS NTAPI MiQueryMemorySectionName (IN HANDLE ProcessHandle, IN PVOID BaseAddress, OUT PVOID MemoryInformation, IN SIZE_T MemoryInformationLength, OUT PSIZE_T ReturnLength)
 
NTSTATUS NTAPI MiRosUnmapViewInSystemSpace (IN PVOID MappedBase)
 
VOID NTAPI MiMakePdeExistAndMakeValid (IN PMMPDE PointerPde, IN PEPROCESS TargetProcess, IN KIRQL OldIrql)
 
VOID NTAPI MiWriteProtectSystemImage (_In_ PVOID ImageBase)
 
FORCEINLINE PFN_NUMBER MiRemoveZeroPageSafe (IN ULONG Color)
 
FORCEINLINE USHORT MiIncrementPageTableReferences (IN PVOID Address)
 
FORCEINLINE USHORT MiDecrementPageTableReferences (IN PVOID Address)
 
FORCEINLINE VOID MiDeletePde (_In_ PMMPDE PointerPde, _In_ PEPROCESS CurrentProcess)
 

Variables

const ULONG_PTR MmProtectToPteMask [32]
 
const ULONG MmProtectToValue [32]
 
ULONG ExpNumberOfPagedPools
 
POOL_DESCRIPTOR NonPagedPoolDescriptor
 
PPOOL_DESCRIPTOR ExpPagedPoolDescriptor [16+1]
 
PPOOL_TRACKER_TABLE PoolTrackTable
 
PMM_SESSION_SPACE MmSessionSpace
 
MMPTE HyperTemplatePte
 
MMPDE ValidKernelPde
 
MMPTE ValidKernelPte
 
MMPDE ValidKernelPdeLocal
 
MMPTE ValidKernelPteLocal
 
MMPDE DemandZeroPde
 
MMPTE DemandZeroPte
 
MMPTE PrototypePte
 
MMPTE MmDecommittedPte
 
BOOLEAN MmLargeSystemCache
 
BOOLEAN MmZeroPageFile
 
BOOLEAN MmProtectFreedNonPagedPool
 
BOOLEAN MmTrackLockedPages
 
BOOLEAN MmTrackPtes
 
BOOLEAN MmDynamicPfn
 
BOOLEAN MmMirroring
 
BOOLEAN MmMakeLowMemory
 
BOOLEAN MmEnforceWriteProtection
 
SIZE_T MmAllocationFragment
 
ULONG MmConsumedPoolPercentage
 
ULONG MmVerifyDriverBufferType
 
ULONG MmVerifyDriverLevel
 
WCHAR MmVerifyDriverBuffer [512]
 
WCHAR MmLargePageDriverBuffer [512]
 
LIST_ENTRY MiLargePageDriverList
 
BOOLEAN MiLargePageAllDrivers
 
ULONG MmVerifyDriverBufferLength
 
ULONG MmLargePageDriverBufferLength
 
SIZE_T MmSizeOfNonPagedPoolInBytes
 
SIZE_T MmMaximumNonPagedPoolInBytes
 
PFN_NUMBER MmMaximumNonPagedPoolInPages
 
PFN_NUMBER MmSizeOfPagedPoolInPages
 
PVOID MmNonPagedSystemStart
 
PVOID MmNonPagedPoolStart
 
PVOID MmNonPagedPoolExpansionStart
 
PVOID MmNonPagedPoolEnd
 
SIZE_T MmSizeOfPagedPoolInBytes
 
PVOID MmPagedPoolStart
 
PVOID MmPagedPoolEnd
 
PVOID MmSessionBase
 
SIZE_T MmSessionSize
 
PMMPTE MmFirstReservedMappingPte
 
PMMPTE MmLastReservedMappingPte
 
PMMPTE MiFirstReservedZeroingPte
 
MI_PFN_CACHE_ATTRIBUTE MiPlatformCacheAttributes [2][MmMaximumCacheType]
 
PPHYSICAL_MEMORY_DESCRIPTOR MmPhysicalMemoryBlock
 
SIZE_T MmBootImageSize
 
PMMPTE MmSystemPtesStart [MaximumPtePoolTypes]
 
PMMPTE MmSystemPtesEnd [MaximumPtePoolTypes]
 
PMEMORY_ALLOCATION_DESCRIPTOR MxFreeDescriptor
 
MEMORY_ALLOCATION_DESCRIPTOR MxOldFreeDescriptor
 
ULONG_PTR MxPfnAllocation
 
MM_PAGED_POOL_INFO MmPagedPoolInfo
 
KGUARDED_MUTEX MmPagedPoolMutex
 
KGUARDED_MUTEX MmSectionCommitMutex
 
PVOID MiSystemViewStart
 
SIZE_T MmSystemViewSize
 
PVOID MiSessionSpaceEnd
 
PMMPTE MiSessionImagePteStart
 
PMMPTE MiSessionImagePteEnd
 
PMMPTE MiSessionBasePte
 
PMMPTE MiSessionLastPte
 
PMMPDE MmSystemPagePtes
 
PVOID MmSystemCacheStart
 
PVOID MmSystemCacheEnd
 
MMSUPPORT MmSystemCacheWs
 
SIZE_T MmAllocatedNonPagedPool
 
ULONG MmSpecialPoolTag
 
PVOID MmHyperSpaceEnd
 
PMMWSL MmSystemCacheWorkingSetList
 
SIZE_T MmMinimumNonPagedPoolSize
 
ULONG MmMinAdditionNonPagedPoolPerMb
 
SIZE_T MmDefaultMaximumNonPagedPool
 
ULONG MmMaxAdditionNonPagedPoolPerMb
 
ULONG MmSecondaryColors
 
ULONG MmSecondaryColorMask
 
ULONG MmNumberOfSystemPtes
 
ULONG MmMaximumNonPagedPoolPercent
 
ULONG MmLargeStackSize
 
PMMCOLOR_TABLES MmFreePagesByColor [FreePageList+1]
 
MMPFNLIST MmStandbyPageListByPriority [8]
 
ULONG MmProductType
 
MM_SYSTEMSIZE MmSystemSize
 
PKEVENT MiLowMemoryEvent
 
PKEVENT MiHighMemoryEvent
 
PKEVENT MiLowPagedPoolEvent
 
PKEVENT MiHighPagedPoolEvent
 
PKEVENT MiLowNonPagedPoolEvent
 
PKEVENT MiHighNonPagedPoolEvent
 
PFN_NUMBER MmLowMemoryThreshold
 
PFN_NUMBER MmHighMemoryThreshold
 
PFN_NUMBER MiLowPagedPoolThreshold
 
PFN_NUMBER MiHighPagedPoolThreshold
 
PFN_NUMBER MiLowNonPagedPoolThreshold
 
PFN_NUMBER MiHighNonPagedPoolThreshold
 
PFN_NUMBER MmMinimumFreePages
 
PFN_NUMBER MmPlentyFreePages
 
SIZE_T MmMinimumStackCommitInBytes
 
PFN_COUNT MiExpansionPoolPagesInitialCharge
 
PFN_NUMBER MmResidentAvailableAtInit
 
ULONG MmTotalFreeSystemPtes [MaximumPtePoolTypes]
 
PFN_NUMBER MmTotalSystemDriverPages
 
ULONG MmCritsectTimeoutSeconds
 
PVOID MiSessionImageStart
 
PVOID MiSessionImageEnd
 
PMMPTE MiHighestUserPte
 
PMMPDE MiHighestUserPde
 
PFN_NUMBER MmSystemPageDirectory [PPE_PER_PAGE]
 
PMMPTE MmSharedUserDataPte
 
LIST_ENTRY MmProcessList
 
KEVENT MmZeroingPageEvent
 
ULONG MmSystemPageColor
 
ULONG MmProcessColorSeed
 
PMMWSL MmWorkingSetList
 
PFN_NUMBER MiNumberOfFreePages
 
SIZE_T MmSessionViewSize
 
SIZE_T MmSessionPoolSize
 
SIZE_T MmSessionImageSize
 
PVOID MiSessionPoolEnd
 
PVOID MiSessionPoolStart
 
PVOID MiSessionViewStart
 
PVOID MiSessionSpaceWs
 
ULONG MmMaximumDeadKernelStacks
 
SLIST_HEADER MmDeadStackSListHead
 
MM_AVL_TABLE MmSectionBasedRoot
 
KGUARDED_MUTEX MmSectionBasedMutex
 
PVOID MmHighSectionBase
 
SIZE_T MmSystemLockPagesCount
 
ULONG_PTR MmSubsectionBase
 
LARGE_INTEGER MmCriticalSectionTimeout
 
LIST_ENTRY MmWorkingSetExpansionHead
 
KSPIN_LOCK MmExpansionLock
 
PETHREAD MiExpansionLockOwner
 

Macro Definition Documentation

◆ _1GB

#define _1GB   (1024 * _1MB)

Definition at line 20 of file miarm.h.

◆ _1KB

#define _1KB   (1024u)

Definition at line 18 of file miarm.h.

◆ _1MB

#define _1MB   (1024 * _1KB)

Definition at line 19 of file miarm.h.

◆ _64K

#define _64K   (64 * _1KB)

Definition at line 23 of file miarm.h.

◆ BASE_POOL_TYPE_MASK

#define BASE_POOL_TYPE_MASK   1

Definition at line 272 of file miarm.h.

◆ IMAGE_SCN_PROTECTION_MASK

#define IMAGE_SCN_PROTECTION_MASK   (IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE)

Definition at line 160 of file miarm.h.

◆ MI_GET_NEXT_COLOR

#define MI_GET_NEXT_COLOR ( )    (MI_GET_PAGE_COLOR(++MmSystemPageColor))

Definition at line 232 of file miarm.h.

◆ MI_GET_NEXT_PROCESS_COLOR

#define MI_GET_NEXT_PROCESS_COLOR (   x)    (MI_GET_PAGE_COLOR(++(x)->NextPageColor))

Definition at line 233 of file miarm.h.

◆ MI_GET_PAGE_COLOR

#define MI_GET_PAGE_COLOR (   x)    ((x) & MmSecondaryColorMask)

Definition at line 231 of file miarm.h.

◆ MI_INITIAL_SESSION_IDS

#define MI_INITIAL_SESSION_IDS   64

Definition at line 207 of file miarm.h.

◆ MI_IS_PAGE_TABLE_ADDRESS

#define MI_IS_PAGE_TABLE_ADDRESS (   Address)     (((PVOID)(Address) >= (PVOID)PTE_BASE) && ((PVOID)(Address) <= (PVOID)PTE_TOP))

Definition at line 177 of file miarm.h.

◆ MI_IS_PAGE_TABLE_OR_HYPER_ADDRESS

#define MI_IS_PAGE_TABLE_OR_HYPER_ADDRESS (   Address)     (((PVOID)(Address) >= (PVOID)PTE_BASE) && ((PVOID)(Address) <= (PVOID)MmHyperSpaceEnd))

Definition at line 183 of file miarm.h.

◆ MI_IS_PFN_DELETED

#define MI_IS_PFN_DELETED (   x)    ((ULONG_PTR)((x)->PteAddress) & 1)

Definition at line 195 of file miarm.h.

◆ MI_IS_ROS_PFN

#define MI_IS_ROS_PFN (   x)    ((x)->u4.AweAllocation == TRUE)

Definition at line 1103 of file miarm.h.

◆ MI_IS_SESSION_ADDRESS

#define MI_IS_SESSION_ADDRESS (   Address)     (((Address) >= MmSessionBase) && ((Address) < MiSessionSpaceEnd))

Definition at line 171 of file miarm.h.

◆ MI_IS_SESSION_IMAGE_ADDRESS

#define MI_IS_SESSION_IMAGE_ADDRESS (   Address)     (((Address) >= MiSessionImageStart) && ((Address) < MiSessionImageEnd))

Definition at line 168 of file miarm.h.

◆ MI_IS_SESSION_PTE

#define MI_IS_SESSION_PTE (   Pte)     ((((PMMPTE)Pte) >= MiSessionBasePte) && (((PMMPTE)Pte) < MiSessionLastPte))

Definition at line 174 of file miarm.h.

◆ MI_IS_SYSTEM_PAGE_TABLE_ADDRESS

#define MI_IS_SYSTEM_PAGE_TABLE_ADDRESS (   Address)     (((Address) >= (PVOID)MiAddressToPte(MmSystemRangeStart)) && ((Address) <= (PVOID)PTE_TOP))

Definition at line 180 of file miarm.h.

◆ MI_LOWEST_VAD_ADDRESS

#define MI_LOWEST_VAD_ADDRESS   (PVOID)MM_LOWEST_USER_ADDRESS

Definition at line 15 of file miarm.h.

◆ MI_MAKE_SOFTWARE_PTE

#define MI_MAKE_SOFTWARE_PTE (   p,
  x 
)    ((p)->u.Long = (x << MM_PTE_SOFTWARE_PROTECTION_BITS))

Definition at line 189 of file miarm.h.

◆ MI_PTE_LOOKUP_NEEDED

#define MI_PTE_LOOKUP_NEEDED   0xFFFFF

Definition at line 241 of file miarm.h.

◆ MI_SESSION_DATA_PAGES_MAXIMUM

#define MI_SESSION_DATA_PAGES_MAXIMUM   (MM_ALLOCATION_GRANULARITY / PAGE_SIZE)

Definition at line 247 of file miarm.h.

◆ MI_SESSION_TAG_PAGES_MAXIMUM

#define MI_SESSION_TAG_PAGES_MAXIMUM   (MM_ALLOCATION_GRANULARITY / PAGE_SIZE)

Definition at line 248 of file miarm.h.

◆ MI_SET_PFN_DELETED

#define MI_SET_PFN_DELETED (   x)    ((x)->PteAddress = (PMMPTE)((ULONG_PTR)(x)->PteAddress | 1))

Definition at line 194 of file miarm.h.

◆ MI_SYSTEM_VIEW_BUCKET_SIZE

#define MI_SYSTEM_VIEW_BUCKET_SIZE   _64K

Definition at line 261 of file miarm.h.

◆ MM_DECOMMIT

#define MM_DECOMMIT   (MM_ZERO_ACCESS | MM_GUARDPAGE)

Definition at line 64 of file miarm.h.

◆ MM_DELETE_CHECK

#define MM_DELETE_CHECK   85

Definition at line 256 of file miarm.h.

◆ MM_EXECUTE

#define MM_EXECUTE   2

Definition at line 45 of file miarm.h.

◆ MM_EXECUTE_READ

#define MM_EXECUTE_READ   3

Definition at line 46 of file miarm.h.

◆ MM_EXECUTE_READWRITE

#define MM_EXECUTE_READWRITE   6

Definition at line 49 of file miarm.h.

◆ MM_EXECUTE_WRITECOPY

#define MM_EXECUTE_WRITECOPY   7

Definition at line 50 of file miarm.h.

◆ MM_GUARDPAGE

#define MM_GUARDPAGE   0x10

Definition at line 57 of file miarm.h.

◆ MM_INVALID_PROTECTION

#define MM_INVALID_PROTECTION   0xFFFFFFFF

Definition at line 67 of file miarm.h.

◆ MM_NO_ACCESS_ALLOWED

#define MM_NO_ACCESS_ALLOWED   01

Definition at line 255 of file miarm.h.

◆ MM_NOACCESS

#define MM_NOACCESS   (MM_ZERO_ACCESS | MM_WRITECOMBINE)

Definition at line 65 of file miarm.h.

◆ MM_NOCACHE

#define MM_NOCACHE   0x08

Definition at line 56 of file miarm.h.

◆ MM_OUTSWAPPED_KSTACK

#define MM_OUTSWAPPED_KSTACK   (MM_EXECUTE_WRITECOPY | MM_WRITECOMBINE)

Definition at line 66 of file miarm.h.

◆ MM_PROTECT_ACCESS

#define MM_PROTECT_ACCESS   7

Definition at line 51 of file miarm.h.

◆ MM_PROTECT_SPECIAL

#define MM_PROTECT_SPECIAL   0x18

Definition at line 59 of file miarm.h.

◆ MM_READ_ONLY_ALLOWED

#define MM_READ_ONLY_ALLOWED   10

Definition at line 254 of file miarm.h.

◆ MM_READ_WRITE_ALLOWED

#define MM_READ_WRITE_ALLOWED   11

Definition at line 253 of file miarm.h.

◆ MM_READONLY

#define MM_READONLY   1

Definition at line 44 of file miarm.h.

◆ MM_READWRITE

#define MM_READWRITE   4

Definition at line 47 of file miarm.h.

◆ MM_SYSLDR_BOOT_LOADED

#define MM_SYSLDR_BOOT_LOADED   ((PVOID)(ULONG_PTR)-1)

Definition at line 201 of file miarm.h.

◆ MM_SYSLDR_NO_IMPORTS

#define MM_SYSLDR_NO_IMPORTS   ((PVOID)(ULONG_PTR)-2)

Definition at line 200 of file miarm.h.

◆ MM_SYSLDR_SINGLE_ENTRY

#define MM_SYSLDR_SINGLE_ENTRY   0x1

Definition at line 202 of file miarm.h.

◆ MM_WRITECOMBINE

#define MM_WRITECOMBINE   0x18

Definition at line 58 of file miarm.h.

◆ MM_WRITECOPY

#define MM_WRITECOPY   5

Definition at line 48 of file miarm.h.

◆ MM_ZERO_ACCESS

#define MM_ZERO_ACCESS   0

Definition at line 43 of file miarm.h.

◆ PD_SIZE

#define PD_SIZE   (PDE_PER_PAGE * sizeof(MMPDE))

Definition at line 29 of file miarm.h.

◆ POOL_ALLOC_IRQL_INVALID

#define POOL_ALLOC_IRQL_INVALID   8

Definition at line 304 of file miarm.h.

◆ POOL_BILLED_PROCESS_INVALID

#define POOL_BILLED_PROCESS_INVALID   13

Definition at line 306 of file miarm.h.

◆ POOL_BLOCK_SIZE

#define POOL_BLOCK_SIZE   8

Definition at line 269 of file miarm.h.

◆ POOL_CORRUPTED_LIST

#define POOL_CORRUPTED_LIST   3

Definition at line 290 of file miarm.h.

◆ POOL_ENTRIES_NOT_ALIGNED_NEXT

#define POOL_ENTRIES_NOT_ALIGNED_NEXT   9

Definition at line 295 of file miarm.h.

◆ POOL_ENTRIES_NOT_ALIGNED_PREVIOUS

#define POOL_ENTRIES_NOT_ALIGNED_PREVIOUS   6

Definition at line 292 of file miarm.h.

◆ POOL_ENTRY_ALREADY_FREE

#define POOL_ENTRY_ALREADY_FREE   6

Definition at line 302 of file miarm.h.

◆ POOL_ENTRY_CORRUPTED

#define POOL_ENTRY_CORRUPTED   1

Definition at line 301 of file miarm.h.

◆ POOL_ENTRY_NOT_ALLOCATED

#define POOL_ENTRY_NOT_ALLOCATED   7

Definition at line 303 of file miarm.h.

◆ POOL_ENTRY_NOT_FOUND

#define POOL_ENTRY_NOT_FOUND   10

Definition at line 296 of file miarm.h.

◆ POOL_FLAG_CHECK_DEADLOCK

#define POOL_FLAG_CHECK_DEADLOCK   0x10

Definition at line 282 of file miarm.h.

◆ POOL_FLAG_CHECK_RESOURCES

#define POOL_FLAG_CHECK_RESOURCES   0x4

Definition at line 280 of file miarm.h.

◆ POOL_FLAG_CHECK_TIMERS

#define POOL_FLAG_CHECK_TIMERS   0x1

Definition at line 278 of file miarm.h.

◆ POOL_FLAG_CHECK_WORKERS

#define POOL_FLAG_CHECK_WORKERS   0x2

Definition at line 279 of file miarm.h.

◆ POOL_FLAG_CRASH_ON_FAILURE

#define POOL_FLAG_CRASH_ON_FAILURE   0x80

Definition at line 285 of file miarm.h.

◆ POOL_FLAG_DBGPRINT_ON_FAILURE

#define POOL_FLAG_DBGPRINT_ON_FAILURE   0x40

Definition at line 284 of file miarm.h.

◆ POOL_FLAG_SPECIAL_POOL

#define POOL_FLAG_SPECIAL_POOL   0x20

Definition at line 283 of file miarm.h.

◆ POOL_FLAG_VERIFIER

#define POOL_FLAG_VERIFIER   0x8

Definition at line 281 of file miarm.h.

◆ POOL_FREE_IRQL_INVALID

#define POOL_FREE_IRQL_INVALID   9

Definition at line 305 of file miarm.h.

◆ POOL_HEADER_IS_ZERO

#define POOL_HEADER_IS_ZERO   8

Definition at line 294 of file miarm.h.

◆ POOL_HEADER_NOT_ALIGNED

#define POOL_HEADER_NOT_ALIGNED   7

Definition at line 293 of file miarm.h.

◆ POOL_HEADER_SIZE_INVALID

#define POOL_HEADER_SIZE_INVALID   32

Definition at line 307 of file miarm.h.

◆ POOL_LISTS_PER_PAGE

#define POOL_LISTS_PER_PAGE   (PAGE_SIZE / POOL_BLOCK_SIZE)

Definition at line 271 of file miarm.h.

◆ POOL_MAX_ALLOC

#define POOL_MAX_ALLOC   (PAGE_SIZE - (sizeof(POOL_HEADER) + POOL_BLOCK_SIZE))

Definition at line 273 of file miarm.h.

◆ POOL_SIZE_OR_INDEX_MISMATCH

#define POOL_SIZE_OR_INDEX_MISMATCH   5

Definition at line 291 of file miarm.h.

◆ PT_SIZE

#define PT_SIZE   (PTE_PER_PAGE * sizeof(MMPTE))

Definition at line 26 of file miarm.h.

◆ SYSTEM_PD_SIZE

#define SYSTEM_PD_SIZE   (PPE_PER_PAGE * PD_SIZE)

Definition at line 32 of file miarm.h.

Typedef Documentation

◆ MI_LARGE_PAGE_DRIVER_ENTRY

◆ MI_LARGE_PAGE_RANGES

◆ MI_PFN_CACHE_ATTRIBUTE

◆ MM_SESSION_SPACE

◆ MM_SESSION_SPACE_FLAGS

◆ MMCOLOR_TABLES

◆ MMSESSION

◆ MMSYSTEM_PTE_POOL_TYPE

◆ MMVIEW

◆ PHYSICAL_MEMORY_DESCRIPTOR

◆ PHYSICAL_MEMORY_RUN

◆ PMI_LARGE_PAGE_DRIVER_ENTRY

◆ PMI_LARGE_PAGE_RANGES

◆ PMI_PFN_CACHE_ATTRIBUTE

◆ PMM_SESSION_SPACE

◆ PMMCOLOR_TABLES

◆ PMMSESSION

◆ PMMVIEW

typedef struct _MMVIEW * PMMVIEW

◆ POOL_DESCRIPTOR

◆ POOL_HEADER

◆ POOL_TRACKER_BIG_PAGES

◆ POOL_TRACKER_TABLE

◆ PPHYSICAL_MEMORY_DESCRIPTOR

◆ PPHYSICAL_MEMORY_RUN

◆ PPOOL_DESCRIPTOR

◆ PPOOL_HEADER

◆ PPOOL_TRACKER_BIG_PAGES

◆ PPOOL_TRACKER_TABLE

Enumeration Type Documentation

◆ _MI_PFN_CACHE_ATTRIBUTE

Enumerator
MiNonCached 
MiCached 
MiWriteCombined 
MiNotMapped 

Definition at line 408 of file miarm.h.

409{
411 MiCached,
enum _MI_PFN_CACHE_ATTRIBUTE MI_PFN_CACHE_ATTRIBUTE
@ MiWriteCombined
Definition: miarm.h:412
@ MiCached
Definition: miarm.h:411
@ MiNotMapped
Definition: miarm.h:413
@ MiNonCached
Definition: miarm.h:410
enum _MI_PFN_CACHE_ATTRIBUTE * PMI_PFN_CACHE_ATTRIBUTE

◆ _MMSYSTEM_PTE_POOL_TYPE

Enumerator
SystemPteSpace 
NonPagedPoolExpansion 
MaximumPtePoolTypes 

Definition at line 401 of file miarm.h.

402{
@ SystemPteSpace
Definition: miarm.h:403
@ MaximumPtePoolTypes
Definition: miarm.h:405
@ NonPagedPoolExpansion
Definition: miarm.h:404
enum _MMSYSTEM_PTE_POOL_TYPE MMSYSTEM_PTE_POOL_TYPE

Function Documentation

◆ C_ASSERT() [1/2]

C_ASSERT ( POOL_BLOCK_SIZE  = =sizeof(LIST_ENTRY))

◆ C_ASSERT() [2/2]

C_ASSERT ( sizeof(POOL_HEADER = =POOL_BLOCK_SIZE)

◆ ExInitializePoolDescriptor()

VOID NTAPI ExInitializePoolDescriptor ( IN PPOOL_DESCRIPTOR  PoolDescriptor,
IN POOL_TYPE  PoolType,
IN ULONG  PoolIndex,
IN ULONG  Threshold,
IN PVOID  PoolLock 
)

Definition at line 969 of file expool.c.

974{
975 PLIST_ENTRY NextEntry, LastEntry;
976
977 //
978 // Setup the descriptor based on the caller's request
979 //
980 PoolDescriptor->PoolType = PoolType;
981 PoolDescriptor->PoolIndex = PoolIndex;
982 PoolDescriptor->Threshold = Threshold;
983 PoolDescriptor->LockAddress = PoolLock;
984
985 //
986 // Initialize accounting data
987 //
988 PoolDescriptor->RunningAllocs = 0;
989 PoolDescriptor->RunningDeAllocs = 0;
990 PoolDescriptor->TotalPages = 0;
991 PoolDescriptor->TotalBytes = 0;
992 PoolDescriptor->TotalBigPages = 0;
993
994 //
995 // Nothing pending for now
996 //
997 PoolDescriptor->PendingFrees = NULL;
998 PoolDescriptor->PendingFreeDepth = 0;
999
1000 //
1001 // Loop all the descriptor's allocation lists and initialize them
1002 //
1003 NextEntry = PoolDescriptor->ListHeads;
1004 LastEntry = NextEntry + POOL_LISTS_PER_PAGE;
1005 while (NextEntry < LastEntry)
1006 {
1007 ExpInitializePoolListHead(NextEntry);
1008 NextEntry++;
1009 }
1010
1011 //
1012 // Note that ReactOS does not support Session Pool Yet
1013 //
1015}
#define NULL
Definition: types.h:112
VOID NTAPI ExpInitializePoolListHead(IN PLIST_ENTRY ListHead)
Definition: expool.c:114
#define POOL_LISTS_PER_PAGE
Definition: miarm.h:271
#define ASSERT(a)
Definition: mode.c:44
Definition: typedefs.h:120
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ _Strict_type_match_ POOL_TYPE PoolType
Definition: wdfdevice.h:3815
@ PagedPoolSession
Definition: ketypes.h:893

Referenced by InitializePool(), and MiInitializeSessionPool().

◆ InitializePool()

VOID NTAPI InitializePool ( IN POOL_TYPE  PoolType,
IN ULONG  Threshold 
)

Definition at line 1020 of file expool.c.

1022{
1025 ULONG i;
1026
1027 //
1028 // Check what kind of pool this is
1029 //
1030 if (PoolType == NonPagedPool)
1031 {
1032 //
1033 // Compute the track table size and convert it from a power of two to an
1034 // actual byte size
1035 //
1036 // NOTE: On checked builds, we'll assert if the registry table size was
1037 // invalid, while on retail builds we'll just break out of the loop at
1038 // that point.
1039 //
1041 for (i = 0; i < 32; i++)
1042 {
1043 if (TableSize & 1)
1044 {
1045 ASSERT((TableSize & ~1) == 0);
1046 if (!(TableSize & ~1)) break;
1047 }
1048 TableSize >>= 1;
1049 }
1050
1051 //
1052 // If we hit bit 32, than no size was defined in the registry, so
1053 // we'll use the default size of 2048 entries.
1054 //
1055 // Otherwise, use the size from the registry, as long as it's not
1056 // smaller than 64 entries.
1057 //
1058 if (i == 32)
1059 {
1060 PoolTrackTableSize = 2048;
1061 }
1062 else
1063 {
1064 PoolTrackTableSize = max(1 << i, 64);
1065 }
1066
1067 //
1068 // Loop trying with the biggest specified size first, and cut it down
1069 // by a power of two each iteration in case not enough memory exist
1070 //
1071 while (TRUE)
1072 {
1073 //
1074 // Do not allow overflow
1075 //
1076 if ((PoolTrackTableSize + 1) > (MAXULONG_PTR / sizeof(POOL_TRACKER_TABLE)))
1077 {
1078 PoolTrackTableSize >>= 1;
1079 continue;
1080 }
1081
1082 //
1083 // Allocate the tracker table and exit the loop if this worked
1084 //
1086 (PoolTrackTableSize + 1) *
1087 sizeof(POOL_TRACKER_TABLE));
1088 if (PoolTrackTable) break;
1089
1090 //
1091 // Otherwise, as long as we're not down to the last bit, keep
1092 // iterating
1093 //
1094 if (PoolTrackTableSize == 1)
1095 {
1096 KeBugCheckEx(MUST_SUCCEED_POOL_EMPTY,
1097 TableSize,
1098 0xFFFFFFFF,
1099 0xFFFFFFFF,
1100 0xFFFFFFFF);
1101 }
1102 PoolTrackTableSize >>= 1;
1103 }
1104
1105 //
1106 // Add one entry, compute the hash, and zero the table
1107 //
1110
1113
1114 //
1115 // Finally, add the most used tags to speed up those allocations
1116 //
1118
1119 //
1120 // We now do the exact same thing with the tracker table for big pages
1121 //
1123 for (i = 0; i < 32; i++)
1124 {
1125 if (TableSize & 1)
1126 {
1127 ASSERT((TableSize & ~1) == 0);
1128 if (!(TableSize & ~1)) break;
1129 }
1130 TableSize >>= 1;
1131 }
1132
1133 //
1134 // For big pages, the default tracker table is 4096 entries, while the
1135 // minimum is still 64
1136 //
1137 if (i == 32)
1138 {
1139 PoolBigPageTableSize = 4096;
1140 }
1141 else
1142 {
1143 PoolBigPageTableSize = max(1 << i, 64);
1144 }
1145
1146 //
1147 // Again, run the exact same loop we ran earlier, but this time for the
1148 // big pool tracker instead
1149 //
1150 while (TRUE)
1151 {
1153 {
1155 continue;
1156 }
1157
1160 sizeof(POOL_TRACKER_BIG_PAGES));
1161 if (PoolBigPageTable) break;
1162
1163 if (PoolBigPageTableSize == 1)
1164 {
1165 KeBugCheckEx(MUST_SUCCEED_POOL_EMPTY,
1166 TableSize,
1167 0xFFFFFFFF,
1168 0xFFFFFFFF,
1169 0xFFFFFFFF);
1170 }
1171
1173 }
1174
1175 //
1176 // An extra entry is not needed for for the big pool tracker, so just
1177 // compute the hash and zero it
1178 //
1182 for (i = 0; i < PoolBigPageTableSize; i++)
1183 {
1185 }
1186
1187 //
1188 // During development, print this out so we can see what's happening
1189 //
1190 DPRINT("EXPOOL: Pool Tracker Table at: 0x%p with 0x%lx bytes\n",
1192 DPRINT("EXPOOL: Big Pool Tracker Table at: 0x%p with 0x%lx bytes\n",
1194
1195 //
1196 // Insert the generic tracker for all of big pool
1197 //
1198 ExpInsertPoolTracker('looP',
1200 sizeof(POOL_TRACKER_BIG_PAGES)),
1201 NonPagedPool);
1202
1203 //
1204 // No support for NUMA systems at this time
1205 //
1206 ASSERT(KeNumberNodes == 1);
1207
1208 //
1209 // Initialize the tag spinlock
1210 //
1212
1213 //
1214 // Initialize the nonpaged pool descriptor
1215 //
1219 0,
1220 Threshold,
1221 NULL);
1222 }
1223 else
1224 {
1225 //
1226 // No support for NUMA systems at this time
1227 //
1228 ASSERT(KeNumberNodes == 1);
1229
1230 //
1231 // Allocate the pool descriptor
1232 //
1234 sizeof(KGUARDED_MUTEX) +
1235 sizeof(POOL_DESCRIPTOR),
1236 'looP');
1237 if (!Descriptor)
1238 {
1239 //
1240 // This is really bad...
1241 //
1242 KeBugCheckEx(MUST_SUCCEED_POOL_EMPTY,
1243 0,
1244 -1,
1245 -1,
1246 -1);
1247 }
1248
1249 //
1250 // Setup the vector and guarded mutex for paged pool
1251 //
1257 PagedPool,
1258 0,
1259 Threshold,
1261
1262 //
1263 // Insert the generic tracker for all of nonpaged pool
1264 //
1265 ExpInsertPoolTracker('looP',
1267 NonPagedPool);
1268 }
1269}
#define MAXULONG_PTR
Definition: basetsd.h:103
#define TRUE
Definition: types.h:120
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define NonPagedPool
Definition: env_spec_w32.h:307
#define KeInitializeSpinLock(sl)
Definition: env_spec_w32.h:604
#define PagedPool
Definition: env_spec_w32.h:308
VOID NTAPI ExInitializePoolDescriptor(IN PPOOL_DESCRIPTOR PoolDescriptor, IN POOL_TYPE PoolType, IN ULONG PoolIndex, IN ULONG Threshold, IN PVOID PoolLock)
Definition: expool.c:969
PPOOL_DESCRIPTOR PoolVector[2]
Definition: expool.c:44
SIZE_T PoolTrackTableMask
Definition: expool.c:46
SIZE_T PoolBigPageTableSize
Definition: expool.c:47
PPOOL_TRACKER_BIG_PAGES PoolBigPageTable
Definition: expool.c:50
PKGUARDED_MUTEX ExpPagedPoolMutex
Definition: expool.c:45
KSPIN_LOCK ExpTaggedPoolLock
Definition: expool.c:51
POOL_DESCRIPTOR NonPagedPoolDescriptor
Definition: expool.c:42
PPOOL_TRACKER_TABLE PoolTrackTable
Definition: expool.c:49
PPOOL_DESCRIPTOR ExpPagedPoolDescriptor[16+1]
Definition: expool.c:43
#define POOL_BIG_TABLE_ENTRY_FREE
Definition: expool.c:23
VOID NTAPI ExpSeedHotTags(VOID)
Definition: expool.c:640
SIZE_T PoolTrackTableSize
Definition: expool.c:46
VOID NTAPI ExpInsertPoolTracker(IN ULONG Key, IN SIZE_T NumberOfBytes, IN POOL_TYPE PoolType)
Definition: expool.c:851
SIZE_T PoolBigPageTableHash
Definition: expool.c:47
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
VOID FASTCALL KeInitializeGuardedMutex(OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:31
#define min(a, b)
Definition: monoChain.cc:55
UCHAR KeNumberNodes
Definition: krnlinit.c:40
PVOID NTAPI MiAllocatePoolPages(IN POOL_TYPE PoolType, IN SIZE_T SizeInBytes)
Definition: pool.c:422
ULONG MmSizeOfNonPagedPoolInBytes
Definition: init.c:21
VOID NTAPI KeBugCheckEx(_In_ ULONG BugCheckCode, _In_ ULONG_PTR BugCheckParameter1, _In_ ULONG_PTR BugCheckParameter2, _In_ ULONG_PTR BugCheckParameter3, _In_ ULONG_PTR BugCheckParameter4)
Definition: rtlcompat.c:108
#define DPRINT
Definition: sndvol32.h:73
#define max(a, b)
Definition: svc.c:63
void * PVOID
Definition: typedefs.h:50
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG
Definition: typedefs.h:59
_Must_inspect_result_ _In_ WDFIORESLIST _In_ PIO_RESOURCE_DESCRIPTOR Descriptor
Definition: wdfresource.h:342
_Must_inspect_result_ typedef _Out_ PULONG TableSize
Definition: iotypes.h:4327
struct _KGUARDED_MUTEX * PKGUARDED_MUTEX
#define ROUND_TO_PAGES(Size)

Referenced by MiBuildPagedPool(), and MiInitMachineDependent().

◆ MI_ERASE_PTE()

FORCEINLINE VOID MI_ERASE_PTE ( IN PMMPTE  PointerPte)

Definition at line 1006 of file miarm.h.

1007{
1008 /* Zero out the PTE */
1009 ASSERT(PointerPte->u.Long != 0);
1010 PointerPte->u.Long = 0;
1011}

Referenced by MiDeletePte(), MiDeleteSystemPageableVm(), MiDeleteVirtualAddresses(), MiUnmapLockedPagesInUserSpace(), and MmFreeSpecialPool().

◆ MI_GET_PROTOTYPE_PTE_FOR_VPN()

FORCEINLINE PMMPTE MI_GET_PROTOTYPE_PTE_FOR_VPN ( IN PMMVAD  Vad,
IN ULONG_PTR  Vpn 
)

Definition at line 1557 of file miarm.h.

1559{
1560 PMMPTE ProtoPte;
1561
1562 /* Find the offset within the VAD's prototype PTEs */
1563 ProtoPte = Vad->FirstPrototypePte + (Vpn - Vad->StartingVpn);
1564 ASSERT(ProtoPte <= Vad->LastContiguousPte);
1565 return ProtoPte;
1566}

Referenced by MiDeleteVirtualAddresses(), MiQueryAddressState(), and NtAllocateVirtualMemory().

◆ MI_IS_MAPPED_PTE()

FORCEINLINE BOOLEAN MI_IS_MAPPED_PTE ( PMMPTE  PointerPte)
Todo:
Make this reasonable code, this is UGLY!

Definition at line 919 of file miarm.h.

920{
922 return ((PointerPte->u.Long & 0xFFFFFC01) != 0);
923}
union _MMPTE::@2334 u
ULONG_PTR Long
Definition: mmtypes.h:215

◆ MI_IS_PHYSICAL_ADDRESS()

FORCEINLINE BOOLEAN MI_IS_PHYSICAL_ADDRESS ( IN PVOID  Address)

Definition at line 945 of file miarm.h.

946{
947 PMMPDE PointerPde;
948
949 /* Large pages are never paged out, always physically resident */
950 PointerPde = MiAddressToPde(Address);
951 return ((PointerPde->u.Hard.LargePage) && (PointerPde->u.Hard.Valid));
952}
#define MiAddressToPde(x)
Definition: mmx86.c:20
static WCHAR Address[46]
Definition: ping.c:68
ULONG64 LargePage
Definition: mmtypes.h:165
ULONG64 Valid
Definition: mmtypes.h:150
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217

Referenced by MiDispatchFault(), MiFindInitializationCode(), MiFreeInitializationCode(), MiProtectFreeNonPagedPool(), MiReleaseProcessReferenceToSessionDataPage(), MiSetPagingOfDriver(), MiUnProtectFreeNonPagedPool(), MiWriteProtectSystemImage(), MmChangeKernelResourceSectionProtection(), MmFreeDriverInitialization(), MmFreeLoaderBlock(), MmMakeKernelResourceSectionWritable(), and MmProbeAndLockPages().

◆ MI_IS_PROCESS_WORKING_SET()

FORCEINLINE BOOLEAN MI_IS_PROCESS_WORKING_SET ( PMMSUPPORT  WorkingSet)

Definition at line 661 of file miarm.h.

662{
663 return (WorkingSet != &MmSystemCacheWs) && !WorkingSet->Flags.SessionSpace;
664}
MMSUPPORT MmSystemCacheWs
Definition: init.c:55
ULONG SessionSpace
Definition: mmtypes.h:905
MMSUPPORT_FLAGS Flags
Definition: mmtypes.h:933

Referenced by MiInitializeWorkingSetList(), and MmWorkingSetManager().

◆ MI_IS_WS_UNSAFE()

FORCEINLINE BOOLEAN MI_IS_WS_UNSAFE ( IN PEPROCESS  Process)

Definition at line 1114 of file miarm.h.

1115{
1116 return (Process->Vm.Flags.AcquiredUnsafe == TRUE);
1117}
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:223

Referenced by MiLockProcessWorkingSet(), MiLockProcessWorkingSetShared(), MiLockProcessWorkingSetUnsafe(), MiUnlockProcessWorkingSet(), MiUnlockProcessWorkingSetForFault(), MiUnlockProcessWorkingSetShared(), and MiUnlockProcessWorkingSetUnsafe().

◆ MI_MAKE_HARDWARE_PTE()

FORCEINLINE VOID MI_MAKE_HARDWARE_PTE ( IN PMMPTE  NewPte,
IN PMMPTE  MappingPte,
IN ULONG_PTR  ProtectionMask,
IN PFN_NUMBER  PageFrameNumber 
)

Definition at line 807 of file miarm.h.

811{
812 /* Check that we are not setting valid a page that should not be */
813 ASSERT(ProtectionMask & MM_PROTECT_ACCESS);
814 ASSERT((ProtectionMask & MM_GUARDPAGE) == 0);
815
816 /* Set the protection and page */
817 NewPte->u.Long = MiDetermineUserGlobalPteMask(MappingPte);
818 NewPte->u.Long |= MmProtectToPteMask[ProtectionMask];
819 NewPte->u.Hard.PageFrameNumber = PageFrameNumber;
820}
#define MM_GUARDPAGE
Definition: miarm.h:57
FORCEINLINE ULONG_PTR MiDetermineUserGlobalPteMask(IN PVOID PointerPte)
Definition: miarm.h:736
#define MM_PROTECT_ACCESS
Definition: miarm.h:51
const ULONG_PTR MmProtectToPteMask[32]
Definition: page.c:22

Referenced by MiCompleteProtoPteFault(), MiResolveDemandZeroFault(), MiResolvePageFileFault(), MiResolveProtoPteFault(), MmArmAccessFault(), and MmCreateVirtualMappingUnsafeEx().

◆ MI_MAKE_HARDWARE_PTE_KERNEL()

FORCEINLINE VOID MI_MAKE_HARDWARE_PTE_KERNEL ( IN PMMPTE  NewPte,
IN PMMPTE  MappingPte,
IN ULONG_PTR  ProtectionMask,
IN PFN_NUMBER  PageFrameNumber 
)

Definition at line 773 of file miarm.h.

777{
778 /* Only valid for kernel, non-session PTEs */
779 ASSERT(MappingPte > MiHighestUserPte);
780 ASSERT(!MI_IS_SESSION_PTE(MappingPte));
781 ASSERT((MappingPte < (PMMPTE)PDE_BASE) || (MappingPte > (PMMPTE)PDE_TOP));
782
783 /* Check that we are not setting valid a page that should not be */
784 ASSERT(ProtectionMask & MM_PROTECT_ACCESS);
785 ASSERT((ProtectionMask & MM_GUARDPAGE) == 0);
786
787 /* Start fresh */
788 NewPte->u.Long = 0;
789
790 /* Set the protection and page */
791 NewPte->u.Hard.PageFrameNumber = PageFrameNumber;
792 NewPte->u.Long |= MmProtectToPteMask[ProtectionMask];
793
794 /* Make this valid & global */
795#ifdef _GLOBAL_PAGES_ARE_AWESOME_
797 NewPte->u.Hard.Global = 1;
798#endif
799 NewPte->u.Hard.Valid = 1;
800}
#define PDE_BASE
Definition: winldr.c:21
PMMPTE MiHighestUserPte
Definition: mminit.c:233
#define MI_IS_SESSION_PTE(Pte)
Definition: miarm.h:174
#define KF_GLOBAL_PAGE
Definition: ketypes.h:35
#define PDE_TOP
Definition: mm.h:168
ULONG KeFeatureBits
Definition: krnlinit.c:22

Referenced by MiArchCreateProcessAddressSpace(), MmChangeKernelResourceSectionProtection(), MmCreateKernelStack(), MmGrowKernelStackEx(), and MmInitSystem().

◆ MI_MAKE_HARDWARE_PTE_USER()

FORCEINLINE VOID MI_MAKE_HARDWARE_PTE_USER ( IN PMMPTE  NewPte,
IN PMMPTE  MappingPte,
IN ULONG_PTR  ProtectionMask,
IN PFN_NUMBER  PageFrameNumber 
)

Definition at line 827 of file miarm.h.

831{
832 /* Only valid for kernel, non-session PTEs */
833 ASSERT(MappingPte <= MiHighestUserPte);
834
835 /* Start fresh */
836 NewPte->u.Long = 0;
837
838 /* Check that we are not setting valid a page that should not be */
839 ASSERT(ProtectionMask & MM_PROTECT_ACCESS);
840 ASSERT((ProtectionMask & MM_GUARDPAGE) == 0);
841
842 NewPte->u.Hard.Valid = TRUE;
843 NewPte->u.Hard.Owner = TRUE;
844 NewPte->u.Hard.PageFrameNumber = PageFrameNumber;
845 NewPte->u.Long |= MmProtectToPteMask[ProtectionMask];
846}

Referenced by MiCompleteProtoPteFault(), MiFlushTbAndCapture(), MiMapLockedPagesInUserSpace(), MiResolveDemandZeroFault(), MiResolveProtoPteFault(), and MmArmAccessFault().

◆ MI_MAKE_PROTOTYPE_PTE()

FORCEINLINE VOID MI_MAKE_PROTOTYPE_PTE ( IN PMMPTE  NewPte,
IN PMMPTE  PointerPte 
)

Definition at line 854 of file miarm.h.

856{
858
859 /* Mark this as a prototype */
860 NewPte->u.Long = 0;
861 NewPte->u.Proto.Prototype = 1;
862
863 /*
864 * Prototype PTEs are only valid in paged pool by design, this little trick
865 * lets us only use 30 bits for the address of the PTE, as long as the area
866 * stays 1024MB At most.
867 */
869
870 /*
871 * 7 bits go in the "low" (but we assume the bottom 2 are zero)
872 * and the other 21 bits go in the "high"
873 */
874 NewPte->u.Proto.ProtoAddressLow = (Offset & 0x1FC) >> 2;
875 NewPte->u.Proto.ProtoAddressHigh = (Offset & 0x3FFFFE00) >> 9;
876}
#define ULONG_PTR
Definition: config.h:101
PVOID MmPagedPoolStart
Definition: miarm.h:574
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
uint32_t ULONG_PTR
Definition: typedefs.h:65

◆ MI_MAKE_SUBSECTION_PTE()

FORCEINLINE VOID MI_MAKE_SUBSECTION_PTE ( IN PMMPTE  NewPte,
IN PVOID  Segment 
)

Definition at line 883 of file miarm.h.

885{
887
888 /* Mark this as a prototype */
889 NewPte->u.Long = 0;
890 NewPte->u.Subsect.Prototype = 1;
891
892 /*
893 * Segments are only valid either in nonpaged pool. We store the 20 bit
894 * difference either from the top or bottom of nonpaged pool, giving a
895 * maximum of 128MB to each delta, meaning nonpaged pool cannot exceed
896 * 256MB.
897 */
898 if ((ULONG_PTR)Segment < ((ULONG_PTR)MmSubsectionBase + (128 * _1MB)))
899 {
901 NewPte->u.Subsect.WhichPool = PagedPool;
902 }
903 else
904 {
906 NewPte->u.Subsect.WhichPool = NonPagedPool;
907 }
908
909 /*
910 * 4 bits go in the "low" (but we assume the bottom 3 are zero)
911 * and the other 20 bits go in the "high"
912 */
913 NewPte->u.Subsect.SubsectionAddressLow = (Offset & 0x78) >> 3;
914 NewPte->u.Subsect.SubsectionAddressHigh = (Offset & 0xFFFFF80) >> 7;
915}
ULONG_PTR MmSubsectionBase
Definition: section.c:196
PVOID MmNonPagedPoolEnd
Definition: mminit.c:99
#define _1MB
Definition: miarm.h:19
_Inout_ PVOID Segment
Definition: exfuncs.h:1101

◆ MI_MAKE_TRANSITION_PTE()

FORCEINLINE VOID MI_MAKE_TRANSITION_PTE ( _Out_ PMMPTE  NewPte,
_In_ PFN_NUMBER  Page,
_In_ ULONG  Protection 
)

Definition at line 929 of file miarm.h.

932{
933 NewPte->u.Long = 0;
934 NewPte->u.Trans.Transition = 1;
935 NewPte->u.Trans.Protection = Protection;
936 NewPte->u.Trans.PageFrameNumber = Page;
937}
_In_ PVOID _Out_opt_ BOOLEAN _Out_opt_ PPFN_NUMBER Page
Definition: mm.h:1306

Referenced by MiResolvePageFileFault(), and TrimWsList().

◆ MI_PFN_ELEMENT()

◆ MI_UPDATE_VALID_PTE()

FORCEINLINE VOID MI_UPDATE_VALID_PTE ( IN PMMPTE  PointerPte,
IN MMPTE  TempPte 
)

Definition at line 977 of file miarm.h.

979{
980 /* Write the valid PTE */
981 ASSERT(PointerPte->u.Hard.Valid == 1);
982 ASSERT(TempPte.u.Hard.Valid == 1);
983 ASSERT(PointerPte->u.Hard.PageFrameNumber == TempPte.u.Hard.PageFrameNumber);
984 *PointerPte = TempPte;
985}
HARDWARE_PTE_ARMV6 TempPte
Definition: winldr.c:76
ULONG PageFrameNumber
Definition: mmtypes.h:109

Referenced by MiFlushTbAndCapture(), MiSetSystemCodeProtection(), MmArmAccessFault(), and MmChangeKernelResourceSectionProtection().

◆ MI_WRITE_INVALID_PDE()

FORCEINLINE VOID MI_WRITE_INVALID_PDE ( IN PMMPDE  PointerPde,
IN MMPDE  InvalidPde 
)

Definition at line 1035 of file miarm.h.

1037{
1038 /* Write the invalid PDE */
1039 ASSERT(InvalidPde.u.Hard.Valid == 0);
1040 ASSERT(InvalidPde.u.Long != 0);
1041#ifdef _M_AMD64
1042 ASSERT(InvalidPde.u.Soft.Protection == MM_EXECUTE_READWRITE);
1043#endif
1044 *PointerPde = InvalidPde;
1045}
#define MM_EXECUTE_READWRITE
Definition: miarm.h:49

Referenced by MmArmAccessFault().

◆ MI_WRITE_INVALID_PTE()

FORCEINLINE VOID MI_WRITE_INVALID_PTE ( IN PMMPTE  PointerPte,
IN MMPTE  InvalidPte 
)

◆ MI_WRITE_VALID_PDE()

FORCEINLINE VOID MI_WRITE_VALID_PDE ( IN PMMPDE  PointerPde,
IN MMPDE  TempPde 
)

Definition at line 1018 of file miarm.h.

1020{
1021 /* Write the valid PDE */
1022 ASSERT(PointerPde->u.Hard.Valid == 0);
1023#ifdef _M_AMD64
1024 ASSERT(PointerPde->u.Hard.NoExecute == 0);
1025#endif
1026 ASSERT(TempPde.u.Hard.Valid == 1);
1027 *PointerPde = TempPde;
1028}
HARDWARE_PDE_ARMV6 TempPde
Definition: winldr.c:78

Referenced by MiAllocatePoolPages(), MiBuildPagedPool(), MiFillSystemPageDirectory(), MiInitializeAndChargePfn(), MiRemoveMappedPtes(), MiSessionCommitPageTables(), MiSessionCreateInternal(), and MiSessionInitializeWorkingSetList().

◆ MI_WRITE_VALID_PTE()

◆ MI_WS_OWNER()

FORCEINLINE BOOLEAN MI_WS_OWNER ( IN PEPROCESS  Process)

Definition at line 1077 of file miarm.h.

1078{
1079 /* Check if this process is the owner, and that the thread owns the WS */
1080 if (PsGetCurrentThread()->OwnsProcessWorkingSetExclusive == 0)
1081 {
1082 DPRINT("Thread: %p is not an owner\n", PsGetCurrentThread());
1083 }
1084 if (KeGetCurrentThread()->ApcState.Process != &Process->Pcb)
1085 {
1086 DPRINT("Current thread %p is attached to another process %p\n", PsGetCurrentThread(), Process);
1087 }
1088 return ((KeGetCurrentThread()->ApcState.Process == &Process->Pcb) &&
1089 ((PsGetCurrentThread()->OwnsProcessWorkingSetExclusive) ||
1090 (PsGetCurrentThread()->OwnsProcessWorkingSetShared)));
1091}
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
#define KeGetCurrentThread
Definition: hal.h:55
_Out_ PKAPC_STATE ApcState
Definition: mm.h:1765

Referenced by MiUnlockProcessWorkingSet(), MiUnlockProcessWorkingSetForFault(), MiUnlockProcessWorkingSetShared(), and MiUnlockProcessWorkingSetUnsafe().

◆ MiAcquireExpansionLock()

FORCEINLINE KIRQL MiAcquireExpansionLock ( VOID  )

Definition at line 1531 of file miarm.h.

1532{
1533 KIRQL OldIrql;
1534
1539 return OldIrql;
1540}
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define APC_LEVEL
Definition: env_spec_w32.h:695
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
PETHREAD MiExpansionLockOwner
Definition: session.c:33
KSPIN_LOCK MmExpansionLock
Definition: session.c:32
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778

Referenced by MiArchCreateProcessAddressSpace(), MiDereferenceSessionFinal(), MiSessionAddProcess(), MiSessionInitializeWorkingSetList(), MiSessionLeader(), MiSessionRemoveProcess(), MmDeleteProcessAddressSpace(), MmGetSessionById(), and MmWorkingSetManager().

◆ MiAllocatePagesForMdl()

PMDL NTAPI MiAllocatePagesForMdl ( IN PHYSICAL_ADDRESS  LowAddress,
IN PHYSICAL_ADDRESS  HighAddress,
IN PHYSICAL_ADDRESS  SkipBytes,
IN SIZE_T  TotalBytes,
IN MI_PFN_CACHE_ATTRIBUTE  CacheAttribute,
IN ULONG  Flags 
)

Definition at line 182 of file freelist.c.

188{
189 PMDL Mdl;
190 PFN_NUMBER PageCount, LowPage, HighPage, SkipPages, PagesFound = 0, Page;
191 PPFN_NUMBER MdlPage, LastMdlPage;
193 PMMPFN Pfn1;
194 INT LookForZeroedPages;
196 DPRINT1("ARM3-DEBUG: Being called with %I64x %I64x %I64x %lx %d %lu\n", LowAddress, HighAddress, SkipBytes, TotalBytes, CacheAttribute, MdlFlags);
197
198 //
199 // Convert the low address into a PFN
200 //
201 LowPage = (PFN_NUMBER)(LowAddress.QuadPart >> PAGE_SHIFT);
202
203 //
204 // Convert, and normalize, the high address into a PFN
205 //
206 HighPage = (PFN_NUMBER)(HighAddress.QuadPart >> PAGE_SHIFT);
207 if (HighPage > MmHighestPhysicalPage) HighPage = MmHighestPhysicalPage;
208
209 //
210 // Validate skipbytes and convert them into pages
211 //
212 if (BYTE_OFFSET(SkipBytes.LowPart)) return NULL;
213 SkipPages = (PFN_NUMBER)(SkipBytes.QuadPart >> PAGE_SHIFT);
214
215 /* This isn't supported at all */
216 if (SkipPages) DPRINT1("WARNING: Caller requesting SkipBytes, MDL might be mismatched\n");
217
218 //
219 // Now compute the number of pages the MDL will cover
220 //
222 do
223 {
224 //
225 // Try creating an MDL for these many pages
226 //
227 Mdl = MmCreateMdl(NULL, NULL, PageCount << PAGE_SHIFT);
228 if (Mdl) break;
229
230 //
231 // This function is not required to return the amount of pages requested
232 // In fact, it can return as little as 1 page, and callers are supposed
233 // to deal with this scenario. So re-attempt the allocation with less
234 // pages than before, and see if it worked this time.
235 //
236 PageCount -= (PageCount >> 4);
237 } while (PageCount);
238
239 //
240 // Wow, not even a single page was around!
241 //
242 if (!Mdl) return NULL;
243
244 //
245 // This is where the page array starts....
246 //
247 MdlPage = (PPFN_NUMBER)(Mdl + 1);
248
249 //
250 // Lock the PFN database
251 //
252 OldIrql = MiAcquirePfnLock();
253
254 //
255 // Are we looking for any pages, without discriminating?
256 //
257 if ((LowPage == 0) && (HighPage == MmHighestPhysicalPage))
258 {
259 //
260 // Well then, let's go shopping
261 //
262 while (PagesFound < PageCount)
263 {
264 /* Grab a page */
266 MI_SET_PROCESS2("Kernel");
267
268 /* FIXME: This check should be smarter */
269 Page = 0;
270 if (MmAvailablePages != 0)
272
273 if (Page == 0)
274 {
275 /* This is not good... hopefully we have at least SOME pages */
276 ASSERT(PagesFound);
277 break;
278 }
279
280 /* Grab the page entry for it */
281 Pfn1 = MiGetPfnEntry(Page);
282
283 //
284 // Make sure it's really free
285 //
286 ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
287
288 /* Now setup the page and mark it */
289 Pfn1->u3.e2.ReferenceCount = 1;
290 Pfn1->u2.ShareCount = 1;
291 MI_SET_PFN_DELETED(Pfn1);
292 Pfn1->u4.PteFrame = 0x1FFEDCB;
293 Pfn1->u3.e1.StartOfAllocation = 1;
294 Pfn1->u3.e1.EndOfAllocation = 1;
295 Pfn1->u4.VerifierAllocation = 0;
296
297 //
298 // Save it into the MDL
299 //
300 *MdlPage++ = MiGetPfnEntryIndex(Pfn1);
301 PagesFound++;
302 }
303 }
304 else
305 {
306 //
307 // You want specific range of pages. We'll do this in two runs
308 //
309 for (LookForZeroedPages = 1; LookForZeroedPages >= 0; LookForZeroedPages--)
310 {
311 //
312 // Scan the range you specified
313 //
314 for (Page = LowPage; Page < HighPage; Page++)
315 {
316 //
317 // Get the PFN entry for this page
318 //
319 Pfn1 = MiGetPfnEntry(Page);
320 ASSERT(Pfn1);
321
322 //
323 // Make sure it's free and if this is our first pass, zeroed
324 //
325 if (MiIsPfnInUse(Pfn1)) continue;
326 if ((Pfn1->u3.e1.PageLocation == ZeroedPageList) != LookForZeroedPages) continue;
327
328 /* Remove the page from the free or zero list */
329 ASSERT(Pfn1->u3.e1.ReadInProgress == 0);
331 MI_SET_PROCESS2("Kernel");
333
334 //
335 // Sanity checks
336 //
337 ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
338
339 //
340 // Now setup the page and mark it
341 //
342 Pfn1->u3.e2.ReferenceCount = 1;
343 Pfn1->u2.ShareCount = 1;
344 MI_SET_PFN_DELETED(Pfn1);
345 Pfn1->u4.PteFrame = 0x1FFEDCB;
346 Pfn1->u3.e1.StartOfAllocation = 1;
347 Pfn1->u3.e1.EndOfAllocation = 1;
348 Pfn1->u4.VerifierAllocation = 0;
349
350 //
351 // Save this page into the MDL
352 //
353 *MdlPage++ = Page;
354 if (++PagesFound == PageCount) break;
355 }
356
357 //
358 // If the first pass was enough, don't keep going, otherwise, go again
359 //
360 if (PagesFound == PageCount) break;
361 }
362 }
363
364 //
365 // Now release the PFN count
366 //
367 MiReleasePfnLock(OldIrql);
368
369 //
370 // We might've found less pages, but not more ;-)
371 //
372 if (PagesFound != PageCount) ASSERT(PagesFound < PageCount);
373 if (!PagesFound)
374 {
375 //
376 // If we didn' tfind any pages at all, fail
377 //
378 DPRINT1("NO MDL PAGES!\n");
380 return NULL;
381 }
382
383 //
384 // Write out how many pages we found
385 //
386 Mdl->ByteCount = (ULONG)(PagesFound << PAGE_SHIFT);
387
388 //
389 // Terminate the MDL array if there's certain missing pages
390 //
391 if (PagesFound != PageCount) *MdlPage = LIST_HEAD;
392
393 //
394 // Now go back and loop over all the MDL pages
395 //
396 MdlPage = (PPFN_NUMBER)(Mdl + 1);
397 LastMdlPage = MdlPage + PagesFound;
398 while (MdlPage < LastMdlPage)
399 {
400 //
401 // Check if we've reached the end
402 //
403 Page = *MdlPage++;
404 if (Page == LIST_HEAD) break;
405
406 //
407 // Get the PFN entry for the page and check if we should zero it out
408 //
409 Pfn1 = MiGetPfnEntry(Page);
410 ASSERT(Pfn1);
413 }
414
415 //
416 // We're done, mark the pages as locked
417 //
418 Mdl->Process = NULL;
419 Mdl->MdlFlags |= MDL_PAGES_LOCKED;
420 return Mdl;
421}
#define DPRINT1
Definition: precomp.h:8
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
BOOLEAN NTAPI MiIsPfnInUse(IN PMMPFN Pfn1)
Definition: freelist.c:174
PFN_NUMBER MmAvailablePages
Definition: freelist.c:26
PFN_NUMBER MmHighestPhysicalPage
Definition: meminit.c:31
VOID NTAPI MiUnlinkFreeOrZeroedPage(IN PMMPFN Entry)
Definition: pfnlist.c:137
#define MI_SET_PFN_DELETED(x)
Definition: miarm.h:194
PFN_NUMBER NTAPI MiRemoveAnyPage(IN ULONG Color)
Definition: pfnlist.c:477
PMDL NTAPI MmCreateMdl(IN PMDL Mdl, IN PVOID Base, IN SIZE_T Length)
Definition: mdlsup.c:378
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
@ ZeroedPageList
Definition: mmtypes.h:153
@ ActiveAndValid
Definition: mmtypes.h:159
VOID NTAPI MiZeroPhysicalPage(IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:122
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:1047
#define MI_SET_PROCESS2(x)
Definition: mm.h:319
@ MI_USAGE_MDL
Definition: mm.h:339
FORCEINLINE PFN_NUMBER MiGetPfnEntryIndex(IN PMMPFN Pfn1)
Definition: mm.h:1067
#define MI_SET_USAGE(x)
Definition: mm.h:317
ULONG * PPFN_NUMBER
Definition: ke.h:9
ULONG PFN_NUMBER
Definition: ke.h:9
USHORT ReadInProgress
Definition: mm.h:361
USHORT PageLocation
Definition: mm.h:365
Definition: mm.h:374
union _MMPFN::@1798 u2
union _MMPFN::@1802 u4
MMPFNENTRY e1
Definition: mm.h:397
ULONG_PTR VerifierAllocation
Definition: mm.h:420
ULONG_PTR ShareCount
Definition: mm.h:390
union _MMPFN::@1799 u3
ULONG_PTR PteFrame
Definition: mm.h:418
struct _MMPFN::@1799::@1805 e2
#define LIST_HEAD(name, type)
Definition: queue.h:167
#define TAG_MDL
Definition: tag.h:89
int32_t INT
Definition: typedefs.h:58
LONGLONG QuadPart
Definition: typedefs.h:114
ULONG LowPart
Definition: typedefs.h:106
_In_ WDFDEVICE _In_ PVOID _In_opt_ PMDL Mdl
_Must_inspect_result_ _In_ PHYSICAL_ADDRESS HighAddress
Definition: mmfuncs.h:226
#define BYTE_OFFSET(Va)
#define ADDRESS_AND_SIZE_TO_SPAN_PAGES(_Va, _Size)
_Must_inspect_result_ _In_ PHYSICAL_ADDRESS _In_ PHYSICAL_ADDRESS SkipBytes
Definition: mmfuncs.h:227
_Must_inspect_result_ _In_ PHYSICAL_ADDRESS _In_ PHYSICAL_ADDRESS _In_ SIZE_T TotalBytes
Definition: mmfuncs.h:228
#define MDL_PAGES_LOCKED
Definition: mmtypes.h:19

Referenced by MmAllocateNonCachedMemory(), MmAllocatePagesForMdl(), and MmAllocatePagesForMdlEx().

◆ MiCheckForConflictingNode()

TABLE_SEARCH_RESULT NTAPI MiCheckForConflictingNode ( IN ULONG_PTR  StartVpn,
IN ULONG_PTR  EndVpn,
IN PMM_AVL_TABLE  Table,
OUT PMMADDRESS_NODE NodeOrParent 
)

Definition at line 150 of file vadnode.c.

154{
155 PMMADDRESS_NODE ParentNode, CurrentNode;
156
158
159 /* If the tree is empty, there is no conflict */
160 if (Table->NumberGenericTableElements == 0) return TableEmptyTree;
161
162 /* Start looping from the root node */
163 CurrentNode = RtlRightChildAvl(&Table->BalancedRoot);
164 ASSERT(CurrentNode != NULL);
165 while (CurrentNode)
166 {
167 ParentNode = CurrentNode;
168
169 /* This address comes after */
170 if (StartVpn > CurrentNode->EndingVpn)
171 {
172 /* Keep searching on the right */
173 CurrentNode = RtlRightChildAvl(CurrentNode);
174 }
175 else if (EndVpn < CurrentNode->StartingVpn)
176 {
177 /* This address ends before the node starts, search on the left */
178 CurrentNode = RtlLeftChildAvl(CurrentNode);
179 }
180 else
181 {
182 /* This address is part of this node, return it */
183 *NodeOrParent = ParentNode;
184 return TableFoundNode;
185 }
186 }
187
188 /* There is no more child, save the current node as parent */
189 *NodeOrParent = ParentNode;
190 if (StartVpn > ParentNode->EndingVpn)
191 {
192 return TableInsertAsRight;
193 }
194 else
195 {
196 return TableInsertAsLeft;
197 }
198}
ASMGENDATA Table[]
Definition: genincdata.c:61
#define RtlRightChildAvl
Definition: miavl.h:45
#define RtlLeftChildAvl
Definition: miavl.h:46
ULONG_PTR EndingVpn
Definition: mmtypes.h:654
#define ASSERT_LOCKED_FOR_READ(Table)
Definition: vadnode.c:109

Referenced by MiInsertVadEx(), MiMapLockedPagesInUserSpace(), MiProtectVirtualMemory(), MmLocateMemoryAreaByAddress(), MmLocateMemoryAreaByRegion(), and NtAllocateVirtualMemory().

◆ MiCheckForContiguousMemory()

PVOID NTAPI MiCheckForContiguousMemory ( IN PVOID  BaseAddress,
IN PFN_NUMBER  BaseAddressPages,
IN PFN_NUMBER  SizeInPages,
IN PFN_NUMBER  LowestPfn,
IN PFN_NUMBER  HighestPfn,
IN PFN_NUMBER  BoundaryPfn,
IN MI_PFN_CACHE_ATTRIBUTE  CacheAttribute 
)

Definition at line 214 of file contmem.c.

221{
222 PMMPTE StartPte, EndPte;
223 PFN_NUMBER PreviousPage = 0, Page, HighPage, BoundaryMask, Pages = 0;
224
225 //
226 // Okay, first of all check if the PFNs match our restrictions
227 //
228 if (LowestPfn > HighestPfn) return NULL;
229 if (LowestPfn + SizeInPages <= LowestPfn) return NULL;
230 if (LowestPfn + SizeInPages - 1 > HighestPfn) return NULL;
231 if (BaseAddressPages < SizeInPages) return NULL;
232
233 //
234 // This is the last page we need to get to and the boundary requested
235 //
236 HighPage = HighestPfn + 1 - SizeInPages;
237 BoundaryMask = ~(BoundaryPfn - 1);
238
239 //
240 // And here's the PTEs for this allocation. Let's go scan them.
241 //
242 StartPte = MiAddressToPte(BaseAddress);
243 EndPte = StartPte + BaseAddressPages;
244 while (StartPte < EndPte)
245 {
246 //
247 // Get this PTE's page number
248 //
249 ASSERT (StartPte->u.Hard.Valid == 1);
250 Page = PFN_FROM_PTE(StartPte);
251
252 //
253 // Is this the beginning of our adventure?
254 //
255 if (!Pages)
256 {
257 //
258 // Check if this PFN is within our range
259 //
260 if ((Page >= LowestPfn) && (Page <= HighPage))
261 {
262 //
263 // It is! Do you care about boundary (alignment)?
264 //
265 if (!(BoundaryPfn) ||
266 (!((Page ^ (Page + SizeInPages - 1)) & BoundaryMask)))
267 {
268 //
269 // You don't care, or you do care but we deliver
270 //
271 Pages++;
272 }
273 }
274
275 //
276 // Have we found all the pages we need by now?
277 // Incidently, this means you only wanted one page
278 //
279 if (Pages == SizeInPages)
280 {
281 //
282 // Mission complete
283 //
284 return MiPteToAddress(StartPte);
285 }
286 }
287 else
288 {
289 //
290 // Have we found a page that doesn't seem to be contiguous?
291 //
292 if (Page != (PreviousPage + 1))
293 {
294 //
295 // Ah crap, we have to start over
296 //
297 Pages = 0;
298 continue;
299 }
300
301 //
302 // Otherwise, we're still in the game. Do we have all our pages?
303 //
304 if (++Pages == SizeInPages)
305 {
306 //
307 // We do! This entire range was contiguous, so we'll return it!
308 //
309 return MiPteToAddress(StartPte - Pages + 1);
310 }
311 }
312
313 //
314 // Try with the next PTE, remember this PFN
315 //
316 PreviousPage = Page;
317 StartPte++;
318 continue;
319 }
320
321 //
322 // All good returns are within the loop...
323 //
324 return NULL;
325}
#define MiAddressToPte(x)
Definition: mmx86.c:19
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
#define PFN_FROM_PTE(v)
Definition: mm.h:92

Referenced by MiAllocateContiguousMemory().

◆ MiCheckPdeForPagedPool()

NTSTATUS FASTCALL MiCheckPdeForPagedPool ( IN PVOID  Address)

Definition at line 479 of file pagfault.c.

480{
482}
#define STATUS_ACCESS_VIOLATION
Definition: ntstatus.h:242

Referenced by MiDeletePte(), MiInitializePfn(), MiInitializePfnAndMakePteValid(), and MmArmAccessFault().

◆ MiCheckSecuredVad()

NTSTATUS NTAPI MiCheckSecuredVad ( IN PMMVAD  Vad,
IN PVOID  Base,
IN SIZE_T  Size,
IN ULONG  ProtectionMask 
)

Definition at line 903 of file vadnode.c.

907{
908 ULONG_PTR StartAddress, EndAddress;
909
910 /* Compute start and end address */
911 StartAddress = (ULONG_PTR)Base;
912 EndAddress = StartAddress + Size - 1;
913
914 /* Are we deleting/unmapping, or changing? */
915 if (ProtectionMask < MM_DELETE_CHECK)
916 {
917 /* Changing... are we allowed to do so? */
918 if ((Vad->u.VadFlags.NoChange == 1) &&
919 (Vad->u2.VadFlags2.SecNoChange == 1) &&
920 (Vad->u.VadFlags.Protection != ProtectionMask))
921 {
922 /* Nope, bail out */
923 DPRINT1("Trying to mess with a no-change VAD!\n");
925 }
926 }
927 else
928 {
929 /* This is allowed */
930 ProtectionMask = 0;
931 }
932
933 /* ARM3 doesn't support this yet */
934 ASSERT(Vad->u2.VadFlags2.MultipleSecured == 0);
935
936 /* Is this a one-secured VAD, like a TEB or PEB? */
937 if (Vad->u2.VadFlags2.OneSecured)
938 {
939 /* Is this allocation being described by the VAD? */
940 if ((StartAddress <= ((PMMVAD_LONG)Vad)->u3.Secured.EndVpn) &&
941 (EndAddress >= ((PMMVAD_LONG)Vad)->u3.Secured.StartVpn))
942 {
943 /* Guard page? */
944 if (ProtectionMask & MM_DECOMMIT)
945 {
946 DPRINT1("Not allowed to change protection on guard page!\n");
948 }
949
950 /* ARM3 doesn't have read-only VADs yet */
951 ASSERT(Vad->u2.VadFlags2.ReadOnly == 0);
952
953 /* Check if read-write protections are allowed */
954 if (MmReadWrite[ProtectionMask] < MM_READ_WRITE_ALLOWED)
955 {
956 DPRINT1("Invalid protection mask for RW access!\n");
958 }
959 }
960 }
961
962 /* All good, allow the change */
963 return STATUS_SUCCESS;
964}
#define MM_READ_WRITE_ALLOWED
Definition: miarm.h:253
#define MM_DELETE_CHECK
Definition: miarm.h:256
#define MM_DECOMMIT
Definition: miarm.h:64
static BYTE u3[]
Definition: msg.c:580
_In_opt_ ULONG Base
Definition: rtlfuncs.h:2451
#define STATUS_INVALID_PAGE_PROTECTION
Definition: ntstatus.h:305
#define STATUS_SUCCESS
Definition: shellext.h:65
ULONG ReadOnly
Definition: mmtypes.h:710
union _MMVAD_LONG::@2619 u2
MMVAD_FLAGS2 VadFlags2
Definition: mmtypes.h:771
CHAR MmReadWrite[32]
Definition: vadnode.c:25
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533

Referenced by MiUnmapViewOfSection(), and NtAllocateVirtualMemory().

◆ MiComputeColorInformation()

VOID NTAPI MiComputeColorInformation ( VOID  )

Definition at line 508 of file mminit.c.

509{
510 ULONG L2Associativity;
511
512 /* Check if no setting was provided already */
514 {
515 /* Get L2 cache information */
516 L2Associativity = KeGetPcr()->SecondLevelCacheAssociativity;
517
518 /* The number of colors is the number of cache bytes by set/way */
519 MmSecondaryColors = KeGetPcr()->SecondLevelCacheSize;
520 if (L2Associativity) MmSecondaryColors /= L2Associativity;
521 }
522
523 /* Now convert cache bytes into pages */
526 {
527 /* If there was no cache data from the KPCR, use the default colors */
529 }
530 else
531 {
532 /* Otherwise, make sure there aren't too many colors */
534 {
535 /* Set the maximum */
537 }
538
539 /* Make sure there aren't too little colors */
541 {
542 /* Set the default */
544 }
545
546 /* Finally make sure the colors are a power of two */
548 {
549 /* Set the default */
551 }
552 }
553
554 /* Compute the mask and store it */
556 KeGetCurrentPrcb()->SecondaryColorMask = MmSecondaryColorMask;
557}
ULONG MmSecondaryColorMask
Definition: mminit.c:257
ULONG MmSecondaryColors
Definition: mminit.c:256
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1161
#define KeGetPcr()
Definition: ketypes.h:81
#define MI_MAX_SECONDARY_COLORS
Definition: mm.h:78
#define MI_SECONDARY_COLORS
Definition: mm.h:77
#define MI_MIN_SECONDARY_COLORS
Definition: mm.h:76

Referenced by MmArmInitSystem().

◆ MiConvertSharedWorkingSetLockToExclusive()

FORCEINLINE BOOLEAN MiConvertSharedWorkingSetLockToExclusive ( _In_ PETHREAD  Thread,
_In_ PMMSUPPORT  Vm 
)

Definition at line 1428 of file miarm.h.

1431{
1432 /* Sanity check: No exclusive lock. */
1436
1437 /* And it should have one and only one shared lock */
1439
1440 /* Try. */
1441 if (!ExConvertPushLockSharedToExclusive(&Vm->WorkingSetMutex))
1442 return FALSE;
1443
1444 if (Vm == &MmSystemCacheWs)
1445 {
1449 }
1450 else if (Vm->Flags.SessionSpace)
1451 {
1455 }
1456 else
1457 {
1461 }
1462
1463 return TRUE;
1464}
#define FALSE
Definition: types.h:117
FORCEINLINE BOOLEAN ExConvertPushLockSharedToExclusive(IN PEX_PUSH_LOCK PushLock)
Definition: ex.h:1139
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
ULONG OwnsSessionWorkingSetExclusive
Definition: pstypes.h:1225
ULONG OwnsSessionWorkingSetShared
Definition: pstypes.h:1226
ULONG OwnsSystemWorkingSetShared
Definition: pstypes.h:1224
ULONG OwnsProcessWorkingSetShared
Definition: pstypes.h:1222
ULONG OwnsProcessWorkingSetExclusive
Definition: pstypes.h:1221
ULONG OwnsSystemWorkingSetExclusive
Definition: pstypes.h:1223

Referenced by MmWorkingSetManager().

◆ MiDecrementPageTableReferences()

FORCEINLINE USHORT MiDecrementPageTableReferences ( IN PVOID  Address)

Definition at line 2492 of file miarm.h.

2493{
2494 PMMPDE PointerPde = MiAddressToPde(Address);
2495 PMMPFN Pfn;
2496
2497 /* We should not tinker with this one. */
2498 ASSERT(PointerPde != (PMMPDE)PXE_SELFMAP);
2499
2500 DPRINT("Decrementing %p from %p\n", PointerPde, _ReturnAddress());
2501
2502 /* Make sure we're locked */
2503 ASSERT(PsGetCurrentThread()->OwnsProcessWorkingSetExclusive);
2504
2505 /* If we're decreasing refcount, then it must be valid! */
2506 ASSERT(PointerPde->u.Hard.Valid == 1);
2507
2508 /* This lies on the PFN */
2509 Pfn = MiGetPfnEntry(PFN_FROM_PDE(PointerPde));
2510
2513
2515
2517}
#define _ReturnAddress()
Definition: intrin_arm.h:35
#define PFN_FROM_PDE(v)
Definition: mm.h:93
#define PTE_PER_PAGE
Definition: mm.h:20
#define PXE_SELFMAP
MMPTE OriginalPte
Definition: mm.h:407
ULONG64 UsedPageTableEntries
Definition: mmtypes.h:91
MMPTE_SOFTWARE Soft
Definition: mmtypes.h:219

Referenced by _Success_(), MiDeletePde(), MiDeleteVirtualAddresses(), MiUnmapLockedPagesInUserSpace(), and MmDeletePageFileMapping().

◆ MiDecrementReferenceCount()

VOID NTAPI MiDecrementReferenceCount ( IN PMMPFN  Pfn1,
IN PFN_NUMBER  PageFrameIndex 
)

Definition at line 1236 of file pfnlist.c.

1238{
1239 /* PFN lock must be held */
1241
1242 /* Handle RosMm PFNs here, too (in case they got locked/unlocked by ARM3) */
1243 if (MI_IS_ROS_PFN(Pfn1))
1244 {
1245 MmDereferencePage(PageFrameIndex);
1246 return;
1247 }
1248
1249 /* Sanity checks on the page */
1250 if (PageFrameIndex > MmHighestPhysicalPage ||
1251 Pfn1 != MI_PFN_ELEMENT(PageFrameIndex) ||
1252 Pfn1->u3.e2.ReferenceCount == 0 ||
1253 Pfn1->u3.e2.ReferenceCount >= 2500)
1254 {
1255 DPRINT1("PageFrameIndex=0x%lx, MmHighestPhysicalPage=0x%lx\n", PageFrameIndex, MmHighestPhysicalPage);
1256 DPRINT1("Pfn1=%p, Element=%p, RefCount=%u\n", Pfn1, MI_PFN_ELEMENT(PageFrameIndex), Pfn1->u3.e2.ReferenceCount);
1257 ASSERT(PageFrameIndex <= MmHighestPhysicalPage);
1258 ASSERT(Pfn1 == MI_PFN_ELEMENT(PageFrameIndex));
1259 ASSERT(Pfn1->u3.e2.ReferenceCount != 0);
1260 ASSERT(Pfn1->u3.e2.ReferenceCount < 2500);
1261 }
1262
1263 /* Dereference the page, bail out if it's still alive */
1264 InterlockedDecrement16((PSHORT)&Pfn1->u3.e2.ReferenceCount);
1265 if (Pfn1->u3.e2.ReferenceCount) return;
1266
1267 /* Nobody should still have reference to this page */
1268 if (Pfn1->u2.ShareCount != 0)
1269 {
1270 /* Otherwise something's really wrong */
1271 KeBugCheckEx(PFN_LIST_CORRUPT, 7, PageFrameIndex, Pfn1->u2.ShareCount, 0);
1272 }
1273
1274 /* And it should be lying on some page list */
1275 ASSERT(Pfn1->u3.e1.PageLocation != ActiveAndValid);
1276
1277 /* Did someone set the delete flag? */
1278 if (MI_IS_PFN_DELETED(Pfn1))
1279 {
1280 /* Insert it into the free list, there's nothing left to do */
1281 MiInsertPageInFreeList(PageFrameIndex);
1282 return;
1283 }
1284
1285 /* Check to see which list this page should go into */
1286 if (Pfn1->u3.e1.Modified == 1)
1287 {
1288 /* Push it into the modified page list */
1290 }
1291 else
1292 {
1293 /* Otherwise, insert this page into the standby list */
1294 ASSERT(Pfn1->u3.e1.RemovalRequested == 0);
1295 MiInsertStandbyListAtFront(PageFrameIndex);
1296 }
1297}
#define InterlockedDecrement16
Definition: interlocked.h:139
#define MI_IS_ROS_PFN(x)
Definition: miarm.h:1103
#define MI_IS_PFN_DELETED(x)
Definition: miarm.h:195
FORCEINLINE PMMPFN MI_PFN_ELEMENT(IN PFN_NUMBER Pfn)
Definition: miarm.h:1574
#define MI_ASSERT_PFN_LOCK_HELD()
Definition: mm.h:1043
VOID NTAPI MiInsertPageInFreeList(IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:611
VOID NTAPI MmDereferencePage(PFN_NUMBER Pfn)
Definition: freelist.c:565
MMPFNLIST MmModifiedPageListHead
Definition: pfnlist.c:45
VOID NTAPI MiInsertPageInList(IN PMMPFNLIST ListHead, IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:779
VOID FASTCALL MiInsertStandbyListAtFront(IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:719
int16_t * PSHORT
Definition: typedefs.h:55

Referenced by MiDecrementShareCount(), MiDeletePte(), MiDereferencePfnAndDropLockCount(), and MmFreePagesFromMdl().

◆ MiDecrementShareCount()

VOID NTAPI MiDecrementShareCount ( IN PMMPFN  Pfn1,
IN PFN_NUMBER  PageFrameIndex 
)

Definition at line 1141 of file pfnlist.c.

1143{
1144 PMMPTE PointerPte;
1145 MMPTE TempPte;
1146
1147 ASSERT(PageFrameIndex > 0);
1148 ASSERT(MI_PFN_ELEMENT(PageFrameIndex) != NULL);
1149 ASSERT(Pfn1 == MI_PFN_ELEMENT(PageFrameIndex));
1150 ASSERT(MI_IS_ROS_PFN(Pfn1) == FALSE);
1151
1152 DPRINT("Decrementing %p from %p\n", Pfn1, _ReturnAddress());
1153
1154 /* Page must be in-use */
1155 if ((Pfn1->u3.e1.PageLocation != ActiveAndValid) &&
1156 (Pfn1->u3.e1.PageLocation != StandbyPageList))
1157 {
1158 /* Otherwise we have PFN corruption */
1159 KeBugCheckEx(PFN_LIST_CORRUPT,
1160 0x99,
1161 PageFrameIndex,
1162 Pfn1->u3.e1.PageLocation,
1163 0);
1164 }
1165
1166 /* Page should at least have one reference */
1167 ASSERT(Pfn1->u3.e2.ReferenceCount != 0);
1168
1169 /* Check if the share count is now 0 */
1170 ASSERT(Pfn1->u2.ShareCount < 0xF000000);
1171 if (!--Pfn1->u2.ShareCount)
1172 {
1173 /* Was this a prototype PTE? */
1174 if (Pfn1->u3.e1.PrototypePte)
1175 {
1176 /* Grab the PTE address and make sure it's in prototype pool */
1177 PointerPte = Pfn1->PteAddress;
1178 ASSERT((PointerPte >= (PMMPTE)MmPagedPoolStart) && (PointerPte <= (PMMPTE)MmPagedPoolEnd));
1179
1180 /* The PTE that backs it should also be valdi */
1181 PointerPte = MiAddressToPte(PointerPte);
1182 ASSERT(PointerPte->u.Hard.Valid == 1);
1183
1184 /* Get the original prototype PTE and turn it into a transition PTE */
1185 PointerPte = Pfn1->PteAddress;
1186 TempPte = *PointerPte;
1187 TempPte.u.Soft.Transition = 1;
1188 TempPte.u.Soft.Valid = 0;
1189 TempPte.u.Soft.Prototype = 0;
1190 TempPte.u.Soft.Protection = Pfn1->OriginalPte.u.Soft.Protection;
1191 MI_WRITE_INVALID_PTE(PointerPte, TempPte);
1192 DPRINT("Marking PTE: %p as transition (%p - %lx)\n", PointerPte, Pfn1, MiGetPfnEntryIndex(Pfn1));
1193 }
1194
1195 /* Put the page in transition */
1196 Pfn1->u3.e1.PageLocation = TransitionPage;
1197
1198 /* PFN lock must be held */
1200
1201 if (Pfn1->u3.e2.ReferenceCount == 1)
1202 {
1203 /* Is there still a PFN for this page? */
1204 if (MI_IS_PFN_DELETED(Pfn1))
1205 {
1206 /* Clear the last reference */
1207 Pfn1->u3.e2.ReferenceCount = 0;
1208 ASSERT(Pfn1->OriginalPte.u.Soft.Prototype == 0);
1209
1210 /* Mark the page temporarily as valid, we're going to make it free soon */
1211 Pfn1->u3.e1.PageLocation = ActiveAndValid;
1212
1213 /* Bring it back into the free list */
1214 MiInsertPageInFreeList(PageFrameIndex);
1215 }
1216 else
1217 {
1218 /* PFN not yet deleted, drop a ref count */
1219 MiDecrementReferenceCount(Pfn1, PageFrameIndex);
1220 }
1221 }
1222 else
1223 {
1224 /* Otherwise, just drop the reference count */
1225 InterlockedDecrement16((PSHORT)&Pfn1->u3.e2.ReferenceCount);
1226 }
1227 }
1228}
FORCEINLINE VOID MI_WRITE_INVALID_PTE(IN PMMPTE PointerPte, IN MMPTE InvalidPte)
Definition: miarm.h:992
@ TransitionPage
Definition: mmtypes.h:160
@ StandbyPageList
Definition: mmtypes.h:155
PVOID MmPagedPoolEnd
Definition: init.c:26
VOID NTAPI MiDecrementReferenceCount(IN PMMPFN Pfn1, IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:1236

Referenced by FreeWsleIndex(), MiDeletePte(), MiDeleteSystemPageableVm(), MiFreeContiguousMemory(), MiProcessValidPteList(), MiProtectVirtualMemory(), MiReleaseProcessReferenceToSessionDataPage(), MiRemoveMappedPtes(), MiUnmapLockedPagesInUserSpace(), MmDeleteKernelStack(), MmDeleteProcessAddressSpace(), MmFreeLoaderBlock(), MmFreeSpecialPool(), and TrimWsList().

◆ MiDeleteARM3Section()

VOID NTAPI MiDeleteARM3Section ( PVOID  ObjectBody)

Definition at line 2949 of file section.c.

2950{
2952 PCONTROL_AREA ControlArea;
2953 KIRQL OldIrql;
2954
2955 SectionObject = (PSECTION)ObjectBody;
2956
2957 if (SectionObject->u.Flags.Based == 1)
2958 {
2959 /* Remove the node from the global section address tree */
2963 }
2964
2965 /* Lock the PFN database */
2966 OldIrql = MiAcquirePfnLock();
2967
2968 ASSERT(SectionObject->Segment);
2969 ASSERT(SectionObject->Segment->ControlArea);
2970
2971 ControlArea = SectionObject->Segment->ControlArea;
2972
2973 /* Dereference */
2974 ControlArea->NumberOfSectionReferences--;
2975 ControlArea->NumberOfUserReferences--;
2976
2977 ASSERT(ControlArea->u.Flags.BeingDeleted == 0);
2978
2979 /* Check it. It will delete it if there is no more reference to it */
2980 MiCheckControlArea(ControlArea, OldIrql);
2981}
KGUARDED_MUTEX MmSectionBasedMutex
Definition: section.c:110
MM_AVL_TABLE MmSectionBasedRoot
Definition: section.c:109
static VOID MiCheckControlArea(IN PCONTROL_AREA ControlArea, IN KIRQL OldIrql)
Definition: section.c:714
_Must_inspect_result_ _Outptr_ PVOID * SectionObject
Definition: fsrtlfuncs.h:860
VOID FASTCALL KeReleaseGuardedMutex(IN OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:53
VOID FASTCALL KeAcquireGuardedMutex(IN PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:42
VOID NTAPI MiRemoveNode(IN PMMADDRESS_NODE Node, IN PMM_AVL_TABLE Table)
Definition: vadnode.c:440
struct _SECTION * PSECTION
ULONG NumberOfSectionReferences
Definition: mmtypes.h:523
ULONG NumberOfUserReferences
Definition: mmtypes.h:527
union _CONTROL_AREA::@2608 u
MMSECTION_FLAGS Flags
Definition: mmtypes.h:531
ULONG BeingDeleted
Definition: mmtypes.h:463

Referenced by MmpDeleteSection().

◆ MiDeletePde()

FORCEINLINE VOID MiDeletePde ( _In_ PMMPDE  PointerPde,
_In_ PEPROCESS  CurrentProcess 
)

Definition at line 2526 of file miarm.h.

2529{
2530 /* Only for user-mode ones */
2531 ASSERT(MiIsUserPde(PointerPde));
2532
2533 /* Kill this one as a PTE */
2534 MiDeletePte((PMMPTE)PointerPde, MiPdeToPte(PointerPde), CurrentProcess, NULL);
2535#if _MI_PAGING_LEVELS >= 3
2536 /* Cascade down */
2537 if (MiDecrementPageTableReferences(MiPdeToPte(PointerPde)) == 0)
2538 {
2539 MiDeletePte(MiPdeToPpe(PointerPde), PointerPde, CurrentProcess, NULL);
2540#if _MI_PAGING_LEVELS == 4
2541 if (MiDecrementPageTableReferences(PointerPde) == 0)
2542 {
2543 MiDeletePte(MiPdeToPxe(PointerPde), MiPdeToPpe(PointerPde), CurrentProcess, NULL);
2544 }
2545#endif
2546 }
2547#endif
2548}
VOID NTAPI MiDeletePte(IN PMMPTE PointerPte, IN PVOID VirtualAddress, IN PEPROCESS CurrentProcess, IN PMMPTE PrototypePte)
Definition: virtual.c:369
FORCEINLINE USHORT MiDecrementPageTableReferences(IN PVOID Address)
Definition: miarm.h:2492
FORCEINLINE BOOLEAN MiIsUserPde(PVOID Address)
Definition: miarm.h:717
FORCEINLINE PMMPXE MiPdeToPxe(PMMPDE PointerPde)
Definition: mm.h:300
FORCEINLINE PMMPDE MiPdeToPpe(PMMPDE PointerPde)
Definition: mm.h:292
#define MiPdeToPte(_Pde)
Definition: mm.h:120

Referenced by _Success_(), MiDeleteVirtualAddresses(), MiUnmapLockedPagesInUserSpace(), and MmDeletePageFileMapping().

◆ MiDeletePte()

VOID NTAPI MiDeletePte ( IN PMMPTE  PointerPte,
IN PVOID  VirtualAddress,
IN PEPROCESS  CurrentProcess,
IN PMMPTE  PrototypePte 
)

Definition at line 369 of file virtual.c.

373{
374 PMMPFN Pfn1;
376 PFN_NUMBER PageFrameIndex;
377 PMMPDE PointerPde;
378
379 /* PFN lock must be held */
381
382 /* WorkingSet must be exclusively locked */
384
385 /* This must be current process. */
386 ASSERT(CurrentProcess == PsGetCurrentProcess());
387
388 /* Capture the PTE */
389 TempPte = *PointerPte;
390
391 /* See if the PTE is valid */
392 if (TempPte.u.Hard.Valid == 0)
393 {
394 /* Prototype and paged out PTEs not supported yet */
395 ASSERT(TempPte.u.Soft.Prototype == 0);
396 ASSERT((TempPte.u.Soft.PageFileHigh == 0) || (TempPte.u.Soft.Transition == 1));
397
398 if (TempPte.u.Soft.Transition)
399 {
400 /* Get the PFN entry */
401 PageFrameIndex = PFN_FROM_PTE(&TempPte);
402 Pfn1 = MiGetPfnEntry(PageFrameIndex);
403
404 DPRINT("Pte %p is transitional!\n", PointerPte);
405
406 /* Make sure the saved PTE address is valid */
407 ASSERT((PMMPTE)((ULONG_PTR)Pfn1->PteAddress & ~0x1) == PointerPte);
408
409 /* Destroy the PTE */
410 MI_ERASE_PTE(PointerPte);
411
412 /* Drop the reference on the page table. */
414
415 /* In case of shared page, the prototype PTE must be in transition, not the process one */
416 ASSERT(Pfn1->u3.e1.PrototypePte == 0);
417
418 /* Delete the PFN */
419 MI_SET_PFN_DELETED(Pfn1);
420
421 /* It must be either free (refcount == 0) or being written (refcount == 1) */
422 ASSERT(Pfn1->u3.e2.ReferenceCount == Pfn1->u3.e1.WriteInProgress);
423
424 /* See if we must free it ourselves, or if it will be freed once I/O is over */
425 if (Pfn1->u3.e2.ReferenceCount == 0)
426 {
427 /* And it should be in standby or modified list */
429
430 /* Unlink it and set its reference count to one */
432 Pfn1->u3.e2.ReferenceCount++;
433
434 /* This will put it back in free list and clean properly up */
435 MiDecrementReferenceCount(Pfn1, PageFrameIndex);
436 }
437 return;
438 }
439 }
440
441 /* Get the PFN entry */
442 PageFrameIndex = PFN_FROM_PTE(&TempPte);
443 Pfn1 = MiGetPfnEntry(PageFrameIndex);
444
445 /* Check if this is a valid, prototype PTE */
446 if (Pfn1->u3.e1.PrototypePte == 1)
447 {
448 /* Get the PDE and make sure it's faulted in */
449 PointerPde = MiPteToPde(PointerPte);
450 if (PointerPde->u.Hard.Valid == 0)
451 {
452#if (_MI_PAGING_LEVELS == 2)
453 /* Could be paged pool access from a new process -- synchronize the page directories */
455 {
456#endif
457 /* The PDE must be valid at this point */
458 KeBugCheckEx(MEMORY_MANAGEMENT,
459 0x61940,
460 (ULONG_PTR)PointerPte,
461 PointerPte->u.Long,
463 }
464#if (_MI_PAGING_LEVELS == 2)
465 }
466#endif
467 /* Drop the share count on the page table */
468 PointerPde = MiPteToPde(PointerPte);
470 PointerPde->u.Hard.PageFrameNumber);
471
472 /* Drop the share count */
473 MiDecrementShareCount(Pfn1, PageFrameIndex);
474
475 /* Either a fork, or this is the shared user data page */
476 if ((PointerPte <= MiHighestUserPte) && (PrototypePte != Pfn1->PteAddress))
477 {
478 /* If it's not the shared user page, then crash, since there's no fork() yet */
481 {
482 /* Must be some sort of memory corruption */
483 KeBugCheckEx(MEMORY_MANAGEMENT,
484 0x400,
485 (ULONG_PTR)PointerPte,
487 (ULONG_PTR)Pfn1->PteAddress);
488 }
489 }
490
491 /* Erase it */
492 MI_ERASE_PTE(PointerPte);
493 }
494 else
495 {
496 /* Make sure the saved PTE address is valid */
497 if ((PMMPTE)((ULONG_PTR)Pfn1->PteAddress & ~0x1) != PointerPte)
498 {
499 /* The PFN entry is illegal, or invalid */
500 KeBugCheckEx(MEMORY_MANAGEMENT,
501 0x401,
502 (ULONG_PTR)PointerPte,
503 PointerPte->u.Long,
504 (ULONG_PTR)Pfn1->PteAddress);
505 }
506
507 /* Erase the PTE */
508 MI_ERASE_PTE(PointerPte);
509
510 /* There should only be 1 shared reference count */
511 ASSERT(Pfn1->u2.ShareCount == 1);
512
513 /* Drop the reference on the page table. */
515
516 /* Mark the PFN for deletion and dereference what should be the last ref */
517 MI_SET_PFN_DELETED(Pfn1);
518 MiDecrementShareCount(Pfn1, PageFrameIndex);
519
520 /* We should eventually do this */
521 //CurrentProcess->NumberOfPrivatePages--;
522 }
523
524 /* Flush the TLB */
526}
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define USER_SHARED_DATA
Definition: pstypes.h:51
FORCEINLINE BOOLEAN MM_ANY_WS_LOCK_HELD_EXCLUSIVE(_In_ PETHREAD Thread)
Definition: miarm.h:1065
FORCEINLINE VOID MI_ERASE_PTE(IN PMMPTE PointerPte)
Definition: miarm.h:1006
VOID NTAPI MiDecrementShareCount(IN PMMPFN Pfn1, IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:1141
VOID NTAPI MiUnlinkPageFromList(IN PMMPFN Pfn)
Definition: pfnlist.c:265
NTSTATUS FASTCALL MiCheckPdeForPagedPool(IN PVOID Address)
Definition: pagfault.c:479
VOID NTAPI MiDecrementReferenceCount(IN PMMPFN Pfn1, IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:1236
@ ModifiedPageList
Definition: mmtypes.h:156
#define MiPteToPde(_Pte)
Definition: mm.h:121
VOID NTAPI KeFlushCurrentTb(VOID)
Definition: cpu.c:526
MMPTE PrototypePte
Definition: init.c:40
PVOID MmHighestUserAddress
Definition: rtlcompat.c:29
USHORT PrototypePte
Definition: mm.h:363
USHORT WriteInProgress
Definition: mm.h:362
PMMPTE PteAddress
Definition: mm.h:386
ULONG64 PageFrameNumber
Definition: mmtypes.h:171
_Must_inspect_result_ _In_ WDFDMATRANSACTION _In_ PFN_WDF_PROGRAM_DMA _In_ WDF_DMA_DIRECTION _In_ PMDL _In_ PVOID VirtualAddress
#define PAGE_ALIGN(Va)
#define PsGetCurrentProcess
Definition: psfuncs.h:17

Referenced by MiDeletePde(), MiDeleteVirtualAddresses(), MiResolveProtoPteFault(), and MmArmAccessFault().

◆ MiDeleteSystemPageableVm()

PFN_COUNT NTAPI MiDeleteSystemPageableVm ( IN PMMPTE  PointerPte,
IN PFN_NUMBER  PageCount,
IN ULONG  Flags,
OUT PPFN_NUMBER  ValidPages 
)

Definition at line 275 of file virtual.c.

279{
280 PFN_COUNT ActualPages = 0;
281 PETHREAD CurrentThread = PsGetCurrentThread();
282 PMMPFN Pfn1, Pfn2;
283 PFN_NUMBER PageFrameIndex, PageTableIndex;
286
287 /* Lock the system working set */
288 MiLockWorkingSet(CurrentThread, &MmSystemCacheWs);
289
290 /* Loop all pages */
291 while (PageCount)
292 {
293 /* Make sure there's some data about the page */
294 if (PointerPte->u.Long)
295 {
296 /* Normally this is one possibility -- freeing a valid page */
297 if (PointerPte->u.Hard.Valid)
298 {
299 /* Get the page PFN */
300 PageFrameIndex = PFN_FROM_PTE(PointerPte);
301 Pfn1 = MiGetPfnEntry(PageFrameIndex);
302
303 /* Should not have any working set data yet */
304 ASSERT(Pfn1->u1.WsIndex == 0);
305
306 /* Actual valid, legitimate, pages */
307 if (ValidPages) (*ValidPages)++;
308
309 /* Get the page table entry */
310 PageTableIndex = Pfn1->u4.PteFrame;
311 Pfn2 = MiGetPfnEntry(PageTableIndex);
312
313 /* Lock the PFN database */
314 OldIrql = MiAcquirePfnLock();
315
316 /* Delete it the page */
317 MI_SET_PFN_DELETED(Pfn1);
318 MiDecrementShareCount(Pfn1, PageFrameIndex);
319
320 /* Decrement the page table too */
321 MiDecrementShareCount(Pfn2, PageTableIndex);
322
323 /* Release the PFN database */
324 MiReleasePfnLock(OldIrql);
325
326 /* Destroy the PTE */
327 MI_ERASE_PTE(PointerPte);
328 }
329 else
330 {
331 /* As always, only handle current ARM3 scenarios */
332 ASSERT(PointerPte->u.Soft.Prototype == 0);
333 ASSERT(PointerPte->u.Soft.Transition == 0);
334
335 /*
336 * The only other ARM3 possibility is a demand zero page, which would
337 * mean freeing some of the paged pool pages that haven't even been
338 * touched yet, as part of a larger allocation.
339 *
340 * Right now, we shouldn't expect any page file information in the PTE
341 */
342 ASSERT(PointerPte->u.Soft.PageFileHigh == 0);
343
344 /* Destroy the PTE */
345 MI_ERASE_PTE(PointerPte);
346 }
347
348 /* Actual legitimate pages */
349 ActualPages++;
350 }
351
352 /* Keep going */
353 PointerPte++;
354 PageCount--;
355 }
356
357 /* Release the working set */
358 MiUnlockWorkingSet(CurrentThread, &MmSystemCacheWs);
359
360 /* Flush the entire TLB */
362
363 /* Done */
364 return ActualPages;
365}
FORCEINLINE VOID MiLockWorkingSet(IN PETHREAD Thread, IN PMMSUPPORT WorkingSet)
Definition: miarm.h:1265
FORCEINLINE VOID MiUnlockWorkingSet(IN PETHREAD Thread, IN PMMSUPPORT WorkingSet)
Definition: miarm.h:1351
VOID NTAPI KeFlushEntireTb(IN BOOLEAN Invalid, IN BOOLEAN AllProcessors)
Definition: cpu.c:652
MMSUPPORT MmSystemCacheWs
Definition: init.c:55
ULONG WsIndex
Definition: mm.h:378
union _MMPFN::@1797 u1
ULONG PFN_COUNT
Definition: mmtypes.h:102

Referenced by MiFreeInitializationCode(), MiFreePoolPages(), MmFreeDriverInitialization(), and MmFreeSpecialPool().

◆ MiDeleteVirtualAddresses()

VOID NTAPI MiDeleteVirtualAddresses ( IN ULONG_PTR  Va,
IN ULONG_PTR  EndingAddress,
IN PMMVAD  Vad 
)

Definition at line 530 of file virtual.c.

533{
534 PMMPTE PointerPte, PrototypePte, LastPrototypePte;
535 PMMPDE PointerPde;
536#if (_MI_PAGING_LEVELS >= 3)
537 PMMPPE PointerPpe;
538#endif
539#if (_MI_PAGING_LEVELS >= 4)
540 PMMPPE PointerPxe;
541#endif
543 PEPROCESS CurrentProcess;
545 BOOLEAN AddressGap = FALSE;
546 PSUBSECTION Subsection;
547
548 /* Get out if this is a fake VAD, RosMm will free the marea pages */
549 if ((Vad) && (Vad->u.VadFlags.Spare == 1)) return;
550
551 /* Get the current process */
552 CurrentProcess = PsGetCurrentProcess();
553
554 /* Check if this is a section VAD or a VM VAD */
555 if (!(Vad) || (Vad->u.VadFlags.PrivateMemory) || !(Vad->FirstPrototypePte))
556 {
557 /* Don't worry about prototypes */
558 PrototypePte = LastPrototypePte = NULL;
559 }
560 else
561 {
562 /* Get the prototype PTE */
563 PrototypePte = Vad->FirstPrototypePte;
564 LastPrototypePte = Vad->FirstPrototypePte + 1;
565 }
566
567 /* In all cases, we don't support fork() yet */
568 ASSERT(CurrentProcess->CloneRoot == NULL);
569
570 /* Loop the PTE for each VA (EndingAddress is inclusive!) */
571 while (Va <= EndingAddress)
572 {
573#if (_MI_PAGING_LEVELS >= 4)
574 /* Get the PXE and check if it's valid */
575 PointerPxe = MiAddressToPxe((PVOID)Va);
576 if (!PointerPxe->u.Hard.Valid)
577 {
578 /* Check for unmapped range and skip it */
579 if (!PointerPxe->u.Long)
580 {
581 /* There are gaps in the address space */
582 AddressGap = TRUE;
583
584 /* Update Va and continue looping */
585 Va = (ULONG_PTR)MiPxeToAddress(PointerPxe + 1);
586 continue;
587 }
588
589 /* Make the PXE valid */
590 MiMakeSystemAddressValid(MiPteToAddress(PointerPxe), CurrentProcess);
591 }
592#endif
593#if (_MI_PAGING_LEVELS >= 3)
594 /* Get the PPE and check if it's valid */
595 PointerPpe = MiAddressToPpe((PVOID)Va);
596 if (!PointerPpe->u.Hard.Valid)
597 {
598 /* Check for unmapped range and skip it */
599 if (!PointerPpe->u.Long)
600 {
601 /* There are gaps in the address space */
602 AddressGap = TRUE;
603
604 /* Update Va and continue looping */
605 Va = (ULONG_PTR)MiPpeToAddress(PointerPpe + 1);
606 continue;
607 }
608
609 /* Make the PPE valid */
610 MiMakeSystemAddressValid(MiPteToAddress(PointerPpe), CurrentProcess);
611 }
612#endif
613 /* Skip invalid PDEs */
614 PointerPde = MiAddressToPde((PVOID)Va);
615 if (!PointerPde->u.Long)
616 {
617 /* There are gaps in the address space */
618 AddressGap = TRUE;
619
620 /* Check if all the PDEs are invalid, so there's nothing to free */
621 Va = (ULONG_PTR)MiPdeToAddress(PointerPde + 1);
622 continue;
623 }
624
625 /* Now check if the PDE is mapped in */
626 if (!PointerPde->u.Hard.Valid)
627 {
628 /* It isn't, so map it in */
629 PointerPte = MiPteToAddress(PointerPde);
630 MiMakeSystemAddressValid(PointerPte, CurrentProcess);
631 }
632
633 /* Now we should have a valid PDE, mapped in, and still have some VA */
634 ASSERT(PointerPde->u.Hard.Valid == 1);
635 ASSERT(Va <= EndingAddress);
636
637 /* Check if this is a section VAD with gaps in it */
638 if ((AddressGap) && (LastPrototypePte))
639 {
640 /* We need to skip to the next correct prototype PTE */
642
643 /* And we need the subsection to skip to the next last prototype PTE */
644 Subsection = MiLocateSubsection(Vad, Va >> PAGE_SHIFT);
645 if (Subsection)
646 {
647 /* Found it! */
648 LastPrototypePte = &Subsection->SubsectionBase[Subsection->PtesInSubsection];
649 }
650 else
651 {
652 /* No more subsections, we are done with prototype PTEs */
654 }
655 }
656
657 /* Lock the PFN Database while we delete the PTEs */
658 OldIrql = MiAcquirePfnLock();
659 PointerPte = MiAddressToPte(Va);
660 do
661 {
662 /* Making sure the PDE is still valid */
663 ASSERT(PointerPde->u.Hard.Valid == 1);
664
665 /* Capture the PDE and make sure it exists */
666 TempPte = *PointerPte;
667 if (TempPte.u.Long)
668 {
669 /* Check if the PTE is actually mapped in */
671 {
672 /* Are we dealing with section VAD? */
673 if ((LastPrototypePte) && (PrototypePte > LastPrototypePte))
674 {
675 /* We need to skip to the next correct prototype PTE */
677
678 /* And we need the subsection to skip to the next last prototype PTE */
679 Subsection = MiLocateSubsection(Vad, Va >> PAGE_SHIFT);
680 if (Subsection)
681 {
682 /* Found it! */
683 LastPrototypePte = &Subsection->SubsectionBase[Subsection->PtesInSubsection];
684 }
685 else
686 {
687 /* No more subsections, we are done with prototype PTEs */
689 }
690 }
691
692 /* Check for prototype PTE */
693 if ((TempPte.u.Hard.Valid == 0) &&
694 (TempPte.u.Soft.Prototype == 1))
695 {
696 /* Just nuke it */
697 MI_ERASE_PTE(PointerPte);
698 }
699 else
700 {
701 /* Delete the PTE proper */
702 MiDeletePte(PointerPte,
703 (PVOID)Va,
704 CurrentProcess,
706 }
707 }
708 else
709 {
710 /* The PTE was never mapped, just nuke it here */
711 MI_ERASE_PTE(PointerPte);
712 }
713
715 {
716 ASSERT(PointerPde->u.Long != 0);
717
718 /* Delete the PDE proper */
719 MiDeletePde(PointerPde, CurrentProcess);
720
721 /* Continue with the next PDE */
722 Va = (ULONG_PTR)MiPdeToAddress(PointerPde + 1);
723
724 /* Use this to detect address gaps */
725 PointerPte++;
726
727 PrototypePte++;
728 break;
729 }
730 }
731
732 /* Update the address and PTE for it */
733 Va += PAGE_SIZE;
734 PointerPte++;
735 PrototypePte++;
736 } while ((Va & (PDE_MAPPED_VA - 1)) && (Va <= EndingAddress));
737
738 /* Release the lock */
739 MiReleasePfnLock(OldIrql);
740
741 if (Va > EndingAddress) return;
742
743 /* Check if we exited the loop regularly */
744 AddressGap = (PointerPte != MiAddressToPte(Va));
745 }
746}
unsigned char BOOLEAN
#define PAGE_SIZE
Definition: env_spec_w32.h:49
FORCEINLINE PMMPTE MI_GET_PROTOTYPE_PTE_FOR_VPN(IN PMMVAD Vad, IN ULONG_PTR Vpn)
Definition: miarm.h:1557
FORCEINLINE VOID MiDeletePde(_In_ PMMPDE PointerPde, _In_ PEPROCESS CurrentProcess)
Definition: miarm.h:2526
PSUBSECTION NTAPI MiLocateSubsection(IN PMMVAD Vad, IN ULONG_PTR Vpn)
Definition: section.c:556
FORCEINLINE PVOID MiPpeToAddress(PMMPTE PointerPpe)
Definition: mm.h:226
FORCEINLINE PMMPTE MiAddressToPpe(PVOID Address)
Definition: mm.h:161
FORCEINLINE PMMPTE MiAddressToPxe(PVOID Address)
Definition: mm.h:171
FORCEINLINE BOOLEAN MI_IS_MAPPED_PTE(PMMPTE PointerPte)
Definition: mm.h:356
#define PDE_MAPPED_VA
Definition: mm.h:39
FORCEINLINE PVOID MiPxeToAddress(PMMPTE PointerPxe)
Definition: mm.h:235
#define MiPdeToAddress(_Pde)
Definition: mm.h:117
VOID NTAPI MiDeletePte(IN PMMPTE PointerPte, IN PVOID VirtualAddress, IN PEPROCESS CurrentProcess, IN PMMPTE PrototypePte)
Definition: virtual.c:369
ULONG NTAPI MiMakeSystemAddressValid(IN PVOID PageTableVirtualAddress, IN PEPROCESS CurrentProcess)
Definition: virtual.c:183
PVOID CloneRoot
Definition: pstypes.h:1299
ULONG PtesInSubsection
Definition: mmtypes.h:583
PMMPTE SubsectionBase
Definition: mmtypes.h:581

Referenced by MiRemoveMappedView(), MmCleanProcessAddressSpace(), MmDeleteTeb(), and NtFreeVirtualMemory().

◆ MiDereferencePfnAndDropLockCount()

FORCEINLINE VOID MiDereferencePfnAndDropLockCount ( IN PMMPFN  Pfn1)

Definition at line 1615 of file miarm.h.

1616{
1617 USHORT RefCount, OldRefCount;
1618 PFN_NUMBER PageFrameIndex;
1619
1620 /* Loop while we decrement the page successfully */
1621 do
1622 {
1623 /* There should be at least one reference */
1624 OldRefCount = Pfn1->u3.e2.ReferenceCount;
1625 ASSERT(OldRefCount != 0);
1626
1627 /* Are we the last one */
1628 if (OldRefCount == 1)
1629 {
1630 /* The page shoudln't be shared not active at this point */
1631 ASSERT(Pfn1->u3.e2.ReferenceCount == 1);
1632 ASSERT(Pfn1->u3.e1.PageLocation != ActiveAndValid);
1633 ASSERT(Pfn1->u2.ShareCount == 0);
1634
1635 /* Is it a prototype PTE? */
1636 if ((Pfn1->u3.e1.PrototypePte == 1) &&
1637 (Pfn1->OriginalPte.u.Soft.Prototype == 1))
1638 {
1639 /* FIXME: We should return commit */
1640 DPRINT1("Not returning commit for prototype PTE\n");
1641 }
1642
1643 /* Update the counter, and drop a reference the long way */
1645 PageFrameIndex = MiGetPfnEntryIndex(Pfn1);
1646 MiDecrementReferenceCount(Pfn1, PageFrameIndex);
1647 return;
1648 }
1649
1650 /* Drop a reference the short way, and that's it */
1651 RefCount = InterlockedCompareExchange16((PSHORT)&Pfn1->u3.e2.ReferenceCount,
1652 OldRefCount - 1,
1653 OldRefCount);
1654 ASSERT(RefCount != 0);
1655 } while (OldRefCount != RefCount);
1656
1657 /* If we got here, there should be more than one reference */
1658 ASSERT(RefCount > 1);
1659 if (RefCount == 2)
1660 {
1661 /* Is it still being shared? */
1662 if (Pfn1->u2.ShareCount >= 1)
1663 {
1664 /* Then it should be valid */
1665 ASSERT(Pfn1->u3.e1.PageLocation == ActiveAndValid);
1666
1667 /* Is it a prototype PTE? */
1668 if ((Pfn1->u3.e1.PrototypePte == 1) &&
1669 (Pfn1->OriginalPte.u.Soft.Prototype == 1))
1670 {
1671 /* We don't handle ethis */
1672 ASSERT(FALSE);
1673 }
1674
1675 /* Update the counter */
1677 }
1678 }
1679}
#define InterlockedCompareExchange16
Definition: interlocked.h:109
#define InterlockedDecrementSizeT(a)
Definition: interlocked.h:153
SIZE_T MmSystemLockPagesCount
Definition: mdlsup.c:22
unsigned short USHORT
Definition: pedump.c:61

Referenced by MI_UNLOCK_VA(), MiCompleteProtoPteFault(), MiDispatchFault(), and MmUnlockPages().

◆ MiDetermineUserGlobalPteMask()

FORCEINLINE ULONG_PTR MiDetermineUserGlobalPteMask ( IN PVOID  PointerPte)

Definition at line 736 of file miarm.h.

737{
739
740 /* Start fresh */
741 TempPte.u.Long = 0;
742
743 /* Make it valid and accessed */
744 TempPte.u.Hard.Valid = TRUE;
746
747 /* Is this for user-mode? */
748 if (
749#if (_MI_PAGING_LEVELS == 4)
750 MiIsUserPxe(PointerPte) ||
751#endif
752#if (_MI_PAGING_LEVELS >= 3)
753 MiIsUserPpe(PointerPte) ||
754#endif
755 MiIsUserPde(PointerPte) ||
756 MiIsUserPte(PointerPte))
757 {
758 /* Set the owner bit */
760 }
761
762 /* FIXME: We should also set the global bit */
763
764 /* Return the protection */
765 return TempPte.u.Long;
766}
FORCEINLINE BOOLEAN MiIsUserPte(PVOID Address)
Definition: miarm.h:725
#define MI_MAKE_OWNER_PAGE(x)
Definition: mm.h:113
#define MI_MAKE_ACCESSED_PAGE(x)
Definition: mm.h:100
#define _MI_PAGING_LEVELS
Definition: mm.h:6

Referenced by MI_MAKE_HARDWARE_PTE(), and MiResolveTransitionFault().

◆ MiDropLockCount()

FORCEINLINE VOID MiDropLockCount ( IN PMMPFN  Pfn1)

Definition at line 1585 of file miarm.h.

1586{
1587 /* This page shouldn't be locked, but it should be valid */
1588 ASSERT(Pfn1->u3.e2.ReferenceCount != 0);
1589 ASSERT(Pfn1->u2.ShareCount == 0);
1590
1591 /* Is this the last reference to the page */
1592 if (Pfn1->u3.e2.ReferenceCount == 1)
1593 {
1594 /* It better not be valid */
1595 ASSERT(Pfn1->u3.e1.PageLocation != ActiveAndValid);
1596
1597 /* Is it a prototype PTE? */
1598 if ((Pfn1->u3.e1.PrototypePte == 1) &&
1599 (Pfn1->OriginalPte.u.Soft.Prototype == 1))
1600 {
1601 /* FIXME: We should return commit */
1602 DPRINT1("Not returning commit for prototype PTE\n");
1603 }
1604
1605 /* Update the counter */
1607 }
1608}

Referenced by MiResolveTransitionFault().

◆ MiFindContiguousPages()

PFN_NUMBER NTAPI MiFindContiguousPages ( IN PFN_NUMBER  LowestPfn,
IN PFN_NUMBER  HighestPfn,
IN PFN_NUMBER  BoundaryPfn,
IN PFN_NUMBER  SizeInPages,
IN MEMORY_CACHING_TYPE  CacheType 
)

Definition at line 22 of file contmem.c.

27{
28 PFN_NUMBER Page, PageCount, LastPage, Length, BoundaryMask;
29 ULONG i = 0;
30 PMMPFN Pfn1, EndPfn;
32 PAGED_CODE();
33 ASSERT(SizeInPages != 0);
34
35 //
36 // Convert the boundary PFN into an alignment mask
37 //
38 BoundaryMask = ~(BoundaryPfn - 1);
39
40 /* Disable APCs */
42
43 //
44 // Loop all the physical memory blocks
45 //
46 do
47 {
48 //
49 // Capture the base page and length of this memory block
50 //
53
54 //
55 // Check how far this memory block will go
56 //
57 LastPage = Page + PageCount;
58
59 //
60 // Trim it down to only the PFNs we're actually interested in
61 //
62 if ((LastPage - 1) > HighestPfn) LastPage = HighestPfn + 1;
63 if (Page < LowestPfn) Page = LowestPfn;
64
65 //
66 // Skip this run if it's empty or fails to contain all the pages we need
67 //
68 if (!(PageCount) || ((Page + SizeInPages) > LastPage)) continue;
69
70 //
71 // Now scan all the relevant PFNs in this run
72 //
73 Length = 0;
74 for (Pfn1 = MI_PFN_ELEMENT(Page); Page < LastPage; Page++, Pfn1++)
75 {
76 //
77 // If this PFN is in use, ignore it
78 //
79 if (MiIsPfnInUse(Pfn1))
80 {
81 Length = 0;
82 continue;
83 }
84
85 //
86 // If we haven't chosen a start PFN yet and the caller specified an
87 // alignment, make sure the page matches the alignment restriction
88 //
89 if ((!(Length) && (BoundaryPfn)) &&
90 (((Page ^ (Page + SizeInPages - 1)) & BoundaryMask)))
91 {
92 //
93 // It does not, so bail out
94 //
95 continue;
96 }
97
98 //
99 // Increase the number of valid pages, and check if we have enough
100 //
101 if (++Length == SizeInPages)
102 {
103 //
104 // It appears we've amassed enough legitimate pages, rollback
105 //
106 Pfn1 -= (Length - 1);
107 Page -= (Length - 1);
108
109 //
110 // Acquire the PFN lock
111 //
112 OldIrql = MiAcquirePfnLock();
113 do
114 {
115 //
116 // Things might've changed for us. Is the page still free?
117 //
118 if (MiIsPfnInUse(Pfn1)) break;
119
120 //
121 // So far so good. Is this the last confirmed valid page?
122 //
123 if (!--Length)
124 {
125 //
126 // Sanity check that we didn't go out of bounds
127 //
129
130 //
131 // Loop until all PFN entries have been processed
132 //
133 EndPfn = Pfn1 - SizeInPages + 1;
134 do
135 {
136 //
137 // This PFN is now a used page, set it up
138 //
140 MI_SET_PROCESS2("Kernel Driver");
142 Pfn1->u3.e2.ReferenceCount = 1;
143 Pfn1->u2.ShareCount = 1;
145 Pfn1->u3.e1.StartOfAllocation = 0;
146 Pfn1->u3.e1.EndOfAllocation = 0;
147 Pfn1->u3.e1.PrototypePte = 0;
148 Pfn1->u4.VerifierAllocation = 0;
149 Pfn1->PteAddress = (PVOID)(ULONG_PTR)0xBAADF00DBAADF00DULL;
150
151 //
152 // Check if this is the last PFN, otherwise go on
153 //
154 if (Pfn1 == EndPfn) break;
155 Pfn1--;
156 } while (TRUE);
157
158 //
159 // Mark the first and last PFN so we can find them later
160 //
161 Pfn1->u3.e1.StartOfAllocation = 1;
162 (Pfn1 + SizeInPages - 1)->u3.e1.EndOfAllocation = 1;
163
164 //
165 // Now it's safe to let go of the PFN lock
166 //
167 MiReleasePfnLock(OldIrql);
168
169 //
170 // Quick sanity check that the last PFN is consistent
171 //
172 EndPfn = Pfn1 + SizeInPages;
173 ASSERT(EndPfn == MI_PFN_ELEMENT(Page + 1));
174
175 //
176 // Compute the first page, and make sure it's consistent
177 //
178 Page = Page - SizeInPages + 1;
179 ASSERT(Pfn1 == MI_PFN_ELEMENT(Page));
180 ASSERT(Page != 0);
181
182 /* Enable APCs and return the page */
184 return Page;
185 }
186
187 //
188 // Keep going. The purpose of this loop is to reconfirm that
189 // after acquiring the PFN lock these pages are still usable
190 //
191 Pfn1++;
192 Page++;
193 } while (TRUE);
194
195 //
196 // If we got here, something changed while we hadn't acquired
197 // the PFN lock yet, so we'll have to restart
198 //
199 MiReleasePfnLock(OldIrql);
200 Length = 0;
201 }
202 }
203 } while (++i != MmPhysicalMemoryBlock->NumberOfRuns);
204
205 //
206 // And if we get here, it means no suitable physical memory runs were found
207 //
209 return 0;
210}
#define PAGED_CODE()
#define KeLeaveGuardedRegion()
Definition: ke_x.h:68
#define KeEnterGuardedRegion()
Definition: ke_x.h:39
BOOLEAN NTAPI MiIsPfnInUse(IN PMMPFN Pfn1)
Definition: freelist.c:174
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
@ MI_USAGE_CONTINOUS_ALLOCATION
Definition: mm.h:338
PPHYSICAL_MEMORY_DESCRIPTOR MmPhysicalMemoryBlock
Definition: init.c:45
PHYSICAL_MEMORY_RUN Run[1]
Definition: miarm.h:426
PFN_NUMBER PageCount
Definition: miarm.h:419
PFN_NUMBER BasePage
Definition: miarm.h:418

Referenced by MiFindContiguousMemory().

◆ MiFindEmptyAddressRangeDownBasedTree()

NTSTATUS NTAPI MiFindEmptyAddressRangeDownBasedTree ( IN SIZE_T  Length,
IN ULONG_PTR  BoundaryAddress,
IN ULONG_PTR  Alignment,
IN PMM_AVL_TABLE  Table,
OUT PULONG_PTR  Base 
)

Definition at line 799 of file vadnode.c.

804{
805 PMMADDRESS_NODE Node, LowestNode;
806 ULONG_PTR LowVpn, BestVpn;
807
809
810 /* Sanity checks */
812 ASSERT(BoundaryAddress);
813 ASSERT(BoundaryAddress <= ((ULONG_PTR)MM_HIGHEST_VAD_ADDRESS + 1));
814
815 /* Compute page length, make sure the boundary address is valid */
817 if ((BoundaryAddress + 1) < Length) return STATUS_NO_MEMORY;
818
819 /* Check if the table is empty */
820 BestVpn = ROUND_DOWN(BoundaryAddress + 1 - Length, Alignment);
821 if (Table->NumberGenericTableElements == 0)
822 {
823 /* Tree is empty, the candidate address is already the best one */
824 *Base = BestVpn;
825 return STATUS_SUCCESS;
826 }
827
828 /* Go to the right-most node which should be the biggest address */
829 Node = Table->BalancedRoot.RightChild;
831
832 /* Check if we can fit in here */
833 LowVpn = ROUND_UP(Node->EndingVpn + 1, Alignment);
834 if ((LowVpn < BoundaryAddress) && (Length <= (BoundaryAddress - LowVpn)))
835 {
836#if (NTDDI_VERSION >= NTDDI_VISTA)
837 /* Return the address. */
838 *Base = BestVpn;
839#else
840 /* Note: this is a compatibility hack that mimics a bug in the 2k3
841 kernel. It will can waste up to Alignment bytes of memory above
842 the allocation. This bug was fixed in Windows Vista */
843 *Base = ROUND_DOWN(BoundaryAddress - Length, Alignment);
844#endif
845 return STATUS_SUCCESS;
846 }
847
848 /* Now loop the Vad nodes */
849 do
850 {
851 /* Break out if we've reached the last node */
852 LowestNode = MiGetPreviousNode(Node);
853 if (!LowestNode) break;
854
855 /* Check if this node could contain the requested address */
856 LowVpn = ROUND_UP(LowestNode->EndingVpn + 1, Alignment);
857 if ((LowestNode->EndingVpn < BestVpn) &&
858 (LowVpn < Node->StartingVpn) &&
859 (Length <= (Node->StartingVpn - LowVpn)))
860 {
861 /* Check if we need to take BoundaryAddress into account */
862 if (BoundaryAddress < Node->StartingVpn)
863 {
864 /* Return the optimal VPN address */
865 *Base = BestVpn;
866 return STATUS_SUCCESS;
867 }
868 else
869 {
870 /* The upper margin is given by the Node's starting address */
871 *Base = ROUND_DOWN(Node->StartingVpn - Length, Alignment);
872 return STATUS_SUCCESS;
873 }
874 }
875
876 /* Move to the next node */
877 Node = LowestNode;
878 } while (TRUE);
879
880 /* Check if there's enough space before the lowest Vad */
881 if ((Node->StartingVpn > (ULONG_PTR)MI_LOWEST_VAD_ADDRESS) &&
882 ((Node->StartingVpn - (ULONG_PTR)MI_LOWEST_VAD_ADDRESS) >= Length))
883 {
884 /* Check if it fits in perfectly */
885 if (BoundaryAddress < Node->StartingVpn)
886 {
887 /* Return the optimal VPN address */
888 *Base = BestVpn;
889 return STATUS_SUCCESS;
890 }
891
892 /* Return an aligned base address within this node */
893 *Base = ROUND_DOWN(Node->StartingVpn - Length, Alignment);
894 return STATUS_SUCCESS;
895 }
896
897 /* No address space left at all */
898 return STATUS_NO_MEMORY;
899}
union node Node
Definition: types.h:1255
#define ROUND_UP(n, align)
Definition: eventvwr.h:34
#define ROUND_DOWN(n, align)
Definition: eventvwr.h:33
#define MI_LOWEST_VAD_ADDRESS
Definition: miarm.h:15
MM_AVL_TABLE MmSectionBasedRoot
Definition: section.c:109
#define MM_HIGHEST_VAD_ADDRESS
Definition: mm.h:46
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
Definition: dlist.c:348
PMMADDRESS_NODE NTAPI MiGetPreviousNode(IN PMMADDRESS_NODE Node)
Definition: vadnode.c:513

Referenced by MmCreateArm3Section().

◆ MiFindEmptyAddressRangeDownTree()

TABLE_SEARCH_RESULT NTAPI MiFindEmptyAddressRangeDownTree ( IN SIZE_T  Length,
IN ULONG_PTR  BoundaryAddress,
IN ULONG_PTR  Alignment,
IN PMM_AVL_TABLE  Table,
OUT PULONG_PTR  Base,
OUT PMMADDRESS_NODE Parent 
)

Definition at line 681 of file vadnode.c.

687{
688 PMMADDRESS_NODE Node, OldNode = NULL, Child;
689 ULONG_PTR LowVpn, HighVpn, AlignmentVpn;
690 PFN_NUMBER PageCount;
691
693
694 /* Sanity checks */
695 ASSERT(BoundaryAddress);
696 ASSERT(BoundaryAddress <= ((ULONG_PTR)MM_HIGHEST_VAD_ADDRESS));
697 ASSERT((Alignment & (PAGE_SIZE - 1)) == 0);
698
699 /* Calculate page numbers for the length and alignment */
701 PageCount = Length >> PAGE_SHIFT;
702 AlignmentVpn = Alignment / PAGE_SIZE;
703
704 /* Check for kernel mode table (memory areas) */
705 if (Table->Unused == 1)
706 {
707 LowVpn = ALIGN_UP_BY((ULONG_PTR)MmSystemRangeStart >> PAGE_SHIFT, AlignmentVpn);
708 }
709 else
710 {
712 }
713
714 /* Check if there is enough space below the boundary */
715 if ((LowVpn + Length) > (BoundaryAddress + 1))
716 {
717 return TableFoundNode;
718 }
719
720 /* Check if the table is empty */
721 if (Table->NumberGenericTableElements == 0)
722 {
723 /* Tree is empty, the candidate address is already the best one */
724 *Base = ALIGN_DOWN_BY(BoundaryAddress + 1 - Length, Alignment);
725 return TableEmptyTree;
726 }
727
728 /* Calculate the initial upper margin */
729 HighVpn = (BoundaryAddress + 1) >> PAGE_SHIFT;
730
731 /* Starting from the root, follow the right children until we found a node
732 that ends above the boundary */
733 Node = RtlRightChildAvl(&Table->BalancedRoot);
734 while ((Node->EndingVpn < HighVpn) &&
736
737 /* Now loop the Vad nodes */
738 while (Node)
739 {
740 /* Calculate the lower margin */
741 LowVpn = ALIGN_UP_BY(Node->EndingVpn + 1, AlignmentVpn);
742
743 /* Check if the current bounds are suitable */
744 if ((HighVpn > LowVpn) && ((HighVpn - LowVpn) >= PageCount))
745 {
746 /* There is enough space to add our node */
747 LowVpn = ALIGN_DOWN_BY(HighVpn - PageCount, AlignmentVpn);
748 *Base = LowVpn << PAGE_SHIFT;
749
750 /* Can we use the current node as parent? */
752 {
753 /* Node has no right child, so use it as parent */
754 *Parent = Node;
755 return TableInsertAsRight;
756 }
757 else
758 {
759 /* Node has a right child. This means we must have already
760 moved one node left from the right-most node we started
761 with, thus we already have an OldNode! */
762 ASSERT(OldNode != NULL);
763
764 /* The node we had before is the most left grandchild of
765 that right child, use it as parent. */
766 ASSERT(RtlLeftChildAvl(OldNode) == NULL);
767 *Parent = OldNode;
768 return TableInsertAsLeft;
769 }
770 }
771
772 /* Update the upper margin if necessary */
773 if (Node->StartingVpn < HighVpn) HighVpn = Node->StartingVpn;
774
775 /* Remember the current node and go to the previous node */
776 OldNode = Node;
778 }
779
780 /* Check if there's enough space before the lowest Vad */
782 if ((HighVpn > LowVpn) && ((HighVpn - LowVpn) >= PageCount))
783 {
784 /* There is enough space to add our address */
785 LowVpn = ALIGN_DOWN_BY(HighVpn - PageCount, Alignment >> PAGE_SHIFT);
786 *Base = LowVpn << PAGE_SHIFT;
787 *Parent = OldNode;
788 return TableInsertAsLeft;
789 }
790
791 /* No address space left at all */
792 *Base = 0;
793 *Parent = NULL;
794 return TableFoundNode;
795}
#define ALIGN_DOWN_BY(size, align)
#define ALIGN_UP_BY(size, align)
ACPI_PHYSICAL_ADDRESS ACPI_SIZE BOOLEAN Warn UINT32 *TableIdx UINT32 ACPI_TABLE_HEADER *OutTableHeader ACPI_TABLE_HEADER **OutTable ACPI_HANDLE UINT32 ACPI_WALK_CALLBACK ACPI_WALK_CALLBACK void void **ReturnValue UINT32 ACPI_BUFFER *RetPathPtr ACPI_OBJECT_HANDLER void *Data ACPI_OBJECT_HANDLER void **Data ACPI_STRING ACPI_OBJECT_LIST ACPI_BUFFER *ReturnObjectBuffer ACPI_DEVICE_INFO **ReturnBuffer ACPI_HANDLE Parent
Definition: acpixf.h:732
#define MM_LOWEST_USER_ADDRESS
Definition: armddk.h:20
#define MmSystemRangeStart
Definition: mm.h:32
_Must_inspect_result_ _In_ WDFDEVICE _In_ WDFDEVICE Child
Definition: wdffdo.h:536

Referenced by MiInsertVadEx(), and MmFindGap().

◆ MiFindEmptyAddressRangeInTree()

TABLE_SEARCH_RESULT NTAPI MiFindEmptyAddressRangeInTree ( IN SIZE_T  Length,
IN ULONG_PTR  Alignment,
IN PMM_AVL_TABLE  Table,
OUT PMMADDRESS_NODE PreviousVad,
OUT PULONG_PTR  Base 
)

Definition at line 584 of file vadnode.c.

589{
590 PMMADDRESS_NODE Node, PreviousNode;
591 ULONG_PTR PageCount, AlignmentVpn, LowVpn, HighestVpn;
592 ASSERT(Length != 0);
593
595
596 /* Calculate page numbers for the length, alignment, and starting address */
597 PageCount = BYTES_TO_PAGES(Length);
598 AlignmentVpn = Alignment >> PAGE_SHIFT;
599 LowVpn = ALIGN_UP_BY((ULONG_PTR)MM_LOWEST_USER_ADDRESS >> PAGE_SHIFT, AlignmentVpn);
600
601 /* Check for kernel mode table (memory areas) */
602 if (Table->Unused == 1)
603 {
604 LowVpn = ALIGN_UP_BY((ULONG_PTR)MmSystemRangeStart >> PAGE_SHIFT, AlignmentVpn);
605 }
606
607 /* Check if the table is empty */
608 if (Table->NumberGenericTableElements == 0)
609 {
610 /* Tree is empty, the candidate address is already the best one */
611 *Base = LowVpn << PAGE_SHIFT;
612 return TableEmptyTree;
613 }
614
615 /* Otherwise, follow the leftmost child of the right root node's child */
616 Node = RtlRightChildAvl(&Table->BalancedRoot);
618
619 /* Start a search to find a gap */
620 PreviousNode = NULL;
621 while (Node != NULL)
622 {
623 /* Check if the gap below the current node is suitable */
624 if (Node->StartingVpn >= LowVpn + PageCount)
625 {
626 /* There is enough space to add our node */
627 *Base = LowVpn << PAGE_SHIFT;
628
629 /* Can we use the current node as parent? */
630 if (RtlLeftChildAvl(Node) == NULL)
631 {
632 /* Node has no left child, so use it as parent */
633 *PreviousVad = Node;
634 return TableInsertAsLeft;
635 }
636 else
637 {
638 /* Node has a left child, this means that the previous node is
639 the right-most child of it's left child and can be used as
640 the parent. In case we use the space before the left-most
641 node, it's left child must be NULL. */
642 ASSERT(PreviousNode != NULL);
643 ASSERT(RtlRightChildAvl(PreviousNode) == NULL);
644 *PreviousVad = PreviousNode;
645 return TableInsertAsRight;
646 }
647 }
648
649 /* The next candidate is above the current node */
650 if (Node->EndingVpn >= LowVpn)
651 LowVpn = ALIGN_UP_BY(Node->EndingVpn + 1, AlignmentVpn);
652
653 /* Remember the current node and go to the next node */
654 PreviousNode = Node;
656 }
657
658 /* We're up to the highest VAD, will this allocation fit above it? */
659 HighestVpn = ((ULONG_PTR)MM_HIGHEST_VAD_ADDRESS + 1) / PAGE_SIZE;
660
661 /* Check for kernel mode table (memory areas) */
662 if (Table->Unused == 1)
663 {
664 HighestVpn = ALIGN_UP_BY((ULONG_PTR)(LONG_PTR)-1 >> PAGE_SHIFT, AlignmentVpn);
665 }
666
667 if (HighestVpn >= LowVpn + PageCount)
668 {
669 /* Yes! Use this VAD to store the allocation */
670 *PreviousVad = PreviousNode;
671 *Base = LowVpn << PAGE_SHIFT;
672 return TableInsertAsRight;
673 }
674
675 /* Nyet, there's no free address space for this allocation, so we'll fail */
676 return TableFoundNode;
677}
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
PMMADDRESS_NODE NTAPI MiGetNextNode(IN PMMADDRESS_NODE Node)
Definition: vadnode.c:549
#define BYTES_TO_PAGES(Size)

Referenced by MiInsertVadEx(), MiMapLockedPagesInUserSpace(), and MmFindGap().

◆ MiGetNextNode()

PMMADDRESS_NODE NTAPI MiGetNextNode ( IN PMMADDRESS_NODE  Node)

Definition at line 549 of file vadnode.c.

550{
552
553 /* Get the right child */
555 {
556 /* Get left-most child */
559 return Node;
560 }
561
563 ASSERT(Parent != NULL);
564 while (Parent != Node)
565 {
566 /* The parent should be a left child, return the real predecessor */
568 {
569 /* Return it */
570 return Parent;
571 }
572
573 /* Keep lopping until we find our parent */
574 Node = Parent;
576 }
577
578 /* Nothing found */
579 return NULL;
580}
#define RtlParentAvl
Definition: miavl.h:44
#define RtlIsLeftChildAvl
Definition: miavl.h:47

Referenced by MiFindEmptyAddressRangeInTree(), and MiQueryMemoryBasicInformation().

◆ MiGetPageProtection()

ULONG NTAPI MiGetPageProtection ( IN PMMPTE  PointerPte)

Definition at line 1355 of file virtual.c.

1356{
1357 MMPTE TempPte;
1358 PMMPFN Pfn;
1359 PEPROCESS CurrentProcess;
1360 PETHREAD CurrentThread;
1361 BOOLEAN WsSafe, WsShared;
1362 ULONG Protect;
1363 KIRQL OldIrql;
1364 PAGED_CODE();
1365
1366 /* Copy this PTE's contents */
1367 TempPte = *PointerPte;
1368
1369 /* Assure it's not totally zero */
1370 ASSERT(TempPte.u.Long);
1371
1372 /* Check for a special prototype format */
1373 if ((TempPte.u.Soft.Valid == 0) &&
1374 (TempPte.u.Soft.Prototype == 1))
1375 {
1376 /* Check if the prototype PTE is not yet pointing to a PTE */
1377 if (TempPte.u.Soft.PageFileHigh == MI_PTE_LOOKUP_NEEDED)
1378 {
1379 /* The prototype PTE contains the protection */
1380 return MmProtectToValue[TempPte.u.Soft.Protection];
1381 }
1382
1383 /* Get a pointer to the underlying shared PTE */
1384 PointerPte = MiProtoPteToPte(&TempPte);
1385
1386 /* Since the PTE we want to read can be paged out at any time, we need
1387 to release the working set lock first, so that it can be paged in */
1388 CurrentThread = PsGetCurrentThread();
1389 CurrentProcess = PsGetCurrentProcess();
1390 MiUnlockProcessWorkingSetForFault(CurrentProcess,
1391 CurrentThread,
1392 &WsSafe,
1393 &WsShared);
1394
1395 /* Now read the PTE value */
1396 TempPte = *PointerPte;
1397
1398 /* Check if that one is invalid */
1399 if (!TempPte.u.Hard.Valid)
1400 {
1401 /* We get the protection directly from this PTE */
1402 Protect = MmProtectToValue[TempPte.u.Soft.Protection];
1403 }
1404 else
1405 {
1406 /* The PTE is valid, so we might need to get the protection from
1407 the PFN. Lock the PFN database */
1408 OldIrql = MiAcquirePfnLock();
1409
1410 /* Check if the PDE is still valid */
1411 if (MiAddressToPte(PointerPte)->u.Hard.Valid == 0)
1412 {
1413 /* It's not, make it valid */
1415 }
1416
1417 /* Now it's safe to read the PTE value again */
1418 TempPte = *PointerPte;
1419 ASSERT(TempPte.u.Long != 0);
1420
1421 /* Check again if the PTE is invalid */
1422 if (!TempPte.u.Hard.Valid)
1423 {
1424 /* The PTE is not valid, so we can use it's protection field */
1425 Protect = MmProtectToValue[TempPte.u.Soft.Protection];
1426 }
1427 else
1428 {
1429 /* The PTE is valid, so we can find the protection in the
1430 OriginalPte field of the PFN */
1433 }
1434
1435 /* Release the PFN database */
1436 MiReleasePfnLock(OldIrql);
1437 }
1438
1439 /* Lock the working set again */
1440 MiLockProcessWorkingSetForFault(CurrentProcess,
1441 CurrentThread,
1442 WsSafe,
1443 WsShared);
1444
1445 return Protect;
1446 }
1447
1448 /* In the easy case of transition or demand zero PTE just return its protection */
1449 if (!TempPte.u.Hard.Valid) return MmProtectToValue[TempPte.u.Soft.Protection];
1450
1451 /* If we get here, the PTE is valid, so look up the page in PFN database */
1453 if (!Pfn->u3.e1.PrototypePte)
1454 {
1455 /* Return protection of the original pte */
1456 ASSERT(Pfn->u4.AweAllocation == 0);
1458 }
1459
1460 /* This is software PTE */
1461 DPRINT("Prototype PTE: %lx %p\n", TempPte.u.Hard.PageFrameNumber, Pfn);
1462 DPRINT("VA: %p\n", MiPteToAddress(&TempPte));
1463 DPRINT("Mask: %lx\n", TempPte.u.Soft.Protection);
1464 DPRINT("Mask2: %lx\n", Pfn->OriginalPte.u.Soft.Protection);
1465 return MmProtectToValue[TempPte.u.Soft.Protection];
1466}
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble * u
Definition: glfuncs.h:240
FORCEINLINE VOID MiUnlockProcessWorkingSetForFault(IN PEPROCESS Process, IN PETHREAD Thread, OUT PBOOLEAN Safe, OUT PBOOLEAN Shared)
Definition: miarm.h:1468
FORCEINLINE VOID MiLockProcessWorkingSetForFault(IN PEPROCESS Process, IN PETHREAD Thread, IN BOOLEAN Safe, IN BOOLEAN Shared)
Definition: miarm.h:1501
#define MI_PTE_LOOKUP_NEEDED
Definition: miarm.h:241
#define MiProtoPteToPte(x)
Definition: mm.h:316
ULONG NTAPI MiMakeSystemAddressValidPfn(IN PVOID VirtualAddress, IN KIRQL OldIrql)
Definition: virtual.c:235
const ULONG MmProtectToValue[32]
Definition: page.c:71
ULONG_PTR AweAllocation
Definition: mm.h:421
ULONG64 Protection
Definition: mmtypes.h:88
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID _In_ ULONG_PTR _In_ SIZE_T _Inout_opt_ PLARGE_INTEGER _Inout_ PSIZE_T _In_ SECTION_INHERIT _In_ ULONG _In_ ULONG Protect
Definition: zwfuncs.h:221

Referenced by MiProtectVirtualMemory(), MiQueryAddressState(), and NtAllocateVirtualMemory().

◆ MiGetPreviousNode()

PMMADDRESS_NODE NTAPI MiGetPreviousNode ( IN PMMADDRESS_NODE  Node)

Definition at line 513 of file vadnode.c.

514{
516
517 /* Get the left child */
519 {
520 /* Get right-most child */
523 return Node;
524 }
525
527 ASSERT(Parent != NULL);
528 while (Parent != Node)
529 {
530 /* The parent should be a right child, return the real predecessor */
532 {
533 /* Return it unless it's the root */
535 return Parent;
536 }
537
538 /* Keep lopping until we find our parent */
539 Node = Parent;
541 }
542
543 /* Nothing found */
544 return NULL;
545}
#define RtlIsRightChildAvl
Definition: miavl.h:48

Referenced by MiFindEmptyAddressRangeDownBasedTree(), and MiFindEmptyAddressRangeDownTree().

◆ MiIncrementPageTableReferences()

FORCEINLINE USHORT MiIncrementPageTableReferences ( IN PVOID  Address)

Definition at line 2466 of file miarm.h.

2467{
2468 PMMPDE PointerPde = MiAddressToPde(Address);
2469 PMMPFN Pfn;
2470
2471 /* We should not tinker with this one. */
2472 ASSERT(PointerPde != (PMMPDE)PXE_SELFMAP);
2473 DPRINT("Incrementing %p from %p\n", Address, _ReturnAddress());
2474
2475 /* Make sure we're locked */
2476 ASSERT(PsGetCurrentThread()->OwnsProcessWorkingSetExclusive);
2477
2478 /* If we're bumping refcount, then it must be valid! */
2479 ASSERT(PointerPde->u.Hard.Valid == 1);
2480
2481 /* This lies on the PFN */
2482 Pfn = MiGetPfnEntry(PFN_FROM_PDE(PointerPde));
2484
2485 ASSERT(Pfn->OriginalPte.u.