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

Go to the source code of this file.

Classes

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

Macros

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

Typedefs

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

Enumerations

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

Functions

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

Variables

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

Macro Definition Documentation

◆ _1GB

#define _1GB   (1024 * _1MB)

Definition at line 20 of file miarm.h.

◆ _1KB

#define _1KB   (1024u)

Definition at line 18 of file miarm.h.

◆ _1MB

#define _1MB   (1024 * _1KB)

Definition at line 19 of file miarm.h.

◆ _64K

#define _64K   (64 * _1KB)

Definition at line 23 of file miarm.h.

◆ BASE_POOL_TYPE_MASK

#define BASE_POOL_TYPE_MASK   1

Definition at line 272 of file miarm.h.

◆ IMAGE_SCN_PROTECTION_MASK

#define IMAGE_SCN_PROTECTION_MASK   (IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE)

Definition at line 160 of file miarm.h.

◆ MI_GET_NEXT_COLOR

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

Definition at line 232 of file miarm.h.

◆ MI_GET_NEXT_PROCESS_COLOR

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

Definition at line 233 of file miarm.h.

◆ MI_GET_PAGE_COLOR

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

Definition at line 231 of file miarm.h.

◆ MI_INITIAL_SESSION_IDS

#define MI_INITIAL_SESSION_IDS   64

Definition at line 207 of file miarm.h.

◆ MI_IS_PAGE_TABLE_ADDRESS

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

Definition at line 177 of file miarm.h.

◆ MI_IS_PAGE_TABLE_OR_HYPER_ADDRESS

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

Definition at line 183 of file miarm.h.

◆ MI_IS_PFN_DELETED

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

Definition at line 195 of file miarm.h.

◆ MI_IS_ROS_PFN

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

Definition at line 1103 of file miarm.h.

◆ MI_IS_SESSION_ADDRESS

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

Definition at line 171 of file miarm.h.

◆ MI_IS_SESSION_IMAGE_ADDRESS

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

Definition at line 168 of file miarm.h.

◆ MI_IS_SESSION_PTE

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

Definition at line 174 of file miarm.h.

◆ MI_IS_SYSTEM_PAGE_TABLE_ADDRESS

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

Definition at line 180 of file miarm.h.

◆ MI_LOWEST_VAD_ADDRESS

#define MI_LOWEST_VAD_ADDRESS   (PVOID)MM_LOWEST_USER_ADDRESS

Definition at line 15 of file miarm.h.

◆ MI_MAKE_SOFTWARE_PTE

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

Definition at line 189 of file miarm.h.

◆ MI_PTE_LOOKUP_NEEDED

#define MI_PTE_LOOKUP_NEEDED   0xFFFFF

Definition at line 241 of file miarm.h.

◆ MI_SESSION_DATA_PAGES_MAXIMUM

#define MI_SESSION_DATA_PAGES_MAXIMUM   (MM_ALLOCATION_GRANULARITY / PAGE_SIZE)

Definition at line 247 of file miarm.h.

◆ MI_SESSION_TAG_PAGES_MAXIMUM

#define MI_SESSION_TAG_PAGES_MAXIMUM   (MM_ALLOCATION_GRANULARITY / PAGE_SIZE)

Definition at line 248 of file miarm.h.

◆ MI_SET_PFN_DELETED

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

Definition at line 194 of file miarm.h.

◆ MI_SYSTEM_VIEW_BUCKET_SIZE

#define MI_SYSTEM_VIEW_BUCKET_SIZE   _64K

Definition at line 261 of file miarm.h.

◆ MM_DECOMMIT

#define MM_DECOMMIT   (MM_ZERO_ACCESS | MM_GUARDPAGE)

Definition at line 64 of file miarm.h.

◆ MM_DELETE_CHECK

#define MM_DELETE_CHECK   85

Definition at line 256 of file miarm.h.

◆ MM_EXECUTE

#define MM_EXECUTE   2

Definition at line 45 of file miarm.h.

◆ MM_EXECUTE_READ

#define MM_EXECUTE_READ   3

Definition at line 46 of file miarm.h.

◆ MM_EXECUTE_READWRITE

#define MM_EXECUTE_READWRITE   6

Definition at line 49 of file miarm.h.

◆ MM_EXECUTE_WRITECOPY

#define MM_EXECUTE_WRITECOPY   7

Definition at line 50 of file miarm.h.

◆ MM_GUARDPAGE

#define MM_GUARDPAGE   0x10

Definition at line 57 of file miarm.h.

◆ MM_INVALID_PROTECTION

#define MM_INVALID_PROTECTION   0xFFFFFFFF

Definition at line 67 of file miarm.h.

◆ MM_NO_ACCESS_ALLOWED

#define MM_NO_ACCESS_ALLOWED   01

Definition at line 255 of file miarm.h.

◆ MM_NOACCESS

#define MM_NOACCESS   (MM_ZERO_ACCESS | MM_WRITECOMBINE)

Definition at line 65 of file miarm.h.

◆ MM_NOCACHE

#define MM_NOCACHE   0x08

Definition at line 56 of file miarm.h.

◆ MM_OUTSWAPPED_KSTACK

#define MM_OUTSWAPPED_KSTACK   (MM_EXECUTE_WRITECOPY | MM_WRITECOMBINE)

Definition at line 66 of file miarm.h.

◆ MM_PROTECT_ACCESS

#define MM_PROTECT_ACCESS   7

Definition at line 51 of file miarm.h.

◆ MM_PROTECT_SPECIAL

#define MM_PROTECT_SPECIAL   0x18

Definition at line 59 of file miarm.h.

◆ MM_READ_ONLY_ALLOWED

#define MM_READ_ONLY_ALLOWED   10

Definition at line 254 of file miarm.h.

◆ MM_READ_WRITE_ALLOWED

#define MM_READ_WRITE_ALLOWED   11

Definition at line 253 of file miarm.h.

◆ MM_READONLY

#define MM_READONLY   1

Definition at line 44 of file miarm.h.

◆ MM_READWRITE

#define MM_READWRITE   4

Definition at line 47 of file miarm.h.

◆ MM_SYSLDR_BOOT_LOADED

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

Definition at line 201 of file miarm.h.

◆ MM_SYSLDR_NO_IMPORTS

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

Definition at line 200 of file miarm.h.

◆ MM_SYSLDR_SINGLE_ENTRY

#define MM_SYSLDR_SINGLE_ENTRY   0x1

Definition at line 202 of file miarm.h.

◆ MM_WRITECOMBINE

#define MM_WRITECOMBINE   0x18

Definition at line 58 of file miarm.h.

◆ MM_WRITECOPY

#define MM_WRITECOPY   5

Definition at line 48 of file miarm.h.

◆ MM_ZERO_ACCESS

#define MM_ZERO_ACCESS   0

Definition at line 43 of file miarm.h.

◆ PD_SIZE

#define PD_SIZE   (PDE_PER_PAGE * sizeof(MMPDE))

Definition at line 29 of file miarm.h.

◆ POOL_ALLOC_IRQL_INVALID

#define POOL_ALLOC_IRQL_INVALID   8

Definition at line 304 of file miarm.h.

◆ POOL_BILLED_PROCESS_INVALID

#define POOL_BILLED_PROCESS_INVALID   13

Definition at line 306 of file miarm.h.

◆ POOL_BLOCK_SIZE

#define POOL_BLOCK_SIZE   8

Definition at line 269 of file miarm.h.

◆ POOL_CORRUPTED_LIST

#define POOL_CORRUPTED_LIST   3

Definition at line 290 of file miarm.h.

◆ POOL_ENTRIES_NOT_ALIGNED_NEXT

#define POOL_ENTRIES_NOT_ALIGNED_NEXT   9

Definition at line 295 of file miarm.h.

◆ POOL_ENTRIES_NOT_ALIGNED_PREVIOUS

#define POOL_ENTRIES_NOT_ALIGNED_PREVIOUS   6

Definition at line 292 of file miarm.h.

◆ POOL_ENTRY_ALREADY_FREE

#define POOL_ENTRY_ALREADY_FREE   6

Definition at line 302 of file miarm.h.

◆ POOL_ENTRY_CORRUPTED

#define POOL_ENTRY_CORRUPTED   1

Definition at line 301 of file miarm.h.

◆ POOL_ENTRY_NOT_ALLOCATED

#define POOL_ENTRY_NOT_ALLOCATED   7

Definition at line 303 of file miarm.h.

◆ POOL_ENTRY_NOT_FOUND

#define POOL_ENTRY_NOT_FOUND   10

Definition at line 296 of file miarm.h.

◆ POOL_FLAG_CHECK_DEADLOCK

#define POOL_FLAG_CHECK_DEADLOCK   0x10

Definition at line 282 of file miarm.h.

◆ POOL_FLAG_CHECK_RESOURCES

#define POOL_FLAG_CHECK_RESOURCES   0x4

Definition at line 280 of file miarm.h.

◆ POOL_FLAG_CHECK_TIMERS

#define POOL_FLAG_CHECK_TIMERS   0x1

Definition at line 278 of file miarm.h.

◆ POOL_FLAG_CHECK_WORKERS

#define POOL_FLAG_CHECK_WORKERS   0x2

Definition at line 279 of file miarm.h.

◆ POOL_FLAG_CRASH_ON_FAILURE

#define POOL_FLAG_CRASH_ON_FAILURE   0x80

Definition at line 285 of file miarm.h.

◆ POOL_FLAG_DBGPRINT_ON_FAILURE

#define POOL_FLAG_DBGPRINT_ON_FAILURE   0x40

Definition at line 284 of file miarm.h.

◆ POOL_FLAG_SPECIAL_POOL

#define POOL_FLAG_SPECIAL_POOL   0x20

Definition at line 283 of file miarm.h.

◆ POOL_FLAG_VERIFIER

#define POOL_FLAG_VERIFIER   0x8

Definition at line 281 of file miarm.h.

◆ POOL_FREE_IRQL_INVALID

#define POOL_FREE_IRQL_INVALID   9

Definition at line 305 of file miarm.h.

◆ POOL_HEADER_IS_ZERO

#define POOL_HEADER_IS_ZERO   8

Definition at line 294 of file miarm.h.

◆ POOL_HEADER_NOT_ALIGNED

#define POOL_HEADER_NOT_ALIGNED   7

Definition at line 293 of file miarm.h.

◆ POOL_HEADER_SIZE_INVALID

#define POOL_HEADER_SIZE_INVALID   32

Definition at line 307 of file miarm.h.

◆ POOL_LISTS_PER_PAGE

#define POOL_LISTS_PER_PAGE   (PAGE_SIZE / POOL_BLOCK_SIZE)

Definition at line 271 of file miarm.h.

