ReactOS 0.4.16-dev-570-g1868985
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 PTE_MAPPING_NONE   0x100
 
#define PTE_MAPPING_NOT_OWNED   0x101
 
#define PTE_MAPPING_EMPTY   0x102
 
#define PTE_MAPPING_RESERVED   0x103
 
#define PTE_MAPPING_ADDRESS_NOT_OWNED   0x104
 
#define PTE_MAPPING_ADDRESS_INVALID   0x105
 
#define PTE_UNMAPPING_ADDRESS_NOT_OWNED   0x108
 
#define PTE_MAPPING_ADDRESS_EMPTY   0x109
 
#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 286 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 174 of file miarm.h.

◆ MI_GET_NEXT_COLOR

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

Definition at line 246 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 247 of file miarm.h.

◆ MI_GET_PAGE_COLOR

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

Definition at line 245 of file miarm.h.

◆ MI_INITIAL_SESSION_IDS

#define MI_INITIAL_SESSION_IDS   64

Definition at line 221 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 191 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 197 of file miarm.h.

◆ MI_IS_PFN_DELETED

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

Definition at line 209 of file miarm.h.

◆ MI_IS_ROS_PFN

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

Definition at line 1116 of file miarm.h.

◆ MI_IS_SESSION_ADDRESS

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

Definition at line 185 of file miarm.h.

◆ MI_IS_SESSION_IMAGE_ADDRESS

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

Definition at line 182 of file miarm.h.

◆ MI_IS_SESSION_PTE

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

Definition at line 188 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 194 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 203 of file miarm.h.

◆ MI_PTE_LOOKUP_NEEDED

#define MI_PTE_LOOKUP_NEEDED   0xFFFFF

Definition at line 255 of file miarm.h.

◆ MI_SESSION_DATA_PAGES_MAXIMUM

#define MI_SESSION_DATA_PAGES_MAXIMUM   (MM_ALLOCATION_GRANULARITY / PAGE_SIZE)

Definition at line 261 of file miarm.h.

◆ MI_SESSION_TAG_PAGES_MAXIMUM

#define MI_SESSION_TAG_PAGES_MAXIMUM   (MM_ALLOCATION_GRANULARITY / PAGE_SIZE)

Definition at line 262 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 208 of file miarm.h.

◆ MI_SYSTEM_VIEW_BUCKET_SIZE

#define MI_SYSTEM_VIEW_BUCKET_SIZE   _64K

Definition at line 275 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 270 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 269 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 268 of file miarm.h.

◆ MM_READ_WRITE_ALLOWED

#define MM_READ_WRITE_ALLOWED   11

Definition at line 267 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 215 of file miarm.h.

◆ MM_SYSLDR_NO_IMPORTS

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

Definition at line 214 of file miarm.h.

◆ MM_SYSLDR_SINGLE_ENTRY

#define MM_SYSLDR_SINGLE_ENTRY   0x1

Definition at line 216 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 318 of file miarm.h.

◆ POOL_BILLED_PROCESS_INVALID

#define POOL_BILLED_PROCESS_INVALID   13

Definition at line 320 of file miarm.h.

◆ POOL_BLOCK_SIZE

#define POOL_BLOCK_SIZE   8

Definition at line 283 of file miarm.h.

◆ POOL_CORRUPTED_LIST

#define POOL_CORRUPTED_LIST   3

Definition at line 304 of file miarm.h.

◆ POOL_ENTRIES_NOT_ALIGNED_NEXT

#define POOL_ENTRIES_NOT_ALIGNED_NEXT   9

Definition at line 309 of file miarm.h.

◆ POOL_ENTRIES_NOT_ALIGNED_PREVIOUS

#define POOL_ENTRIES_NOT_ALIGNED_PREVIOUS   6

Definition at line 306 of file miarm.h.

◆ POOL_ENTRY_ALREADY_FREE

#define POOL_ENTRY_ALREADY_FREE   6

Definition at line 316 of file miarm.h.

◆ POOL_ENTRY_CORRUPTED

#define POOL_ENTRY_CORRUPTED   1

Definition at line 315 of file miarm.h.

◆ POOL_ENTRY_NOT_ALLOCATED

#define POOL_ENTRY_NOT_ALLOCATED   7

Definition at line 317 of file miarm.h.

◆ POOL_ENTRY_NOT_FOUND

