ReactOS 0.4.16-dev-981-g80eb313
miarm.h File Reference
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

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

Macros

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

Typedefs

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

Enumerations

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

Functions

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

Variables

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

Macro Definition Documentation

◆ _1GB

#define _1GB   (1024 * _1MB)

Definition at line 20 of file miarm.h.

◆ _1KB

#define _1KB   (1024u)

Definition at line 18 of file miarm.h.

◆ _1MB

#define _1MB   (1024 * _1KB)

Definition at line 19 of file miarm.h.

◆ _64K

#define _64K   (64 * _1KB)

Definition at line 23 of file miarm.h.

◆ BASE_POOL_TYPE_MASK

#define BASE_POOL_TYPE_MASK   1

Definition at line 286 of file miarm.h.

◆ IMAGE_SCN_PROTECTION_MASK

#define IMAGE_SCN_PROTECTION_MASK   (IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE)

Definition at line 174 of file miarm.h.

◆ MI_GET_NEXT_COLOR

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

Definition at line 246 of file miarm.h.

◆ MI_GET_NEXT_PROCESS_COLOR

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

Definition at line 247 of file miarm.h.

◆ MI_GET_PAGE_COLOR

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

Definition at line 245 of file miarm.h.

◆ MI_INITIAL_SESSION_IDS

#define MI_INITIAL_SESSION_IDS   64

Definition at line 221 of file miarm.h.

◆ MI_IS_PAGE_TABLE_ADDRESS

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

Definition at line 191 of file miarm.h.

◆ MI_IS_PAGE_TABLE_OR_HYPER_ADDRESS

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

Definition at line 197 of file miarm.h.

◆ MI_IS_PFN_DELETED

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

Definition at line 209 of file miarm.h.

◆ MI_IS_ROS_PFN

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

Definition at line 1116 of file miarm.h.

◆ MI_IS_SESSION_ADDRESS

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

Definition at line 185 of file miarm.h.

◆ MI_IS_SESSION_IMAGE_ADDRESS

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

Definition at line 182 of file miarm.h.

◆ MI_IS_SESSION_PTE

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

Definition at line 188 of file miarm.h.

◆ MI_IS_SYSTEM_PAGE_TABLE_ADDRESS

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

Definition at line 194 of file miarm.h.

◆ MI_LOWEST_VAD_ADDRESS

#define MI_LOWEST_VAD_ADDRESS   (PVOID)MM_LOWEST_USER_ADDRESS

Definition at line 15 of file miarm.h.

◆ MI_MAKE_SOFTWARE_PTE

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

Definition at line 203 of file miarm.h.

◆ MI_PTE_LOOKUP_NEEDED

#define MI_PTE_LOOKUP_NEEDED   0xFFFFF

Definition at line 255 of file miarm.h.

◆ MI_SESSION_DATA_PAGES_MAXIMUM

#define MI_SESSION_DATA_PAGES_MAXIMUM   (MM_ALLOCATION_GRANULARITY / PAGE_SIZE)

Definition at line 261 of file miarm.h.

◆ MI_SESSION_TAG_PAGES_MAXIMUM

#define MI_SESSION_TAG_PAGES_MAXIMUM   (MM_ALLOCATION_GRANULARITY / PAGE_SIZE)

Definition at line 262 of file miarm.h.

◆ MI_SET_PFN_DELETED

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

Definition at line 208 of file miarm.h.

◆ MI_SYSTEM_VIEW_BUCKET_SIZE

#define MI_SYSTEM_VIEW_BUCKET_SIZE   _64K

Definition at line 275 of file miarm.h.

◆ MM_DECOMMIT

#define MM_DECOMMIT   (MM_ZERO_ACCESS | MM_GUARDPAGE)

Definition at line 64 of file miarm.h.

◆ MM_DELETE_CHECK

#define MM_DELETE_CHECK   85

Definition at line 270 of file miarm.h.

◆ MM_EXECUTE

#define MM_EXECUTE   2

Definition at line 45 of file miarm.h.

◆ MM_EXECUTE_READ

#define MM_EXECUTE_READ   3

Definition at line 46 of file miarm.h.

◆ MM_EXECUTE_READWRITE

#define MM_EXECUTE_READWRITE   6

Definition at line 49 of file miarm.h.

◆ MM_EXECUTE_WRITECOPY

#define MM_EXECUTE_WRITECOPY   7

Definition at line 50 of file miarm.h.

◆ MM_GUARDPAGE

#define MM_GUARDPAGE   0x10

Definition at line 57 of file miarm.h.

◆ MM_INVALID_PROTECTION

#define MM_INVALID_PROTECTION   0xFFFFFFFF

Definition at line 67 of file miarm.h.

◆ MM_NO_ACCESS_ALLOWED

#define MM_NO_ACCESS_ALLOWED   01

Definition at line 269 of file miarm.h.

◆ MM_NOACCESS

#define MM_NOACCESS   (MM_ZERO_ACCESS | MM_WRITECOMBINE)

Definition at line 65 of file miarm.h.

◆ MM_NOCACHE

#define MM_NOCACHE   0x08

Definition at line 56 of file miarm.h.

◆ MM_OUTSWAPPED_KSTACK

#define MM_OUTSWAPPED_KSTACK   (MM_EXECUTE_WRITECOPY | MM_WRITECOMBINE)

Definition at line 66 of file miarm.h.

◆ MM_PROTECT_ACCESS

#define MM_PROTECT_ACCESS   7

Definition at line 51 of file miarm.h.

◆ MM_PROTECT_SPECIAL

#define MM_PROTECT_SPECIAL   0x18

Definition at line 59 of file miarm.h.

◆ MM_READ_ONLY_ALLOWED

#define MM_READ_ONLY_ALLOWED   10

Definition at line 268 of file miarm.h.

◆ MM_READ_WRITE_ALLOWED

#define MM_READ_WRITE_ALLOWED   11

Definition at line 267 of file miarm.h.

◆ MM_READONLY

#define MM_READONLY   1

Definition at line 44 of file miarm.h.

◆ MM_READWRITE

#define MM_READWRITE   4

Definition at line 47 of file miarm.h.

◆ MM_SYSLDR_BOOT_LOADED

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

Definition at line 215 of file miarm.h.

◆ MM_SYSLDR_NO_IMPORTS

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

Definition at line 214 of file miarm.h.

◆ MM_SYSLDR_SINGLE_ENTRY

#define MM_SYSLDR_SINGLE_ENTRY   0x1

Definition at line 216 of file miarm.h.

◆ MM_WRITECOMBINE

#define MM_WRITECOMBINE   0x18

Definition at line 58 of file miarm.h.

◆ MM_WRITECOPY

#define MM_WRITECOPY   5

Definition at line 48 of file miarm.h.

◆ MM_ZERO_ACCESS

#define MM_ZERO_ACCESS   0

Definition at line 43 of file miarm.h.

◆ PD_SIZE

#define PD_SIZE   (PDE_PER_PAGE * sizeof(MMPDE))

Definition at line 29 of file miarm.h.

◆ POOL_ALLOC_IRQL_INVALID

#define POOL_ALLOC_IRQL_INVALID   8

Definition at line 318 of file miarm.h.

◆ POOL_BILLED_PROCESS_INVALID

#define POOL_BILLED_PROCESS_INVALID   13

Definition at line 320 of file miarm.h.

◆ POOL_BLOCK_SIZE

#define POOL_BLOCK_SIZE   8

Definition at line 283 of file miarm.h.

◆ POOL_CORRUPTED_LIST

#define POOL_CORRUPTED_LIST   3

Definition at line 304 of file miarm.h.

◆ POOL_ENTRIES_NOT_ALIGNED_NEXT

#define POOL_ENTRIES_NOT_ALIGNED_NEXT   9

Definition at line 309 of file miarm.h.

◆ POOL_ENTRIES_NOT_ALIGNED_PREVIOUS

#define POOL_ENTRIES_NOT_ALIGNED_PREVIOUS   6

Definition at line 306 of file miarm.h.

◆ POOL_ENTRY_ALREADY_FREE

#define POOL_ENTRY_ALREADY_FREE   6

Definition at line 316 of file miarm.h.

◆ POOL_ENTRY_CORRUPTED

#define POOL_ENTRY_CORRUPTED   1

Definition at line 315 of file miarm.h.

◆ POOL_ENTRY_NOT_ALLOCATED

#define POOL_ENTRY_NOT_ALLOCATED   7

Definition at line 317 of file miarm.h.

◆ POOL_ENTRY_NOT_FOUND

#define POOL_ENTRY_NOT_FOUND   10

Definition at line 310 of file miarm.h.

◆ POOL_FLAG_CHECK_DEADLOCK

#define POOL_FLAG_CHECK_DEADLOCK   0x10

Definition at line 296 of file miarm.h.

◆ POOL_FLAG_CHECK_RESOURCES

#define POOL_FLAG_CHECK_RESOURCES   0x4

Definition at line 294 of file miarm.h.

◆ POOL_FLAG_CHECK_TIMERS

#define POOL_FLAG_CHECK_TIMERS   0x1

Definition at line 292 of file miarm.h.

◆ POOL_FLAG_CHECK_WORKERS

#define POOL_FLAG_CHECK_WORKERS   0x2

Definition at line 293 of file miarm.h.

◆ POOL_FLAG_CRASH_ON_FAILURE

#define POOL_FLAG_CRASH_ON_FAILURE   0x80

Definition at line 299 of file miarm.h.

◆ POOL_FLAG_DBGPRINT_ON_FAILURE

#define POOL_FLAG_DBGPRINT_ON_FAILURE   0x40

Definition at line 298 of file miarm.h.

◆ POOL_FLAG_SPECIAL_POOL

#define POOL_FLAG_SPECIAL_POOL   0x20

Definition at line 297 of file miarm.h.

◆ POOL_FLAG_VERIFIER

#define POOL_FLAG_VERIFIER   0x8

Definition at line 295 of file miarm.h.

◆ POOL_FREE_IRQL_INVALID

#define POOL_FREE_IRQL_INVALID   9

Definition at line 319 of file miarm.h.

◆ POOL_HEADER_IS_ZERO

#define POOL_HEADER_IS_ZERO   8

Definition at line 308 of file miarm.h.

◆ POOL_HEADER_NOT_ALIGNED

#define POOL_HEADER_NOT_ALIGNED   7

Definition at line 307 of file miarm.h.

◆ POOL_HEADER_SIZE_INVALID

#define POOL_HEADER_SIZE_INVALID   32

Definition at line 321 of file miarm.h.

◆ POOL_LISTS_PER_PAGE

#define POOL_LISTS_PER_PAGE   (PAGE_SIZE / POOL_BLOCK_SIZE)

Definition at line 285 of file miarm.h.

◆ POOL_MAX_ALLOC

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

Definition at line 287 of file miarm.h.

◆ POOL_SIZE_OR_INDEX_MISMATCH

#define POOL_SIZE_OR_INDEX_MISMATCH   5

Definition at line 305 of file miarm.h.

◆ PT_SIZE

#define PT_SIZE   (PTE_PER_PAGE * sizeof(MMPTE))

Definition at line 26 of file miarm.h.

◆ PTE_MAPPING_ADDRESS_EMPTY

#define PTE_MAPPING_ADDRESS_EMPTY   0x109

Definition at line 169 of file miarm.h.

◆ PTE_MAPPING_ADDRESS_INVALID

#define PTE_MAPPING_ADDRESS_INVALID   0x105

Definition at line 167 of file miarm.h.

◆ PTE_MAPPING_ADDRESS_NOT_OWNED

#define PTE_MAPPING_ADDRESS_NOT_OWNED   0x104

Definition at line 166 of file miarm.h.

◆ PTE_MAPPING_EMPTY

#define PTE_MAPPING_EMPTY   0x102

Definition at line 164 of file miarm.h.

◆ PTE_MAPPING_NONE

#define PTE_MAPPING_NONE   0x100

Definition at line 162 of file miarm.h.

◆ PTE_MAPPING_NOT_OWNED

#define PTE_MAPPING_NOT_OWNED   0x101

Definition at line 163 of file miarm.h.

◆ PTE_MAPPING_RESERVED

#define PTE_MAPPING_RESERVED   0x103

Definition at line 165 of file miarm.h.

◆ PTE_UNMAPPING_ADDRESS_NOT_OWNED

#define PTE_UNMAPPING_ADDRESS_NOT_OWNED   0x108

Definition at line 168 of file miarm.h.

◆ SYSTEM_PD_SIZE

#define SYSTEM_PD_SIZE   (PPE_PER_PAGE * PD_SIZE)

Definition at line 32 of file miarm.h.

Typedef Documentation

◆ MI_LARGE_PAGE_DRIVER_ENTRY

◆ MI_LARGE_PAGE_RANGES

◆ MI_PFN_CACHE_ATTRIBUTE

◆ MM_SESSION_SPACE

◆ MM_SESSION_SPACE_FLAGS

◆ MMCOLOR_TABLES

◆ MMSESSION

◆ MMSYSTEM_PTE_POOL_TYPE

◆ MMVIEW

◆ PHYSICAL_MEMORY_DESCRIPTOR

◆ PHYSICAL_MEMORY_RUN

◆ PMI_LARGE_PAGE_DRIVER_ENTRY

◆ PMI_LARGE_PAGE_RANGES

◆ PMI_PFN_CACHE_ATTRIBUTE

◆ PMM_SESSION_SPACE

◆ PMMCOLOR_TABLES

◆ PMMSESSION

◆ PMMVIEW

typedef struct _MMVIEW * PMMVIEW

◆ POOL_DESCRIPTOR

◆ POOL_HEADER

◆ POOL_TRACKER_BIG_PAGES

◆ POOL_TRACKER_TABLE

◆ PPHYSICAL_MEMORY_DESCRIPTOR

◆ PPHYSICAL_MEMORY_RUN

◆ PPOOL_DESCRIPTOR

◆ PPOOL_HEADER

◆ PPOOL_TRACKER_BIG_PAGES

◆ PPOOL_TRACKER_TABLE

Enumeration Type Documentation

◆ _MI_PFN_CACHE_ATTRIBUTE

Enumerator
MiNonCached 
MiCached 
MiWriteCombined 
MiNotMapped 

Definition at line 422 of file miarm.h.

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

◆ _MMSYSTEM_PTE_POOL_TYPE

Enumerator
SystemPteSpace 
NonPagedPoolExpansion 
MaximumPtePoolTypes 

Definition at line 415 of file miarm.h.

416{
@ SystemPteSpace
Definition: miarm.h:417
@ MaximumPtePoolTypes
Definition: miarm.h:419
@ NonPagedPoolExpansion
Definition: miarm.h:418
enum _MMSYSTEM_PTE_POOL_TYPE MMSYSTEM_PTE_POOL_TYPE

Function Documentation

◆ C_ASSERT() [1/2]

C_ASSERT ( POOL_BLOCK_SIZE  = =sizeof(LIST_ENTRY))

◆ C_ASSERT() [2/2]

C_ASSERT ( sizeof(POOL_HEADER = =POOL_BLOCK_SIZE)

◆ ExInitializePoolDescriptor()

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

Definition at line 969 of file expool.c.

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

Referenced by InitializePool(), and MiInitializeSessionPool().

◆ InitializePool()

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

Definition at line 1020 of file expool.c.

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

Referenced by MiBuildPagedPool(), and MiInitMachineDependent().

◆ MI_ERASE_PTE()

FORCEINLINE VOID MI_ERASE_PTE ( IN PMMPTE  PointerPte)

Definition at line 1019 of file miarm.h.

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

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

◆ MI_GET_PROTOTYPE_PTE_FOR_VPN()

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

Definition at line 1570 of file miarm.h.

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

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

◆ MI_IS_MAPPED_PTE()

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

Definition at line 933 of file miarm.h.

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

◆ MI_IS_PHYSICAL_ADDRESS()

FORCEINLINE BOOLEAN MI_IS_PHYSICAL_ADDRESS ( IN PVOID  Address)

Definition at line 959 of file miarm.h.

960{
961 PMMPDE PointerPde;
962
963 /* Large pages are never paged out, always physically resident */
964 PointerPde = MiAddressToPde(Address);
965 return ((PointerPde->u.Hard.LargePage) && (PointerPde->u.Hard.Valid));
966}
#define MiAddressToPde(x)
Definition: mmx86.c:20
static WCHAR Address[46]
Definition: ping.c:68
ULONG64 LargePage
Definition: mmtypes.h:165
ULONG64 Valid
Definition: mmtypes.h:150
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217

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

◆ MI_IS_PROCESS_WORKING_SET()

FORCEINLINE BOOLEAN MI_IS_PROCESS_WORKING_SET ( PMMSUPPORT  WorkingSet)

Definition at line 675 of file miarm.h.

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

Referenced by MiInitializeWorkingSetList(), and MmWorkingSetManager().

◆ MI_IS_WS_UNSAFE()

FORCEINLINE BOOLEAN MI_IS_WS_UNSAFE ( IN PEPROCESS  Process)

Definition at line 1127 of file miarm.h.

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

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

◆ MI_MAKE_HARDWARE_PTE()

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

Definition at line 821 of file miarm.h.

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

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

◆ MI_MAKE_HARDWARE_PTE_KERNEL()

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

Definition at line 787 of file miarm.h.

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

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

◆ MI_MAKE_HARDWARE_PTE_USER()

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

Definition at line 841 of file miarm.h.

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

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

◆ MI_MAKE_PROTOTYPE_PTE()

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

Definition at line 868 of file miarm.h.

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

◆ MI_MAKE_SUBSECTION_PTE()

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

Definition at line 897 of file miarm.h.

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

◆ MI_MAKE_TRANSITION_PTE()

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

Definition at line 943 of file miarm.h.

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

Referenced by MiResolvePageFileFault(), and TrimWsList().

◆ MI_PFN_ELEMENT()

◆ MI_UPDATE_VALID_PTE()

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

Definition at line 991 of file miarm.h.

993{
994 /* Write the valid PTE */
995 ASSERT(PointerPte->u.Hard.Valid == 1);
996 ASSERT(TempPte.u.Hard.Valid == 1);
997 ASSERT(PointerPte->u.Hard.PageFrameNumber == TempPte.u.Hard.PageFrameNumber);
998 *PointerPte = TempPte;
999}
HARDWARE_PTE_ARMV6 TempPte
Definition: winldr.c:76
ULONG PageFrameNumber
Definition: mmtypes.h:109

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

◆ MI_WRITE_INVALID_PDE()

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

Definition at line 1048 of file miarm.h.

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

Referenced by MmArmAccessFault().

◆ MI_WRITE_INVALID_PTE()

◆ MI_WRITE_VALID_PDE()

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

Definition at line 1031 of file miarm.h.

1033{
1034 /* Write the valid PDE */
1035 ASSERT(PointerPde->u.Hard.Valid == 0);
1036#ifdef _M_AMD64
1037 ASSERT(PointerPde->u.Hard.NoExecute == 0);
1038#endif
1039 ASSERT(TempPde.u.Hard.Valid == 1);
1040 *PointerPde = TempPde;
1041}
HARDWARE_PDE_ARMV6 TempPde
Definition: winldr.c:78

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

◆ MI_WRITE_VALID_PTE()

◆ MI_WS_OWNER()

FORCEINLINE BOOLEAN MI_WS_OWNER ( IN PEPROCESS  Process)

Definition at line 1090 of file miarm.h.

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

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

◆ MiAcquireExpansionLock()

FORCEINLINE KIRQL MiAcquireExpansionLock ( VOID  )

Definition at line 1544 of file miarm.h.

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

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

◆ MiAllocatePagesForMdl()

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

Definition at line 182 of file freelist.c.

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

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

◆ MiCheckForConflictingNode()

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

Definition at line 150 of file vadnode.c.

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

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

◆ MiCheckForContiguousMemory()

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

Definition at line 214 of file contmem.c.

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

Referenced by MiAllocateContiguousMemory().

◆ MiCheckPdeForPagedPool()

NTSTATUS FASTCALL MiCheckPdeForPagedPool ( IN PVOID  Address)

Definition at line 479 of file pagfault.c.

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

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

◆ MiCheckSecuredVad()

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

Definition at line 903 of file vadnode.c.

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

Referenced by MiUnmapViewOfSection(), and NtAllocateVirtualMemory().

◆ MiComputeColorInformation()

VOID NTAPI MiComputeColorInformation ( VOID  )

Definition at line 499 of file mminit.c.

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

Referenced by MmArmInitSystem().

◆ MiConvertSharedWorkingSetLockToExclusive()

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

Definition at line 1441 of file miarm.h.

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

Referenced by MmWorkingSetManager().

◆ MiDecrementPageTableReferences()

FORCEINLINE USHORT MiDecrementPageTableReferences ( IN PVOID  Address)

Definition at line 2505 of file miarm.h.

2506{
2507 PMMPDE PointerPde = MiAddressToPde(Address);
2508 PMMPFN Pfn;
2509
2510 /* We should not tinker with this one. */
2511 ASSERT(PointerPde != (PMMPDE)PXE_SELFMAP);
2512
2513 DPRINT("Decrementing %p from %p\n", PointerPde, _ReturnAddress());
2514
2515 /* Make sure we're locked */
2516 ASSERT(PsGetCurrentThread()->OwnsProcessWorkingSetExclusive);
2517
2518 /* If we're decreasing refcount, then it must be valid! */
2519 ASSERT(PointerPde->u.Hard.Valid == 1);
2520
2521 /* This lies on the PFN */
2522 Pfn = MiGetPfnEntry(PFN_FROM_PDE(PointerPde));
2523
2526
2528
2530}
#define _ReturnAddress()
Definition: intrin_arm.h:35
#define PFN_FROM_PDE(v)
Definition: mm.h:93
#define PTE_PER_PAGE
Definition: mm.h:20
#define PXE_SELFMAP
MMPTE OriginalPte
Definition: mm.h:414
ULONG64 UsedPageTableEntries
Definition: mmtypes.h:91
MMPTE_SOFTWARE Soft
Definition: mmtypes.h:219

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

◆ MiDecrementReferenceCount()

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

Definition at line 1236 of file pfnlist.c.

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

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

◆ MiDecrementShareCount()

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

Definition at line 1141 of file pfnlist.c.

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

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

◆ MiDeleteARM3Section()

VOID NTAPI MiDeleteARM3Section ( PVOID  ObjectBody)

Definition at line 2949 of file section.c.

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

Referenced by MmpDeleteSection().

◆ MiDeletePde()

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

Definition at line 2539 of file miarm.h.

2542{
2543 /* Only for user-mode ones */
2544 ASSERT(MiIsUserPde(PointerPde));
2545
2546 /* Kill this one as a PTE */
2547 MiDeletePte((PMMPTE)PointerPde, MiPdeToPte(PointerPde), CurrentProcess, NULL);
2548#if _MI_PAGING_LEVELS >= 3
2549 /* Cascade down */
2550 if (MiDecrementPageTableReferences(MiPdeToPte(PointerPde)) == 0)
2551 {
2552 MiDeletePte(MiPdeToPpe(PointerPde), PointerPde, CurrentProcess, NULL);
2553#if _MI_PAGING_LEVELS == 4
2554 if (MiDecrementPageTableReferences(PointerPde) == 0)
2555 {
2556 MiDeletePte(MiPdeToPxe(PointerPde), MiPdeToPpe(PointerPde), CurrentProcess, NULL);
2557 }
2558#endif
2559 }
2560#endif
2561}
VOID NTAPI MiDeletePte(IN PMMPTE PointerPte, IN PVOID VirtualAddress, IN PEPROCESS CurrentProcess, IN PMMPTE PrototypePte)
Definition: virtual.c:369
FORCEINLINE USHORT MiDecrementPageTableReferences(IN PVOID Address)
Definition: miarm.h:2505
FORCEINLINE BOOLEAN MiIsUserPde(PVOID Address)
Definition: miarm.h:731
FORCEINLINE PMMPXE MiPdeToPxe(PMMPDE PointerPde)
Definition: mm.h:300
FORCEINLINE PMMPDE MiPdeToPpe(PMMPDE PointerPde)
Definition: mm.h:292
#define MiPdeToPte(_Pde)
Definition: mm.h:120

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

◆ MiDeletePte()

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

Definition at line 369 of file virtual.c.

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

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

◆ MiDeleteSystemPageableVm()

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

Definition at line 275 of file virtual.c.

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

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

◆ MiDeleteVirtualAddresses()

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

Definition at line 530 of file virtual.c.

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

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

◆ MiDereferencePfnAndDropLockCount()

FORCEINLINE VOID MiDereferencePfnAndDropLockCount ( IN PMMPFN  Pfn1)

Definition at line 1628 of file miarm.h.

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

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

◆ MiDetermineUserGlobalPteMask()

FORCEINLINE ULONG_PTR MiDetermineUserGlobalPteMask ( IN PVOID  PointerPte)

Definition at line 750 of file miarm.h.

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

Referenced by MI_MAKE_HARDWARE_PTE(), and MiResolveTransitionFault().

◆ MiDropLockCount()

FORCEINLINE VOID MiDropLockCount ( IN PMMPFN  Pfn1)

Definition at line 1598 of file miarm.h.

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

Referenced by MiResolveTransitionFault().

◆ MiFindContiguousPages()

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

Definition at line 22 of file contmem.c.

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

Referenced by MiFindContiguousMemory().

◆ MiFindEmptyAddressRangeDownBasedTree()

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

Definition at line 799 of file vadnode.c.

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

Referenced by MmCreateArm3Section().

◆ MiFindEmptyAddressRangeDownTree()

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

Definition at line 681 of file vadnode.c.

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

Referenced by MiInsertVadEx(), and MmFindGap().

◆ MiFindEmptyAddressRangeInTree()

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

Definition at line 584 of file vadnode.c.

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

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

◆ MiGetNextNode()

PMMADDRESS_NODE NTAPI MiGetNextNode ( IN PMMADDRESS_NODE  Node)

Definition at line 549 of file vadnode.c.

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

Referenced by MiFindEmptyAddressRangeInTree(), and MiQueryMemoryBasicInformation().

◆ MiGetPageProtection()

ULONG NTAPI MiGetPageProtection ( IN PMMPTE  PointerPte)

Definition at line 1355 of file virtual.c.

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

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

◆ MiGetPreviousNode()

PMMADDRESS_NODE NTAPI MiGetPreviousNode ( IN PMMADDRESS_NODE  Node)

Definition at line 513 of file vadnode.c.

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

Referenced by MiFindEmptyAddressRangeDownBasedTree(), and MiFindEmptyAddressRangeDownTree().

◆ MiIncrementPageTableReferences()

FORCEINLINE USHORT MiIncrementPageTableReferences ( IN PVOID  Address)

Definition at line 2479 of file miarm.h.

2480{
2481 PMMPDE PointerPde = MiAddressToPde(Address);
2482 PMMPFN Pfn;
2483
2484 /* We should not tinker with this one. */
2485 ASSERT(PointerPde != (PMMPDE)PXE_SELFMAP);
2486 DPRINT("Incrementing %p from %p\n", Address, _ReturnAddress());
2487
2488 /* Make sure we're locked */
2489 ASSERT(PsGetCurrentThread()->OwnsProcessWorkingSetExclusive);
2490
2491 /* If we're bumping refcount, then it must be valid! */
2492 ASSERT(PointerPde->u.Hard.Valid == 1);
2493
2494 /* This lies on the PFN */
2495 Pfn = MiGetPfnEntry(PFN_FROM_PDE(PointerPde));
2497
2499
2501}

Referenced by MiDecommitPages(), MiMapLockedPagesInUserSpace(), MiProtectVirtualMemory(), MmArmAccessFault(), MmCreatePageFileMapping(), MmCreateVirtualMappingUnsafeEx(), and NtAllocateVirtualMemory().

◆ MiInitializeAndChargePfn()

NTSTATUS NTAPI MiInitializeAndChargePfn ( OUT PPFN_NUMBER  PageFrameIndex,
IN PMMPDE  PointerPde,
IN PFN_NUMBER  ContainingPageFrame,
IN BOOLEAN  SessionAllocation 
)

Definition at line 1101 of file pfnlist.c.

1105{
1106 MMPDE TempPde;
1107 KIRQL OldIrql;
1108
1109 /* Use either a global or local PDE */
1110 TempPde = SessionAllocation ? ValidKernelPdeLocal : ValidKernelPde;
1111
1112 /* Lock the PFN database */
1113 OldIrql = MiAcquirePfnLock();
1114
1115 /* Make sure nobody is racing us */
1116 if (PointerPde->u.Hard.Valid == 1)
1117 {
1118 /* Return special error if that was the case */
1119 MiReleasePfnLock(OldIrql);
1120 return STATUS_RETRY;
1121 }
1122
1123 /* Grab a zero page and set the PFN, then make it valid */
1124 *PageFrameIndex = MiRemoveZeroPage(MI_GET_NEXT_COLOR());
1125 TempPde.u.Hard.PageFrameNumber = *PageFrameIndex;
1126 MI_WRITE_VALID_PDE(PointerPde, TempPde);
1127
1128 /* Initialize the PFN */
1129 MiInitializePfnForOtherProcess(*PageFrameIndex,
1130 PointerPde,
1131 ContainingPageFrame);
1132 ASSERT(MI_PFN_ELEMENT(*PageFrameIndex)->u1.WsIndex == 0);
1133
1134 /* Release the lock and return success */
1135 MiReleasePfnLock(OldIrql);
1136 return STATUS_SUCCESS;
1137}
#define MI_GET_NEXT_COLOR()
Definition: miarm.h:246
FORCEINLINE VOID MI_WRITE_VALID_PDE(IN PMMPDE PointerPde, IN MMPDE TempPde)
Definition: miarm.h:1031
MMPTE ValidKernelPdeLocal
Definition: init.c:32
MMPTE ValidKernelPde
Definition: init.c:28
PFN_NUMBER NTAPI MiRemoveZeroPage(IN ULONG Color)
Definition: pfnlist.c:537
VOID NTAPI MiInitializePfnForOtherProcess(IN PFN_NUMBER PageFrameIndex, IN PVOID PteAddress, IN PFN_NUMBER PteFrame)
Definition: pfnlist.c:1301
ULONG PageFrameNumber
Definition: mmtypes.h:74
#define STATUS_RETRY
Definition: udferr_usr.h:182

Referenced by MiInitializeSessionPool().

◆ MiInitializeColorTables()

VOID NTAPI MiInitializeColorTables ( VOID  )

Definition at line 553 of file mminit.c.

554{
555 ULONG i;
556 PMMPTE PointerPte, LastPte;
558
559 /* The color table starts after the ARM3 PFN database */
561
562 /* Loop the PTEs. We have two color tables for each secondary color */
563 PointerPte = MiAddressToPte(&MmFreePagesByColor[0][0]);
565 (2 * MmSecondaryColors * sizeof(MMCOLOR_TABLES))
566 - 1);
567 while (PointerPte <= LastPte)
568 {
569 /* Check for valid PTE */
570 if (PointerPte->u.Hard.Valid == 0)
571 {
572 /* Get a page and map it */
574 MI_WRITE_VALID_PTE(PointerPte, TempPte);
575
576 /* Zero out the page */
578 }
579
580 /* Next */
581 PointerPte++;
582 }
583
584 /* Now set the address of the next list, right after this one */
586
587 /* Now loop the lists to set them up */
588 for (i = 0; i < MmSecondaryColors; i++)
589 {
590 /* Set both free and zero lists for each color */
597 }
598}
PFN_NUMBER NTAPI MxGetNextPage(IN PFN_NUMBER PageCount)
Definition: mminit.c:474
PFN_NUMBER MmHighestPhysicalPage
Definition: mminit.c:211
PMMCOLOR_TABLES MmFreePagesByColor[FreePageList+1]
Definition: mminit.c:286
struct _MMCOLOR_TABLES * PMMCOLOR_TABLES
FORCEINLINE VOID MI_WRITE_VALID_PTE(IN PMMPTE PointerPte, IN MMPTE TempPte)
Definition: miarm.h:973
@ FreePageList
Definition: mmtypes.h:154
MMPTE ValidKernelPte
Definition: init.c:29
PFN_NUMBER Count
Definition: miarm.h:447
PVOID Blink
Definition: miarm.h:446
PFN_NUMBER Flink
Definition: miarm.h:445

Referenced by MiBuildPfnDatabase(), and MiInitMachineDependent().

◆ MiInitializeDriverLargePageList()

VOID NTAPI MiInitializeDriverLargePageList ( VOID  )

Definition at line 68 of file largepag.c.

69{
70 PWCHAR p, pp;
71
72 /* Initialize the list */
74
75 /* Bail out if there's nothing */
76 if (MmLargePageDriverBufferLength == 0xFFFFFFFF) return;
77
78 /* Loop from start to finish */
81 while (p < pp)
82 {
83 /* Skip whitespaces */
84 if ((*p == L' ') || (*p == L'\n') || (*p == L'\r') || (*p == L'\t'))
85 {
86 /* Skip the character */
87 p++;
88 continue;
89 }
90
91 /* A star means everything */
92 if (*p == L'*')
93 {
94 /* No need to keep going */
96 break;
97 }
98
99 DPRINT1("Large page drivers not supported\n");
100 ASSERT(FALSE);
101 }
102}
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
GLfloat GLfloat p
Definition: glext.h:8902
ULONG MmLargePageDriverBufferLength
Definition: largepag.c:25
BOOLEAN MiLargePageAllDrivers
Definition: largepag.c:27
LIST_ENTRY MiLargePageDriverList
Definition: largepag.c:26
WCHAR MmLargePageDriverBuffer[512]
Definition: largepag.c:24
#define L(x)
Definition: ntvdm.h:50
uint16_t * PWCHAR
Definition: typedefs.h:56
__wchar_t WCHAR
Definition: xmlstorage.h:180

Referenced by MmArmInitSystem().

◆ MiInitializeLargePageSupport()

VOID NTAPI MiInitializeLargePageSupport ( VOID  )

Definition at line 34 of file largepag.c.

35{
36#if _MI_PAGING_LEVELS > 2
37 DPRINT1("MiInitializeLargePageSupport: PAE/x64 Not Implemented\n");
38 //ASSERT(FALSE);
39#else
40 /* Initialize the large-page hyperspace PTE used for initial mapping */
44
45 /* Initialize the process tracking list, and insert the system process */
48#endif
49}
#define InsertTailList(ListHead, Entry)
LIST_ENTRY MmProcessList
Definition: largepag.c:20
PMMPTE MiLargePageHyperPte
Definition: largepag.c:21
PMMPTE NTAPI MiReserveSystemPtes(IN ULONG NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType)
Definition: syspte.c:246

Referenced by MmArmInitSystem().

◆ MiInitializeMemoryEvents()

BOOLEAN NTAPI MiInitializeMemoryEvents ( VOID  )

Definition at line 1330 of file mminit.c.

1331{
1332 UNICODE_STRING LowString = RTL_CONSTANT_STRING(L"\\KernelObjects\\LowMemoryCondition");
1333 UNICODE_STRING HighString = RTL_CONSTANT_STRING(L"\\KernelObjects\\HighMemoryCondition");
1334 UNICODE_STRING LowPagedPoolString = RTL_CONSTANT_STRING(L"\\KernelObjects\\LowPagedPoolCondition");
1335 UNICODE_STRING HighPagedPoolString = RTL_CONSTANT_STRING(L"\\KernelObjects\\HighPagedPoolCondition");
1336 UNICODE_STRING LowNonPagedPoolString = RTL_CONSTANT_STRING(L"\\KernelObjects\\LowNonPagedPoolCondition");
1337 UNICODE_STRING HighNonPagedPoolString = RTL_CONSTANT_STRING(L"\\KernelObjects\\HighNonPagedPoolCondition");
1339
1340 /* Check if we have a registry setting */
1342 {
1343 /* Convert it to pages */
1345 }
1346 else
1347 {
1348 /* The low memory threshold is hit when we don't consider that we have "plenty" of free pages anymore */
1350
1351 /* More than one GB of memory? */
1352 if (MmNumberOfPhysicalPages > 0x40000)
1353 {
1354 /* Start at 32MB, and add another 16MB for each GB */
1356 MmLowMemoryThreshold += ((MmNumberOfPhysicalPages - 0x40000) >> 7);
1357 }
1358 else if (MmNumberOfPhysicalPages > 0x8000)
1359 {
1360 /* For systems with > 128MB RAM, add another 4MB for each 128MB */
1361 MmLowMemoryThreshold += ((MmNumberOfPhysicalPages - 0x8000) >> 5);
1362 }
1363
1364 /* Don't let the minimum threshold go past 64MB */
1366 }
1367
1368 /* Check if we have a registry setting */
1370 {
1371 /* Convert it into pages */
1373 }
1374 else
1375 {
1376 /* Otherwise, the default is three times the low memory threshold */
1379 }
1380
1381 /* Make sure high threshold is actually higher than the low */
1383
1384 /* Create the memory events for all the thresholds */
1386 if (!NT_SUCCESS(Status)) return FALSE;
1388 if (!NT_SUCCESS(Status)) return FALSE;
1389 Status = MiCreateMemoryEvent(&LowPagedPoolString, &MiLowPagedPoolEvent);
1390 if (!NT_SUCCESS(Status)) return FALSE;
1391 Status = MiCreateMemoryEvent(&HighPagedPoolString, &MiHighPagedPoolEvent);
1392 if (!NT_SUCCESS(Status)) return FALSE;
1393 Status = MiCreateMemoryEvent(&LowNonPagedPoolString, &MiLowNonPagedPoolEvent);
1394 if (!NT_SUCCESS(Status)) return FALSE;
1395 Status = MiCreateMemoryEvent(&HighNonPagedPoolString, &MiHighNonPagedPoolEvent);
1396 if (!NT_SUCCESS(Status)) return FALSE;
1397
1398 /* Now setup the pool events */
1400
1401 /* Set the initial event state */
1403 return TRUE;
1404}
PFN_NUMBER MmLowMemoryThreshold
Definition: mminit.c:300
PFN_COUNT MmNumberOfPhysicalPages
Definition: mminit.c:212
PFN_NUMBER MmPlentyFreePages
Definition: mminit.c:322
NTSTATUS NTAPI MiCreateMemoryEvent(IN PUNICODE_STRING Name, OUT PKEVENT *Event)
Definition: mminit.c:1235
PKEVENT MiLowNonPagedPoolEvent
Definition: mminit.c:296
PKEVENT MiHighMemoryEvent
Definition: mminit.c:293
PKEVENT MiLowMemoryEvent
Definition: mminit.c:292
VOID NTAPI MiNotifyMemoryEvents(VOID)
Definition: mminit.c:1209
PKEVENT MiHighPagedPoolEvent
Definition: mminit.c:295
PKEVENT MiLowPagedPoolEvent
Definition: mminit.c:294
PFN_NUMBER MmHighMemoryThreshold
Definition: mminit.c:301
PKEVENT MiHighNonPagedPoolEvent
Definition: mminit.c:297
LONG NTSTATUS
Definition: precomp.h:26
Status
Definition: gdiplustypes.h:25
VOID NTAPI MiInitializePoolEvents(VOID)
Definition: pool.c:203
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14

Referenced by MmInitSystem().

◆ MiInitializeNonPagedPoolThresholds()

VOID NTAPI MiInitializeNonPagedPoolThresholds ( VOID  )

Definition at line 186 of file pool.c.

187{
189
190 /* Default low threshold of 8MB or one third of nonpaged pool */
193
194 /* Default high threshold of 20MB or 50% */
198}
PFN_NUMBER MmMaximumNonPagedPoolInPages
Definition: mminit.c:30
PFN_NUMBER MiLowNonPagedPoolThreshold
Definition: mminit.c:304
PFN_NUMBER MiHighNonPagedPoolThreshold
Definition: mminit.c:305

Referenced by MiBuildNonPagedPool(), and MiInitMachineDependent().

◆ MiInitializePfn()

VOID NTAPI MiInitializePfn ( IN PFN_NUMBER  PageFrameIndex,
IN PMMPTE  PointerPte,
IN BOOLEAN  Modified 
)

Definition at line 970 of file pfnlist.c.

973{
974 PMMPFN Pfn1;
976 PMMPTE PointerPtePte;
978
979 /* Setup the PTE */
980 Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
981 Pfn1->PteAddress = PointerPte;
982
983 DPRINT("Called for %p from %p\n", Pfn1, _ReturnAddress());
984
985 /* Check if this PFN is part of a valid address space */
986 if (PointerPte->u.Hard.Valid == 1)
987 {
988 /* Only valid from MmCreateProcessAddressSpace path */
989 ASSERT(PsGetCurrentProcess()->Vm.WorkingSetSize == 0);
990
991 /* Make this a demand zero PTE */
993 }
994 else
995 {
996 /* Copy the PTE data */
997 Pfn1->OriginalPte = *PointerPte;
998 ASSERT(!((Pfn1->OriginalPte.u.Soft.Prototype == 0) &&
999 (Pfn1->OriginalPte.u.Soft.Transition == 1)));
1000 }
1001
1002 /* Otherwise this is a fresh page -- set it up */
1003 ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
1004 Pfn1->u3.e2.ReferenceCount = 1;
1005 Pfn1->u2.ShareCount = 1;
1007 ASSERT(Pfn1->u3.e1.Rom == 0);
1008 Pfn1->u3.e1.Modified = Modified;
1009
1010 /* Get the page table for the PTE */
1011 PointerPtePte = MiAddressToPte(PointerPte);
1012 if (PointerPtePte->u.Hard.Valid == 0)
1013 {
1014 /* Make sure the PDE gets paged in properly */
1015 Status = MiCheckPdeForPagedPool(PointerPte);
1016 if (!NT_SUCCESS(Status))
1017 {
1018 /* Crash */
1019 KeBugCheckEx(MEMORY_MANAGEMENT,
1020 0x61940,
1021 (ULONG_PTR)PointerPte,
1022 (ULONG_PTR)PointerPtePte->u.Long,
1023 (ULONG_PTR)MiPteToAddress(PointerPte));
1024 }
1025 }
1026
1027 /* Get the PFN for the page table */
1028 PageFrameIndex = PFN_FROM_PTE(PointerPtePte);
1029 ASSERT(PageFrameIndex != 0);
1030 Pfn1->u4.PteFrame = PageFrameIndex;
1031
1032 DPRINT("Incrementing share count of %lp from %p\n", PageFrameIndex, _ReturnAddress());
1033
1034 /* Increase its share count so we don't get rid of it */
1035 Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
1036 Pfn1->u2.ShareCount++;
1037}
#define MM_READWRITE
Definition: bootanim.c:19
#define MI_MAKE_SOFTWARE_PTE(p, x)
Definition: miarm.h:203
USHORT Modified
Definition: mm.h:367
USHORT Rom
Definition: mm.h:375
ULONG64 Transition
Definition: mmtypes.h:90
ULONG64 Prototype
Definition: mmtypes.h:89

Referenced by MiLoadImageSection(), MiResolveDemandZeroFault(), MiResolvePageFileFault(), MiResolveProtoPteFault(), MmArmAccessFault(), MmCreateKernelStack(), MmGrowKernelStackEx(), and MmInitializeProcessAddressSpace().

◆ MiInitializePfnAndMakePteValid()

VOID NTAPI MiInitializePfnAndMakePteValid ( IN PFN_NUMBER  PageFrameIndex,
IN PMMPTE  PointerPte,
IN MMPTE  TempPte 
)

Definition at line 1041 of file pfnlist.c.

1044{
1045 PMMPFN Pfn1;
1047 PMMPTE PointerPtePte;
1049
1050 /* PTE must be invalid */
1051 ASSERT(PointerPte->u.Hard.Valid == 0);
1052
1053 /* Setup the PTE */
1054 Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
1055 Pfn1->PteAddress = PointerPte;
1056 Pfn1->OriginalPte = DemandZeroPte;
1057
1058 DPRINT("Incrementing %p from %p\n", Pfn1, _ReturnAddress());
1059
1060 /* Otherwise this is a fresh page -- set it up */
1061 ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
1062 Pfn1->u3.e2.ReferenceCount++;
1063 Pfn1->u2.ShareCount++;
1065 ASSERT(Pfn1->u3.e1.Rom == 0);
1066 Pfn1->u3.e1.Modified = 1;
1067
1068 /* Get the page table for the PTE */
1069 PointerPtePte = MiAddressToPte(PointerPte);
1070 if (PointerPtePte->u.Hard.Valid == 0)
1071 {
1072 /* Make sure the PDE gets paged in properly */
1073 Status = MiCheckPdeForPagedPool(PointerPte);
1074 if (!NT_SUCCESS(Status))
1075 {
1076 /* Crash */
1077 KeBugCheckEx(MEMORY_MANAGEMENT,
1078 0x61940,
1079 (ULONG_PTR)PointerPte,
1080 (ULONG_PTR)PointerPtePte->u.Long,
1081 (ULONG_PTR)MiPteToAddress(PointerPte));
1082 }
1083 }
1084
1085 /* Get the PFN for the page table */
1086 PageFrameIndex = PFN_FROM_PTE(PointerPtePte);
1087 ASSERT(PageFrameIndex != 0);
1088 Pfn1->u4.PteFrame = PageFrameIndex;
1089
1090 /* Increase its share count so we don't get rid of it */
1091 Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
1092 Pfn1->u2.ShareCount++;
1093 DPRINT("Incrementing %p from %p\n", Pfn1, _ReturnAddress());
1094
1095 /* Write valid PTE */
1096 MI_WRITE_VALID_PTE(PointerPte, TempPte);
1097}
MMPTE DemandZeroPte
Definition: init.c:37

Referenced by GetFreeWsleIndex(), MiSessionCreateInternal(), MiSessionInitializeWorkingSetList(), and MmAllocateSpecialPool().

◆ MiInitializePfnDatabase()

VOID NTAPI MiInitializePfnDatabase ( IN PLOADER_PARAMETER_BLOCK  LoaderBlock)

Definition at line 1065 of file mminit.c.

1066{
1067 /* Scan memory and start setting up PFN entries */
1068 MiBuildPfnDatabaseFromPages(LoaderBlock);
1069
1070 /* Add the zero page */
1072
1073 /* Scan the loader block and build the rest of the PFN database */
1075
1076 /* Finally add the pages for the PFN database itself */
1078}
VOID NTAPI MiBuildPfnDatabaseFromPages(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: mminit.c:759
VOID NTAPI MiBuildPfnDatabaseZeroPage(VOID)
Definition: mminit.c:868
VOID NTAPI MiBuildPfnDatabaseFromLoaderBlock(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: mminit.c:891
VOID NTAPI MiBuildPfnDatabaseSelf(VOID)
Definition: mminit.c:1035

Referenced by MiInitMachineDependent().

◆ MiInitializePfnForOtherProcess()

VOID NTAPI MiInitializePfnForOtherProcess ( IN PFN_NUMBER  PageFrameIndex,
IN PVOID  PteAddress,
IN PFN_NUMBER  PteFrame 
)

Definition at line 1301 of file pfnlist.c.

1304{
1305 PMMPFN Pfn1;
1306
1307 /* Setup the PTE */
1308 Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
1309 Pfn1->PteAddress = PteAddress;
1310
1311 /* Make this a software PTE */
1313
1314 DPRINT("Called for %p from %p\n", Pfn1, _ReturnAddress());
1315
1316 /* Setup the page */
1317 ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
1318 Pfn1->u3.e2.ReferenceCount = 1;
1319 Pfn1->u2.ShareCount = 1;
1321 Pfn1->u3.e1.Modified = TRUE;
1322 Pfn1->u4.InPageError = FALSE;
1323
1324 /* Did we get a PFN for the page table */
1325 if (PteFrame)
1326 {
1327 /* Store it */
1328 Pfn1->u4.PteFrame = PteFrame;
1329
1330 /* Increase its share count so we don't get rid of it */
1331 Pfn1 = MI_PFN_ELEMENT(PteFrame);
1332
1333 DPRINT("Incrementing %p from %p\n", Pfn1, _ReturnAddress());
1334 Pfn1->u2.ShareCount++;
1335 }
1336}
ULONG_PTR InPageError
Definition: mm.h:426

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

◆ MiInitializePoolEvents()

VOID NTAPI MiInitializePoolEvents ( VOID  )

Definition at line 203 of file pool.c.

204{
206 PFN_NUMBER FreePoolInPages;
207
208 /* Lock paged pool */
210
211 /* Total size of the paged pool minus the allocated size, is free */
213
214 /* Check the initial state high state */
215 if (FreePoolInPages >= MiHighPagedPoolThreshold)
216 {
217 /* We have plenty of pool */
219 }
220 else
221 {
222 /* We don't */
224 }
225
226 /* Check the initial low state */
227 if (FreePoolInPages <= MiLowPagedPoolThreshold)
228 {
229 /* We're very low in free pool memory */
231 }
232 else
233 {
234 /* We're not */
236 }
237
238 /* Release the paged pool lock */
240
241 /* Now it's time for the nonpaged pool lock */
243
244 /* Free pages are the maximum minus what's been allocated */
246
247 /* Check if we have plenty */
248 if (FreePoolInPages >= MiHighNonPagedPoolThreshold)
249 {
250 /* We do, set the event */
252 }
253 else
254 {
255 /* We don't, clear the event */
257 }
258
259 /* Check if we have very little */
260 if (FreePoolInPages <= MiLowNonPagedPoolThreshold)
261 {
262 /* We do, set the event */
264 }
265 else
266 {
267 /* We don't, clear it */
269 }
270
271 /* We're done, release the nonpaged pool lock */
273}
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
VOID NTAPI KeClearEvent(IN PKEVENT Event)
Definition: eventobj.c:22
VOID FASTCALL KeReleaseQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber, IN KIRQL OldIrql)
Definition: spinlock.c:154
KIRQL FASTCALL KeAcquireQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber)
Definition: spinlock.c:108
PFN_NUMBER MiLowPagedPoolThreshold
Definition: mminit.c:302
PFN_NUMBER MiHighPagedPoolThreshold
Definition: mminit.c:303
PKEVENT MiLowNonPagedPoolEvent
Definition: mminit.c:296
PKEVENT MiHighPagedPoolEvent
Definition: mminit.c:295
PKEVENT MiLowPagedPoolEvent
Definition: mminit.c:294
PFN_NUMBER MmSizeOfPagedPoolInPages
Definition: mminit.c:111
PKEVENT MiHighNonPagedPoolEvent
Definition: mminit.c:297
KGUARDED_MUTEX MmPagedPoolMutex
Definition: pool.c:24
MM_PAGED_POOL_INFO MmPagedPoolInfo
Definition: pool.c:25
SIZE_T MmAllocatedNonPagedPool
Definition: pool.c:26
SIZE_T AllocatedPagedPool
Definition: mm.h:500
@ LockQueueMmNonPagedPoolLock
Definition: ketypes.h:673

Referenced by MiInitializeMemoryEvents().

◆ MiInitializeSessionIds()

VOID NTAPI MiInitializeSessionIds ( VOID  )

Definition at line 116 of file session.c.

117{
118 ULONG Size, BitmapSize;
119 PFN_NUMBER TotalPages;
120
121 /* Setup the total number of data pages needed for the structure */
125 TotalPages -= MiSessionDataPages;
126
127 /* Setup the number of pages needed for session pool tags */
131 ASSERT(MiSessionTagPages <= TotalPages);
133
134 /* Total pages needed for a session (FIXME: Probably different on PAE/x64) */
136
137 /* Initialize the lock */
139
140 /* Allocate the bitmap */
142 BitmapSize = ((Size + 31) / 32) * sizeof(ULONG);
144 sizeof(RTL_BITMAP) + BitmapSize,
145 TAG_MM);
147 {
148 /* Free all the bits */
151 Size);
153 }
154 else
155 {
156 /* Die if we couldn't allocate the bitmap */
157 KeBugCheckEx(INSTALL_MORE_MEMORY,
161 0x200);
162 }
163}
#define RtlInitializeBitMap
Definition: dbgbitmap.h:326
#define RtlClearAllBits
Definition: dbgbitmap.h:329
PFN_NUMBER MmLowestPhysicalPage
Definition: meminit.c:30
#define MI_SESSION_TAG_PAGES_MAXIMUM
Definition: miarm.h:262
#define MI_INITIAL_SESSION_IDS
Definition: miarm.h:221
#define MI_SESSION_DATA_PAGES_MAXIMUM
Definition: miarm.h:261
PFN_COUNT MmNumberOfPhysicalPages
Definition: init.c:48
PFN_NUMBER MiSessionTagPages
Definition: session.c:22
PFN_NUMBER MiSessionCreateCharge
Definition: session.c:23
PFN_NUMBER MiSessionBigPoolPages
Definition: session.c:23
PRTL_BITMAP MiSessionIdBitmap
Definition: session.c:26
KGUARDED_MUTEX MiSessionIdMutex
Definition: session.c:24
PFN_NUMBER MiSessionTagSizePages
Definition: session.c:22
PFN_NUMBER MiSessionDataPages
Definition: session.c:22
#define TAG_MM
Definition: tag.h:112

