ReactOS  r76032
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 PDE_MAPPED_VA   (PTE_COUNT * PAGE_SIZE)
 
#define PT_SIZE   (PTE_COUNT * sizeof(MMPTE))
 
#define PD_SIZE   (PDE_COUNT * sizeof(MMPDE))
 
#define PD_COUNT   PPE_PER_PAGE
 
#define PDE_COUNT   PDE_PER_PAGE
 
#define PTE_COUNT   PTE_PER_PAGE
 
#define SYSTEM_PD_SIZE   (PD_COUNT * 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 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)0xFFFFFFFE
 
#define MM_SYSLDR_BOOT_LOADED   (PVOID)0xFFFFFFFF
 
#define MM_SYSLDR_SINGLE_ENTRY   0x1
 
#define MI_INITIAL_SESSION_IDS   64
 
#define MM_NOIRQL   (KIRQL)0xFFFFFFFF
 
#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_TABLE
PPOOL_TRACKER_TABLE
 
typedef struct
_POOL_TRACKER_BIG_PAGES 
POOL_TRACKER_BIG_PAGES
 
typedef struct
_POOL_TRACKER_BIG_PAGES
PPOOL_TRACKER_BIG_PAGES
 
typedef struct
_MI_LARGE_PAGE_DRIVER_ENTRY 
MI_LARGE_PAGE_DRIVER_ENTRY
 
typedef struct
_MI_LARGE_PAGE_DRIVER_ENTRY
PMI_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_ATTRIBUTE
PMI_PFN_CACHE_ATTRIBUTE
 
typedef struct _PHYSICAL_MEMORY_RUN PHYSICAL_MEMORY_RUN
 
typedef struct
_PHYSICAL_MEMORY_RUN
PPHYSICAL_MEMORY_RUN
 
typedef struct
_PHYSICAL_MEMORY_DESCRIPTOR 
PHYSICAL_MEMORY_DESCRIPTOR
 
typedef struct
_PHYSICAL_MEMORY_DESCRIPTOR
PPHYSICAL_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_RANGES
PMI_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 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 MI_WS_OWNER (IN PEPROCESS Process)
 
FORCEINLINE BOOLEAN MiIsRosSectionObject (IN PVOID 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 MiUnlockWorkingSet (IN PETHREAD Thread, IN PMMSUPPORT WorkingSet)
 
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)
 
FORCEINLINE VOID MiIncrementPageTableReferences (IN PVOID Address)
 
FORCEINLINE VOID MiDecrementPageTableReferences (IN PVOID Address)
 
FORCEINLINE USHORT MiQueryPageTableReferences (IN PVOID Address)
 
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 BOOLEAN StoreInstruction, IN PVOID Address, IN KPROCESSOR_MODE Mode, IN PVOID TrapInformation)
 
NTSTATUS FASTCALL MiCheckPdeForPagedPool (IN PVOID Address)
 
VOID NTAPI MiInitializeNonPagedPool (VOID)
 
VOID NTAPI MiInitializeNonPagedPoolThresholds (VOID)
 
VOID NTAPI MiInitializePoolEvents (VOID)
 
VOID NTAPI InitializePool (IN POOL_TYPE PoolType, IN ULONG Threshold)
 
VOID NTAPI INIT_FUNCTION 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 MiUnmapViewOfSection (IN PEPROCESS Process, IN PVOID BaseAddress, IN ULONG Flags)
 
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)
 
NTSTATUS NTAPI MiSessionCommitPageTables (IN PVOID StartVa, IN PVOID EndVa)
 
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)
 
POOL_TYPE NTAPI MmDeterminePoolType (IN PVOID PoolAddress)
 
VOID NTAPI MiMakePdeExistAndMakeValid (IN PMMPDE PointerPde, IN PEPROCESS TargetProcess, IN KIRQL OldIrql)
 
FORCEINLINE PFN_NUMBER MiRemoveZeroPageSafe (IN ULONG Color)
 

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
 
RTL_BITMAP MiPfnBitMap
 
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 MmResidentAvailablePages
 
PFN_NUMBER MmResidentAvailableAtInit
 
ULONG MmTotalFreeSystemPtes [MaximumPtePoolTypes]
 
PFN_NUMBER MmTotalSystemDriverPages
 
ULONG MmCritsectTimeoutSeconds
 
PVOID MiSessionImageStart
 
PVOID MiSessionImageEnd
 
PMMPTE MiHighestUserPte
 
PMMPDE MiHighestUserPde
 
PFN_NUMBER MmSystemPageDirectory [PD_COUNT]
 
PMMPTE MmSharedUserDataPte
 
LIST_ENTRY MmProcessList
 
BOOLEAN MmZeroingPageThreadActive
 
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

#define _1GB   (1024 * _1MB)

Definition at line 14 of file miarm.h.

Referenced by MiInitializeNonPagedPool(), and MmArmInitSystem().

#define _1KB   (1024u)

Definition at line 12 of file miarm.h.

Referenced by FsRtlTest_StartTest(), and MmArmInitSystem().

#define BASE_POOL_TYPE_MASK   1

Definition at line 249 of file miarm.h.

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

Definition at line 208 of file miarm.h.

Referenced by MmZeroPageThread().

#define MI_INITIAL_SESSION_IDS   64

Definition at line 179 of file miarm.h.

Referenced by MiInitializeSessionIds().

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

Definition at line 144 of file miarm.h.

Referenced by MiCheckVirtualAddress(), and MiResolveDemandZeroFault().

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

Definition at line 150 of file miarm.h.

Referenced by MmArmAccessFault().

#define MI_IS_PFN_DELETED (   x)    ((ULONG_PTR)((x)->PteAddress) & 1)
#define MI_IS_ROS_PFN (   x)    ((x)->u4.AweAllocation == TRUE)
#define MI_IS_SESSION_IMAGE_ADDRESS (   Address)    (((Address) >= MiSessionImageStart) && ((Address) < MiSessionImageEnd))
#define MI_IS_SESSION_PTE (   Pte)    ((((PMMPTE)Pte) >= MiSessionBasePte) && (((PMMPTE)Pte) < MiSessionLastPte))

Definition at line 141 of file miarm.h.

Referenced by MI_MAKE_HARDWARE_PTE_KERNEL(), and MmArmAccessFault().

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

Definition at line 147 of file miarm.h.

Referenced by MmArmAccessFault().

#define MI_MAKE_SOFTWARE_PTE (   p,
  x 
)    ((p)->u.Long = (x << MM_PTE_SOFTWARE_PROTECTION_BITS))
#define MI_SESSION_DATA_PAGES_MAXIMUM   (MM_ALLOCATION_GRANULARITY / PAGE_SIZE)
#define MI_SESSION_TAG_PAGES_MAXIMUM   (MM_ALLOCATION_GRANULARITY / PAGE_SIZE)

Definition at line 225 of file miarm.h.

Referenced by MiInitializeSessionIds(), and MiSessionCreateInternal().

#define MI_SYSTEM_VIEW_BUCKET_SIZE   _64K
#define MM_DELETE_CHECK   85

Definition at line 233 of file miarm.h.

Referenced by MiCheckSecuredVad(), and MiUnmapViewOfSection().

#define MM_EXECUTE   2

Definition at line 47 of file miarm.h.

Referenced by MiComputeDriverProtection().

#define MM_EXECUTE_READ   3

Definition at line 48 of file miarm.h.

#define MM_EXECUTE_READWRITE   6

Definition at line 51 of file miarm.h.

Referenced by MiComputeDriverProtection().

#define MM_EXECUTE_WRITECOPY   7

Definition at line 52 of file miarm.h.

#define MM_GUARDPAGE   0x10

Definition at line 59 of file miarm.h.

Referenced by MiAccessCheck(), MiMakeProtectionMask(), and MmArmAccessFault().

#define MM_INVALID_PROTECTION   0xFFFFFFFF
#define MM_NO_ACCESS_ALLOWED   01

Definition at line 232 of file miarm.h.

#define MM_NOCACHE   0x08

Definition at line 58 of file miarm.h.

Referenced by MiFlushTbAndCapture(), and MiMakeProtectionMask().

#define MM_OUTSWAPPED_KSTACK   (MM_EXECUTE_WRITECOPY | MM_WRITECOMBINE)

Definition at line 68 of file miarm.h.

#define MM_PROTECT_ACCESS   7

Definition at line 53 of file miarm.h.

Referenced by MiIsAccessAllowed().

#define MM_PROTECT_SPECIAL   0x18

Definition at line 61 of file miarm.h.

Referenced by MiAccessCheck(), MiCompleteProtoPteFault(), and MmArmAccessFault().

#define MM_READ_ONLY_ALLOWED   10

Definition at line 231 of file miarm.h.

#define MM_READ_WRITE_ALLOWED   11

Definition at line 230 of file miarm.h.

Referenced by MiCheckSecuredVad().

#define MM_SYSLDR_BOOT_LOADED   (PVOID)0xFFFFFFFF
#define MM_SYSLDR_NO_IMPORTS   (PVOID)0xFFFFFFFE
#define MM_SYSLDR_SINGLE_ENTRY   0x1
#define MM_WRITECOMBINE   0x18

Definition at line 60 of file miarm.h.

#define MM_WRITECOPY   5

Definition at line 50 of file miarm.h.

Referenced by MiCompleteProtoPteFault(), and MiResolveProtoPteFault().

#define MM_ZERO_ACCESS   0

Definition at line 45 of file miarm.h.

Referenced by MiCompleteProtoPteFault(), MiComputeDriverProtection(), and MmArmAccessFault().

#define PD_COUNT   PPE_PER_PAGE

Definition at line 29 of file miarm.h.

Referenced by MiBuildPagedPool(), and MiBuildPfnDatabaseFromPages().

#define PD_SIZE   (PDE_COUNT * sizeof(MMPDE))

Definition at line 26 of file miarm.h.

Referenced by MiSegmentDelete().

#define POOL_ALLOC_IRQL_INVALID   8

Definition at line 281 of file miarm.h.

Referenced by ExpCheckPoolIrqlLevel().

#define POOL_BILLED_PROCESS_INVALID   13

Definition at line 283 of file miarm.h.

#define POOL_BLOCK_SIZE   8
#define POOL_CORRUPTED_LIST   3

Definition at line 267 of file miarm.h.

#define POOL_ENTRIES_NOT_ALIGNED_NEXT   9

Definition at line 272 of file miarm.h.

#define POOL_ENTRIES_NOT_ALIGNED_PREVIOUS   6

Definition at line 269 of file miarm.h.

#define POOL_ENTRY_ALREADY_FREE   6

Definition at line 279 of file miarm.h.

#define POOL_ENTRY_CORRUPTED   1

Definition at line 278 of file miarm.h.

#define POOL_ENTRY_NOT_ALLOCATED   7

Definition at line 280 of file miarm.h.

#define POOL_ENTRY_NOT_FOUND   10

Definition at line 273 of file miarm.h.

#define POOL_FLAG_CHECK_DEADLOCK   0x10

Definition at line 259 of file miarm.h.

Referenced by ExFreePoolWithTag().

#define POOL_FLAG_CHECK_RESOURCES   0x4

Definition at line 257 of file miarm.h.

Referenced by ExFreePoolWithTag().

#define POOL_FLAG_CHECK_TIMERS   0x1

Definition at line 255 of file miarm.h.

Referenced by ExFreePoolWithTag().

#define POOL_FLAG_CHECK_WORKERS   0x2

Definition at line 256 of file miarm.h.

Referenced by ExFreePoolWithTag().

#define POOL_FLAG_CRASH_ON_FAILURE   0x80

Definition at line 262 of file miarm.h.

Referenced by ExAllocatePoolWithTag().

#define POOL_FLAG_DBGPRINT_ON_FAILURE   0x40

Definition at line 261 of file miarm.h.

Referenced by ExAllocatePoolWithTag().

#define POOL_FLAG_SPECIAL_POOL   0x20
#define POOL_FLAG_VERIFIER   0x8

Definition at line 258 of file miarm.h.

Referenced by ExAllocatePoolWithTag(), and ExFreePoolWithTag().

#define POOL_FREE_IRQL_INVALID   9

Definition at line 282 of file miarm.h.

Referenced by ExpCheckPoolIrqlLevel().

#define POOL_HEADER_IS_ZERO   8

Definition at line 271 of file miarm.h.

#define POOL_HEADER_NOT_ALIGNED   7

Definition at line 270 of file miarm.h.

#define POOL_HEADER_SIZE_INVALID   32

Definition at line 284 of file miarm.h.

#define POOL_LISTS_PER_PAGE   (PAGE_SIZE / POOL_BLOCK_SIZE)

Definition at line 248 of file miarm.h.

Referenced by ExAllocatePoolWithTag(), and ExInitializePoolDescriptor().

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

Definition at line 250 of file miarm.h.

Referenced by ExAllocatePoolWithTag().

#define POOL_SIZE_OR_INDEX_MISMATCH   5

Definition at line 268 of file miarm.h.

#define PT_SIZE   (PTE_COUNT * sizeof(MMPTE))

Definition at line 23 of file miarm.h.

Typedef Documentation

typedef struct _MMVIEW * PMMVIEW

Enumeration Type Documentation

Enumerator
MiNonCached 
MiCached 
MiWriteCombined 
MiNotMapped 

Definition at line 385 of file miarm.h.