#define POOL_ENTRY_NOT_FOUND   10

Definition at line 310 of file miarm.h.

◆ POOL_FLAG_CHECK_DEADLOCK

#define POOL_FLAG_CHECK_DEADLOCK   0x10

Definition at line 296 of file miarm.h.

◆ POOL_FLAG_CHECK_RESOURCES

#define POOL_FLAG_CHECK_RESOURCES   0x4

Definition at line 294 of file miarm.h.

◆ POOL_FLAG_CHECK_TIMERS

#define POOL_FLAG_CHECK_TIMERS   0x1

Definition at line 292 of file miarm.h.

◆ POOL_FLAG_CHECK_WORKERS

#define POOL_FLAG_CHECK_WORKERS   0x2

Definition at line 293 of file miarm.h.

◆ POOL_FLAG_CRASH_ON_FAILURE

#define POOL_FLAG_CRASH_ON_FAILURE   0x80

Definition at line 299 of file miarm.h.

◆ POOL_FLAG_DBGPRINT_ON_FAILURE

#define POOL_FLAG_DBGPRINT_ON_FAILURE   0x40

Definition at line 298 of file miarm.h.

◆ POOL_FLAG_SPECIAL_POOL

#define POOL_FLAG_SPECIAL_POOL   0x20

Definition at line 297 of file miarm.h.

◆ POOL_FLAG_VERIFIER

#define POOL_FLAG_VERIFIER   0x8

Definition at line 295 of file miarm.h.

◆ POOL_FREE_IRQL_INVALID

#define POOL_FREE_IRQL_INVALID   9

Definition at line 319 of file miarm.h.

◆ POOL_HEADER_IS_ZERO

#define POOL_HEADER_IS_ZERO   8

Definition at line 308 of file miarm.h.

◆ POOL_HEADER_NOT_ALIGNED

#define POOL_HEADER_NOT_ALIGNED   7

Definition at line 307 of file miarm.h.

◆ POOL_HEADER_SIZE_INVALID

#define POOL_HEADER_SIZE_INVALID   32

Definition at line 321 of file miarm.h.

◆ POOL_LISTS_PER_PAGE

#define POOL_LISTS_PER_PAGE   (PAGE_SIZE / POOL_BLOCK_SIZE)

Definition at line 285 of file miarm.h.

◆ POOL_MAX_ALLOC

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

Definition at line 287 of file miarm.h.

◆ POOL_SIZE_OR_INDEX_MISMATCH

#define POOL_SIZE_OR_INDEX_MISMATCH   5

Definition at line 305 of file miarm.h.

◆ PT_SIZE

#define PT_SIZE   (PTE_PER_PAGE * sizeof(MMPTE))

Definition at line 26 of file miarm.h.

◆ PTE_MAPPING_ADDRESS_EMPTY

#define PTE_MAPPING_ADDRESS_EMPTY   0x109

Definition at line 169 of file miarm.h.

◆ PTE_MAPPING_ADDRESS_INVALID

#define PTE_MAPPING_ADDRESS_INVALID   0x105

Definition at line 167 of file miarm.h.

◆ PTE_MAPPING_ADDRESS_NOT_OWNED

#define PTE_MAPPING_ADDRESS_NOT_OWNED   0x104

Definition at line 166 of file miarm.h.

◆ PTE_MAPPING_EMPTY

#define PTE_MAPPING_EMPTY   0x102

Definition at line 164 of file miarm.h.

◆ PTE_MAPPING_NONE

#define PTE_MAPPING_NONE   0x100

Definition at line 162 of file miarm.h.

◆ PTE_MAPPING_NOT_OWNED

#define PTE_MAPPING_NOT_OWNED   0x101

Definition at line 163 of file miarm.h.

◆ PTE_MAPPING_RESERVED

#define PTE_MAPPING_RESERVED   0x103

Definition at line 165 of file miarm.h.

◆ PTE_UNMAPPING_ADDRESS_NOT_OWNED

#define PTE_UNMAPPING_ADDRESS_NOT_OWNED   0x108

Definition at line 168 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 422 of file miarm.h.