Referenced by MmInitSystem().

◆ MiInitializeSessionPool()

NTSTATUS NTAPI MiInitializeSessionPool ( VOID  )

Definition at line 1276 of file pool.c.

1277{
1278 PMMPTE PointerPte, LastPte;
1279 PMMPDE PointerPde, LastPde;
1280 PFN_NUMBER PageFrameIndex, PdeCount;
1281 PPOOL_DESCRIPTOR PoolDescriptor;
1282 PMM_SESSION_SPACE SessionGlobal;
1283 PMM_PAGED_POOL_INFO PagedPoolInfo;
1285 ULONG Index, PoolSize, BitmapSize;
1286 PAGED_CODE();
1287
1288 /* Lock session pool */
1289 SessionGlobal = MmSessionSpace->GlobalVirtualAddress;
1291
1292 /* Setup a valid pool descriptor */
1293 PoolDescriptor = &MmSessionSpace->PagedPool;
1294 ExInitializePoolDescriptor(PoolDescriptor,
1296 0,
1297 0,
1298 &SessionGlobal->PagedPoolMutex);
1299
1300 /* Setup the pool addresses */
1303 DPRINT1("Session Pool Start: 0x%p End: 0x%p\n",
1305
1306 /* Reset all the counters */
1307 PagedPoolInfo = &MmSessionSpace->PagedPoolInfo;
1308 PagedPoolInfo->PagedPoolCommit = 0;
1309 PagedPoolInfo->PagedPoolHint = 0;
1310 PagedPoolInfo->AllocatedPagedPool = 0;
1311
1312 /* Compute PDE and PTE addresses */
1317
1318 /* Write them down */
1319 MmSessionSpace->PagedPoolBasePde = PointerPde;
1320 PagedPoolInfo->FirstPteForPagedPool = PointerPte;
1321 PagedPoolInfo->LastPteForPagedPool = LastPte;
1322 PagedPoolInfo->NextPdeForPagedPoolExpansion = PointerPde + 1;
1323
1324 /* Zero the PDEs */
1325 PdeCount = LastPde - PointerPde;
1326 RtlZeroMemory(PointerPde, (PdeCount + 1) * sizeof(MMPTE));
1327
1328 /* Initialize the PFN for the PDE */
1329 Status = MiInitializeAndChargePfn(&PageFrameIndex,
1330 PointerPde,
1332 TRUE);
1334
1335 /* Initialize the first page table */
1337 Index >>= 22;
1338#ifndef _M_AMD64 // FIXME
1340 MmSessionSpace->PageTables[Index] = *PointerPde;
1341#endif
1342
1343 /* Bump up counters */
1346
1347 /* Compute the size of the pool in pages, and of the bitmap for it */
1348 PoolSize = MmSessionPoolSize >> PAGE_SHIFT;
1349 BitmapSize = sizeof(RTL_BITMAP) + ((PoolSize + 31) / 32) * sizeof(ULONG);
1350
1351 /* Allocate and initialize the bitmap to track allocations */
1353 BitmapSize,
1354 TAG_MM);
1355 ASSERT(PagedPoolInfo->PagedPoolAllocationMap != NULL);
1357 (PULONG)(PagedPoolInfo->PagedPoolAllocationMap + 1),
1358 PoolSize);
1359
1360 /* Set all bits, but clear the first page table's worth */
1361 RtlSetAllBits(PagedPoolInfo->PagedPoolAllocationMap);
1363
1364 /* Allocate and initialize the bitmap to track free space */
1366 BitmapSize,
1367 TAG_MM);
1368 ASSERT(PagedPoolInfo->EndOfPagedPoolBitmap != NULL);
1370 (PULONG)(PagedPoolInfo->EndOfPagedPoolBitmap + 1),
1371 PoolSize);
1372
1373 /* Clear all the bits and return success */
1374 RtlClearAllBits(PagedPoolInfo->EndOfPagedPoolBitmap);
1375 return STATUS_SUCCESS;
1376}
#define RtlClearBits
Definition: dbgbitmap.h:331
#define RtlSetAllBits
Definition: dbgbitmap.h:346
#define RTL_BITMAP
Definition: dbgbitmap.h:323
#define InterlockedIncrementSizeT(a)
Definition: interlocked.h:220
PMM_SESSION_SPACE MmSessionSpace
Definition: session.c:21
NTSTATUS NTAPI MiInitializeAndChargePfn(OUT PPFN_NUMBER PageFrameIndex, IN PMMPDE PointerPde, IN PFN_NUMBER ContainingPageFrame, IN BOOLEAN SessionAllocation)
Definition: pfnlist.c:1101
PVOID MiSessionPoolStart
Definition: init.c:32
ULONG MmSessionPoolSize
Definition: init.c:36
PVOID MmSessionBase
Definition: init.c:33
PVOID MiSessionPoolEnd
Definition: init.c:31
PMMPTE LastPteForPagedPool
Definition: mm.h:496
PRTL_BITMAP EndOfPagedPoolBitmap
Definition: mm.h:494
PRTL_BITMAP PagedPoolAllocationMap
Definition: mm.h:493
PMMPDE NextPdeForPagedPoolExpansion
Definition: mm.h:497
PMMPTE FirstPteForPagedPool
Definition: mm.h:495
ULONG PagedPoolHint
Definition: mm.h:498
SIZE_T PagedPoolCommit
Definition: mm.h:499
PFN_NUMBER SessionPageDirectoryIndex
Definition: miarm.h:494
PMMPDE PageTables
Definition: miarm.h:521
KGUARDED_MUTEX PagedPoolMutex
Definition: miarm.h:512
PVOID PagedPoolStart
Definition: miarm.h:497
MM_PAGED_POOL_INFO PagedPoolInfo
Definition: miarm.h:513
struct _MM_SESSION_SPACE * GlobalVirtualAddress
Definition: miarm.h:484
PVOID PagedPoolEnd
Definition: miarm.h:498
SIZE_T CommittedPages
Definition: miarm.h:496
SIZE_T NonPageablePages
Definition: miarm.h:495
POOL_DESCRIPTOR PagedPool
Definition: miarm.h:517
PMMPDE PagedPoolBasePde
Definition: miarm.h:499
uint32_t * PULONG
Definition: typedefs.h:59
_In_ WDFCOLLECTION _In_ ULONG Index

◆ MiInitializeSessionSpaceLayout()

VOID NTAPI MiInitializeSessionSpaceLayout ( VOID  )

Definition at line 63 of file init.c.

64{
65 /* This is the entire size */
67
68 /* Start with session space end */
70
71 /* The highest range is the session image range */
76
77 /* Session working set is below the session image range */
79
80 /* Session view is below the session working set */
85
86 /* Session pool is below session view */
91
92 /* And it all begins here */
94
95 /* System view space ends at session space, so now that we know where
96 * this is, we can compute the base address of system view space itself. */
100
101 /* Sanity checks */
105
106 /* Compute the PTE addresses for all the addresses we carved out */
111
112 /* Initialize the pointer to the session space structure */
114}
#define Add2Ptr(PTR, INC)
PMMPTE MiSessionBasePte
Definition: mminit.c:145
struct _MM_SESSION_SPACE * PMM_SESSION_SPACE
PMMPTE MiSessionImagePteEnd
Definition: mminit.c:144
PMMPTE MiSessionLastPte
Definition: mminit.c:146
PMMPTE MiSessionImagePteStart
Definition: mminit.c:143
PVOID MiSessionSpaceWs
Definition: mminit.c:130
#define MI_SESSION_WORKING_SET_SIZE
Definition: mm.h:65
#define MI_SESSION_SIZE
Definition: mm.h:66
#define MI_SESSION_VIEW_SIZE
Definition: mm.h:62
#define MI_SESSION_SPACE_END
Definition: mm.h:25
#define MI_SESSION_IMAGE_SIZE
Definition: mm.h:64
#define MI_SYSTEM_VIEW_SIZE
Definition: mm.h:61
#define MI_SESSION_POOL_SIZE
Definition: mm.h:63
ULONG MmSessionImageSize
Definition: init.c:37
ULONG MmSessionSize
Definition: init.c:34
PVOID MiSessionViewStart
Definition: init.c:30
ULONG MmSessionViewSize
Definition: init.c:35
PVOID MiSessionImageStart
Definition: init.c:29
ULONG MmSystemViewSize
Definition: init.c:39
PVOID MiSystemViewStart
Definition: init.c:38
PVOID MiSessionImageEnd
Definition: init.c:28
PVOID MiSessionSpaceEnd
Definition: init.c:27
#define IS_PAGE_ALIGNED(addr)
Definition: init.c:23
PVOID MiSessionViewEnd
Definition: init.c:47
unsigned char * PUCHAR
Definition: typedefs.h:53

Referenced by MmArmInitSystem().

◆ MiInitializeSessionWsSupport()

VOID NTAPI MiInitializeSessionWsSupport ( VOID  )

Definition at line 40 of file session.c.

41{
42 /* Initialize the list heads */
44}
LIST_ENTRY MiSessionWsList
Definition: session.c:29

Referenced by MmInitSystem().

◆ MiInitializeSystemPtes()

VOID NTAPI MiInitializeSystemPtes ( IN PMMPTE  StartingPte,
IN ULONG  NumberOfPtes,
IN MMSYSTEM_PTE_POOL_TYPE  PoolType 
)

Definition at line 388 of file syspte.c.

391{
392 //
393 // Sanity checks
394 //
395 ASSERT(NumberOfPtes >= 1);
396
397 //
398 // Set the starting and ending PTE addresses for this space
399 //
401 MmSystemPtesStart[PoolType] = StartingPte;
402 MmSystemPtesEnd[PoolType] = StartingPte + NumberOfPtes - 1;
403 DPRINT("System PTE space for %d starting at: %p and ending at: %p\n",
405
406 //
407 // Clear all the PTEs to start with
408 //
409 RtlZeroMemory(StartingPte, NumberOfPtes * sizeof(MMPTE));
410
411 //
412 // Make the first entry free and link it
413 //
414 StartingPte->u.List.NextEntry = MM_EMPTY_PTE_LIST;
418
419 //
420 // The second entry stores the size of this PTE space
421 //
422 StartingPte++;
423 StartingPte->u.Long = 0;
424 StartingPte->u.List.NextEntry = NumberOfPtes;
425
426 //
427 // We also keep a global for it
428 //
429 MmTotalFreeSystemPtes[PoolType] = NumberOfPtes;
430
431 //
432 // Check if this is the system PTE space
433 //
435 {
436 //
437 // Remember how many PTEs we have
438 //
439 MmTotalSystemPtes = NumberOfPtes;
440 }
441}
#define MI_SYSTEM_PTE_BASE
Definition: mm.h:45
#define MM_EMPTY_PTE_LIST
Definition: mm.h:87
ULONG64 NextEntry
Definition: mmtypes.h:145
MMPTE_LIST List
Definition: mmtypes.h:222
PMMPTE MmSystemPtesStart[MaximumPtePoolTypes]
Definition: syspte.c:22
PMMPTE MmSystemPtesEnd[MaximumPtePoolTypes]
Definition: syspte.c:23
PMMPTE MmSystemPteBase
Definition: syspte.c:21
MMPTE MmFirstFreeSystemPte[MaximumPtePoolTypes]
Definition: syspte.c:24
ULONG MmTotalSystemPtes
Definition: syspte.c:26
ULONG MmTotalFreeSystemPtes[MaximumPtePoolTypes]
Definition: syspte.c:25

Referenced by MiBuildSystemPteSpace(), MiInitializeNonPagedPool(), and MiInitMachineDependent().

◆ MiInitializeSystemSpaceMap()

BOOLEAN NTAPI MiInitializeSystemSpaceMap ( IN PMMSESSION InputSession  OPTIONAL)

Definition at line 222 of file section.c.

223{
224 SIZE_T AllocSize, BitmapSize, Size;
225 PVOID ViewStart;
226 PMMSESSION Session;
227
228 /* Check if this a session or system space */
229 if (InputSession)
230 {
231 /* Use the input session */
232 Session = InputSession;
233 ViewStart = MiSessionViewStart;
235 }
236 else
237 {
238 /* Use the system space "session" */
239 Session = &MmSession;
240 ViewStart = MiSystemViewStart;
242 }
243
244 /* Initialize the system space lock */
247
248 /* Set the start address */
249 Session->SystemSpaceViewStart = ViewStart;
250
251 /* Create a bitmap to describe system space */
252 BitmapSize = sizeof(RTL_BITMAP) + ((((Size / MI_SYSTEM_VIEW_BUCKET_SIZE) + 31) / 32) * sizeof(ULONG));
254 BitmapSize,
255 TAG_MM);
256 ASSERT(Session->SystemSpaceBitMap);
258 (PULONG)(Session->SystemSpaceBitMap + 1),
260
261 /* Set system space fully empty to begin with */
263
264 /* Set default hash flags */
265 Session->SystemSpaceHashSize = 31;
266 Session->SystemSpaceHashKey = Session->SystemSpaceHashSize - 1;
267 Session->SystemSpaceHashEntries = 0;
268
269 /* Calculate how much space for the hash views we'll need */
270 AllocSize = sizeof(MMVIEW) * Session->SystemSpaceHashSize;
271 ASSERT(AllocSize < PAGE_SIZE);
272
273 /* Allocate and zero the view table */
276 PagedPool,
277 AllocSize,
278 TAG_MM);
279 ASSERT(Session->SystemSpaceViewTable != NULL);
280 RtlZeroMemory(Session->SystemSpaceViewTable, AllocSize);
281
282 /* Success */
283 return TRUE;
284}
MMSESSION MmSession
Definition: section.c:107
#define MI_SYSTEM_VIEW_BUCKET_SIZE
Definition: miarm.h:275
struct _MMVIEW MMVIEW
ULONG SystemSpaceHashKey
Definition: miarm.h:470
ULONG SystemSpaceHashEntries
Definition: miarm.h:469
PKGUARDED_MUTEX SystemSpaceViewLockPointer
Definition: miarm.h:465
PRTL_BITMAP SystemSpaceBitMap
Definition: miarm.h:472
PCHAR SystemSpaceViewStart
Definition: miarm.h:466
ULONG SystemSpaceHashSize
Definition: miarm.h:468
PMMVIEW SystemSpaceViewTable
Definition: miarm.h:467
KGUARDED_MUTEX SystemSpaceViewLock
Definition: miarm.h:464

Referenced by MiBuildPagedPool(), and MiSessionCreateInternal().

◆ MiInitMachineDependent()

NTSTATUS NTAPI MiInitMachineDependent ( IN PLOADER_PARAMETER_BLOCK  LoaderBlock)

Definition at line 697 of file init.c.