386 {
387  MiNonCached,
388  MiCached,
enum _MI_PFN_CACHE_ATTRIBUTE MI_PFN_CACHE_ATTRIBUTE
enum _MI_PFN_CACHE_ATTRIBUTE * PMI_PFN_CACHE_ATTRIBUTE
Enumerator
SystemPteSpace 
NonPagedPoolExpansion 
MaximumPtePoolTypes 

Definition at line 378 of file miarm.h.

379 {
enum _MMSYSTEM_PTE_POOL_TYPE MMSYSTEM_PTE_POOL_TYPE

Function Documentation

C_ASSERT ( sizeof(POOL_HEADER = =POOL_BLOCK_SIZE)
C_ASSERT ( POOL_BLOCK_SIZE  = =sizeof(LIST_ENTRY))
VOID NTAPI INIT_FUNCTION ExInitializePoolDescriptor ( IN PPOOL_DESCRIPTOR  PoolDescriptor,
IN POOL_TYPE  PoolType,
IN ULONG  PoolIndex,
IN ULONG  Threshold,
IN PVOID  PoolLock 
)

Definition at line 798 of file expool.c.

Referenced by InitializePool(), and MiInitializeSessionPool().

803 {
804  PLIST_ENTRY NextEntry, LastEntry;
805 
806  //
807  // Setup the descriptor based on the caller's request
808  //
809  PoolDescriptor->PoolType = PoolType;
810  PoolDescriptor->PoolIndex = PoolIndex;
811  PoolDescriptor->Threshold = Threshold;
812  PoolDescriptor->LockAddress = PoolLock;
813 
814  //
815  // Initialize accounting data
816  //
817  PoolDescriptor->RunningAllocs = 0;
818  PoolDescriptor->RunningDeAllocs = 0;
819  PoolDescriptor->TotalPages = 0;
820  PoolDescriptor->TotalBytes = 0;
821  PoolDescriptor->TotalBigPages = 0;
822 
823  //
824  // Nothing pending for now
825  //
826  PoolDescriptor->PendingFrees = NULL;
827  PoolDescriptor->PendingFreeDepth = 0;
828 
829  //
830  // Loop all the descriptor's allocation lists and initialize them
831  //
832  NextEntry = PoolDescriptor->ListHeads;
833  LastEntry = NextEntry + POOL_LISTS_PER_PAGE;
834  while (NextEntry < LastEntry)
835  {
836  ExpInitializePoolListHead(NextEntry);
837  NextEntry++;
838  }
839 
840  //
841  // Note that ReactOS does not support Session Pool Yet
842  //
844 }
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
VOID NTAPI ExpInitializePoolListHead(IN PLIST_ENTRY ListHead)
Definition: expool.c:104
smooth NULL
Definition: ftsmooth.c:557
IN REFCLSID IN PUNKNOWN IN POOL_TYPE PoolType
Definition: unknown.h:68
Definition: typedefs.h:117
#define POOL_LISTS_PER_PAGE
Definition: miarm.h:248
VOID NTAPI InitializePool ( IN POOL_TYPE  PoolType,
IN ULONG  Threshold 
)

Definition at line 849 of file expool.c.

Referenced by MiBuildPagedPool(), and MiInitMachineDependent().

851 {
854  ULONG i;
855 
856  //
857  // Check what kind of pool this is
858  //
859  if (PoolType == NonPagedPool)
860  {
861  //
862  // Compute the track table size and convert it from a power of two to an
863  // actual byte size
864  //
865  // NOTE: On checked builds, we'll assert if the registry table size was
866  // invalid, while on retail builds we'll just break out of the loop at
867  // that point.
868  //
870  for (i = 0; i < 32; i++)
871  {
872  if (TableSize & 1)
873  {
874  ASSERT((TableSize & ~1) == 0);
875  if (!(TableSize & ~1)) break;
876  }
877  TableSize >>= 1;
878  }
879 
880  //
881  // If we hit bit 32, than no size was defined in the registry, so
882  // we'll use the default size of 2048 entries.
883  //
884  // Otherwise, use the size from the registry, as long as it's not
885  // smaller than 64 entries.
886  //
887  if (i == 32)
888  {
889  PoolTrackTableSize = 2048;
890  }
891  else
892  {
893  PoolTrackTableSize = max(1 << i, 64);
894  }
895 
896  //
897  // Loop trying with the biggest specified size first, and cut it down
898  // by a power of two each iteration in case not enough memory exist
899  //
900  while (TRUE)
901  {
902  //
903  // Do not allow overflow
904  //
905  if ((PoolTrackTableSize + 1) > (MAXULONG_PTR / sizeof(POOL_TRACKER_TABLE)))
906  {
907  PoolTrackTableSize >>= 1;
908  continue;
909  }
910 
911  //
912  // Allocate the tracker table and exit the loop if this worked
913  //
915  (PoolTrackTableSize + 1) *
916  sizeof(POOL_TRACKER_TABLE));
917  if (PoolTrackTable) break;
918 
919  //
920  // Otherwise, as long as we're not down to the last bit, keep
921  // iterating
922  //
923  if (PoolTrackTableSize == 1)
924  {
925  KeBugCheckEx(MUST_SUCCEED_POOL_EMPTY,
926  TableSize,
927  0xFFFFFFFF,
928  0xFFFFFFFF,
929  0xFFFFFFFF);
930  }
931  PoolTrackTableSize >>= 1;
932  }
933 
934  //
935  // Add one entry, compute the hash, and zero the table
936  //
939 
942 
943  //
944  // Finally, add the most used tags to speed up those allocations
945  //
946  ExpSeedHotTags();
947 
948  //
949  // We now do the exact same thing with the tracker table for big pages
950  //
952  for (i = 0; i < 32; i++)
953  {
954  if (TableSize & 1)
955  {
956  ASSERT((TableSize & ~1) == 0);
957  if (!(TableSize & ~1)) break;
958  }
959  TableSize >>= 1;
960  }
961 
962  //
963  // For big pages, the default tracker table is 4096 entries, while the
964  // minimum is still 64
965  //
966  if (i == 32)
967  {
968  PoolBigPageTableSize = 4096;
969  }
970  else
971  {
972  PoolBigPageTableSize = max(1 << i, 64);
973  }
974 
975  //
976  // Again, run the exact same loop we ran earlier, but this time for the
977  // big pool tracker instead
978  //
979  while (TRUE)
980  {
982  {
983  PoolBigPageTableSize >>= 1;
984  continue;
985  }
986 
989  sizeof(POOL_TRACKER_BIG_PAGES));
990  if (PoolBigPageTable) break;
991 
992  if (PoolBigPageTableSize == 1)
993  {
994  KeBugCheckEx(MUST_SUCCEED_POOL_EMPTY,
995  TableSize,
996  0xFFFFFFFF,
997  0xFFFFFFFF,
998  0xFFFFFFFF);
999  }
1000 
1001  PoolBigPageTableSize >>= 1;
1002  }
1003 
1004  //
1005  // An extra entry is not needed for for the big pool tracker, so just
1006  // compute the hash and zero it
1007  //
1011  for (i = 0; i < PoolBigPageTableSize; i++) PoolBigPageTable[i].Va = (PVOID)1;
1012 
1013  //
1014  // During development, print this out so we can see what's happening
1015  //
1016  DPRINT("EXPOOL: Pool Tracker Table at: 0x%p with 0x%lx bytes\n",
1018  DPRINT("EXPOOL: Big Pool Tracker Table at: 0x%p with 0x%lx bytes\n",
1019  PoolBigPageTable, PoolBigPageTableSize * sizeof(POOL_TRACKER_BIG_PAGES));
1020 
1021  //
1022  // Insert the generic tracker for all of big pool
1023  //
1024  ExpInsertPoolTracker('looP',
1025  ROUND_TO_PAGES(PoolBigPageTableSize *
1026  sizeof(POOL_TRACKER_BIG_PAGES)),
1027  NonPagedPool);
1028 
1029  //
1030  // No support for NUMA systems at this time
1031  //
1032  ASSERT(KeNumberNodes == 1);
1033 
1034  //
1035  // Initialize the tag spinlock
1036  //
1038 
1039  //
1040  // Initialize the nonpaged pool descriptor
1041  //
1044  NonPagedPool,
1045  0,
1046  Threshold,
1047  NULL);
1048  }
1049  else
1050  {
1051  //
1052  // No support for NUMA systems at this time
1053  //
1054  ASSERT(KeNumberNodes == 1);
1055 
1056  //
1057  // Allocate the pool descriptor
1058  //
1059  Descriptor = ExAllocatePoolWithTag(NonPagedPool,
1060  sizeof(KGUARDED_MUTEX) +
1061  sizeof(POOL_DESCRIPTOR),
1062  'looP');
1063  if (!Descriptor)
1064  {
1065  //
1066  // This is really bad...
1067  //
1068  KeBugCheckEx(MUST_SUCCEED_POOL_EMPTY,
1069  0,
1070  -1,
1071  -1,
1072  -1);
1073  }
1074 
1075  //
1076  // Setup the vector and guarded mutex for paged pool
1077  //
1079  ExpPagedPoolMutex = (PKGUARDED_MUTEX)(Descriptor + 1);
1082  ExInitializePoolDescriptor(Descriptor,
1083  PagedPool,
1084  0,
1085  Threshold,
1087 
1088  //
1089  // Insert the generic tracker for all of nonpaged pool
1090  //
1091  ExpInsertPoolTracker('looP',
1093  NonPagedPool);
1094  }
1095 }
DWORD *typedef PVOID
Definition: winlogon.h:52
PVOID NTAPI ExAllocatePoolWithTag(IN POOL_TYPE PoolType, IN SIZE_T NumberOfBytes, IN ULONG Tag)
Definition: expool.c:1566
#define max(a, b)
Definition: svc.c:63
#define TRUE
Definition: types.h:120
SIZE_T PoolTrackTableMask
Definition: expool.c:38
struct _KGUARDED_MUTEX * PKGUARDED_MUTEX
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
SIZE_T PoolTrackTableSize
Definition: expool.c:38
#define MAXULONG_PTR
Definition: basetsd.h:102
PKGUARDED_MUTEX ExpPagedPoolMutex
Definition: expool.c:37
GLenum GLclampf GLint i
Definition: glfuncs.h:14
PPOOL_DESCRIPTOR PoolVector[2]
Definition: expool.c:36
SIZE_T PoolBigPageTableSize
Definition: expool.c:39
FORCEINLINE VOID KeInitializeSpinLock(_Out_ PKSPIN_LOCK SpinLock)
Definition: kefuncs.h:251
smooth NULL
Definition: ftsmooth.c:557
void DPRINT(...)
Definition: polytest.cpp:61
PPOOL_TRACKER_TABLE PoolTrackTable
Definition: expool.c:40
PPOOL_DESCRIPTOR ExpPagedPoolDescriptor[16+1]
Definition: expool.c:35
VOID NTAPI INIT_SECTION ExpSeedHotTags(VOID)
Definition: expool.c:468
POOL_DESCRIPTOR NonPagedPoolDescriptor
Definition: expool.c:34
PVOID NTAPI MiAllocatePoolPages(IN POOL_TYPE PoolType, IN SIZE_T SizeInBytes)
Definition: pool.c:420
IN REFCLSID IN PUNKNOWN IN POOL_TYPE PoolType
Definition: unknown.h:68
UCHAR KeNumberNodes
Definition: krnlinit.c:40
ULONG_PTR SIZE_T
Definition: typedefs.h:78
VOID NTAPI INIT_SECTION ExInitializePoolDescriptor(IN PPOOL_DESCRIPTOR PoolDescriptor, IN POOL_TYPE PoolType, IN ULONG PoolIndex, IN ULONG Threshold, IN PVOID PoolLock)
Definition: expool.c:798
VOID FASTCALL KeInitializeGuardedMutex(OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:31
#define ROUND_TO_PAGES(Size)
VOID NTAPI ExpInsertPoolTracker(IN ULONG Key, IN SIZE_T NumberOfBytes, IN POOL_TYPE PoolType)
Definition: expool.c:679
#define min(a, b)
Definition: monoChain.cc:55
PPOOL_TRACKER_BIG_PAGES PoolBigPageTable
Definition: expool.c:41
SIZE_T PoolBigPageTableHash
Definition: expool.c:39
_Must_inspect_result_ typedef _Out_ PULONG TableSize
Definition: iotypes.h:3938
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
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:90
KSPIN_LOCK ExpTaggedPoolLock
Definition: expool.c:42
_In_ PSTORAGE_PROPERTY_ID _Outptr_ PSTORAGE_DESCRIPTOR_HEADER * Descriptor
Definition: classpnp.h:966
FORCEINLINE VOID MI_ERASE_PTE ( IN PMMPTE  PointerPte)

Definition at line 957 of file miarm.h.

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

958 {
959  /* Zero out the PTE */
960  ASSERT(PointerPte->u.Long != 0);
961  PointerPte->u.Long = 0;
962 }
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
FORCEINLINE PMMPTE MI_GET_PROTOTYPE_PTE_FOR_VPN ( IN PMMVAD  Vad,
IN ULONG_PTR  Vpn 
)

Definition at line 1374 of file miarm.h.

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

1376 {
1377  PMMPTE ProtoPte;
1378 
1379  /* Find the offset within the VAD's prototype PTEs */
1380  ProtoPte = Vad->FirstPrototypePte + (Vpn - Vad->StartingVpn);
1381  ASSERT(ProtoPte <= Vad->LastContiguousPte);
1382  return ProtoPte;
1383 }
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
FORCEINLINE BOOLEAN MI_IS_MAPPED_PTE ( PMMPTE  PointerPte)
Todo:
Make this reasonable code, this is UGLY!

Definition at line 874 of file miarm.h.

875 {
877  return ((PointerPte->u.Long & 0xFFFFFC01) != 0);
878 }
ULONG_PTR Long
Definition: mmtypes.h:215
union _MMPTE::@2072 u
FORCEINLINE BOOLEAN MI_IS_PHYSICAL_ADDRESS ( IN PVOID  Address)

Definition at line 900 of file miarm.h.

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

901 {
902  PMMPDE PointerPde;
903 
904  /* Large pages are never paged out, always physically resident */
905  PointerPde = MiAddressToPde(Address);
906  return ((PointerPde->u.Hard.LargePage) && (PointerPde->u.Hard.Valid));
907 }
PVOID ULONG Address
Definition: oprghdlr.h:14
#define MiAddressToPde(x)
Definition: mmx86.c:20
ULONG64 Valid
Definition: mmtypes.h:150
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217
ULONG64 LargePage
Definition: mmtypes.h:165
union _MMPTE::@2072 u
FORCEINLINE BOOLEAN MI_IS_WS_UNSAFE ( IN PEPROCESS  Process)

Definition at line 1052 of file miarm.h.

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

1053 {
1054  return (Process->Vm.Flags.AcquiredUnsafe == TRUE);
1055 }
#define TRUE
Definition: types.h:120
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
FORCEINLINE VOID MI_MAKE_HARDWARE_PTE ( IN PMMPTE  NewPte,
IN PMMPTE  MappingPte,
IN ULONG_PTR  ProtectionMask,
IN PFN_NUMBER  PageFrameNumber 
)

Definition at line 769 of file miarm.h.

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

773 {
774  /* Set the protection and page */
775  NewPte->u.Long = MiDetermineUserGlobalPteMask(MappingPte);
776  NewPte->u.Long |= MmProtectToPteMask[ProtectionMask];
777  NewPte->u.Hard.PageFrameNumber = PageFrameNumber;
778 }
const ULONG_PTR MmProtectToPteMask[32]
Definition: page.c:32
FORCEINLINE ULONG_PTR MiDetermineUserGlobalPteMask(IN PVOID PointerPte)
Definition: miarm.h:709
FORCEINLINE VOID MI_MAKE_HARDWARE_PTE_KERNEL ( IN PMMPTE  NewPte,
IN PMMPTE  MappingPte,
IN ULONG_PTR  ProtectionMask,
IN PFN_NUMBER  PageFrameNumber 
)

Definition at line 746 of file miarm.h.

Referenced by MiInitializeWorkingSetList(), MmCreateKernelStack(), MmGrowKernelStackEx(), and MmInitSystem().

750 {
751  /* Only valid for kernel, non-session PTEs */
752  ASSERT(MappingPte > MiHighestUserPte);
753  ASSERT(!MI_IS_SESSION_PTE(MappingPte));
754  ASSERT((MappingPte < (PMMPTE)PDE_BASE) || (MappingPte > (PMMPTE)PDE_TOP));
755 
756  /* Start fresh */
757  *NewPte = ValidKernelPte;
758 
759  /* Set the protection and page */
760  NewPte->u.Hard.PageFrameNumber = PageFrameNumber;
761  NewPte->u.Long |= MmProtectToPteMask[ProtectionMask];
762 }
MMPTE ValidKernelPte
Definition: init.c:31
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
#define PDE_BASE
Definition: winldr.c:20
const ULONG_PTR MmProtectToPteMask[32]
Definition: page.c:32
#define MI_IS_SESSION_PTE(Pte)
Definition: miarm.h:141
#define PDE_TOP
Definition: mm.h:30
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217
ULONG64 PageFrameNumber
Definition: mmtypes.h:171
union _MMPTE::@2072 u
PMMPTE MiHighestUserPte
Definition: mminit.c:233
FORCEINLINE VOID MI_MAKE_HARDWARE_PTE_USER ( IN PMMPTE  NewPte,
IN PMMPTE  MappingPte,
IN ULONG_PTR  ProtectionMask,
IN PFN_NUMBER  PageFrameNumber 
)

Definition at line 785 of file miarm.h.

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

789 {
790  /* Only valid for kernel, non-session PTEs */
791  ASSERT(MappingPte <= MiHighestUserPte);
792 
793  /* Start fresh */
794  NewPte->u.Long = 0;
795 
796  /* Set the protection and page */
797  NewPte->u.Hard.Valid = TRUE;
798  NewPte->u.Hard.Owner = TRUE;
799  NewPte->u.Hard.PageFrameNumber = PageFrameNumber;
800  NewPte->u.Long |= MmProtectToPteMask[ProtectionMask];
801 }
#define TRUE
Definition: types.h:120
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
const ULONG_PTR MmProtectToPteMask[32]
Definition: page.c:32
PMMPTE MiHighestUserPte
Definition: mminit.c:233
FORCEINLINE VOID MI_MAKE_PROTOTYPE_PTE ( IN PMMPTE  NewPte,
IN PMMPTE  PointerPte 
)

Definition at line 809 of file miarm.h.

811 {
813 
814  /* Mark this as a prototype */
815  NewPte->u.Long = 0;
816  NewPte->u.Proto.Prototype = 1;
817 
818  /*
819  * Prototype PTEs are only valid in paged pool by design, this little trick
820  * lets us only use 30 bits for the adress of the PTE, as long as the area
821  * stays 1024MB At most.
822  */
823  Offset = (ULONG_PTR)PointerPte - (ULONG_PTR)MmPagedPoolStart;
824 
825  /*
826  * 7 bits go in the "low" (but we assume the bottom 2 are zero)
827  * and the other 21 bits go in the "high"
828  */
829  NewPte->u.Proto.ProtoAddressLow = (Offset & 0x1FC) >> 2;
830  NewPte->u.Proto.ProtoAddressHigh = (Offset & 0x3FFFFE00) >> 9;
831 }
uint32_t ULONG_PTR
Definition: typedefs.h:63
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
PVOID MmPagedPoolStart
Definition: miarm.h:552
#define ULONG_PTR
Definition: config.h:101
FORCEINLINE VOID MI_MAKE_SUBSECTION_PTE ( IN PMMPTE  NewPte,
IN PVOID  Segment 
)

Definition at line 838 of file miarm.h.

840 {
842 
843  /* Mark this as a prototype */
844  NewPte->u.Long = 0;
845  NewPte->u.Subsect.Prototype = 1;
846 
847  /*
848  * Segments are only valid either in nonpaged pool. We store the 20 bit
849  * difference either from the top or bottom of nonpaged pool, giving a
850  * maximum of 128MB to each delta, meaning nonpaged pool cannot exceed
851  * 256MB.
852  */
853  if ((ULONG_PTR)Segment < ((ULONG_PTR)MmSubsectionBase + (128 * _1MB)))
854  {
856  NewPte->u.Subsect.WhichPool = PagedPool;
857  }
858  else
859  {
861  NewPte->u.Subsect.WhichPool = NonPagedPool;
862  }
863 
864  /*
865  * 4 bits go in the "low" (but we assume the bottom 3 are zero)
866  * and the other 20 bits go in the "high"
867  */
868  NewPte->u.Subsect.SubsectionAddressLow = (Offset & 0x78) >> 3;
869  NewPte->u.Subsect.SubsectionAddressHigh = (Offset & 0xFFFFF80) >> 7;
870 }
ULONG_PTR MmSubsectionBase
Definition: section.c:138
PVOID MmNonPagedPoolEnd
Definition: mminit.c:99
uint32_t ULONG_PTR
Definition: typedefs.h:63
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
_Inout_ PVOID Segment
Definition: exfuncs.h:893
#define _1MB
Definition: miarm.h:13
#define ULONG_PTR
Definition: config.h:101
FORCEINLINE VOID MI_MAKE_TRANSITION_PTE ( _Out_ PMMPTE  NewPte,
_In_ PFN_NUMBER  Page,
_In_ ULONG  Protection 
)

Definition at line 884 of file miarm.h.

Referenced by MiResolvePageFileFault().

887 {
888  NewPte->u.Long = 0;
889  NewPte->u.Trans.Transition = 1;
890  NewPte->u.Trans.Protection = Protection;
891  NewPte->u.Trans.PageFrameNumber = Page;
892 }
FORCEINLINE VOID MI_UPDATE_VALID_PTE ( IN PMMPTE  PointerPte,
IN MMPTE  TempPte 
)

Definition at line 928 of file miarm.h.

Referenced by MiFlushTbAndCapture().

930 {
931  /* Write the valid PTE */
932  ASSERT(PointerPte->u.Hard.Valid == 1);
933  ASSERT(TempPte.u.Hard.Valid == 1);
934  ASSERT(PointerPte->u.Hard.PageFrameNumber == TempPte.u.Hard.PageFrameNumber);
935  *PointerPte = TempPte;
936 }
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
HARDWARE_PTE_ARMV6 TempPte
Definition: winldr.c:75
ULONG PageFrameNumber
Definition: mmtypes.h:109
FORCEINLINE VOID MI_WRITE_INVALID_PDE ( IN PMMPDE  PointerPde,
IN MMPDE  InvalidPde 
)

Definition at line 983 of file miarm.h.

Referenced by MmArmAccessFault().

985 {
986  /* Write the invalid PDE */
987  ASSERT(InvalidPde.u.Hard.Valid == 0);
988  ASSERT(InvalidPde.u.Long != 0);
989  *PointerPde = InvalidPde;
990 }
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
FORCEINLINE VOID MI_WRITE_INVALID_PTE ( IN PMMPTE  PointerPte,
IN MMPTE  InvalidPte 
)

Definition at line 943 of file miarm.h.

Referenced by MiAccessCheck(), MiAddMappedPtes(), MiAllocatePoolPages(), MiDecommitPages(), MiDecrementShareCount(), MiMapViewOfDataSection(), MiProcessValidPteList(), MiProtectFreeNonPagedPool(), MiProtectVirtualMemory(), MiResolvePageFileFault(), MiSetProtectionOnSection(), MmArmAccessFault(), MmCommitSessionMappedView(), MmCreateKernelStack(), MmGetPageTableForProcess(), MmGrowKernelStackEx(), MmInitializeProcessAddressSpace(), and NtAllocateVirtualMemory().

945 {
946  /* Write the invalid PTE */
947  ASSERT(InvalidPte.u.Hard.Valid == 0);
948  ASSERT(InvalidPte.u.Long != 0);
949  *PointerPte = InvalidPte;
950 }
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
FORCEINLINE VOID MI_WRITE_VALID_PDE ( IN PMMPDE  PointerPde,
IN MMPDE  TempPde 
)

Definition at line 969 of file miarm.h.

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

971 {
972  /* Write the valid PDE */
973  ASSERT(PointerPde->u.Hard.Valid == 0);
974  ASSERT(TempPde.u.Hard.Valid == 1);
975  *PointerPde = TempPde;
976 }
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
HARDWARE_PDE_ARMV6 TempPde
Definition: winldr.c:77
FORCEINLINE BOOLEAN MI_WS_OWNER ( IN PEPROCESS  Process)

Definition at line 1013 of file miarm.h.

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

1014 {
1015  /* Check if this process is the owner, and that the thread owns the WS */
1016  if (PsGetCurrentThread()->OwnsProcessWorkingSetExclusive == 0)
1017  {
1018  DPRINT("Thread: %p is not an owner\n", PsGetCurrentThread());
1019  }
1020  if (KeGetCurrentThread()->ApcState.Process != &Process->Pcb)
1021  {
1022  DPRINT("Current thread %p is attached to another process %p\n", PsGetCurrentThread(), Process);
1023  }
1024  return ((KeGetCurrentThread()->ApcState.Process == &Process->Pcb) &&
1025  ((PsGetCurrentThread()->OwnsProcessWorkingSetExclusive) ||
1026  (PsGetCurrentThread()->OwnsProcessWorkingSetShared)));
1027 }
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
void DPRINT(...)
Definition: polytest.cpp:61
_Out_ PKAPC_STATE ApcState
Definition: mm.h:1411
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
#define KeGetCurrentThread
Definition: hal.h:44
FORCEINLINE KIRQL MiAcquireExpansionLock ( VOID  )

Definition at line 1348 of file miarm.h.

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

1349 {
1350  KIRQL OldIrql;
1351 
1353  KeAcquireSpinLock(&MmExpansionLock, &OldIrql);
1356  return OldIrql;
1357 }
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
KSPIN_LOCK MmExpansionLock
Definition: session.c:32
UCHAR KIRQL
Definition: env_spec_w32.h:591
PETHREAD MiExpansionLockOwner
Definition: session.c:33
smooth NULL
Definition: ftsmooth.c:557
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
#define APC_LEVEL
Definition: env_spec_w32.h:695
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 150 of file freelist.c.

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

156 {
157  PMDL Mdl;
158  PFN_NUMBER PageCount, LowPage, HighPage, SkipPages, PagesFound = 0, Page;
159  PPFN_NUMBER MdlPage, LastMdlPage;
160  KIRQL OldIrql;
161  PMMPFN Pfn1;
162  INT LookForZeroedPages;
164  DPRINT1("ARM3-DEBUG: Being called with %I64x %I64x %I64x %lx %d %lu\n", LowAddress, HighAddress, SkipBytes, TotalBytes, CacheAttribute, MdlFlags);
165 
166  //
167  // Convert the low address into a PFN
168  //
169  LowPage = (PFN_NUMBER)(LowAddress.QuadPart >> PAGE_SHIFT);
170 
171  //
172  // Convert, and normalize, the high address into a PFN
173  //
174  HighPage = (PFN_NUMBER)(HighAddress.QuadPart >> PAGE_SHIFT);
175  if (HighPage > MmHighestPhysicalPage) HighPage = MmHighestPhysicalPage;
176 
177  //
178  // Validate skipbytes and convert them into pages
179  //
180  if (BYTE_OFFSET(SkipBytes.LowPart)) return NULL;
181  SkipPages = (PFN_NUMBER)(SkipBytes.QuadPart >> PAGE_SHIFT);
182 
183  /* This isn't supported at all */
184  if (SkipPages) DPRINT1("WARNING: Caller requesting SkipBytes, MDL might be mismatched\n");
185 
186  //
187  // Now compute the number of pages the MDL will cover
188  //
190  do
191  {
192  //
193  // Try creating an MDL for these many pages
194  //
195  Mdl = MmCreateMdl(NULL, NULL, PageCount << PAGE_SHIFT);
196  if (Mdl) break;
197 
198  //
199  // This function is not required to return the amount of pages requested
200  // In fact, it can return as little as 1 page, and callers are supposed
201  // to deal with this scenario. So re-attempt the allocation with less
202  // pages than before, and see if it worked this time.
203  //
204  PageCount -= (PageCount >> 4);
205  } while (PageCount);
206 
207  //
208  // Wow, not even a single page was around!
209  //
210  if (!Mdl) return NULL;
211 
212  //
213  // This is where the page array starts....
214  //
215  MdlPage = (PPFN_NUMBER)(Mdl + 1);
216 
217  //
218  // Lock the PFN database
219  //
221 
222  //
223  // Are we looking for any pages, without discriminating?
224  //
225  if ((LowPage == 0) && (HighPage == MmHighestPhysicalPage))
226  {
227  //
228  // Well then, let's go shopping
229  //
230  while (PagesFound < PageCount)
231  {
232  /* Grab a page */
234  MI_SET_PROCESS2("Kernel");
235 
236  /* FIXME: This check should be smarter */
237  Page = 0;
238  if (MmAvailablePages != 0)
239  Page = MiRemoveAnyPage(0);
240 
241  if (Page == 0)
242  {
243  /* This is not good... hopefully we have at least SOME pages */
244  ASSERT(PagesFound);
245  break;
246  }
247 
248  /* Grab the page entry for it */
249  Pfn1 = MiGetPfnEntry(Page);
250 
251  //
252  // Make sure it's really free
253  //
254  ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
255 
256  /* Now setup the page and mark it */
257  Pfn1->u3.e2.ReferenceCount = 1;
258  Pfn1->u2.ShareCount = 1;
259  MI_SET_PFN_DELETED(Pfn1);
260  Pfn1->u4.PteFrame = 0x1FFEDCB;
261  Pfn1->u3.e1.StartOfAllocation = 1;
262  Pfn1->u3.e1.EndOfAllocation = 1;
263  Pfn1->u4.VerifierAllocation = 0;
264 
265  //
266  // Save it into the MDL
267  //
268  *MdlPage++ = MiGetPfnEntryIndex(Pfn1);
269  PagesFound++;
270  }
271  }
272  else
273  {
274  //
275  // You want specific range of pages. We'll do this in two runs
276  //
277  for (LookForZeroedPages = 1; LookForZeroedPages >= 0; LookForZeroedPages--)
278  {
279  //
280  // Scan the range you specified
281  //
282  for (Page = LowPage; Page < HighPage; Page++)
283  {
284  //
285  // Get the PFN entry for this page
286  //
287  Pfn1 = MiGetPfnEntry(Page);
288  ASSERT(Pfn1);
289 
290  //
291  // Make sure it's free and if this is our first pass, zeroed
292  //
293  if (MiIsPfnInUse(Pfn1)) continue;
294  if ((Pfn1->u3.e1.PageLocation == ZeroedPageList) != LookForZeroedPages) continue;
295 
296  /* Remove the page from the free or zero list */
297  ASSERT(Pfn1->u3.e1.ReadInProgress == 0);
299  MI_SET_PROCESS2("Kernel");
301 
302  //
303  // Sanity checks
304  //
305  ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
306 
307  //
308  // Now setup the page and mark it
309  //
310  Pfn1->u3.e2.ReferenceCount = 1;
311  Pfn1->u2.ShareCount = 1;
312  MI_SET_PFN_DELETED(Pfn1);
313  Pfn1->u4.PteFrame = 0x1FFEDCB;
314  Pfn1->u3.e1.StartOfAllocation = 1;
315  Pfn1->u3.e1.EndOfAllocation = 1;
316  Pfn1->u4.VerifierAllocation = 0;
317 
318  //
319  // Save this page into the MDL
320  //
321  *MdlPage++ = Page;
322  if (++PagesFound == PageCount) break;
323  }
324 
325  //
326  // If the first pass was enough, don't keep going, otherwise, go again
327  //
328  if (PagesFound == PageCount) break;
329  }
330  }
331 
332  //
333  // Now release the PFN count
334  //
336 
337  //
338  // We might've found less pages, but not more ;-)
339  //
340  if (PagesFound != PageCount) ASSERT(PagesFound < PageCount);
341  if (!PagesFound)
342  {
343  //
344  // If we didn' tfind any pages at all, fail
345  //
346  DPRINT1("NO MDL PAGES!\n");
348  return NULL;
349  }
350 
351  //
352  // Write out how many pages we found
353  //
354  Mdl->ByteCount = (ULONG)(PagesFound << PAGE_SHIFT);
355 
356  //
357  // Terminate the MDL array if there's certain missing pages
358  //
359  if (PagesFound != PageCount) *MdlPage = LIST_HEAD;
360 
361  //
362  // Now go back and loop over all the MDL pages
363  //
364  MdlPage = (PPFN_NUMBER)(Mdl + 1);
365  LastMdlPage = MdlPage + PagesFound;
366  while (MdlPage < LastMdlPage)
367  {
368  //
369  // Check if we've reached the end
370  //
371  Page = *MdlPage++;
372  if (Page == LIST_HEAD) break;
373 
374  //
375  // Get the PFN entry for the page and check if we should zero it out
376  //
377  Pfn1 = MiGetPfnEntry(Page);
378  ASSERT(Pfn1);
379  if (Pfn1->u3.e1.PageLocation != ZeroedPageList) MiZeroPhysicalPage(Page);
381  }
382 
383  //
384  // We're done, mark the pages as locked
385  //
386  Mdl->Process = NULL;
387  Mdl->MdlFlags |= MDL_PAGES_LOCKED;
388  return Mdl;
389 }
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
USHORT ReadInProgress
Definition: mm.h:289
union _MMPFN::@1569 u4
VOID NTAPI MiZeroPhysicalPage(IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:122
PVOID PMDL
Definition: usb.h:39
int32_t INT
Definition: typedefs.h:56
USHORT PageLocation
Definition: mm.h:293
UCHAR KIRQL
Definition: env_spec_w32.h:591
MMPFNENTRY e1
Definition: mm.h:325
ULONG * PPFN_NUMBER
Definition: ke.h:8
union _MMPFN::@1566 u3
ULONG PFN_NUMBER
Definition: ke.h:8
ULONG_PTR ShareCount
Definition: mm.h:318
#define MI_SET_PROCESS2(x)
Definition: mm.h:250
smooth NULL
Definition: ftsmooth.c:557
ULONG_PTR VerifierAllocation
Definition: mm.h:348
#define MI_SET_USAGE(x)
Definition: mm.h:249
_Must_inspect_result_ _In_ PHYSICAL_ADDRESS _In_ PHYSICAL_ADDRESS SkipBytes
Definition: mmfuncs.h:226
#define ADDRESS_AND_SIZE_TO_SPAN_PAGES(_Va, _Size)
#define MDL_PAGES_LOCKED
Definition: mmtypes.h:19
#define TAG_MDL
Definition: tag.h:86
VOID FASTCALL KeReleaseQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber, IN KIRQL OldIrql)
Definition: spinlock.c:154
PFN_NUMBER MmAvailablePages
Definition: freelist.c:26
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
Definition: mm.h:301
ULONG LowPart
Definition: typedefs.h:104
LIST_HEAD(acpi_bus_event_list)
KIRQL FASTCALL KeAcquireQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber)
Definition: spinlock.c:108
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:873
BOOLEAN NTAPI MiIsPfnInUse(IN PMMPFN Pfn1)
Definition: freelist.c:142
PFN_NUMBER NTAPI MiRemoveAnyPage(IN ULONG Color)
Definition: pfnlist.c:475
#define MI_SET_PFN_DELETED(x)
Definition: miarm.h:161
_Must_inspect_result_ _In_ PHYSICAL_ADDRESS HighAddress
Definition: mmfuncs.h:226
ULONG_PTR PteFrame
Definition: mm.h:346
PMDL NTAPI MmCreateMdl(IN PMDL Mdl, IN PVOID Base, IN SIZE_T Length)
Definition: mdlsup.c:352
#define DPRINT1
Definition: precomp.h:8
struct _MMPFN::@1566::@1572 e2
FORCEINLINE PFN_NUMBER MiGetPfnEntryIndex(IN PMMPFN Pfn1)
Definition: mm.h:893
unsigned int ULONG
Definition: retypes.h:1
PFN_NUMBER MmHighestPhysicalPage
Definition: meminit.c:31
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1097
union _MMPFN::@1565 u2
VOID NTAPI MiUnlinkFreeOrZeroedPage(IN PMMPFN Entry)
Definition: pfnlist.c:137
#define APC_LEVEL
Definition: env_spec_w32.h:695
#define BYTE_OFFSET(Va)
_Must_inspect_result_ _In_ PHYSICAL_ADDRESS _In_ PHYSICAL_ADDRESS _In_ SIZE_T TotalBytes
Definition: mmfuncs.h:226
LONGLONG QuadPart
Definition: typedefs.h:112
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 78 of file vadnode.c.

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

82 {
83  PMMADDRESS_NODE ParentNode, CurrentNode;
84 
85  /* If the tree is empty, there is no conflict */
86  if (Table->NumberGenericTableElements == 0) return TableEmptyTree;
87 
88  /* Start looping from the root node */
89  CurrentNode = RtlRightChildAvl(&Table->BalancedRoot);
90  ASSERT(CurrentNode != NULL);
91  while (CurrentNode)
92  {
93  ParentNode = CurrentNode;
94 
95  /* This address comes after */
96  if (StartVpn > CurrentNode->EndingVpn)
97  {
98  /* Keep searching on the right */
99  CurrentNode = RtlRightChildAvl(CurrentNode);
100  }
101  else if (EndVpn < CurrentNode->StartingVpn)
102  {
103  /* This address ends before the node starts, search on the left */
104  CurrentNode = RtlLeftChildAvl(CurrentNode);
105  }
106  else
107  {
108  /* This address is part of this node, return it */
109  *NodeOrParent = ParentNode;
110  return TableFoundNode;
111  }
112  }
113 
114  /* There is no more child, save the current node as parent */
115  *NodeOrParent = ParentNode;
116  if (StartVpn > ParentNode->EndingVpn)
117  {
118  return TableInsertAsRight;
119  }
120  else
121  {
122  return TableInsertAsLeft;
123  }
124 }
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
#define RtlRightChildAvl
Definition: miavl.h:45
smooth NULL
Definition: ftsmooth.c:557
ULONG_PTR EndingVpn
Definition: mmtypes.h:655
#define RtlLeftChildAvl
Definition: miavl.h:46
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.

Referenced by MiAllocateContiguousMemory().

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 }
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
#define MiAddressToPte(x)
Definition: mmx86.c:19
ULONG PFN_NUMBER
Definition: ke.h:8
smooth NULL
Definition: ftsmooth.c:557
PVOID FORCEINLINE MiPteToAddress(PMMPTE PointerPte)
Definition: mm.h:185
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
ULONG64 Valid
Definition: mmtypes.h:150
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217
union _MMPTE::@2072 u
#define PFN_FROM_PTE(v)
Definition: mm.h:82
NTSTATUS FASTCALL MiCheckPdeForPagedPool ( IN PVOID  Address)

Definition at line 471 of file pagfault.c.

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

472 {
474 }
#define STATUS_ACCESS_VIOLATION
Definition: ntstatus.h:228
NTSTATUS NTAPI MiCheckSecuredVad ( IN PMMVAD  Vad,
IN PVOID  Base,
IN SIZE_T  Size,
IN ULONG  ProtectionMask 
)

Definition at line 809 of file vadnode.c.

Referenced by MiUnmapViewOfSection(), and NtAllocateVirtualMemory().

813 {
814  ULONG_PTR StartAddress, EndAddress;
815 
816  /* Compute start and end address */
817  StartAddress = (ULONG_PTR)Base;
818  EndAddress = StartAddress + Size - 1;
819 
820  /* Are we deleting/unmapping, or changing? */
821  if (ProtectionMask < MM_DELETE_CHECK)
822  {
823  /* Changing... are we allowed to do so? */
824  if ((Vad->u.VadFlags.NoChange == 1) &&
825  (Vad->u2.VadFlags2.SecNoChange == 1) &&
826  (Vad->u.VadFlags.Protection != ProtectionMask))
827  {
828  /* Nope, bail out */
829  DPRINT1("Trying to mess with a no-change VAD!\n");
831  }
832  }
833  else
834  {
835  /* This is allowed */
836  ProtectionMask = 0;
837  }
838 
839  /* ARM3 doesn't support this yet */
840  ASSERT(Vad->u2.VadFlags2.MultipleSecured == 0);
841 
842  /* Is this a one-secured VAD, like a TEB or PEB? */
843  if (Vad->u2.VadFlags2.OneSecured)
844  {
845  /* Is this allocation being described by the VAD? */
846  if ((StartAddress <= ((PMMVAD_LONG)Vad)->u3.Secured.EndVpn) &&
847  (EndAddress >= ((PMMVAD_LONG)Vad)->u3.Secured.StartVpn))
848  {
849  /* Guard page? */
850  if (ProtectionMask & MM_DECOMMIT)
851  {
852  DPRINT1("Not allowed to change protection on guard page!\n");
854  }
855 
856  /* ARM3 doesn't have read-only VADs yet */
857  ASSERT(Vad->u2.VadFlags2.ReadOnly == 0);
858 
859  /* Check if read-write protections are allowed */
860  if (MmReadWrite[ProtectionMask] < MM_READ_WRITE_ALLOWED)
861  {
862  DPRINT1("Invalid protection mask for RW access!\n");
864  }
865  }
866  }
867 
868  /* All good, allow the change */
869  return STATUS_SUCCESS;
870 }
union _MMVAD_LONG::@2315 u2
ULONG ReadOnly
Definition: mmtypes.h:711
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
return STATUS_SUCCESS
Definition: btrfs.c:2664
#define MM_DECOMMIT
Definition: miarm.h:66
_In_opt_ ULONG Base
Definition: rtlfuncs.h:2327
#define MM_DELETE_CHECK
Definition: miarm.h:233
uint32_t ULONG_PTR
Definition: typedefs.h:63
#define MM_READ_WRITE_ALLOWED
Definition: miarm.h:230
UINTN Size
Definition: acefiex.h:555
MMVAD_FLAGS2 VadFlags2
Definition: mmtypes.h:772
#define STATUS_INVALID_PAGE_PROTECTION
Definition: ntstatus.h:291
#define DPRINT1
Definition: precomp.h:8
CHAR MmReadWrite[32]
Definition: vadnode.c:25
#define ULONG_PTR
Definition: config.h:101
static BYTE u3[]
Definition: msg.c:580
VOID NTAPI MiComputeColorInformation ( VOID  )

Definition at line 498 of file mminit.c.

Referenced by MmArmInitSystem().

499 {
500  ULONG L2Associativity;
501 
502  /* Check if no setting was provided already */
503  if (!MmSecondaryColors)
504  {
505  /* Get L2 cache information */
506  L2Associativity = KeGetPcr()->SecondLevelCacheAssociativity;
507 
508  /* The number of colors is the number of cache bytes by set/way */
509  MmSecondaryColors = KeGetPcr()->SecondLevelCacheSize;
510  if (L2Associativity) MmSecondaryColors /= L2Associativity;
511  }
512 
513  /* Now convert cache bytes into pages */
515  if (!MmSecondaryColors)
516  {
517  /* If there was no cache data from the KPCR, use the default colors */
519  }
520  else
521  {
522  /* Otherwise, make sure there aren't too many colors */
524  {
525  /* Set the maximum */
527  }
528 
529  /* Make sure there aren't too little colors */
531  {
532  /* Set the default */
534  }
535 
536  /* Finally make sure the colors are a power of two */
538  {
539  /* Set the default */
541  }
542  }
543 
544  /* Compute the mask and store it */
546  KeGetCurrentPrcb()->SecondaryColorMask = MmSecondaryColorMask;
547 }
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1054
#define MI_MAX_SECONDARY_COLORS
Definition: mm.h:68
#define KeGetPcr()
Definition: ke.h:25
#define MI_SECONDARY_COLORS
Definition: mm.h:67
ULONG MmSecondaryColorMask
Definition: mminit.c:256
#define MI_MIN_SECONDARY_COLORS
Definition: mm.h:66
unsigned int ULONG
Definition: retypes.h:1
ULONG MmSecondaryColors
Definition: mminit.c:255
FORCEINLINE VOID MiDecrementPageTableReferences ( IN PVOID  Address)

Definition at line 1647 of file miarm.h.

Referenced by MiDeleteVirtualAddresses(), and MiUnmapLockedPagesInUserSpace().

1648 {
1649  PUSHORT RefCount;
1650 
1652 
1653  *RefCount -= 1;
1654  ASSERT(*RefCount < PTE_PER_PAGE);
1655 }
PVOID ULONG Address
Definition: oprghdlr.h:14
USHORT UsedPageTableEntries[768]
Definition: mmtypes.h:870
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
#define MiGetPdeOffset(x)
Definition: mm.h:172
unsigned short * PUSHORT
Definition: retypes.h:2
#define PTE_PER_PAGE
Definition: mm.h:18
PMMWSL MmWorkingSetList
Definition: procsup.c:21
VOID NTAPI MiDecrementReferenceCount ( IN PMMPFN  Pfn1,
IN PFN_NUMBER  PageFrameIndex 
)

Definition at line 1222 of file pfnlist.c.

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

1224 {
1225  /* PFN lock must be held */
1227 
1228  /* Sanity checks on the page */
1229  if (PageFrameIndex > MmHighestPhysicalPage ||
1230  Pfn1 != MI_PFN_ELEMENT(PageFrameIndex) ||
1231  Pfn1->u3.e2.ReferenceCount == 0 ||
1232  Pfn1->u3.e2.ReferenceCount >= 2500)
1233  {
1234  DPRINT1("PageFrameIndex=0x%lx, MmHighestPhysicalPage=0x%lx\n", PageFrameIndex, MmHighestPhysicalPage);
1235  DPRINT1("Pfn1=%p, Element=%p, RefCount=%u\n", Pfn1, MI_PFN_ELEMENT(PageFrameIndex), Pfn1->u3.e2.ReferenceCount);
1236  ASSERT(PageFrameIndex <= MmHighestPhysicalPage);
1237  ASSERT(Pfn1 == MI_PFN_ELEMENT(PageFrameIndex));
1238  ASSERT(Pfn1->u3.e2.ReferenceCount != 0);
1239  ASSERT(Pfn1->u3.e2.ReferenceCount < 2500);
1240  }
1241 
1242  /* Dereference the page, bail out if it's still alive */
1243  InterlockedDecrement16((PSHORT)&Pfn1->u3.e2.ReferenceCount);
1244  if (Pfn1->u3.e2.ReferenceCount) return;
1245 
1246  /* Nobody should still have reference to this page */
1247  if (Pfn1->u2.ShareCount != 0)
1248  {
1249  /* Otherwise something's really wrong */
1250  KeBugCheckEx(PFN_LIST_CORRUPT, 7, PageFrameIndex, Pfn1->u2.ShareCount, 0);
1251  }
1252 
1253  /* And it should be lying on some page list */
1254  ASSERT(Pfn1->u3.e1.PageLocation != ActiveAndValid);
1255 
1256  /* Did someone set the delete flag? */
1257  if (MI_IS_PFN_DELETED(Pfn1))
1258  {
1259  /* Insert it into the free list, there's nothing left to do */
1260  MiInsertPageInFreeList(PageFrameIndex);
1261  return;
1262  }
1263 
1264  /* Check to see which list this page should go into */
1265  if (Pfn1->u3.e1.Modified == 1)
1266  {
1267  /* Push it into the modified page list */
1268  MiInsertPageInList(&MmModifiedPageListHead, PageFrameIndex);
1269  }
1270  else
1271  {
1272  /* Otherwise, insert this page into the standby list */
1273  ASSERT(Pfn1->u3.e1.RemovalRequested == 0);
1274  MiInsertStandbyListAtFront(PageFrameIndex);
1275  }
1276 }
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
VOID FASTCALL MiInsertStandbyListAtFront(IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:718
signed short * PSHORT
Definition: retypes.h:6
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
VOID NTAPI MiInsertPageInList(IN PMMPFNLIST ListHead, IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:778
union _MMPFN::@1566 u3
MMPFNLIST MmModifiedPageListHead
Definition: pfnlist.c:45
#define MI_IS_PFN_DELETED(x)
Definition: miarm.h:162
FORCEINLINE PMMPFN MI_PFN_ELEMENT(IN PFN_NUMBER Pfn)
Definition: miarm.h:1391
VOID NTAPI MiInsertPageInFreeList(IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:604
#define InterlockedDecrement16
Definition: interlocked.h:139
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
#define DPRINT1
Definition: precomp.h:8
struct _MMPFN::@1566::@1572 e2
PFN_NUMBER MmHighestPhysicalPage
Definition: meminit.c:31
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:90
VOID NTAPI MiDecrementShareCount ( IN PMMPFN  Pfn1,
IN PFN_NUMBER  PageFrameIndex 
)

Definition at line 1133 of file pfnlist.c.

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

1135 {
1136  PMMPTE PointerPte;
1137  MMPTE TempPte;
1138 
1139  ASSERT(PageFrameIndex > 0);
1140  ASSERT(MI_PFN_ELEMENT(PageFrameIndex) != NULL);
1141  ASSERT(Pfn1 == MI_PFN_ELEMENT(PageFrameIndex));
1142  ASSERT(MI_IS_ROS_PFN(Pfn1) == FALSE);
1143 
1144  /* Page must be in-use */
1145  if ((Pfn1->u3.e1.PageLocation != ActiveAndValid) &&
1146  (Pfn1->u3.e1.PageLocation != StandbyPageList))
1147  {
1148  /* Otherwise we have PFN corruption */
1149  KeBugCheckEx(PFN_LIST_CORRUPT,
1150  0x99,
1151  PageFrameIndex,
1152  Pfn1->u3.e1.PageLocation,
1153  0);
1154  }
1155 
1156  /* Page should at least have one reference */
1157  ASSERT(Pfn1->u3.e2.ReferenceCount != 0);
1158 
1159  /* Check if the share count is now 0 */
1160  ASSERT(Pfn1->u2.ShareCount < 0xF000000);
1161  if (!--Pfn1->u2.ShareCount)
1162  {
1163  /* Was this a prototype PTE? */
1164  if (Pfn1->u3.e1.PrototypePte)
1165  {
1166  /* Grab the PTE address and make sure it's in prototype pool */
1167  PointerPte = Pfn1->PteAddress;
1168  ASSERT((PointerPte >= (PMMPTE)MmPagedPoolStart) && (PointerPte <= (PMMPTE)MmPagedPoolEnd));
1169 
1170  /* The PTE that backs it should also be valdi */
1171  PointerPte = MiAddressToPte(PointerPte);
1172  ASSERT(PointerPte->u.Hard.Valid == 1);
1173 
1174  /* Get the original prototype PTE and turn it into a transition PTE */
1175  PointerPte = Pfn1->PteAddress;
1176  TempPte = *PointerPte;
1177  TempPte.u.Soft.Transition = 1;
1178  TempPte.u.Soft.Valid = 0;
1179  TempPte.u.Soft.Prototype = 0;
1180  TempPte.u.Soft.Protection = Pfn1->OriginalPte.u.Soft.Protection;
1181  MI_WRITE_INVALID_PTE(PointerPte, TempPte);
1182  DPRINT("Marking PTE: %p as transition (%p - %lx)\n", PointerPte, Pfn1, MiGetPfnEntryIndex(Pfn1));
1183  }
1184 
1185  /* Put the page in transition */
1186  Pfn1->u3.e1.PageLocation = TransitionPage;
1187 
1188  /* PFN lock must be held */
1190 
1191  if (Pfn1->u3.e2.ReferenceCount == 1)
1192  {
1193  /* Is there still a PFN for this page? */
1194  if (MI_IS_PFN_DELETED(Pfn1))
1195  {
1196  /* Clear the last reference */
1197  Pfn1->u3.e2.ReferenceCount = 0;
1198  ASSERT(Pfn1->OriginalPte.u.Soft.Prototype == 0);
1199 
1200  /* Mark the page temporarily as valid, we're going to make it free soon */
1201  Pfn1->u3.e1.PageLocation = ActiveAndValid;
1202 
1203  /* Bring it back into the free list */
1204  MiInsertPageInFreeList(PageFrameIndex);
1205  }
1206  else
1207  {
1208  /* PFN not yet deleted, drop a ref count */
1209  MiDecrementReferenceCount(Pfn1, PageFrameIndex);
1210  }
1211  }
1212  else
1213  {
1214  /* Otherwise, just drop the reference count */
1215  InterlockedDecrement16((PSHORT)&Pfn1->u3.e2.ReferenceCount);
1216  }
1217  }
1218 }
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
signed short * PSHORT
Definition: retypes.h:6
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
PVOID MmPagedPoolEnd
Definition: init.c:26
#define MiAddressToPte(x)
Definition: mmx86.c:19
#define FALSE
Definition: types.h:117
smooth NULL
Definition: ftsmooth.c:557
void DPRINT(...)
Definition: polytest.cpp:61
ULONG64 Protection
Definition: mmtypes.h:88
ULONG64 Valid
Definition: mmtypes.h:150
#define MI_IS_PFN_DELETED(x)
Definition: miarm.h:162
HARDWARE_PTE_ARMV6 TempPte
Definition: winldr.c:75
FORCEINLINE PMMPFN MI_PFN_ELEMENT(IN PFN_NUMBER Pfn)
Definition: miarm.h:1391
VOID NTAPI MiInsertPageInFreeList(IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:604
ULONG64 Prototype
Definition: mmtypes.h:89
ULONG64 Valid
Definition: mmtypes.h:86
#define InterlockedDecrement16
Definition: interlocked.h:139
PVOID MmPagedPoolStart
Definition: miarm.h:552
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217
FORCEINLINE VOID MI_WRITE_INVALID_PTE(IN PMMPTE PointerPte, IN MMPTE InvalidPte)
Definition: miarm.h:943
VOID NTAPI MiDecrementReferenceCount(IN PMMPFN Pfn1, IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:1222
ULONG64 Transition
Definition: mmtypes.h:90
#define MI_IS_ROS_PFN(x)
Definition: miarm.h:1041
MMPTE_SOFTWARE Soft
Definition: mmtypes.h:219
FORCEINLINE PFN_NUMBER MiGetPfnEntryIndex(IN PMMPFN Pfn1)
Definition: mm.h:893
union _MMPTE::@2072 u
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:90
VOID NTAPI MiDeleteARM3Section ( PVOID  ObjectBody)

Definition at line 3244 of file section.c.

Referenced by MmpDeleteSection().

3245 {
3247  PCONTROL_AREA ControlArea;
3248  KIRQL OldIrql;
3249 
3250  SectionObject = (PSECTION)ObjectBody;
3251 
3252  if (SectionObject->u.Flags.Based == 1)
3253  {
3254  /* Remove the node from the global section address tree */
3256  MiRemoveNode(&SectionObject->Address, &MmSectionBasedRoot);
3258  }
3259 
3260  /* Lock the PFN database */
3262 
3263  ASSERT(SectionObject->Segment);
3264  ASSERT(SectionObject->Segment->ControlArea);
3265 
3266  ControlArea = SectionObject->Segment->ControlArea;
3267 
3268  /* Dereference */
3269  ControlArea->NumberOfSectionReferences--;
3270  ControlArea->NumberOfUserReferences--;
3271 
3272  ASSERT(ControlArea->u.Flags.BeingDeleted == 0);
3273 
3274  /* Check it. It will delete it if there is no more reference to it */
3275  MiCheckControlArea(ControlArea, OldIrql);
3276 }
_Must_inspect_result_ _Outptr_ PVOID * SectionObject
Definition: fsrtlfuncs.h:860
ULONG NumberOfSectionReferences
Definition: mmtypes.h:515
PSEGMENT Segment
Definition: mmtypes.h:813
VOID FASTCALL KeAcquireGuardedMutex(IN PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:42
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
KGUARDED_MUTEX MmSectionBasedMutex
Definition: section.c:110
MM_AVL_TABLE MmSectionBasedRoot
Definition: section.c:109
union _CONTROL_AREA::@2304 u
union _SECTION::@2320 u
struct _CONTROL_AREA * ControlArea
Definition: mmtypes.h:401
UCHAR KIRQL
Definition: env_spec_w32.h:591
struct _SECTION * PSECTION
MMSECTION_FLAGS Flags
Definition: mmtypes.h:818
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
KIRQL FASTCALL KeAcquireQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber)
Definition: spinlock.c:108
VOID NTAPI MiRemoveNode(IN PMMADDRESS_NODE Node, IN PMM_AVL_TABLE Table)
Definition: vadnode.c:360
ULONG BeingDeleted
Definition: mmtypes.h:455
MMADDRESS_NODE Address
Definition: mmtypes.h:812
ULONG NumberOfUserReferences
Definition: mmtypes.h:519
VOID NTAPI MiCheckControlArea(IN PCONTROL_AREA ControlArea, IN KIRQL OldIrql)
Definition: section.c:728
VOID FASTCALL KeReleaseGuardedMutex(IN OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:53
MMSECTION_FLAGS Flags
Definition: mmtypes.h:523
VOID NTAPI MiDeletePte ( IN PMMPTE  PointerPte,
IN PVOID  VirtualAddress,
IN PEPROCESS  CurrentProcess,
IN PMMPTE  PrototypePte 
)

Definition at line 391 of file virtual.c.

Referenced by MiBalancerThread(), MiDeleteVirtualAddresses(), MiResolveProtoPteFault(), MiUnmapLockedPagesInUserSpace(), MmArmAccessFault(), MmDeleteProcessAddressSpace(), and MmFreeMemoryArea().

395 {
396  PMMPFN Pfn1;
397  MMPTE TempPte;
398  PFN_NUMBER PageFrameIndex;
399  PMMPDE PointerPde;
400 
401  /* PFN lock must be held */
403 
404  /* Capture the PTE */
405  TempPte = *PointerPte;
406 
407  /* See if the PTE is valid */
408  if (TempPte.u.Hard.Valid == 0)
409  {
410  /* Prototype and paged out PTEs not supported yet */
411  ASSERT(TempPte.u.Soft.Prototype == 0);
412  ASSERT((TempPte.u.Soft.PageFileHigh == 0) || (TempPte.u.Soft.Transition == 1));
413 
414  if (TempPte.u.Soft.Transition)
415  {
416  /* Get the PFN entry */
417  PageFrameIndex = PFN_FROM_PTE(&TempPte);
418  Pfn1 = MiGetPfnEntry(PageFrameIndex);
419 
420  DPRINT("Pte %p is transitional!\n", PointerPte);
421 
422  /* Make sure the saved PTE address is valid */
423  ASSERT((PMMPTE)((ULONG_PTR)Pfn1->PteAddress & ~0x1) == PointerPte);
424 
425  /* Destroy the PTE */
426  MI_ERASE_PTE(PointerPte);
427 
428  /* Drop the reference on the page table. */
430 
431  ASSERT(Pfn1->u3.e1.PrototypePte == 0);
432 
433  /* Make the page free. For prototypes, it will be made free when deleting the section object */
434  if (Pfn1->u3.e2.ReferenceCount == 0)
435  {
436  /* And it should be in standby or modified list */
438 
439  /* Unlink it and set its reference count to one */
440  MiUnlinkPageFromList(Pfn1);
441  Pfn1->u3.e2.ReferenceCount++;
442 
443  /* This will put it back in free list and clean properly up */
444  MI_SET_PFN_DELETED(Pfn1);
445  MiDecrementReferenceCount(Pfn1, PageFrameIndex);
446  }
447  return;
448  }
449  }
450 
451  /* Get the PFN entry */
452  PageFrameIndex = PFN_FROM_PTE(&TempPte);
453  Pfn1 = MiGetPfnEntry(PageFrameIndex);
454 
455  /* Check if this is a valid, prototype PTE */
456  if (Pfn1->u3.e1.PrototypePte == 1)
457  {
458  /* Get the PDE and make sure it's faulted in */
459  PointerPde = MiPteToPde(PointerPte);
460  if (PointerPde->u.Hard.Valid == 0)
461  {
462 #if (_MI_PAGING_LEVELS == 2)
463  /* Could be paged pool access from a new process -- synchronize the page directories */
465  {
466 #endif
467  /* The PDE must be valid at this point */
468  KeBugCheckEx(MEMORY_MANAGEMENT,
469  0x61940,
470  (ULONG_PTR)PointerPte,
471  PointerPte->u.Long,
473  }
474 #if (_MI_PAGING_LEVELS == 2)
475  }
476 #endif
477  /* Drop the share count on the page table */
478  PointerPde = MiPteToPde(PointerPte);
480  PointerPde->u.Hard.PageFrameNumber);
481 
482  /* Drop the share count */
483  MiDecrementShareCount(Pfn1, PageFrameIndex);
484 
485  /* Either a fork, or this is the shared user data page */
486  if ((PointerPte <= MiHighestUserPte) && (PrototypePte != Pfn1->PteAddress))
487  {
488  /* If it's not the shared user page, then crash, since there's no fork() yet */
490  (MmHighestUserAddress <= (PVOID)USER_SHARED_DATA))
491  {
492  /* Must be some sort of memory corruption */
493  KeBugCheckEx(MEMORY_MANAGEMENT,
494  0x400,
495  (ULONG_PTR)PointerPte,
497  (ULONG_PTR)Pfn1->PteAddress);
498  }
499  }
500 
501  /* Erase it */
502  MI_ERASE_PTE(PointerPte);
503  }
504  else
505  {
506  /* Make sure the saved PTE address is valid */
507  if ((PMMPTE)((ULONG_PTR)Pfn1->PteAddress & ~0x1) != PointerPte)
508  {
509  /* The PFN entry is illegal, or invalid */
510  KeBugCheckEx(MEMORY_MANAGEMENT,
511  0x401,
512  (ULONG_PTR)PointerPte,
513  PointerPte->u.Long,
514  (ULONG_PTR)Pfn1->PteAddress);
515  }
516 
517  /* Erase the PTE */
518  MI_ERASE_PTE(PointerPte);
519 
520  /* There should only be 1 shared reference count */
521  ASSERT(Pfn1->u2.ShareCount == 1);
522 
523  /* Drop the reference on the page table. */
525 
526  /* Mark the PFN for deletion and dereference what should be the last ref */
527  MI_SET_PFN_DELETED(Pfn1);
528  MiDecrementShareCount(Pfn1, PageFrameIndex);
529 
530  /* We should eventually do this */
531  //CurrentProcess->NumberOfPrivatePages--;
532  }
533 
534  /* Flush the TLB */
536 }
DWORD *typedef PVOID
Definition: winlogon.h:52
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
FORCEINLINE VOID MI_ERASE_PTE(IN PMMPTE PointerPte)
Definition: miarm.h:957
MMPTE PrototypePte
Definition: init.c:42
VOID NTAPI MiUnlinkPageFromList(IN PMMPFN Pfn)
Definition: pfnlist.c:264
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG x1
Definition: winddi.h:3706
union _MMPFN::@1569 u4
NTSTATUS FASTCALL MiCheckPdeForPagedPool(IN PVOID Address)
Definition: pagfault.c:471
USHORT PageLocation
Definition: mm.h:293
uint32_t ULONG_PTR
Definition: typedefs.h:63
USHORT PrototypePte
Definition: mm.h:291
MMPFNENTRY e1
Definition: mm.h:325
union _MMPFN::@1566 u3
ULONG PFN_NUMBER
Definition: ke.h:8
ULONG_PTR ShareCount
Definition: mm.h:318
#define USER_SHARED_DATA
Definition: pstypes.h:51
void DPRINT(...)
Definition: polytest.cpp:61
VOID NTAPI MiDecrementShareCount(IN PMMPFN Pfn1, IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:1133
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:24
ULONG64 Valid
Definition: mmtypes.h:150
#define PAGE_ALIGN(Va)
HARDWARE_PTE_ARMV6 TempPte
Definition: winldr.c:75
VOID NTAPI MiDecrementReferenceCount(IN PMMPFN Pfn1, IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:1222
ULONG64 PageFileHigh
Definition: mmtypes.h:93
Definition: mm.h:301
ULONG64 Prototype
Definition: mmtypes.h:89
_In_ ULONG _In_ BOOLEAN _Must_inspect_result_ PVOID * VirtualAddress
Definition: ndis.h:3772
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:873
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217
#define MI_SET_PFN_DELETED(x)
Definition: miarm.h:161
#define MiPteToPde(_Pte)
Definition: mm.h:220
ULONG_PTR PteFrame
Definition: mm.h:346
ULONG64 Transition
Definition: mmtypes.h:90
PMMPTE PteAddress
Definition: mm.h:314
MMPTE_SOFTWARE Soft
Definition: mmtypes.h:219
PVOID MmHighestUserAddress
Definition: rtlcompat.c:26
struct _MMPFN::@1566::@1572 e2
ULONG64 PageFrameNumber
Definition: mmtypes.h:171
union _MMPTE::@2072 u
PMMPTE MiHighestUserPte
Definition: mminit.c:233
union _MMPFN::@1565 u2
#define PFN_FROM_PTE(v)
Definition: mm.h:82
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:90
VOID NTAPI KeFlushCurrentTb(VOID)
Definition: cpu.c:332
PFN_COUNT NTAPI MiDeleteSystemPageableVm ( IN PMMPTE  PointerPte,
IN PFN_NUMBER  PageCount,
IN ULONG  Flags,
OUT PPFN_NUMBER  ValidPages 
)

Definition at line 297 of file virtual.c.

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

301 {
302  PFN_COUNT ActualPages = 0;
303  PETHREAD CurrentThread = PsGetCurrentThread();
304  PMMPFN Pfn1, Pfn2;
305  PFN_NUMBER PageFrameIndex, PageTableIndex;
306  KIRQL OldIrql;
308 
309  /* Lock the system working set */
310  MiLockWorkingSet(CurrentThread, &MmSystemCacheWs);
311 
312  /* Loop all pages */
313  while (PageCount)
314  {
315  /* Make sure there's some data about the page */
316  if (PointerPte->u.Long)
317  {
318  /* As always, only handle current ARM3 scenarios */
319  ASSERT(PointerPte->u.Soft.Prototype == 0);
320  ASSERT(PointerPte->u.Soft.Transition == 0);
321 
322  /* Normally this is one possibility -- freeing a valid page */
323  if (PointerPte->u.Hard.Valid)
324  {
325  /* Get the page PFN */
326  PageFrameIndex = PFN_FROM_PTE(PointerPte);
327  Pfn1 = MiGetPfnEntry(PageFrameIndex);
328 
329  /* Should not have any working set data yet */
330  ASSERT(Pfn1->u1.WsIndex == 0);
331 
332  /* Actual valid, legitimate, pages */
333  if (ValidPages) (*ValidPages)++;
334 
335  /* Get the page table entry */
336  PageTableIndex = Pfn1->u4.PteFrame;
337  Pfn2 = MiGetPfnEntry(PageTableIndex);
338 
339  /* Lock the PFN database */
341 
342  /* Delete it the page */
343  MI_SET_PFN_DELETED(Pfn1);
344  MiDecrementShareCount(Pfn1, PageFrameIndex);
345 
346  /* Decrement the page table too */
347  MiDecrementShareCount(Pfn2, PageTableIndex);
348 
349  /* Release the PFN database */
351 
352  /* Destroy the PTE */
353  MI_ERASE_PTE(PointerPte);
354  }
355  else
356  {
357  /*
358  * The only other ARM3 possibility is a demand zero page, which would
359  * mean freeing some of the paged pool pages that haven't even been
360  * touched yet, as part of a larger allocation.
361  *
362  * Right now, we shouldn't expect any page file information in the PTE
363  */
364  ASSERT(PointerPte->u.Soft.PageFileHigh == 0);
365 
366  /* Destroy the PTE */
367  MI_ERASE_PTE(PointerPte);
368  }
369 
370  /* Actual legitimate pages */
371  ActualPages++;
372  }
373 
374  /* Keep going */
375  PointerPte++;
376  PageCount--;
377  }
378 
379  /* Release the working set */
380  MiUnlockWorkingSet(CurrentThread, &MmSystemCacheWs);
381 
382  /* Flush the entire TLB */
384 
385  /* Done */
386  return ActualPages;
387 }
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
FORCEINLINE VOID MI_ERASE_PTE(IN PMMPTE PointerPte)
Definition: miarm.h:957
#define TRUE
Definition: types.h:120
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
ULONG PFN_COUNT
Definition: mmtypes.h:102
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
union _MMPFN::@1569 u4
union _MMPFN::@1564 u1
UCHAR KIRQL
Definition: env_spec_w32.h:591
ULONG PFN_NUMBER
Definition: ke.h:8
MMSUPPORT MmSystemCacheWs
Definition: init.c:55
VOID NTAPI MiDecrementShareCount(IN PMMPFN Pfn1, IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:1133
FORCEINLINE VOID MiUnlockWorkingSet(IN PETHREAD Thread, IN PMMSUPPORT WorkingSet)
Definition: miarm.h:1247
VOID NTAPI KeFlushEntireTb(IN BOOLEAN Invalid, IN BOOLEAN AllProcessors)
Definition: cpu.c:423
VOID FASTCALL KeReleaseQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber, IN KIRQL OldIrql)
Definition: spinlock.c:154
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
Definition: mm.h:301
KIRQL FASTCALL KeAcquireQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber)
Definition: spinlock.c:108
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:873
#define MI_SET_PFN_DELETED(x)
Definition: miarm.h:161
ULONG_PTR PteFrame
Definition: mm.h:346
ULONG WsIndex
Definition: mm.h:306
FORCEINLINE VOID MiLockWorkingSet(IN PETHREAD Thread, IN PMMSUPPORT WorkingSet)
Definition: miarm.h:1203
#define APC_LEVEL
Definition: env_spec_w32.h:695
#define PFN_FROM_PTE(v)
Definition: mm.h:82
VOID NTAPI MiDeleteVirtualAddresses ( IN ULONG_PTR  Va,
IN ULONG_PTR  EndingAddress,
IN PMMVAD  Vad 
)

Definition at line 540 of file virtual.c.

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

543 {
544  PMMPTE PointerPte, PrototypePte, LastPrototypePte;
545  PMMPDE PointerPde;
546  MMPTE TempPte;
548  KIRQL OldIrql;
549  BOOLEAN AddressGap = FALSE;
550  PSUBSECTION Subsection;
551 
552  /* Get out if this is a fake VAD, RosMm will free the marea pages */
553  if ((Vad) && (Vad->u.VadFlags.Spare == 1)) return;
554 
555  /* Grab the process and PTE/PDE for the address being deleted */
556  CurrentProcess = PsGetCurrentProcess();
557  PointerPde = MiAddressToPde(Va);
558  PointerPte = MiAddressToPte(Va);
559 
560  /* Check if this is a section VAD or a VM VAD */
561  if (!(Vad) || (Vad->u.VadFlags.PrivateMemory) || !(Vad->FirstPrototypePte))
562  {
563  /* Don't worry about prototypes */
564  PrototypePte = LastPrototypePte = NULL;
565  }
566  else
567  {
568  /* Get the prototype PTE */
569  PrototypePte = Vad->FirstPrototypePte;
570  LastPrototypePte = Vad->FirstPrototypePte + 1;
571  }
572 
573  /* In all cases, we don't support fork() yet */
574  ASSERT(CurrentProcess->CloneRoot == NULL);
575 
576  /* Loop the PTE for each VA */
577  while (TRUE)
578  {
579  /* First keep going until we find a valid PDE */
580  while (!PointerPde->u.Long)
581  {
582  /* There are gaps in the address space */
583  AddressGap = TRUE;
584 
585  /* Still no valid PDE, try the next 4MB (or whatever) */
586  PointerPde++;
587 
588  /* Update the PTE on this new boundary */
589  PointerPte = MiPteToAddress(PointerPde);
590 
591  /* Check if all the PDEs are invalid, so there's nothing to free */
592  Va = (ULONG_PTR)MiPteToAddress(PointerPte);
593  if (Va > EndingAddress) return;
594  }
595 
596  /* Now check if the PDE is mapped in */
597  if (!PointerPde->u.Hard.Valid)
598  {
599  /* It isn't, so map it in */
600  PointerPte = MiPteToAddress(PointerPde);
601  MiMakeSystemAddressValid(PointerPte, CurrentProcess);
602  }
603 
604  /* Now we should have a valid PDE, mapped in, and still have some VA */
605  ASSERT(PointerPde->u.Hard.Valid == 1);
606  ASSERT(Va <= EndingAddress);
607 
608  /* Check if this is a section VAD with gaps in it */
609  if ((AddressGap) && (LastPrototypePte))
610  {
611  /* We need to skip to the next correct prototype PTE */
612  PrototypePte = MI_GET_PROTOTYPE_PTE_FOR_VPN(Vad, Va >> PAGE_SHIFT);
613 
614  /* And we need the subsection to skip to the next last prototype PTE */
615  Subsection = MiLocateSubsection(Vad, Va >> PAGE_SHIFT);
616  if (Subsection)
617  {
618  /* Found it! */
619  LastPrototypePte = &Subsection->SubsectionBase[Subsection->PtesInSubsection];
620  }
621  else
622  {
623  /* No more subsections, we are done with prototype PTEs */
624  PrototypePte = NULL;
625  }
626  }
627 
628  /* Lock the PFN Database while we delete the PTEs */
630  do
631  {
632  /* Capture the PDE and make sure it exists */
633  TempPte = *PointerPte;
634  if (TempPte.u.Long)
635  {
637 
638  /* Check if the PTE is actually mapped in */
639  if (MI_IS_MAPPED_PTE(&TempPte))
640  {
641  /* Are we dealing with section VAD? */
642  if ((LastPrototypePte) && (PrototypePte > LastPrototypePte))
643  {
644  /* We need to skip to the next correct prototype PTE */
645  PrototypePte = MI_GET_PROTOTYPE_PTE_FOR_VPN(Vad, Va >> PAGE_SHIFT);
646 
647  /* And we need the subsection to skip to the next last prototype PTE */
648  Subsection = MiLocateSubsection(Vad, Va >> PAGE_SHIFT);
649  if (Subsection)
650  {
651  /* Found it! */
652  LastPrototypePte = &Subsection->SubsectionBase[Subsection->PtesInSubsection];
653  }
654  else
655  {
656  /* No more subsections, we are done with prototype PTEs */
657  PrototypePte = NULL;
658  }
659  }
660 
661  /* Check for prototype PTE */
662  if ((TempPte.u.Hard.Valid == 0) &&
663  (TempPte.u.Soft.Prototype == 1))
664  {
665  /* Just nuke it */
666  MI_ERASE_PTE(PointerPte);
667  }
668  else
669  {
670  /* Delete the PTE proper */
671  MiDeletePte(PointerPte,
672  (PVOID)Va,
673  CurrentProcess,
674  PrototypePte);
675  }
676  }
677  else
678  {
679  /* The PTE was never mapped, just nuke it here */
680  MI_ERASE_PTE(PointerPte);
681  }
682  }
683 
684  /* Update the address and PTE for it */
685  Va += PAGE_SIZE;
686  PointerPte++;
687  PrototypePte++;
688 
689  /* Making sure the PDE is still valid */
690  ASSERT(PointerPde->u.Hard.Valid == 1);
691  }
692  while ((Va & (PDE_MAPPED_VA - 1)) && (Va <= EndingAddress));
693 
694  /* The PDE should still be valid at this point */
695  ASSERT(PointerPde->u.Hard.Valid == 1);
696 
697  /* Check remaining PTE count (go back 1 page due to above loop) */
698  if (MiQueryPageTableReferences((PVOID)(Va - PAGE_SIZE)) == 0)
699  {
700  if (PointerPde->u.Long != 0)
701  {
702  /* Delete the PTE proper */
703  MiDeletePte(PointerPde,
704  MiPteToAddress(PointerPde),
705  CurrentProcess,
706  NULL);
707  }
708  }
709 
710  /* Release the lock and get out if we're done */
712  if (Va > EndingAddress) return;
713 
714  /* Otherwise, we exited because we hit a new PDE boundary, so start over */
715  PointerPde = MiAddressToPde(Va);
716  AddressGap = FALSE;
717  }
718 }
DWORD *typedef PVOID
Definition: winlogon.h:52
ULONG NTAPI MiMakeSystemAddressValid(IN PVOID PageTableVirtualAddress, IN PEPROCESS CurrentProcess)
Definition: virtual.c:205
FORCEINLINE VOID MI_ERASE_PTE(IN PMMPTE PointerPte)
Definition: miarm.h:957
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
MMPTE PrototypePte
Definition: init.c:42
#define TRUE
Definition: types.h:120
#define MiAddressToPde(x)
Definition: mmx86.c:20
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
FORCEINLINE USHORT MiQueryPageTableReferences(IN PVOID Address)
Definition: miarm.h:1659
PVOID CloneRoot
Definition: pstypes.h:1231
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define MiAddressToPte(x)
Definition: mmx86.c:19
#define FALSE
Definition: types.h:117
#define PsGetCurrentProcess
Definition: psfuncs.h:17
smooth NULL
Definition: ftsmooth.c:557
PVOID FORCEINLINE MiPteToAddress(PMMPTE PointerPte)
Definition: mm.h:185
#define PDE_MAPPED_VA
Definition: miarm.h:20
unsigned char BOOLEAN
FORCEINLINE VOID MiDecrementPageTableReferences(IN PVOID Address)
Definition: miarm.h:1647
ULONG CurrentProcess
Definition: shell.c:125
ULONG64 Valid
Definition: mmtypes.h:150
VOID FASTCALL KeReleaseQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber, IN KIRQL OldIrql)
Definition: spinlock.c:154
HARDWARE_PTE_ARMV6 TempPte
Definition: winldr.c:75
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
ULONG64 Prototype
Definition: mmtypes.h:89
#define PAGE_SIZE
Definition: env_spec_w32.h:49
KIRQL FASTCALL KeAcquireQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber)
Definition: spinlock.c:108
ULONG_PTR Long
Definition: mmtypes.h:215
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217
PSUBSECTION NTAPI MiLocateSubsection(IN PMMVAD Vad, IN ULONG_PTR Vpn)
Definition: section.c:570
MMPTE_SOFTWARE Soft
Definition: mmtypes.h:219
VOID NTAPI MiDeletePte(IN PMMPTE PointerPte, IN PVOID VirtualAddress, IN PEPROCESS CurrentProcess, IN PMMPTE PrototypePte)
Definition: virtual.c:391
FORCEINLINE BOOLEAN MI_IS_MAPPED_PTE(PMMPTE PointerPte)
Definition: mm.h:267
#define ULONG_PTR
Definition: config.h:101
union _MMPTE::@2072 u
PMMPTE SubsectionBase
Definition: mmtypes.h:571
FORCEINLINE PMMPTE MI_GET_PROTOTYPE_PTE_FOR_VPN(IN PMMVAD Vad, IN ULONG_PTR Vpn)
Definition: miarm.h:1374
ULONG PtesInSubsection
Definition: mmtypes.h:573
FORCEINLINE VOID MiDereferencePfnAndDropLockCount ( IN PMMPFN  Pfn1)

Definition at line 1432 of file miarm.h.

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

1433 {
1434  USHORT RefCount, OldRefCount;
1435  PFN_NUMBER PageFrameIndex;
1436 
1437  /* Loop while we decrement the page successfully */
1438  do
1439  {
1440  /* There should be at least one reference */
1441  OldRefCount = Pfn1->u3.e2.ReferenceCount;
1442  ASSERT(OldRefCount != 0);
1443 
1444  /* Are we the last one */
1445  if (OldRefCount == 1)
1446  {
1447  /* The page shoudln't be shared not active at this point */
1448  ASSERT(Pfn1->u3.e2.ReferenceCount == 1);
1449  ASSERT(Pfn1->u3.e1.PageLocation != ActiveAndValid);
1450  ASSERT(Pfn1->u2.ShareCount == 0);
1451 
1452  /* Is it a prototype PTE? */
1453  if ((Pfn1->u3.e1.PrototypePte == 1) &&
1454  (Pfn1->OriginalPte.u.Soft.Prototype == 1))
1455  {
1456  /* FIXME: We should return commit */
1457  DPRINT1("Not returning commit for prototype PTE\n");
1458  }
1459 
1460  /* Update the counter, and drop a reference the long way */
1462  PageFrameIndex = MiGetPfnEntryIndex(Pfn1);
1463  MiDecrementReferenceCount(Pfn1, PageFrameIndex);
1464  return;
1465  }
1466 
1467  /* Drop a reference the short way, and that's it */
1468  RefCount = InterlockedCompareExchange16((PSHORT)&Pfn1->u3.e2.ReferenceCount,
1469  OldRefCount - 1,
1470  OldRefCount);
1471  ASSERT(RefCount != 0);
1472  } while (OldRefCount != RefCount);
1473 
1474  /* If we got here, there should be more than one reference */
1475  ASSERT(RefCount > 1);
1476  if (RefCount == 2)
1477  {
1478  /* Is it still being shared? */
1479  if (Pfn1->u2.ShareCount >= 1)
1480  {
1481  /* Then it should be valid */
1482  ASSERT(Pfn1->u3.e1.PageLocation == ActiveAndValid);
1483 
1484  /* Is it a prototype PTE? */
1485  if ((Pfn1->u3.e1.PrototypePte == 1) &&
1486  (Pfn1->OriginalPte.u.Soft.Prototype == 1))
1487  {
1488  /* We don't handle ethis */
1489  ASSERT(FALSE);
1490  }
1491 
1492  /* Update the counter */
1494  }
1495  }
1496 }
signed short * PSHORT
Definition: retypes.h:6
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
SIZE_T MmSystemLockPagesCount
Definition: mdlsup.c:22
ULONG PFN_NUMBER
Definition: ke.h:8
#define FALSE
Definition: types.h:117
VOID NTAPI MiDecrementReferenceCount(IN PMMPFN Pfn1, IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:1222
unsigned short USHORT
Definition: pedump.c:61
#define InterlockedCompareExchange16
Definition: interlocked.h:109
#define DPRINT1
Definition: precomp.h:8
FORCEINLINE PFN_NUMBER MiGetPfnEntryIndex(IN PMMPFN Pfn1)
Definition: mm.h:893
#define InterlockedDecrementSizeT(a)
Definition: interlocked.h:153
FORCEINLINE ULONG_PTR MiDetermineUserGlobalPteMask ( IN PVOID  PointerPte)

Definition at line 709 of file miarm.h.

Referenced by MI_MAKE_HARDWARE_PTE(), and MiResolveTransitionFault().

710 {
711  MMPTE TempPte;
712 
713  /* Start fresh */
714  TempPte.u.Long = 0;
715 
716  /* Make it valid and accessed */
717  TempPte.u.Hard.Valid = TRUE;
718  MI_MAKE_ACCESSED_PAGE(&TempPte);
719 
720  /* Is this for user-mode? */
721  if (
722 #if (_MI_PAGING_LEVELS == 4)
723  MiIsUserPxe(PointerPte) ||
724 #endif
725 #if (_MI_PAGING_LEVELS >= 3)
726  MiIsUserPpe(PointerPte) ||
727 #endif
728  MiIsUserPde(PointerPte) ||
729  MiIsUserPte(PointerPte))
730  {
731  /* Set the owner bit */
732  MI_MAKE_OWNER_PAGE(&TempPte);
733  }
734 
735  /* FIXME: We should also set the global bit */
736 
737  /* Return the protection */
738  return TempPte.u.Long;
739 }
#define _MI_PAGING_LEVELS
Definition: mm.h:6
#define TRUE
Definition: types.h:120
#define MI_MAKE_ACCESSED_PAGE(x)
Definition: mm.h:90
#define MI_MAKE_OWNER_PAGE(x)
Definition: mm.h:102
FORCEINLINE BOOLEAN MiIsUserPde(PVOID Address)
Definition: miarm.h:690
ULONG64 Valid
Definition: mmtypes.h:150
HARDWARE_PTE_ARMV6 TempPte
Definition: winldr.c:75
FORCEINLINE BOOLEAN MiIsUserPte(PVOID Address)
Definition: miarm.h:698
ULONG_PTR Long
Definition: mmtypes.h:215
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217
union _MMPTE::@2072 u
FORCEINLINE VOID MiDropLockCount ( IN PMMPFN  Pfn1)

Definition at line 1402 of file miarm.h.

Referenced by MiResolveTransitionFault().

1403 {
1404  /* This page shouldn't be locked, but it should be valid */
1405  ASSERT(Pfn1->u3.e2.ReferenceCount != 0);
1406  ASSERT(Pfn1->u2.ShareCount == 0);
1407 
1408  /* Is this the last reference to the page */
1409  if (Pfn1->u3.e2.ReferenceCount == 1)
1410  {
1411  /* It better not be valid */
1412  ASSERT(Pfn1->u3.e1.PageLocation != ActiveAndValid);
1413 
1414  /* Is it a prototype PTE? */
1415  if ((Pfn1->u3.e1.PrototypePte == 1) &&
1416  (Pfn1->OriginalPte.u.Soft.Prototype == 1))
1417  {
1418  /* FIXME: We should return commit */
1419  DPRINT1("Not returning commit for prototype PTE\n");
1420  }
1421 
1422  /* Update the counter */
1424  }
1425 }
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
SIZE_T MmSystemLockPagesCount
Definition: mdlsup.c:22
#define DPRINT1
Definition: precomp.h:8
#define InterlockedDecrementSizeT(a)
Definition: interlocked.h:153
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.

Referenced by MiFindContiguousMemory().

27 {
28  PFN_NUMBER Page, PageCount, LastPage, Length, BoundaryMask;
29  ULONG i = 0;
30  PMMPFN Pfn1, EndPfn;
31  KIRQL OldIrql;
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  //
52  PageCount = MmPhysicalMemoryBlock->Run[i].PageCount;
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  //
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)0xBAADF00D;
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  //
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  //
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 }
DWORD *typedef PVOID
Definition: winlogon.h:52
#define TRUE
Definition: types.h:120
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
PFN_NUMBER PageCount
Definition: miarm.h:396
union _MMPFN::@1569 u4
PHYSICAL_MEMORY_RUN Run[1]
Definition: miarm.h:403
USHORT PageLocation
Definition: mm.h:293
USHORT PrototypePte
Definition: mm.h:291
UCHAR KIRQL
Definition: env_spec_w32.h:591
MMPFNENTRY e1
Definition: mm.h:325
union _MMPFN::@1566 u3
GLenum GLclampf GLint i
Definition: glfuncs.h:14
ULONG PFN_NUMBER
Definition: ke.h:8
ULONG_PTR ShareCount
Definition: mm.h:318
PFN_NUMBER BasePage
Definition: miarm.h:395
#define MI_SET_PROCESS2(x)
Definition: mm.h:250
#define KeLeaveGuardedRegion()
Definition: ke_x.h:63
ULONG_PTR VerifierAllocation
Definition: mm.h:348
#define MI_SET_USAGE(x)
Definition: mm.h:249
PPHYSICAL_MEMORY_DESCRIPTOR MmPhysicalMemoryBlock
Definition: init.c:45
VOID FASTCALL KeReleaseQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber, IN KIRQL OldIrql)
Definition: spinlock.c:154
#define PAGED_CODE()
Definition: video.h:57
#define KeEnterGuardedRegion()
Definition: ke_x.h:34
FORCEINLINE PMMPFN MI_PFN_ELEMENT(IN PFN_NUMBER Pfn)
Definition: miarm.h:1391
VOID UINTN Length
Definition: acefiex.h:744
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
Definition: mm.h:301
KIRQL FASTCALL KeAcquireQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber)
Definition: spinlock.c:108
PMMPTE PteAddress
Definition: mm.h:314
struct _MMPFN::@1566::@1572 e2
unsigned int ULONG
Definition: retypes.h:1
BOOLEAN NTAPI MiIsPfnInUse(IN PMMPFN Pfn1)
Definition: freelist.c:142
static BYTE u3[]
Definition: msg.c:580
union _MMPFN::@1565 u2
VOID NTAPI MiUnlinkFreeOrZeroedPage(IN PMMPFN Entry)
Definition: pfnlist.c:137
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 707 of file vadnode.c.

Referenced by MmCreateArm3Section().

712 {
713  PMMADDRESS_NODE Node, LowestNode;
714  ULONG_PTR LowVpn, BestVpn;
715 
716  /* Sanity checks */
718  ASSERT(BoundaryAddress);
719  ASSERT(BoundaryAddress <= ((ULONG_PTR)MM_HIGHEST_VAD_ADDRESS + 1));
720 
721  /* Compute page length, make sure the boundary address is valid */
723  if ((BoundaryAddress + 1) < Length) return STATUS_NO_MEMORY;
724 
725  /* Check if the table is empty */
726  BestVpn = ROUND_DOWN(BoundaryAddress + 1 - Length, Alignment);
727  if (Table->NumberGenericTableElements == 0)
728  {
729  /* Tree is empty, the candidate address is already the best one */
730  *Base = BestVpn;
731  return STATUS_SUCCESS;
732  }
733 
734  /* Go to the right-most node which should be the biggest address */
735  Node = Table->BalancedRoot.RightChild;
736  while (RtlRightChildAvl(Node)) Node = RtlRightChildAvl(Node);
737 
738  /* Check if we can fit in here */
739  LowVpn = ROUND_UP(Node->EndingVpn + 1, Alignment);
740  if ((LowVpn < BoundaryAddress) && (Length <= (BoundaryAddress - LowVpn)))
741  {
742 #if (NTDDI_VERSION >= NTDDI_VISTA)
743  /* Return the address. */
744  *Base = BestVpn;
745 #else
746  /* Note: this is a compatibility hack that mimics a bug in the 2k3
747  kernel. It will can waste up to Alignment bytes of memory above
748  the allocation. This bug was fixed in Windows Vista */
749  *Base = ROUND_DOWN(BoundaryAddress - Length, Alignment);
750 #endif
751  return STATUS_SUCCESS;
752  }
753 
754  /* Now loop the Vad nodes */
755  do
756  {
757  /* Break out if we've reached the last node */
758  LowestNode = MiGetPreviousNode(Node);
759  if (!LowestNode) break;
760 
761  /* Check if this node could contain the requested address */
762  LowVpn = ROUND_UP(LowestNode->EndingVpn + 1, Alignment);
763  if ((LowestNode->EndingVpn < BestVpn) &&
764  (LowVpn < Node->StartingVpn) &&
765  (Length <= (Node->StartingVpn - LowVpn)))
766  {
767  /* Check if we need to take BoundaryAddress into account */
768  if (BoundaryAddress < Node->StartingVpn)
769  {
770  /* Return the optimal VPN address */
771  *Base = BestVpn;
772  return STATUS_SUCCESS;
773  }
774  else
775  {
776  /* The upper margin is given by the Node's starting address */
778  return STATUS_SUCCESS;
779  }
780  }
781 
782  /* Move to the next node */
783  Node = LowestNode;
784  } while (TRUE);
785 
786  /* Check if there's enough space before the lowest Vad */
788  ((Node->StartingVpn - (ULONG_PTR)MI_LOWEST_VAD_ADDRESS) >= Length))
789  {
790  /* Check if it fits in perfectly */
791  if (BoundaryAddress < Node->StartingVpn)
792  {
793  /* Return the optimal VPN address */
794  *Base = BestVpn;
795  return STATUS_SUCCESS;
796  }
797 
798  /* Return an aligned base address within this node */
800  return STATUS_SUCCESS;
801  }
802 
803  /* No address space left at all */
804  return STATUS_NO_MEMORY;
805 }
#define TRUE
Definition: types.h:120
MM_AVL_TABLE MmSectionBasedRoot
Definition: section.c:109
#define ROUND_UP(n, align)
Definition: eventvwr.h:31
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
#define MI_LOWEST_VAD_ADDRESS
Definition: miarm.h:9
return STATUS_SUCCESS
Definition: btrfs.c:2664
_In_opt_ ULONG Base
Definition: rtlfuncs.h:2327
#define RtlRightChildAvl
Definition: miavl.h:45
uint32_t ULONG_PTR
Definition: typedefs.h:63
ULONG_PTR StartingVpn
Definition: mmtypes.h:654
ULONG_PTR EndingVpn
Definition: mmtypes.h:655
VOID UINTN Length
Definition: acefiex.h:744
#define ROUND_DOWN(n, align)
Definition: eventvwr.h:30
#define ROUND_TO_PAGES(Size)
#define STATUS_NO_MEMORY
Definition: ntstatus.h:246
#define MM_HIGHEST_VAD_ADDRESS
Definition: mm.h:36
PMMADDRESS_NODE NTAPI MiGetPreviousNode(IN PMMADDRESS_NODE Node)
Definition: vadnode.c:431
union gl_dlist_node Node
Definition: dlist.c:302
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 597 of file vadnode.c.

Referenced by MiInsertVadEx(), and MmFindGap().

603 {
604  PMMADDRESS_NODE Node, OldNode, Child;
605  ULONG_PTR LowVpn, HighVpn, AlignmentVpn;
606  PFN_NUMBER PageCount;
607 
608  /* Sanity checks */
609  ASSERT(BoundaryAddress);
610  ASSERT(BoundaryAddress <= ((ULONG_PTR)MM_HIGHEST_VAD_ADDRESS));
611  ASSERT((Alignment & (PAGE_SIZE - 1)) == 0);
612 
613  /* Calculate page numbers for the length and alignment */
615  PageCount = Length >> PAGE_SHIFT;
616  AlignmentVpn = Alignment / PAGE_SIZE;
617 
618  /* Check for kernel mode table (memory areas) */
619  if (Table->Unused == 1)
620  {
621  LowVpn = ALIGN_UP_BY((ULONG_PTR)MmSystemRangeStart >> PAGE_SHIFT, AlignmentVpn);
622  }
623  else
624  {
626  }
627 
628  /* Check if there is enough space below the boundary */
629  if ((LowVpn + Length) > (BoundaryAddress + 1))
630  {
631  return TableFoundNode;
632  }
633 
634  /* Check if the table is empty */
635  if (Table->NumberGenericTableElements == 0)
636  {
637  /* Tree is empty, the candidate address is already the best one */
638  *Base = ALIGN_DOWN_BY(BoundaryAddress + 1 - Length, Alignment);
639  return TableEmptyTree;
640  }
641 
642  /* Calculate the initial upper margin */
643  HighVpn = (BoundaryAddress + 1) >> PAGE_SHIFT;
644 
645  /* Starting from the root, follow the right children until we found a node
646  that ends above the boundary */
647  Node = RtlRightChildAvl(&Table->BalancedRoot);
648  while ((Node->EndingVpn < HighVpn) &&
649  ((Child = RtlRightChildAvl(Node)) != NULL)) Node = Child;
650 
651  /* Now loop the Vad nodes */
652  while (Node)
653  {
654  /* Calculate the lower margin */
655  LowVpn = ALIGN_UP_BY(Node->EndingVpn + 1, AlignmentVpn);
656 
657  /* Check if the current bounds are suitable */
658  if ((HighVpn > LowVpn) && ((HighVpn - LowVpn) >= PageCount))
659  {
660  /* There is enough space to add our node */
661  LowVpn = ALIGN_DOWN_BY(HighVpn - PageCount, AlignmentVpn);
662  *Base = LowVpn << PAGE_SHIFT;
663 
664  /* Can we use the current node as parent? */
665  if (!RtlRightChildAvl(Node))
666  {
667  /* Node has no right child, so use it as parent */
668  *Parent = Node;
669  return TableInsertAsRight;
670  }
671  else
672  {
673  /* Node has a right child, the node we had before is the most
674  left grandchild of that right child, use it as parent. */
675  *Parent = OldNode;
676  return TableInsertAsLeft;
677  }
678  }
679 
680  /* Update the upper margin if necessary */
681  if (Node->StartingVpn < HighVpn) HighVpn = Node->StartingVpn;
682 
683  /* Remember the current node and go to the previous node */
684  OldNode = Node;
685  Node = MiGetPreviousNode(Node);
686  }
687 
688  /* Check if there's enough space before the lowest Vad */
690  if ((HighVpn > LowVpn) && ((HighVpn - LowVpn) >= PageCount))
691  {
692  /* There is enough space to add our address */
693  LowVpn = ALIGN_DOWN_BY(HighVpn - PageCount, Alignment >> PAGE_SHIFT);
694  *Base = LowVpn << PAGE_SHIFT;
695  *Parent = OldNode;
696  return TableInsertAsLeft;
697  }
698 
699  /* No address space left at all */
700  *Base = 0;
701  *Parent = NULL;
702  return TableFoundNode;
703 }
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
#define MI_LOWEST_VAD_ADDRESS
De