423{
425 MiCached,
enum _MI_PFN_CACHE_ATTRIBUTE MI_PFN_CACHE_ATTRIBUTE
@ MiWriteCombined
Definition: miarm.h:426
@ MiCached
Definition: miarm.h:425
@ MiNotMapped
Definition: miarm.h:427
@ MiNonCached
Definition: miarm.h:424
enum _MI_PFN_CACHE_ATTRIBUTE * PMI_PFN_CACHE_ATTRIBUTE

◆ _MMSYSTEM_PTE_POOL_TYPE

Enumerator
SystemPteSpace 
NonPagedPoolExpansion 
MaximumPtePoolTypes 

Definition at line 415 of file miarm.h.

416{
@ SystemPteSpace
Definition: miarm.h:417
@ MaximumPtePoolTypes
Definition: miarm.h:419
@ NonPagedPoolExpansion
Definition: miarm.h:418
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:285
#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 1019 of file miarm.h.

1020{
1021 /* Zero out the PTE */
1022 ASSERT(PointerPte->u.Long != 0);
1023 PointerPte->u.Long = 0;
1024}

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 1570 of file miarm.h.

1572{
1573 PMMPTE ProtoPte;
1574
1575 /* Find the offset within the VAD's prototype PTEs */
1576 ProtoPte = Vad->FirstPrototypePte + (Vpn - Vad->StartingVpn);
1577 ASSERT(ProtoPte <= Vad->LastContiguousPte);
1578 return ProtoPte;
1579}

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 933 of file miarm.h.

934{
936 return ((PointerPte->u.Long & 0xFFFFFC01) != 0);
937}
union _MMPTE::@2341 u
ULONG_PTR Long
Definition: mmtypes.h:215

◆ MI_IS_PHYSICAL_ADDRESS()

FORCEINLINE BOOLEAN MI_IS_PHYSICAL_ADDRESS ( IN PVOID  Address)

Definition at line 959 of file miarm.h.

960{
961 PMMPDE PointerPde;
962
963 /* Large pages are never paged out, always physically resident */
964 PointerPde = MiAddressToPde(Address);
965 return ((PointerPde->u.Hard.LargePage) && (PointerPde->u.Hard.Valid));
966}
#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 675 of file miarm.h.

676{
677 return (WorkingSet != &MmSystemCacheWs) && !WorkingSet->Flags.SessionSpace;
678}
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 1127 of file miarm.h.

1128{
1129 return (Process->Vm.Flags.AcquiredUnsafe == TRUE);
1130}
_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 821 of file miarm.h.

825{
826 /* Check that we are not setting valid a page that should not be */
827 ASSERT(ProtectionMask & MM_PROTECT_ACCESS);
828 ASSERT((ProtectionMask & MM_GUARDPAGE) == 0);
829
830 /* Set the protection and page */
831 NewPte->u.Long = MiDetermineUserGlobalPteMask(MappingPte);
832 NewPte->u.Long |= MmProtectToPteMask[ProtectionMask];
833 NewPte->u.Hard.PageFrameNumber = PageFrameNumber;
834}
#define MM_GUARDPAGE
Definition: miarm.h:57
FORCEINLINE ULONG_PTR MiDetermineUserGlobalPteMask(IN PVOID PointerPte)
Definition: miarm.h:750
#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 787 of file miarm.h.

791{
792 /* Only valid for kernel, non-session PTEs */
793 ASSERT(MappingPte > MiHighestUserPte);
794 ASSERT(!MI_IS_SESSION_PTE(MappingPte));
795 ASSERT((MappingPte < (PMMPTE)PDE_BASE) || (MappingPte > (PMMPTE)PDE_TOP));
796
797 /* Check that we are not setting valid a page that should not be */
798 ASSERT(ProtectionMask & MM_PROTECT_ACCESS);
799 ASSERT((ProtectionMask & MM_GUARDPAGE) == 0);
800
801 /* Start fresh */
802 NewPte->u.Long = 0;
803
804 /* Set the protection and page */
805 NewPte->u.Hard.PageFrameNumber = PageFrameNumber;
806 NewPte->u.Long |= MmProtectToPteMask[ProtectionMask];
807
808 /* Make this valid & global */
809#ifdef _GLOBAL_PAGES_ARE_AWESOME_
811 NewPte->u.Hard.Global = 1;
812#endif
813 NewPte->u.Hard.Valid = 1;
814}
#define PDE_BASE
Definition: winldr.c:21
PMMPTE MiHighestUserPte
Definition: mminit.c:233
#define MI_IS_SESSION_PTE(Pte)
Definition: miarm.h:188
#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 841 of file miarm.h.

845{
846 /* Only valid for kernel, non-session PTEs */
847 ASSERT(MappingPte <= MiHighestUserPte);
848
849 /* Start fresh */
850 NewPte->u.Long = 0;
851
852 /* Check that we are not setting valid a page that should not be */
853 ASSERT(ProtectionMask & MM_PROTECT_ACCESS);
854 ASSERT((ProtectionMask & MM_GUARDPAGE) == 0);
855
856 NewPte->u.Hard.Valid = TRUE;
857 NewPte->u.Hard.Owner = TRUE;
858 NewPte->u.Hard.PageFrameNumber = PageFrameNumber;
859 NewPte->u.Long |= MmProtectToPteMask[ProtectionMask];
860}

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 868 of file miarm.h.

870{
872
873 /* Mark this as a prototype */
874 NewPte->u.Long = 0;
875 NewPte->u.Proto.Prototype = 1;
876
877 /*
878 * Prototype PTEs are only valid in paged pool by design, this little trick
879 * lets us only use 30 bits for the address of the PTE, as long as the area
880 * stays 1024MB At most.
881 */
883
884 /*
885 * 7 bits go in the "low" (but we assume the bottom 2 are zero)
886 * and the other 21 bits go in the "high"
887 */
888 NewPte->u.Proto.ProtoAddressLow = (Offset & 0x1FC) >> 2;
889 NewPte->u.Proto.ProtoAddressHigh = (Offset & 0x3FFFFE00) >> 9;
890}
#define ULONG_PTR
Definition: config.h:101
PVOID MmPagedPoolStart
Definition: miarm.h:588
_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 897 of file miarm.h.

899{
901
902 /* Mark this as a prototype */
903 NewPte->u.Long = 0;
904 NewPte->u.Subsect.Prototype = 1;
905
906 /*
907 * Segments are only valid either in nonpaged pool. We store the 20 bit
908 * difference either from the top or bottom of nonpaged pool, giving a
909 * maximum of 128MB to each delta, meaning nonpaged pool cannot exceed
910 * 256MB.
911 */
912 if ((ULONG_PTR)Segment < ((ULONG_PTR)MmSubsectionBase + (128 * _1MB)))
913 {
915 NewPte->u.Subsect.WhichPool = PagedPool;
916 }
917 else
918 {
920 NewPte->u.Subsect.WhichPool = NonPagedPool;
921 }
922
923 /*
924 * 4 bits go in the "low" (but we assume the bottom 3 are zero)
925 * and the other 20 bits go in the "high"
926 */
927 NewPte->u.Subsect.SubsectionAddressLow = (Offset & 0x78) >> 3;
928 NewPte->u.Subsect.SubsectionAddressHigh = (Offset & 0xFFFFF80) >> 7;
929}
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 943 of file miarm.h.

946{
947 NewPte->u.Long = 0;
948 NewPte->u.Trans.Transition = 1;
949 NewPte->u.Trans.Protection = Protection;
950 NewPte->u.Trans.PageFrameNumber = Page;
951}
_In_ PVOID _Out_opt_ BOOLEAN _Out_opt_ PPFN_NUMBER Page
Definition: mm.h:1313

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 991 of file miarm.h.

993{
994 /* Write the valid PTE */
995 ASSERT(PointerPte->u.Hard.Valid == 1);
996 ASSERT(TempPte.u.Hard.Valid == 1);
997 ASSERT(PointerPte->u.Hard.PageFrameNumber == TempPte.u.Hard.PageFrameNumber);
998 *PointerPte = TempPte;
999}
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 1048 of file miarm.h.

1050{
1051 /* Write the invalid PDE */
1052 ASSERT(InvalidPde.u.Hard.Valid == 0);
1053 ASSERT(InvalidPde.u.Long != 0);
1054#ifdef _M_AMD64
1055 ASSERT(InvalidPde.u.Soft.Protection == MM_EXECUTE_READWRITE);
1056#endif
1057 *PointerPde = InvalidPde;
1058}
#define MM_EXECUTE_READWRITE
Definition: miarm.h:49

Referenced by MmArmAccessFault().

◆ MI_WRITE_INVALID_PTE()

◆ MI_WRITE_VALID_PDE()

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

Definition at line 1031 of file miarm.h.

1033{
1034 /* Write the valid PDE */
1035 ASSERT(PointerPde->u.Hard.Valid == 0);
1036#ifdef _M_AMD64
1037 ASSERT(PointerPde->u.Hard.NoExecute == 0);
1038#endif
1039 ASSERT(TempPde.u.Hard.Valid == 1);
1040 *PointerPde = TempPde;
1041}
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 1090 of file miarm.h.

1091{
1092 /* Check if this process is the owner, and that the thread owns the WS */
1093 if (PsGetCurrentThread()->OwnsProcessWorkingSetExclusive == 0)
1094 {
1095 DPRINT("Thread: %p is not an owner\n", PsGetCurrentThread());
1096 }
1097 if (KeGetCurrentThread()->ApcState.Process != &Process->Pcb)
1098 {
1099 DPRINT("Current thread %p is attached to another process %p\n", PsGetCurrentThread(), Process);
1100 }
1101 return ((KeGetCurrentThread()->ApcState.Process == &Process->Pcb) &&
1102 ((PsGetCurrentThread()->OwnsProcessWorkingSetExclusive) ||
1103 (PsGetCurrentThread()->OwnsProcessWorkingSetShared)));
1104}
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
#define KeGetCurrentThread
Definition: hal.h:55
_Out_ PKAPC_STATE ApcState
Definition: mm.h:1772

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

◆ MiAcquireExpansionLock()

FORCEINLINE KIRQL MiAcquireExpansionLock ( VOID  )

Definition at line 1544 of file miarm.h.

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

500{
501 ULONG L2Associativity;
502
503 /* Check if no setting was provided already */
505 {
506 /* Get L2 cache information */
507 L2Associativity = KeGetPcr()->SecondLevelCacheAssociativity;
508
509 /* The number of colors is the number of cache bytes by set/way */
510 MmSecondaryColors = KeGetPcr()->SecondLevelCacheSize;
511 if (L2Associativity) MmSecondaryColors /= L2Associativity;
512 }
513
514 /* Now convert cache bytes into pages */
517 {
518 /* If there was no cache data from the KPCR, use the default colors */
520 }
521 else
522 {
523 /* Otherwise, make sure there aren't too many colors */
525 {
526 /* Set the maximum */
528 }
529
530 /* Make sure there aren't too little colors */
532 {
533 /* Set the default */
535 }
536
537 /* Finally make sure the colors are a power of two */
539 {
540 /* Set the default */
542 }
543 }
544
545 /* Compute the mask and store it */
547 KeGetCurrentPrcb()->SecondaryColorMask = MmSecondaryColorMask;
548}
ULONG MmSecondaryColorMask
Definition: mminit.c:257
ULONG MmSecondaryColors
Definition: mminit.c:256
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1179
#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 1441 of file miarm.h.

1444{
1445 /* Sanity check: No exclusive lock. */
1449
1450 /* And it should have one and only one shared lock */
1452
1453 /* Try. */
1454 if (!ExConvertPushLockSharedToExclusive(&Vm->WorkingSetMutex))
1455 return FALSE;
1456
1457 if (Vm == &MmSystemCacheWs)
1458 {
1462 }
1463 else if (Vm->Flags.SessionSpace)
1464 {
1468 }
1469 else
1470 {
1474 }
1475
1476 return TRUE;
1477}
#define FALSE
Definition: types.h:117
FORCEINLINE BOOLEAN ExConvertPushLockSharedToExclusive(IN PEX_PUSH_LOCK PushLock)
Definition: ex.h:1142
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
ULONG OwnsSessionWorkingSetExclusive
Definition: pstypes.h:1226
ULONG OwnsSessionWorkingSetShared
Definition: pstypes.h:1227
ULONG OwnsSystemWorkingSetShared
Definition: pstypes.h:1225
ULONG OwnsProcessWorkingSetShared
Definition: pstypes.h:1223
ULONG OwnsProcessWorkingSetExclusive
Definition: pstypes.h:1222
ULONG OwnsSystemWorkingSetExclusive
Definition: pstypes.h:1224

Referenced by MmWorkingSetManager().

◆ MiDecrementPageTableReferences()

FORCEINLINE USHORT MiDecrementPageTableReferences ( IN PVOID  Address)

Definition at line 2505 of file miarm.h.

2506{
2507 PMMPDE PointerPde = MiAddressToPde(Address);
2508 PMMPFN Pfn;
2509
2510 /* We should not tinker with this one. */
2511 ASSERT(PointerPde != (PMMPDE)PXE_SELFMAP);
2512
2513 DPRINT("Decrementing %p from %p\n", PointerPde, _ReturnAddress());
2514
2515 /* Make sure we're locked */
2516 ASSERT(PsGetCurrentThread()->OwnsProcessWorkingSetExclusive);
2517
2518 /* If we're decreasing refcount, then it must be valid! */
2519 ASSERT(PointerPde->u.Hard.Valid == 1);
2520
2521 /* This lies on the PFN */
2522 Pfn = MiGetPfnEntry(PFN_FROM_PDE(PointerPde));
2523
2526
2528
2530}
#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:414
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:1116
#define MI_IS_PFN_DELETED(x)
Definition: miarm.h:209
FORCEINLINE PMMPFN MI_PFN_ELEMENT(IN PFN_NUMBER Pfn)
Definition: miarm.h:1587
#define MI_ASSERT_PFN_LOCK_HELD()
Definition: mm.h:1050
VOID NTAPI MiInsertPageInFreeList(IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:611
VOID NTAPI MmDereferencePage(PFN_NUMBER Pfn)
Definition: freelist.c:566
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:1006
@ 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::@2615 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 2539 of file miarm.h.

2542{
2543 /* Only for user-mode ones */
2544 ASSERT(MiIsUserPde(PointerPde));
2545
2546 /* Kill this one as a PTE */
2547 MiDeletePte((PMMPTE)PointerPde, MiPdeToPte(PointerPde), CurrentProcess, NULL);
2548#if _MI_PAGING_LEVELS >= 3
2549 /* Cascade down */
2550 if (MiDecrementPageTableReferences(MiPdeToPte(PointerPde)) == 0)
2551 {
2552 MiDeletePte(MiPdeToPpe(PointerPde), PointerPde, CurrentProcess, NULL);
2553#if _MI_PAGING_LEVELS == 4
2554 if (MiDecrementPageTableReferences(PointerPde) == 0)
2555 {
2556 MiDeletePte(MiPdeToPxe(PointerPde), MiPdeToPpe(PointerPde), CurrentProcess, NULL);
2557 }
2558#endif
2559 }
2560#endif
2561}
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:2505
FORCEINLINE BOOLEAN MiIsUserPde(PVOID Address)
Definition: miarm.h:731
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:1078
FORCEINLINE VOID MI_ERASE_PTE(IN PMMPTE PointerPte)
Definition: miarm.h:1019
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:370
USHORT WriteInProgress
Definition: mm.h:369
PMMPTE PteAddress
Definition: mm.h:393
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:1278
FORCEINLINE VOID MiUnlockWorkingSet(IN PETHREAD Thread, IN PMMSUPPORT WorkingSet)
Definition: miarm.h:1364
VOID NTAPI KeFlushEntireTb(IN BOOLEAN Invalid, IN BOOLEAN AllProcessors)
Definition: cpu.c:652
MMSUPPORT MmSystemCacheWs
Definition: init.c:55
ULONG WsIndex
Definition: mm.h:385
union _MMPFN::@1805 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:1570
FORCEINLINE VOID MiDeletePde(_In_ PMMPDE PointerPde, _In_ PEPROCESS CurrentProcess)
Definition: miarm.h:2539
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:1300
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 1628 of file miarm.h.

1629{
1630 USHORT RefCount, OldRefCount;
1631 PFN_NUMBER PageFrameIndex;
1632
1633 /* Loop while we decrement the page successfully */
1634 do
1635 {
1636 /* There should be at least one reference */
1637 OldRefCount = Pfn1->u3.e2.ReferenceCount;
1638 ASSERT(OldRefCount != 0);
1639
1640 /* Are we the last one */
1641 if (OldRefCount == 1)
1642 {
1643 /* The page shoudln't be shared not active at this point */
1644 ASSERT(Pfn1->u3.e2.ReferenceCount == 1);
1645 ASSERT(Pfn1->u3.e1.PageLocation != ActiveAndValid);
1646 ASSERT(Pfn1->u2.ShareCount == 0);
1647
1648 /* Is it a prototype PTE? */
1649 if ((Pfn1->u3.e1.PrototypePte == 1) &&
1650 (Pfn1->OriginalPte.u.Soft.Prototype == 1))
1651 {
1652 /* FIXME: We should return commit */
1653 DPRINT1("Not returning commit for prototype PTE\n");
1654 }
1655
1656 /* Update the counter, and drop a reference the long way */
1658 PageFrameIndex = MiGetPfnEntryIndex(Pfn1);
1659 MiDecrementReferenceCount(Pfn1, PageFrameIndex);
1660 return;
1661 }
1662
1663 /* Drop a reference the short way, and that's it */
1664 RefCount = InterlockedCompareExchange16((PSHORT)&Pfn1->u3.e2.ReferenceCount,
1665 OldRefCount - 1,
1666 OldRefCount);
1667 ASSERT(RefCount != 0);
1668 } while (OldRefCount != RefCount);
1669
1670 /* If we got here, there should be more than one reference */
1671 ASSERT(RefCount > 1);
1672 if (RefCount == 2)
1673 {
1674 /* Is it still being shared? */
1675 if (Pfn1->u2.ShareCount >= 1)
1676 {
1677 /* Then it should be valid */
1678 ASSERT(Pfn1->u3.e1.PageLocation == ActiveAndValid);
1679
1680 /* Is it a prototype PTE? */
1681 if ((Pfn1->u3.e1.PrototypePte == 1) &&
1682 (Pfn1->OriginalPte.u.Soft.Prototype == 1))
1683 {
1684 /* We don't handle ethis */
1685 ASSERT(FALSE);
1686 }
1687
1688 /* Update the counter */
1690 }
1691 }
1692}
#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 750 of file miarm.h.

751{
753
754 /* Start fresh */
755 TempPte.u.Long = 0;
756
757 /* Make it valid and accessed */
758 TempPte.u.Hard.Valid = TRUE;
760
761 /* Is this for user-mode? */
762 if (
763#if (_MI_PAGING_LEVELS == 4)
764 MiIsUserPxe(PointerPte) ||
765#endif
766#if (_MI_PAGING_LEVELS >= 3)
767 MiIsUserPpe(PointerPte) ||
768#endif
769 MiIsUserPde(PointerPte) ||
770 MiIsUserPte(PointerPte))
771 {
772 /* Set the owner bit */
774 }
775
776 /* FIXME: We should also set the global bit */
777
778 /* Return the protection */
779 return TempPte.u.Long;
780}
FORCEINLINE BOOLEAN MiIsUserPte(PVOID Address)
Definition: miarm.h:739
#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 1598 of file miarm.h.

1599{
1600 /* This page shouldn't be locked, but it should be valid */
1601 ASSERT(Pfn1->u3.e2.ReferenceCount != 0);
1602 ASSERT(Pfn1->u2.ShareCount == 0);
1603
1604 /* Is this the last reference to the page */
1605 if (Pfn1->u3.e2.ReferenceCount == 1)
1606 {
1607 /* It better not be valid */
1608 ASSERT(Pfn1->u3.e1.PageLocation != ActiveAndValid);
1609
1610 /* Is it a prototype PTE? */
1611 if ((Pfn1->u3.e1.PrototypePte == 1) &&
1612 (Pfn1->OriginalPte.u.Soft.Prototype == 1))
1613 {
1614 /* FIXME: We should return commit */
1615 DPRINT1("Not returning commit for prototype PTE\n");
1616 }
1617
1618 /* Update the counter */
1620 }
1621}

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:345
PPHYSICAL_MEMORY_DESCRIPTOR MmPhysicalMemoryBlock
Definition: init.c:45
PHYSICAL_MEMORY_RUN Run[1]
Definition: miarm.h:440
PFN_NUMBER PageCount
Definition: miarm.h:433
PFN_NUMBER BasePage
Definition: miarm.h:432

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}
#define STATUS_NO_MEMORY
Definition: d3dkmdt.h:51
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
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:1481
FORCEINLINE VOID MiLockProcessWorkingSetForFault(IN PEPROCESS Process, IN PETHREAD Thread, IN BOOLEAN Safe, IN BOOLEAN Shared)
Definition: miarm.h:1514
#define MI_PTE_LOOKUP_NEEDED
Definition: miarm.h:255
#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:428
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(