698{
700 ULONG Flags;
701
703
704 /* Set some hardcoded addresses */
709
710
711// PrototypePte.u.Proto.Valid = 1
712// PrototypePte.u.ReadOnly
713// PrototypePte.u.Prototype
714// PrototypePte.u.Protection = MM_READWRITE;
715// PrototypePte.u.ProtoAddress
717
719
721
723
724 /* Map the PFN database pages */
725 MiBuildPfnDatabase(LoaderBlock);
726
727 /* Reset the ref/share count so that MmInitializeProcessAddressSpace works */
729 Pfn->u2.ShareCount = 0;
730 Pfn->u3.e2.ReferenceCount = 0;
731
733 Pfn->u2.ShareCount = 0;
734 Pfn->u3.e2.ReferenceCount = 0;
735
737 Pfn->u2.ShareCount = 0;
738 Pfn->u3.e2.ReferenceCount = 0;
739
741 Pfn->u2.ShareCount = 0;
742 Pfn->u3.e2.ReferenceCount = 0;
743
745 Pfn->u2.ShareCount = 0;
746 Pfn->u3.e2.ReferenceCount = 0;
747
748 /* Initialize the nonpaged pool */
750
751 /* Initialize the bogus address space */
752 Flags = 0;
754 if (!NT_SUCCESS(Status))
755 {
756 DPRINT1("MmInitializeProcessAddressSpace(9 failed: 0x%lx\n", Status);
757 return Status;
758 }
759
760 /* Initialize the balancer */
762
763 /* Make sure we have everything we need */
774
775 return STATUS_SUCCESS;
776}
VOID NTAPI InitializePool(IN POOL_TYPE PoolType, IN ULONG Threshold)
Definition: expool.c:1020
PMMWSL MmWorkingSetList
Definition: wslist.cpp:19
#define HYPER_SPACE
Definition: mm.h:14
#define PFN_FROM_PXE(v)
Definition: mm.h:95
#define MI_WORKING_SET_LIST
Definition: mm.h:51
#define MM_SYSTEM_SPACE_START
Definition: mm.h:19
#define PFN_FROM_PPE(v)
Definition: mm.h:94
#define HYPER_SPACE_END
Definition: mm.h:15
#define MI_PFN_DATABASE
Definition: mm.h:28
NTSTATUS NTAPI MmInitializeProcessAddressSpace(IN PEPROCESS Process, IN PEPROCESS Clone OPTIONAL, IN PVOID Section OPTIONAL, IN OUT PULONG Flags, IN POBJECT_NAME_INFORMATION *AuditName OPTIONAL)
VOID NTAPI MmInitializeBalancer(ULONG NrAvailablePages, ULONG NrSystemPages)
Definition: balance.c:44
PFN_NUMBER MmAvailablePages
Definition: freelist.c:26
ULONG MxPfnAllocation
Definition: init.c:43
PVOID MmNonPagedSystemStart
Definition: init.c:23
ULONG MmMaximumNonPagedPoolInBytes
Definition: init.c:22
ULONG MmNumberOfSystemPtes
Definition: init.c:42
PVOID MmNonPagedPoolExpansionStart
Definition: init.c:25
PVOID MmHyperSpaceEnd
Definition: init.c:56
PVOID MmNonPagedPoolStart
Definition: init.c:24
VOID NTAPI MiBuildSystemPteSpace(VOID)
Definition: init.c:379
VOID NTAPI MiInitializePageTable(VOID)
Definition: init.c:200
VOID NTAPI MiBuildPfnDatabase(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: init.c:617
VOID NTAPI MiBuildNonPagedPool(VOID)
Definition: init.c:288
ULONG64 PageFileHigh
Definition: mmtypes.h:93
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170

Referenced by MmArmInitSystem().

◆ MiInsertBasedSection()

VOID NTAPI MiInsertBasedSection ( IN PSECTION  Section)

Definition at line 423 of file vadnode.c.

424{
427 ASSERT(Section->Address.EndingVpn >= Section->Address.StartingVpn);
428
430
431 /* Find the parent VAD and where this child should be inserted */
432 Result = RtlpFindAvlTableNodeOrParent(&MmSectionBasedRoot, (PVOID)Section->Address.StartingVpn, &Parent);
433 ASSERT(Result != TableFoundNode);
434 ASSERT((Parent != NULL) || (Result == TableEmptyTree));
435 MiInsertNode(&MmSectionBasedRoot, &Section->Address, Parent, Result);
436}
#define RtlpFindAvlTableNodeOrParent
Definition: miavl.h:32
VOID NTAPI MiInsertNode(IN PMM_AVL_TABLE Table, IN PMMADDRESS_NODE NewNode, IN PMMADDRESS_NODE Parent, IN TABLE_SEARCH_RESULT Result)
Definition: vadnode.c:202
#define ASSERT_LOCKED_FOR_WRITE(Table)
Definition: vadnode.c:110
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:409
TABLE_SEARCH_RESULT
Definition: rtltypes.h:386

Referenced by MmCreateArm3Section().

◆ MiInsertNode()

VOID NTAPI MiInsertNode ( IN PMM_AVL_TABLE  Table,
IN PMMADDRESS_NODE  NewNode,
PMMADDRESS_NODE  Parent,
TABLE_SEARCH_RESULT  Result 
)

◆ MiInsertPageInFreeList()

VOID NTAPI MiInsertPageInFreeList ( IN PFN_NUMBER  PageFrameIndex)

Definition at line 611 of file pfnlist.c.

612{
613 PMMPFNLIST ListHead;
614 PFN_NUMBER LastPage;
615 PMMPFN Pfn1;
616 ULONG Color;
617 PMMPFN Blink;
618 PMMCOLOR_TABLES ColorTable;
619
620 /* Make sure the page index is valid */
622 ASSERT((PageFrameIndex != 0) &&
623 (PageFrameIndex <= MmHighestPhysicalPage) &&
624 (PageFrameIndex >= MmLowestPhysicalPage));
625
626 /* Get the PFN entry */
627 Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
628
629 /* Sanity checks that a right kind of page is being inserted here */
630 ASSERT(Pfn1->u4.MustBeCached == 0);
631 ASSERT(Pfn1->u3.e1.Rom != 1);
632 ASSERT(Pfn1->u3.e1.RemovalRequested == 0);
633 ASSERT(Pfn1->u4.VerifierAllocation == 0);
634 ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
635
636 /* Get the free page list and increment its count */
637 ListHead = &MmFreePageListHead;
638 ASSERT_LIST_INVARIANT(ListHead);
639 ListHead->Total++;
640
641 /* Get the last page on the list */
642 LastPage = ListHead->Blink;
643 if (LastPage != LIST_HEAD)
644 {
645 /* Link us with the previous page, so we're at the end now */
646 MI_PFN_ELEMENT(LastPage)->u1.Flink = PageFrameIndex;
647 }
648 else
649 {
650 /* The list is empty, so we are the first page */
651 ListHead->Flink = PageFrameIndex;
652 }
653
654 /* Now make the list head point back to us (since we go at the end) */
655 ListHead->Blink = PageFrameIndex;
656 ASSERT_LIST_INVARIANT(ListHead);
657
658 /* And initialize our own list pointers */
659 Pfn1->u1.Flink = LIST_HEAD;
660 Pfn1->u2.Blink = LastPage;
661
662 /* Set the list name and default priority */
664 Pfn1->u4.Priority = 3;
665
666 /* Clear some status fields */
667 Pfn1->u4.InPageError = 0;
668 Pfn1->u4.AweAllocation = 0;
669
670 /* Increment number of available pages */
672
673 /* Get the page color */
674 Color = PageFrameIndex & MmSecondaryColorMask;
675
676 /* Get the first page on the color list */
677 ColorTable = &MmFreePagesByColor[FreePageList][Color];
678 if (ColorTable->Flink == LIST_HEAD)
679 {
680 /* The list is empty, so we are the first page */
681 Pfn1->u4.PteFrame = COLORED_LIST_HEAD;
682 ColorTable->Flink = PageFrameIndex;
683 }
684 else
685 {
686 /* Get the previous page */
687 Blink = (PMMPFN)ColorTable->Blink;
688
689 /* Make it link to us, and link back to it */
690 Blink->OriginalPte.u.Long = PageFrameIndex;
691 Pfn1->u4.PteFrame = MiGetPfnEntryIndex(Blink);
692 }
693
694 /* Now initialize our own list pointers */
695 ColorTable->Blink = Pfn1;
696
697 /* This page is now the last */
698 Pfn1->OriginalPte.u.Long = LIST_HEAD;
699
700 /* And increase the count in the colored list */
701 ColorTable->Count++;
702
703 /* Notify zero page thread if enough pages are on the free list now */
704 if (ListHead->Total >= 8)
705 {
706 /* Set the event */
708 }
709
710#if MI_TRACE_PFNS
711 Pfn1->PfnUsage = MI_USAGE_FREE_PAGE;
712 RtlZeroMemory(Pfn1->ProcessName, 16);
713 Pfn1->CallSite = NULL;
714#endif
715}
ULONG MmSecondaryColorMask
Definition: mminit.c:257
KEVENT MmZeroingPageEvent
Definition: zeropage.c:20
PMMCOLOR_TABLES MmFreePagesByColor[FreePageList+1]
Definition: mminit.c:286
@ MI_USAGE_FREE_PAGE
Definition: mm.h:356
struct _MMPFN * PMMPFN
#define ASSERT_LIST_INVARIANT(x)
Definition: pfnlist.c:29
static VOID MiIncrementAvailablePages(VOID)
Definition: pfnlist.c:69
MMPFNLIST MmFreePageListHead
Definition: pfnlist.c:42
USHORT RemovalRequested
Definition: mm.h:373
Definition: mm.h:449
PFN_NUMBER Total
Definition: mm.h:450
PFN_NUMBER Blink
Definition: mm.h:453
PFN_NUMBER Flink
Definition: mm.h:452
ULONG_PTR MustBeCached
Definition: mm.h:430
PFN_NUMBER Blink
Definition: mm.h:396
PFN_NUMBER Flink
Definition: mm.h:384
ULONG_PTR Priority
Definition: mm.h:429
#define IO_NO_INCREMENT
Definition: iotypes.h:598

Referenced by MiAddDescriptorToDatabase(), MiBuildPfnDatabaseFromLoaderBlock(), MiDecrementReferenceCount(), MiDecrementShareCount(), MiSegmentDelete(), MmCreateProcessAddressSpace(), MmDereferencePage(), and MmFreeLoaderBlock().

◆ MiInsertPageInList()

VOID NTAPI MiInsertPageInList ( IN PMMPFNLIST  ListHead,
IN PFN_NUMBER  PageFrameIndex 
)

Definition at line 779 of file pfnlist.c.

781{
782 PFN_NUMBER Flink, LastPage;
783 PMMPFN Pfn1, Pfn2;
784 MMLISTS ListName;
785 PMMCOLOR_TABLES ColorHead;
786 ULONG Color;
787
788 /* For free pages, use MiInsertPageInFreeList */
789 ASSERT(ListHead != &MmFreePageListHead);
790
791 /* Make sure the lock is held */
793
794 /* Make sure the PFN is valid */
795 ASSERT((PageFrameIndex) &&
796 (PageFrameIndex <= MmHighestPhysicalPage) &&
797 (PageFrameIndex >= MmLowestPhysicalPage));
798
799 /* Page should be unused */
800 Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
801 ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
802 ASSERT(Pfn1->u3.e1.Rom != 1);
803
804 /* Is a standby or modified page being inserted? */
805 ListName = ListHead->ListName;
806 if ((ListName == StandbyPageList) || (ListName == ModifiedPageList))
807 {
808 /* If the page is in transition, it must also be a prototype page */
809 if ((Pfn1->OriginalPte.u.Soft.Prototype == 0) &&
810 (Pfn1->OriginalPte.u.Soft.Transition == 1))
811 {
812 /* Crash the system on inconsistency */
813 KeBugCheckEx(MEMORY_MANAGEMENT, 0x8888, 0, 0, 0);
814 }
815 }
816
817 /* Standby pages are prioritized, so we need to get the real head */
818 if (ListHead == &MmStandbyPageListHead)
819 {
820 /* Obviously the prioritized list should still have the same name */
821 ListHead = &MmStandbyPageListByPriority[Pfn1->u4.Priority];
822 ASSERT(ListHead->ListName == ListName);
823 }
824
825 /* Increment the list count */
826 ListHead->Total++;
827
828 /* Is a modified page being inserted? */
829 if (ListHead == &MmModifiedPageListHead)
830 {
831 /* For now, only single-prototype pages should end up in this path */
832 DPRINT("Modified page being added: %lx\n", PageFrameIndex);
833 ASSERT(Pfn1->OriginalPte.u.Soft.Prototype == 0);
834
835 /* Modified pages are colored when they are selected for page file */
836 ListHead = &MmModifiedPageListByColor[0];
837 ASSERT (ListHead->ListName == ListName);
838 ListHead->Total++;
839
840 /* Increment the number of paging file modified pages */
842 }
843
844 /* Don't handle bad pages yet yet */
845 ASSERT(Pfn1->u3.e1.RemovalRequested == 0);
846
847 /* Zero pages go to the head, all other pages go to the end */
848 if (ListName == ZeroedPageList)
849 {
850 /* Make the head of the list point to this page now */
851 Flink = ListHead->Flink;
852 ListHead->Flink = PageFrameIndex;
853
854 /* Make the page point to the previous head, and back to the list */
855 Pfn1->u1.Flink = Flink;
856 Pfn1->u2.Blink = LIST_HEAD;
857
858 /* Was the list empty? */
859 if (Flink != LIST_HEAD)
860 {
861 /* It wasn't, so update the backlink of the previous head page */
862 Pfn2 = MI_PFN_ELEMENT(Flink);
863 Pfn2->u2.Blink = PageFrameIndex;
864 }
865 else
866 {
867 /* It was empty, so have it loop back around to this new page */
868 ListHead->Blink = PageFrameIndex;
869 }
870 }
871 else
872 {
873 /* Get the last page on the list */
874 LastPage = ListHead->Blink;
875 if (LastPage != LIST_HEAD)
876 {
877 /* Link us with the previous page, so we're at the end now */
878 MI_PFN_ELEMENT(LastPage)->u1.Flink = PageFrameIndex;
879 }
880 else
881 {
882 /* The list is empty, so we are the first page */
883 ListHead->Flink = PageFrameIndex;
884 }
885
886 /* Now make the list head point back to us (since we go at the end) */
887 ListHead->Blink = PageFrameIndex;
888 ASSERT_LIST_INVARIANT(ListHead);
889
890 /* And initialize our own list pointers */
891 Pfn1->u1.Flink = LIST_HEAD;
892 Pfn1->u2.Blink = LastPage;
893 }
894
895 /* Move the page onto its new location */
896 Pfn1->u3.e1.PageLocation = ListName;
897
898 /* For zero/free pages, we also have to handle the colored lists */
899 if (ListName <= StandbyPageList)
900 {
901 /* Increment number of available pages */
903
904 /* Sanity checks */
905 ASSERT(ListName == ZeroedPageList);
906 ASSERT(Pfn1->u4.InPageError == 0);
907
908 /* Get the page color */
909 Color = PageFrameIndex & MmSecondaryColorMask;
910
911 /* Get the list for this color */
913
914 /* Get the old head */
915 Flink = ColorHead->Flink;
916
917 /* Make this page point back to the list, and point forwards to the old head */
918 Pfn1->OriginalPte.u.Long = Flink;
919 Pfn1->u4.PteFrame = COLORED_LIST_HEAD;
920
921 /* Set the new head */
922 ColorHead->Flink = PageFrameIndex;
923
924 /* Was the head empty? */
925 if (Flink != LIST_HEAD)
926 {
927 /* No, so make the old head point to this page */
928 Pfn2 = MI_PFN_ELEMENT(Flink);
929 Pfn2->u4.PteFrame = PageFrameIndex;
930 }
931 else
932 {
933 /* Yes, make it loop back to this page */
934 ColorHead->Blink = (PVOID)Pfn1;
935 }
936
937 /* One more paged on the colored list */
938 ColorHead->Count++;
939
940#if MI_TRACE_PFNS
942 Pfn1->PfnUsage = MI_USAGE_FREE_PAGE;
943 RtlZeroMemory(Pfn1->ProcessName, 16);
944 Pfn1->CallSite = NULL;
945#endif
946 }
947 else if (ListName == ModifiedPageList)
948 {
949 /* In ARM3, page must be destined for page file, and not yet written out */
950 ASSERT(Pfn1->OriginalPte.u.Soft.Prototype == 0);
952
953 /* One more transition page */
955
956 /* Increment the number of per-process modified pages */
957 PsGetCurrentProcess()->ModifiedPageCount++;
958
959 /* FIXME: Wake up modified page writer if there are not enough free pages */
960 }
961 else if (ListName == ModifiedNoWritePageList)
962 {
963 /* This list is not yet implemented */
964 ASSERT(FALSE);
965 }
966}
enum _MMLISTS MMLISTS
@ ModifiedNoWritePageList
Definition: mmtypes.h:157
@ MI_USAGE_NOT_SET
Definition: mm.h:331
MMPFNLIST MmStandbyPageListHead
Definition: pfnlist.c:43
MMPFNLIST MmModifiedPageListByColor[1]
Definition: pfnlist.c:46
ULONG MmTransitionSharedPages
Definition: pfnlist.c:38
ULONG MI_PFN_CURRENT_USAGE
Definition: pfnlist.c:63
MMPFNLIST MmStandbyPageListByPriority[8]
Definition: pfnlist.c:44
ULONG MmTotalPagesForPagingFile
Definition: pfnlist.c:39

Referenced by MiDecrementReferenceCount(), and MmZeroPageThread().

◆ MiInsertVad()

VOID NTAPI MiInsertVad ( _Inout_ PMMVAD  Vad,
_Inout_ PMM_AVL_TABLE  VadRoot 
)

◆ MiInsertVadEx()

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 
)

Definition at line 282 of file vadnode.c.

