/* * PROJECT: ReactOS Kernel * LICENSE: BSD - See COPYING.ARM in the top level directory * FILE: ntoskrnl/mm/ARM3/miarm.h * PURPOSE: ARM Memory Manager Header * PROGRAMMERS: ReactOS Portable Systems Group */ #ifndef _M_AMD64 #define MI_MIN_PAGES_FOR_NONPAGED_POOL_TUNING ((255 * _1MB) >> PAGE_SHIFT) #define MI_MIN_PAGES_FOR_SYSPTE_TUNING ((19 * _1MB) >> PAGE_SHIFT) #define MI_MIN_PAGES_FOR_SYSPTE_BOOST ((32 * _1MB) >> PAGE_SHIFT) #define MI_MAX_INIT_NONPAGED_POOL_SIZE (128 * _1MB) #define MI_MAX_NONPAGED_POOL_SIZE (128 * _1MB) #define MI_MAX_FREE_PAGE_LISTS 4 #define MI_MIN_INIT_PAGED_POOLSIZE (32 * _1MB) #define MI_SESSION_VIEW_SIZE (20 * _1MB) #define MI_SESSION_POOL_SIZE (16 * _1MB) #define MI_SESSION_IMAGE_SIZE (8 * _1MB) #define MI_SESSION_WORKING_SET_SIZE (4 * _1MB) #define MI_SESSION_SIZE (MI_SESSION_VIEW_SIZE + \ MI_SESSION_POOL_SIZE + \ MI_SESSION_IMAGE_SIZE + \ MI_SESSION_WORKING_SET_SIZE) #define MI_SYSTEM_VIEW_SIZE (16 * _1MB) #define MI_SYSTEM_CACHE_WS_START (PVOID)0xC0C00000 #define MI_PAGED_POOL_START (PVOID)0xE1000000 #define MI_NONPAGED_POOL_END (PVOID)0xFFBE0000 #define MI_DEBUG_MAPPING (PVOID)0xFFBFF000 #define MI_SYSTEM_PTE_BASE (PVOID)MiAddressToPte(NULL) #define MI_MIN_SECONDARY_COLORS 8 #define MI_SECONDARY_COLORS 64 #define MI_MAX_SECONDARY_COLORS 1024 #define MI_MIN_ALLOCATION_FRAGMENT (4 * _1KB) #define MI_ALLOCATION_FRAGMENT (64 * _1KB) #define MI_MAX_ALLOCATION_FRAGMENT (2 * _1MB) #define MM_HIGHEST_VAD_ADDRESS \ (PVOID)((ULONG_PTR)MM_HIGHEST_USER_ADDRESS - (16 * PAGE_SIZE)) #define MI_LOWEST_VAD_ADDRESS (PVOID)MM_LOWEST_USER_ADDRESS #endif /* !_M_AMD64 */ /* Make the code cleaner with some definitions for size multiples */ #define _1KB (1024u) #define _1MB (1024 * _1KB) #define _1GB (1024 * _1MB) /* Everyone loves 64K */ #define _64K (64 * _1KB) /* Area mapped by a PDE */ #define PDE_MAPPED_VA (PTE_COUNT * PAGE_SIZE) /* Size of a page table */ #define PT_SIZE (PTE_COUNT * sizeof(MMPTE)) /* Size of a page directory */ #define PD_SIZE (PDE_COUNT * sizeof(MMPDE)) /* Size of all page directories for a process */ #define SYSTEM_PD_SIZE (PD_COUNT * PD_SIZE) /* Architecture specific count of PDEs in a directory, and count of PTEs in a PT */ #ifdef _M_IX86 #define PD_COUNT 1 #define PDE_COUNT 1024 #define PTE_COUNT 1024 C_ASSERT(SYSTEM_PD_SIZE == PAGE_SIZE); #elif _M_ARM #define PD_COUNT 1 #define PDE_COUNT 4096 #define PTE_COUNT 256 #else #define PD_COUNT PPE_PER_PAGE #define PDE_COUNT PDE_PER_PAGE #define PTE_COUNT PTE_PER_PAGE #endif #ifdef _M_IX86 #define IMAGE_FILE_MACHINE_NATIVE IMAGE_FILE_MACHINE_I386 #elif _M_ARM #define IMAGE_FILE_MACHINE_NATIVE IMAGE_FILE_MACHINE_ARM #elif _M_AMD64 #define IMAGE_FILE_MACHINE_NATIVE IMAGE_FILE_MACHINE_AMD64 #else #error Define these please! #endif // // Protection Bits part of the internal memory manager Protection Mask // Taken from http://www.reactos.org/wiki/Techwiki:Memory_management_in_the_Windows_XP_kernel // and public assertions. // #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_NOCACHE 8 #define MM_DECOMMIT 0x10 #define MM_NOACCESS (MM_DECOMMIT | MM_NOCACHE) #define MM_INVALID_PROTECTION 0xFFFFFFFF // // Specific PTE Definitions that map to the Memory Manager's Protection Mask Bits // The Memory Manager's definition define the attributes that must be preserved // and these PTE definitions describe the attributes in the hardware sense. This // helps deal with hardware differences between the actual boolean expression of // the argument. // // For example, in the logical attributes, we want to express read-only as a flag // but on x86, it is writability that must be set. On the other hand, on x86, just // like in the kernel, it is disabling the caches that requires a special flag, // while on certain architectures such as ARM, it is enabling the cache which // requires a flag. // #if defined(_M_IX86) || defined(_M_AMD64) // // Access Flags // #define PTE_READONLY 0 #define PTE_EXECUTE 0 // Not worrying about NX yet #define PTE_EXECUTE_READ 0 // Not worrying about NX yet #define PTE_READWRITE 0x2 #define PTE_WRITECOPY 0x200 #define PTE_EXECUTE_READWRITE 0x0 #define PTE_EXECUTE_WRITECOPY 0x200 #define PTE_PROTOTYPE 0x400 // // Cache flags // #define PTE_ENABLE_CACHE 0 #define PTE_DISABLE_CACHE 0x10 #define PTE_WRITECOMBINED_CACHE 0x10 #elif defined(_M_ARM) #else #error Define these please! #endif extern const ULONG MmProtectToPteMask[32]; extern const ULONG MmProtectToValue[32]; // // Assertions for session images, addresses, and PTEs // #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)) // // Corresponds to MMPTE_SOFTWARE.Protection // #ifdef _M_IX86 #define MM_PTE_SOFTWARE_PROTECTION_BITS 5 #elif _M_ARM #define MM_PTE_SOFTWARE_PROTECTION_BITS 5 #elif _M_AMD64 #define MM_PTE_SOFTWARE_PROTECTION_BITS 5 #else #error Define these please! #endif // // Creates a software PTE with the given protection // #define MI_MAKE_SOFTWARE_PTE(p, x) ((p)->u.Long = (x << MM_PTE_SOFTWARE_PROTECTION_BITS)) // // Marks a PTE as deleted // #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) // // Special values for LoadedImports // #define MM_SYSLDR_NO_IMPORTS (PVOID)0xFFFFFFFE #define MM_SYSLDR_BOOT_LOADED (PVOID)0xFFFFFFFF #define MM_SYSLDR_SINGLE_ENTRY 0x1 #if defined(_M_IX86) || defined(_M_ARM) // // PFN List Sentinel // #define LIST_HEAD 0xFFFFFFFF // // Because GCC cannot automatically downcast 0xFFFFFFFF to lesser-width bits, // we need a manual definition suited to the number of bits in the PteFrame. // This is used as a LIST_HEAD for the colored list // #define COLORED_LIST_HEAD ((1 << 25) - 1) // 0x1FFFFFF #elif defined(_M_AMD64) #define LIST_HEAD 0xFFFFFFFFFFFFFFFFLL #define COLORED_LIST_HEAD ((1 << 57) - 1) // 0x1FFFFFFFFFFFFFFLL #else #error Define these please! #endif // // Special IRQL value (found in assertions) // #define MM_NOIRQL (KIRQL)0xFFFFFFFF // // Returns the color of a page // #define MI_GET_PAGE_COLOR(x) ((x) & MmSecondaryColorMask) #define MI_GET_NEXT_COLOR(x) (MI_GET_PAGE_COLOR(++MmSystemPageColor)) #define MI_GET_NEXT_PROCESS_COLOR(x) (MI_GET_PAGE_COLOR(++(x)->NextPageColor)) #ifdef _M_IX86 // // Decodes a Prototype PTE into the underlying PTE // #define MiProtoPteToPte(x) \ (PMMPTE)((ULONG_PTR)MmPagedPoolStart + \ (((x)->u.Proto.ProtoAddressHigh << 7) | (x)->u.Proto.ProtoAddressLow)) #endif // // Prototype PTEs that don't yet have a pagefile association // #define MI_PTE_LOOKUP_NEEDED 0xFFFFF // // System views are binned into 64K chunks // #define MI_SYSTEM_VIEW_BUCKET_SIZE _64K // // FIXFIX: These should go in ex.h after the pool merge // #ifdef _M_AMD64 #define POOL_BLOCK_SIZE 16 #else #define POOL_BLOCK_SIZE 8 #endif #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)) typedef struct _POOL_DESCRIPTOR { POOL_TYPE PoolType; ULONG PoolIndex; ULONG RunningAllocs; ULONG RunningDeAllocs; ULONG TotalPages; ULONG TotalBigPages; ULONG Threshold; PVOID LockAddress; PVOID PendingFrees; LONG PendingFreeDepth; SIZE_T TotalBytes; SIZE_T Spare0; LIST_ENTRY ListHeads[POOL_LISTS_PER_PAGE]; } POOL_DESCRIPTOR, *PPOOL_DESCRIPTOR; typedef struct _POOL_HEADER { union { struct { #ifdef _M_AMD64 ULONG PreviousSize:8; ULONG PoolIndex:8; ULONG BlockSize:8; ULONG PoolType:8; #else USHORT PreviousSize:9; USHORT PoolIndex:7; USHORT BlockSize:9; USHORT PoolType:7; #endif }; ULONG Ulong1; }; #ifdef _M_AMD64 ULONG PoolTag; #endif union { #ifdef _M_AMD64 PEPROCESS ProcessBilled; #else ULONG PoolTag; #endif struct { USHORT AllocatorBackTraceIndex; USHORT PoolTagHash; }; }; } POOL_HEADER, *PPOOL_HEADER; C_ASSERT(sizeof(POOL_HEADER) == POOL_BLOCK_SIZE); C_ASSERT(POOL_BLOCK_SIZE == sizeof(LIST_ENTRY)); extern ULONG ExpNumberOfPagedPools; extern POOL_DESCRIPTOR NonPagedPoolDescriptor; extern PPOOL_DESCRIPTOR ExpPagedPoolDescriptor[16 + 1]; extern PVOID PoolTrackTable; // // END FIXFIX // typedef struct _MI_LARGE_PAGE_DRIVER_ENTRY { LIST_ENTRY Links; UNICODE_STRING BaseName; } MI_LARGE_PAGE_DRIVER_ENTRY, *PMI_LARGE_PAGE_DRIVER_ENTRY; typedef enum _MMSYSTEM_PTE_POOL_TYPE { SystemPteSpace, NonPagedPoolExpansion, MaximumPtePoolTypes } MMSYSTEM_PTE_POOL_TYPE; typedef enum _MI_PFN_CACHE_ATTRIBUTE { MiNonCached, MiCached, MiWriteCombined, MiNotMapped } MI_PFN_CACHE_ATTRIBUTE, *PMI_PFN_CACHE_ATTRIBUTE; typedef struct _PHYSICAL_MEMORY_RUN { ULONG BasePage; ULONG PageCount; } PHYSICAL_MEMORY_RUN, *PPHYSICAL_MEMORY_RUN; typedef struct _PHYSICAL_MEMORY_DESCRIPTOR { ULONG NumberOfRuns; ULONG NumberOfPages; PHYSICAL_MEMORY_RUN Run[1]; } PHYSICAL_MEMORY_DESCRIPTOR, *PPHYSICAL_MEMORY_DESCRIPTOR; typedef struct _MMCOLOR_TABLES { PFN_NUMBER Flink; PVOID Blink; PFN_NUMBER Count; } MMCOLOR_TABLES, *PMMCOLOR_TABLES; typedef struct _MI_LARGE_PAGE_RANGES { PFN_NUMBER StartFrame; PFN_NUMBER LastFrame; } MI_LARGE_PAGE_RANGES, *PMI_LARGE_PAGE_RANGES; typedef struct _MMVIEW { ULONG_PTR Entry; PCONTROL_AREA ControlArea; } MMVIEW, *PMMVIEW; typedef struct _MMSESSION { KGUARDED_MUTEX SystemSpaceViewLock; PKGUARDED_MUTEX SystemSpaceViewLockPointer; PCHAR SystemSpaceViewStart; PMMVIEW SystemSpaceViewTable; ULONG SystemSpaceHashSize; ULONG SystemSpaceHashEntries; ULONG SystemSpaceHashKey; ULONG BitmapFailures; PRTL_BITMAP SystemSpaceBitMap; } MMSESSION, *PMMSESSION; extern MMPTE HyperTemplatePte; extern MMPDE ValidKernelPde; extern MMPTE ValidKernelPte; extern MMPDE DemandZeroPde; extern MMPTE PrototypePte; extern BOOLEAN MmLargeSystemCache; extern BOOLEAN MmZeroPageFile; extern BOOLEAN MmProtectFreedNonPagedPool; extern BOOLEAN MmTrackLockedPages; extern BOOLEAN MmTrackPtes; extern BOOLEAN MmDynamicPfn; extern BOOLEAN MmMirroring; extern BOOLEAN MmMakeLowMemory; extern BOOLEAN MmEnforceWriteProtection; extern SIZE_T MmAllocationFragment; extern ULONG MmConsumedPoolPercentage; extern ULONG MmVerifyDriverBufferType; extern ULONG MmVerifyDriverLevel; extern WCHAR MmVerifyDriverBuffer[512]; extern WCHAR MmLargePageDriverBuffer[512]; extern LIST_ENTRY MiLargePageDriverList; extern BOOLEAN MiLargePageAllDrivers; extern ULONG MmVerifyDriverBufferLength; extern ULONG MmLargePageDriverBufferLength; extern SIZE_T MmSizeOfNonPagedPoolInBytes; extern SIZE_T MmMaximumNonPagedPoolInBytes; extern PFN_NUMBER MmMaximumNonPagedPoolInPages; extern PFN_NUMBER MmSizeOfPagedPoolInPages; extern PVOID MmNonPagedSystemStart; extern PVOID MmNonPagedPoolStart; extern PVOID MmNonPagedPoolExpansionStart; extern PVOID MmNonPagedPoolEnd; extern SIZE_T MmSizeOfPagedPoolInBytes; extern PVOID MmPagedPoolStart; extern PVOID MmPagedPoolEnd; extern PVOID MmSessionBase; extern SIZE_T MmSessionSize; extern PMMPTE MmFirstReservedMappingPte, MmLastReservedMappingPte; extern PMMPTE MiFirstReservedZeroingPte; extern MI_PFN_CACHE_ATTRIBUTE MiPlatformCacheAttributes[2][MmMaximumCacheType]; extern PPHYSICAL_MEMORY_DESCRIPTOR MmPhysicalMemoryBlock; extern SIZE_T MmBootImageSize; extern PMMPTE MmSystemPtesStart[MaximumPtePoolTypes]; extern PMMPTE MmSystemPtesEnd[MaximumPtePoolTypes]; extern PMEMORY_ALLOCATION_DESCRIPTOR MxFreeDescriptor; extern MEMORY_ALLOCATION_DESCRIPTOR MxOldFreeDescriptor; extern ULONG_PTR MxPfnAllocation; extern MM_PAGED_POOL_INFO MmPagedPoolInfo; extern RTL_BITMAP MiPfnBitMap; extern KGUARDED_MUTEX MmPagedPoolMutex; extern PVOID MmPagedPoolStart; extern PVOID MmPagedPoolEnd; extern PVOID MmNonPagedSystemStart; extern PVOID MiSystemViewStart; extern SIZE_T MmSystemViewSize; extern PVOID MmSessionBase; extern PVOID MiSessionSpaceEnd; extern PMMPTE MiSessionImagePteStart; extern PMMPTE MiSessionImagePteEnd; extern PMMPTE MiSessionBasePte; extern PMMPTE MiSessionLastPte; extern SIZE_T MmSizeOfPagedPoolInBytes; extern PMMPTE MmSystemPagePtes; extern PVOID MmSystemCacheStart; extern PVOID MmSystemCacheEnd; extern MMSUPPORT MmSystemCacheWs; extern SIZE_T MmAllocatedNonPagedPool; extern ULONG_PTR MmSubsectionBase; extern ULONG MmSpecialPoolTag; extern PVOID MmHyperSpaceEnd; extern PMMWSL MmSystemCacheWorkingSetList; extern SIZE_T MmMinimumNonPagedPoolSize; extern ULONG MmMinAdditionNonPagedPoolPerMb; extern SIZE_T MmDefaultMaximumNonPagedPool; extern ULONG MmMaxAdditionNonPagedPoolPerMb; extern ULONG MmSecondaryColors; extern ULONG MmSecondaryColorMask; extern ULONG_PTR MmNumberOfSystemPtes; extern ULONG MmMaximumNonPagedPoolPercent; extern ULONG MmLargeStackSize; extern PMMCOLOR_TABLES MmFreePagesByColor[FreePageList + 1]; extern ULONG MmProductType; extern MM_SYSTEMSIZE MmSystemSize; extern PKEVENT MiLowMemoryEvent; extern PKEVENT MiHighMemoryEvent; extern PKEVENT MiLowPagedPoolEvent; extern PKEVENT MiHighPagedPoolEvent; extern PKEVENT MiLowNonPagedPoolEvent; extern PKEVENT MiHighNonPagedPoolEvent; extern PFN_NUMBER MmLowMemoryThreshold; extern PFN_NUMBER MmHighMemoryThreshold; extern PFN_NUMBER MiLowPagedPoolThreshold; extern PFN_NUMBER MiHighPagedPoolThreshold; extern PFN_NUMBER MiLowNonPagedPoolThreshold; extern PFN_NUMBER MiHighNonPagedPoolThreshold; extern PFN_NUMBER MmMinimumFreePages; extern PFN_NUMBER MmPlentyFreePages; extern PFN_NUMBER MiExpansionPoolPagesInitialCharge; extern PFN_NUMBER MmResidentAvailablePages; extern PFN_NUMBER MmResidentAvailableAtInit; extern ULONG MmTotalFreeSystemPtes[MaximumPtePoolTypes]; extern PFN_NUMBER MmTotalSystemDriverPages; extern PVOID MiSessionImageStart; extern PVOID MiSessionImageEnd; extern PMMPTE MiHighestUserPte; extern PMMPDE MiHighestUserPde; extern PFN_NUMBER MmSystemPageDirectory[PD_COUNT]; extern PMMPTE MmSharedUserDataPte; extern LIST_ENTRY MmProcessList; extern BOOLEAN MmZeroingPageThreadActive; extern KEVENT MmZeroingPageEvent; extern ULONG MmSystemPageColor; extern ULONG MmProcessColorSeed; // // Figures out the hardware bits for a PTE // ULONG FORCEINLINE MiDetermineUserGlobalPteMask(IN PMMPTE PointerPte) { MMPTE TempPte; /* Start fresh */ TempPte.u.Long = 0; /* Make it valid and accessed */ TempPte.u.Hard.Valid = TRUE; TempPte.u.Hard.Accessed = TRUE; /* Is this for user-mode? */ if ((PointerPte <= MiHighestUserPte) || ((PointerPte >= MiAddressToPde(NULL)) && (PointerPte <= MiHighestUserPde))) { /* Set the owner bit */ TempPte.u.Hard.Owner = TRUE; } /* FIXME: We should also set the global bit */ /* Return the protection */ return TempPte.u.Long; } // // Creates a valid kernel PTE with the given protection // FORCEINLINE VOID MI_MAKE_HARDWARE_PTE_KERNEL(IN PMMPTE NewPte, IN PMMPTE MappingPte, IN ULONG ProtectionMask, IN PFN_NUMBER PageFrameNumber) { /* Only valid for kernel, non-session PTEs */ ASSERT(MappingPte > MiHighestUserPte); ASSERT(!MI_IS_SESSION_PTE(MappingPte)); ASSERT((MappingPte < (PMMPTE)PDE_BASE) || (MappingPte > (PMMPTE)PDE_TOP)); /* Start fresh */ *NewPte = ValidKernelPte; /* Set the protection and page */ NewPte->u.Hard.PageFrameNumber = PageFrameNumber; NewPte->u.Long |= MmProtectToPteMask[ProtectionMask]; } // // Creates a valid PTE with the given protection // FORCEINLINE VOID MI_MAKE_HARDWARE_PTE(IN PMMPTE NewPte, IN PMMPTE MappingPte, IN ULONG ProtectionMask, IN PFN_NUMBER PageFrameNumber) { /* Set the protection and page */ NewPte->u.Long = MiDetermineUserGlobalPteMask(MappingPte); NewPte->u.Long |= MmProtectToPteMask[ProtectionMask]; NewPte->u.Hard.PageFrameNumber = PageFrameNumber; } // // Creates a valid user PTE with the given protection // FORCEINLINE VOID MI_MAKE_HARDWARE_PTE_USER(IN PMMPTE NewPte, IN PMMPTE MappingPte, IN ULONG ProtectionMask, IN PFN_NUMBER PageFrameNumber) { /* Only valid for kernel, non-session PTEs */ ASSERT(MappingPte <= MiHighestUserPte); /* Start fresh */ *NewPte = ValidKernelPte; /* Set the protection and page */ NewPte->u.Hard.Owner = TRUE; NewPte->u.Hard.PageFrameNumber = PageFrameNumber; NewPte->u.Long |= MmProtectToPteMask[ProtectionMask]; } #ifdef _M_IX86 // // Builds a Prototype PTE for the address of the PTE // FORCEINLINE VOID MI_MAKE_PROTOTYPE_PTE(IN PMMPTE NewPte, IN PMMPTE PointerPte) { ULONG_PTR Offset; /* Mark this as a prototype */ NewPte->u.Long = 0; NewPte->u.Proto.Prototype = 1; /* * Prototype PTEs are only valid in paged pool by design, this little trick * lets us only use 28 bits for the adress of the PTE */ Offset = (ULONG_PTR)PointerPte - (ULONG_PTR)MmPagedPoolStart; /* 7 bits go in the "low", and the other 21 bits go in the "high" */ NewPte->u.Proto.ProtoAddressLow = Offset & 0x7F; NewPte->u.Proto.ProtoAddressHigh = (Offset & 0xFFFFFF80) >> 7; ASSERT(MiProtoPteToPte(NewPte) == PointerPte); } #endif // // Returns if the page is physically resident (ie: a large page) // FIXFIX: CISC/x86 only? // FORCEINLINE BOOLEAN MI_IS_PHYSICAL_ADDRESS(IN PVOID Address) { PMMPDE PointerPde; /* Large pages are never paged out, always physically resident */ PointerPde = MiAddressToPde(Address); return ((PointerPde->u.Hard.LargePage) && (PointerPde->u.Hard.Valid)); } // // Writes a valid PTE // VOID FORCEINLINE MI_WRITE_VALID_PTE(IN PMMPTE PointerPte, IN MMPTE TempPte) { /* Write the valid PTE */ ASSERT(PointerPte->u.Hard.Valid == 0); ASSERT(TempPte.u.Hard.Valid == 1); *PointerPte = TempPte; } // // Writes an invalid PTE // VOID FORCEINLINE MI_WRITE_INVALID_PTE(IN PMMPTE PointerPte, IN MMPTE InvalidPte) { /* Write the invalid PTE */ ASSERT(InvalidPte.u.Hard.Valid == 0); *PointerPte = InvalidPte; } // // Checks if the thread already owns a working set // FORCEINLINE BOOLEAN MM_ANY_WS_LOCK_HELD(IN PETHREAD Thread) { /* If any of these are held, return TRUE */ return ((Thread->OwnsProcessWorkingSetExclusive) || (Thread->OwnsProcessWorkingSetShared) || (Thread->OwnsSystemWorkingSetExclusive) || (Thread->OwnsSystemWorkingSetShared) || (Thread->OwnsSessionWorkingSetExclusive) || (Thread->OwnsSessionWorkingSetShared)); } // // Checks if the process owns the working set lock // FORCEINLINE BOOLEAN MI_WS_OWNER(IN PEPROCESS Process) { /* Check if this process is the owner, and that the thread owns the WS */ return ((KeGetCurrentThread()->ApcState.Process == &Process->Pcb) && ((PsGetCurrentThread()->OwnsProcessWorkingSetExclusive) || (PsGetCurrentThread()->OwnsProcessWorkingSetShared))); } // // Locks the working set for the given process // FORCEINLINE VOID MiLockProcessWorkingSet(IN PEPROCESS Process, IN PETHREAD Thread) { /* Shouldn't already be owning the process working set */ ASSERT(Thread->OwnsProcessWorkingSetShared == FALSE); ASSERT(Thread->OwnsProcessWorkingSetExclusive == FALSE); /* Block APCs, make sure that still nothing is already held */ KeEnterGuardedRegion(); ASSERT(!MM_ANY_WS_LOCK_HELD(Thread)); /* FIXME: Actually lock it (we can't because Vm is used by MAREAs) */ /* FIXME: This also can't be checked because Vm is used by MAREAs) */ //ASSERT(Process->Vm.Flags.AcquiredUnsafe == 0); /* Okay, now we can own it exclusively */ ASSERT(Thread->OwnsProcessWorkingSetExclusive == FALSE); Thread->OwnsProcessWorkingSetExclusive = TRUE; } // // Unlocks the working set for the given process // FORCEINLINE VOID MiUnlockProcessWorkingSet(IN PEPROCESS Process, IN PETHREAD Thread) { /* Make sure this process really is owner, and it was a safe acquisition */ ASSERT(MI_WS_OWNER(Process)); /* This can't be checked because Vm is used by MAREAs) */ //ASSERT(Process->Vm.Flags.AcquiredUnsafe == 0); /* The thread doesn't own it anymore */ ASSERT(Thread->OwnsProcessWorkingSetExclusive == TRUE); Thread->OwnsProcessWorkingSetExclusive = FALSE; /* FIXME: Actually release it (we can't because Vm is used by MAREAs) */ /* Unblock APCs */ KeLeaveGuardedRegion(); } // // Locks the working set // FORCEINLINE VOID MiLockWorkingSet(IN PETHREAD Thread, IN PMMSUPPORT WorkingSet) { /* Block APCs */ KeEnterGuardedRegion(); /* Working set should be in global memory */ ASSERT(MI_IS_SESSION_ADDRESS((PVOID)WorkingSet) == FALSE); /* Thread shouldn't already be owning something */ ASSERT(!MM_ANY_WS_LOCK_HELD(Thread)); /* FIXME: Actually lock it (we can't because Vm is used by MAREAs) */ /* Which working set is this? */ if (WorkingSet == &MmSystemCacheWs) { /* Own the system working set */ ASSERT((Thread->OwnsSystemWorkingSetExclusive == FALSE) && (Thread->OwnsSystemWorkingSetShared == FALSE)); Thread->OwnsSystemWorkingSetExclusive = TRUE; } else if (WorkingSet->Flags.SessionSpace) { /* We don't implement this yet */ UNIMPLEMENTED; while (TRUE); } else { /* Own the process working set */ ASSERT((Thread->OwnsProcessWorkingSetExclusive == FALSE) && (Thread->OwnsProcessWorkingSetShared == FALSE)); Thread->OwnsProcessWorkingSetExclusive = TRUE; } } // // Unlocks the working set // FORCEINLINE VOID MiUnlockWorkingSet(IN PETHREAD Thread, IN PMMSUPPORT WorkingSet) { /* Working set should be in global memory */ ASSERT(MI_IS_SESSION_ADDRESS((PVOID)WorkingSet) == FALSE); /* Which working set is this? */ if (WorkingSet == &MmSystemCacheWs) { /* Release the system working set */ ASSERT((Thread->OwnsSystemWorkingSetExclusive == TRUE) || (Thread->OwnsSystemWorkingSetShared == TRUE)); Thread->OwnsSystemWorkingSetExclusive = FALSE; } else if (WorkingSet->Flags.SessionSpace) { /* We don't implement this yet */ UNIMPLEMENTED; while (TRUE); } else { /* Release the process working set */ ASSERT((Thread->OwnsProcessWorkingSetExclusive) || (Thread->OwnsProcessWorkingSetShared)); Thread->OwnsProcessWorkingSetExclusive = FALSE; } /* FIXME: Actually release it (we can't because Vm is used by MAREAs) */ /* Unblock APCs */ KeLeaveGuardedRegion(); } // // Returns the ProtoPTE inside a VAD for the given VPN // FORCEINLINE PMMPTE MI_GET_PROTOTYPE_PTE_FOR_VPN(IN PMMVAD Vad, IN ULONG_PTR Vpn) { PMMPTE ProtoPte; /* Find the offset within the VAD's prototype PTEs */ ProtoPte = Vad->FirstPrototypePte + (Vpn - Vad->StartingVpn); ASSERT(ProtoPte <= Vad->LastContiguousPte); return ProtoPte; } BOOLEAN NTAPI MmArmInitSystem( IN ULONG Phase, IN PLOADER_PARAMETER_BLOCK LoaderBlock ); 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 ); 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 MmArmAccessFault( IN BOOLEAN StoreInstruction, IN PVOID Address, IN KPROCESSOR_MODE Mode, IN PVOID TrapInformation ); NTSTATUS FASTCALL MiCheckPdeForPagedPool( IN PVOID Address ); VOID NTAPI MiInitializeNonPagedPool( VOID ); VOID NTAPI MiInitializeNonPagedPoolThresholds( VOID ); VOID NTAPI MiInitializePoolEvents( VOID ); VOID // NTAPI // InitializePool( // IN POOL_TYPE PoolType,// FIXFIX: This should go in ex.h after the pool merge IN ULONG Threshold // ); // 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 ); PVOID NTAPI MiMapLockedPagesInUserSpace( IN PMDL Mdl, IN PVOID BaseVa, IN MEMORY_CACHING_TYPE CacheType, IN PVOID BaseAddress ); VOID NTAPI MiUnmapLockedPagesInUserSpace( IN PVOID BaseAddress, IN PMDL Mdl ); VOID NTAPI MiInsertPageInList( IN PMMPFNLIST ListHead, IN PFN_NUMBER PageFrameIndex ); VOID NTAPI MiUnlinkFreeOrZeroedPage( IN PMMPFN Entry ); PFN_NUMBER NTAPI MiAllocatePfn( IN PMMPTE PointerPte, IN ULONG Protection ); VOID NTAPI MiInitializePfn( IN PFN_NUMBER PageFrameIndex, IN PMMPTE PointerPte, IN BOOLEAN Modified ); VOID NTAPI MiInitializePfnForOtherProcess( IN PFN_NUMBER PageFrameIndex, IN PMMPTE PointerPte, IN PFN_NUMBER PteFrame ); VOID NTAPI MiDecrementShareCount( IN PMMPFN Pfn1, IN PFN_NUMBER PageFrameIndex ); VOID NTAPI MiDecrementReferenceCount( 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_NUMBER NTAPI MiDeleteSystemPageableVm( IN PMMPTE PointerPte, IN PFN_NUMBER PageCount, IN ULONG Flags, OUT PPFN_NUMBER ValidPages ); 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 ); PMMADDRESS_NODE NTAPI MiCheckForConflictingNode( IN ULONG_PTR StartVpn, IN ULONG_PTR EndVpn, IN PMM_AVL_TABLE Table ); 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 MiFindEmptyAddressRangeInTree( IN SIZE_T Length, IN ULONG_PTR Alignment, IN PMM_AVL_TABLE Table, OUT PMMADDRESS_NODE *PreviousVad, OUT PULONG_PTR Base ); VOID NTAPI MiInsertVad( IN PMMVAD Vad, IN PEPROCESS Process ); 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 PVOID InputSession OPTIONAL ); ULONG NTAPI MiMakeProtectionMask( IN ULONG Protect ); VOID NTAPI MiDeleteVirtualAddresses( IN ULONG_PTR Va, IN ULONG_PTR EndingAddress, IN PMMVAD Vad ); 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 ); // // MiRemoveZeroPage will use inline code to zero out the page manually if only // free pages are available. In some scenarios, we don't/can't run that piece of // code and would rather only have a real zero page. If we can't have a zero page, // then we'd like to have our own code to grab a free page and zero it out, by // using MiRemoveAnyPage. This macro implements this. // PFN_NUMBER FORCEINLINE MiRemoveZeroPageSafe(IN ULONG Color) { if (MmFreePagesByColor[ZeroedPageList][Color].Flink != LIST_HEAD) return MiRemoveZeroPage(Color); return 0; } // // New ARM3<->RosMM PAGE Architecture // #define MI_GET_ROS_DATA(x) ((PMMROSPFN)(x->RosMmData)) #define MI_IS_ROS_PFN(x) (((x)->u4.AweAllocation == TRUE) && (MI_GET_ROS_DATA(x) != NULL)) #define ASSERT_IS_ROS_PFN(x) ASSERT(MI_IS_ROS_PFN(x) == TRUE); typedef struct _MMROSPFN { PMM_RMAP_ENTRY RmapListHead; SWAPENTRY SwapEntry; } MMROSPFN, *PMMROSPFN; #define RosMmData AweReferenceCount /* EOF */