◆ POOL_MAX_ALLOC

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

Definition at line 273 of file miarm.h.

◆ POOL_SIZE_OR_INDEX_MISMATCH

#define POOL_SIZE_OR_INDEX_MISMATCH   5

Definition at line 291 of file miarm.h.

◆ PT_SIZE

#define PT_SIZE   (PTE_PER_PAGE * sizeof(MMPTE))

Definition at line 26 of file miarm.h.

◆ SYSTEM_PD_SIZE

#define SYSTEM_PD_SIZE   (PPE_PER_PAGE * PD_SIZE)

Definition at line 32 of file miarm.h.

Typedef Documentation

◆ MI_LARGE_PAGE_DRIVER_ENTRY

◆ MI_LARGE_PAGE_RANGES

◆ MI_PFN_CACHE_ATTRIBUTE

◆ MM_SESSION_SPACE

◆ MM_SESSION_SPACE_FLAGS

◆ MMCOLOR_TABLES

◆ MMSESSION

◆ MMSYSTEM_PTE_POOL_TYPE

◆ MMVIEW

◆ PHYSICAL_MEMORY_DESCRIPTOR

◆ PHYSICAL_MEMORY_RUN

◆ PMI_LARGE_PAGE_DRIVER_ENTRY

◆ PMI_LARGE_PAGE_RANGES

◆ PMI_PFN_CACHE_ATTRIBUTE

◆ PMM_SESSION_SPACE

◆ PMMCOLOR_TABLES

◆ PMMSESSION

◆ PMMVIEW

typedef struct _MMVIEW * PMMVIEW

◆ POOL_DESCRIPTOR

◆ POOL_HEADER

◆ POOL_TRACKER_BIG_PAGES

◆ POOL_TRACKER_TABLE

◆ PPHYSICAL_MEMORY_DESCRIPTOR

◆ PPHYSICAL_MEMORY_RUN

◆ PPOOL_DESCRIPTOR

◆ PPOOL_HEADER

◆ PPOOL_TRACKER_BIG_PAGES

◆ PPOOL_TRACKER_TABLE

Enumeration Type Documentation

◆ _MI_PFN_CACHE_ATTRIBUTE

Enumerator
MiNonCached 
MiCached 
MiWriteCombined 
MiNotMapped 

Definition at line 408 of file miarm.h.

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

◆ _MMSYSTEM_PTE_POOL_TYPE

Enumerator
SystemPteSpace 
NonPagedPoolExpansion 
MaximumPtePoolTypes 

Definition at line 401 of file miarm.h.

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

Function Documentation

◆ C_ASSERT() [1/2]

C_ASSERT ( POOL_BLOCK_SIZE  = =sizeof(LIST_ENTRY))

◆ C_ASSERT() [2/2]