289{
290 ULONG_PTR StartingAddress, EndingAddress;
291 PEPROCESS CurrentProcess;
292 PETHREAD CurrentThread;
295
296 /* Align the view size to pages */
298
299 /* Get the current process */
300 CurrentProcess = PsGetCurrentProcess();
301
302 /* Acquire the address creation lock and make sure the process is alive */
304 if (CurrentProcess->VmDeleted)
305 {
307 DPRINT1("The process is dying\n");
309 }
310
311 /* Did the caller specify an address? */
312 if (*BaseAddress == 0)
313 {
314 /* Make sure HighestAddress is not too large */
315 HighestAddress = min(HighestAddress, (ULONG_PTR)MM_HIGHEST_VAD_ADDRESS);
316
317 /* Which way should we search? */
318 if ((AllocationType & MEM_TOP_DOWN) || CurrentProcess->VmTopDown)
319 {
320 /* Find an address top-down */
322 HighestAddress,
323 Alignment,
324 &CurrentProcess->VadRoot,
325 &StartingAddress,
326 &Parent);
327 }
328 else
329 {
330 /* Find an address bottom-up */
332 Alignment,
333 &CurrentProcess->VadRoot,
334 &Parent,
335 &StartingAddress);
336 }
337
338 /* Get the ending address, which is the last piece we need for the VAD */
339 EndingAddress = StartingAddress + ViewSize - 1;
340
341 /* Check if we found a suitable location */
342 if ((Result == TableFoundNode) || (EndingAddress > HighestAddress))
343 {
344 DPRINT1("Not enough free space to insert this VAD node!\n");
346 return STATUS_NO_MEMORY;
347 }
348
349 ASSERT(StartingAddress != 0);
350 ASSERT(StartingAddress < (ULONG_PTR)HighestAddress);
351 ASSERT(EndingAddress > StartingAddress);
352 }
353 else
354 {
355 /* Calculate the starting and ending address */
356 StartingAddress = ALIGN_DOWN_BY(*BaseAddress, Alignment);
357 EndingAddress = StartingAddress + ViewSize - 1;
358
359 /* Make sure it doesn't conflict with an existing allocation */
360 Result = MiCheckForConflictingNode(StartingAddress >> PAGE_SHIFT,
361 EndingAddress >> PAGE_SHIFT,
362 &CurrentProcess->VadRoot,
363 &Parent);
364 if (Result == TableFoundNode)
365 {
366 DPRINT("Given address conflicts with existing node\n");
369 }
370 }
371
372 /* Now set the VAD address */
373 Vad->StartingVpn = StartingAddress >> PAGE_SHIFT;
374 Vad->EndingVpn = EndingAddress >> PAGE_SHIFT;
375
376 /* Check if we already need to charge for the pages */
377 if ((Vad->u.VadFlags.PrivateMemory && Vad->u.VadFlags.MemCommit) ||
378 (!Vad->u.VadFlags.PrivateMemory &&
379 (Vad->u.VadFlags.Protection & PAGE_WRITECOPY)))
380 {
381 /* Set the commit charge */
382 Vad->u.VadFlags.CommitCharge = ViewSize / PAGE_SIZE;
383 }
384
385 /* Check if the VAD is to be secured */
386 if (Vad->u2.VadFlags2.OneSecured)
387 {
388 /* This *must* be a long VAD! */
389 ASSERT(Vad->u2.VadFlags2.LongVad);
390
391 /* Yeah this is retarded, I didn't invent it! */
392 ((PMMVAD_LONG)Vad)->u3.Secured.StartVpn = StartingAddress;
393 ((PMMVAD_LONG)Vad)->u3.Secured.EndVpn = EndingAddress;
394 }
395
396 /* Lock the working set */
397 CurrentThread = PsGetCurrentThread();
398 MiLockProcessWorkingSetUnsafe(CurrentProcess, CurrentThread);
399
400 /* Insert the VAD */
401 CurrentProcess->VadRoot.NodeHint = Vad;
402 MiInsertNode(&CurrentProcess->VadRoot, (PVOID)Vad, Parent, Result);
403
404 /* Release the working set */
405 MiUnlockProcessWorkingSetUnsafe(CurrentProcess, CurrentThread);
406
407 /* Update the process' virtual size, and peak virtual size */
408 CurrentProcess->VirtualSize += ViewSize;
409 if (CurrentProcess->VirtualSize > CurrentProcess->PeakVirtualSize)
410 {
411 CurrentProcess->PeakVirtualSize = CurrentProcess->VirtualSize;
412 }
413
414 /* Unlock the address space */
416
417 *BaseAddress = StartingAddress;
418 return STATUS_SUCCESS;
419}
FORCEINLINE VOID MiUnlockProcessWorkingSetUnsafe(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1252
FORCEINLINE VOID MiLockProcessWorkingSetUnsafe(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1182
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID _In_ ULONG_PTR _In_ SIZE_T _Inout_opt_ PLARGE_INTEGER _Inout_ PSIZE_T _In_ SECTION_INHERIT _In_ ULONG AllocationType
Definition: mmfuncs.h:410
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID _In_ ULONG_PTR _In_ SIZE_T _Inout_opt_ PLARGE_INTEGER _Inout_ PSIZE_T ViewSize
Definition: mmfuncs.h:408
struct _MMVAD_LONG * PMMVAD_LONG
#define MEM_TOP_DOWN
Definition: nt_native.h:1321
#define PAGE_WRITECOPY
Definition: nt_native.h:1305
#define STATUS_PROCESS_IS_TERMINATING
Definition: ntstatus.h:502
#define STATUS_CONFLICTING_ADDRESSES
Definition: ntstatus.h:261
MM_AVL_TABLE VadRoot
Definition: pstypes.h:1454
EX_PUSH_LOCK AddressCreationLock
Definition: pstypes.h:1291
SIZE_T PeakVirtualSize
Definition: pstypes.h:1273
SIZE_T VirtualSize
Definition: pstypes.h:1274
ULONG VmDeleted
Definition: pstypes.h:1399
ULONG VmTopDown
Definition: pstypes.h:1418
PVOID NodeHint
Definition: mmtypes.h:670
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: vadnode.c:681
TABLE_SEARCH_RESULT NTAPI MiFindEmptyAddressRangeInTree(IN SIZE_T Length, IN ULONG_PTR Alignment, IN PMM_AVL_TABLE Table, OUT PMMADDRESS_NODE *PreviousVad, OUT PULONG_PTR Base)
Definition: vadnode.c:584
TABLE_SEARCH_RESULT NTAPI MiCheckForConflictingNode(IN ULONG_PTR StartVpn, IN ULONG_PTR EndVpn, IN PMM_AVL_TABLE Table, OUT PMMADDRESS_NODE *NodeOrParent)
Definition: vadnode.c:150

Referenced by MiCreatePebOrTeb(), MiMapViewOfDataSection(), and NtAllocateVirtualMemory().

◆ MiIsMemoryTypeFree()

FORCEINLINE BOOLEAN MiIsMemoryTypeFree ( TYPE_OF_MEMORY  MemoryType)

Definition at line 682 of file miarm.h.

683{
684 return ((MemoryType == LoaderFree) ||
685 (MemoryType == LoaderLoadedProgram) ||
686 (MemoryType == LoaderFirmwareTemporary) ||
687 (MemoryType == LoaderOsloaderStack));
688}
@ LoaderFree
Definition: arc.h:176
@ LoaderFirmwareTemporary
Definition: arc.h:179
@ LoaderLoadedProgram
Definition: arc.h:178
@ LoaderOsloaderStack
Definition: arc.h:182

Referenced by MiAddDescriptorToDatabase(), and MiScanMemoryDescriptors().

◆ MiIsMemoryTypeInvisible()

FORCEINLINE BOOLEAN MiIsMemoryTypeInvisible ( TYPE_OF_MEMORY  MemoryType)

Definition at line 692 of file miarm.h.

693{
694 return ((MemoryType == LoaderFirmwarePermanent) ||
695 (MemoryType == LoaderSpecialMemory) ||
696 (MemoryType == LoaderHALCachedMemory) ||
697 (MemoryType == LoaderBBTMemory));
698}
@ LoaderHALCachedMemory
Definition: arc.h:200
@ LoaderFirmwarePermanent
Definition: arc.h:180
@ LoaderSpecialMemory
Definition: arc.h:196
@ LoaderBBTMemory
Definition: arc.h:197

Referenced by KdpGetMemorySizeInMBs(), MiAddDescriptorToDatabase(), MiBuildPfnDatabase(), and MiScanMemoryDescriptors().

◆ MiIsPfnInUse()

BOOLEAN NTAPI MiIsPfnInUse ( IN PMMPFN  Pfn1)

Definition at line 174 of file freelist.c.

175{
176 /* Standby list or higher, unlinked, and with references */
177 return !MiIsPfnFree(Pfn1);
178}
BOOLEAN NTAPI MiIsPfnFree(IN PMMPFN Pfn1)
Definition: freelist.c:163

Referenced by MiAllocatePagesForMdl(), MiFindContiguousPages(), MmGetRmapListHeadPage(), MmIsPageInUse(), and MmSetRmapListHeadPage().

◆ MiIsRosSectionObject()

FORCEINLINE BOOLEAN MiIsRosSectionObject ( IN PSECTION  Section)

◆ MiIsUserPde()

FORCEINLINE BOOLEAN MiIsUserPde ( PVOID  Address)

Definition at line 731 of file miarm.h.

732{
733 return ((Address >= (PVOID)MiAddressToPde(NULL)) &&
735}
PMMPDE MiHighestUserPde
Definition: mminit.c:234

Referenced by MiDeletePde(), MiDetermineUserGlobalPteMask(), and MmArmAccessFault().

◆ MiIsUserPte()

FORCEINLINE BOOLEAN MiIsUserPte ( PVOID  Address)

Definition at line 739 of file miarm.h.

740{
741 return (Address >= (PVOID)PTE_BASE) && (Address <= (PVOID)MiHighestUserPte);
742}
#define PTE_BASE
Definition: mmx86.c:14

Referenced by MiDetermineUserGlobalPteMask(), and MmArmAccessFault().

◆ MiLocateAddress()

PMMVAD NTAPI MiLocateAddress ( IN PVOID  VirtualAddress)

Definition at line 116 of file vadnode.c.

117{
118 PMMVAD FoundVad;
119 ULONG_PTR Vpn;
121 TABLE_SEARCH_RESULT SearchResult;
122
124
125 /* Start with the the hint */
126 FoundVad = (PMMVAD)Table->NodeHint;
127 if (!FoundVad) return NULL;
128
129 /* Check if this VPN is in the hint, if so, use it */
131 if ((Vpn >= FoundVad->StartingVpn) && (Vpn <= FoundVad->EndingVpn)) return FoundVad;
132
133 /* VAD hint didn't work, go look for it */
134 SearchResult = RtlpFindAvlTableNodeOrParent(Table,
135 (PVOID)Vpn,
136 (PMMADDRESS_NODE*)&FoundVad);
137 if (SearchResult != TableFoundNode) return NULL;
138
139 /* We found it, update the hint */
140 ASSERT(FoundVad != NULL);
141 ASSERT((Vpn >= FoundVad->StartingVpn) && (Vpn <= FoundVad->EndingVpn));
142
143 /* We allow this (atomic) update without exclusive lock, because it's a hint only */
144 Table->NodeHint = FoundVad;
145 return FoundVad;
146}
if(dx< 0)
Definition: linetemp.h:194
struct _MMVAD * PMMVAD
ULONG_PTR EndingVpn
Definition: mmtypes.h:730
ULONG_PTR StartingVpn
Definition: mmtypes.h:729

Referenced by MiCheckVadsForLockOperation(), MiCheckVirtualAddress(), MiUnmapLockedPagesInUserSpace(), MiUnmapViewOfSection(), MmDeleteTeb(), MmGetFileNameForAddress(), NtAreMappedFilesTheSame(), and NtFreeVirtualMemory().

◆ MiLocateSubsection()

PSUBSECTION NTAPI MiLocateSubsection ( IN PMMVAD  Vad,
IN ULONG_PTR  Vpn 
)

Definition at line 556 of file section.c.

558{
559 PSUBSECTION Subsection;
560 PCONTROL_AREA ControlArea;
561 ULONG_PTR PteOffset;
562
563 /* Get the control area */
564 ControlArea = Vad->ControlArea;
565 ASSERT(ControlArea->u.Flags.Rom == 0);
566 ASSERT(ControlArea->u.Flags.Image == 0);
567 ASSERT(ControlArea->u.Flags.GlobalOnlyPerSession == 0);
568
569 /* Get the subsection */
570 Subsection = (PSUBSECTION)(ControlArea + 1);
571
572 /* We only support single-subsection segments */
573 ASSERT(Subsection->SubsectionBase != NULL);
574 ASSERT(Vad->FirstPrototypePte >= Subsection->SubsectionBase);
575 ASSERT(Vad->FirstPrototypePte < &Subsection->SubsectionBase[Subsection->PtesInSubsection]);
576
577 /* Compute the PTE offset */
578 PteOffset = Vpn - Vad->StartingVpn;
579 PteOffset += Vad->FirstPrototypePte - Subsection->SubsectionBase;
580
581 /* Again, we only support single-subsection segments */
582 ASSERT(PteOffset < 0xF0000000);
583 ASSERT(PteOffset < Subsection->PtesInSubsection);
584
585 /* Return the subsection */
586 return Subsection;
587}
struct _SUBSECTION * PSUBSECTION
ULONG GlobalOnlyPerSession
Definition: mmtypes.h:491

Referenced by MiDeleteVirtualAddresses().

◆ MiLockProcessWorkingSet()

FORCEINLINE VOID MiLockProcessWorkingSet ( IN PEPROCESS  Process,
IN PETHREAD  Thread 
)

Definition at line 1137 of file miarm.h.

1139{
1140 /* Shouldn't already be owning the process working set */
1143
1144 /* Block APCs, make sure that still nothing is already held */
1147
1148 /* Lock the working set */
1149 ExAcquirePushLockExclusive(&Process->Vm.WorkingSetMutex);
1150
1151 /* Now claim that we own the lock */
1155}
FORCEINLINE VOID ExAcquirePushLockExclusive(PEX_PUSH_LOCK PushLock)
Definition: ex.h:1039
FORCEINLINE BOOLEAN MI_IS_WS_UNSAFE(IN PEPROCESS Process)
Definition: miarm.h:1127
FORCEINLINE BOOLEAN MM_ANY_WS_LOCK_HELD(IN PETHREAD Thread)
Definition: miarm.h:1065

Referenced by MiLockProcessWorkingSetForFault(), MiLockVirtualMemory(), MiUnlockVirtualMemory(), MmArmAccessFault(), MmFreeMemoryArea(), MmInitializeProcessAddressSpace(), MmProbeAndLockPages(), and MmTrimUserMemory().

◆ MiLockProcessWorkingSetForFault()

FORCEINLINE VOID MiLockProcessWorkingSetForFault ( IN PEPROCESS  Process,
IN PETHREAD  Thread,
IN BOOLEAN  Safe,
IN BOOLEAN  Shared 
)

Definition at line 1514 of file miarm.h.

1518{
1519 /* Check if this was a safe lock or not */
1520 if (Safe)
1521 {
1522 if (Shared)
1523 {
1524 /* Reacquire safely & shared */
1526 }
1527 else
1528 {
1529 /* Reacquire safely */
1531 }
1532 }
1533 else
1534 {
1535 /* Unsafe lock cannot be shared */
1536 ASSERT(Shared == FALSE);
1537 /* Reacquire unsafely */
1539 }
1540}
FORCEINLINE VOID MiLockProcessWorkingSetShared(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1159
FORCEINLINE VOID MiLockProcessWorkingSet(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1137

Referenced by MiGetPageProtection(), and MiMakeSystemAddressValid().

◆ MiLockProcessWorkingSetShared()

FORCEINLINE VOID MiLockProcessWorkingSetShared ( IN PEPROCESS  Process,
IN PETHREAD  Thread 
)

Definition at line 1159 of file miarm.h.

1161{
1162 /* Shouldn't already be owning the process working set */
1165
1166 /* Block APCs, make sure that still nothing is already held */
1169
1170 /* Lock the working set */
1171 ExAcquirePushLockShared(&Process->Vm.WorkingSetMutex);
1172
1173 /* Now claim that we own the lock */
1178}
FORCEINLINE VOID ExAcquirePushLockShared(PEX_PUSH_LOCK PushLock)
Definition: ex.h:1108

Referenced by MiLockProcessWorkingSetForFault(), MiQueryMemoryBasicInformation(), MmAccessFault(), MmGetPageFileMapping(), MmGetPageProtect(), MmGetPfnForProcess(), MmIsDisabledPage(), MmIsPagePresent(), and MmIsPageSwapEntry().

◆ MiLockProcessWorkingSetUnsafe()

FORCEINLINE VOID MiLockProcessWorkingSetUnsafe ( IN PEPROCESS  Process,
IN PETHREAD  Thread 
)

Definition at line 1182 of file miarm.h.

1184{
1185 /* Shouldn't already be owning the process working set */
1187
1188 /* APCs must be blocked, make sure that still nothing is already held */
1191
1192 /* Lock the working set */
1193 ExAcquirePushLockExclusive(&Process->Vm.WorkingSetMutex);
1194
1195 /* Now claim that we own the lock */
1197 Process->Vm.Flags.AcquiredUnsafe = 1;
1200}
BOOLEAN NTAPI KeAreAllApcsDisabled(VOID)
Definition: apc.c:985

Referenced by _Success_(), MiDecommitPages(), MiInsertVadEx(), MiLockProcessWorkingSetForFault(), MiMapLockedPagesInUserSpace(), MiProtectVirtualMemory(), MiUnmapLockedPagesInUserSpace(), MiUnmapViewOfSection(), MmCleanProcessAddressSpace(), MmCreatePageFileMapping(), MmCreateVirtualMappingUnsafeEx(), MmDeletePageFileMapping(), MmDeleteTeb(), MmInsertMemoryArea(), MmSetDirtyBit(), MmSetPageProtect(), NtAllocateVirtualMemory(), and NtFreeVirtualMemory().

◆ MiLockWorkingSet()

FORCEINLINE VOID MiLockWorkingSet ( IN PETHREAD  Thread,
IN PMMSUPPORT  WorkingSet 
)

Definition at line 1278 of file miarm.h.

1280{
1281 /* Block APCs */
1283
1284 /* Working set should be in global memory */
1285 ASSERT(MI_IS_SESSION_ADDRESS((PVOID)WorkingSet) == FALSE);
1286
1287 /* Thread shouldn't already be owning something */
1289
1290 /* Lock this working set */
1291 ExAcquirePushLockExclusive(&WorkingSet->WorkingSetMutex);
1292
1293 /* Which working set is this? */
1294 if (WorkingSet == &MmSystemCacheWs)
1295 {
1296 /* Own the system working set */
1300 }
1301 else if (WorkingSet->Flags.SessionSpace)
1302 {
1303 /* Own the session working set */
1307 }
1308 else
1309 {
1310 /* Own the process working set */
1314 }
1315}
#define MI_IS_SESSION_ADDRESS(Address)
Definition: miarm.h:185

Referenced by MiDeleteSystemPageableVm(), MiSetPagingOfDriver(), MmAdjustWorkingSetSize(), MmArmAccessFault(), MmFreeMemoryArea(), and MmInsertMemoryArea().

◆ MiLockWorkingSetShared()

FORCEINLINE VOID MiLockWorkingSetShared ( _In_ PETHREAD  Thread,
_In_ PMMSUPPORT  WorkingSet 
)

Definition at line 1319 of file miarm.h.

1322{
1323 /* Block APCs */
1325
1326 /* Working set should be in global memory */
1327 ASSERT(MI_IS_SESSION_ADDRESS((PVOID)WorkingSet) == FALSE);
1328
1329 /* Thread shouldn't already be owning something */
1331
1332 /* Lock this working set */
1333 ExAcquirePushLockShared(&WorkingSet->WorkingSetMutex);
1334
1335 /* Which working set is this? */
1336 if (WorkingSet == &MmSystemCacheWs)
1337 {
1338 /* Own the system working set */
1342 }
1343 else if (WorkingSet->Flags.SessionSpace)
1344 {
1345 /* Own the session working set */
1349 }
1350 else
1351 {
1352 /* Own the process working set */
1356 }
1357}

Referenced by MmAccessFault(), and MmWorkingSetManager().

◆ MiLookupDataTableEntry()

PLDR_DATA_TABLE_ENTRY NTAPI MiLookupDataTableEntry ( IN PVOID  Address)

Definition at line 3528 of file sysldr.c.

3529{
3530 PLDR_DATA_TABLE_ENTRY LdrEntry, FoundEntry = NULL;
3531 PLIST_ENTRY NextEntry;
3532 PAGED_CODE();
3533
3534 /* Loop entries */
3535 NextEntry = PsLoadedModuleList.Flink;
3536 do
3537 {
3538 /* Get the loader entry */
3539 LdrEntry = CONTAINING_RECORD(NextEntry,
3541 InLoadOrderLinks);
3542
3543 /* Check if the address matches */
3544 if ((Address >= LdrEntry->DllBase) &&
3545 (Address < (PVOID)((ULONG_PTR)LdrEntry->DllBase +
3546 LdrEntry->SizeOfImage)))
3547 {
3548 /* Found a match */
3549 FoundEntry = LdrEntry;
3550 break;
3551 }
3552
3553 /* Move on */
3554 NextEntry = NextEntry->Flink;
3555 } while(NextEntry != &PsLoadedModuleList);
3556
3557 /* Return the entry */
3558 return FoundEntry;
3559}
Definition: btrfs_drv.h:1876
ULONG SizeOfImage
Definition: ldrtypes.h:147
PVOID DllBase
Definition: btrfs_drv.h:1880
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
LIST_ENTRY PsLoadedModuleList
Definition: sysldr.c:21
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260

Referenced by ExAllocatePool(), MmAddVerifierThunks(), and MmPageEntireDriver().

◆ MiMakePdeExistAndMakeValid()

VOID NTAPI MiMakePdeExistAndMakeValid ( IN PMMPDE  PointerPde,
IN PEPROCESS  TargetProcess,
IN KIRQL  OldIrql 
)

Definition at line 2481 of file virtual.c.

2484{
2485 PMMPTE PointerPte;
2486#if _MI_PAGING_LEVELS >= 3
2487 PMMPPE PointerPpe = MiPdeToPpe(PointerPde);
2488#if _MI_PAGING_LEVELS == 4
2489 PMMPXE PointerPxe = MiPdeToPxe(PointerPde);
2490#endif
2491#endif
2492
2493 //
2494 // Sanity checks. The latter is because we only use this function with the
2495 // PFN lock not held, so it may go away in the future.
2496 //
2499
2500 //
2501 // If everything is already valid, there is nothing to do.
2502 //
2503 if (
2504#if _MI_PAGING_LEVELS == 4
2505 (PointerPxe->u.Hard.Valid) &&
2506#endif
2507#if _MI_PAGING_LEVELS >= 3
2508 (PointerPpe->u.Hard.Valid) &&
2509#endif
2510 (PointerPde->u.Hard.Valid))
2511 {
2512 return;
2513 }
2514
2515 //
2516 // At least something is invalid, so begin by getting the PTE for the PDE itself
2517 // and then lookup each additional level. We must do it in this precise order
2518 // because the pagfault.c code (as well as in Windows) depends that the next
2519 // level up (higher) must be valid when faulting a lower level
2520 //
2521 PointerPte = MiPteToAddress(PointerPde);
2522 do
2523 {
2524 //
2525 // Make sure APCs continued to be disabled
2526 //
2528
2529#if _MI_PAGING_LEVELS == 4
2530 //
2531 // First, make the PXE valid if needed
2532 //
2533 if (!PointerPxe->u.Hard.Valid)
2534 {
2535 MiMakeSystemAddressValid(PointerPpe, TargetProcess);
2536 ASSERT(PointerPxe->u.Hard.Valid == 1);
2537 }
2538#endif
2539
2540#if _MI_PAGING_LEVELS >= 3
2541 //
2542 // Next, the PPE
2543 //
2544 if (!PointerPpe->u.Hard.Valid)
2545 {
2546 MiMakeSystemAddressValid(PointerPde, TargetProcess);
2547 ASSERT(PointerPpe->u.Hard.Valid == 1);
2548 }
2549#endif
2550
2551 //
2552 // And finally, make the PDE itself valid.
2553 //
2554 MiMakeSystemAddressValid(PointerPte, TargetProcess);
2555
2556 /* Do not increment Page table refcount here for the PDE, this must be managed by caller */
2557
2558 //
2559 // This should've worked the first time so the loop is really just for
2560 // show -- ASSERT that we're actually NOT going to be looping.
2561 //
2562 ASSERT(PointerPde->u.Hard.Valid == 1);
2563 } while (
2564#if _MI_PAGING_LEVELS == 4
2565 !PointerPxe->u.Hard.Valid ||
2566#endif
2567#if _MI_PAGING_LEVELS >= 3
2568 !PointerPpe->u.Hard.Valid ||
2569#endif
2570 !PointerPde->u.Hard.Valid);
2571}
#define MM_NOIRQL
Definition: mm.h:70

Referenced by _Success_(), MiDecommitPages(), MiMapLockedPagesInUserSpace(), MiProtectVirtualMemory(), MmCreatePageFileMapping(), MmCreateVirtualMappingUnsafeEx(), MmDeletePageFileMapping(), MmGetPageFileMapping(), MmGetPageProtect(), MmGetPfnForProcess(), MmIsDisabledPage(), MmIsPagePresent(), MmIsPageSwapEntry(), MmSetDirtyBit(), MmSetPageProtect(), and NtAllocateVirtualMemory().

◆ MiMakeProtectionMask()

ULONG NTAPI MiMakeProtectionMask ( IN ULONG  Protect)

Definition at line 140 of file section.c.

141{
142 ULONG Mask1, Mask2, ProtectMask;
143
144 /* PAGE_EXECUTE_WRITECOMBINE is theoretically the maximum */
146
147 /*
148 * Windows API protection mask can be understood as two bitfields, differing
149 * by whether or not execute rights are being requested
150 */
151 Mask1 = Protect & 0xF;
152 Mask2 = (Protect >> 4) & 0xF;
153
154 /* Check which field is there */
155 if (!Mask1)
156 {
157 /* Mask2 must be there, use it to determine the PTE protection */
158 if (!Mask2) return MM_INVALID_PROTECTION;
159 ProtectMask = MmUserProtectionToMask2[Mask2];
160 }
161 else
162 {
163 /* Mask2 should not be there, use Mask1 to determine the PTE mask */
164 if (Mask2) return MM_INVALID_PROTECTION;
165 ProtectMask = MmUserProtectionToMask1[Mask1];
166 }
167
168 /* Make sure the final mask is a valid one */
169 if (ProtectMask == MM_INVALID_PROTECTION) return MM_INVALID_PROTECTION;
170
171 /* Check for PAGE_GUARD option */
172 if (Protect & PAGE_GUARD)
173 {
174 /* It's not valid on no-access, nocache, or writecombine pages */
175 if ((ProtectMask == MM_NOACCESS) ||
177 {
178 /* Fail such requests */
180 }
181
182 /* This actually turns on guard page in this scenario! */
183 ProtectMask |= MM_GUARDPAGE;
184 }
185
186 /* Check for nocache option */
187 if (Protect & PAGE_NOCACHE)
188 {
189 /* The earlier check should've eliminated this possibility */
190 ASSERT((Protect & PAGE_GUARD) == 0);
191
192 /* Check for no-access page or write combine page */
193 if ((ProtectMask == MM_NOACCESS) || (Protect & PAGE_WRITECOMBINE))
194 {
195 /* Such a request is invalid */
197 }
198
199 /* Add the PTE flag */
200 ProtectMask |= MM_NOCACHE;
201 }
202
203 /* Check for write combine option */
205 {
206 /* The two earlier scenarios should've caught this */
208
209 /* Don't allow on no-access pages */
210 if (ProtectMask == MM_NOACCESS) return MM_INVALID_PROTECTION;
211
212 /* This actually turns on write-combine in this scenario! */
213 ProtectMask |= MM_NOACCESS;
214 }
215
216 /* Return the final MM PTE protection mask */
217 return ProtectMask;
218}
CHAR MmUserProtectionToMask1[16]
Definition: section.c:44
CHAR MmUserProtectionToMask2[16]
Definition: section.c:64
#define MM_NOCACHE
Definition: miarm.h:56
#define MM_INVALID_PROTECTION
Definition: miarm.h:67
#define MM_NOACCESS
Definition: miarm.h:65
#define PAGE_NOCACHE
Definition: nt_native.h:1311
#define PAGE_NOACCESS
Definition: nt_native.h:1302
#define PAGE_GUARD
Definition: nt_native.h:1310
#define PAGE_WRITECOMBINE
Definition: mmtypes.h:78

Referenced by MiProtectVirtualMemory(), MmCreateVirtualMappingUnsafeEx(), MmSetPageProtect(), and NtAllocateVirtualMemory().

◆ MiMakeSystemAddressValid()

ULONG NTAPI MiMakeSystemAddressValid ( IN PVOID  PageTableVirtualAddress,
IN PEPROCESS  CurrentProcess 
)

Definition at line 183 of file virtual.c.

185{
187 BOOLEAN WsShared = FALSE, WsSafe = FALSE, LockChange = FALSE;
188 PETHREAD CurrentThread = PsGetCurrentThread();
189
190 /* Must be a non-pool page table, since those are double-mapped already */
191 ASSERT(PageTableVirtualAddress > MM_HIGHEST_USER_ADDRESS);
192 ASSERT((PageTableVirtualAddress < MmPagedPoolStart) ||
193 (PageTableVirtualAddress > MmPagedPoolEnd));
194
195 /* Working set lock or PFN lock should be held */
197
198 /* Check if the page table is valid */
199 while (!MmIsAddressValid(PageTableVirtualAddress))
200 {
201 /* Release the working set lock */
203 CurrentThread,
204 &WsSafe,
205 &WsShared);
206
207 /* Fault it in */
208 Status = MmAccessFault(FALSE, PageTableVirtualAddress, KernelMode, NULL);
209 if (!NT_SUCCESS(Status))
210 {
211 /* This should not fail */
212 KeBugCheckEx(KERNEL_DATA_INPAGE_ERROR,
213 1,
214 Status,
215 (ULONG_PTR)CurrentProcess,
216 (ULONG_PTR)PageTableVirtualAddress);
217 }
218
219 /* Lock the working set again */
220 MiLockProcessWorkingSetForFault(CurrentProcess,
221 CurrentThread,
222 WsSafe,
223 WsShared);
224
225 /* This flag will be useful later when we do better locking */
226 LockChange = TRUE;
227 }
228
229 /* Let caller know what the lock state is */
230 return LockChange;
231}
#define MM_HIGHEST_USER_ADDRESS
Definition: armddk.h:17
BOOLEAN NTAPI MmIsAddressValid(IN PVOID VirtualAddress)
Definition: mmsup.c:174
#define KernelMode
Definition: asm.h:38
NTSTATUS NTAPI MmAccessFault(IN ULONG FaultCode, IN PVOID Address, IN KPROCESSOR_MODE Mode, IN PVOID TrapInformation)
Definition: mmfault.c:218

Referenced by MiCalculatePageCommitment(), MiDeleteVirtualAddresses(), MiIsEntireRangeCommitted(), MiIsPageTablePresent(), MiMakePdeExistAndMakeValid(), and MiQueryAddressState().

◆ MiMakeSystemAddressValidPfn()

ULONG NTAPI MiMakeSystemAddressValidPfn ( IN PVOID  VirtualAddress,
IN KIRQL  OldIrql 
)

Definition at line 235 of file virtual.c.

237{
239 BOOLEAN LockChange = FALSE;
240
241 /* Must be e kernel address */
243
244 /* Check if the page is valid */
246 {
247 /* Release the PFN database */
248 MiReleasePfnLock(OldIrql);
249
250 /* Fault it in */
252 if (!NT_SUCCESS(Status))
253 {
254 /* This should not fail */
255 KeBugCheckEx(KERNEL_DATA_INPAGE_ERROR,
256 3,
257 Status,
258 0,
260 }
261
262 /* This flag will be useful later when we do better locking */
263 LockChange = TRUE;
264
265 /* Lock the PFN database */
266 OldIrql = MiAcquirePfnLock();
267 }
268
269 /* Let caller know what the lock state is */
270 return LockChange;
271}

Referenced by MiGetPageProtection(), and MiSegmentDelete().

◆ MiMapPfnDatabase()

VOID NTAPI MiMapPfnDatabase ( IN PLOADER_PARAMETER_BLOCK  LoaderBlock)

Definition at line 663 of file mminit.c.

664{
665 PFN_NUMBER FreePage, FreePageCount, PagesLeft, BasePage, PageCount;
666 PLIST_ENTRY NextEntry;
668 PMMPTE PointerPte, LastPte;
670
671 /* Get current page data, since we won't be using MxGetNextPage as it would corrupt our state */
673 FreePageCount = MxFreeDescriptor->PageCount;
674 PagesLeft = 0;
675
676 /* Loop the memory descriptors */
677 NextEntry = LoaderBlock->MemoryDescriptorListHead.Flink;
678 while (NextEntry != &LoaderBlock->MemoryDescriptorListHead)
679 {
680 /* Get the descriptor */
681 MdBlock = CONTAINING_RECORD(NextEntry,
683 ListEntry);
684 if ((MdBlock->MemoryType == LoaderFirmwarePermanent) ||
685 (MdBlock->MemoryType == LoaderBBTMemory) ||
686 (MdBlock->MemoryType == LoaderSpecialMemory))
687 {
688 /* These pages are not part of the PFN database */
689 NextEntry = MdBlock->ListEntry.Flink;
690 continue;
691 }
692
693 /* Next, check if this is our special free descriptor we've found */
694 if (MdBlock == MxFreeDescriptor)
695 {
696 /* Use the real numbers instead */
697 BasePage = MxOldFreeDescriptor.BasePage;
698 PageCount = MxOldFreeDescriptor.PageCount;
699 }
700 else
701 {
702 /* Use the descriptor's numbers */
703 BasePage = MdBlock->BasePage;
704 PageCount = MdBlock->PageCount;
705 }
706
707 /* Get the PTEs for this range */
708 PointerPte = MiAddressToPte(&MmPfnDatabase[BasePage]);
709 LastPte = MiAddressToPte(((ULONG_PTR)&MmPfnDatabase[BasePage + PageCount]) - 1);
710 DPRINT("MD Type: %lx Base: %lx Count: %lx\n", MdBlock->MemoryType, BasePage, PageCount);
711
712 /* Loop them */
713 while (PointerPte <= LastPte)
714 {
715 /* We'll only touch PTEs that aren't already valid */
716 if (PointerPte->u.Hard.Valid == 0)
717 {
718 /* Use the next free page */
720 ASSERT(FreePageCount != 0);
721
722 /* Consume free pages */
723 FreePage++;
724 FreePageCount--;
725 if (!FreePageCount)
726 {
727 /* Out of memory */
728 KeBugCheckEx(INSTALL_MORE_MEMORY,
730 FreePageCount,
732 1);
733 }
734
735 /* Write out this PTE */
736 PagesLeft++;
737 MI_WRITE_VALID_PTE(PointerPte, TempPte);
738
739 /* Zero this page */
741 }
742
743 /* Next! */
744 PointerPte++;
745 }
746
747 /* Do the next address range */
748 NextEntry = MdBlock->ListEntry.Flink;
749 }
750
751 /* Now update the free descriptors to consume the pages we used up during the PFN allocation loop */
753 MxFreeDescriptor->PageCount = FreePageCount;
754}
PMEMORY_ALLOCATION_DESCRIPTOR MxFreeDescriptor
Definition: mminit.c:272
MEMORY_ALLOCATION_DESCRIPTOR MxOldFreeDescriptor
Definition: mminit.c:273
TYPE_OF_MEMORY MemoryType
Definition: arc.h:240
@ FreePage
Definition: ketypes.h:416

Referenced by MiInitMachineDependent().

◆ MiPagesInLoaderBlock()

PFN_NUMBER NTAPI MiPagesInLoaderBlock ( IN PLOADER_PARAMETER_BLOCK  LoaderBlock,
IN PBOOLEAN  IncludeType 
)

◆ MiQueryMemorySectionName()

NTSTATUS NTAPI MiQueryMemorySectionName ( IN HANDLE  ProcessHandle,
IN PVOID  BaseAddress,
OUT PVOID  MemoryInformation,
IN SIZE_T  MemoryInformationLength,
OUT PSIZE_T  ReturnLength 
)

Definition at line 1752 of file section.c.

1757{
1761 PMEMORY_SECTION_NAME SectionName = NULL;
1763
1766 NULL,
1768 (PVOID*)(&Process),
1769 NULL);
1770
1771 if (!NT_SUCCESS(Status))
1772 {
1773 DPRINT("MiQueryMemorySectionName: ObReferenceObjectByHandle returned %x\n",Status);
1774 return Status;
1775 }
1776
1778
1779 if (NT_SUCCESS(Status))
1780 {
1781 SectionName = MemoryInformation;
1782 if (PreviousMode != KernelMode)
1783 {
1784 _SEH2_TRY
1785 {
1786 RtlInitEmptyUnicodeString(&SectionName->SectionFileName,
1787 (PWSTR)(SectionName + 1),
1788 MemoryInformationLength - sizeof(MEMORY_SECTION_NAME));
1790
1792
1793 }
1795 {
1797 }
1798 _SEH2_END;
1799 }
1800 else
1801 {
1802 RtlInitEmptyUnicodeString(&SectionName->SectionFileName,
1803 (PWSTR)(SectionName + 1),
1804 MemoryInformationLength - sizeof(MEMORY_SECTION_NAME));
1806
1808
1809 }
1810
1812 }
1814 return Status;
1815}
NTSTATUS NTAPI MmGetFileNameForAddress(IN PVOID Address, OUT PUNICODE_STRING ModuleName)
Definition: section.c:1689
_In_ PVOID _In_ ULONG _Out_ PVOID _In_ ULONG _Inout_ PULONG ReturnLength
_In_ PVOID _In_ ULONG _Out_ PVOID _In_ ULONG _Inout_ PULONG _In_ KPROCESSOR_MODE PreviousMode
#define ExGetPreviousMode
Definition: ex.h:143
#define PROCESS_QUERY_INFORMATION
Definition: pstypes.h:167
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:90
_In_ HANDLE ProcessHandle
Definition: mmfuncs.h:403
NTSYSAPI VOID NTAPI RtlCopyUnicodeString(PUNICODE_STRING DestinationString, PUNICODE_STRING SourceString)
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
NTSTATUS NTAPI ObReferenceObjectByHandle(IN HANDLE Handle, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PVOID *Object, OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
Definition: obref.c:494
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:181
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:82
#define _SEH2_END
Definition: pseh2_64.h:171
#define _SEH2_TRY
Definition: pseh2_64.h:71
TCHAR ModuleFileName[MAX_PATH+1]
Definition: rundll32.c:56
UNICODE_STRING SectionFileName
Definition: mmtypes.h:326
uint16_t * PWSTR
Definition: typedefs.h:56
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
#define ObDereferenceObject
Definition: obfuncs.h:203

Referenced by NtQueryVirtualMemory().

◆ MiReferenceProbedPageAndBumpLockCount()

FORCEINLINE VOID MiReferenceProbedPageAndBumpLockCount ( IN PMMPFN  Pfn1)

Definition at line 1700 of file miarm.h.

1701{
1702 USHORT RefCount, OldRefCount;
1703
1704 /* Sanity check */
1705 ASSERT(Pfn1->u3.e2.ReferenceCount != 0);
1706
1707 /* Does ARM3 own the page? */
1708 if (MI_IS_ROS_PFN(Pfn1))
1709 {
1710 /* ReactOS Mm doesn't track share count */
1711 ASSERT(Pfn1->u3.e1.PageLocation == ActiveAndValid);
1712 }
1713 else
1714 {
1715 /* On ARM3 pages, we should see a valid share count */
1716 ASSERT((Pfn1->u2.ShareCount != 0) && (Pfn1->u3.e1.PageLocation == ActiveAndValid));
1717
1718 /* Is it a prototype PTE? */
1719 if ((Pfn1->u3.e1.PrototypePte == 1) &&
1720 (Pfn1->OriginalPte.u.Soft.Prototype == 1))
1721 {
1722 /* FIXME: We should charge commit */
1723 DPRINT1("Not charging commit for prototype PTE\n");
1724 }
1725 }
1726
1727 /* More locked pages! */
1729
1730 /* Loop trying to update the reference count */
1731 do
1732 {
1733 /* Get the current reference count, make sure it's valid */
1734 OldRefCount = Pfn1->u3.e2.ReferenceCount;
1735 ASSERT(OldRefCount != 0);
1736 ASSERT(OldRefCount < 2500);
1737
1738 /* Bump it up by one */
1739 RefCount = InterlockedCompareExchange16((PSHORT)&Pfn1->u3.e2.ReferenceCount,
1740 OldRefCount + 1,
1741 OldRefCount);
1742 ASSERT(RefCount != 0);
1743 } while (OldRefCount != RefCount);
1744
1745 /* Was this the first lock attempt? If not, undo our bump */
1746 if (OldRefCount != 1) InterlockedDecrementSizeT(&MmSystemLockPagesCount);
1747}

Referenced by MI_LOCK_VA(), and MmProbeAndLockPages().

◆ MiReferenceUnusedPageAndBumpLockCount()

FORCEINLINE VOID MiReferenceUnusedPageAndBumpLockCount ( IN PMMPFN  Pfn1)

Definition at line 1800 of file miarm.h.

1801{
1802 USHORT NewRefCount;
1803
1804 /* Make sure the page isn't used yet */
1805 ASSERT(Pfn1->u2.ShareCount == 0);
1806 ASSERT(Pfn1->u3.e1.PageLocation != ActiveAndValid);
1807
1808 /* Is it a prototype PTE? */
1809 if ((Pfn1->u3.e1.PrototypePte == 1) &&
1810 (Pfn1->OriginalPte.u.Soft.Prototype == 1))
1811 {
1812 /* FIXME: We should charge commit */
1813 DPRINT1("Not charging commit for prototype PTE\n");
1814 }
1815
1816 /* More locked pages! */
1818
1819 /* Update the reference count */
1820 NewRefCount = InterlockedIncrement16((PSHORT)&Pfn1->u3.e2.ReferenceCount);
1821 if (NewRefCount != 1)
1822 {
1823 /* Someone had already locked the page, so undo our bump */
1824 ASSERT(NewRefCount < 2500);
1826 }
1827}
#define InterlockedIncrement16
Definition: interlocked.h:206

Referenced by MiResolveTransitionFault().

◆ MiReferenceUsedPageAndBumpLockCount()

FORCEINLINE VOID MiReferenceUsedPageAndBumpLockCount ( IN PMMPFN  Pfn1)

Definition at line 1755 of file miarm.h.

1756{
1757 USHORT NewRefCount;
1758
1759 /* Is it a prototype PTE? */
1760 if ((Pfn1->u3.e1.PrototypePte == 1) &&
1761 (Pfn1->OriginalPte.u.Soft.Prototype == 1))
1762 {
1763 /* FIXME: We should charge commit */
1764 DPRINT1("Not charging commit for prototype PTE\n");
1765 }
1766
1767 /* More locked pages! */
1769
1770 /* Update the reference count */
1771 NewRefCount = InterlockedIncrement16((PSHORT)&Pfn1->u3.e2.ReferenceCount);
1772 if (NewRefCount == 2)
1773 {
1774 /* Is it locked or shared? */
1775 if (Pfn1->u2.ShareCount)
1776 {
1777 /* It's shared, so make sure it's active */
1778 ASSERT(Pfn1->u3.e1.PageLocation == ActiveAndValid);
1779 }
1780 else
1781 {
1782 /* It's locked, so we shouldn't lock again */
1784 }
1785 }
1786 else
1787 {
1788 /* Someone had already locked the page, so undo our bump */
1789 ASSERT(NewRefCount < 2500);
1791 }
1792}

Referenced by MiDispatchFault().

◆ MiReleaseExpansionLock()

◆ MiReleaseProcessReferenceToSessionDataPage()

VOID NTAPI MiReleaseProcessReferenceToSessionDataPage ( IN PMM_SESSION_SPACE  SessionGlobal)

Definition at line 209 of file session.c.

210{
212 PMMPTE PointerPte;
214 PMMPFN Pfn1;
216
217 /* Is there more than just this reference? If so, bail out */
218 if (InterlockedDecrement(&SessionGlobal->ProcessReferenceToSession)) return;
219
220 /* Get the session ID */
221 SessionId = SessionGlobal->SessionId;
222 DPRINT1("Last process in session %lu going down!!!\n", SessionId);
223
224 /* Free the session page tables */
225#ifndef _M_AMD64
226 ExFreePoolWithTag(SessionGlobal->PageTables, 'tHmM');
227#endif
228 ASSERT(!MI_IS_PHYSICAL_ADDRESS(SessionGlobal));
229
230 /* Capture the data page PFNs */
231 PointerPte = MiAddressToPte(SessionGlobal);
232 for (i = 0; i < MiSessionDataPages; i++)
233 {
234 PageFrameIndex[i] = PFN_FROM_PTE(PointerPte + i);
235 }
236
237 /* Release them */
239
240 /* Mark them as deleted */
241 for (i = 0; i < MiSessionDataPages; i++)
242 {
243 Pfn1 = MI_PFN_ELEMENT(PageFrameIndex[i]);
244 MI_SET_PFN_DELETED(Pfn1);
245 }
246
247 /* Loop every data page and drop a reference count */
248 OldIrql = MiAcquirePfnLock();
249 for (i = 0; i < MiSessionDataPages; i++)
250 {
251 /* Sanity check that the page is correct, then decrement it */
252 Pfn1 = MI_PFN_ELEMENT(PageFrameIndex[i]);
253 ASSERT(Pfn1->u2.ShareCount == 1);
254 ASSERT(Pfn1->u3.e2.ReferenceCount == 1);
255 MiDecrementShareCount(Pfn1, PageFrameIndex[i]);
256 }
257
258 /* Done playing with pages, release the lock */
259 MiReleasePfnLock(OldIrql);
260
261 /* Decrement the number of data pages */
263
264 /* Free this session ID from the session bitmap */
269}
#define InterlockedDecrement
Definition: armddk.h:52
#define RtlClearBit
Definition: dbgbitmap.h:330
#define RtlCheckBit
Definition: dbgbitmap.h:349
ULONG SessionId
Definition: dllmain.c:28
FORCEINLINE BOOLEAN MI_IS_PHYSICAL_ADDRESS(IN PVOID Address)
Definition: miarm.h:959
VOID NTAPI MiReleaseSystemPtes(IN PMMPTE StartingPte, IN ULONG NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType)
Definition: syspte.c:264
LONG MmSessionDataPages
Definition: session.c:25

Referenced by MiDereferenceSession(), and MmDeleteProcessAddressSpace().

◆ MiReleaseSystemPtes()

VOID NTAPI MiReleaseSystemPtes ( IN PMMPTE  StartingPte,
IN ULONG  NumberOfPtes,
IN MMSYSTEM_PTE_POOL_TYPE  SystemPtePoolType 
)

Definition at line 264 of file syspte.c.

267{
270 PMMPTE PreviousPte, NextPte, InsertPte;
271
272 //
273 // Check to make sure the PTE address is within bounds
274 //
275 ASSERT(NumberOfPtes != 0);
276 ASSERT(StartingPte >= MmSystemPtesStart[SystemPtePoolType]);
277 ASSERT(StartingPte + NumberOfPtes - 1 <= MmSystemPtesEnd[SystemPtePoolType]);
278
279 //
280 // Zero PTEs
281 //
282 RtlZeroMemory(StartingPte, NumberOfPtes * sizeof(MMPTE));
283
284 //
285 // Acquire the System PTE lock
286 //
288
289 //
290 // Increase availability
291 //
292 MmTotalFreeSystemPtes[SystemPtePoolType] += NumberOfPtes;
293
294 //
295 // Step through the cluster list to find where to insert the PTEs
296 //
297 PreviousPte = &MmFirstFreeSystemPte[SystemPtePoolType];
298 InsertPte = NULL;
299
300 while (PreviousPte->u.List.NextEntry != MM_EMPTY_PTE_LIST)
301 {
302 //
303 // Get the next cluster and its size
304 //
305 NextPte = MmSystemPteBase + PreviousPte->u.List.NextEntry;
307
308 //
309 // Check if this cluster is adjacent to the PTEs being released
310 //
311 if ((NextPte + ClusterSize == StartingPte) ||
312 (StartingPte + NumberOfPtes == NextPte))
313 {
314 //
315 // Add the PTEs in the cluster to the PTEs being released
316 //
317 NumberOfPtes += ClusterSize;
318
319 if (NextPte < StartingPte)
320 StartingPte = NextPte;
321
322 //
323 // Unlink this cluster and zero it
324 //
325 PreviousPte->u.List.NextEntry = NextPte->u.List.NextEntry;
326
327 if (NextPte->u.List.OneEntry == 0)
328 {
329 NextPte->u.Long = 0;
330 NextPte++;
331 }
332 NextPte->u.Long = 0;
333
334 //
335 // Invalidate the previously found insertion location, if any
336 //
337 InsertPte = NULL;
338 }
339 else
340 {
341 //
342 // Check if the insertion location is right before this cluster
343 //
344 if ((InsertPte == NULL) && (NumberOfPtes <= ClusterSize))
345 InsertPte = PreviousPte;
346
347 //
348 // On to the next cluster
349 //
350 PreviousPte = NextPte;
351 }
352 }
353
354 //
355 // If no insertion location was found, use the tail of the list
356 //
357 if (InsertPte == NULL)
358 InsertPte = PreviousPte;
359
360 //
361 // Create a new cluster using the PTEs being released
362 //
363 if (NumberOfPtes != 1)
364 {
365 StartingPte->u.List.OneEntry = 0;
366
367 NextPte = StartingPte + 1;
368 NextPte->u.List.NextEntry = NumberOfPtes;
369 }
370 else
371 StartingPte->u.List.OneEntry = 1;
372
373 //
374 // Link the new cluster into the cluster list at the insertion location
375 //
376 StartingPte->u.List.NextEntry = InsertPte->u.List.NextEntry;
377 InsertPte->u.List.NextEntry = StartingPte - MmSystemPteBase;
378
379 //
380 // Release the System PTE lock
381 //
383}
DWORD ClusterSize
Definition: format.c:67
ULONG64 OneEntry
Definition: mmtypes.h:139
FORCEINLINE ULONG MI_GET_CLUSTER_SIZE(IN PMMPTE Pte)
Definition: syspte.c:71
@ LockQueueSystemSpaceLock
Definition: ketypes.h:661

Referenced by MiAllocatePoolPages(), MiArchCreateProcessAddressSpace(), MiCopyPfn(), MiReleaseProcessReferenceToSessionDataPage(), MiZeroPfn(), MmDeleteKernelStack(), MmFreeNonCachedMemory(), MmUnmapIoSpace(), and MmUnmapLockedPages().

◆ MiRemoveAnyPage()

PFN_NUMBER NTAPI MiRemoveAnyPage ( IN ULONG  Color)

Definition at line 477 of file pfnlist.c.

478{
479 PFN_NUMBER PageIndex;
480 PMMPFN Pfn1;
481
482 /* Make sure PFN lock is held and we have pages */
485 if (MmAvailablePages == 0)
486 {
487 return 0;
488 }
489
490 /* Check the colored free list */
492 if (PageIndex == LIST_HEAD)
493 {
494 /* Check the colored zero list */
496 if (PageIndex == LIST_HEAD)
497 {
498 /* Check the free list */
500 PageIndex = MmFreePageListHead.Flink;
501 Color = PageIndex & MmSecondaryColorMask;
502 if (PageIndex == LIST_HEAD)
503 {
504 /* Check the zero list */
506 PageIndex = MmZeroedPageListHead.Flink;
507 Color = PageIndex & MmSecondaryColorMask;
508 ASSERT(PageIndex != LIST_HEAD);
509 if (PageIndex == LIST_HEAD)
510 {
511 /* FIXME: Should check the standby list */
513 }
514 }
515 }
516 }
517
518 /* Remove the page from its list */
519 PageIndex = MiRemovePageByColor(PageIndex, Color);
520 ASSERT(PageIndex != 0);
521
522 /* Sanity checks */
523 Pfn1 = MI_PFN_ELEMENT(PageIndex);
524 ASSERT((Pfn1->u3.e1.PageLocation == FreePageList) ||
525 (Pfn1->u3.e1.PageLocation == ZeroedPageList));
526 ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
527 ASSERT(Pfn1->u2.ShareCount == 0);
530
531 /* Return the page */
532 return PageIndex;
533}
ULONG MmSecondaryColors
Definition: mminit.c:256
PFN_NUMBER NTAPI MiRemovePageByColor(IN PFN_NUMBER PageIndex, IN ULONG Color)
Definition: pfnlist.c:364
MMPFNLIST MmZeroedPageListHead
Definition: pfnlist.c:41

Referenced by GetFreeWsleIndex(), MiAllocatePagesForMdl(), MiAllocatePoolPages(), MiArchCreateProcessAddressSpace(), MiInitMachineDependent(), MiLoadImageSection(), MiResolveDemandZeroFault(), MiResolvePageFileFault(), MiResolveProtoPteFault(), MiSessionCreateInternal(), MiSessionInitializeWorkingSetList(), MmAllocateSpecialPool(), MmArmAccessFault(), MmCreateKernelStack(), MmCreateProcessAddressSpace(), MmGrowKernelStackEx(), and MmZeroPageThread().

◆ MiRemoveMappedView()

VOID NTAPI MiRemoveMappedView ( IN PEPROCESS  CurrentProcess,
IN PMMVAD  Vad 
)

Definition at line 766 of file section.c.

768{
770 PCONTROL_AREA ControlArea;
771 PETHREAD CurrentThread = PsGetCurrentThread();
772
773 /* Get the control area */
774 ControlArea = Vad->ControlArea;
775
776 /* We only support non-extendable, non-image, pagefile-backed regular sections */
777 ASSERT(Vad->u.VadFlags.VadType == VadNone);
778 ASSERT(Vad->u2.VadFlags2.ExtendableFile == FALSE);
779 ASSERT(ControlArea);
780 ASSERT(ControlArea->FilePointer == NULL);
781
782 /* Delete the actual virtual memory pages */
783 MiDeleteVirtualAddresses(Vad->StartingVpn << PAGE_SHIFT,
784 (Vad->EndingVpn << PAGE_SHIFT) | (PAGE_SIZE - 1),
785 Vad);
786
787 /* Release the working set */
788 MiUnlockProcessWorkingSetUnsafe(CurrentProcess, CurrentThread);
789
790 /* Lock the PFN database */
791 OldIrql = MiAcquirePfnLock();
792
793 /* Remove references */
794 ControlArea->NumberOfMappedViews--;
795 ControlArea->NumberOfUserReferences--;
796
797 /* Check if it should be destroyed */
798 MiCheckControlArea(ControlArea, OldIrql);
799}
VOID NTAPI MiDeleteVirtualAddresses(IN ULONG_PTR Va, IN ULONG_PTR EndingAddress, IN PMMVAD Vad)
Definition: virtual.c:530
@ VadNone
Definition: mmtypes.h:204
ULONG NumberOfMappedViews
Definition: mmtypes.h:525
PFILE_OBJECT FilePointer
Definition: mmtypes.h:533

Referenced by MiUnmapViewOfSection(), and MmCleanProcessAddressSpace().

◆ MiRemoveNode()

VOID NTAPI MiRemoveNode ( IN PMMADDRESS_NODE  Node,
IN PMM_AVL_TABLE  Table 
)

Definition at line 440 of file vadnode.c.

442{
443 PMMVAD_LONG Vad;
444
446
447 /* Call the AVL code */
449
450 /* Decrease element count */
451 Table->NumberGenericTableElements--;
452
453 /* Check if this node was the hint */
454 if (Table->NodeHint == Node)
455 {
456 /* Get a new hint, unless we're empty now, in which case nothing */
457 if (!Table->NumberGenericTableElements) Table->NodeHint = NULL;
458 else Table->NodeHint = Table->BalancedRoot.RightChild;
459 }
460
461 /* Free the node from ReactOS view as well */
462 Vad = (PMMVAD_LONG)Node;
463 if ((Table != &MmSectionBasedRoot) && (Vad->u.VadFlags.Spare == 0))
464 {
467
468 /* Check if this is VM VAD */
469 if (Vad->ControlArea == NULL)
470 {
471 /* We store the ReactOS MEMORY_AREA here */
473 }
474 else
475 {
476 /* This is a section VAD. We store the ReactOS MEMORY_AREA here */
478 }
479
480 /* Make sure one actually still exists */
481 if (MemoryArea)
482 {
483 /* Make sure we have not already freed it */
484 ASSERT(MemoryArea != (PVOID)(ULONG_PTR)0xDEADBAB1DEADBAB1ULL);
485
486 /* Get the process */
488
489 /* We only create fake memory-areas for ARM3 VADs */
492
493 /* Free it */
495
496 /* Check if this is VM VAD */
497 if (Vad->ControlArea == NULL)
498 {
499 /* Delete the pointer to it */
500 Vad->FirstPrototypePte = (PVOID)(ULONG_PTR)0xDEADBAB1DEADBAB1ULL;
501 }
502 else
503 {
504 /* Delete the pointer to it */
505 Vad->u4.Banked = (PVOID)(ULONG_PTR)0xDEADBAB1DEADBAB1ULL;
506 }
507 }
508 }
509}
#define RtlpDeleteAvlTreeNode
Definition: miavl.h:36
_In_ PMEMORY_AREA MemoryArea
Definition: newmm.h:207
NTSTATUS NTAPI MmFreeMemoryArea(PMMSUPPORT AddressSpace, PMEMORY_AREA MemoryArea, PMM_FREE_PAGE_FUNC FreePage, PVOID FreePageContext)
Definition: marea.c:283
#define MEMORY_AREA_OWNED_BY_ARM3
Definition: mm.h:97
struct _MEMORY_AREA * PMEMORY_AREA
PVOID Vad
Definition: mm.h:262
ULONG Type
Definition: mm.h:258
ULONG_PTR Spare
Definition: mmtypes.h:697
PMMPTE FirstPrototypePte
Definition: mmtypes.h:766
PVOID Banked
Definition: mmtypes.h:780
union _MMVAD_LONG::@2706 u
MMVAD_FLAGS VadFlags
Definition: mmtypes.h:763
union _MMVAD_LONG::@2709 u4
PCONTROL_AREA ControlArea
Definition: mmtypes.h:765

Referenced by MiDeleteARM3Section(), MiUnmapLockedPagesInUserSpace(), MiUnmapViewOfSection(), MmCleanProcessAddressSpace(), MmDeleteTeb(), and NtFreeVirtualMemory().

◆ MiRemoveZeroPage()

PFN_NUMBER NTAPI MiRemoveZeroPage ( IN ULONG  Color)

Definition at line 537 of file pfnlist.c.

538{
539 PFN_NUMBER PageIndex;
540 PMMPFN Pfn1;
542
543 /* Make sure PFN lock is held and we have pages */
546 if (MmAvailablePages == 0)
547 {
548 return 0;
549 }
550
551 /* Check the colored zero list */
553 if (PageIndex == LIST_HEAD)
554 {
555 /* Check the zero list */
557 PageIndex = MmZeroedPageListHead.Flink;
558 if (PageIndex == LIST_HEAD)
559 {
560 /* This means there's no zero pages, we have to look for free ones */
562 Zero = TRUE;
563
564 /* Check the colored free list */
566 if (PageIndex == LIST_HEAD)
567 {
568 /* Check the free list */
570 PageIndex = MmFreePageListHead.Flink;
571 Color = PageIndex & MmSecondaryColorMask;
572 ASSERT(PageIndex != LIST_HEAD);
573 if (PageIndex == LIST_HEAD)
574 {
575 /* FIXME: Should check the standby list */
577 }
578 }
579 }
580 else
581 {
582 Color = PageIndex & MmSecondaryColorMask;
583 }
584 }
585
586 /* Sanity checks */
587 Pfn1 = MI_PFN_ELEMENT(PageIndex);
588 ASSERT((Pfn1->u3.e1.PageLocation == FreePageList) ||
589 (Pfn1->u3.e1.PageLocation == ZeroedPageList));
590
591 /* Remove the page from its list */
592 PageIndex = MiRemovePageByColor(PageIndex, Color);
593 ASSERT(PageIndex != 0);
594 ASSERT(Pfn1 == MI_PFN_ELEMENT(PageIndex));
595
596 /* Zero it, if needed */
597 if (Zero) MiZeroPhysicalPage(PageIndex);
598
599 /* Sanity checks */
600 ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
601 ASSERT(Pfn1->u2.ShareCount == 0);
604
605 /* Return the page */
606 return PageIndex;
607}
IN PVCB IN VBO IN ULONG OUT PBCB OUT PVOID IN BOOLEAN IN BOOLEAN Zero
Definition: fatprocs.h:419
VOID NTAPI MiZeroPhysicalPage(IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:122

Referenced by MiBuildPagedPool(), MiFillSystemPageDirectory(), MiInitializeAndChargePfn(), MiRemoveZeroPageSafe(), MiResolveDemandZeroFault(), MiSessionCommitPageTables(), and MmAllocPage().

◆ MiRemoveZeroPageSafe()

FORCEINLINE PFN_NUMBER MiRemoveZeroPageSafe ( IN ULONG  Color)

Definition at line 2413 of file miarm.h.

2414{
2416 return 0;
2417}
PFN_NUMBER NTAPI MiRemoveZeroPage(IN ULONG Color)
Definition: pfnlist.c:537

Referenced by MiArchCreateProcessAddressSpace(), MiResolveDemandZeroFault(), MiSessionCreateInternal(), MiSessionInitializeWorkingSetList(), MmArmAccessFault(), and MmCreateProcessAddressSpace().

◆ MiReserveSystemPtes()

PMMPTE NTAPI MiReserveSystemPtes ( IN ULONG  NumberOfPtes,
IN MMSYSTEM_PTE_POOL_TYPE  SystemPtePoolType 
)

Definition at line 246 of file syspte.c.

248{
249 PMMPTE PointerPte;
250
251 //
252 // Use the extended function
253 //
254 PointerPte = MiReserveAlignedSystemPtes(NumberOfPtes, SystemPtePoolType, 0);
255
256 //
257 // Return the PTE Pointer
258 //
259 return PointerPte;
260}
PMMPTE NTAPI MiReserveAlignedSystemPtes(IN ULONG NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType, IN ULONG Alignment)
Definition: syspte.c:88

Referenced by _IRQL_requires_max_(), MiAllocatePoolPages(), MiArchCreateProcessAddressSpace(), MiBuildPagedPool(), MiBuildSystemPteSpace(), MiCopyPfn(), MiInitializeLargePageSupport(), MiInitMachineDependent(), MiLoadImageSection(), MiReloadBootLoadedDrivers(), MiSessionCreateInternal(), MiZeroPfn(), MmAllocateNonCachedMemory(), MmCreateKernelStack(), MmMapIoSpace(), and MmMapLockedPagesSpecifyCache().

◆ MiRosProtectVirtualMemory()

NTSTATUS NTAPI MiRosProtectVirtualMemory ( IN PEPROCESS  Process,
IN OUT PVOID BaseAddress,
IN OUT PSIZE_T  NumberOfBytesToProtect,
IN ULONG  NewAccessProtection,
OUT PULONG OldAccessProtection  OPTIONAL 
)

Definition at line 2158 of file virtual.c.

2163{
2166 ULONG OldAccessProtection_;
2168
2169 *NumberOfBytesToProtect = PAGE_ROUND_UP((ULONG_PTR)(*BaseAddress) + (*NumberOfBytesToProtect)) - PAGE_ROUND_DOWN(*BaseAddress);
2171
2172 AddressSpace = &Process->Vm;
2176 {
2178 return STATUS_UNSUCCESSFUL;
2179 }
2180
2181 if (OldAccessProtection == NULL) OldAccessProtection = &OldAccessProtection_;
2182
2185 MemoryArea,
2186 *BaseAddress,
2187 *NumberOfBytesToProtect,
2188 NewAccessProtection,
2189 OldAccessProtection);
2190
2192
2193 return Status;
2194}
#define PAGE_ROUND_UP(x)
Definition: mmtypes.h:38
#define PAGE_ROUND_DOWN(x)
Definition: mmtypes.h:36
FORCEINLINE VOID MmLockAddressSpace(PMMSUPPORT AddressSpace)
Definition: mm.h:1703
NTSTATUS NTAPI MmProtectSectionView(PMMSUPPORT AddressSpace, PMEMORY_AREA MemoryArea, PVOID BaseAddress, SIZE_T Length, ULONG Protect, PULONG OldProtect)
Definition: section.c:2068
PMEMORY_AREA NTAPI MmLocateMemoryAreaByAddress(PMMSUPPORT AddressSpace, PVOID Address)
Definition: marea.c:60
FORCEINLINE VOID MmUnlockAddressSpace(PMMSUPPORT AddressSpace)
Definition: mm.h:1716
#define MEMORY_AREA_SECTION_VIEW
Definition: mm.h:93
BOOLEAN DeleteInProgress
Definition: mm.h:260
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
_In_ ULONG _In_ PHYSICAL_ADDRESS _Inout_ PULONG AddressSpace
Definition: iofuncs.h:2274

Referenced by MiProtectVirtualMemory().

◆ MiRosUnmapViewInSystemSpace()

NTSTATUS NTAPI MiRosUnmapViewInSystemSpace ( IN PVOID  MappedBase)

Definition at line 4562 of file section.c.

4563{
4564 DPRINT("MmUnmapViewInSystemSpace() called\n");
4565
4567}
FORCEINLINE PMMSUPPORT MmGetKernelAddressSpace(VOID)
Definition: mm.h:1738
static NTSTATUS MmUnmapViewOfSegment(PMMSUPPORT AddressSpace, PVOID BaseAddress)
Definition: section.c:3530
_Must_inspect_result_ _Outptr_result_bytebuffer_ ViewSize PVOID * MappedBase
Definition: mmfuncs.h:492

Referenced by MmUnmapViewInSystemSpace().

◆ MiRosUnmapViewOfSection()

NTSTATUS NTAPI MiRosUnmapViewOfSection ( IN PEPROCESS  Process,
IN PVOID  BaseAddress,
IN BOOLEAN  SkipDebuggerNotify 
)

Definition at line 3594 of file section.c.

3597{
3601 PVOID ImageBaseAddress = 0;
3602
3603 DPRINT("Opening memory area Process %p BaseAddress %p\n",
3605
3606 ASSERT(Process);
3607
3608 AddressSpace = &Process->Vm;
3609
3611 BaseAddress);
3612 if (MemoryArea == NULL ||
3613#ifdef NEWCC
3614 ((MemoryArea->Type != MEMORY_AREA_SECTION_VIEW) && (MemoryArea->Type != MEMORY_AREA_CACHE)) ||
3615#else
3617#endif
3619
3620 {
3622
3623 DPRINT1("Unable to find memory area at address %p.\n", BaseAddress);
3625 }
3626
3628 {
3629 ULONG i;
3630 ULONG NrSegments;
3631 PMM_IMAGE_SECTION_OBJECT ImageSectionObject;
3632 PMM_SECTION_SEGMENT SectionSegments;
3634
3635 Segment = MemoryArea->SectionData.Segment;
3636 ImageSectionObject = ImageSectionObjectFromSegment(Segment);
3637 SectionSegments = ImageSectionObject->Segments;
3638 NrSegments = ImageSectionObject->NrSegments;
3639
3641
3642 /* Search for the current segment within the section segments
3643 * and calculate the image base address */
3644 for (i = 0; i < NrSegments; i++)
3645 {
3646 if (Segment == &SectionSegments[i])
3647 {
3648 ImageBaseAddress = (char*)BaseAddress - (ULONG_PTR)SectionSegments[i].Image.VirtualAddress;
3649 break;
3650 }
3651 }
3652 if (i >= NrSegments)
3653 {
3654 KeBugCheck(MEMORY_MANAGEMENT);
3655 }
3656
3657 for (i = 0; i < NrSegments; i++)
3658 {
3659 PVOID SBaseAddress = (PVOID)
3660 ((char*)ImageBaseAddress + (ULONG_PTR)SectionSegments[i].Image.VirtualAddress);
3661
3662 Status = MmUnmapViewOfSegment(AddressSpace, SBaseAddress);
3663 if (!NT_SUCCESS(Status))
3664 {
3665 DPRINT1("MmUnmapViewOfSegment failed for %p (Process %p) with %lx\n",
3666 SBaseAddress, Process, Status);
3668 }
3669 }
3670 DPRINT("One mapping less for %p\n", ImageSectionObject->FileObject->SectionObjectPointer);
3671 InterlockedDecrement(&ImageSectionObject->MapCount);
3672 }
3673 else
3674 {
3676 PMMVAD Vad = &MemoryArea->VadNode;
3677 PCONTROL_AREA ControlArea = Vad->ControlArea;
3680 LARGE_INTEGER ViewOffset;
3681 ViewOffset.QuadPart = MemoryArea->SectionData.ViewOffset;
3682
3683 InterlockedIncrement64(Segment->ReferenceCount);
3684
3685 ViewSize = PAGE_SIZE + ((Vad->EndingVpn - Vad->StartingVpn) << PAGE_SHIFT);
3686
3688 if (!NT_SUCCESS(Status))
3689 {
3690 DPRINT1("MmUnmapViewOfSegment failed for %p (Process %p) with %lx\n",
3693 }
3694
3695 /* These might be deleted now */
3696 Vad = NULL;
3697 MemoryArea = NULL;
3698
3700 {
3701 /* Don't bother */
3702 MmDereferenceSegment(Segment);
3703 return STATUS_SUCCESS;
3704 }
3706
3707 FileObject = Segment->FileObject;
3709
3710 /* Don't bother for auto-delete closed file. */
3712 {
3714 MmDereferenceSegment(Segment);
3715 return STATUS_SUCCESS;
3716 }
3717
3718 /*
3719 * Flush only when last mapping is deleted.
3720 * FIXME: Why ControlArea == NULL? Or rather: is ControlArea ever not NULL here?
3721 */
3722 if (ControlArea == NULL || ControlArea->NumberOfMappedViews == 1)
3723 {
3724 while (ViewSize > 0)
3725 {
3726 ULONG FlushSize = min(ViewSize, PAGE_ROUND_DOWN(MAXULONG));
3727 MmFlushSegment(FileObject->SectionObjectPointer,
3728 &ViewOffset,
3729 FlushSize,
3730 NULL);
3731 ViewSize -= FlushSize;
3732 ViewOffset.QuadPart += FlushSize;
3733 }
3734 }
3735
3737 MmDereferenceSegment(Segment);
3738 }
3739
3740 /* Notify debugger */
3741 if (ImageBaseAddress && !SkipDebuggerNotify) DbgkUnMapViewOfSection(ImageBaseAddress);
3742
3743 return STATUS_SUCCESS;
3744}
#define InterlockedIncrement64(a)
Definition: btrfs_drv.h:143
DECLSPEC_NORETURN VOID NTAPI KeBugCheck(ULONG BugCheckCode)
Definition: bug.c:1434
VOID NTAPI DbgkUnMapViewOfSection(IN PVOID BaseAddress)
Definition: dbgkutil.c:436
#define FlagOn(_F, _SF)
Definition: ext2fs.h:179
@ VadImageMap
Definition: mmtypes.h:206
VOID NTAPI FsRtlReleaseFile(IN PFILE_OBJECT FileObject)
Definition: fastio.c:1665
VOID NTAPI FsRtlAcquireFileExclusive(IN PFILE_OBJECT FileObject)
Definition: fastio.c:1640
#define MM_PHYSICALMEMORY_SEGMENT
Definition: mm.h:244
#define MM_DATAFILE_SEGMENT
Definition: mm.h:245
#define STATUS_NOT_MAPPED_VIEW
Definition: ntstatus.h:262
PMM_IMAGE_SECTION_OBJECT ImageSectionObjectFromSegment(PMM_SECTION_SEGMENT Segment)
Definition: section.c:120
NTSTATUS NTAPI MmFlushSegment(_In_ PSECTION_OBJECT_POINTERS SectionObjectPointer, _In_opt_ PLARGE_INTEGER Offset, _In_ ULONG Length, _Out_opt_ PIO_STATUS_BLOCK Iosb)
Definition: section.c:5051
struct _MEMORY_AREA::@1832 SectionData
MMVAD VadNode
Definition: mm.h:256
ULONG_PTR VadType
Definition: mmtypes.h:694
PCONTROL_AREA ControlArea
Definition: mmtypes.h:736
union _MMVAD::@2703 u
MMVAD_FLAGS VadFlags
Definition: mmtypes.h:734
PMM_SECTION_SEGMENT Segments
Definition: mm.h:241
PFILE_OBJECT FileObject
Definition: mm.h:233
struct _MM_SECTION_SEGMENT::@1831 Image
else
Definition: tritemp.h:161
#define MAXULONG
Definition: typedefs.h:251
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550
#define FO_CLEANUP_COMPLETE
Definition: iotypes.h:1790
* PFILE_OBJECT
Definition: iotypes.h:1998
#define FO_DELETE_ON_CLOSE
Definition: iotypes.h:1792

Referenced by MiRosCleanupMemoryArea(), and MiUnmapViewOfSection().

◆ MiSessionAddProcess()

VOID NTAPI MiSessionAddProcess ( IN PEPROCESS  NewProcess)

Definition at line 423 of file session.c.

424{
425 PMM_SESSION_SPACE SessionGlobal;
427
428 /* The current process must already be in a session */
430
431 /* Sanity check */
433
434 /* Get the global session */
435 SessionGlobal = MmSessionSpace->GlobalVirtualAddress;
436
437 /* Increment counters */
438 InterlockedIncrement((PLONG)&SessionGlobal->ReferenceCount);
441
442 /* Set the session pointer */
443 ASSERT(NewProcess->Session == NULL);
444 NewProcess->Session = SessionGlobal;
445
446 /* Acquire the expansion lock while touching the session */
448
449 /* Insert it into the process list */
450 InsertTailList(&SessionGlobal->ProcessList, &NewProcess->SessionProcessLinks);
451
452 /* Release the lock again */
454
455 /* Set the flag */
457}
#define InterlockedIncrement
Definition: armddk.h:53
#define PSF_PROCESS_IN_SESSION_BIT
Definition: pstypes.h:289
FORCEINLINE KIRQL MiAcquireExpansionLock(VOID)
Definition: miarm.h:1544
FORCEINLINE VOID MiReleaseExpansionLock(KIRQL OldIrql)
Definition: miarm.h:1557
PMM_SESSION_SPACE MmSessionSpace
Definition: session.c:21
#define PspSetProcessFlag(Process, Flag)
Definition: ps_x.h:33
LONG ResidentProcessCount
Definition: miarm.h:501
LONG ProcessReferenceToSession
Definition: miarm.h:508
LIST_ENTRY ProcessList
Definition: miarm.h:492
LONG ReferenceCount
Definition: miarm.h:485
int32_t * PLONG
Definition: typedefs.h:58

Referenced by MmCreateProcessAddressSpace().

◆ MiSessionRemoveProcess()

VOID NTAPI MiSessionRemoveProcess ( VOID  )

Definition at line 392 of file session.c.

393{
394 PEPROCESS CurrentProcess = PsGetCurrentProcess();
396
397 /* If the process isn't already in a session, or if it's the leader... */
398 if (!(CurrentProcess->Flags & PSF_PROCESS_IN_SESSION_BIT) ||
399 (CurrentProcess->Vm.Flags.SessionLeader))
400 {
401 /* Then there's nothing to do */
402 return;
403 }
404
405 /* Sanity check */
407
408 /* Acquire the expansion lock while touching the session */
410
411 /* Remove the process from the list */
412 RemoveEntryList(&CurrentProcess->SessionProcessLinks);
413
414 /* Release the lock again */
416
417 /* Dereference the session */
419}
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
VOID NTAPI MiDereferenceSession(VOID)
Definition: session.c:339
MMSUPPORT Vm
Definition: pstypes.h:1357
ULONG Flags
Definition: pstypes.h:1436
LIST_ENTRY SessionProcessLinks
Definition: pstypes.h:1275
ULONG SessionLeader
Definition: mmtypes.h:907

Referenced by MmCleanProcessAddressSpace().

◆ MiSyncARM3WithROS()

VOID FASTCALL MiSyncARM3WithROS ( IN PVOID  AddressStart,
IN PVOID  AddressEnd 
)

◆ MiSyncCachedRanges()

VOID NTAPI MiSyncCachedRanges ( VOID  )

Definition at line 54 of file largepag.c.

55{
56 ULONG i;
57
58 /* Scan every range */
59 for (i = 0; i < MiLargePageRangeIndex; i++)
60 {
61 UNIMPLEMENTED_DBGBREAK("No support for large pages\n");
62 }
63}
#define UNIMPLEMENTED_DBGBREAK(...)
Definition: debug.h:57
ULONG MiLargePageRangeIndex
Definition: largepag.c:22

Referenced by MmArmInitSystem().

◆ MiUnlinkFreeOrZeroedPage()

VOID NTAPI MiUnlinkFreeOrZeroedPage ( IN PMMPFN  Entry)

Definition at line 137 of file pfnlist.c.

138{
139 PFN_NUMBER OldFlink, OldBlink;
140 PMMPFNLIST ListHead;
141 MMLISTS ListName;
142 ULONG Color;
143 PMMCOLOR_TABLES ColorTable;
144 PMMPFN Pfn1;
145
146 /* Make sure the PFN lock is held */
148
149 /* Make sure the PFN entry isn't in-use */
150 ASSERT(Entry->u3.e1.WriteInProgress == 0);
151 ASSERT(Entry->u3.e1.ReadInProgress == 0);
152
153 /* Find the list for this entry, make sure it's the free or zero list */
154 ListHead = MmPageLocationList[Entry->u3.e1.PageLocation];
155 ListName = ListHead->ListName;
156 ASSERT(ListHead != NULL);
157 ASSERT(ListName <= FreePageList);
158 ASSERT_LIST_INVARIANT(ListHead);
159
160 /* Remove one count */
161 ASSERT(ListHead->Total != 0);
162 ListHead->Total--;
163
164 /* Get the forward and back pointers */
165 OldFlink = Entry->u1.Flink;
166 OldBlink = Entry->u2.Blink;
167
168 /* Check if the next entry is the list head */
169 if (OldFlink != LIST_HEAD)
170 {
171 /* It is not, so set the backlink of the actual entry, to our backlink */
172 MI_PFN_ELEMENT(OldFlink)->u2.Blink = OldBlink;
173 }
174 else
175 {
176 /* Set the list head's backlink instead */
177 ListHead->Blink = OldBlink;
178 }
179
180 /* Check if the back entry is the list head */
181 if (OldBlink != LIST_HEAD)
182 {
183 /* It is not, so set the backlink of the actual entry, to our backlink */
184 MI_PFN_ELEMENT(OldBlink)->u1.Flink = OldFlink;
185 }
186 else
187 {
188 /* Set the list head's backlink instead */
189 ListHead->Flink = OldFlink;
190 }
191
192 /* Get the page color */
193 OldBlink = MiGetPfnEntryIndex(Entry);
194 Color = OldBlink & MmSecondaryColorMask;
195
196 /* Get the first page on the color list */
197 ColorTable = &MmFreePagesByColor[ListName][Color];
198
199 /* Check if this was was actually the head */
200 OldFlink = ColorTable->Flink;
201 if (OldFlink == OldBlink)
202 {
203 /* Make the table point to the next page this page was linking to */
204 ColorTable->Flink = Entry->OriginalPte.u.Long;
205 if (ColorTable->Flink != LIST_HEAD)
206 {
207 /* And make the previous link point to the head now */
208 MI_PFN_ELEMENT(ColorTable->Flink)->u4.PteFrame = COLORED_LIST_HEAD;
209 }
210 else
211 {
212 /* And if that page was the head, loop the list back around */
213 ColorTable->Blink = (PVOID)LIST_HEAD;
214 }
215 }
216 else
217 {
218 /* This page shouldn't be pointing back to the head */
219 ASSERT(Entry->u4.PteFrame != COLORED_LIST_HEAD);
220
221 /* Make the back link point to whoever the next page is */
222 Pfn1 = MI_PFN_ELEMENT(Entry->u4.PteFrame);
223 Pfn1->OriginalPte.u.Long = Entry->OriginalPte.u.Long;
224
225 /* Check if this page was pointing to the head */
226 if (Entry->OriginalPte.u.Long != LIST_HEAD)
227 {
228 /* Make the back link point to the head */
229 Pfn1 = MI_PFN_ELEMENT(Entry->OriginalPte.u.Long);
230 Pfn1->u4.PteFrame = Entry->u4.PteFrame;
231 }
232 else
233 {
234 /* Then the table is directly back pointing to this page now */
235 ColorTable->Blink = Pfn1;
236 }
237 }
238
239 /* One less colored page */
240 ASSERT(ColorTable->Count >= 1);
241 ColorTable->Count--;
242
243 /* ReactOS Hack */
244 Entry->OriginalPte.u.Long = 0;
245
246 /* We are not on a list anymore */
247 Entry->u1.Flink = Entry->u2.Blink = 0;
248 ASSERT_LIST_INVARIANT(ListHead);
249
250 /* Decrement number of available pages */
252
253#if MI_TRACE_PFNS
255 Entry->PfnUsage = MI_PFN_CURRENT_USAGE;
256 memcpy(Entry->ProcessName, MI_PFN_CURRENT_PROCESS_NAME, 16);
257 Entry->CallSite = _ReturnAddress();
259 MI_SET_PROCESS2("Not Set");
260#endif
261}
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
static VOID MiDecrementAvailablePages(VOID)
Definition: pfnlist.c:90
CHAR MI_PFN_CURRENT_PROCESS_NAME[16]
Definition: pfnlist.c:64
PMMPFNLIST MmPageLocationList[]
Definition: pfnlist.c:51
base of all file and directory entries
Definition: entries.h:83
MMLISTS ListName
Definition: mm.h:451

Referenced by MiAllocatePagesForMdl(), and MiFindContiguousPages().

◆ MiUnlinkPageFromList()

VOID NTAPI MiUnlinkPageFromList ( IN PMMPFN  Pfn)

Definition at line 265 of file pfnlist.c.

266{
267 PMMPFNLIST ListHead;
268 PFN_NUMBER OldFlink, OldBlink;
269
270 /* Make sure the PFN lock is held */
272
273 /* ARM3 should only call this for dead pages */
274 ASSERT(Pfn->u3.e2.ReferenceCount == 0);
275
276 /* Transition pages are supposed to be standby/modified/nowrite */
277 ListHead = MmPageLocationList[Pfn->u3.e1.PageLocation];
278 ASSERT(ListHead->ListName >= StandbyPageList);
279
280 /* Check if this was standby, or modified */
281 if (ListHead == &MmStandbyPageListHead)
282 {
283 /* Should not be a ROM page */
284 ASSERT(Pfn->u3.e1.Rom == 0);
285
286 /* Get the exact list */
287 ListHead = &MmStandbyPageListByPriority[Pfn->u4.Priority];
288
289 /* Decrement number of available pages */
291
292 /* Decrease transition page counter */
293 ASSERT(Pfn->u3.e1.PrototypePte == 1); /* Only supported ARM3 case */
295 }
296 else if (ListHead == &MmModifiedPageListHead)
297 {
298 /* Only shared memory (page-file backed) modified pages are supported */
299 ASSERT(Pfn->OriginalPte.u.Soft.Prototype == 0);
300
301 /* Decrement the counters */
302 ListHead->Total--;
304
305 /* Pick the correct colored list */
306 ListHead = &MmModifiedPageListByColor[0];
307
308 /* Decrease transition page counter */
310 }
311 else if (ListHead == &MmModifiedNoWritePageListHead)
312 {
313 /* List not yet supported */
314 ASSERT(FALSE);
315 }
316
317 /* Nothing should be in progress and the list should not be empty */
318 ASSERT(Pfn->u3.e1.WriteInProgress == 0);
319 ASSERT(Pfn->u3.e1.ReadInProgress == 0);
320 ASSERT(ListHead->Total != 0);
321
322 /* Get the forward and back pointers */
323 OldFlink = Pfn->u1.Flink;
324 OldBlink = Pfn->u2.Blink;
325
326 /* Check if the next entry is the list head */
327 if (OldFlink != LIST_HEAD)
328 {
329 /* It is not, so set the backlink of the actual entry, to our backlink */
330 MI_PFN_ELEMENT(OldFlink)->u2.Blink = OldBlink;
331 }
332 else
333 {
334 /* Set the list head's backlink instead */
335 ListHead->Blink = OldBlink;
336 }
337
338 /* Check if the back entry is the list head */
339 if (OldBlink != LIST_HEAD)
340 {
341 /* It is not, so set the backlink of the actual entry, to our backlink */
342 MI_PFN_ELEMENT(OldBlink)->u1.Flink = OldFlink;
343 }
344 else
345 {
346 /* Set the list head's backlink instead */
347 ListHead->Flink = OldFlink;
348 }
349
350 /* ReactOS Hack */
351 Pfn->OriginalPte.u.Long = 0;
352
353 /* We are not on a list anymore */
354 Pfn->u1.Flink = Pfn->u2.Blink = 0;
355
356 /* Remove one entry from the list */
357 ListHead->Total--;
358
359 ASSERT_LIST_INVARIANT(ListHead);
360}
MMPFNLIST MmModifiedNoWritePageListHead
Definition: pfnlist.c:47

Referenced by MiDeletePte(), MiDispatchFault(), MiResolveTransitionFault(), and MiSegmentDelete().

◆ MiUnlockProcessWorkingSet()

FORCEINLINE VOID MiUnlockProcessWorkingSet ( IN PEPROCESS  Process,
IN PETHREAD  Thread 
)

Definition at line 1207 of file miarm.h.

1209{
1210 /* Make sure we are the owner of a safe acquisition */
1213
1214 /* The thread doesn't own it anymore */
1217
1218 /* Release the lock and re-enable APCs */
1219 ExReleasePushLockExclusive(&Process->Vm.WorkingSetMutex);
1221}
FORCEINLINE VOID ExReleasePushLockExclusive(PEX_PUSH_LOCK PushLock)
Definition: ex.h:1255
FORCEINLINE BOOLEAN MI_WS_OWNER(IN PEPROCESS Process)
Definition: miarm.h:1090

Referenced by MiLockVirtualMemory(), MiUnlockProcessWorkingSetForFault(), MiUnlockVirtualMemory(), MmArmAccessFault(), MmFreeMemoryArea(), MmInitializeProcessAddressSpace(), MmProbeAndLockPages(), and MmTrimUserMemory().

◆ MiUnlockProcessWorkingSetForFault()

FORCEINLINE VOID MiUnlockProcessWorkingSetForFault ( IN PEPROCESS  Process,
IN PETHREAD  Thread,
OUT PBOOLEAN  Safe,
OUT PBOOLEAN  Shared 
)

Definition at line 1481 of file miarm.h.

1485{
1487
1488 /* Check if the current owner is unsafe */
1490 {
1491 /* Release unsafely */
1493 *Safe = FALSE;
1494 *Shared = FALSE;
1495 }
1497 {
1498 /* Owner is safe and exclusive, release normally */
1500 *Safe = TRUE;
1501 *Shared = FALSE;
1502 }
1503 else
1504 {
1505 /* Owner is shared (implies safe), release normally */
1507 *Safe = TRUE;
1508 *Shared = TRUE;
1509 }
1510}
FORCEINLINE VOID MiUnlockProcessWorkingSetShared(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1228
FORCEINLINE VOID MiUnlockProcessWorkingSet(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1207

Referenced by MiGetPageProtection(), and MiMakeSystemAddressValid().

◆ MiUnlockProcessWorkingSetShared()

FORCEINLINE VOID MiUnlockProcessWorkingSetShared ( IN PEPROCESS  Process,
IN PETHREAD  Thread 
)

Definition at line 1228 of file miarm.h.

1230{
1231 /* Make sure we are the owner of a safe acquisition (because shared) */
1234
1235 /* Ensure we are in a shared acquisition */
1238
1239 /* Don't claim the lock anylonger */
1241
1242 /* Release the lock and re-enable APCs */
1243 ExReleasePushLockShared(&Process->Vm.WorkingSetMutex);
1245}
FORCEINLINE VOID ExReleasePushLockShared(PEX_PUSH_LOCK PushLock)
Definition: ex.h:1216

Referenced by MiQueryMemoryBasicInformation(), MiUnlockProcessWorkingSetForFault(), MmAccessFault(), MmGetPageFileMapping(), MmGetPageProtect(), MmGetPfnForProcess(), MmIsDisabledPage(), MmIsPagePresent(), and MmIsPageSwapEntry().

◆ MiUnlockProcessWorkingSetUnsafe()

FORCEINLINE VOID MiUnlockProcessWorkingSetUnsafe ( IN PEPROCESS  Process,
IN PETHREAD  Thread 
)

Definition at line 1252 of file miarm.h.

1254{
1255 /* Make sure we are the owner of an unsafe acquisition */
1260
1261 /* No longer unsafe */
1262 Process->Vm.Flags.AcquiredUnsafe = 0;
1263
1264 /* The thread doesn't own it anymore */
1267
1268 /* Release the lock but don't touch APC state */
1269 ExReleasePushLockExclusive(&Process->Vm.WorkingSetMutex);
1271}

Referenced by _Success_(), MiDecommitPages(), MiInsertVadEx(), MiMapLockedPagesInUserSpace(), MiProtectVirtualMemory(), MiRemoveMappedView(), MiUnlockProcessWorkingSetForFault(), MiUnmapLockedPagesInUserSpace(), MmCleanProcessAddressSpace(), MmCreatePageFileMapping(), MmCreateVirtualMappingUnsafeEx(), MmDeletePageFileMapping(), MmDeleteTeb(), MmInsertMemoryArea(), MmSetDirtyBit(), MmSetPageProtect(), NtAllocateVirtualMemory(), and NtFreeVirtualMemory().

◆ MiUnlockWorkingSet()

FORCEINLINE VOID MiUnlockWorkingSet ( IN PETHREAD  Thread,
IN PMMSUPPORT  WorkingSet 
)

Definition at line 1364 of file miarm.h.

1366{
1367 /* Working set should be in global memory */
1368 ASSERT(MI_IS_SESSION_ADDRESS((PVOID)WorkingSet) == FALSE);
1369
1370 /* Which working set is this? */
1371 if (WorkingSet == &MmSystemCacheWs)
1372 {
1373 /* Release the system working set */
1377 }
1378 else if (WorkingSet->Flags.SessionSpace)
1379 {
1380 /* Release the session working set */
1384 }
1385 else
1386 {
1387 /* Release the process working set */
1391 }
1392
1393 /* Release the working set lock */
1394 ExReleasePushLockExclusive(&WorkingSet->WorkingSetMutex);
1395
1396 /* Unblock APCs */
1398}

Referenced by MiDeleteSystemPageableVm(), MiSetPagingOfDriver(), MmAdjustWorkingSetSize(), MmArmAccessFault(), MmFreeMemoryArea(), MmInsertMemoryArea(), and MmWorkingSetManager().

◆ MiUnlockWorkingSetShared()

FORCEINLINE VOID MiUnlockWorkingSetShared ( _In_ PETHREAD  Thread,
_In_ PMMSUPPORT  WorkingSet 
)

Definition at line 1402 of file miarm.h.

1405{
1406 /* Working set should be in global memory */
1407 ASSERT(MI_IS_SESSION_ADDRESS((PVOID)WorkingSet) == FALSE);
1408
1409 /* Which working set is this? */
1410 if (WorkingSet == &MmSystemCacheWs)
1411 {
1412 /* Release the system working set */
1416 }
1417 else if (WorkingSet->Flags.SessionSpace)
1418 {
1419 /* Release the session working set */
1423 }
1424 else
1425 {
1426 /* Release the process working set */
1430 }
1431
1432 /* Release the working set lock */
1433 ExReleasePushLockShared(&WorkingSet->WorkingSetMutex);
1434
1435 /* Unblock APCs */
1437}

Referenced by MmAccessFault(), and MmWorkingSetManager().

◆ MiWriteProtectSystemImage()

VOID NTAPI MiWriteProtectSystemImage ( _In_ PVOID  ImageBase)

Definition at line 2481 of file sysldr.c.

2483{
2484 PIMAGE_NT_HEADERS NtHeaders;
2485 PIMAGE_SECTION_HEADER SectionHeaders, Section;
2486 ULONG i;
2487 PVOID SectionBase, SectionEnd;
2488 ULONG SectionSize;
2489 ULONG Protection;
2490 PMMPTE FirstPte, LastPte;
2491
2492 /* Check if the registry setting is on or not */
2494 {
2495 /* Ignore section protection */
2496 return;
2497 }
2498
2499 /* Large page mapped images are not supported */
2500 NT_ASSERT(!MI_IS_PHYSICAL_ADDRESS(ImageBase));
2501
2502 /* Session images are not yet supported */
2503 NT_ASSERT(!MI_IS_SESSION_ADDRESS(ImageBase));
2504
2505 /* Get the NT headers */
2506 NtHeaders = RtlImageNtHeader(ImageBase);
2507 if (NtHeaders == NULL)
2508 {
2509 DPRINT1("Failed to get NT headers for image @ %p\n", ImageBase);
2510 return;
2511 }
2512
2513 /* Don't touch NT4 drivers */
2514 if ((NtHeaders->OptionalHeader.MajorOperatingSystemVersion < 5) ||
2515 (NtHeaders->OptionalHeader.MajorSubsystemVersion < 5))
2516 {
2517 DPRINT1("Skipping NT 4 driver @ %p\n", ImageBase);
2518 return;
2519 }
2520
2521 /* Get the section headers */
2522 SectionHeaders = IMAGE_FIRST_SECTION(NtHeaders);
2523
2524 /* Get the base address of the first section */
2525 SectionBase = Add2Ptr(ImageBase, SectionHeaders[0].VirtualAddress);
2526
2527 /* Start protecting the image header as R/W */
2528 FirstPte = MiAddressToPte(ImageBase);
2529 LastPte = MiAddressToPte(SectionBase) - 1;
2531 if (LastPte >= FirstPte)
2532 {
2533 MiSetSystemCodeProtection(FirstPte, LastPte, Protection);
2534 }
2535
2536 /* Loop the sections */
2537 for (i = 0; i < NtHeaders->FileHeader.NumberOfSections; i++)
2538 {
2539 /* Get the section base address and size */
2540 Section = &SectionHeaders[i];
2541 SectionBase = Add2Ptr(ImageBase, Section->VirtualAddress);
2542 SectionSize = max(Section->SizeOfRawData, Section->Misc.VirtualSize);
2543
2544 /* Get the first PTE of this section */
2545 FirstPte = MiAddressToPte(SectionBase);
2546
2547 /* Check for overlap with the previous range */
2548 if (FirstPte == LastPte)
2549 {
2550 /* Combine the old and new protection by ORing them */
2551 Protection |= (Section->Characteristics & IMAGE_SCN_PROTECTION_MASK);
2552
2553 /* Update the protection for this PTE */
2554 MiSetSystemCodeProtection(FirstPte, FirstPte, Protection);
2555
2556 /* Skip this PTE */
2557 FirstPte++;
2558 }
2559
2560 /* There can not be gaps! */
2561 NT_ASSERT(FirstPte == (LastPte + 1));
2562
2563 /* Get the end of the section and the last PTE */
2564 SectionEnd = Add2Ptr(SectionBase, SectionSize - 1);
2565 NT_ASSERT(SectionEnd < Add2Ptr(ImageBase, NtHeaders->OptionalHeader.SizeOfImage));
2566 LastPte = MiAddressToPte(SectionEnd);
2567
2568 /* If there are no more pages (after an overlap), skip this section */
2569 if (LastPte < FirstPte)
2570 {
2571 NT_ASSERT(FirstPte == (LastPte + 1));
2572 continue;
2573 }
2574
2575 /* Get the section protection */
2576 Protection = (Section->Characteristics & IMAGE_SCN_PROTECTION_MASK);
2577
2578 /* Update the protection for this section */
2579 MiSetSystemCodeProtection(FirstPte, LastPte, Protection);
2580 }
2581
2582 /* Image should end with the last section */
2583 if (ALIGN_UP_POINTER_BY(SectionEnd, PAGE_SIZE) !=
2584 Add2Ptr(ImageBase, NtHeaders->OptionalHeader.SizeOfImage))
2585 {
2586 DPRINT1("ImageBase 0x%p ImageSize 0x%lx Section %u VA 0x%lx Raw 0x%lx virt 0x%lx\n",
2587 ImageBase,
2588 NtHeaders->OptionalHeader.SizeOfImage,
2589 i,
2590 Section->VirtualAddress,
2591 Section->SizeOfRawData,
2592 Section->Misc.VirtualSize);
2593 }
2594}
#define RtlImageNtHeader
Definition: compat.h:806
#define IMAGE_SCN_PROTECTION_MASK
Definition: miarm.h:174
#define IMAGE_SCN_MEM_WRITE
Definition: ntimage.h:241
#define IMAGE_FIRST_SECTION(NtHeader)
Definition: ntimage.h:427
#define IMAGE_SCN_MEM_READ
Definition: ntimage.h:240
IMAGE_OPTIONAL_HEADER32 OptionalHeader
Definition: ntddk_ex.h:184
IMAGE_FILE_HEADER FileHeader
Definition: ntddk_ex.h:183
WORD MajorOperatingSystemVersion
Definition: ntddk_ex.h:160
union _IMAGE_SECTION_HEADER::@1603 Misc
BOOLEAN MmEnforceWriteProtection
Definition: sysldr.c:34
VOID NTAPI MiSetSystemCodeProtection(_In_ PMMPTE FirstPte, _In_ PMMPTE LastPte, _In_ ULONG Protection)
Definition: sysldr.c:2442
#define ALIGN_UP_POINTER_BY(ptr, align)
Definition: umtypes.h:85
#define NT_ASSERT
Definition: rtlfuncs.h:3327

Referenced by MmInitSystem(), and MmLoadSystemImage().

◆ MiZeroPhysicalPage()

VOID NTAPI MiZeroPhysicalPage ( IN PFN_NUMBER  PageFrameIndex)

Definition at line 122 of file pfnlist.c.

123{
127
128 /* Map in hyperspace, then wipe it using XMMI or MEMSET */
133}
VOID FASTCALL KeZeroPages(IN PVOID Address, IN ULONG Size)
Definition: cpu.c:56
VOID NTAPI MiUnmapPageInHyperSpace(IN PEPROCESS Process, IN PVOID Address, IN KIRQL OldIrql)
Definition: hypermap.c:91
PVOID NTAPI MiMapPageInHyperSpace(IN PEPROCESS Process, IN PFN_NUMBER Page, IN PKIRQL OldIrql)
Definition: hypermap.c:28

◆ MM_ANY_WS_LOCK_HELD()

◆ MM_ANY_WS_LOCK_HELD_EXCLUSIVE()

FORCEINLINE BOOLEAN MM_ANY_WS_LOCK_HELD_EXCLUSIVE ( _In_ PETHREAD  Thread)

◆ MmArmAccessFault()

NTSTATUS NTAPI MmArmAccessFault ( IN ULONG  FaultCode,
IN PVOID  Address,
IN KPROCESSOR_MODE  Mode,
IN PVOID  TrapInformation 
)

Definition at line 1698 of file pagfault.c.

1702{
1703 KIRQL OldIrql = KeGetCurrentIrql(), LockIrql;
1704 PMMPTE ProtoPte = NULL;
1705 PMMPTE PointerPte = MiAddressToPte(Address);
1706 PMMPDE PointerPde = MiAddressToPde(Address);
1707#if (_MI_PAGING_LEVELS >= 3)
1708 PMMPDE PointerPpe = MiAddressToPpe(Address);
1709#if (_MI_PAGING_LEVELS == 4)
1710 PMMPDE PointerPxe = MiAddressToPxe(Address);
1711#endif
1712#endif
1713 MMPTE TempPte;
1714 PETHREAD CurrentThread;
1715 PEPROCESS CurrentProcess;
1717 PMMSUPPORT WorkingSet;
1718 ULONG ProtectionCode;
1719 PMMVAD Vad = NULL;
1720 PFN_NUMBER PageFrameIndex;
1721 ULONG Color;
1722 BOOLEAN IsSessionAddress;
1723 PMMPFN Pfn1;
1724 DPRINT("ARM3 FAULT AT: %p\n", Address);
1725
1726 /* Check for page fault on high IRQL */
1727 if (OldIrql > APC_LEVEL)
1728 {
1729#if (_MI_PAGING_LEVELS < 3)
1730 /* Could be a page table for paged pool, which we'll allow */
1731 if (MI_IS_SYSTEM_PAGE_TABLE_ADDRESS(Address)) MiSynchronizeSystemPde((PMMPDE)PointerPte);
1733#endif
1734 /* Check if any of the top-level pages are invalid */
1735 if (
1736#if (_MI_PAGING_LEVELS == 4)
1737 (PointerPxe->u.Hard.Valid == 0) ||
1738#endif
1739#if (_MI_PAGING_LEVELS >= 3)
1740 (PointerPpe->u.Hard.Valid == 0) ||
1741#endif
1742 (PointerPde->u.Hard.Valid == 0) ||
1743 (PointerPte->u.Hard.Valid == 0))
1744 {
1745 /* This fault is not valid, print out some debugging help */
1746 DbgPrint("MM:***PAGE FAULT AT IRQL > 1 Va %p, IRQL %lx\n",
1747 Address,
1748 OldIrql);
1749 if (TrapInformation)
1750 {
1751 PKTRAP_FRAME TrapFrame = TrapInformation;
1752#ifdef _M_IX86
1753 DbgPrint("MM:***EIP %p, EFL %p\n", TrapFrame->Eip, TrapFrame->EFlags);
1754 DbgPrint("MM:***EAX %p, ECX %p EDX %p\n", TrapFrame->Eax, TrapFrame->Ecx, TrapFrame->Edx);
1755 DbgPrint("MM:***EBX %p, ESI %p EDI %p\n", TrapFrame->Ebx, TrapFrame->Esi, TrapFrame->Edi);
1756#elif defined(_M_AMD64)
1757 DbgPrint("MM:***RIP %p, EFL %p\n", TrapFrame->Rip, TrapFrame->EFlags);
1758 DbgPrint("MM:***RAX %p, RCX %p RDX %p\n", TrapFrame->Rax, TrapFrame->Rcx, TrapFrame->Rdx);
1759 DbgPrint("MM:***RBX %p, RSI %p RDI %p\n", TrapFrame->Rbx, TrapFrame->Rsi, TrapFrame->Rdi);
1760#elif defined(_M_ARM)
1761 DbgPrint("MM:***PC %p\n", TrapFrame->Pc);
1762 DbgPrint("MM:***R0 %p, R1 %p R2 %p, R3 %p\n", TrapFrame->R0, TrapFrame->R1, TrapFrame->R2, TrapFrame->R3);
1763 DbgPrint("MM:***R11 %p, R12 %p SP %p, LR %p\n", TrapFrame->R11, TrapFrame->R12, TrapFrame->Sp, TrapFrame->Lr);
1764#endif
1765 }
1766
1767 /* Tell the trap handler to fail */
1768 return STATUS_IN_PAGE_ERROR | 0x10000000;
1769 }
1770
1771 /* Not yet implemented in ReactOS */
1772 ASSERT(MI_IS_PAGE_LARGE(PointerPde) == FALSE);
1773 ASSERT((!MI_IS_NOT_PRESENT_FAULT(FaultCode) && MI_IS_PAGE_COPY_ON_WRITE(PointerPte)) == FALSE);
1774
1775 /* Check if this was a write */
1776 if (MI_IS_WRITE_ACCESS(FaultCode))
1777 {
1778 /* Was it to a read-only page? */
1779 Pfn1 = MI_PFN_ELEMENT(PointerPte->u.Hard.PageFrameNumber);
1780 if (!(PointerPte->u.Long & PTE_READWRITE) &&
1782 {
1783 /* Crash with distinguished bugcheck code */
1784 KeBugCheckEx(ATTEMPTED_WRITE_TO_READONLY_MEMORY,
1786 PointerPte->u.Long,
1787 (ULONG_PTR)TrapInformation,
1788 10);
1789 }
1790 }
1791
1792 /* Nothing is actually wrong */
1793 DPRINT1("Fault at IRQL %u is ok (%p)\n", OldIrql, Address);
1794 return STATUS_SUCCESS;
1795 }
1796
1797 /* Check for kernel fault address */
1799 {
1800 /* Bail out, if the fault came from user mode */
1801 if (Mode == UserMode) return STATUS_ACCESS_VIOLATION;
1802
1803#if (_MI_PAGING_LEVELS == 2)
1804 if (MI_IS_SYSTEM_PAGE_TABLE_ADDRESS(Address)) MiSynchronizeSystemPde((PMMPDE)PointerPte);
1806#endif
1807
1808 /* Check if the higher page table entries are invalid */
1809 if (
1810#if (_MI_PAGING_LEVELS == 4)
1811 /* AMD64 system, check if PXE is invalid */
1812 (PointerPxe->u.Hard.Valid == 0) ||
1813#endif
1814#if (_MI_PAGING_LEVELS >= 3)
1815 /* PAE/AMD64 system, check if PPE is invalid */
1816 (PointerPpe->u.Hard.Valid == 0) ||
1817#endif
1818 /* Always check if the PDE is valid */
1819 (PointerPde->u.Hard.Valid == 0))
1820 {
1821 /* PXE/PPE/PDE (still) not valid, kill the system */
1822 KeBugCheckEx(PAGE_FAULT_IN_NONPAGED_AREA,
1824 FaultCode,
1825 (ULONG_PTR)TrapInformation,
1826 2);
1827 }
1828
1829 /* Not handling session faults yet */
1830 IsSessionAddress = MI_IS_SESSION_ADDRESS(Address);
1831
1832 /* The PDE is valid, so read the PTE */
1833 TempPte = *PointerPte;
1834 if (TempPte.u.Hard.Valid == 1)
1835 {
1836 /* Check if this was system space or session space */
1837 if (!IsSessionAddress)
1838 {
1839 /* Check if the PTE is still valid under PFN lock */
1840 OldIrql = MiAcquirePfnLock();
1841 TempPte = *PointerPte;
1842 if (TempPte.u.Hard.Valid)
1843 {
1844 /* Check if this was a write */
1845 if (MI_IS_WRITE_ACCESS(FaultCode))
1846 {
1847 /* Was it to a read-only page? */
1848 Pfn1 = MI_PFN_ELEMENT(PointerPte->u.Hard.PageFrameNumber);
1849 if (!(PointerPte->u.Long & PTE_READWRITE) &&
1851 {
1852 /* Crash with distinguished bugcheck code */
1853 KeBugCheckEx(ATTEMPTED_WRITE_TO_READONLY_MEMORY,
1855 PointerPte->u.Long,
1856 (ULONG_PTR)TrapInformation,
1857 11);
1858 }
1859 }
1860
1861 /* Check for execution of non-executable memory */
1862 if (MI_IS_INSTRUCTION_FETCH(FaultCode) &&
1864 {
1865 KeBugCheckEx(ATTEMPTED_EXECUTE_OF_NOEXECUTE_MEMORY,
1867 (ULONG_PTR)TempPte.u.Long,
1868 (ULONG_PTR)TrapInformation,
1869 1);
1870 }
1871 }
1872
1873 /* Release PFN lock and return all good */
1874 MiReleasePfnLock(OldIrql);
1875 return STATUS_SUCCESS;
1876 }
1877 }
1878#if (_MI_PAGING_LEVELS == 2)
1879 /* Check if this was a session PTE that needs to remap the session PDE */
1881 {
1882 /* Do the remapping */
1883 Status = MiCheckPdeForSessionSpace(Address);
1884 if (!NT_SUCCESS(Status))
1885 {
1886 /* It failed, this address is invalid */
1887 KeBugCheckEx(PAGE_FAULT_IN_NONPAGED_AREA,
1889 FaultCode,
1890 (ULONG_PTR)TrapInformation,
1891 6);
1892 }
1893 }
1894#else
1895
1896_WARN("Session space stuff is not implemented yet!")
1897
1898#endif
1899
1900 /* Check for a fault on the page table or hyperspace */
1902 {
1903#if (_MI_PAGING_LEVELS < 3)
1904 /* Windows does this check but I don't understand why -- it's done above! */
1906#endif
1907 /* Handle this as a user mode fault */
1908 goto UserFault;
1909 }
1910
1911 /* Get the current thread */
1912 CurrentThread = PsGetCurrentThread();
1913
1914 /* What kind of address is this */
1915 if (!IsSessionAddress)
1916 {
1917 /* Use the system working set */
1918 WorkingSet = &MmSystemCacheWs;
1919 CurrentProcess = NULL;
1920
1921 /* Make sure we don't have a recursive working set lock */
1922 if ((CurrentThread->OwnsProcessWorkingSetExclusive) ||
1923 (CurrentThread->OwnsProcessWorkingSetShared) ||
1924 (CurrentThread->OwnsSystemWorkingSetExclusive) ||
1925 (CurrentThread->OwnsSystemWorkingSetShared) ||
1926 (CurrentThread->OwnsSessionWorkingSetExclusive) ||
1927 (CurrentThread->OwnsSessionWorkingSetShared))
1928 {
1929 /* Fail */
1930 return STATUS_IN_PAGE_ERROR | 0x10000000;
1931 }
1932 }
1933 else
1934 {
1935 /* Use the session process and working set */
1936 CurrentProcess = HYDRA_PROCESS;
1937 WorkingSet = &MmSessionSpace->GlobalVirtualAddress->Vm;
1938
1939 /* Make sure we don't have a recursive working set lock */
1940 if ((CurrentThread->OwnsSessionWorkingSetExclusive) ||
1941 (CurrentThread->OwnsSessionWorkingSetShared))
1942 {
1943 /* Fail */
1944 return STATUS_IN_PAGE_ERROR | 0x10000000;
1945 }
1946 }
1947RetryKernel:
1948 /* Acquire the working set lock */
1949 KeRaiseIrql(APC_LEVEL, &LockIrql);
1950 MiLockWorkingSet(CurrentThread, WorkingSet);
1951
1952 /* Re-read PTE now that we own the lock */
1953 TempPte = *PointerPte;
1954 if (TempPte.u.Hard.Valid == 1)
1955 {
1956 /* Check if this was a write */
1957 if (MI_IS_WRITE_ACCESS(FaultCode))
1958 {
1959 /* Was it to a read-only page that is not copy on write? */
1960 Pfn1 = MI_PFN_ELEMENT(PointerPte->u.Hard.PageFrameNumber);
1961 if (!(TempPte.u.Long & PTE_READWRITE) &&
1964 {
1965 /* Case not yet handled */
1966 ASSERT(!IsSessionAddress);
1967
1968 /* Crash with distinguished bugcheck code */
1969 KeBugCheckEx(ATTEMPTED_WRITE_TO_READONLY_MEMORY,
1971 TempPte.u.Long,
1972 (ULONG_PTR)TrapInformation,
1973 12);
1974 }
1975 }
1976
1977 /* Check for execution of non-executable memory */
1978 if (MI_IS_INSTRUCTION_FETCH(FaultCode) &&
1980 {
1981 KeBugCheckEx(ATTEMPTED_EXECUTE_OF_NOEXECUTE_MEMORY,
1983 (ULONG_PTR)TempPte.u.Long,
1984 (ULONG_PTR)TrapInformation,
1985 2);
1986 }
1987
1988 /* Check for read-only write in session space */
1989 if ((IsSessionAddress) &&
1990 MI_IS_WRITE_ACCESS(FaultCode) &&
1992 {
1993 /* Sanity check */
1995
1996 /* Was this COW? */
1998 {
1999 /* Then this is not allowed */
2000 KeBugCheckEx(ATTEMPTED_WRITE_TO_READONLY_MEMORY,
2002 (ULONG_PTR)TempPte.u.Long,
2003 (ULONG_PTR)TrapInformation,
2004 13);
2005 }
2006
2007 /* Otherwise, handle COW */
2008 ASSERT(FALSE);
2009 }
2010
2011 /* Release the working set */
2012 MiUnlockWorkingSet(CurrentThread, WorkingSet);
2013 KeLowerIrql(LockIrql);
2014
2015 /* Otherwise, the PDE was probably invalid, and all is good now */
2016 return STATUS_SUCCESS;
2017 }
2018
2019 /* Check one kind of prototype PTE */
2020 if (TempPte.u.Soft.Prototype)
2021 {
2022 /* Make sure protected pool is on, and that this is a pool address */
2029 {
2030 /* Bad boy, bad boy, whatcha gonna do, whatcha gonna do when ARM3 comes for you! */
2031 KeBugCheckEx(DRIVER_CAUGHT_MODIFYING_FREED_POOL,
2033 FaultCode,
2034 Mode,
2035 4);
2036 }
2037
2038 /* Get the prototype PTE! */
2039 ProtoPte = MiProtoPteToPte(&TempPte);
2040
2041 /* Do we need to locate the prototype PTE in session space? */
2042 if ((IsSessionAddress) &&
2043 (TempPte.u.Soft.PageFileHigh == MI_PTE_LOOKUP_NEEDED))
2044 {
2045 /* Yep, go find it as well as the VAD for it */
2046 ProtoPte = MiCheckVirtualAddress(Address,
2047 &ProtectionCode,
2048 &Vad);
2049 ASSERT(ProtoPte != NULL);
2050 }
2051 }
2052 else
2053 {
2054 /* We don't implement transition PTEs */
2055 ASSERT(TempPte.u.Soft.Transition == 0);
2056
2057 /* Check for no-access PTE */
2058 if (TempPte.u.Soft.Protection == MM_NOACCESS)
2059 {
2060 /* Bugcheck the system! */
2061 KeBugCheckEx(PAGE_FAULT_IN_NONPAGED_AREA,
2063 FaultCode,
2064 (ULONG_PTR)TrapInformation,
2065 1);
2066 }
2067
2068 /* Check for no protecton at all */
2069 if (TempPte.u.Soft.Protection == MM_ZERO_ACCESS)
2070 {
2071 /* Bugcheck the system! */
2072 KeBugCheckEx(PAGE_FAULT_IN_NONPAGED_AREA,
2074 FaultCode,
2075 (ULONG_PTR)TrapInformation,
2076 0);
2077 }
2078 }
2079
2080 /* Check for demand page */
2081 if (MI_IS_WRITE_ACCESS(FaultCode) &&
2082 !(ProtoPte) &&
2083 !(IsSessionAddress) &&
2084 !(TempPte.u.Hard.Valid))
2085 {
2086 /* Get the protection code */
2087 ASSERT(TempPte.u.Soft.Transition == 0);
2088 if (!(TempPte.u.Soft.Protection & MM_READWRITE))
2089 {
2090 /* Bugcheck the system! */
2091 KeBugCheckEx(ATTEMPTED_WRITE_TO_READONLY_MEMORY,
2093 TempPte.u.Long,
2094 (ULONG_PTR)TrapInformation,
2095 14);
2096 }
2097 }
2098
2099 /* Now do the real fault handling */
2100 Status = MiDispatchFault(FaultCode,
2101 Address,
2102 PointerPte,
2103 ProtoPte,
2104 FALSE,
2105 CurrentProcess,
2106 TrapInformation,
2107 NULL);
2108
2109 /* Release the working set */
2111 MiUnlockWorkingSet(CurrentThread, WorkingSet);
2112 KeLowerIrql(LockIrql);
2113
2114 if (Status == STATUS_NO_MEMORY)
2115 {
2117 goto RetryKernel;
2118 }
2119
2120 /* We are done! */
2121 DPRINT("Fault resolved with status: %lx\n", Status);
2122 return Status;
2123 }
2124
2125 /* This is a user fault */
2126UserFault:
2127 CurrentThread = PsGetCurrentThread();
2128 CurrentProcess = (PEPROCESS)CurrentThread->Tcb.ApcState.Process;
2129
2130 /* Lock the working set */
2131 MiLockProcessWorkingSet(CurrentProcess, CurrentThread);
2132
2133 ProtectionCode = MM_INVALID_PROTECTION;
2134
2135#if (_MI_PAGING_LEVELS == 4)
2136 /* Check if the PXE is valid */
2137 if (PointerPxe->u.Hard.Valid == 0)
2138 {
2139 /* Right now, we only handle scenarios where the PXE is totally empty */
2140 ASSERT(PointerPxe->u.Long == 0);
2141
2142 /* This is only possible for user mode addresses! */
2143 ASSERT(PointerPte <= MiHighestUserPte);
2144
2145 /* Check if we have a VAD */
2146 MiCheckVirtualAddress(Address, &ProtectionCode, &Vad);
2147 if (ProtectionCode == MM_NOACCESS)
2148 {
2149 MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
2151 }
2152
2153 /* Resolve a demand zero fault */
2154 Status = MiResolveDemandZeroFault(PointerPpe,
2155 PointerPxe,
2157 CurrentProcess,
2158 MM_NOIRQL);
2159 if (!NT_SUCCESS(Status))
2160 {
2161 goto ExitUser;
2162 }
2163
2164 /* We should come back with a valid PXE */
2165 ASSERT(PointerPxe->u.Hard.Valid == 1);
2166 }
2167#endif
2168
2169#if (_MI_PAGING_LEVELS >= 3)
2170 /* Check if the PPE is valid */
2171 if (PointerPpe->u.Hard.Valid == 0)
2172 {
2173 /* Right now, we only handle scenarios where the PPE is totally empty */
2174 ASSERT(PointerPpe->u.Long == 0);
2175
2176 /* This is only possible for user mode addresses! */
2177 ASSERT(PointerPte <= MiHighestUserPte);
2178
2179 /* Check if we have a VAD, unless we did this already */
2180 if (ProtectionCode == MM_INVALID_PROTECTION)
2181 {
2182 MiCheckVirtualAddress(Address, &ProtectionCode, &Vad);
2183 }
2184
2185 if (ProtectionCode == MM_NOACCESS)
2186 {
2187 MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
2189 }
2190
2191 /* Resolve a demand zero fault */
2192 Status = MiResolveDemandZeroFault(PointerPde,
2193 PointerPpe,
2195 CurrentProcess,
2196 MM_NOIRQL);
2197 if (!NT_SUCCESS(Status))
2198 {
2199 goto ExitUser;
2200 }
2201
2202 /* We should come back with a valid PPE */
2203 ASSERT(PointerPpe->u.Hard.Valid == 1);
2205 }
2206#endif
2207
2208 /* Check if the PDE is invalid */
2209 if (PointerPde->u.Hard.Valid == 0)
2210 {
2211 /* Right now, we only handle scenarios where the PDE is totally empty */
2212 ASSERT(PointerPde->u.Long == 0);
2213
2214 /* And go dispatch the fault on the PDE. This should handle the demand-zero */
2215#if MI_TRACE_PFNS
2216 UserPdeFault = TRUE;
2217#endif
2218 /* Check if we have a VAD, unless we did this already */
2219 if (ProtectionCode == MM_INVALID_PROTECTION)
2220 {
2221 MiCheckVirtualAddress(Address, &ProtectionCode, &Vad);
2222 }
2223
2224 if (ProtectionCode == MM_NOACCESS)
2225 {
2226#if (_MI_PAGING_LEVELS == 2)
2227 /* Could be a page table for paged pool */
2229#endif
2230 /* Has the code above changed anything -- is this now a valid PTE? */
2231 Status = (PointerPde->u.Hard.Valid == 1) ? STATUS_SUCCESS : STATUS_ACCESS_VIOLATION;
2232
2233 /* Either this was a bogus VA or we've fixed up a paged pool PDE */
2234 MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
2235 return Status;
2236 }
2237
2238 /* Resolve a demand zero fault */
2239 Status = MiResolveDemandZeroFault(PointerPte,
2240 PointerPde,
2242 CurrentProcess,
2243 MM_NOIRQL);
2244 if (!NT_SUCCESS(Status))
2245 {
2246 goto ExitUser;
2247 }
2248
2249#if _MI_PAGING_LEVELS >= 3
2251#endif
2252
2253#if MI_TRACE_PFNS
2254 UserPdeFault = FALSE;
2255 /* Update debug info */
2256 if (TrapInformation)
2257 MiGetPfnEntry(PointerPde->u.Hard.PageFrameNumber)->CallSite = (PVOID)((PKTRAP_FRAME)TrapInformation)->Eip;
2258 else
2259 MiGetPfnEntry(PointerPde->u.Hard.PageFrameNumber)->CallSite = _ReturnAddress();
2260#endif
2261 /* We should come back with APCs enabled, and with a valid PDE */
2263 ASSERT(PointerPde->u.Hard.Valid == 1);
2264 }
2265 else
2266 {
2267 /* Not yet implemented in ReactOS */
2268 ASSERT(MI_IS_PAGE_LARGE(PointerPde) == FALSE);
2269 }
2270
2271 /* Now capture the PTE. */
2272 TempPte = *PointerPte;
2273
2274 /* Check if the PTE is valid */
2275 if (TempPte.u.Hard.Valid)
2276 {
2277 /* Check if this is a write on a readonly PTE */
2278 if (MI_IS_WRITE_ACCESS(FaultCode))
2279 {
2280 /* Is this a copy on write PTE? */
2282 {
2283 PFN_NUMBER PageFrameIndex, OldPageFrameIndex;
2284 PMMPFN Pfn1;
2285
2286 LockIrql = MiAcquirePfnLock();
2287
2289
2291 MI_SET_PROCESS(CurrentProcess);
2292
2293 /* Allocate a new page and copy it */
2294 PageFrameIndex = MiRemoveAnyPage(MI_GET_NEXT_PROCESS_COLOR(CurrentProcess));
2295 if (PageFrameIndex == 0)
2296 {
2297 MiReleasePfnLock(LockIrql);
2299 goto ExitUser;
2300 }
2301 OldPageFrameIndex = PFN_FROM_PTE(&TempPte);
2302
2303 MiCopyPfn(PageFrameIndex, OldPageFrameIndex);
2304
2305 /* Dereference whatever this PTE is referencing */
2306 Pfn1 = MI_PFN_ELEMENT(OldPageFrameIndex);
2307 ASSERT(Pfn1->u3.e1.PrototypePte == 1);
2308 ASSERT(!MI_IS_PFN_DELETED(Pfn1));
2309 ProtoPte = Pfn1->PteAddress;
2310 MiDeletePte(PointerPte, Address, CurrentProcess, ProtoPte);
2311
2312 /* And make a new shiny one with our page */
2313 MiInitializePfn(PageFrameIndex, PointerPte, TRUE);
2314 TempPte.u.Hard.PageFrameNumber = PageFrameIndex;
2315 TempPte.u.Hard.Write = 1;
2316 TempPte.u.Hard.CopyOnWrite = 0;
2317
2318 MI_WRITE_VALID_PTE(PointerPte, TempPte);
2319
2320 MiReleasePfnLock(LockIrql);
2321
2322 /* Return the status */
2323 MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
2325 }
2326
2327 /* Is this a read-only PTE? */
2329 {
2330 /* Return the status */
2331 MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
2333 }
2334 }
2335
2336#if _MI_HAS_NO_EXECUTE
2337 /* Check for execution of non-executable memory */
2338 if (MI_IS_INSTRUCTION_FETCH(FaultCode) &&
2340 {
2341 /* Check if execute enable was set */
2342 if (CurrentProcess->Pcb.Flags.ExecuteEnable)
2343 {
2344 /* Fix up the PTE to be executable */
2345 TempPte.u.Hard.NoExecute = 0;
2346 MI_UPDATE_VALID_PTE(PointerPte, TempPte);
2347 MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
2348 return STATUS_SUCCESS;
2349 }
2350
2351 /* Return the status */
2352 MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
2354 }
2355#endif
2356
2357 /* The fault has already been resolved by a different thread */
2358 MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
2359 return STATUS_SUCCESS;
2360 }
2361
2362 /* Quick check for demand-zero */
2365 {
2366 /* Resolve the fault */
2368 PointerPte,
2369 TempPte.u.Soft.Protection,
2370 CurrentProcess,
2371 MM_NOIRQL);
2372 if (!NT_SUCCESS(Status))
2373 {
2374 goto ExitUser;
2375 }
2376
2377#if MI_TRACE_PFNS
2378 /* Update debug info */
2379 if (TrapInformation)
2380 MiGetPfnEntry(PointerPte->u.Hard.PageFrameNumber)->CallSite = (PVOID)((PKTRAP_FRAME)TrapInformation)->Eip;
2381 else
2382 MiGetPfnEntry(PointerPte->u.Hard.PageFrameNumber)->CallSite = _ReturnAddress();
2383#endif
2384
2385 /* Return the status */
2386 MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
2388 }
2389
2390 /* Check for zero PTE */
2391 if (TempPte.u.Long == 0)
2392 {
2393 /* Check if this address range belongs to a valid allocation (VAD) */
2394 ProtoPte = MiCheckVirtualAddress(Address, &ProtectionCode, &Vad);
2395 if (ProtectionCode == MM_NOACCESS)
2396 {
2397#if (_MI_PAGING_LEVELS == 2)
2398 /* Could be a page table for paged pool */
2400#endif
2401 /* Has the code above changed anything -- is this now a valid PTE? */
2402 Status = (PointerPte->u.Hard.Valid == 1) ? STATUS_SUCCESS : STATUS_ACCESS_VIOLATION;
2403
2404 /* Either this was a bogus VA or we've fixed up a paged pool PDE */
2405 MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
2406 return Status;
2407 }
2408
2409 /*
2410 * Check if this is a real user-mode address or actually a kernel-mode
2411 * page table for a user mode address
2412 */
2414#if _MI_PAGING_LEVELS >= 3
2416#if _MI_PAGING_LEVELS == 4
2418#endif
2419#endif
2420 )
2421 {
2422 /* Add an additional page table reference */
2424 }
2425
2426 /* Is this a guard page? */
2427 if ((ProtectionCode & MM_PROTECT_SPECIAL) == MM_GUARDPAGE)
2428 {
2429 /* The VAD protection cannot be MM_DECOMMIT! */
2430 ASSERT(ProtectionCode != MM_DECOMMIT);
2431
2432 /* Remove the bit */
2433 TempPte.u.Soft.Protection = ProtectionCode & ~MM_GUARDPAGE;
2434 MI_WRITE_INVALID_PTE(PointerPte, TempPte);
2435
2436 /* Not supported */
2437 ASSERT(ProtoPte == NULL);
2438 ASSERT(CurrentThread->ApcNeeded == 0);
2439
2440 /* Drop the working set lock */
2441 MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
2443
2444 /* Handle stack expansion */
2445 return MiCheckForUserStackOverflow(Address, TrapInformation);
2446 }
2447
2448 /* Did we get a prototype PTE back? */
2449 if (!ProtoPte)
2450 {
2451 /* Is this PTE actually part of the PDE-PTE self-mapping directory? */
2452 if (PointerPde == MiAddressToPde(PTE_BASE))
2453 {
2454 /* Then it's really a demand-zero PDE (on behalf of user-mode) */
2455#ifdef _M_ARM
2456 _WARN("This is probably completely broken!");
2458#else
2460#endif
2461 }
2462 else
2463 {
2464 /* No, create a new PTE. First, write the protection */
2465 TempPte.u.Soft.Protection = ProtectionCode;
2466 MI_WRITE_INVALID_PTE(PointerPte, TempPte);
2467 }
2468
2469 /* Lock the PFN database since we're going to grab a page */
2470 OldIrql = MiAcquirePfnLock();
2471
2472 /* Make sure we have enough pages */
2473 //ASSERT(MmAvailablePages >= 32);
2474
2475 /* Try to get a zero page */
2477 MI_SET_PROCESS2(CurrentProcess->ImageFileName);
2478 Color = MI_GET_NEXT_PROCESS_COLOR(CurrentProcess);
2479 PageFrameIndex = MiRemoveZeroPageSafe(Color);
2480 if (!PageFrameIndex)
2481 {
2482 /* Grab a page out of there. Later we should grab a colored zero page */
2483 PageFrameIndex = MiRemoveAnyPage(Color);
2484
2485 /* Release the lock since we need to do some zeroing */
2486 MiReleasePfnLock(OldIrql);
2487
2488 if (PageFrameIndex == 0)
2489 {
2491 goto ExitUser;
2492 }
2493
2494 /* Zero out the page, since it's for user-mode */
2495 MiZeroPfn(PageFrameIndex);
2496
2497 /* Grab the lock again so we can initialize the PFN entry */
2498 OldIrql = MiAcquirePfnLock();
2499 }
2500
2501 /* Initialize the PFN entry now */
2502 MiInitializePfn(PageFrameIndex, PointerPte, 1);
2503
2504 /* Increment the count of pages in the process */
2505 CurrentProcess->NumberOfPrivatePages++;
2506
2507 /* One more demand-zero fault */
2508 KeGetCurrentPrcb()->MmDemandZeroCount++;
2509
2510 /* And we're done with the lock */
2511 MiReleasePfnLock(OldIrql);
2512
2513 /* Fault on user PDE, or fault on user PTE? */
2514 if (PointerPte <= MiHighestUserPte)
2515 {
2516 /* User fault, build a user PTE */
2518 PointerPte,
2519 PointerPte->u.Soft.Protection,
2520 PageFrameIndex);
2521 }
2522 else
2523 {
2524 /* This is a user-mode PDE, create a kernel PTE for it */
2526 PointerPte,
2527 PointerPte->u.Soft.Protection,
2528 PageFrameIndex);
2529 }
2530
2531 /* Write the dirty bit for writeable pages */
2533
2534 /* And now write down the PTE, making the address valid */
2535 MI_WRITE_VALID_PTE(PointerPte, TempPte);
2536 Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
2537 ASSERT(Pfn1->u1.Event == NULL);
2538
2539 /* Demand zero */
2541 MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
2543 }
2544
2545 /* We should have a valid protection here */
2546 ASSERT(ProtectionCode != 0x100);
2547
2548 /* Write the prototype PTE */
2550 TempPte.u.Soft.Protection = ProtectionCode;
2551 ASSERT(TempPte.u.Long != 0);
2552 MI_WRITE_INVALID_PTE(PointerPte, TempPte);
2553 }
2554 else
2555 {
2556 /* Get the protection code and check if this is a proto PTE */
2557 ProtectionCode = (ULONG)TempPte.u.Soft.Protection;
2558 if (TempPte.u.Soft.Prototype)
2559 {
2560 /* Do we need to go find the real PTE? */
2561 if (TempPte.u.Soft.PageFileHigh == MI_PTE_LOOKUP_NEEDED)
2562 {
2563 /* Get the prototype pte and VAD for it */
2564 ProtoPte = MiCheckVirtualAddress(Address,
2565 &ProtectionCode,
2566 &Vad);
2567 if (!ProtoPte)
2568 {
2570 MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
2572 }
2573 }
2574 else
2575 {
2576 /* Get the prototype PTE! */
2577 ProtoPte = MiProtoPteToPte(&TempPte);
2578
2579 /* Is it read-only */
2580 if (TempPte.u.Proto.ReadOnly)
2581 {
2582 /* Set read-only code */
2583 ProtectionCode = MM_READONLY;
2584 }
2585 else
2586 {
2587 /* Set unknown protection */
2588 ProtectionCode = 0x100;
2589 ASSERT(CurrentProcess->CloneRoot != NULL);
2590 }
2591 }
2592 }
2593 }
2594
2595 /* Do we have a valid protection code? */
2596 if (ProtectionCode != 0x100)
2597 {
2598 /* Run a software access check first, including to detect guard pages */
2599 Status = MiAccessCheck(PointerPte,
2600 !MI_IS_NOT_PRESENT_FAULT(FaultCode),
2601 Mode,
2602 ProtectionCode,
2603 TrapInformation,
2604 FALSE);
2605 if (Status != STATUS_SUCCESS)
2606 {
2607 /* Not supported */
2608 ASSERT(CurrentThread->ApcNeeded == 0);
2609
2610 /* Drop the working set lock */
2611 MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
2613
2614 /* Did we hit a guard page? */
2616 {
2617 /* Handle stack expansion */
2618 return MiCheckForUserStackOverflow(Address, TrapInformation);
2619 }
2620
2621 /* Otherwise, fail back to the caller directly */
2622 return Status;
2623 }
2624 }
2625
2626 /* Dispatch the fault */
2627 Status = MiDispatchFault(FaultCode,
2628 Address,
2629 PointerPte,
2630 ProtoPte,
2631 FALSE,
2632 CurrentProcess,
2633 TrapInformation,
2634 Vad);
2635
2636ExitUser:
2637
2638 /* Return the status */
2640 MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
2641
2642 if (Status == STATUS_NO_MEMORY)
2643 {
2645 goto UserFault;
2646 }
2647
2648 return Status;
2649}
#define MM_READONLY
Definition: bootanim.c:18
#define KeRaiseIrql(irql, oldIrql)
Definition: env_spec_w32.h:597
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
#define DbgPrint
Definition: hal.h:12
_In_ ULONG Mode
Definition: hubbusif.h:303
#define MI_IS_SYSTEM_PAGE_TABLE_ADDRESS(Address)
Definition: miarm.h:194
FORCEINLINE VOID MI_MAKE_HARDWARE_PTE_USER(IN PMMPTE NewPte, IN PMMPTE MappingPte, IN ULONG_PTR ProtectionMask, IN PFN_NUMBER PageFrameNumber)
Definition: miarm.h:841
#define MI_IS_SESSION_IMAGE_ADDRESS(Address)
Definition: miarm.h:182
BOOLEAN MmProtectFreedNonPagedPool
Definition: pool.c:31
#define MM_ZERO_ACCESS
Definition: miarm.h:43
FORCEINLINE VOID MI_WRITE_INVALID_PDE(IN PMMPDE PointerPde, IN MMPDE InvalidPde)
Definition: miarm.h:1048
#define MM_PROTECT_SPECIAL
Definition: miarm.h:59
FORCEINLINE VOID MI_MAKE_HARDWARE_PTE(IN PMMPTE NewPte, IN PMMPTE MappingPte, IN ULONG_PTR ProtectionMask, IN PFN_NUMBER PageFrameNumber)
Definition: miarm.h:821
FORCEINLINE VOID MI_UPDATE_VALID_PTE(IN PMMPTE PointerPte, IN MMPTE TempPte)
Definition: miarm.h:991
VOID NTAPI MiInitializePfn(IN PFN_NUMBER PageFrameIndex, IN PMMPTE PointerPte, IN BOOLEAN Modified)
Definition: pfnlist.c:970
#define MI_IS_PAGE_TABLE_OR_HYPER_ADDRESS(Address)
Definition: miarm.h:197
FORCEINLINE USHORT MiIncrementPageTableReferences(IN PVOID Address)
Definition: miarm.h:2479
#define MI_GET_NEXT_PROCESS_COLOR(x)
Definition: miarm.h:247
FORCEINLINE PFN_NUMBER MiRemoveZeroPageSafe(IN ULONG Color)
Definition: miarm.h:2413
#define UserMode
Definition: asm.h:39
struct _EPROCESS * PEPROCESS
Definition: nt_native.h:30
#define MI_IS_PAGE_EXECUTABLE(x)
Definition: mm.h:111
#define MI_IS_PAGE_COPY_ON_WRITE(x)
Definition: mm.h:110
#define MI_IS_WRITE_ACCESS(FaultCode)
Definition: mm.h:122
#define MI_IS_PAGE_WRITEABLE(x)
Definition: mm.h:106
#define MM_PTE_SOFTWARE_PROTECTION_BITS
Definition: mm.h:75
#define MI_IS_INSTRUCTION_FETCH(FaultCode)
Definition: mm.h:125
#define MI_IS_NOT_PRESENT_FAULT(FaultCode)
Definition: mm.h:121
#define MI_IS_PAGE_LARGE(x)
Definition: mm.h:104
#define MI_MAKE_DIRTY_PAGE(x)
Definition: mm.h:98
@ MI_USAGE_COW
Definition: mm.h:354
@ MI_USAGE_PEB_TEB
Definition: mm.h:339
#define MI_SET_PROCESS(x)
Definition: mm.h:325
MMPDE DemandZeroPde
Definition: init.c:36
#define STATUS_WAIT_1
Definition: ntstatus.h:71
#define STATUS_PAGE_FAULT_COPY_ON_WRITE
Definition: ntstatus.h:96
#define STATUS_PAGE_FAULT_DEMAND_ZERO
Definition: ntstatus.h:95
#define STATUS_IN_PAGE_ERROR
Definition: ntstatus.h:243
#define STATUS_GUARD_PAGE_VIOLATION
Definition: ntstatus.h:182
VOID NTAPI MiCopyPfn(_In_ PFN_NUMBER DestPage, _In_ PFN_NUMBER SrcPage)
Definition: pagfault.c:533
static NTSTATUS NTAPI MiAccessCheck(IN PMMPTE PointerPte, IN BOOLEAN StoreInstruction, IN KPROCESSOR_MODE PreviousMode, IN ULONG_PTR ProtectionMask, IN PVOID TrapFrame, IN BOOLEAN LockHeld)
Definition: pagfault.c:172
static NTSTATUS NTAPI MiResolveDemandZeroFault(IN PVOID Address, IN PMMPTE PointerPte, IN ULONG Protection, IN PEPROCESS Process, IN KIRQL OldIrql)
Definition: pagfault.c:599
static PMMPTE NTAPI MiCheckVirtualAddress(IN PVOID VirtualAddress, OUT PULONG ProtectCode, OUT PMMVAD *ProtoVad)
Definition: pagfault.c:241
VOID NTAPI MiZeroPfn(IN PFN_NUMBER PageFrameNumber)
Definition: pagfault.c:487
VOID NTAPI MmRebalanceMemoryConsumersAndWait(VOID)
Definition: balance.c:300
#define HYDRA_PROCESS
Definition: pagfault.c:24
NTSTATUS FASTCALL MiCheckPdeForPagedPool(IN PVOID Address)
Definition: pagfault.c:479
static NTSTATUS NTAPI MiCheckForUserStackOverflow(IN PVOID Address, IN PVOID TrapInformation)
Definition: pagfault.c:34
NTSTATUS NTAPI MiDispatchFault(IN ULONG FaultCode, IN PVOID Address, IN PMMPTE PointerPte, IN PMMPTE PointerProtoPte, IN BOOLEAN Recursive, IN PEPROCESS Process, IN PVOID TrapInformation, IN PMMVAD Vad)
Definition: pagfault.c:1338
#define _WARN(msg)
Definition: debug.h:263
PFN_NUMBER NumberOfPrivatePages
Definition: pstypes.h:1301
KPROCESS Pcb
Definition: pstypes.h:1263
CHAR ImageFileName[16]
Definition: pstypes.h:1327
KTHREAD Tcb
Definition: pstypes.h:1104
UCHAR ExecuteEnable
Definition: ketypes.h:988
KEXECUTE_OPTIONS Flags
Definition: ketypes.h:2130
KAPC_STATE ApcState
Definition: ketypes.h:1778
ULONG R3
Definition: ketypes.h:370
UINT64 Rdi
Definition: ketypes.h:464
ULONG Sp
Definition: ketypes.h:372
ULONG Pc
Definition: ketypes.h:375
ULONG Edi
Definition: ketypes.h:316
UINT64 Rsi
Definition: ketypes.h:465
UINT64 Rdx
Definition: ketypes.h:414
ULONG Lr
Definition: ketypes.h:373
ULONG EFlags
Definition: ketypes.h:478
ULONG R0
Definition: ketypes.h:367
ULONG Ebx
Definition: ketypes.h:318
ULONG Ecx
Definition: ketypes.h:311
UINT64 Rbx
Definition: ketypes.h:463
ULONG Eip
Definition: ketypes.h:321
UINT64 Rax
Definition: ketypes.h:412
UINT64 Rip
Definition: ketypes.h:473
ULONG R2
Definition: ketypes.h:369
ULONG R1
Definition: ketypes.h:368
ULONG Eax
Definition: ketypes.h:312
UINT64 Rcx
Definition: ketypes.h:413
ULONG Esi
Definition: ketypes.h:317
ULONG Edx
Definition: ketypes.h:310
UINT64 R11
Definition: ketypes.h:418
ULONG R12
Definition: ketypes.h:371
PKEVENT Event
Definition: mm.h:386

Referenced by MmAccessFault().

◆ MmArmInitSystem()

BOOLEAN NTAPI MmArmInitSystem ( IN ULONG  Phase,
IN PLOADER_PARAMETER_BLOCK  LoaderBlock 
)

Definition at line 2037 of file mminit.c.

2039{
2040 ULONG i;
2041 BOOLEAN IncludeType[LoaderMaximum];
2042 PVOID Bitmap;
2044 PFN_NUMBER PageCount;
2045#if DBG
2046 ULONG j;
2047 PMMPTE PointerPte, TestPte;
2048 MMPTE TempPte;
2049#endif
2050
2051 /* Dump memory descriptors */
2053
2054 //
2055 // Instantiate memory that we don't consider RAM/usable
2056 // We use the same exclusions that Windows does, in order to try to be
2057 // compatible with WinLDR-style booting
2058 //
2059 for (i = 0; i < LoaderMaximum; i++) IncludeType[i] = TRUE;
2060 IncludeType[LoaderBad] = FALSE;
2061 IncludeType[LoaderFirmwarePermanent] = FALSE;
2062 IncludeType[LoaderSpecialMemory] = FALSE;
2063 IncludeType[LoaderBBTMemory] = FALSE;
2064 if (Phase == 0)
2065 {
2066 /* Count physical pages on the system */
2067 MiScanMemoryDescriptors(LoaderBlock);
2068
2069 /* Initialize the phase 0 temporary event */
2071
2072 /* Set all the events to use the temporary event for now */
2079
2080 //
2081 // Default throttling limits for Cc
2082 // May be ajusted later on depending on system type
2083 //
2084 MmThrottleTop = 450;
2085 MmThrottleBottom = 127;
2086
2087 //
2088 // Define the basic user vs. kernel address space separation
2089 //
2093
2094 /* Highest PTE and PDE based on the addresses above */
2097#if (_MI_PAGING_LEVELS >= 3)
2098 MiHighestUserPpe = MiAddressToPpe(MmHighestUserAddress);
2099#if (_MI_PAGING_LEVELS >= 4)
2100 MiHighestUserPxe = MiAddressToPxe(MmHighestUserAddress);
2101#endif
2102#endif
2103 //
2104 // Get the size of the boot loader's image allocations and then round
2105 // that region up to a PDE size, so that any PDEs we might create for
2106 // whatever follows are separate from the PDEs that boot loader might've
2107 // already created (and later, we can blow all that away if we want to).
2108 //
2113
2114 /* Initialize session space address layout */
2116
2117 /* Set the based section highest address */
2119
2120 /* Loop all 8 standby lists */
2121 for (i = 0; i < 8; i++)
2122 {
2123 /* Initialize them */
2128 }
2129
2130 /* Initialize the user mode image list */
2132
2133 /* Initalize the Working set list */
2135
2136 /* Initialize critical section timeout value (relative time is negative) */
2138
2139 /* Initialize the paged pool mutex and the section commit mutex */
2143
2144 /* Initialize the Loader Lock */
2146
2147 /* Set up the zero page event */
2149
2150 /* Initialize the dead stack S-LIST */
2152
2153 //
2154 // Check if this is a machine with less than 19MB of RAM
2155 //
2156 PageCount = MmNumberOfPhysicalPages;
2157 if (PageCount < MI_MIN_PAGES_FOR_SYSPTE_TUNING)
2158 {
2159 //
2160 // Use the very minimum of system PTEs
2161 //
2162 MmNumberOfSystemPtes = 7000;
2163 }
2164 else
2165 {
2166 //
2167 // Use the default
2168 //
2169 MmNumberOfSystemPtes = 11000;
2170 if (PageCount > MI_MIN_PAGES_FOR_SYSPTE_BOOST)
2171 {
2172 //
2173 // Double the amount of system PTEs
2174 //
2176 }
2178 {
2179 //
2180 // Double the amount of system PTEs
2181 //
2183 }
2184 if (MmSpecialPoolTag != 0 && MmSpecialPoolTag != -1)
2185 {
2186 //
2187 // Add some extra PTEs for special pool
2188 //
2189 MmNumberOfSystemPtes += 0x6000;
2190 }
2191 }
2192
2193 DPRINT("System PTE count has been tuned to %lu (%lu bytes)\n",
2195
2196 /* Check if no values are set for the heap limits */
2197 if (MmHeapSegmentReserve == 0)
2198 {
2200 }
2201
2202 if (MmHeapSegmentCommit == 0)
2203 {
2205 }
2206
2208 {
2210 }
2211
2213 {
2215 }
2216
2217 /* Initialize the working set lock */
2219
2220 /* Set commit limit */
2223
2224 /* Has the allocation fragment been setup? */
2226 {
2227 /* Use the default value */
2229 if (PageCount < ((256 * _1MB) / PAGE_SIZE))
2230 {
2231 /* On memory systems with less than 256MB, divide by 4 */
2233 }
2234 else if (PageCount < (_1GB / PAGE_SIZE))
2235 {
2236 /* On systems with less than 1GB, divide by 2 */
2238 }
2239 }
2240 else
2241 {
2242 /* Convert from 1KB fragments to pages */
2245
2246 /* Don't let it past the maximum */
2249
2250 /* Don't let it too small either */
2253 }
2254
2255 /* Check for kernel stack size that's too big */
2257 {
2258 /* Sanitize to default value */
2260 }
2261 else
2262 {
2263 /* Take the registry setting, and convert it into bytes */
2265
2266 /* Now align it to a page boundary */
2268
2269 /* Sanity checks */
2271 ASSERT((MmLargeStackSize & (PAGE_SIZE - 1)) == 0);
2272
2273 /* Make sure it's not too low */
2275 }
2276
2277 /* Compute color information (L2 cache-separated paging lists) */
2279
2280 // Calculate the number of bytes for the PFN database
2281 // then add the color tables and convert to pages
2285
2286 // We have to add one to the count here, because in the process of
2287 // shifting down to the page size, we actually ended up getting the
2288 // lower aligned size (so say, 0x5FFFF bytes is now 0x5F pages).
2289 // Later on, we'll shift this number back into bytes, which would cause
2290 // us to end up with only 0x5F000 bytes -- when we actually want to have
2291 // 0x60000 bytes.
2293
2294 /* Initialize the platform-specific parts */
2295 MiInitMachineDependent(LoaderBlock);
2296
2297#if DBG
2298 /* Prototype PTEs are assumed to be in paged pool, so check if the math works */
2299 PointerPte = (PMMPTE)MmPagedPoolStart;
2300 MI_MAKE_PROTOTYPE_PTE(&TempPte, PointerPte);
2301 TestPte = MiProtoPteToPte(&TempPte);
2302 ASSERT(PointerPte == TestPte);
2303
2304 /* Try the last nonpaged pool address */
2305 PointerPte = (PMMPTE)MI_NONPAGED_POOL_END;
2306 MI_MAKE_PROTOTYPE_PTE(&TempPte, PointerPte);
2307 TestPte = MiProtoPteToPte(&TempPte);
2308 ASSERT(PointerPte == TestPte);
2309
2310 /* Try a bunch of random addresses near the end of the address space */
2311 PointerPte = (PMMPTE)((ULONG_PTR)MI_HIGHEST_SYSTEM_ADDRESS - 0x37FFF);
2312 for (j = 0; j < 20; j += 1)
2313 {
2314 MI_MAKE_PROTOTYPE_PTE(&TempPte, PointerPte);
2315 TestPte = MiProtoPteToPte(&TempPte);
2316 ASSERT(PointerPte == TestPte);
2317 PointerPte++;
2318 }
2319
2320 /* Subsection PTEs are always in nonpaged pool, pick a random address to try */
2322 MI_MAKE_SUBSECTION_PTE(&TempPte, PointerPte);
2324 ASSERT(PointerPte == TestPte);
2325#endif
2326
2327 //
2328 // Build the physical memory block
2329 //
2331 IncludeType);
2332
2333 //
2334 // Allocate enough buffer for the PFN bitmap
2335 // Align it up to a 32-bit boundary
2336 //
2338 (((MmHighestPhysicalPage + 1) + 31) / 32) * 4,
2339 TAG_MM);
2340 if (!Bitmap)
2341 {
2342 //
2343 // This is critical
2344 //
2345 KeBugCheckEx(INSTALL_MORE_MEMORY,
2349 0x101);
2350 }
2351
2352 //
2353 // Initialize it and clear all the bits to begin with
2354 //
2356 Bitmap,
2359
2360 //
2361 // Loop physical memory runs
2362 //
2363 for (i = 0; i < MmPhysicalMemoryBlock->NumberOfRuns; i++)
2364 {
2365 //
2366 // Get the run
2367 //
2369 DPRINT("PHYSICAL RAM [0x%08p to 0x%08p]\n",
2370 Run->BasePage << PAGE_SHIFT,
2371 (Run->BasePage + Run->PageCount) << PAGE_SHIFT);
2372
2373 //
2374 // Make sure it has pages inside it
2375 //
2376 if (Run->PageCount)
2377 {
2378 //
2379 // Set the bits in the PFN bitmap
2380 //
2381 RtlSetBits(&MiPfnBitMap, (ULONG)Run->BasePage, (ULONG)Run->PageCount);
2382 }
2383 }
2384
2385 /* Look for large page cache entries that need caching */
2387
2388 /* Loop for HAL Heap I/O device mappings that need coherency tracking */
2390
2391 /* Set the initial resident page count */
2393
2394 /* Initialize large page structures on PAE/x64, and MmProcessList on x86 */
2396
2397 /* Check if the registry says any drivers should be loaded with large pages */
2399
2400 /* Relocate the boot drivers into system PTE space and fixup their PFNs */
2401 MiReloadBootLoadedDrivers(LoaderBlock);
2402
2403 /* FIXME: Call out into Driver Verifier for initialization */
2404
2405 /* Check how many pages the system has */
2406 if (MmNumberOfPhysicalPages <= ((13 * _1MB) / PAGE_SIZE))
2407 {
2408 /* Set small system */
2411 }
2412 else if (MmNumberOfPhysicalPages <= ((19 * _1MB) / PAGE_SIZE))
2413 {
2414 /* Set small system and add 100 pages for the cache */
2418 }
2419 else
2420 {
2421 /* Set medium system and add 400 pages for the cache */
2425 }
2426
2427 /* Check for less than 24MB */
2428 if (MmNumberOfPhysicalPages < ((24 * _1MB) / PAGE_SIZE))
2429 {
2430 /* No more than 32 pages */
2432 }
2433
2434 /* Check for more than 32MB */
2435 if (MmNumberOfPhysicalPages >= ((32 * _1MB) / PAGE_SIZE))
2436 {
2437 /* Check for product type being "Wi" for WinNT */
2438 if (MmProductType == '\0i\0W')
2439 {
2440 /* Then this is a large system */
2442 }
2443 else
2444 {
2445 /* For servers, we need 64MB to consider this as being large */
2446 if (MmNumberOfPhysicalPages >= ((64 * _1MB) / PAGE_SIZE))
2447 {
2448 /* Set it as large */
2450 }
2451 }
2452 }
2453
2454 /* Check for more than 33 MB */
2455 if (MmNumberOfPhysicalPages > ((33 * _1MB) / PAGE_SIZE))
2456 {
2457 /* Add another 500 pages to the cache */
2459 }
2460
2461 /* Now setup the shared user data fields */
2462 ASSERT(SharedUserData->NumberOfPhysicalPages == 0);
2463 SharedUserData->NumberOfPhysicalPages = MmNumberOfPhysicalPages;
2464 SharedUserData->LargePageMinimum = 0;
2465
2466 /* Check for workstation (Wi for WinNT) */
2467 if (MmProductType == '\0i\0W')
2468 {
2469 /* Set Windows NT Workstation product type */
2470 SharedUserData->NtProductType = NtProductWinNt;
2471 MmProductType = 0;
2472
2473 /* For this product, we wait till the last moment to throttle */
2474 MmThrottleTop = 250;
2475 MmThrottleBottom = 30;
2476 }
2477 else
2478 {
2479 /* Check for LanMan server (La for LanmanNT) */
2480 if (MmProductType == '\0a\0L')
2481 {
2482 /* This is a domain controller */
2483 SharedUserData->NtProductType = NtProductLanManNt;
2484 }
2485 else
2486 {
2487 /* Otherwise it must be a normal server (Se for ServerNT) */
2488 SharedUserData->NtProductType = NtProductServer;
2489 }
2490
2491 /* Set the product type, and make the system more aggressive with low memory */
2492 MmProductType = 1;
2493 MmMinimumFreePages = 81;
2494
2495 /* We will throttle earlier to preserve memory */
2496 MmThrottleTop = 450;
2497 MmThrottleBottom = 80;
2498 }
2499
2500 /* Update working set tuning parameters */
2502
2503 /* Finetune the page count by removing working set and NP expansion */
2507 if (MmResidentAvailablePages <= 0)
2508 {
2509 /* This should not happen */
2510 DPRINT1("System cache working set too big\n");
2511 return FALSE;
2512 }
2513
2514 /* Define limits for system cache */
2515#ifdef _M_AMD64
2517#else
2519#endif
2521#ifdef _M_AMD64
2523#else
2525#endif
2526
2527 /* Initialize the system cache */
2528 //MiInitializeSystemCache(MmSystemCacheWsMinimum, MmAvailablePages);
2529
2530 /* Update the commit limit */
2532 if (MmTotalCommitLimit > 1024) MmTotalCommitLimit -= 1024;
2534
2535 /* Size up paged pool and build the shadow system page directory */
2537
2538 /* Debugger physical memory support is now ready to be used */
2540
2541 /* Initialize the loaded module list */
2542 MiInitializeLoadedModuleList(LoaderBlock);
2543 }
2544
2545 //
2546 // Always return success for now
2547 //
2548 return TRUE;
2549}
SIZE_T MmHeapSegmentReserve
Definition: mminit.c:366
PMMPTE MiHighestUserPte
Definition: mminit.c:233
PFN_NUMBER MmSystemCacheWsMinimum
Definition: mminit.c:336
SIZE_T MmHeapDeCommitFreeBlockThreshold
Definition: mminit.c:369
SIZE_T MmTotalCommitLimitMaximum
Definition: mminit.c:360
PVOID MmPagedPoolStart
Definition: mminit.c:104
SIZE_T MmTotalCommitLimit
Definition: mminit.c:359
MM_SYSTEMSIZE MmSystemSize
Definition: mminit.c:326
SIZE_T MmBootImageSize
Definition: mminit.c:222
PVOID MmSystemRangeStart
Definition: mminit.c:230
PMMPDE MiHighestUserPde
Definition: mminit.c:234
SIZE_T MmHeapDeCommitTotalFreeThreshold
Definition: mminit.c:368
ULONG MmThrottleTop
Definition: mminit.c:396
PFN_NUMBER MmMinimumFreePages
Definition: mminit.c:314
SIZE_T MmSizeOfNonPagedPoolInBytes
Definition: mminit.c:26
KEVENT MiTempEvent
Definition: mminit.c:289
VOID NTAPI MiAdjustWorkingSetManagerParameters(IN BOOLEAN Client)
Definition: mminit.c:1194
VOID NTAPI MiBuildPagedPool(VOID)
Definition: mminit.c:1742
VOID NTAPI MiScanMemoryDescriptors(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: mminit.c:403
VOID NTAPI MiAddHalIoMappings(VOID)
Definition: mminit.c:1409
VOID NTAPI MiDbgDumpMemoryDescriptors(VOID)
Definition: mminit.c:1985
PFN_NUMBER MmLowestPhysicalPage
Definition: mminit.c:211
ULONG MmProductType
Definition: mminit.c:325
PPHYSICAL_MEMORY_DESCRIPTOR NTAPI MmInitializeMemoryLimits(IN PLOADER_PARAMETER_BLOCK LoaderBlock, IN PBOOLEAN IncludeType)
Definition: mminit.c:1613
ULONG_PTR MmSizeOfSystemCacheInPages
Definition: mminit.c:245
ULONG_PTR MmUserProbeAddress
Definition: mminit.c:228
RTL_BITMAP MiPfnBitMap
Definition: mminit.c:201
MMSUPPORT MmSystemCacheWs
Definition: mminit.c:246
ULONG MmLargeStackSize
Definition: mminit.c:262
VOID NTAPI MiComputeColorInformation(VOID)
Definition: mminit.c:499
PFN_NUMBER MxPfnAllocation
Definition: mminit.c:187
ULONG MmThrottleBottom
Definition: mminit.c:397
PVOID MmNonPagedPoolStart
Definition: mminit.c:97
BOOLEAN MiDbgEnableMdDump
Definition: mminit.c:373
SIZE_T MmHeapSegmentCommit
Definition: mminit.c:367
SIZE_T MmAllocationFragment
Definition: mminit.c:352
LARGE_INTEGER MmCriticalSectionTimeout
Definition: mminit.c:388
PFN_COUNT MmNumberOfSystemPtes
Definition: mminit.c:181
PPHYSICAL_MEMORY_DESCRIPTOR MmPhysicalMemoryBlock
Definition: mminit.c:206
PVOID MmSystemCacheStart
Definition: mminit.c:243
PVOID MmSystemCacheEnd
Definition: mminit.c:244
PVOID MmHighestUserAddress
Definition: mminit.c:229
ULONG MmCritsectTimeoutSeconds
Definition: mminit.c:387
#define RtlSetBits
Definition: dbgbitmap.h:345
@ NtProductWinNt
Definition: shellpath.c:64
@ NtProductLanManNt
Definition: shellpath.c:65
@ NtProductServer
Definition: shellpath.c:66
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define ExInitializePushLock
Definition: ex.h:1016
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
PLOADER_PARAMETER_BLOCK KeLoaderBlock
Definition: krnlinit.c:28
VOID NTAPI MiInitializeDriverLargePageList(VOID)
Definition: largepag.c:68
VOID NTAPI MiInitializeLargePageSupport(VOID)
Definition: largepag.c:34
VOID NTAPI MiSyncCachedRanges(VOID)
Definition: largepag.c:54
PFN_COUNT MiExpansionPoolPagesInitialCharge
Definition: pool.c:21
KGUARDED_MUTEX MmSectionBasedMutex
Definition: section.c:110
SLIST_HEADER MmDeadStackSListHead
Definition: procsup.c:22
#define _1GB
Definition: miarm.h:20
struct _MMCOLOR_TABLES MMCOLOR_TABLES
KGUARDED_MUTEX MmPagedPoolMutex
Definition: pool.c:24
PFN_NUMBER MmResidentAvailableAtInit
Definition: freelist.c:28
MMPFNLIST MmStandbyPageListByPriority[8]
Definition: pfnlist.c:44
PVOID MmHighSectionBase
Definition: section.c:111
ULONG MmSpecialPoolTag
Definition: pool.c:29
KGUARDED_MUTEX MmSectionCommitMutex
Definition: section.c:108
LIST_ENTRY MmWorkingSetExpansionHead
Definition: session.c:30
#define _1KB
Definition: miarm.h:18
ULONG MmMaximumDeadKernelStacks
Definition: procsup.c:21
struct _MMPTE * PMMPTE
#define MI_HIGHEST_USER_ADDRESS
Definition: mmtypes.h:43
@ NotificationEvent
#define MI_ALLOCATION_FRAGMENT
Definition: mm.h:71
#define MI_PAGED_POOL_START
Definition: mm.h:21
#define MI_USER_PROBE_ADDRESS
Definition: mm.h:10
#define MI_DEFAULT_SYSTEM_RANGE_START
Definition: mm.h:11
#define MiSubsectionPteToSubsection(x)
Definition: mm.h:323
FORCEINLINE VOID MI_MAKE_PROTOTYPE_PTE(IN PMMPTE NewPte, IN PMMPTE PointerPte)
Definition: mm.h:342
#define MI_MIN_PAGES_FOR_SYSPTE_BOOST
Definition: mm.h:56
#define MM_EMPTY_LIST
Definition: mm.h:88
#define MI_MIN_PAGES_FOR_SYSPTE_TUNING
Definition: mm.h:55
#define MI_HIGHEST_SYSTEM_ADDRESS
Definition: mm.h:31
#define MI_NONPAGED_POOL_END
Definition: mm.h:29
#define MI_MIN_ALLOCATION_FRAGMENT
Definition: mm.h:70
#define MI_SYSTEM_CACHE_END
Definition: mm.h:27
#define MI_MIN_PAGES_FOR_SYSPTE_BOOST_BOOST
Definition: mm.h:57
FORCEINLINE VOID MI_MAKE_SUBSECTION_PTE(_Out_ PMMPTE NewPte, _In_ PVOID Segment)
Definition: mm.h:328
#define MI_SYSTEM_CACHE_START
Definition: mm.h:26
#define MI_MAX_ALLOCATION_FRAGMENT
Definition: mm.h:72
PFN_NUMBER MmResidentAvailablePages
Definition: freelist.c:27
BOOLEAN NTAPI MiInitializeLoadedModuleList(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: sysldr.c:2242
PMMPTE MmDebugPte
Definition: mmdbg.c:31
LIST_ENTRY MmLoadedUserImageList
Definition: sysldr.c:22
VOID NTAPI MiReloadBootLoadedDrivers(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: sysldr.c:1731
PVOID MiDebugMapping
Definition: mmdbg.c:30
KMUTANT MmSystemLoadLock
Definition: sysldr.c:26
VOID NTAPI KeInitializeMutant(IN PKMUTANT Mutant, IN BOOLEAN InitialOwner)
Definition: mutex.c:22
VOID NTAPI MiInitializeSessionSpaceLayout(VOID)
Definition: init.c:63
NTSTATUS NTAPI MiInitMachineDependent(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: init.c:697
@ LoaderBad
Definition: arc.h:177
@ LoaderMaximum
Definition: arc.h:203
#define KERNEL_LARGE_STACK_SIZE
#define KERNEL_STACK_SIZE
#define SharedUserData
PLOADER_PARAMETER_EXTENSION Extension
Definition: arc.h:559
ULONG_PTR LoaderPagesSpanned
Definition: arc.h:403
EX_PUSH_LOCK WorkingSetMutex
Definition: mmtypes.h:961
Definition: bidi.c:434
struct tagRun Run
@ MmLargeSystem
Definition: mmtypes.h:147
@ MmMediumSystem
Definition: mmtypes.h:146
@ MmSmallSystem
Definition: mmtypes.h:145
FORCEINLINE VOID InitializeSListHead(_Out_ PSLIST_HEADER SListHead)
Definition: rtlfuncs.h:3368

◆ MmInitializeMemoryLimits()

PPHYSICAL_MEMORY_DESCRIPTOR NTAPI MmInitializeMemoryLimits ( IN PLOADER_PARAMETER_BLOCK  LoaderBlock,
IN PBOOLEAN  IncludeType 
)

Definition at line 1613 of file mminit.c.

1615{
1616 PLIST_ENTRY NextEntry;
1617 ULONG Run = 0, InitialRuns;
1618 PFN_NUMBER NextPage = -1, PageCount = 0;
1621
1622 //
1623 // Start with the maximum we might need
1624 //
1625 InitialRuns = MiNumberDescriptors;
1626
1627 //
1628 // Allocate the maximum we'll ever need
1629 //
1632 sizeof(PHYSICAL_MEMORY_RUN) *
1633 (InitialRuns - 1),
1634 'lMmM');
1635 if (!Buffer) return NULL;
1636
1637 //
1638 // For now that's how many runs we have
1639 //
1640 Buffer->NumberOfRuns = InitialRuns;
1641
1642 //
1643 // Now loop through the descriptors again
1644 //
1645 NextEntry = LoaderBlock->MemoryDescriptorListHead.Flink;
1646 while (NextEntry != &LoaderBlock->MemoryDescriptorListHead)
1647 {
1648 //
1649 // Grab each one, and check if it's one we should include
1650 //
1651 MdBlock = CONTAINING_RECORD(NextEntry,
1653 ListEntry);
1654 if ((MdBlock->MemoryType < LoaderMaximum) &&
1655 (IncludeType[MdBlock->MemoryType]))
1656 {
1657 //
1658 // Add this to our running total
1659 //
1660 PageCount += MdBlock->PageCount;
1661
1662 //
1663 // Check if the next page is described by the next descriptor
1664 //
1665 if (MdBlock->BasePage == NextPage)
1666 {
1667 //
1668 // Combine it into the same physical run
1669 //
1670 ASSERT(MdBlock->PageCount != 0);
1671 Buffer->Run[Run - 1].PageCount += MdBlock->PageCount;
1672 NextPage += MdBlock->PageCount;
1673 }
1674 else
1675 {
1676 //
1677 // Otherwise just duplicate the descriptor's contents
1678 //
1679 Buffer->Run[Run].BasePage = MdBlock->BasePage;
1680 Buffer->Run[Run].PageCount = MdBlock->PageCount;
1681 NextPage = Buffer->Run[Run].BasePage + Buffer->Run[Run].PageCount;
1682
1683 //
1684 // And in this case, increase the number of runs
1685 //
1686 Run++;
1687 }
1688 }
1689
1690 //
1691 // Try the next descriptor
1692 //
1693 NextEntry = MdBlock->ListEntry.Flink;
1694 }
1695
1696 //
1697 // We should not have been able to go past our initial estimate
1698 //
1699 ASSERT(Run <= Buffer->NumberOfRuns);
1700
1701 //
1702 // Our guess was probably exaggerated...
1703 //
1704 if (InitialRuns > Run)
1705 {
1706 //
1707 // Allocate a more accurately sized buffer
1708 //
1711 sizeof(PHYSICAL_MEMORY_RUN) *
1712 (Run - 1),
1713 'lMmM');
1714 if (NewBuffer)
1715 {
1716 //
1717 // Copy the old buffer into the new, then free it
1718 //
1719 RtlCopyMemory(NewBuffer->Run,
1720 Buffer->Run,
1721 sizeof(PHYSICAL_MEMORY_RUN) * Run);
1722 ExFreePoolWithTag(Buffer, 'lMmM');
1723
1724 //
1725 // Now use the new buffer
1726 //
1727 Buffer = NewBuffer;
1728 }
1729 }
1730
1731 //
1732 // Write the final numbers, and return it
1733 //
1734 Buffer->NumberOfRuns = Run;
1735 Buffer->NumberOfPages = PageCount;
1736 return Buffer;
1737}
ULONG MiNumberDescriptors
Definition: mminit.c:381
Definition: bufpool.h:45
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263

Referenced by MmArmInitSystem().

◆ MxGetNextPage()

PFN_NUMBER NTAPI MxGetNextPage ( IN PFN_NUMBER  PageCount)

Definition at line 474 of file mminit.c.

475{
476 PFN_NUMBER Pfn;
477
478 /* Make sure we have enough pages */
479 if (PageCount > MxFreeDescriptor->PageCount)
480 {
481 /* Crash the system */
482 KeBugCheckEx(INSTALL_MORE_MEMORY,
486 PageCount);
487 }
488
489 /* Use our lowest usable free pages */
491 MxFreeDescriptor->BasePage += PageCount;
492 MxFreeDescriptor->PageCount -= PageCount;
493 return Pfn;
494}

Referenced by MiInitializeColorTables(), MiInitializePageTable(), MiInitMachineDependent(), MiMapPDEs(), MiMapPPEs(), and MiMapPTEs().

Variable Documentation

◆ DemandZeroPde

MMPDE DemandZeroPde
extern

Definition at line 36 of file init.c.

Referenced by MmArmAccessFault().

◆ DemandZeroPte

MMPTE DemandZeroPte
extern

Definition at line 37 of file init.c.

Referenced by MiInitializePfnAndMakePteValid(), and MiQueryAddressState().

◆ ExpNumberOfPagedPools

ULONG ExpNumberOfPagedPools
extern

Definition at line 41 of file expool.c.

Referenced by ExQueryPoolUsage().

◆ ExpPagedPoolDescriptor

PPOOL_DESCRIPTOR ExpPagedPoolDescriptor[16+1]
extern

Definition at line 43 of file expool.c.

Referenced by ExQueryPoolUsage(), and InitializePool().

◆ HyperTemplatePte

MMPTE HyperTemplatePte
extern

Definition at line 22 of file hypermap.c.

Referenced by MiInitializePageTable().

◆ MiExpansionLockOwner

PETHREAD MiExpansionLockOwner
extern

Definition at line 33 of file session.c.

Referenced by MiAcquireExpansionLock(), and MiReleaseExpansionLock().

◆ MiExpansionPoolPagesInitialCharge

PFN_COUNT MiExpansionPoolPagesInitialCharge
extern

Definition at line 21 of file pool.c.

Referenced by MiInitializeNonPagedPool(), and MmArmInitSystem().

◆ MiFirstReservedZeroingPte

PMMPTE MiFirstReservedZeroingPte
extern

Definition at line 21 of file hypermap.c.

Referenced by MiBuildSystemPteSpace(), MiInitMachineDependent(), and MiMapPagesInZeroSpace().

◆ MiHighestUserPde

PMMPDE MiHighestUserPde
extern

Definition at line 234 of file mminit.c.

Referenced by MiIsUserPde(), and MmArmInitSystem().

◆ MiHighestUserPte

◆ MiHighMemoryEvent

◆ MiHighNonPagedPoolEvent

PKEVENT MiHighNonPagedPoolEvent
extern

Definition at line 297 of file mminit.c.

Referenced by MiInitializeMemoryEvents(), MiInitializePoolEvents(), and MmArmInitSystem().

◆ MiHighNonPagedPoolThreshold

PFN_NUMBER MiHighNonPagedPoolThreshold
extern

Definition at line 305 of file mminit.c.

Referenced by MiInitializeNonPagedPoolThresholds(), and MiInitializePoolEvents().

◆ MiHighPagedPoolEvent

PKEVENT MiHighPagedPoolEvent
extern

Definition at line 295 of file mminit.c.

Referenced by MiInitializeMemoryEvents(), MiInitializePoolEvents(), and MmArmInitSystem().

◆ MiHighPagedPoolThreshold

PFN_NUMBER MiHighPagedPoolThreshold
extern

Definition at line 303 of file mminit.c.

Referenced by MiBuildPagedPool(), and MiInitializePoolEvents().

◆ MiLargePageAllDrivers

BOOLEAN MiLargePageAllDrivers
extern

Definition at line 27 of file largepag.c.

Referenced by MiInitializeDriverLargePageList(), and MiUseLargeDriverPage().

◆ MiLargePageDriverList

LIST_ENTRY MiLargePageDriverList
extern

Definition at line 26 of file largepag.c.

Referenced by MiInitializeDriverLargePageList(), and MiUseLargeDriverPage().

◆ MiLowMemoryEvent

◆ MiLowNonPagedPoolEvent

PKEVENT MiLowNonPagedPoolEvent
extern

Definition at line 296 of file mminit.c.

Referenced by MiInitializeMemoryEvents(), MiInitializePoolEvents(), and MmArmInitSystem().

◆ MiLowNonPagedPoolThreshold

PFN_NUMBER MiLowNonPagedPoolThreshold
extern

Definition at line 304 of file mminit.c.

Referenced by MiInitializeNonPagedPoolThresholds(), and MiInitializePoolEvents().

◆ MiLowPagedPoolEvent

PKEVENT MiLowPagedPoolEvent
extern

Definition at line 294 of file mminit.c.

Referenced by MiInitializeMemoryEvents(), MiInitializePoolEvents(), and MmArmInitSystem().

◆ MiLowPagedPoolThreshold

PFN_NUMBER MiLowPagedPoolThreshold
extern

Definition at line 302 of file mminit.c.

Referenced by MiBuildPagedPool(), and MiInitializePoolEvents().

◆ MiNumberOfFreePages

PFN_NUMBER MiNumberOfFreePages
extern

Definition at line 384 of file mminit.c.

Referenced by MiInitMachineDependent(), and MiScanMemoryDescriptors().

◆ MiPlatformCacheAttributes

◆ MiSessionBasePte

PMMPTE MiSessionBasePte
extern

Definition at line 145 of file mminit.c.

Referenced by MiInitializeSessionSpaceLayout().

◆ MiSessionImageEnd

PVOID MiSessionImageEnd
extern

Definition at line 28 of file init.c.

Referenced by MiInitializeSessionSpaceLayout().

◆ MiSessionImagePteEnd

PMMPTE MiSessionImagePteEnd
extern

Definition at line 144 of file mminit.c.

Referenced by MiInitializeSessionSpaceLayout().

◆ MiSessionImagePteStart

PMMPTE MiSessionImagePteStart
extern

Definition at line 143 of file mminit.c.

Referenced by MiInitializeSessionSpaceLayout().

◆ MiSessionImageStart

PVOID MiSessionImageStart
extern

Definition at line 29 of file init.c.

Referenced by MiInitializeSessionSpaceLayout().

◆ MiSessionLastPte

PMMPTE MiSessionLastPte
extern

Definition at line 146 of file mminit.c.

Referenced by MiInitializeSessionSpaceLayout().

◆ MiSessionPoolEnd

PVOID MiSessionPoolEnd
extern

Definition at line 31 of file init.c.

Referenced by MiInitializeSessionPool(), and MiInitializeSessionSpaceLayout().

◆ MiSessionPoolStart

PVOID MiSessionPoolStart
extern

Definition at line 32 of file init.c.

Referenced by MiInitializeSessionPool(), and MiInitializeSessionSpaceLayout().

◆ MiSessionSpaceEnd

PVOID MiSessionSpaceEnd
extern

◆ MiSessionSpaceWs

PVOID MiSessionSpaceWs
extern

◆ MiSessionViewStart

PVOID MiSessionViewStart
extern

◆ MiSystemViewStart

◆ MmAllocatedNonPagedPool

SIZE_T MmAllocatedNonPagedPool
extern

Definition at line 26 of file pool.c.

Referenced by _Requires_lock_held_(), and MiInitializePoolEvents().

◆ MmAllocationFragment

SIZE_T MmAllocationFragment
extern

Definition at line 352 of file mminit.c.

Referenced by MmArmInitSystem().

◆ MmBootImageSize

SIZE_T MmBootImageSize
extern

◆ MmConsumedPoolPercentage

ULONG MmConsumedPoolPercentage
extern

Definition at line 30 of file pool.c.

◆ MmCriticalSectionTimeout

LARGE_INTEGER MmCriticalSectionTimeout
extern

Definition at line 388 of file mminit.c.

Referenced by MmArmInitSystem(), and MmCreatePeb().

◆ MmCritsectTimeoutSeconds

ULONG MmCritsectTimeoutSeconds
extern

Definition at line 387 of file mminit.c.

Referenced by MmArmInitSystem().

◆ MmDeadStackSListHead

SLIST_HEADER MmDeadStackSListHead
extern

Definition at line 22 of file procsup.c.

Referenced by MmArmInitSystem(), MmCreateKernelStack(), and MmDeleteKernelStack().

◆ MmDecommittedPte

MMPTE MmDecommittedPte
extern

◆ MmDefaultMaximumNonPagedPool

SIZE_T MmDefaultMaximumNonPagedPool
extern

Definition at line 41 of file mminit.c.

Referenced by MiBuildNonPagedPool(), and MiComputeNonPagedPoolVa().

◆ MmDynamicPfn

BOOLEAN MmDynamicPfn
extern

Definition at line 34 of file pfnlist.c.

◆ MmEnforceWriteProtection

BOOLEAN MmEnforceWriteProtection
extern

Definition at line 34 of file sysldr.c.

Referenced by MiWriteProtectSystemImage().

◆ MmExpansionLock

KSPIN_LOCK MmExpansionLock
extern

◆ MmFirstReservedMappingPte

PMMPTE MmFirstReservedMappingPte
extern

Definition at line 20 of file hypermap.c.

Referenced by MiInitializePageTable(), MiInitMachineDependent(), and MiMapPageInHyperSpace().

◆ MmFreePagesByColor

◆ MmHighMemoryThreshold

PFN_NUMBER MmHighMemoryThreshold
extern

◆ MmHighSectionBase

PVOID MmHighSectionBase
extern

Definition at line 111 of file section.c.

Referenced by MmArmInitSystem(), and MmCreateArm3Section().

◆ MmHyperSpaceEnd

PVOID MmHyperSpaceEnd
extern

◆ MmLargePageDriverBuffer

WCHAR MmLargePageDriverBuffer[512]
extern

Definition at line 24 of file largepag.c.

Referenced by MiInitializeDriverLargePageList().

◆ MmLargePageDriverBufferLength

ULONG MmLargePageDriverBufferLength
extern

Definition at line 25 of file largepag.c.

Referenced by MiInitializeDriverLargePageList().

◆ MmLargeStackSize

ULONG MmLargeStackSize
extern

◆ MmLargeSystemCache

BOOLEAN MmLargeSystemCache
extern

Definition at line 340 of file mminit.c.

◆ MmLastReservedMappingPte

PMMPTE MmLastReservedMappingPte

Definition at line 575 of file miarm.h.

◆ MmLowMemoryThreshold

PFN_NUMBER MmLowMemoryThreshold
extern

◆ MmMakeLowMemory

BOOLEAN MmMakeLowMemory
extern

Definition at line 33 of file sysldr.c.

◆ MmMaxAdditionNonPagedPoolPerMb

ULONG MmMaxAdditionNonPagedPoolPerMb
extern

Definition at line 42 of file mminit.c.

Referenced by MiBuildNonPagedPool(), and MiComputeNonPagedPoolVa().

◆ MmMaximumDeadKernelStacks

ULONG MmMaximumDeadKernelStacks
extern

Definition at line 21 of file procsup.c.

Referenced by MmArmInitSystem(), and MmDeleteKernelStack().

◆ MmMaximumNonPagedPoolInBytes

SIZE_T MmMaximumNonPagedPoolInBytes
extern

◆ MmMaximumNonPagedPoolInPages

◆ MmMaximumNonPagedPoolPercent

ULONG MmMaximumNonPagedPoolPercent
extern

Definition at line 20 of file init.c.

Referenced by MiBuildNonPagedPool(), and MiComputeNonPagedPoolVa().

◆ MmMinAdditionNonPagedPoolPerMb

ULONG MmMinAdditionNonPagedPoolPerMb
extern

Definition at line 40 of file mminit.c.

Referenced by MiBuildNonPagedPool(), and MiComputeNonPagedPoolVa().

◆ MmMinimumFreePages

PFN_NUMBER MmMinimumFreePages
extern

Definition at line 314 of file mminit.c.

Referenced by MiDecrementAvailablePages(), MmArmInitSystem(), and MmWorkingSetManager().

◆ MmMinimumNonPagedPoolSize

SIZE_T MmMinimumNonPagedPoolSize
extern

Definition at line 39 of file mminit.c.

Referenced by MiBuildNonPagedPool(), and MiComputeNonPagedPoolVa().

◆ MmMinimumStackCommitInBytes

SIZE_T MmMinimumStackCommitInBytes
extern

Definition at line 370 of file mminit.c.

Referenced by MmCreatePeb().

◆ MmMirroring

BOOLEAN MmMirroring
extern

Definition at line 35 of file pfnlist.c.

◆ MmNonPagedPoolEnd

◆ MmNonPagedPoolExpansionStart

◆ MmNonPagedPoolStart

◆ MmNonPagedSystemStart

PVOID MmNonPagedSystemStart
extern

◆ MmNumberOfSystemPtes

ULONG MmNumberOfSystemPtes
extern

◆ MmPagedPoolEnd

◆ MmPagedPoolInfo

◆ MmPagedPoolMutex

KGUARDED_MUTEX MmPagedPoolMutex
extern

◆ MmPagedPoolStart

◆ MmPhysicalMemoryBlock

PPHYSICAL_MEMORY_DESCRIPTOR MmPhysicalMemoryBlock
extern

Definition at line 45 of file init.c.

Referenced by MiFindContiguousPages(), MmArmInitSystem(), and MmGetPhysicalMemoryRanges().

◆ MmPlentyFreePages

PFN_NUMBER MmPlentyFreePages
extern

◆ MmProcessColorSeed

ULONG MmProcessColorSeed
extern

Definition at line 20 of file procsup.c.

Referenced by MmCreateProcessAddressSpace().

◆ MmProcessList

LIST_ENTRY MmProcessList
extern

Definition at line 20 of file largepag.c.

Referenced by MiArchCreateProcessAddressSpace(), and MiInitializeLargePageSupport().

◆ MmProductType

ULONG MmProductType
extern

Definition at line 325 of file mminit.c.

Referenced by MmArmInitSystem().

◆ MmProtectFreedNonPagedPool

BOOLEAN MmProtectFreedNonPagedPool
extern

◆ MmProtectToPteMask

◆ MmProtectToValue

◆ MmResidentAvailableAtInit

PFN_NUMBER MmResidentAvailableAtInit
extern

Definition at line 28 of file freelist.c.

Referenced by MmArmInitSystem().

◆ MmSecondaryColorMask

◆ MmSecondaryColors

◆ MmSectionBasedMutex

KGUARDED_MUTEX MmSectionBasedMutex
extern

Definition at line 110 of file section.c.

Referenced by MiDeleteARM3Section(), MmArmInitSystem(), and MmCreateArm3Section().

◆ MmSectionBasedRoot

◆ MmSectionCommitMutex

KGUARDED_MUTEX MmSectionCommitMutex
extern

◆ MmSessionBase

◆ MmSessionImageSize

SIZE_T MmSessionImageSize
extern

Definition at line 37 of file init.c.

Referenced by MiInitializeSessionSpaceLayout().

◆ MmSessionPoolSize

SIZE_T MmSessionPoolSize
extern

Definition at line 36 of file init.c.

Referenced by MiInitializeSessionPool(), and MiInitializeSessionSpaceLayout().

◆ MmSessionSize

SIZE_T MmSessionSize
extern

Definition at line 34 of file init.c.

Referenced by MiInitializeSessionSpaceLayout().

◆ MmSessionSpace

◆ MmSessionViewSize

SIZE_T MmSessionViewSize
extern

◆ MmSharedUserDataPte

PMMPTE MmSharedUserDataPte
extern

Definition at line 26 of file mminit.c.

Referenced by MiCheckVirtualAddress(), and MmInitSystem().

◆ MmSizeOfNonPagedPoolInBytes

◆ MmSizeOfPagedPoolInBytes

SIZE_T MmSizeOfPagedPoolInBytes
extern

◆ MmSizeOfPagedPoolInPages

PFN_NUMBER MmSizeOfPagedPoolInPages
extern

Definition at line 111 of file mminit.c.

Referenced by _Requires_lock_held_(), MiBuildPagedPool(), and MiInitializePoolEvents().

◆ MmSpecialPoolTag

ULONG MmSpecialPoolTag
extern

Definition at line 29 of file pool.c.

Referenced by MiInitializeSpecialPool(), MmArmInitSystem(), and MmUseSpecialPool().

◆ MmStandbyPageListByPriority

MMPFNLIST MmStandbyPageListByPriority[8]
extern

◆ MmSubsectionBase

ULONG_PTR MmSubsectionBase
extern

Definition at line 196 of file section.c.

Referenced by MI_MAKE_SUBSECTION_PTE(), and MiInitMachineDependent().

◆ MmSystemCacheEnd

PVOID MmSystemCacheEnd
extern

Definition at line 54 of file init.c.

Referenced by MiDbgDumpAddressSpace(), and MmArmInitSystem().

◆ MmSystemCacheStart

PVOID MmSystemCacheStart
extern

Definition at line 53 of file init.c.

Referenced by MiDbgDumpAddressSpace(), and MmArmInitSystem().

◆ MmSystemCacheWorkingSetList

PMMWSL MmSystemCacheWorkingSetList
extern

◆ MmSystemCacheWs

◆ MmSystemLockPagesCount

◆ MmSystemPageColor

ULONG MmSystemPageColor
extern

Definition at line 36 of file pfnlist.c.

◆ MmSystemPageDirectory

PFN_NUMBER MmSystemPageDirectory[PPE_PER_PAGE]
extern

Definition at line 40 of file init.c.

Referenced by MiAllocatePoolPages(), MiBuildPagedPool(), and MiFillSystemPageDirectory().

◆ MmSystemPagePtes

PMMPDE MmSystemPagePtes
extern

◆ MmSystemPtesEnd

PMMPTE MmSystemPtesEnd[MaximumPtePoolTypes]
extern

◆ MmSystemPtesStart

PMMPTE MmSystemPtesStart[MaximumPtePoolTypes]
extern

◆ MmSystemSize

MM_SYSTEMSIZE MmSystemSize
extern

Definition at line 326 of file mminit.c.

Referenced by MmArmInitSystem(), MmQuerySystemSize(), and MmSetMemoryPriorityProcess().

◆ MmSystemViewSize

◆ MmTotalFreeSystemPtes

ULONG MmTotalFreeSystemPtes[MaximumPtePoolTypes]
extern

◆ MmTotalSystemDriverPages

PFN_NUMBER MmTotalSystemDriverPages
extern

Definition at line 28 of file sysldr.c.

Referenced by MiSetPagingOfDriver().

◆ MmTrackLockedPages

BOOLEAN MmTrackLockedPages
extern

Definition at line 21 of file mdlsup.c.

◆ MmTrackPtes

BOOLEAN MmTrackPtes
extern

Definition at line 20 of file mdlsup.c.

◆ MmVerifyDriverBuffer

WCHAR MmVerifyDriverBuffer[512]
extern

Definition at line 23 of file drvmgmt.c.

◆ MmVerifyDriverBufferLength

ULONG MmVerifyDriverBufferLength
extern

Definition at line 24 of file drvmgmt.c.

◆ MmVerifyDriverBufferType

ULONG MmVerifyDriverBufferType
extern

Definition at line 25 of file drvmgmt.c.

◆ MmVerifyDriverLevel

ULONG MmVerifyDriverLevel
extern

Definition at line 26 of file drvmgmt.c.

◆ MmWorkingSetExpansionHead

LIST_ENTRY MmWorkingSetExpansionHead
extern

◆ MmWorkingSetList

PMMWSL MmWorkingSetList
extern

Definition at line 19 of file wslist.cpp.

Referenced by MiInitializeWorkingSetList().

◆ MmZeroingPageEvent

KEVENT MmZeroingPageEvent
extern

Definition at line 20 of file zeropage.c.

Referenced by MiInsertPageInFreeList(), MmArmInitSystem(), and MmZeroPageThread().

◆ MmZeroPageFile

BOOLEAN MmZeroPageFile
extern

Definition at line 71 of file pagefile.c.

◆ MxFreeDescriptor

◆ MxOldFreeDescriptor

◆ MxPfnAllocation

◆ NonPagedPoolDescriptor

POOL_DESCRIPTOR NonPagedPoolDescriptor
extern

Definition at line 42 of file expool.c.

Referenced by ExAllocatePoolWithTag(), ExQueryPoolUsage(), and InitializePool().

◆ PoolTrackTable

◆ PrototypePte

MMPTE PrototypePte
extern

◆ ValidKernelPde

◆ ValidKernelPdeLocal

◆ ValidKernelPte

◆ ValidKernelPteLocal