C_ASSERT ( sizeof(POOL_HEADER = =POOL_BLOCK_SIZE)

◆ ExInitializePoolDescriptor()

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

Definition at line 969 of file expool.c.

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

Referenced by InitializePool(), and MiInitializeSessionPool().

◆ InitializePool()

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

Definition at line 1020 of file expool.c.

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

Referenced by MiBuildPagedPool(), and MiInitMachineDependent().

◆ MI_ERASE_PTE()

FORCEINLINE VOID MI_ERASE_PTE ( IN PMMPTE  PointerPte)

Definition at line 1006 of file miarm.h.

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

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

◆ MI_GET_PROTOTYPE_PTE_FOR_VPN()

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

Definition at line 1557 of file miarm.h.

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

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

◆ MI_IS_MAPPED_PTE()

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

Definition at line 919 of file miarm.h.

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

◆ MI_IS_PHYSICAL_ADDRESS()

FORCEINLINE BOOLEAN MI_IS_PHYSICAL_ADDRESS ( IN PVOID  Address)

Definition at line 945 of file miarm.h.

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

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

◆ MI_IS_PROCESS_WORKING_SET()

FORCEINLINE BOOLEAN MI_IS_PROCESS_WORKING_SET ( PMMSUPPORT  WorkingSet)

Definition at line 661 of file miarm.h.

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

Referenced by MiInitializeWorkingSetList(), and MmWorkingSetManager().

◆ MI_IS_WS_UNSAFE()

FORCEINLINE BOOLEAN MI_IS_WS_UNSAFE ( IN PEPROCESS  Process)

Definition at line 1114 of file miarm.h.

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

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

◆ MI_MAKE_HARDWARE_PTE()

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

Definition at line 807 of file miarm.h.

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

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

◆ MI_MAKE_HARDWARE_PTE_KERNEL()

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

Definition at line 773 of file miarm.h.

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

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

◆ MI_MAKE_HARDWARE_PTE_USER()

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

Definition at line 827 of file miarm.h.

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

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

◆ MI_MAKE_PROTOTYPE_PTE()

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

Definition at line 854 of file miarm.h.

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

◆ MI_MAKE_SUBSECTION_PTE()

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

Definition at line 883 of file miarm.h.

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

◆ MI_MAKE_TRANSITION_PTE()

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

Definition at line 929 of file miarm.h.

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

Referenced by MiResolvePageFileFault(), and TrimWsList().

◆ MI_PFN_ELEMENT()

◆ MI_UPDATE_VALID_PTE()

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

Definition at line 977 of file miarm.h.

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

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

◆ MI_WRITE_INVALID_PDE()

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

Definition at line 1035 of file miarm.h.

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

Referenced by MmArmAccessFault().

◆ MI_WRITE_INVALID_PTE()

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

◆ MI_WRITE_VALID_PDE()

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

Definition at line 1018 of file miarm.h.

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

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

◆ MI_WRITE_VALID_PTE()

◆ MI_WS_OWNER()

FORCEINLINE BOOLEAN MI_WS_OWNER ( IN PEPROCESS  Process)

Definition at line 1077 of file miarm.h.

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

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

◆ MiAcquireExpansionLock()

FORCEINLINE KIRQL MiAcquireExpansionLock ( VOID  )

Definition at line 1531 of file miarm.h.

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

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

◆ MiAllocatePagesForMdl()

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

Definition at line 182 of file freelist.c.

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

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

◆ MiCheckForConflictingNode()

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

Definition at line 150 of file vadnode.c.

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

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

◆ MiCheckForContiguousMemory()

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

Definition at line 214 of file contmem.c.

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

Referenced by MiAllocateContiguousMemory().

◆ MiCheckPdeForPagedPool()

NTSTATUS FASTCALL MiCheckPdeForPagedPool ( IN PVOID  Address)

Definition at line 479 of file pagfault.c.

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

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

◆ MiCheckSecuredVad()

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

Definition at line 903 of file vadnode.c.

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

Referenced by MiUnmapViewOfSection(), and NtAllocateVirtualMemory().

◆ MiComputeColorInformation()

VOID NTAPI MiComputeColorInformation ( VOID  )

Definition at line 508 of file mminit.c.

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

Referenced by MmArmInitSystem().

◆ MiConvertSharedWorkingSetLockToExclusive()

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

Definition at line 1428 of file miarm.h.

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

Referenced by MmWorkingSetManager().

◆ MiDecrementPageTableReferences()

FORCEINLINE USHORT MiDecrementPageTableReferences ( IN PVOID  Address)

Definition at line 2507 of file miarm.h.

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

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

◆ MiDecrementReferenceCount()

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

Definition at line 1236 of file pfnlist.c.

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

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

◆ MiDecrementShareCount()

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

Definition at line 1141 of file pfnlist.c.

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

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

◆ MiDeleteARM3Section()

VOID NTAPI MiDeleteARM3Section ( PVOID  ObjectBody)

Definition at line 3316 of file section.c.

3317{
3319 PCONTROL_AREA ControlArea;
3320 KIRQL OldIrql;
3321
3322 SectionObject = (PSECTION)ObjectBody;
3323
3324 if (SectionObject->u.Flags.Based == 1)
3325 {
3326 /* Remove the node from the global section address tree */
3330 }
3331
3332 /* Lock the PFN database */
3333 OldIrql = MiAcquirePfnLock();
3334
3335 ASSERT(SectionObject->Segment);
3336 ASSERT(SectionObject->Segment->ControlArea);
3337
3338 ControlArea = SectionObject->Segment->ControlArea;
3339
3340 /* Dereference */
3341 ControlArea->NumberOfSectionReferences--;
3342 ControlArea->NumberOfUserReferences--;
3343
3344 ASSERT(ControlArea->u.Flags.BeingDeleted == 0);
3345
3346 /* Check it. It will delete it if there is no more reference to it */
3347 MiCheckControlArea(ControlArea, OldIrql);
3348}
KGUARDED_MUTEX MmSectionBasedMutex
Definition: section.c:110
VOID NTAPI MiCheckControlArea(IN PCONTROL_AREA ControlArea, IN KIRQL OldIrql)
Definition: section.c:714
MM_AVL_TABLE MmSectionBasedRoot
Definition: section.c:109
_Must_inspect_result_ _Outptr_ PVOID * SectionObject
Definition: fsrtlfuncs.h:860
VOID FASTCALL KeReleaseGuardedMutex(IN OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:53
VOID FASTCALL KeAcquireGuardedMutex(IN PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:42
VOID NTAPI MiRemoveNode(IN PMMADDRESS_NODE Node, IN PMM_AVL_TABLE Table)
Definition: vadnode.c:440
struct _SECTION * PSECTION
ULONG NumberOfSectionReferences
Definition: mmtypes.h:523
ULONG NumberOfUserReferences
Definition: mmtypes.h:527
union _CONTROL_AREA::@2604 u
MMSECTION_FLAGS Flags
Definition: mmtypes.h:531
ULONG BeingDeleted
Definition: mmtypes.h:463

Referenced by MmpDeleteSection().

◆ MiDeletePde()

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

Definition at line 2541 of file miarm.h.

2544{
2545 /* Only for user-mode ones */
2546 ASSERT(MiIsUserPde(PointerPde));
2547
2548 /* Kill this one as a PTE */
2549 MiDeletePte((PMMPTE)PointerPde, MiPdeToPte(PointerPde), CurrentProcess, NULL);
2550#if _MI_PAGING_LEVELS >= 3
2551 /* Cascade down */
2552 if (MiDecrementPageTableReferences(MiPdeToPte(PointerPde)) == 0)
2553 {
2554 MiDeletePte(MiPdeToPpe(PointerPde), PointerPde, CurrentProcess, NULL);
2555#if _MI_PAGING_LEVELS == 4
2556 if (MiDecrementPageTableReferences(PointerPde) == 0)
2557 {
2558 MiDeletePte(MiPdeToPxe(PointerPde), MiPdeToPpe(PointerPde), CurrentProcess, NULL);
2559 }
2560#endif
2561 }
2562#endif
2563}
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:2507
FORCEINLINE BOOLEAN MiIsUserPde(PVOID Address)
Definition: miarm.h:717
FORCEINLINE PMMPXE MiPdeToPxe(PMMPDE PointerPde)
Definition: mm.h:300
FORCEINLINE PMMPDE MiPdeToPpe(PMMPDE PointerPde)
Definition: mm.h:292
#define MiPdeToPte(_Pde)
Definition: mm.h:120

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

◆ MiDeletePte()

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

Definition at line 369 of file virtual.c.

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

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

◆ MiDeleteSystemPageableVm()

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

Definition at line 275 of file virtual.c.

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

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

◆ MiDeleteVirtualAddresses()

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

Definition at line 530 of file virtual.c.

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

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

◆ MiDereferencePfnAndDropLockCount()

FORCEINLINE VOID MiDereferencePfnAndDropLockCount ( IN PMMPFN  Pfn1)

Definition at line 1615 of file miarm.h.

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

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

◆ MiDetermineUserGlobalPteMask()

FORCEINLINE ULONG_PTR MiDetermineUserGlobalPteMask ( IN PVOID  PointerPte)

Definition at line 736 of file miarm.h.

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

Referenced by MI_MAKE_HARDWARE_PTE(), and MiResolveTransitionFault().

◆ MiDropLockCount()

FORCEINLINE VOID MiDropLockCount ( IN PMMPFN  Pfn1)

Definition at line 1585 of file miarm.h.

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

Referenced by MiResolveTransitionFault().

◆ MiFindContiguousPages()

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

Definition at line 22 of file contmem.c.

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

Referenced by MiFindContiguousMemory().

◆ MiFindEmptyAddressRangeDownBasedTree()

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

Definition at line 799 of file vadnode.c.

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

Referenced by MmCreateArm3Section().

◆ MiFindEmptyAddressRangeDownTree()

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

Definition at line 681 of file vadnode.c.

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

Referenced by MiInsertVadEx(), and MmFindGap().

◆ MiFindEmptyAddressRangeInTree()

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

Definition at line 584 of file vadnode.c.

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

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

◆ MiGetNextNode()

PMMADDRESS_NODE NTAPI MiGetNextNode ( IN PMMADDRESS_NODE  Node)

Definition at line 549 of file vadnode.c.

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

Referenced by MiFindEmptyAddressRangeInTree(), and MiQueryMemoryBasicInformation().

◆ MiGetPageProtection()

ULONG NTAPI MiGetPageProtection ( IN PMMPTE  PointerPte)

Definition at line 1355 of file virtual.c.

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

Referenced by MiProtectVirtualMemory(), MiQueryAddressState(), MiSetProtectionOnSection(), 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 2481 of file miarm.h.

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

Referenced by MiDecommitPages(), MiMapLockedPagesInUserSpace(), MiProtectVirtualMemory(), MiSetProtectionOnSection(), 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:232
FORCEINLINE VOID MI_WRITE_VALID_PDE(IN PMMPDE PointerPde, IN MMPDE TempPde)
Definition: miarm.h:1018
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 562 of file mminit.c.

563{
564 ULONG i;
565 PMMPTE PointerPte, LastPte;
567
568 /* The color table starts after the ARM3 PFN database */
570
571 /* Loop the PTEs. We have two color tables for each secondary color */
572 PointerPte = MiAddressToPte(&MmFreePagesByColor[0][0]);
574 (2 * MmSecondaryColors * sizeof(MMCOLOR_TABLES))
575 - 1);
576 while (PointerPte <= LastPte)
577 {
578 /* Check for valid PTE */
579 if (PointerPte->u.Hard.Valid == 0)
580 {
581 /* Get a page and map it */
583 MI_WRITE_VALID_PTE(PointerPte, TempPte);
584
585 /* Zero out the page */
587 }
588
589 /* Next */
590 PointerPte++;
591 }
592
593 /* Now set the address of the next list, right after this one */
595
596 /* Now loop the lists to set them up */
597 for (i = 0; i < MmSecondaryColors; i++)
598 {
599 /* Set both free and zero lists for each color */
606 }
607}
PFN_NUMBER NTAPI MxGetNextPage(IN PFN_NUMBER PageCount)
Definition: mminit.c:483
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:959
@ FreePageList
Definition: mmtypes.h:154
MMPTE ValidKernelPte
Definition: init.c:29
PFN_NUMBER Count
Definition: miarm.h:433
PVOID Blink
Definition: miarm.h:432
PFN_NUMBER Flink
Definition: miarm.h:431

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 1339 of file mminit.c.

1340{
1341 UNICODE_STRING LowString = RTL_CONSTANT_STRING(L"\\KernelObjects\\LowMemoryCondition");
1342 UNICODE_STRING HighString = RTL_CONSTANT_STRING(L"\\KernelObjects\\HighMemoryCondition");
1343 UNICODE_STRING LowPagedPoolString = RTL_CONSTANT_STRING(L"\\KernelObjects\\LowPagedPoolCondition");
1344 UNICODE_STRING HighPagedPoolString = RTL_CONSTANT_STRING(L"\\KernelObjects\\HighPagedPoolCondition");
1345 UNICODE_STRING LowNonPagedPoolString = RTL_CONSTANT_STRING(L"\\KernelObjects\\LowNonPagedPoolCondition");
1346 UNICODE_STRING HighNonPagedPoolString = RTL_CONSTANT_STRING(L"\\KernelObjects\\HighNonPagedPoolCondition");
1348
1349 /* Check if we have a registry setting */
1351 {
1352 /* Convert it to pages */
1354 }
1355 else
1356 {
1357 /* The low memory threshold is hit when we don't consider that we have "plenty" of free pages anymore */
1359
1360 /* More than one GB of memory? */
1361 if (MmNumberOfPhysicalPages > 0x40000)
1362 {
1363 /* Start at 32MB, and add another 16MB for each GB */
1365 MmLowMemoryThreshold += ((MmNumberOfPhysicalPages - 0x40000) >> 7);
1366 }
1367 else if (MmNumberOfPhysicalPages > 0x8000)
1368 {
1369 /* For systems with > 128MB RAM, add another 4MB for each 128MB */
1370 MmLowMemoryThreshold += ((MmNumberOfPhysicalPages - 0x8000) >> 5);
1371 }
1372
1373 /* Don't let the minimum threshold go past 64MB */
1375 }
1376
1377 /* Check if we have a registry setting */
1379 {
1380 /* Convert it into pages */
1382 }
1383 else
1384 {
1385 /* Otherwise, the default is three times the low memory threshold */
1388 }
1389
1390 /* Make sure high threshold is actually higher than the low */
1392
1393 /* Create the memory events for all the thresholds */
1395 if (!NT_SUCCESS(Status)) return FALSE;
1397 if (!NT_SUCCESS(Status)) return FALSE;
1398 Status = MiCreateMemoryEvent(&LowPagedPoolString, &MiLowPagedPoolEvent);
1399 if (!NT_SUCCESS(Status)) return FALSE;
1400 Status = MiCreateMemoryEvent(&HighPagedPoolString, &MiHighPagedPoolEvent);
1401 if (!NT_SUCCESS(Status)) return FALSE;
1402 Status = MiCreateMemoryEvent(&LowNonPagedPoolString, &MiLowNonPagedPoolEvent);
1403 if (!NT_SUCCESS(Status)) return FALSE;
1404 Status = MiCreateMemoryEvent(&HighNonPagedPoolString, &MiHighNonPagedPoolEvent);
1405 if (!NT_SUCCESS(Status)) return FALSE;
1406
1407 /* Now setup the pool events */
1409
1410 /* Set the initial event state */
1412 return TRUE;
1413}
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:1244
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:1218
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:189
USHORT Modified
Definition: mm.h:360
USHORT Rom
Definition: mm.h:368
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 1074 of file mminit.c.

1075{
1076 /* Scan memory and start setting up PFN entries */
1077 MiBuildPfnDatabaseFromPages(LoaderBlock);
1078
1079 /* Add the zero page */
1081
1082 /* Scan the loader block and build the rest of the PFN database */
1084
1085 /* Finally add the pages for the PFN database itself */
1087}
VOID NTAPI MiBuildPfnDatabaseFromPages(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: mminit.c:768
VOID NTAPI MiBuildPfnDatabaseZeroPage(VOID)
Definition: mminit.c:877
VOID NTAPI MiBuildPfnDatabaseFromLoaderBlock(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: mminit.c:900
VOID NTAPI MiBuildPfnDatabaseSelf(VOID)
Definition: mminit.c:1044

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:419

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:493
@ 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}
NTSYSAPI void WINAPI RtlInitializeBitMap(PRTL_BITMAP, PULONG, ULONG)
NTSYSAPI void WINAPI RtlClearAllBits(PRTL_BITMAP)
PFN_NUMBER MmLowestPhysicalPage
Definition: meminit.c:30
#define MI_SESSION_TAG_PAGES_MAXIMUM
Definition: miarm.h:248
#define MI_INITIAL_SESSION_IDS
Definition: miarm.h:207
#define MI_SESSION_DATA_PAGES_MAXIMUM
Definition: miarm.h:247
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:113

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}
NTSYSAPI void WINAPI RtlSetAllBits(PRTL_BITMAP)
NTSYSAPI void WINAPI RtlClearBits(PRTL_BITMAP, ULONG, ULONG)
#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:489
PRTL_BITMAP EndOfPagedPoolBitmap
Definition: mm.h:487
PRTL_BITMAP PagedPoolAllocationMap
Definition: mm.h:486
PMMPDE NextPdeForPagedPoolExpansion
Definition: mm.h:490
PMMPTE FirstPteForPagedPool
Definition: mm.h:488
ULONG PagedPoolHint
Definition: mm.h:491
SIZE_T PagedPoolCommit
Definition: mm.h:492
PFN_NUMBER SessionPageDirectoryIndex
Definition: miarm.h:480
PMMPDE PageTables
Definition: miarm.h:507
KGUARDED_MUTEX PagedPoolMutex
Definition: miarm.h:498
PVOID PagedPoolStart
Definition: miarm.h:483
MM_PAGED_POOL_INFO PagedPoolInfo
Definition: miarm.h:499
struct _MM_SESSION_SPACE * GlobalVirtualAddress
Definition: miarm.h:470
PVOID PagedPoolEnd
Definition: miarm.h:484
SIZE_T CommittedPages
Definition: miarm.h:482
SIZE_T NonPageablePages
Definition: miarm.h:481
POOL_DESCRIPTOR PagedPool
Definition: miarm.h:503
PMMPDE PagedPoolBasePde
Definition: miarm.h:485
uint32_t * PULONG
Definition: typedefs.h:59
struct _RTL_BITMAP RTL_BITMAP
_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:261
struct _MMVIEW MMVIEW
ULONG SystemSpaceHashKey
Definition: miarm.h:456
ULONG SystemSpaceHashEntries
Definition: miarm.h:455
PKGUARDED_MUTEX SystemSpaceViewLockPointer
Definition: miarm.h:451
PRTL_BITMAP SystemSpaceBitMap
Definition: miarm.h:458
PCHAR SystemSpaceViewStart
Definition: miarm.h:452
ULONG SystemSpaceHashSize
Definition: miarm.h:454
PMMVIEW SystemSpaceViewTable
Definition: miarm.h:453
KGUARDED_MUTEX SystemSpaceViewLock
Definition: miarm.h:450

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:373

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:349
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:366
Definition: mm.h:442
PFN_NUMBER Total
Definition: mm.h:443
PFN_NUMBER Blink
Definition: mm.h:446
PFN_NUMBER Flink
Definition: mm.h:445
ULONG_PTR MustBeCached
Definition: mm.h:423
PFN_NUMBER Blink
Definition: mm.h:389
PFN_NUMBER Flink
Definition: mm.h:377
ULONG_PTR Priority
Definition: mm.h:422
#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:324
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:1239
FORCEINLINE VOID MiLockProcessWorkingSetUnsafe(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1169
_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:1453
EX_PUSH_LOCK AddressCreationLock
Definition: pstypes.h:1290
SIZE_T PeakVirtualSize
Definition: pstypes.h:1272
SIZE_T VirtualSize
Definition: pstypes.h:1273
ULONG VmDeleted
Definition: pstypes.h:1398
ULONG VmTopDown
Definition: pstypes.h:1417
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 668 of file miarm.h.

669{
670 return ((MemoryType == LoaderFree) ||
671 (MemoryType == LoaderLoadedProgram) ||
672 (MemoryType == LoaderFirmwareTemporary) ||
673 (MemoryType == LoaderOsloaderStack));
674}
@ LoaderFree
Definition: arc.h:176
@ LoaderFirmwareTemporary
Definition: arc.h:179
@ LoaderLoadedProgram
Definition: arc.h:178
@ LoaderOsloaderStack
Definition: arc.h:182

Referenced by MiAddDescriptorToDatabase().

◆ MiIsMemoryTypeInvisible()

FORCEINLINE BOOLEAN MiIsMemoryTypeInvisible ( TYPE_OF_MEMORY  MemoryType)

Definition at line 678 of file miarm.h.

679{
680 return ((MemoryType == LoaderFirmwarePermanent) ||
681 (MemoryType == LoaderSpecialMemory) ||
682 (MemoryType == LoaderHALCachedMemory) ||
683 (MemoryType == LoaderBBTMemory));
684}
@ LoaderHALCachedMemory
Definition: arc.h:200
@ LoaderFirmwarePermanent
Definition: arc.h:180
@ LoaderSpecialMemory
Definition: arc.h:196
@ LoaderBBTMemory
Definition: arc.h:197

Referenced by MiAddDescriptorToDatabase(), and MiBuildPfnDatabase().

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

718{
719 return ((Address >= (PVOID)MiAddressToPde(NULL)) &&
721}
PMMPDE MiHighestUserPde
Definition: mminit.c:234

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

◆ MiIsUserPte()

FORCEINLINE BOOLEAN MiIsUserPte ( PVOID  Address)

Definition at line 725 of file miarm.h.

726{
727 return (Address >= (PVOID)PTE_BASE) && (Address <= (PVOID)MiHighestUserPte);
728}
#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(), MiGetFileObjectForSectionAddress(), 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 1124 of file miarm.h.

1126{
1127 /* Shouldn't already be owning the process working set */
1130
1131 /* Block APCs, make sure that still nothing is already held */
1134
1135 /* Lock the working set */
1136 ExAcquirePushLockExclusive(&Process->Vm.WorkingSetMutex);
1137
1138 /* Now claim that we own the lock */
1142}
FORCEINLINE VOID ExAcquirePushLockExclusive(PEX_PUSH_LOCK PushLock)
Definition: ex.h:1036
FORCEINLINE BOOLEAN MI_IS_WS_UNSAFE(IN PEPROCESS Process)
Definition: miarm.h:1114
FORCEINLINE BOOLEAN MM_ANY_WS_LOCK_HELD(IN PETHREAD Thread)
Definition: miarm.h:1052

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

1505{
1506 /* Check if this was a safe lock or not */
1507 if (Safe)
1508 {
1509 if (Shared)
1510 {
1511 /* Reacquire safely & shared */
1513 }
1514 else
1515 {
1516 /* Reacquire safely */
1518 }
1519 }
1520 else
1521 {
1522 /* Unsafe lock cannot be shared */
1523 ASSERT(Shared == FALSE);
1524 /* Reacquire unsafely */
1526 }
1527}
FORCEINLINE VOID MiLockProcessWorkingSetShared(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1146
FORCEINLINE VOID MiLockProcessWorkingSet(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1124

Referenced by MiGetPageProtection(), and MiMakeSystemAddressValid().

◆ MiLockProcessWorkingSetShared()

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

Definition at line 1146 of file miarm.h.

1148{
1149 /* Shouldn't already be owning the process working set */
1152
1153 /* Block APCs, make sure that still nothing is already held */
1156
1157 /* Lock the working set */
1158 ExAcquirePushLockShared(&Process->Vm.WorkingSetMutex);
1159
1160 /* Now claim that we own the lock */
1165}
FORCEINLINE VOID ExAcquirePushLockShared(PEX_PUSH_LOCK PushLock)
Definition: ex.h:1105

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

1171{
1172 /* Shouldn't already be owning the process working set */
1174
1175 /* APCs must be blocked, make sure that still nothing is already held */
1178
1179 /* Lock the working set */
1180 ExAcquirePushLockExclusive(&Process->Vm.WorkingSetMutex);
1181
1182 /* Now claim that we own the lock */
1184 Process->Vm.Flags.AcquiredUnsafe = 1;
1187}
BOOLEAN NTAPI KeAreAllApcsDisabled(VOID)
Definition: apc.c:985

Referenced by _Success_(), MiDecommitPages(), MiInsertVadEx(), MiLockProcessWorkingSetForFault(), MiMapLockedPagesInUserSpace(), MiProtectVirtualMemory(), MiSetProtectionOnSection(), 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 1265 of file miarm.h.

1267{
1268 /* Block APCs */
1270
1271 /* Working set should be in global memory */
1272 ASSERT(MI_IS_SESSION_ADDRESS((PVOID)WorkingSet) == FALSE);
1273
1274 /* Thread shouldn't already be owning something */
1276
1277 /* Lock this working set */
1278 ExAcquirePushLockExclusive(&WorkingSet->WorkingSetMutex);
1279
1280 /* Which working set is this? */
1281 if (WorkingSet == &MmSystemCacheWs)
1282 {
1283 /* Own the system working set */
1287 }
1288 else if (WorkingSet->Flags.SessionSpace)
1289 {
1290 /* Own the session working set */
1294 }
1295 else
1296 {
1297 /* Own the process working set */
1301 }
1302}
#define MI_IS_SESSION_ADDRESS(Address)
Definition: miarm.h:171

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

◆ MiLockWorkingSetShared()

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

Definition at line 1306 of file miarm.h.

1309{
1310 /* Block APCs */
1312
1313 /* Working set should be in global memory */
1314 ASSERT(MI_IS_SESSION_ADDRESS((PVOID)WorkingSet) == FALSE);
1315
1316 /* Thread shouldn't already be owning something */
1318
1319 /* Lock this working set */
1320 ExAcquirePushLockShared(&WorkingSet->WorkingSetMutex);
1321
1322 /* Which working set is this? */
1323 if (WorkingSet == &MmSystemCacheWs)
1324 {
1325 /* Own the system working set */
1329 }
1330 else if (WorkingSet->Flags.SessionSpace)
1331 {
1332 /* Own the session working set */
1336 }
1337 else
1338 {
1339 /* Own the process working set */
1343 }
1344}

Referenced by MmAccessFault(), and MmWorkingSetManager().

◆ MiLookupDataTableEntry()

PLDR_DATA_TABLE_ENTRY NTAPI MiLookupDataTableEntry ( IN PVOID  Address)

Definition at line 3517 of file sysldr.c.

3518{
3519 PLDR_DATA_TABLE_ENTRY LdrEntry, FoundEntry = NULL;
3520 PLIST_ENTRY NextEntry;
3521 PAGED_CODE();
3522
3523 /* Loop entries */
3524 NextEntry = PsLoadedModuleList.Flink;
3525 do
3526 {
3527 /* Get the loader entry */
3528 LdrEntry = CONTAINING_RECORD(NextEntry,
3530 InLoadOrderLinks);
3531
3532 /* Check if the address matches */
3533 if ((Address >= LdrEntry->DllBase) &&
3534 (Address < (PVOID)((ULONG_PTR)LdrEntry->DllBase +
3535 LdrEntry->SizeOfImage)))
3536 {
3537 /* Found a match */
3538 FoundEntry = LdrEntry;
3539 break;
3540 }
3541
3542 /* Move on */
3543 NextEntry = NextEntry->Flink;
3544 } while(NextEntry != &PsLoadedModuleList);
3545
3546 /* Return the entry */
3547 return FoundEntry;
3548}
Definition: btrfs_drv.h:1876
ULONG SizeOfImage
Definition: ldrtypes.h:143
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(), MiSetProtectionOnSection(), 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:34
NTSTATUS NTAPI MmAccessFault(IN ULONG FaultCode, IN PVOID Address, IN KPROCESSOR_MODE Mode, IN PVOID TrapInformation)
Definition: mmfault.c:209

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 672 of file mminit.c.

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

1953{
1957 PMEMORY_SECTION_NAME SectionName = NULL;
1959
1962 NULL,
1964 (PVOID*)(&Process),
1965 NULL);
1966
1967 if (!NT_SUCCESS(Status))
1968 {
1969 DPRINT("MiQueryMemorySectionName: ObReferenceObjectByHandle returned %x\n",Status);
1970 return Status;
1971 }
1972
1974
1975 if (NT_SUCCESS(Status))
1976 {
1977 SectionName = MemoryInformation;
1978 if (PreviousMode != KernelMode)
1979 {
1980 _SEH2_TRY
1981 {
1982 RtlInitEmptyUnicodeString(&SectionName->SectionFileName,
1983 (PWSTR)(SectionName + 1),
1984 MemoryInformationLength - sizeof(MEMORY_SECTION_NAME));
1986
1988
1989 }
1991 {
1993 }
1994 _SEH2_END;
1995 }
1996 else
1997 {
1998 RtlInitEmptyUnicodeString(&SectionName->SectionFileName,
1999 (PWSTR)(SectionName + 1),
2000 MemoryInformationLength - sizeof(MEMORY_SECTION_NAME));
2002
2004
2005 }
2006
2008 }
2010 return Status;
2011}
NTSTATUS NTAPI MmGetFileNameForAddress(IN PVOID Address, OUT PUNICODE_STRING ModuleName)
Definition: section.c:1885
IN CINT OUT PVOID IN ULONG OUT PULONG ReturnLength
Definition: dumpinfo.c:43
#define ExGetPreviousMode
Definition: ex.h:140
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
#define PROCESS_QUERY_INFORMATION
Definition: pstypes.h:166
_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:159
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:34
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
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103

Referenced by NtQueryVirtualMemory().

◆ MiReferenceProbedPageAndBumpLockCount()

FORCEINLINE VOID MiReferenceProbedPageAndBumpLockCount ( IN PMMPFN  Pfn1)

Definition at line 1687 of file miarm.h.

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

Referenced by MI_LOCK_VA(), and MmProbeAndLockPages().

◆ MiReferenceUnusedPageAndBumpLockCount()

FORCEINLINE VOID MiReferenceUnusedPageAndBumpLockCount ( IN PMMPFN  Pfn1)

Definition at line 1787 of file miarm.h.

1788{
1789 USHORT NewRefCount;
1790
1791 /* Make sure the page isn't used yet */
1792 ASSERT(Pfn1->u2.ShareCount == 0);
1793 ASSERT(Pfn1->u3.e1.PageLocation != ActiveAndValid);
1794
1795 /* Is it a prototype PTE? */
1796 if ((Pfn1->u3.e1.PrototypePte == 1) &&
1797 (Pfn1->OriginalPte.u.Soft.Prototype == 1))
1798 {
1799 /* FIXME: We should charge commit */
1800 DPRINT1("Not charging commit for prototype PTE\n");
1801 }
1802
1803 /* More locked pages! */
1805
1806 /* Update the reference count */
1807 NewRefCount = InterlockedIncrement16((PSHORT)&Pfn1->u3.e2.ReferenceCount);
1808 if (NewRefCount != 1)
1809 {
1810 /* Someone had already locked the page, so undo our bump */
1811 ASSERT(NewRefCount < 2500);
1813 }
1814}
#define InterlockedIncrement16
Definition: interlocked.h:206

Referenced by MiResolveTransitionFault().

◆ MiReferenceUsedPageAndBumpLockCount()

FORCEINLINE VOID MiReferenceUsedPageAndBumpLockCount ( IN PMMPFN  Pfn1)

Definition at line 1742 of file miarm.h.

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

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
ULONG SessionId
Definition: dllmain.c:28
FORCEINLINE BOOLEAN MI_IS_PHYSICAL_ADDRESS(IN PVOID Address)
Definition: miarm.h:945
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
VOID NTAPI RtlClearBit(_In_ PRTL_BITMAP BitMapHeader, _In_ BITMAP_INDEX BitNumber)
Definition: bitmap.c:294
#define RtlCheckBit(BMH, BP)
Definition: rtlfuncs.h:3152

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:255
ULONG Type
Definition: mm.h:251
ULONG_PTR Spare
Definition: mmtypes.h:697
union _MMVAD_LONG::@2614 u
PMMPTE FirstPrototypePte
Definition: mmtypes.h:766
PVOID Banked
Definition: mmtypes.h:780
MMVAD_FLAGS VadFlags
Definition: mmtypes.h:763
union _MMVAD_LONG::@2617 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:418
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 2415 of file miarm.h.

2416{
2418 return 0;
2419}
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 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:1691
NTSTATUS NTAPI MmProtectSectionView(PMMSUPPORT AddressSpace, PMEMORY_AREA MemoryArea, PVOID BaseAddress, SIZE_T Length, ULONG Protect, PULONG OldProtect)
Definition: section.c:2063
PMEMORY_AREA NTAPI MmLocateMemoryAreaByAddress(PMMSUPPORT AddressSpace, PVOID Address)
Definition: marea.c:60
FORCEINLINE VOID MmUnlockAddressSpace(PMMSUPPORT AddressSpace)
Definition: mm.h:1704
#define MEMORY_AREA_SECTION_VIEW
Definition: mm.h:93
BOOLEAN DeleteInProgress
Definition: mm.h:253
#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 4557 of file section.c.

4558{
4559 DPRINT("MmUnmapViewInSystemSpace() called\n");
4560
4562}
FORCEINLINE PMMSUPPORT MmGetKernelAddressSpace(VOID)
Definition: mm.h:1726
static NTSTATUS MmUnmapViewOfSegment(PMMSUPPORT AddressSpace, PVOID BaseAddress)
Definition: section.c:3525
_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 3589 of file section.c.

3592{
3596 PVOID ImageBaseAddress = 0;
3597
3598 DPRINT("Opening memory area Process %p BaseAddress %p\n",
3600
3601 ASSERT(Process);
3602
3603 AddressSpace = &Process->Vm;
3604
3606 BaseAddress);
3607 if (MemoryArea == NULL ||
3608#ifdef NEWCC
3609 ((MemoryArea->Type != MEMORY_AREA_SECTION_VIEW) && (MemoryArea->Type != MEMORY_AREA_CACHE)) ||
3610#else
3612#endif
3614
3615 {
3617
3618 DPRINT1("Unable to find memory area at address %p.\n", BaseAddress);
3620 }
3621
3623 {
3624 ULONG i;
3625 ULONG NrSegments;
3626 PMM_IMAGE_SECTION_OBJECT ImageSectionObject;
3627 PMM_SECTION_SEGMENT SectionSegments;
3629
3630 Segment = MemoryArea->SectionData.Segment;
3631 ImageSectionObject = ImageSectionObjectFromSegment(Segment);
3632 SectionSegments = ImageSectionObject->Segments;
3633 NrSegments = ImageSectionObject->NrSegments;
3634
3636
3637 /* Search for the current segment within the section segments
3638 * and calculate the image base address */
3639 for (i = 0; i < NrSegments; i++)
3640 {
3641 if (Segment == &SectionSegments[i])
3642 {
3643 ImageBaseAddress = (char*)BaseAddress - (ULONG_PTR)SectionSegments[i].Image.VirtualAddress;
3644 break;
3645 }
3646 }
3647 if (i >= NrSegments)
3648 {
3649 KeBugCheck(MEMORY_MANAGEMENT);
3650 }
3651
3652 for (i = 0; i < NrSegments; i++)
3653 {
3654 PVOID SBaseAddress = (PVOID)
3655 ((char*)ImageBaseAddress + (ULONG_PTR)SectionSegments[i].Image.VirtualAddress);
3656
3657 Status = MmUnmapViewOfSegment(AddressSpace, SBaseAddress);
3658 if (!NT_SUCCESS(Status))
3659 {
3660 DPRINT1("MmUnmapViewOfSegment failed for %p (Process %p) with %lx\n",
3661 SBaseAddress, Process, Status);
3663 }
3664 }
3665 DPRINT("One mapping less for %p\n", ImageSectionObject->FileObject->SectionObjectPointer);
3666 InterlockedDecrement(&ImageSectionObject->MapCount);
3667 }
3668 else
3669 {
3671 PMMVAD Vad = &MemoryArea->VadNode;
3672 PCONTROL_AREA ControlArea = Vad->ControlArea;
3675 LARGE_INTEGER ViewOffset;
3676 ViewOffset.QuadPart = MemoryArea->SectionData.ViewOffset;
3677
3678 InterlockedIncrement64(Segment->ReferenceCount);
3679
3680 ViewSize = PAGE_SIZE + ((Vad->EndingVpn - Vad->StartingVpn) << PAGE_SHIFT);
3681
3683 if (!NT_SUCCESS(Status))
3684 {
3685 DPRINT1("MmUnmapViewOfSegment failed for %p (Process %p) with %lx\n",
3688 }
3689
3690 /* These might be deleted now */
3691 Vad = NULL;
3692 MemoryArea = NULL;
3693
3695 {
3696 /* Don't bother */
3697 MmDereferenceSegment(Segment);
3698 return STATUS_SUCCESS;
3699 }
3701
3702 FileObject = Segment->FileObject;
3704
3705 /* Don't bother for auto-delete closed file. */
3707 {
3709 MmDereferenceSegment(Segment);
3710 return STATUS_SUCCESS;
3711 }
3712
3713 /*
3714 * Flush only when last mapping is deleted.
3715 * FIXME: Why ControlArea == NULL? Or rather: is ControlArea ever not NULL here?
3716 */
3717 if (ControlArea == NULL || ControlArea->NumberOfMappedViews == 1)
3718 {
3719 while (ViewSize > 0)
3720 {
3721 ULONG FlushSize = min(ViewSize, PAGE_ROUND_DOWN(MAXULONG));
3722 MmFlushSegment(FileObject->SectionObjectPointer,
3723 &ViewOffset,
3724 FlushSize,
3725 NULL);
3726 ViewSize -= FlushSize;
3727 ViewOffset.QuadPart += FlushSize;
3728 }
3729 }
3730
3732 MmDereferenceSegment(Segment);
3733 }
3734
3735 /* Notify debugger */
3736 if (ImageBaseAddress && !SkipDebuggerNotify) DbgkUnMapViewOfSection(ImageBaseAddress);
3737
3738 return STATUS_SUCCESS;
3739}
#define InterlockedIncrement64(a)
Definition: btrfs_drv.h:143
DECLSPEC_NORETURN VOID NTAPI KeBugCheck(ULONG BugCheckCode)
Definition: bug.c:1430
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:1659
VOID NTAPI FsRtlAcquireFileExclusive(IN PFILE_OBJECT FileObject)
Definition: fastio.c:1634
#define MM_PHYSICALMEMORY_SEGMENT
Definition: mm.h:237
#define MM_DATAFILE_SEGMENT
Definition: mm.h:238
#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:4940
struct _MEMORY_AREA::@1792 SectionData
MMVAD VadNode
Definition: mm.h:249
ULONG_PTR VadType
Definition: mmtypes.h:694
PCONTROL_AREA ControlArea
Definition: mmtypes.h:736
MMVAD_FLAGS VadFlags
Definition: mmtypes.h:734
union _MMVAD::@2611 u
PMM_SECTION_SEGMENT Segments
Definition: mm.h:234
PFILE_OBJECT FileObject
Definition: mm.h:226
struct _MM_SECTION_SEGMENT::@1791 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:288
FORCEINLINE KIRQL MiAcquireExpansionLock(VOID)
Definition: miarm.h:1531
FORCEINLINE VOID MiReleaseExpansionLock(KIRQL OldIrql)
Definition: miarm.h:1544
PMM_SESSION_SPACE MmSessionSpace
Definition: session.c:21
#define PspSetProcessFlag(Process, Flag)
Definition: ps_x.h:33
LONG ResidentProcessCount
Definition: miarm.h:487
LONG ProcessReferenceToSession
Definition: miarm.h:494
LIST_ENTRY ProcessList
Definition: miarm.h:478
LONG ReferenceCount
Definition: miarm.h:471
int32_t * PLONG
Definition: typedefs.h:58

Referenced by MmCreateProcessAddressSpace().

◆ MiSessionCommitPageTables()

NTSTATUS NTAPI MiSessionCommitPageTables ( IN PVOID  StartVa,
IN PVOID  EndVa 
)

Definition at line 924 of file section.c.

926{
929 PMMPDE StartPde, EndPde;
931 PMMPFN Pfn1;
932 PFN_NUMBER PageCount = 0, ActualPages = 0, PageFrameNumber;
933
934 /* Windows sanity checks */
935 ASSERT(StartVa >= (PVOID)MmSessionBase);
937 ASSERT(PAGE_ALIGN(EndVa) == EndVa);
938
939 /* Get the start and end PDE, then loop each one */
940 StartPde = MiAddressToPde(StartVa);
941 EndPde = MiAddressToPde((PVOID)((ULONG_PTR)EndVa - 1));
942 Index = ((ULONG_PTR)StartVa - (ULONG_PTR)MmSessionBase) >> 22;
943 while (StartPde <= EndPde)
944 {
945#ifndef _M_AMD64
946 /* If we don't already have a page table for it, increment count */
947 if (MmSessionSpace->PageTables[Index].u.Long == 0) PageCount++;
948#endif
949 /* Move to the next one */
950 StartPde++;
951 Index++;
952 }
953
954 /* If there's no page tables to create, bail out */
955 if (PageCount == 0) return STATUS_SUCCESS;
956
957 /* Reset the start PDE and index */
958 StartPde = MiAddressToPde(StartVa);
959 Index = ((ULONG_PTR)StartVa - (ULONG_PTR)MmSessionBase) >> 22;
960
961 /* Loop each PDE while holding the working set lock */
962// MiLockWorkingSet(PsGetCurrentThread(),
963// &MmSessionSpace->GlobalVirtualAddress->Vm);
964#ifdef _M_AMD64
965_WARN("MiSessionCommitPageTables halfplemented for amd64")
970 DBG_UNREFERENCED_LOCAL_VARIABLE(PageFrameNumber);
971 ASSERT(FALSE);
972#else
973 while (StartPde <= EndPde)
974 {
975 /* Check if we already have a page table */
977 {
978 /* We don't, so the PDE shouldn't be ready yet */
979 ASSERT(StartPde->u.Hard.Valid == 0);
980
981 /* ReactOS check to avoid MiEnsureAvailablePageOrWait */
983
984 /* Acquire the PFN lock and grab a zero page */
985 OldIrql = MiAcquirePfnLock();
987 MI_SET_PROCESS2(PsGetCurrentProcess()->ImageFileName);
989 PageFrameNumber = MiRemoveZeroPage(Color);
990 TempPde.u.Hard.PageFrameNumber = PageFrameNumber;
991 MI_WRITE_VALID_PDE(StartPde, TempPde);
992
993 /* Write the page table in session space structure */
996
997 /* Initialize the PFN */
998 MiInitializePfnForOtherProcess(PageFrameNumber,
999 StartPde,
1001
1002 /* And now release the lock */
1003 MiReleasePfnLock(OldIrql);
1004
1005 /* Get the PFN entry and make sure there's no event for it */
1006 Pfn1 = MI_PFN_ELEMENT(PageFrameNumber);
1007 ASSERT(Pfn1->u1.Event == NULL);
1008
1009 /* Increment the number of pages */
1010 ActualPages++;
1011 }
1012
1013 /* Move to the next PDE */
1014 StartPde++;
1015 Index++;
1016 }
1017#endif
1018
1019 /* Make sure we didn't do more pages than expected */
1020 ASSERT(ActualPages <= PageCount);
1021
1022 /* Release the working set lock */
1023// MiUnlockWorkingSet(PsGetCurrentThread(),
1024// &MmSessionSpace->GlobalVirtualAddress->Vm);
1025
1026
1027 /* If we did at least one page... */
1028 if (ActualPages)
1029 {
1030 /* Update the performance counters! */
1033 }
1034
1035 /* Return status */
1036 return STATUS_SUCCESS;
1037}
#define InterlockedExchangeAddSizeT(a, b)
Definition: interlocked.h:196
VOID NTAPI MiInitializePfnForOtherProcess(IN PFN_NUMBER PageFrameIndex, IN PVOID PteAddress, IN PFN_NUMBER PteFrame)
Definition: pfnlist.c:1301
#define DBG_UNREFERENCED_LOCAL_VARIABLE(L)
Definition: ntbasedef.h:319
@ MI_USAGE_PAGE_TABLE
Definition: mm.h:334
#define _WARN(msg)
Definition: debug.h:263

Referenced by MiMapViewInSystemSpace().

◆ 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:1356
ULONG Flags
Definition: pstypes.h:1435
LIST_ENTRY SessionProcessLinks
Definition: pstypes.h:1274
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:444

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

1196{
1197 /* Make sure we are the owner of a safe acquisition */
1200
1201 /* The thread doesn't own it anymore */
1204
1205 /* Release the lock and re-enable APCs */
1206 ExReleasePushLockExclusive(&Process->Vm.WorkingSetMutex);
1208}
FORCEINLINE VOID ExReleasePushLockExclusive(PEX_PUSH_LOCK PushLock)
Definition: ex.h:1252
FORCEINLINE BOOLEAN MI_WS_OWNER(IN PEPROCESS Process)
Definition: miarm.h:1077

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

1472{
1474
1475 /* Check if the current owner is unsafe */
1477 {
1478 /* Release unsafely */
1480 *Safe = FALSE;
1481 *Shared = FALSE;
1482 }
1484 {
1485 /* Owner is safe and exclusive, release normally */
1487 *Safe = TRUE;
1488 *Shared = FALSE;
1489 }
1490 else
1491 {
1492 /* Owner is shared (implies safe), release normally */
1494 *Safe = TRUE;
1495 *Shared = TRUE;
1496 }
1497}
FORCEINLINE VOID MiUnlockProcessWorkingSetShared(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1215
FORCEINLINE VOID MiUnlockProcessWorkingSet(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1194

Referenced by MiGetPageProtection(), and MiMakeSystemAddressValid().

◆ MiUnlockProcessWorkingSetShared()

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

Definition at line 1215 of file miarm.h.

1217{
1218 /* Make sure we are the owner of a safe acquisition (because shared) */
1221
1222 /* Ensure we are in a shared acquisition */
1225
1226 /* Don't claim the lock anylonger */
1228
1229 /* Release the lock and re-enable APCs */
1230 ExReleasePushLockShared(&Process->Vm.WorkingSetMutex);
1232}
FORCEINLINE VOID ExReleasePushLockShared(PEX_PUSH_LOCK PushLock)
Definition: ex.h:1213

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

◆ MiUnlockProcessWorkingSetUnsafe()

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

◆ MiUnlockWorkingSet()

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

Definition at line 1351 of file miarm.h.

1353{
1354 /* Working set should be in global memory */
1355 ASSERT(MI_IS_SESSION_ADDRESS((PVOID)WorkingSet) == FALSE);
1356
1357 /* Which working set is this? */
1358 if (WorkingSet == &MmSystemCacheWs)
1359 {
1360 /* Release the system working set */
1364 }
1365 else if (WorkingSet->Flags.SessionSpace)
1366 {
1367 /* Release the session working set */
1371 }
1372 else
1373 {
1374 /* Release the process working set */
1378 }
1379
1380 /* Release the working set lock */
1381 ExReleasePushLockExclusive(&WorkingSet->WorkingSetMutex);
1382
1383 /* Unblock APCs */
1385}

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

◆ MiUnlockWorkingSetShared()

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

Definition at line 1389 of file miarm.h.

1392{
1393 /* Working set should be in global memory */
1394 ASSERT(MI_IS_SESSION_ADDRESS((PVOID)WorkingSet) == FALSE);
1395
1396 /* Which working set is this? */
1397 if (WorkingSet == &MmSystemCacheWs)
1398 {
1399 /* Release the system working set */
1403 }
1404 else if (WorkingSet->Flags.SessionSpace)
1405 {
1406 /* Release the session working set */
1410 }
1411 else
1412 {
1413 /* Release the process working set */
1417 }
1418
1419 /* Release the working set lock */
1420 ExReleasePushLockShared(&WorkingSet->WorkingSetMutex);
1421
1422 /* Unblock APCs */
1424}

Referenced by MmAccessFault(), and MmWorkingSetManager().

◆ MiUnmapViewOfSection()

NTSTATUS NTAPI MiUnmapViewOfSection ( IN PEPROCESS  Process,
IN PVOID  BaseAddress,
IN ULONG  Flags 
)

Definition at line 803 of file section.c.

806{
810 PMMVAD Vad;
811 PVOID DbgBase = NULL;
814 PETHREAD CurrentThread = PsGetCurrentThread();
815 PEPROCESS CurrentProcess = PsGetCurrentProcess();
816 PAGED_CODE();
817
818 /* Check if we need to lock the address space */
819 if (!Flags) MmLockAddressSpace(&Process->Vm);
820
821 /* Check for Mm Region */
824 {
825 /* Call Mm API */
828 return Status;
829 }
830
831 /* Check if we should attach to the process */
832 if (CurrentProcess != Process)
833 {
834 /* The process is different, do an attach */
836 Attached = TRUE;
837 }
838
839 /* Check if the process is already dead */
840 if (Process->VmDeleted)
841 {
842 /* Fail the call */
843 DPRINT1("Process died!\n");
846 goto Quickie;
847 }
848
849 /* Find the VAD for the address and make sure it's a section VAD */
851 if (!(Vad) || (Vad->u.VadFlags.PrivateMemory))
852 {
853 /* Couldn't find it, or invalid VAD, fail */
854 DPRINT1("No VAD or invalid VAD\n");
857 goto Quickie;
858 }
859
860 /* We should be attached */
862
863 /* We need the base address for the debugger message on image-backed VADs */
864 if (Vad->u.VadFlags.VadType == VadImageMap)
865 {
866 DbgBase = (PVOID)(Vad->StartingVpn >> PAGE_SHIFT);
867 }
868
869 /* Compute the size of the VAD region */
870 RegionSize = PAGE_SIZE + ((Vad->EndingVpn - Vad->StartingVpn) << PAGE_SHIFT);
871
872 /* For SEC_NO_CHANGE sections, we need some extra checks */
873 if (Vad->u.VadFlags.NoChange == 1)
874 {
875 /* Are we allowed to mess with this VAD? */
877 (PVOID)(Vad->StartingVpn >> PAGE_SHIFT),
880 if (!NT_SUCCESS(Status))
881 {
882 /* We failed */
883 DPRINT1("Trying to unmap protected VAD!\n");
885 goto Quickie;
886 }
887 }
888
889 /* Not currently supported */
891
892 /* FIXME: Remove VAD charges */
893
894 /* Lock the working set */
896
897 /* Remove the VAD */
898 ASSERT(Process->VadRoot.NumberGenericTableElements >= 1);
899 MiRemoveNode((PMMADDRESS_NODE)Vad, &Process->VadRoot);
901
902 /* Remove the PTEs for this view, which also releases the working set lock */
904
905 /* FIXME: Remove commitment */
906
907 /* Update performance counter and release the lock */
908 Process->VirtualSize -= RegionSize;
910
911 /* Destroy the VAD and return success */
912 ExFreePool(Vad);
914
915 /* Failure and success case -- send debugger message, detach, and return */
916Quickie:
917 if (DbgBase) DbgkUnMapViewOfSection(DbgBase);
919 return Status;
920}
VOID NTAPI MiRemoveMappedView(IN PEPROCESS CurrentProcess, IN PMMVAD Vad)
Definition: section.c:766
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
PMMVAD NTAPI MiLocateAddress(IN PVOID VirtualAddress)
Definition: vadnode.c:116
NTSTATUS NTAPI MiRosUnmapViewOfSection(IN PEPROCESS Process, IN PVOID BaseAddress, IN BOOLEAN SkipDebuggerNotify)
Definition: section.c:3589
NTSTATUS NTAPI MiCheckSecuredVad(IN PMMVAD Vad, IN PVOID Base, IN SIZE_T Size, IN ULONG ProtectionMask)
Definition: vadnode.c:903
__kernel_entry _Inout_ _Inout_ PSIZE_T RegionSize
Definition: mmfuncs.h:172
@ VadRotatePhysical
Definition: mmtypes.h:210
VOID NTAPI KeStackAttachProcess(IN PKPROCESS Process, OUT PRKAPC_STATE ApcState)
Definition: procobj.c:704
VOID NTAPI KeUnstackDetachProcess(IN PRKAPC_STATE ApcState)
Definition: procobj.c:756
VOID NTAPI PsReturnProcessNonPagedPoolQuota(_In_ PEPROCESS Process, _In_ SIZE_T Amount)
Returns the non paged quota pool that the process was taking up.
Definition: quota.c:938
ULONG_PTR NoChange
Definition: mmtypes.h:693
ULONG_PTR PrivateMemory
Definition: mmtypes.h:698
static BOOL Attached
Definition: vidbios.c:3905
KAPC_STATE
Definition: ketypes.h:1409

Referenced by MmUnmapViewOfSection(), and NtUnmapViewOfSection().

◆ 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:160
#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::@1556 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:3310

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:180
FORCEINLINE VOID MI_MAKE_HARDWARE_PTE_USER(IN PMMPTE NewPte, IN PMMPTE MappingPte, IN ULONG_PTR ProtectionMask, IN PFN_NUMBER PageFrameNumber)
Definition: miarm.h:827
#define MI_IS_SESSION_IMAGE_ADDRESS(Address)
Definition: miarm.h:168
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:1035
#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:807
FORCEINLINE VOID MI_UPDATE_VALID_PTE(IN PMMPTE PointerPte, IN MMPTE TempPte)
Definition: miarm.h:977
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:183
FORCEINLINE USHORT MiIncrementPageTableReferences(IN PVOID Address)
Definition: miarm.h:2481
#define MI_GET_NEXT_PROCESS_COLOR(x)
Definition: miarm.h:233
FORCEINLINE PFN_NUMBER MiRemoveZeroPageSafe(IN ULONG Color)
Definition: miarm.h:2415
#define UserMode
Definition: asm.h:35
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:347
@ MI_USAGE_PEB_TEB
Definition: mm.h:332
#define MI_SET_PROCESS(x)
Definition: mm.h:318
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
PFN_NUMBER NumberOfPrivatePages
Definition: pstypes.h:1300
KPROCESS Pcb
Definition: pstypes.h:1262
CHAR ImageFileName[16]
Definition: pstypes.h:1326
KTHREAD Tcb
Definition: pstypes.h:1103
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:455
ULONG Sp
Definition: ketypes.h:372
ULONG Pc
Definition: ketypes.h:375
ULONG Edi
Definition: ketypes.h:316
UINT64 Rsi
Definition: ketypes.h:456
UINT64 Rdx
Definition: ketypes.h:405
ULONG Lr
Definition: ketypes.h:373
ULONG EFlags
Definition: ketypes.h:469
ULONG R0
Definition: ketypes.h:367
ULONG Ebx
Definition: ketypes.h:318
ULONG Ecx
Definition: ketypes.h:311
UINT64 Rbx
Definition: ketypes.h:454
ULONG Eip
Definition: ketypes.h:321
UINT64 Rax
Definition: ketypes.h:403
UINT64 Rip
Definition: ketypes.h:464
ULONG R2
Definition: ketypes.h:369
ULONG R1
Definition: ketypes.h:368
ULONG Eax
Definition: ketypes.h:312
UINT64 Rcx
Definition: ketypes.h:404
ULONG Esi
Definition: ketypes.h:317
ULONG Edx
Definition: ketypes.h:310
UINT64 R11
Definition: ketypes.h:409
ULONG R12
Definition: ketypes.h:371
PKEVENT Event
Definition: mm.h:379

Referenced by MmAccessFault().

◆ MmArmInitSystem()

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

Definition at line 2046 of file mminit.c.

2048{
2049 ULONG i;
2050 BOOLEAN IncludeType[LoaderMaximum];
2051 PVOID Bitmap;
2053 PFN_NUMBER PageCount;
2054#if DBG
2055 ULONG j;
2056 PMMPTE PointerPte, TestPte;
2057 MMPTE TempPte;
2058#endif
2059
2060 /* Dump memory descriptors */
2062
2063 //
2064 // Instantiate memory that we don't consider RAM/usable
2065 // We use the same exclusions that Windows does, in order to try to be
2066 // compatible with WinLDR-style booting
2067 //
2068 for (i = 0; i < LoaderMaximum; i++) IncludeType[i] = TRUE;
2069 IncludeType[LoaderBad] = FALSE;
2070 IncludeType[LoaderFirmwarePermanent] = FALSE;
2071 IncludeType[LoaderSpecialMemory] = FALSE;
2072 IncludeType[LoaderBBTMemory] = FALSE;
2073 if (Phase == 0)
2074 {
2075 /* Count physical pages on the system */
2076 MiScanMemoryDescriptors(LoaderBlock);
2077
2078 /* Initialize the phase 0 temporary event */
2080
2081 /* Set all the events to use the temporary event for now */
2088
2089 //
2090 // Default throttling limits for Cc
2091 // May be ajusted later on depending on system type
2092 //
2093 MmThrottleTop = 450;
2094 MmThrottleBottom = 127;
2095
2096 //
2097 // Define the basic user vs. kernel address space separation
2098 //
2102
2103 /* Highest PTE and PDE based on the addresses above */
2106#if (_MI_PAGING_LEVELS >= 3)
2107 MiHighestUserPpe = MiAddressToPpe(MmHighestUserAddress);
2108#if (_MI_PAGING_LEVELS >= 4)
2109 MiHighestUserPxe = MiAddressToPxe(MmHighestUserAddress);
2110#endif
2111#endif
2112 //
2113 // Get the size of the boot loader's image allocations and then round
2114 // that region up to a PDE size, so that any PDEs we might create for
2115 // whatever follows are separate from the PDEs that boot loader might've
2116 // already created (and later, we can blow all that away if we want to).
2117 //
2122
2123 /* Initialize session space address layout */
2125
2126 /* Set the based section highest address */
2128
2129 /* Loop all 8 standby lists */
2130 for (i = 0; i < 8; i++)
2131 {
2132 /* Initialize them */
2137 }
2138
2139 /* Initialize the user mode image list */
2141
2142 /* Initalize the Working set list */
2144
2145 /* Initialize critical section timeout value (relative time is negative) */
2147
2148 /* Initialize the paged pool mutex and the section commit mutex */
2152
2153 /* Initialize the Loader Lock */
2155
2156 /* Set up the zero page event */
2158
2159 /* Initialize the dead stack S-LIST */
2161
2162 //
2163 // Check if this is a machine with less than 19MB of RAM
2164 //
2165 PageCount = MmNumberOfPhysicalPages;
2166 if (PageCount < MI_MIN_PAGES_FOR_SYSPTE_TUNING)
2167 {
2168 //
2169 // Use the very minimum of system PTEs
2170 //
2171 MmNumberOfSystemPtes = 7000;
2172 }
2173 else
2174 {
2175 //
2176 // Use the default
2177 //
2178 MmNumberOfSystemPtes = 11000;
2179 if (PageCount > MI_MIN_PAGES_FOR_SYSPTE_BOOST)
2180 {
2181 //
2182 // Double the amount of system PTEs
2183 //
2185 }
2187 {
2188 //
2189 // Double the amount of system PTEs
2190 //
2192 }
2193 if (MmSpecialPoolTag != 0 && MmSpecialPoolTag != -1)
2194 {
2195 //
2196 // Add some extra PTEs for special pool
2197 //
2198 MmNumberOfSystemPtes += 0x6000;
2199 }
2200 }
2201
2202 DPRINT("System PTE count has been tuned to %lu (%lu bytes)\n",
2204
2205 /* Check if no values are set for the heap limits */
2206 if (MmHeapSegmentReserve == 0)
2207 {
2209 }
2210
2211 if (MmHeapSegmentCommit == 0)
2212 {
2214 }
2215
2217 {
2219 }
2220
2222 {
2224 }
2225
2226 /* Initialize the working set lock */
2228
2229 /* Set commit limit */
2232
2233 /* Has the allocation fragment been setup? */
2235 {
2236 /* Use the default value */
2238 if (PageCount < ((256 * _1MB) / PAGE_SIZE))
2239 {
2240 /* On memory systems with less than 256MB, divide by 4 */
2242 }
2243 else if (PageCount < (_1GB / PAGE_SIZE))
2244 {
2245 /* On systems with less than 1GB, divide by 2 */
2247 }
2248 }
2249 else
2250 {
2251 /* Convert from 1KB fragments to pages */
2254
2255 /* Don't let it past the maximum */
2258
2259 /* Don't let it too small either */
2262 }
2263
2264 /* Check for kernel stack size that's too big */
2266 {
2267 /* Sanitize to default value */
2269 }
2270 else
2271 {
2272 /* Take the registry setting, and convert it into bytes */
2274
2275 /* Now align it to a page boundary */
2277
2278 /* Sanity checks */
2280 ASSERT((MmLargeStackSize & (PAGE_SIZE - 1)) == 0);
2281
2282 /* Make sure it's not too low */
2284 }
2285
2286 /* Compute color information (L2 cache-separated paging lists) */
2288
2289 // Calculate the number of bytes for the PFN database
2290 // then add the color tables and convert to pages
2294
2295 // We have to add one to the count here, because in the process of
2296 // shifting down to the page size, we actually ended up getting the
2297 // lower aligned size (so say, 0x5FFFF bytes is now 0x5F pages).
2298 // Later on, we'll shift this number back into bytes, which would cause
2299 // us to end up with only 0x5F000 bytes -- when we actually want to have
2300 // 0x60000 bytes.
2302
2303 /* Initialize the platform-specific parts */
2304 MiInitMachineDependent(LoaderBlock);
2305
2306#if DBG
2307 /* Prototype PTEs are assumed to be in paged pool, so check if the math works */
2308 PointerPte = (PMMPTE)MmPagedPoolStart;
2309 MI_MAKE_PROTOTYPE_PTE(&TempPte, PointerPte);
2310 TestPte = MiProtoPteToPte(&TempPte);
2311 ASSERT(PointerPte == TestPte);
2312
2313 /* Try the last nonpaged pool address */
2314 PointerPte = (PMMPTE)MI_NONPAGED_POOL_END;
2315 MI_MAKE_PROTOTYPE_PTE(&TempPte, PointerPte);
2316 TestPte = MiProtoPteToPte(&TempPte);
2317 ASSERT(PointerPte == TestPte);
2318
2319 /* Try a bunch of random addresses near the end of the address space */
2320 PointerPte = (PMMPTE)((ULONG_PTR)MI_HIGHEST_SYSTEM_ADDRESS - 0x37FFF);
2321 for (j = 0; j < 20; j += 1)
2322 {
2323 MI_MAKE_PROTOTYPE_PTE(&TempPte, PointerPte);
2324 TestPte = MiProtoPteToPte(&TempPte);
2325 ASSERT(PointerPte == TestPte);
2326 PointerPte++;
2327 }
2328
2329 /* Subsection PTEs are always in nonpaged pool, pick a random address to try */
2331 MI_MAKE_SUBSECTION_PTE(&TempPte, PointerPte);
2333 ASSERT(PointerPte == TestPte);
2334#endif
2335
2336 //
2337 // Build the physical memory block
2338 //
2340 IncludeType);
2341
2342 //
2343 // Allocate enough buffer for the PFN bitmap
2344 // Align it up to a 32-bit boundary
2345 //
2347 (((MmHighestPhysicalPage + 1) + 31) / 32) * 4,
2348 TAG_MM);
2349 if (!Bitmap)
2350 {
2351 //
2352 // This is critical
2353 //
2354 KeBugCheckEx(INSTALL_MORE_MEMORY,
2358 0x101);
2359 }
2360
2361 //
2362 // Initialize it and clear all the bits to begin with
2363 //
2365 Bitmap,
2368
2369 //
2370 // Loop physical memory runs
2371 //
2372 for (i = 0; i < MmPhysicalMemoryBlock->NumberOfRuns; i++)
2373 {
2374 //
2375 // Get the run
2376 //
2378 DPRINT("PHYSICAL RAM [0x%08p to 0x%08p]\n",
2379 Run->BasePage << PAGE_SHIFT,
2380 (Run->BasePage + Run->PageCount) << PAGE_SHIFT);
2381
2382 //
2383 // Make sure it has pages inside it
2384 //
2385 if (Run->PageCount)
2386 {
2387 //
2388 // Set the bits in the PFN bitmap
2389 //
2390 RtlSetBits(&MiPfnBitMap, (ULONG)Run->BasePage, (ULONG)Run->PageCount);
2391 }
2392 }
2393
2394 /* Look for large page cache entries that need caching */
2396
2397 /* Loop for HAL Heap I/O device mappings that need coherency tracking */
2399
2400 /* Set the initial resident page count */
2402
2403 /* Initialize large page structures on PAE/x64, and MmProcessList on x86 */
2405
2406 /* Check if the registry says any drivers should be loaded with large pages */
2408
2409 /* Relocate the boot drivers into system PTE space and fixup their PFNs */
2410 MiReloadBootLoadedDrivers(LoaderBlock);
2411
2412 /* FIXME: Call out into Driver Verifier for initialization */
2413
2414 /* Check how many pages the system has */
2415 if (MmNumberOfPhysicalPages <= ((13 * _1MB) / PAGE_SIZE))
2416 {
2417 /* Set small system */
2420 }
2421 else if (MmNumberOfPhysicalPages <= ((19 * _1MB) / PAGE_SIZE))
2422 {
2423 /* Set small system and add 100 pages for the cache */
2427 }
2428 else
2429 {
2430 /* Set medium system and add 400 pages for the cache */
2434 }
2435
2436 /* Check for less than 24MB */
2437 if (MmNumberOfPhysicalPages < ((24 * _1MB) / PAGE_SIZE))
2438 {
2439 /* No more than 32 pages */
2441 }
2442
2443 /* Check for more than 32MB */
2444 if (MmNumberOfPhysicalPages >= ((32 * _1MB) / PAGE_SIZE))
2445 {
2446 /* Check for product type being "Wi" for WinNT */
2447 if (MmProductType == '\0i\0W')
2448 {
2449 /* Then this is a large system */
2451 }
2452 else
2453 {
2454 /* For servers, we need 64MB to consider this as being large */
2455 if (MmNumberOfPhysicalPages >= ((64 * _1MB) / PAGE_SIZE))
2456 {
2457 /* Set it as large */
2459 }
2460 }
2461 }
2462
2463 /* Check for more than 33 MB */
2464 if (MmNumberOfPhysicalPages > ((33 * _1MB) / PAGE_SIZE))
2465 {
2466 /* Add another 500 pages to the cache */
2468 }
2469
2470 /* Now setup the shared user data fields */
2471 ASSERT(SharedUserData->NumberOfPhysicalPages == 0);
2472 SharedUserData->NumberOfPhysicalPages = MmNumberOfPhysicalPages;
2473 SharedUserData->LargePageMinimum = 0;
2474
2475 /* Check for workstation (Wi for WinNT) */
2476 if (MmProductType == '\0i\0W')
2477 {
2478 /* Set Windows NT Workstation product type */
2479 SharedUserData->NtProductType = NtProductWinNt;
2480 MmProductType = 0;
2481
2482 /* For this product, we wait till the last moment to throttle */
2483 MmThrottleTop = 250;
2484 MmThrottleBottom = 30;
2485 }
2486 else
2487 {
2488 /* Check for LanMan server (La for LanmanNT) */
2489 if (MmProductType == '\0a\0L')
2490 {
2491 /* This is a domain controller */
2492 SharedUserData->NtProductType = NtProductLanManNt;
2493 }
2494 else
2495 {
2496 /* Otherwise it must be a normal server (Se for ServerNT) */
2497 SharedUserData->NtProductType = NtProductServer;
2498 }
2499
2500 /* Set the product type, and make the system more aggressive with low memory */
2501 MmProductType = 1;
2502 MmMinimumFreePages = 81;
2503
2504 /* We will throttle earlier to preserve memory */
2505 MmThrottleTop = 450;
2506 MmThrottleBottom = 80;
2507 }
2508
2509 /* Update working set tuning parameters */
2511
2512 /* Finetune the page count by removing working set and NP expansion */
2516 if (MmResidentAvailablePages <= 0)
2517 {
2518 /* This should not happen */
2519 DPRINT1("System cache working set too big\n");
2520 return FALSE;
2521 }
2522
2523 /* Define limits for system cache */
2524#ifdef _M_AMD64
2526#else
2528#endif
2530#ifdef _M_AMD64
2532#else
2534#endif
2535
2536 /* Initialize the system cache */
2537 //MiInitializeSystemCache(MmSystemCacheWsMinimum, MmAvailablePages);
2538
2539 /* Update the commit limit */
2541 if (MmTotalCommitLimit > 1024) MmTotalCommitLimit -= 1024;
2543
2544 /* Size up paged pool and build the shadow system page directory */
2546
2547 /* Debugger physical memory support is now ready to be used */
2549
2550 /* Initialize the loaded module list */
2551 MiInitializeLoadedModuleList(LoaderBlock);
2552 }
2553
2554 //
2555 // Always return success for now
2556 //
2557 return TRUE;
2558}
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:1203
VOID NTAPI MiBuildPagedPool(VOID)
Definition: mminit.c:1751
VOID NTAPI MiScanMemoryDescriptors(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: mminit.c:403
VOID NTAPI MiAddHalIoMappings(VOID)
Definition: mminit.c:1418
VOID NTAPI MiDbgDumpMemoryDescriptors(VOID)
Definition: mminit.c:1994
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:1622
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:508
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
@ 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:1013
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
NTSYSAPI void WINAPI RtlSetBits(PRTL_BITMAP, ULONG, ULONG)
PLOADER_PARAMETER_BLOCK KeLoaderBlock
Definition: krnlinit.c:29
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:3351

◆ MmInitializeMemoryLimits()

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

Definition at line 1622 of file mminit.c.

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

484{
485 PFN_NUMBER Pfn;
486
487 /* Make sure we have enough pages */
488 if (PageCount > MxFreeDescriptor->PageCount)
489 {
490 /* Crash the system */
491 KeBugCheckEx(INSTALL_MORE_MEMORY,
495 PageCount);
496 }
497
498 /* Use our lowest usable free pages */
500 MxFreeDescriptor->BasePage += PageCount;
501 MxFreeDescriptor->PageCount -= PageCount;
502 return Pfn;
503}

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 561 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

Definition at line 23 of file syspte.c.

Referenced by MiInitializeSystemPtes(), MiReleaseSystemPtes(), and MmUnmapLockedPages().

◆ MmSystemPtesStart

PMMPTE MmSystemPtesStart[MaximumPtePoolTypes]
extern

Definition at line 22 of file syspte.c.

Referenced by MiInitializeSystemPtes(), MiReleaseSystemPtes(), and MmUnmapLockedPages().

◆ 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