Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

sysptes.c File Reference

#include "mi.h"

Go to the source code of this file.

Defines

#define MM_MIN_SYSPTE_FREE   500
#define MM_MAX_SYSPTE_FREE   3000
#define MM_PTE_LIST_1   400
#define MM_PTE_LIST_2   100
#define MM_PTE_LIST_4   60
#define MM_PTE_LIST_8   50
#define MM_PTE_LIST_16   40
#define MM_PTE_TABLE_LIMIT   16

Functions

VOID MiFeedSysPtePool (IN ULONG Index)
PMMPTE MiReserveSystemPtes2 (IN ULONG NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType, IN ULONG Alignment, IN ULONG Offset, IN ULONG BugCheckOnFailure)
ULONG MiGetSystemPteListCount (IN ULONG ListSize)
VOID MiDumpSystemPtes (IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType)
ULONG MiCountFreeSystemPtes (IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType)
PVOID MiGetHighestPteConsumer (OUT PULONG_PTR NumberOfPtes)
PMMPTE MiReserveSystemPtes (IN ULONG NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType, IN ULONG Alignment, IN ULONG Offset, IN ULONG BugCheckOnFailure)
VOID MiReleaseSystemPtes (IN PMMPTE StartingPte, IN ULONG NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType)
VOID MiInitializeSystemPtes (IN PMMPTE StartingPte, IN ULONG NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType)
VOID MiAddSystemPtes (IN PMMPTE StartingPte, IN ULONG NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType)
LOGICAL MiGetSystemPteAvailability (IN ULONG NumberOfPtes, IN MM_PAGE_PRIORITY Priority)

Variables

ULONG MmTotalFreeSystemPtes [MaximumPtePoolTypes]
PMMPTE MmSystemPtesStart [MaximumPtePoolTypes]
PMMPTE MmSystemPtesEnd [MaximumPtePoolTypes]
PMMPTE MmFlushPte1
ULONG MmFlushCounter
ULONG MmSysPteIndex [MM_SYS_PTE_TABLES_MAX] = {1,2,4,8,16}
UCHAR MmSysPteTables [17] = {0,0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4}
MMPTE MmFreeSysPteListBySize [MM_SYS_PTE_TABLES_MAX]
PMMPTE MmLastSysPteListBySize [MM_SYS_PTE_TABLES_MAX]
ULONG MmSysPteListBySizeCount [MM_SYS_PTE_TABLES_MAX]
ULONG MmSysPteMinimumFree [MM_SYS_PTE_TABLES_MAX] = {100,50,30,20,20}


Define Documentation

#define MM_MAX_SYSPTE_FREE   3000
 

Definition at line 74 of file sysptes.c.

Referenced by MiReleaseSystemPtes().

#define MM_MIN_SYSPTE_FREE   500
 

Definition at line 73 of file sysptes.c.

Referenced by MiFeedSysPtePool(), and MiReleaseSystemPtes().

#define MM_PTE_LIST_1   400
 

Definition at line 110 of file sysptes.c.

Referenced by MiInitializeSystemPtes().

#define MM_PTE_LIST_16   40
 

Definition at line 114 of file sysptes.c.

Referenced by MiInitializeSystemPtes().

#define MM_PTE_LIST_2   100
 

Definition at line 111 of file sysptes.c.

Referenced by MiInitializeSystemPtes().

#define MM_PTE_LIST_4   60
 

Definition at line 112 of file sysptes.c.

Referenced by MiInitializeSystemPtes().

#define MM_PTE_LIST_8   50
 

Definition at line 113 of file sysptes.c.

Referenced by MiInitializeSystemPtes().

#define MM_PTE_TABLE_LIMIT   16
 

Definition at line 116 of file sysptes.c.

Referenced by MiGetSystemPteAvailability(), MiGetSystemPteListCount(), MiReleaseSystemPtes(), and MiReserveSystemPtes().


Function Documentation

VOID MiAddSystemPtes IN PMMPTE  StartingPte,
IN ULONG  NumberOfPtes,
IN MMSYSTEM_PTE_POOL_TYPE  SystemPtePoolType
 

Definition at line 1907 of file sysptes.c.

References ASSERT, Index, MiFillMemoryPte, MiReleaseSystemPtes(), MM_KERNEL_NOACCESS_PTE, MmSystemPtesEnd, MmSystemPtesStart, NULL, SystemPteSpace, TRUE, and USHORT.

Referenced by MiInitMachineDependent(), and MmInitSystem().

01915 : 01916 01917 This routine adds newly created PTEs to the specified pool. 01918 01919 Arguments: 01920 01921 StartingPte - Supplies the address of the first PTE to put in the pool. 01922 01923 NumberOfPtes - Supplies the number of PTEs to put in the pool. 01924 01925 SystemPtePoolType - Supplies the PTE type of the pool to expand, one of 01926 SystemPteSpace or NonPagedPoolExpansion. 01927 01928 Return Value: 01929 01930 None. 01931 01932 Environment: 01933 01934 Kernel mode. 01935 01936 --*/ 01937 01938 { 01939 PMMPTE EndingPte; 01940 01941 EndingPte = StartingPte + NumberOfPtes - 1; 01942 01943 #ifdef _MI_SYSPTE_DEBUG_ 01944 MiRebuildPteTracker (StartingPte, NumberOfPtes); 01945 #endif 01946 01947 if (StartingPte < MmSystemPtesStart[SystemPtePoolType]) { 01948 MmSystemPtesStart[SystemPtePoolType] = StartingPte; 01949 } 01950 01951 if (EndingPte > MmSystemPtesEnd[SystemPtePoolType]) { 01952 MmSystemPtesEnd[SystemPtePoolType] = EndingPte; 01953 } 01954 01955 #ifdef _MI_SYSPTE_DEBUG_ 01956 01957 if (SystemPtePoolType == SystemPteSpace && MiPteTracker != NULL) { 01958 01959 ULONG i; 01960 ULONG_PTR Index; 01961 PMMPTE_TRACKER Tracker; 01962 01963 Index = StartingPte - MmSystemPtesStart[SystemPteSpace]; 01964 Tracker = &MiPteTracker[Index]; 01965 01966 ASSERT (NumberOfPtes < 0x10000); 01967 Tracker->NumberOfPtes = (USHORT)NumberOfPtes; 01968 01969 for (i = 0; i < NumberOfPtes; i += 1) { 01970 Tracker->InUse = TRUE; 01971 Tracker += 1; 01972 } 01973 } 01974 01975 MiFillMemoryPte (StartingPte, NumberOfPtes * sizeof (MMPTE), MM_KERNEL_NOACCESS_PTE); 01976 #endif 01977 01978 #ifdef _MI_GUARD_PTE_ 01979 MiReleaseSystemPtes (StartingPte, NumberOfPtes - 1, SystemPtePoolType); 01980 #else 01981 MiReleaseSystemPtes (StartingPte, NumberOfPtes, SystemPtePoolType); 01982 #endif 01983 }

ULONG MiCountFreeSystemPtes IN MMSYSTEM_PTE_POOL_TYPE  SystemPtePoolType  ) 
 

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

VOID MiDumpSystemPtes IN MMSYSTEM_PTE_POOL_TYPE  SystemPtePoolType  ) 
 

Referenced by MiReleaseSystemPtes(), and MiReserveSystemPtes2().

VOID MiFeedSysPtePool IN ULONG  Index  ) 
 

Definition at line 788 of file sysptes.c.

References FALSE, Index, MiReleaseSystemPtes(), MiReserveSystemPtes2(), MM_MIN_SYSPTE_FREE, MmSysPteIndex, MmTotalFreeSystemPtes, NULL, and SystemPteSpace.

Referenced by MiReserveSystemPtes().

00794 : 00795 00796 This routine adds PTEs to the look aside lists. 00797 00798 Arguments: 00799 00800 Index - Supplies the index for the look aside list to fill. 00801 00802 Return Value: 00803 00804 None. 00805 00806 00807 Environment: 00808 00809 Kernel mode, internal to SysPtes. 00810 00811 --*/ 00812 00813 { 00814 #ifdef _MI_GUARD_PTE_ 00815 UNREFERENCED_PARAMETER (Index); 00816 #else 00817 ULONG i; 00818 PMMPTE PointerPte; 00819 00820 if (MmTotalFreeSystemPtes[SystemPteSpace] < MM_MIN_SYSPTE_FREE) { 00821 return; 00822 } 00823 00824 for (i = 0; i < 10 ; i++ ) { 00825 PointerPte = MiReserveSystemPtes2 (MmSysPteIndex [Index], 00826 SystemPteSpace, 00827 0, 00828 0, 00829 FALSE); 00830 if (PointerPte == NULL) { 00831 return; 00832 } 00833 MiReleaseSystemPtes (PointerPte, 00834 MmSysPteIndex [Index], 00835 SystemPteSpace); 00836 } 00837 #endif 00838 return; 00839 }

PVOID MiGetHighestPteConsumer OUT PULONG_PTR  NumberOfPtes  ) 
 

Definition at line 1901 of file iosup.c.

References _PTE_TRACKER::CallingAddress, _PTE_TRACKER::Count, FALSE, _SYSPTES_HEADER::ListHead, MiPteHeader, MiTrackPtesAborted, MmTrackPtes, NULL, PPTE_TRACKER, PsLoadedModuleList, and TRUE.

Referenced by MiReserveSystemPtes2().

01907 : 01908 01909 This function examines the PTE tracking blocks and returns the biggest 01910 consumer. 01911 01912 Arguments: 01913 01914 None. 01915 01916 Return Value: 01917 01918 The loaded module entry of the biggest consumer. 01919 01920 Environment: 01921 01922 Kernel mode, called during bugcheck only. Many locks may be held. 01923 01924 --*/ 01925 01926 { 01927 PPTE_TRACKER Tracker; 01928 PVOID BaseAddress; 01929 PFN_NUMBER NumberOfPages; 01930 PLIST_ENTRY NextEntry; 01931 PLIST_ENTRY NextEntry2; 01932 PLDR_DATA_TABLE_ENTRY DataTableEntry; 01933 ULONG_PTR Highest; 01934 ULONG_PTR PagesByThisModule; 01935 PLDR_DATA_TABLE_ENTRY HighDataTableEntry; 01936 01937 *NumberOfPtes = 0; 01938 01939 // 01940 // No locks are acquired as this is only called during a bugcheck. 01941 // 01942 01943 if (MmTrackPtes == FALSE) { 01944 return NULL; 01945 } 01946 01947 if (MiTrackPtesAborted == TRUE) { 01948 return NULL; 01949 } 01950 01951 if (IsListEmpty(&MiPteHeader.ListHead)) { 01952 return NULL; 01953 } 01954 01955 if (PsLoadedModuleList.Flink == NULL) { 01956 return NULL; 01957 } 01958 01959 Highest = 0; 01960 HighDataTableEntry = NULL; 01961 01962 NextEntry = PsLoadedModuleList.Flink; 01963 while (NextEntry != &PsLoadedModuleList) { 01964 01965 DataTableEntry = CONTAINING_RECORD(NextEntry, 01966 LDR_DATA_TABLE_ENTRY, 01967 InLoadOrderLinks); 01968 01969 PagesByThisModule = 0; 01970 01971 // 01972 // Walk the PTE mapping list and update each driver's counts. 01973 // 01974 01975 NextEntry2 = MiPteHeader.ListHead.Flink; 01976 while (NextEntry2 != &MiPteHeader.ListHead) { 01977 01978 Tracker = (PPTE_TRACKER) CONTAINING_RECORD (NextEntry2, 01979 PTE_TRACKER, 01980 ListEntry.Flink); 01981 01982 BaseAddress = Tracker->CallingAddress; 01983 NumberOfPages = Tracker->Count; 01984 01985 if ((BaseAddress >= DataTableEntry->DllBase) && 01986 (BaseAddress < (PVOID)((ULONG_PTR)(DataTableEntry->DllBase) + DataTableEntry->SizeOfImage))) { 01987 01988 PagesByThisModule += NumberOfPages; 01989 } 01990 01991 NextEntry2 = NextEntry2->Flink; 01992 01993 } 01994 01995 if (PagesByThisModule > Highest) { 01996 Highest = PagesByThisModule; 01997 HighDataTableEntry = DataTableEntry; 01998 } 01999 02000 NextEntry = NextEntry->Flink; 02001 } 02002 02003 *NumberOfPtes = Highest; 02004 02005 return (PVOID)HighDataTableEntry; 02006 }

LOGICAL MiGetSystemPteAvailability IN ULONG  NumberOfPtes,
IN MM_PAGE_PRIORITY  Priority
 

Definition at line 2030 of file sysptes.c.

References FALSE, HighPagePriority, Index, MM_PTE_TABLE_LIMIT, MmSysPteListBySizeCount, MmSysPteMinimumFree, MmSysPteTables, MmTotalFreeSystemPtes, NormalPagePriority, SystemPteSpace, and TRUE.

Referenced by MiMapSinglePage(), and MmMapLockedPagesSpecifyCache().

02037 : 02038 02039 This routine checks how many SystemPteSpace PTEs are available for the 02040 requested size. If plenty are available then TRUE is returned. 02041 If we are reaching a low resource situation, then the request is evaluated 02042 based on the argument priority. 02043 02044 Arguments: 02045 02046 NumberOfPtes - Supplies the number of PTEs needed. 02047 02048 Priority - Supplies the priority of the request. 02049 02050 Return Value: 02051 02052 TRUE if the caller should allocate the PTEs, FALSE if not. 02053 02054 Environment: 02055 02056 Kernel mode. 02057 02058 --*/ 02059 02060 { 02061 ULONG Index; 02062 ULONG FreePtes; 02063 ULONG FreeBinnedPtes; 02064 02065 if (Priority == HighPagePriority) { 02066 return TRUE; 02067 } 02068 02069 #ifdef _MI_GUARD_PTE_ 02070 NumberOfPtes += 1; 02071 #endif 02072 02073 FreePtes = MmTotalFreeSystemPtes[SystemPteSpace]; 02074 02075 if (NumberOfPtes <= MM_PTE_TABLE_LIMIT) { 02076 Index = MmSysPteTables [NumberOfPtes]; 02077 FreeBinnedPtes = MmSysPteListBySizeCount[Index]; 02078 02079 if (FreeBinnedPtes > MmSysPteMinimumFree[Index]) { 02080 return TRUE; 02081 } 02082 if (FreeBinnedPtes != 0) { 02083 if (Priority == NormalPagePriority) { 02084 if (FreeBinnedPtes > 1 || FreePtes > 512) { 02085 return TRUE; 02086 } 02087 return FALSE; 02088 } 02089 if (FreePtes > 2048) { 02090 return TRUE; 02091 } 02092 return FALSE; 02093 } 02094 } 02095 02096 if (Priority == NormalPagePriority) { 02097 if ((LONG)NumberOfPtes < (LONG)FreePtes - 512) { 02098 return TRUE; 02099 } 02100 return FALSE; 02101 } 02102 02103 if ((LONG)NumberOfPtes < (LONG)FreePtes - 2048) { 02104 return TRUE; 02105 } 02106 return FALSE; 02107 }

ULONG MiGetSystemPteListCount IN ULONG  ListSize  ) 
 

Referenced by MmCreateKernelStack().

VOID MiInitializeSystemPtes IN PMMPTE  StartingPte,
IN ULONG  NumberOfPtes,
IN MMSYSTEM_PTE_POOL_TYPE  SystemPtePoolType
 

Definition at line 1740 of file sysptes.c.

References ASSERT, MI_PTE_BASE_FOR_LOWEST_KERNEL_ADDRESS, MI_WRITE_INVALID_PTE, MiAllocatePoolPages(), MiCountFreeSystemPtes(), MiFillMemoryPte, MiReleaseSystemPtes(), MiReserveSystemPtes(), MM_EMPTY_LIST, MM_EMPTY_PTE_LIST, MM_PTE_LIST_1, MM_PTE_LIST_16, MM_PTE_LIST_2, MM_PTE_LIST_4, MM_PTE_LIST_8, MM_SYS_PTE_TABLES_MAX, MmFirstFreeSystemPte, MmFlushCounter, MmFlushPte1, MmFreeSysPteListBySize, MmLastSysPteListBySize, MmSysPteIndex, MmSystemPteBase, MmSystemPtesEnd, MmSystemPtesStart, MmTotalFreeSystemPtes, NonPagedPool, NULL, SystemPteSpace, TRUE, _MMPTE::u, and ZeroKernelPte.

Referenced by MiInitializeNonPagedPool(), and MiInitMachineDependent().

01748 : 01749 01750 This routine initializes the system PTE pool. 01751 01752 Arguments: 01753 01754 StartingPte - Supplies the address of the first PTE to put in the pool. 01755 01756 NumberOfPtes - Supplies the number of PTEs to put in the pool. 01757 01758 SystemPtePoolType - Supplies the PTE type of the pool to initialize, one of 01759 SystemPteSpace or NonPagedPoolExpansion. 01760 01761 Return Value: 01762 01763 none. 01764 01765 Environment: 01766 01767 Kernel mode. 01768 01769 --*/ 01770 01771 { 01772 LONG i; 01773 LONG j; 01774 #ifdef _MI_SYSPTE_DEBUG_ 01775 PMMPTE_TRACKER Tracker; 01776 #endif 01777 01778 // 01779 // Set the base of the system PTE pool to this PTE. This takes into 01780 // account that systems may have additional PTE pools below the PTE_BASE. 01781 // 01782 01783 MmSystemPteBase = MI_PTE_BASE_FOR_LOWEST_KERNEL_ADDRESS; 01784 01785 MmSystemPtesStart[SystemPtePoolType] = StartingPte; 01786 MmSystemPtesEnd[SystemPtePoolType] = StartingPte + NumberOfPtes - 1; 01787 01788 // 01789 // If there are no PTEs specified, then make a valid chain by indicating 01790 // that the list is empty. 01791 // 01792 01793 if (NumberOfPtes == 0) { 01794 MmFirstFreeSystemPte[SystemPtePoolType] = ZeroKernelPte; 01795 MmFirstFreeSystemPte[SystemPtePoolType].u.List.NextEntry = 01796 MM_EMPTY_LIST; 01797 return; 01798 } 01799 01800 // 01801 // Initialize the specified system pte pool. 01802 // 01803 01804 MiFillMemoryPte (StartingPte, 01805 NumberOfPtes * sizeof (MMPTE), 01806 ZeroKernelPte.u.Long); 01807 01808 // 01809 // The page frame field points to the next cluster. As we only 01810 // have one cluster at initialization time, mark it as the last 01811 // cluster. 01812 // 01813 01814 StartingPte->u.List.NextEntry = MM_EMPTY_LIST; 01815 01816 MmFirstFreeSystemPte[SystemPtePoolType] = ZeroKernelPte; 01817 MmFirstFreeSystemPte[SystemPtePoolType].u.List.NextEntry = 01818 StartingPte - MmSystemPteBase; 01819 01820 // 01821 // If there is only one PTE in the pool, then mark it as a one entry 01822 // PTE. Otherwise, store the cluster size in the following PTE. 01823 // 01824 01825 if (NumberOfPtes == 1) { 01826 StartingPte->u.List.OneEntry = TRUE; 01827 01828 } else { 01829 StartingPte += 1; 01830 MI_WRITE_INVALID_PTE (StartingPte, ZeroKernelPte); 01831 StartingPte->u.List.NextEntry = NumberOfPtes; 01832 } 01833 01834 // 01835 // Set the total number of free PTEs for the specified type. 01836 // 01837 01838 MmTotalFreeSystemPtes[SystemPtePoolType] = NumberOfPtes; 01839 01840 ASSERT (MmTotalFreeSystemPtes[SystemPtePoolType] == 01841 MiCountFreeSystemPtes (SystemPtePoolType)); 01842 01843 if (SystemPtePoolType == SystemPteSpace) { 01844 01845 ULONG Lists[MM_SYS_PTE_TABLES_MAX] = {MM_PTE_LIST_1, MM_PTE_LIST_2, MM_PTE_LIST_4, MM_PTE_LIST_8, MM_PTE_LIST_16}; 01846 PMMPTE PointerPte; 01847 ULONG total; 01848 01849 #ifdef _MI_SYSPTE_DEBUG_ 01850 Tracker = (PMMPTE_TRACKER) MiAllocatePoolPages ( 01851 NonPagedPool, 01852 NumberOfPtes * sizeof (MMPTE_TRACKER), 01853 0); 01854 01855 if (Tracker) { 01856 RtlZeroMemory (Tracker, NumberOfPtes * sizeof (MMPTE_TRACKER)); 01857 } 01858 #endif 01859 01860 for (j = 0; j < MM_SYS_PTE_TABLES_MAX ; j++) { 01861 MmFreeSysPteListBySize [j].u.List.NextEntry = MM_EMPTY_PTE_LIST; 01862 MmLastSysPteListBySize [j] = &MmFreeSysPteListBySize [j]; 01863 } 01864 MmFlushCounter += 1; 01865 01866 #ifndef _MI_GUARD_PTE_ 01867 01868 // 01869 // Initialize the by size lists. 01870 // 01871 01872 total = MM_PTE_LIST_1 * MmSysPteIndex[0] + 01873 MM_PTE_LIST_2 * MmSysPteIndex[1] + 01874 MM_PTE_LIST_4 * MmSysPteIndex[2] + 01875 MM_PTE_LIST_8 * MmSysPteIndex[3] + 01876 MM_PTE_LIST_16 * MmSysPteIndex[4]; 01877 01878 PointerPte = MiReserveSystemPtes (total, 01879 SystemPteSpace, 01880 64*1024, 01881 0, 01882 TRUE); 01883 01884 for (i = (MM_SYS_PTE_TABLES_MAX - 1); i >= 0; i--) { 01885 do { 01886 Lists[i] -= 1; 01887 MiReleaseSystemPtes (PointerPte, 01888 MmSysPteIndex[i], 01889 SystemPteSpace); 01890 PointerPte += MmSysPteIndex[i]; 01891 } while (Lists[i] != 0 ); 01892 } 01893 #endif 01894 01895 MmFlushCounter += 1; 01896 MmFlushPte1 = NULL; 01897 01898 #ifdef _MI_SYSPTE_DEBUG_ 01899 MiPteTracker = Tracker; 01900 #endif 01901 } 01902 01903 return; 01904 }

VOID MiReleaseSystemPtes IN PMMPTE  StartingPte,
IN ULONG  NumberOfPtes,
IN MMSYSTEM_PTE_POOL_TYPE  SystemPtePoolType
 

Definition at line 1354 of file sysptes.c.

References ASSERT, _MMPTE_FLUSH_LIST::Count, DbgPrint, DISPATCH_LEVEL, _MMPTE_FLUSH_LIST::FlushPte, _MMPTE_FLUSH_LIST::FlushVa, Index, KeBugCheckEx(), KeFlushEntireTb(), KeLowerIrql(), KeRaiseIrql(), MiCountFreeSystemPtes(), MiDumpSystemPtes(), MiFillMemoryPte, MiFlushPteList(), MiGetVirtualAddressMappedByPte, MiLockSystemSpace, MiUnlockSystemSpace, MM_DBG_SYS_PTES, MM_EMPTY_PTE_LIST, MM_KERNEL_NOACCESS_PTE, MM_MAX_SYSPTE_FREE, MM_MAXIMUM_FLUSH_COUNT, MM_MIN_SYSPTE_FREE, MM_PTE_TABLE_LIMIT, MmFirstFreeSystemPte, MmFlushCounter, MmFlushPte1, MmFreeSysPteListBySize, MmLastSysPteListBySize, MmSysPteIndex, MmSysPteListBySizeCount, MmSysPteMinimumFree, MmSysPteTables, MmSystemPteBase, MmSystemPtesEnd, MmSystemPtesStart, MmTotalFreeSystemPtes, NULL, PAGE_SIZE, Size, SystemPteSpace, TRUE, _MMPTE::u, and ZeroKernelPte.

Referenced by ExFreePool(), MiAddSystemPtes(), MiDereferenceSession(), MiFeedSysPtePool(), MiFreeNonPagedPool(), MiInitializeSystemPtes(), MiLoadImageSection(), MiReloadBootLoadedDrivers(), MiSessionCreateInternal(), MiUnmapSinglePage(), MmAllocateIndependentPages(), MmAllocateNonCachedMemory(), MmDeleteKernelStack(), MmFreeNonCachedMemory(), MmMapIoSpace(), MmMapLockedPagesSpecifyCache(), MmMapVideoDisplay(), MmUnloadSystemImage(), MmUnmapIoSpace(), MmUnmapLockedPages(), and MmUnmapVideoDisplay().

01362 : 01363 01364 This function releases the specified number of PTEs 01365 within the non paged portion of system space. 01366 01367 Note that the PTEs must be invalid and the page frame number 01368 must have been set to zero. 01369 01370 Arguments: 01371 01372 StartingPte - Supplies the address of the first PTE to release. 01373 01374 NumberOfPtes - Supplies the number of PTEs to release. 01375 01376 SystemPtePoolType - Supplies the PTE type of the pool to release PTEs to, 01377 one of SystemPteSpace or NonPagedPoolExpansion. 01378 01379 Return Value: 01380 01381 none. 01382 01383 Environment: 01384 01385 Kernel mode. 01386 01387 --*/ 01388 01389 { 01390 ULONG_PTR Size; 01391 ULONG i; 01392 ULONG_PTR PteOffset; 01393 PMMPTE PointerPte; 01394 PMMPTE PointerFollowingPte; 01395 PMMPTE NextPte; 01396 KIRQL OldIrql; 01397 ULONG Index; 01398 #if defined(_IA64_) 01399 MMPTE_FLUSH_LIST PteFlushList; 01400 PMMPTE Previous; 01401 PVOID BaseAddress; 01402 #endif 01403 01404 // 01405 // Check to make sure the PTEs don't map anything. 01406 // 01407 01408 ASSERT (NumberOfPtes != 0); 01409 01410 #ifdef _MI_GUARD_PTE_ 01411 if (NumberOfPtes == 0) { 01412 KeBugCheckEx (SYSTEM_PTE_MISUSE, 01413 0xD, 01414 (ULONG_PTR)StartingPte, 01415 NumberOfPtes, 01416 SystemPtePoolType); 01417 } 01418 01419 if (SystemPtePoolType == SystemPteSpace) { 01420 if ((StartingPte + NumberOfPtes)->u.Long != MM_KERNEL_NOACCESS_PTE) { 01421 KeBugCheckEx (SYSTEM_PTE_MISUSE, 01422 0xE, 01423 (ULONG_PTR)StartingPte, 01424 NumberOfPtes, 01425 SystemPtePoolType); 01426 } 01427 NumberOfPtes += 1; 01428 } 01429 #endif 01430 01431 #if DBG 01432 if (StartingPte < MmSystemPtesStart[SystemPtePoolType]) { 01433 KeBugCheckEx (SYSTEM_PTE_MISUSE, 01434 0xF, 01435 (ULONG_PTR)StartingPte, 01436 NumberOfPtes, 01437 SystemPtePoolType); 01438 } 01439 01440 if (StartingPte > MmSystemPtesEnd[SystemPtePoolType]) { 01441 KeBugCheckEx (SYSTEM_PTE_MISUSE, 01442 0x10, 01443 (ULONG_PTR)StartingPte, 01444 NumberOfPtes, 01445 SystemPtePoolType); 01446 } 01447 #endif //DBG 01448 01449 #if 0 01450 if (MmDebug & MM_DBG_SYS_PTES) { 01451 DbgPrint("releasing 0x%lx system PTEs at location %lx\n",NumberOfPtes,StartingPte); 01452 } 01453 #endif //0 01454 01455 #if defined(_IA64_) 01456 01457 PteFlushList.Count = 0; 01458 Previous = StartingPte; 01459 BaseAddress = MiGetVirtualAddressMappedByPte (Previous); 01460 for (i = 0; i < NumberOfPtes ; i++) { 01461 if (PteFlushList.Count != MM_MAXIMUM_FLUSH_COUNT) { 01462 PteFlushList.FlushPte[PteFlushList.Count] = Previous; 01463 PteFlushList.FlushVa[PteFlushList.Count] = BaseAddress; 01464 PteFlushList.Count += 1; 01465 } 01466 *Previous = ZeroKernelPte; 01467 BaseAddress = (PVOID)((PCHAR)BaseAddress + PAGE_SIZE); 01468 Previous++; 01469 } 01470 01471 KeRaiseIrql (DISPATCH_LEVEL, &OldIrql); 01472 MiFlushPteList (&PteFlushList, TRUE, ZeroKernelPte); 01473 KeLowerIrql (OldIrql); 01474 01475 #else 01476 01477 // 01478 // Zero PTEs. 01479 // 01480 01481 #ifdef _MI_SYSPTE_DEBUG_ 01482 MiValidateSystemPtes (StartingPte, NumberOfPtes); 01483 #endif 01484 01485 MiFillMemoryPte (StartingPte, 01486 NumberOfPtes * sizeof (MMPTE), 01487 ZeroKernelPte.u.Long); 01488 01489 #ifdef _MI_SYSPTE_DEBUG_ 01490 01491 // 01492 // Invalidate any TB entries that might have been mapped to 01493 // immediately prevent bad callers from corrupting the system. 01494 // 01495 01496 KeFlushEntireTb (TRUE, TRUE); 01497 #endif 01498 01499 #endif 01500 01501 // 01502 // Acquire system space spin lock to synchronize access. 01503 // 01504 01505 PteOffset = (ULONG_PTR)(StartingPte - MmSystemPteBase); 01506 01507 #ifdef _MI_SYSPTE_DEBUG_ 01508 if (PteOffset == 0) { 01509 KeBugCheckEx (SYSTEM_PTE_MISUSE, 01510 0x11, 01511 (ULONG_PTR)StartingPte, 01512 NumberOfPtes, 01513 SystemPtePoolType); 01514 } 01515 #endif 01516 01517 MiLockSystemSpace(OldIrql); 01518 01519 #ifdef _MI_SYSPTE_DEBUG_ 01520 MiCheckPteRelease (StartingPte, NumberOfPtes); 01521 #endif 01522 01523 #ifndef _MI_GUARD_PTE_ 01524 if ((SystemPtePoolType == SystemPteSpace) && 01525 (NumberOfPtes <= MM_PTE_TABLE_LIMIT)) { 01526 01527 Index = MmSysPteTables [NumberOfPtes]; 01528 NumberOfPtes = MmSysPteIndex [Index]; 01529 01530 if (MmTotalFreeSystemPtes[SystemPteSpace] >= MM_MIN_SYSPTE_FREE) { 01531 01532 // 01533 // Don't add to the pool if the size is greater than 15 + the minimum. 01534 // 01535 01536 i = MmSysPteMinimumFree[Index]; 01537 if (MmTotalFreeSystemPtes[SystemPteSpace] >= MM_MAX_SYSPTE_FREE) { 01538 01539 // 01540 // Lots of free PTEs, quadruple the limit. 01541 // 01542 01543 i = i * 4; 01544 } 01545 i += 15; 01546 if (MmSysPteListBySizeCount[Index] <= i) { 01547 01548 #if DBG 01549 if (MmDebug & MM_DBG_SYS_PTES) { 01550 PMMPTE PointerPte1; 01551 01552 PointerPte1 = &MmFreeSysPteListBySize[Index]; 01553 while (PointerPte1->u.List.NextEntry != MM_EMPTY_PTE_LIST) { 01554 PMMPTE PointerFreedPte; 01555 ULONG j; 01556 01557 PointerPte1 = MmSystemPteBase + PointerPte1->u.List.NextEntry; 01558 PointerFreedPte = PointerPte1; 01559 for (j = 0; j < MmSysPteIndex[Index]; j++) { 01560 ASSERT (PointerFreedPte->u.Hard.Valid == 0); 01561 PointerFreedPte++; 01562 } 01563 } 01564 } 01565 #endif //DBG 01566 MmSysPteListBySizeCount [Index] += 1; 01567 PointerPte = MmLastSysPteListBySize[Index]; 01568 ASSERT (PointerPte->u.List.NextEntry == MM_EMPTY_PTE_LIST); 01569 PointerPte->u.List.NextEntry = PteOffset; 01570 MmLastSysPteListBySize[Index] = StartingPte; 01571 StartingPte->u.List.NextEntry = MM_EMPTY_PTE_LIST; 01572 01573 #if DBG 01574 if (MmDebug & MM_DBG_SYS_PTES) { 01575 PMMPTE PointerPte1; 01576 PointerPte1 = &MmFreeSysPteListBySize[Index]; 01577 while (PointerPte1->u.List.NextEntry != MM_EMPTY_PTE_LIST) { 01578 PMMPTE PointerFreedPte; 01579 ULONG j; 01580 01581 PointerPte1 = MmSystemPteBase + PointerPte1->u.List.NextEntry; 01582 PointerFreedPte = PointerPte1; 01583 for (j = 0; j < MmSysPteIndex[Index]; j++) { 01584 ASSERT (PointerFreedPte->u.Hard.Valid == 0); 01585 PointerFreedPte++; 01586 } 01587 } 01588 } 01589 #endif //DBG 01590 if (NumberOfPtes == 1) { 01591 if (MmFlushPte1 == NULL) { 01592 MmFlushPte1 = StartingPte; 01593 } 01594 } else { 01595 (StartingPte + 1)->u.List.NextEntry = MmFlushCounter; 01596 } 01597 01598 MiUnlockSystemSpace(OldIrql); 01599 return; 01600 } 01601 } 01602 } 01603 #endif 01604 01605 MmTotalFreeSystemPtes[SystemPtePoolType] += NumberOfPtes; 01606 01607 PteOffset = (ULONG_PTR)(StartingPte - MmSystemPteBase); 01608 PointerPte = &MmFirstFreeSystemPte[SystemPtePoolType]; 01609 01610 while (TRUE) { 01611 NextPte = MmSystemPteBase + PointerPte->u.List.NextEntry; 01612 if (PteOffset < PointerPte->u.List.NextEntry) { 01613 01614 // 01615 // Insert in the list at this point. The 01616 // previous one should point to the new freed set and 01617 // the new freed set should point to the place 01618 // the previous set points to. 01619 // 01620 // Attempt to combine the clusters before we 01621 // insert. 01622 // 01623 // Locate the end of the current structure. 01624 // 01625 01626 ASSERT (((StartingPte + NumberOfPtes) <= NextPte) || 01627 (PointerPte->u.List.NextEntry == MM_EMPTY_PTE_LIST)); 01628 01629 PointerFollowingPte = PointerPte + 1; 01630 if (PointerPte->u.List.OneEntry) { 01631 Size = 1; 01632 } else { 01633 Size = (ULONG_PTR) PointerFollowingPte->u.List.NextEntry; 01634 } 01635 if ((PointerPte + Size) == StartingPte) { 01636 01637 // 01638 // We can combine the clusters. 01639 // 01640 01641 NumberOfPtes += (ULONG)Size; 01642 PointerFollowingPte->u.List.NextEntry = NumberOfPtes; 01643 PointerPte->u.List.OneEntry = 0; 01644 01645 // 01646 // Point the starting PTE to the beginning of 01647 // the new free set and try to combine with the 01648 // following free cluster. 01649 // 01650 01651 StartingPte = PointerPte; 01652 01653 } else { 01654 01655 // 01656 // Can't combine with previous. Make this Pte the 01657 // start of a cluster. 01658 // 01659 01660 // 01661 // Point this cluster to the next cluster. 01662 // 01663 01664 StartingPte->u.List.NextEntry = PointerPte->u.List.NextEntry; 01665 01666 // 01667 // Point the current cluster to this cluster. 01668 // 01669 01670 PointerPte->u.List.NextEntry = PteOffset; 01671 01672 // 01673 // Set the size of this cluster. 01674 // 01675 01676 if (NumberOfPtes == 1) { 01677 StartingPte->u.List.OneEntry = 1; 01678 01679 } else { 01680 StartingPte->u.List.OneEntry = 0; 01681 PointerFollowingPte = StartingPte + 1; 01682 PointerFollowingPte->u.List.NextEntry = NumberOfPtes; 01683 } 01684 } 01685 01686 // 01687 // Attempt to combine the newly created cluster with 01688 // the following cluster. 01689 // 01690 01691 if ((StartingPte + NumberOfPtes) == NextPte) { 01692 01693 // 01694 // Combine with following cluster. 01695 // 01696 01697 // 01698 // Set the next cluster to the value contained in the 01699 // cluster we are merging into this one. 01700 // 01701 01702 StartingPte->u.List.NextEntry = NextPte->u.List.NextEntry; 01703 StartingPte->u.List.OneEntry = 0; 01704 PointerFollowingPte = StartingPte + 1; 01705 01706 if (NextPte->u.List.OneEntry) { 01707 Size = 1; 01708 01709 } else { 01710 NextPte++; 01711 Size = (ULONG_PTR) NextPte->u.List.NextEntry; 01712 } 01713 PointerFollowingPte->u.List.NextEntry = NumberOfPtes + Size; 01714 } 01715 #if 0 01716 if (MmDebug & MM_DBG_SYS_PTES) { 01717 MiDumpSystemPtes(SystemPtePoolType); 01718 } 01719 #endif //0 01720 01721 #if DBG 01722 if (MmDebug & MM_DBG_SYS_PTES) { 01723 ASSERT (MmTotalFreeSystemPtes[SystemPtePoolType] == 01724 MiCountFreeSystemPtes (SystemPtePoolType)); 01725 } 01726 #endif //DBG 01727 MiUnlockSystemSpace(OldIrql); 01728 return; 01729 } 01730 01731 // 01732 // Point to next freed cluster. 01733 // 01734 01735 PointerPte = NextPte; 01736 } 01737 }

PMMPTE MiReserveSystemPtes IN ULONG  NumberOfPtes,
IN MMSYSTEM_PTE_POOL_TYPE  SystemPtePoolType,
IN ULONG  Alignment,
IN ULONG  Offset,
IN ULONG  BugCheckOnFailure
 

Definition at line 524 of file sysptes.c.

References ASSERT, Index, KeBugCheckEx(), KeFlushEntireTb(), MiFeedSysPtePool(), MiLockSystemSpace, MiReserveSystemPtes2(), MiUnlockSystemSpace, MM_DBG_SYS_PTES, MM_EMPTY_PTE_LIST, MM_FLUSH_COUNTER_MASK, MM_KERNEL_NOACCESS_PTE, MM_PTE_TABLE_LIMIT, MmFlushCounter, MmFlushPte1, MmFreeSysPteListBySize, MmLastSysPteListBySize, MmSysPteIndex, MmSysPteListBySizeCount, MmSysPteMinimumFree, MmSysPteTables, MmSystemPteBase, MmSystemPtesEnd, MmSystemPtesStart, NULL, Offset, PAGE_SHIFT, PTE_SHIFT, SystemPteSpace, TRUE, and _MMPTE::u.

Referenced by ExAllocatePool(), MiAllocatePoolPages(), MiBuildPagedPool(), MiFindContiguousMemory(), MiInitializeSpecialPool(), MiInitializeSystemPtes(), MiInitMachineDependent(), MiLoadImageSection(), MiMapBBTMemory(), MiMapSinglePage(), MiReloadBootLoadedDrivers(), MiSessionCreateInternal(), MmAllocateIndependentPages(), MmAllocateNonCachedMemory(), MmCreateKernelStack(), MmMapIoSpace(), MmMapLockedPagesSpecifyCache(), and MmMapVideoDisplay().

00534 : 00535 00536 This function locates the specified number of unused PTEs to locate 00537 within the non paged portion of system space. 00538 00539 Arguments: 00540 00541 NumberOfPtes - Supplies the number of PTEs to locate. 00542 00543 SystemPtePoolType - Supplies the PTE type of the pool to expand, one of 00544 SystemPteSpace or NonPagedPoolExpansion. 00545 00546 Alignment - Supplies the virtual address alignment for the address 00547 the returned PTE maps. For example, if the value is 64K, 00548 the returned PTE will map an address on a 64K boundary. 00549 An alignment of zero means to align on a page boundary. 00550 00551 Offset - Supplies the offset into the alignment for the virtual address. 00552 For example, if the Alignment is 64k and the Offset is 4k, 00553 the returned address will be 4k above a 64k boundary. 00554 00555 BugCheckOnFailure - Supplies FALSE if NULL should be returned if 00556 the request cannot be satisfied, TRUE if 00557 a bugcheck should be issued. 00558 00559 Return Value: 00560 00561 Returns the address of the first PTE located. 00562 NULL if no system PTEs can be located and BugCheckOnFailure is FALSE. 00563 00564 Environment: 00565 00566 Kernel mode, DISPATCH_LEVEL or below. 00567 00568 --*/ 00569 00570 { 00571 PMMPTE PointerPte; 00572 PMMPTE Previous; 00573 KIRQL OldIrql; 00574 ULONG PteMask; 00575 ULONG MaskSize; 00576 ULONG Index; 00577 00578 #ifdef _MI_GUARD_PTE_ 00579 ULONG ExactPtes; 00580 00581 if (NumberOfPtes == 0) { 00582 KeBugCheckEx (SYSTEM_PTE_MISUSE, 00583 0xA, 00584 BugCheckOnFailure, 00585 NumberOfPtes, 00586 SystemPtePoolType); 00587 } 00588 00589 if (SystemPtePoolType == SystemPteSpace) { 00590 NumberOfPtes += 1; 00591 } 00592 00593 ExactPtes = NumberOfPtes; 00594 #endif 00595 00596 if (SystemPtePoolType == SystemPteSpace) { 00597 00598 MaskSize = (Alignment - 1) >> (PAGE_SHIFT - PTE_SHIFT); 00599 PteMask = MaskSize & (Offset >> (PAGE_SHIFT - PTE_SHIFT)); 00600 00601 // 00602 // Acquire the system space lock to synchronize access to this 00603 // routine. 00604 // 00605 00606 MiLockSystemSpace(OldIrql); 00607 00608 if (NumberOfPtes <= MM_PTE_TABLE_LIMIT) { 00609 Index = MmSysPteTables [NumberOfPtes]; 00610 ASSERT (NumberOfPtes <= MmSysPteIndex[Index]); 00611 PointerPte = &MmFreeSysPteListBySize[Index]; 00612 #if DBG 00613 if (MmDebug & MM_DBG_SYS_PTES) { 00614 PMMPTE PointerPte1; 00615 PointerPte1 = &MmFreeSysPteListBySize[Index]; 00616 while (PointerPte1->u.List.NextEntry != MM_EMPTY_PTE_LIST) { 00617 PMMPTE PointerFreedPte; 00618 ULONG j; 00619 00620 PointerPte1 = MmSystemPteBase + PointerPte1->u.List.NextEntry; 00621 PointerFreedPte = PointerPte1; 00622 for (j = 0; j < MmSysPteIndex[Index]; j++) { 00623 ASSERT (PointerFreedPte->u.Hard.Valid == 0); 00624 PointerFreedPte++; 00625 } 00626 } 00627 } 00628 #endif //DBG 00629 00630 Previous = PointerPte; 00631 00632 while (PointerPte->u.List.NextEntry != MM_EMPTY_PTE_LIST) { 00633 00634 // 00635 // Try to find suitable PTEs with the proper alignment. 00636 // 00637 00638 Previous = PointerPte; 00639 PointerPte = MmSystemPteBase + PointerPte->u.List.NextEntry; 00640 #if !defined(_IA64_) 00641 if (PointerPte == MmFlushPte1) { 00642 KeFlushEntireTb (TRUE, TRUE); 00643 MmFlushCounter = (MmFlushCounter + 1) & MM_FLUSH_COUNTER_MASK; 00644 MmFlushPte1 = NULL; 00645 } 00646 #endif 00647 if ((Alignment == 0) || 00648 (((ULONG_PTR)PointerPte & MaskSize) == PteMask)) { 00649 00650 #ifdef _MI_SYSPTE_DEBUG_ 00651 MiCheckPteAllocation (PointerPte, 00652 NumberOfPtes, 00653 0, 00654 MmSysPteIndex[Index]); 00655 #endif 00656 // 00657 // Proper alignment and offset, update list index. 00658 // 00659 00660 ASSERT ((PointerPte->u.List.NextEntry + MmSystemPteBase) >= 00661 MmSystemPtesStart[SystemPtePoolType] || 00662 PointerPte->u.List.NextEntry == MM_EMPTY_PTE_LIST); 00663 ASSERT ((PointerPte->u.List.NextEntry + MmSystemPteBase) <= 00664 MmSystemPtesEnd[SystemPtePoolType] || 00665 PointerPte->u.List.NextEntry == MM_EMPTY_PTE_LIST); 00666 00667 Previous->u.List.NextEntry = PointerPte->u.List.NextEntry; 00668 MmSysPteListBySizeCount [Index] -= 1; 00669 00670 #if !defined(_IA64_) 00671 if (NumberOfPtes != 1) { 00672 00673 // 00674 // Check to see if the TB should be flushed. 00675 // 00676 00677 if ((PointerPte + 1)->u.List.NextEntry == MmFlushCounter) { 00678 KeFlushEntireTb (TRUE, TRUE); 00679 MmFlushCounter = (MmFlushCounter + 1) & 00680 MM_FLUSH_COUNTER_MASK; 00681 MmFlushPte1 = NULL; 00682 } 00683 } 00684 #endif 00685 if (PointerPte->u.List.NextEntry == MM_EMPTY_PTE_LIST) { 00686 MmLastSysPteListBySize[Index] = Previous; 00687 } 00688 #if DBG 00689 00690 if (MmDebug & MM_DBG_SYS_PTES) { 00691 PMMPTE PointerPte1; 00692 PointerPte1 = &MmFreeSysPteListBySize[Index]; 00693 while (PointerPte1->u.List.NextEntry != MM_EMPTY_PTE_LIST) { 00694 PMMPTE PointerFreedPte; 00695 ULONG j; 00696 00697 PointerPte1 = MmSystemPteBase + PointerPte1->u.List.NextEntry; 00698 PointerFreedPte = PointerPte1; 00699 for (j = 0; j < MmSysPteIndex[Index]; j++) { 00700 ASSERT (PointerFreedPte->u.Hard.Valid == 0); 00701 PointerFreedPte++; 00702 } 00703 } 00704 } 00705 #endif //DBG 00706 MiUnlockSystemSpace(OldIrql); 00707 00708 #if DBG 00709 PointerPte->u.List.NextEntry = 0xABCDE; 00710 if (MmDebug & MM_DBG_SYS_PTES) { 00711 00712 PMMPTE PointerFreedPte; 00713 ULONG j; 00714 00715 PointerFreedPte = PointerPte; 00716 for (j = 0; j < MmSysPteIndex[Index]; j++) { 00717 ASSERT (PointerFreedPte->u.Hard.Valid == 0); 00718 PointerFreedPte++; 00719 } 00720 } 00721 if (PointerPte < MmSystemPtesStart[SystemPtePoolType]) { 00722 KeBugCheckEx (SYSTEM_PTE_MISUSE, 00723 0xB, 00724 (ULONG_PTR)PointerPte, 00725 NumberOfPtes, 00726 SystemPtePoolType); 00727 } 00728 if (PointerPte > MmSystemPtesEnd[SystemPtePoolType]) { 00729 KeBugCheckEx (SYSTEM_PTE_MISUSE, 00730 0xC, 00731 (ULONG_PTR)PointerPte, 00732 NumberOfPtes, 00733 SystemPtePoolType); 00734 } 00735 #endif //DBG 00736 00737 if (MmSysPteListBySizeCount[Index] < 00738 MmSysPteMinimumFree[Index]) { 00739 MiFeedSysPtePool (Index); 00740 } 00741 #ifdef _MI_GUARD_PTE_ 00742 (PointerPte + ExactPtes - 1)->u.Long = MM_KERNEL_NOACCESS_PTE; 00743 #endif 00744 return PointerPte; 00745 } 00746 } 00747 NumberOfPtes = MmSysPteIndex [Index]; 00748 } 00749 MiUnlockSystemSpace(OldIrql); 00750 } 00751 00752 #ifdef _MI_GUARD_PTE_ 00753 NumberOfPtes = ExactPtes; 00754 #endif 00755 00756 PointerPte = MiReserveSystemPtes2 (NumberOfPtes, 00757 SystemPtePoolType, 00758 Alignment, 00759 Offset, 00760 BugCheckOnFailure); 00761 00762 #if DBG 00763 if (MmDebug & MM_DBG_SYS_PTES) { 00764 00765 PMMPTE PointerFreedPte; 00766 ULONG j; 00767 00768 if (PointerPte) { 00769 PointerFreedPte = PointerPte; 00770 for (j = 0; j < NumberOfPtes; j++) { 00771 ASSERT (PointerFreedPte->u.Hard.Valid == 0); 00772 PointerFreedPte++; 00773 } 00774 } 00775 } 00776 #endif //DBG 00777 00778 #ifdef _MI_GUARD_PTE_ 00779 if (PointerPte) { 00780 (PointerPte + ExactPtes - 1)->u.Long = MM_KERNEL_NOACCESS_PTE; 00781 } 00782 #endif 00783 00784 return PointerPte; 00785 }

PMMPTE MiReserveSystemPtes2 IN ULONG  NumberOfPtes,
IN MMSYSTEM_PTE_POOL_TYPE  SystemPtePoolType,
IN ULONG  Alignment,
IN ULONG  Offset,
IN ULONG  BugCheckOnFailure
 

Definition at line 843 of file sysptes.c.

References ASSERT, _MMPTE_FLUSH_LIST::Count, DbgPrint, DISPATCH_LEVEL, _MMPTE_FLUSH_LIST::FlushPte, _MMPTE_FLUSH_LIST::FlushVa, KeBugCheckEx(), KeLowerIrql(), KeRaiseIrql(), MiCountFreeSystemPtes(), MiDumpSystemPtes(), MiFlushPteList(), MiGetHighestPteConsumer(), MiGetVirtualAddressMappedByPte, MiLockSystemSpace, MiUnlockSystemSpace, MM_DBG_SYS_PTES, MM_EMPTY_PTE_LIST, MM_MAXIMUM_FLUSH_COUNT, MmFirstFreeSystemPte, MmNumberOfSystemPtes, MmSystemPteBase, MmTotalFreeSystemPtes, NULL, Offset, PAGE_SHIFT, PAGE_SIZE, PTE_SHIFT, SystemPteSpace, TRUE, _MMPTE::u, and ZeroKernelPte.

Referenced by MiFeedSysPtePool(), and MiReserveSystemPtes().

00853 : 00854 00855 This function locates the specified number of unused PTEs to locate 00856 within the non paged portion of system space. 00857 00858 Arguments: 00859 00860 NumberOfPtes - Supplies the number of PTEs to locate. 00861 00862 SystemPtePoolType - Supplies the PTE type of the pool to expand, one of 00863 SystemPteSpace or NonPagedPoolExpansion. 00864 00865 Alignment - Supplies the virtual address alignment for the address 00866 the returned PTE maps. For example, if the value is 64K, 00867 the returned PTE will map an address on a 64K boundary. 00868 An alignment of zero means to align on a page boundary. 00869 00870 Offset - Supplies the offset into the alignment for the virtual address. 00871 For example, if the Alignment is 64k and the Offset is 4k, 00872 the returned address will be 4k above a 64k boundary. 00873 00874 BugCheckOnFailure - Supplies FALSE if NULL should be returned if 00875 the request cannot be satisfied, TRUE if 00876 a bugcheck should be issued. 00877 00878 Return Value: 00879 00880 Returns the address of the first PTE located. 00881 NULL if no system PTEs can be located and BugCheckOnFailure is FALSE. 00882 00883 Environment: 00884 00885 Kernel mode, DISPATCH_LEVEL or below. 00886 00887 --*/ 00888 00889 { 00890 PMMPTE PointerPte; 00891 PMMPTE PointerFollowingPte; 00892 PMMPTE Previous; 00893 ULONG_PTR SizeInSet; 00894 KIRQL OldIrql; 00895 ULONG MaskSize; 00896 ULONG NumberOfRequiredPtes; 00897 ULONG OffsetSum; 00898 ULONG PtesToObtainAlignment; 00899 PMMPTE NextSetPointer; 00900 ULONG_PTR LeftInSet; 00901 ULONG_PTR PteOffset; 00902 MMPTE_FLUSH_LIST PteFlushList; 00903 PVOID HighConsumer; 00904 ULONG_PTR HighPteUse; 00905 00906 MaskSize = (Alignment - 1) >> (PAGE_SHIFT - PTE_SHIFT); 00907 00908 OffsetSum = (Offset >> (PAGE_SHIFT - PTE_SHIFT)) | 00909 (Alignment >> (PAGE_SHIFT - PTE_SHIFT)); 00910 00911 MiLockSystemSpace(OldIrql); 00912 00913 // 00914 // The nonpaged PTE pool uses the invalid PTEs to define the pool 00915 // structure. A global pointer points to the first free set 00916 // in the list, each free set contains the number free and a pointer 00917 // to the next free set. The free sets are kept in an ordered list 00918 // such that the pointer to the next free set is always greater 00919 // than the address of the current free set. 00920 // 00921 // As to not limit the size of this pool, two PTEs are used 00922 // to define a free region. If the region is a single PTE, the 00923 // prototype field within the PTE is set indicating the set 00924 // consists of a single PTE. 00925 // 00926 // The page frame number field is used to define the next set 00927 // and the number free. The two flavors are: 00928 // 00929 // o V 00930 // n l 00931 // e d 00932 // +-----------------------+-+----------+ 00933 // | next set |0|0 0| 00934 // +-----------------------+-+----------+ 00935 // | number in this set |0|0 0| 00936 // +-----------------------+-+----------+ 00937 // 00938 // 00939 // +-----------------------+-+----------+ 00940 // | next set |1|0 0| 00941 // +-----------------------+-+----------+ 00942 // ... 00943 // 00944 00945 // 00946 // Acquire the system space lock to synchronize access to this routine. 00947 // 00948 00949 PointerPte = &MmFirstFreeSystemPte[SystemPtePoolType]; 00950 Previous = PointerPte; 00951 00952 if (PointerPte->u.List.NextEntry == MM_EMPTY_PTE_LIST) { 00953 00954 // 00955 // End of list and none found, return NULL or bugcheck. 00956 // 00957 00958 if (BugCheckOnFailure) { 00959 goto IssueBugcheck; 00960 } 00961 00962 MiUnlockSystemSpace(OldIrql); 00963 return NULL; 00964 } 00965 00966 PointerPte = MmSystemPteBase + PointerPte->u.List.NextEntry; 00967 00968 if (Alignment <= PAGE_SIZE) { 00969 00970 // 00971 // Don't deal with alignment issues. 00972 // 00973 00974 while (TRUE) { 00975 00976 if (PointerPte->u.List.OneEntry) { 00977 SizeInSet = 1; 00978 00979 } else { 00980 00981 PointerFollowingPte = PointerPte + 1; 00982 SizeInSet = (ULONG_PTR) PointerFollowingPte->u.List.NextEntry; 00983 } 00984 00985 if (NumberOfPtes < SizeInSet) { 00986 00987 // 00988 // Get the PTEs from this set and reduce the size of the 00989 // set. Note that the size of the current set cannot be 1. 00990 // 00991 00992 if ((SizeInSet - NumberOfPtes) == 1) { 00993 00994 // 00995 // Collapse to the single PTE format. 00996 // 00997 00998 PointerPte->u.List.OneEntry = 1; 00999 01000 } else { 01001 01002 PointerFollowingPte->u.List.NextEntry = SizeInSet - NumberOfPtes; 01003 01004 // 01005 // Get the required PTEs from the end of the set. 01006 // 01007 01008 #if 0 01009 if (MmDebug & MM_DBG_SYS_PTES) { 01010 MiDumpSystemPtes(SystemPtePoolType); 01011 PointerFollowingPte = PointerPte + (SizeInSet - NumberOfPtes); 01012 DbgPrint("allocated 0x%lx Ptes at %lx\n",NumberOfPtes,PointerFollowingPte); 01013 } 01014 #endif //0 01015 } 01016 01017 MmTotalFreeSystemPtes[SystemPtePoolType] -= NumberOfPtes; 01018 #if DBG 01019 if (MmDebug & MM_DBG_SYS_PTES) { 01020 ASSERT (MmTotalFreeSystemPtes[SystemPtePoolType] == 01021 MiCountFreeSystemPtes (SystemPtePoolType)); 01022 } 01023 #endif //DBG 01024 01025 #ifdef _MI_SYSPTE_DEBUG_ 01026 MiCheckPteAllocation (PointerPte + (SizeInSet - NumberOfPtes), 01027 NumberOfPtes, 01028 1, 01029 0); 01030 #endif 01031 01032 MiUnlockSystemSpace(OldIrql); 01033 01034 PointerPte = PointerPte + (SizeInSet - NumberOfPtes); 01035 goto Flush; 01036 } 01037 01038 if (NumberOfPtes == SizeInSet) { 01039 01040 // 01041 // Satisfy the request with this complete set and change 01042 // the list to reflect the fact that this set is gone. 01043 // 01044 01045 Previous->u.List.NextEntry = PointerPte->u.List.NextEntry; 01046 01047 // 01048 // Release the system PTE lock. 01049 // 01050 01051 #if 0 01052 if (MmDebug & MM_DBG_SYS_PTES) { 01053 MiDumpSystemPtes(SystemPtePoolType); 01054 PointerFollowingPte = PointerPte + (SizeInSet - NumberOfPtes); 01055 DbgPrint("allocated 0x%lx Ptes at %lx\n",NumberOfPtes,PointerFollowingPte); 01056 } 01057 #endif //0 01058 01059 MmTotalFreeSystemPtes[SystemPtePoolType] -= NumberOfPtes; 01060 #if DBG 01061 if (MmDebug & MM_DBG_SYS_PTES) { 01062 ASSERT (MmTotalFreeSystemPtes[SystemPtePoolType] == 01063 MiCountFreeSystemPtes (SystemPtePoolType)); 01064 } 01065 #endif //DBG 01066 01067 #ifdef _MI_SYSPTE_DEBUG_ 01068 MiCheckPteAllocation (PointerPte, 01069 NumberOfPtes, 01070 2, 01071 0); 01072 #endif 01073 01074 MiUnlockSystemSpace(OldIrql); 01075 goto Flush; 01076 } 01077 01078 // 01079 // Point to the next set and try again 01080 // 01081 01082 if (PointerPte->u.List.NextEntry == MM_EMPTY_PTE_LIST) { 01083 01084 // 01085 // End of list and none found, return NULL or bugcheck. 01086 // 01087 01088 if (BugCheckOnFailure) { 01089 goto IssueBugcheck; 01090 } 01091 01092 MiUnlockSystemSpace(OldIrql); 01093 return NULL; 01094 } 01095 Previous = PointerPte; 01096 PointerPte = MmSystemPteBase + PointerPte->u.List.NextEntry; 01097 ASSERT (PointerPte > Previous); 01098 } 01099 01100 } else { 01101 01102 // 01103 // Deal with the alignment issues. 01104 // 01105 01106 while (TRUE) { 01107 01108 if (PointerPte->u.List.OneEntry) { 01109 SizeInSet = 1; 01110 01111 } else { 01112 01113 PointerFollowingPte = PointerPte + 1; 01114 SizeInSet = (ULONG_PTR) PointerFollowingPte->u.List.NextEntry; 01115 } 01116 01117 PtesToObtainAlignment = (ULONG) 01118 (((OffsetSum - ((ULONG_PTR)PointerPte & MaskSize)) & MaskSize) >> 01119 PTE_SHIFT); 01120 01121 NumberOfRequiredPtes = NumberOfPtes + PtesToObtainAlignment; 01122 01123 if (NumberOfRequiredPtes < SizeInSet) { 01124 01125 // 01126 // Get the PTEs from this set and reduce the size of the 01127 // set. Note that the size of the current set cannot be 1. 01128 // 01129 // This current block will be slit into 2 blocks if 01130 // the PointerPte does not match the alignment. 01131 // 01132 01133 // 01134 // Check to see if the first PTE is on the proper 01135 // alignment, if so, eliminate this block. 01136 // 01137 01138 LeftInSet = SizeInSet - NumberOfRequiredPtes; 01139 01140 // 01141 // Set up the new set at the end of this block. 01142 // 01143 01144 NextSetPointer = PointerPte + NumberOfRequiredPtes; 01145 NextSetPointer->u.List.NextEntry = 01146 PointerPte->u.List.NextEntry; 01147 01148 PteOffset = (ULONG_PTR)(NextSetPointer - MmSystemPteBase); 01149 01150 if (PtesToObtainAlignment == 0) { 01151 01152 Previous->u.List.NextEntry += NumberOfRequiredPtes; 01153 01154 } else { 01155 01156 // 01157 // Point to the new set at the end of the block 01158 // we are giving away. 01159 // 01160 01161 PointerPte->u.List.NextEntry = PteOffset; 01162 01163 // 01164 // Update the size of the current set. 01165 // 01166 01167 if (PtesToObtainAlignment == 1) { 01168 01169 // 01170 // Collapse to the single PTE format. 01171 // 01172 01173 PointerPte->u.List.OneEntry = 1; 01174 01175 } else { 01176 01177 // 01178 // Set the set size in the next PTE. 01179 // 01180 01181 PointerFollowingPte->u.List.NextEntry = 01182 PtesToObtainAlignment; 01183 } 01184 } 01185 01186 // 01187 // Set up the new set at the end of the block. 01188 // 01189 01190 if (LeftInSet == 1) { 01191 NextSetPointer->u.List.OneEntry = 1; 01192 } else { 01193 NextSetPointer->u.List.OneEntry = 0; 01194 NextSetPointer += 1; 01195 NextSetPointer->u.List.NextEntry = LeftInSet; 01196 } 01197 MmTotalFreeSystemPtes[SystemPtePoolType] -= NumberOfPtes; 01198 #if DBG 01199 if (MmDebug & MM_DBG_SYS_PTES) { 01200 ASSERT (MmTotalFreeSystemPtes[SystemPtePoolType] == 01201 MiCountFreeSystemPtes (SystemPtePoolType)); 01202 } 01203 #endif //DBG 01204 01205 #ifdef _MI_SYSPTE_DEBUG_ 01206 MiCheckPteAllocation (PointerPte + PtesToObtainAlignment, 01207 NumberOfPtes, 01208 3, 01209 0); 01210 #endif 01211 01212 MiUnlockSystemSpace(OldIrql); 01213 01214 PointerPte = PointerPte + PtesToObtainAlignment; 01215 goto Flush; 01216 } 01217 01218 if (NumberOfRequiredPtes == SizeInSet) { 01219 01220 // 01221 // Satisfy the request with this complete set and change 01222 // the list to reflect the fact that this set is gone. 01223 // 01224 01225 if (PtesToObtainAlignment == 0) { 01226 01227 // 01228 // This block exactly satisfies the request. 01229 // 01230 01231 Previous->u.List.NextEntry = 01232 PointerPte->u.List.NextEntry; 01233 01234 } else { 01235 01236 // 01237 // A portion at the start of this block remains. 01238 // 01239 01240 if (PtesToObtainAlignment == 1) { 01241 01242 // 01243 // Collapse to the single PTE format. 01244 // 01245 01246 PointerPte->u.List.OneEntry = 1; 01247 01248 } else { 01249 PointerFollowingPte->u.List.NextEntry = 01250 PtesToObtainAlignment; 01251 01252 } 01253 } 01254 01255 MmTotalFreeSystemPtes[SystemPtePoolType] -= NumberOfPtes; 01256 #if DBG 01257 if (MmDebug & MM_DBG_SYS_PTES) { 01258 ASSERT (MmTotalFreeSystemPtes[SystemPtePoolType] == 01259 MiCountFreeSystemPtes (SystemPtePoolType)); 01260 } 01261 #endif //DBG 01262 01263 #ifdef _MI_SYSPTE_DEBUG_ 01264 MiCheckPteAllocation (PointerPte + PtesToObtainAlignment, 01265 NumberOfPtes, 01266 4, 01267 0); 01268 #endif 01269 01270 MiUnlockSystemSpace(OldIrql); 01271 01272 PointerPte = PointerPte + PtesToObtainAlignment; 01273 goto Flush; 01274 } 01275 01276 // 01277 // Point to the next set and try again 01278 // 01279 01280 if (PointerPte->u.List.NextEntry == MM_EMPTY_PTE_LIST) { 01281 01282 // 01283 // End of list and none found, return NULL or bugcheck. 01284 // 01285 01286 if (BugCheckOnFailure) { 01287 goto IssueBugcheck; 01288 } 01289 01290 MiUnlockSystemSpace(OldIrql); 01291 return NULL; 01292 } 01293 Previous = PointerPte; 01294 PointerPte = MmSystemPteBase + PointerPte->u.List.NextEntry; 01295 ASSERT (PointerPte > Previous); 01296 } 01297 } 01298 Flush: 01299 01300 if (SystemPtePoolType == SystemPteSpace) { 01301 PVOID BaseAddress; 01302 ULONG j; 01303 01304 PteFlushList.Count = 0; 01305 Previous = PointerPte; 01306 BaseAddress = MiGetVirtualAddressMappedByPte (Previous); 01307 01308 for (j = 0; j < NumberOfPtes ; j++) { 01309 if (PteFlushList.Count != MM_MAXIMUM_FLUSH_COUNT) { 01310 PteFlushList.FlushPte[PteFlushList.Count] = Previous; 01311 PteFlushList.FlushVa[PteFlushList.Count] = BaseAddress; 01312 PteFlushList.Count += 1; 01313 } 01314 01315 // 01316 // PTEs being freed better be invalid. 01317 // 01318 ASSERT (Previous->u.Hard.Valid == 0); 01319 01320 *Previous = ZeroKernelPte; 01321 BaseAddress = (PVOID)((PCHAR)BaseAddress + PAGE_SIZE); 01322 Previous++; 01323 } 01324 01325 KeRaiseIrql (DISPATCH_LEVEL, &OldIrql); 01326 MiFlushPteList (&PteFlushList, TRUE, ZeroKernelPte); 01327 KeLowerIrql (OldIrql); 01328 } 01329 return PointerPte; 01330 01331 IssueBugcheck: 01332 01333 if (SystemPtePoolType == SystemPteSpace) { 01334 01335 HighConsumer = MiGetHighestPteConsumer (&HighPteUse); 01336 01337 if (HighConsumer != NULL) { 01338 KeBugCheckEx (DRIVER_USED_EXCESSIVE_PTES, 01339 (ULONG_PTR)HighConsumer, 01340 HighPteUse, 01341 MmTotalFreeSystemPtes[SystemPtePoolType], 01342 MmNumberOfSystemPtes); 01343 } 01344 } 01345 01346 KeBugCheckEx (NO_MORE_SYSTEM_PTES, 01347 (ULONG_PTR)SystemPtePoolType, 01348 NumberOfPtes, 01349 MmTotalFreeSystemPtes[SystemPtePoolType], 01350 MmNumberOfSystemPtes); 01351 }


Variable Documentation

ULONG MmFlushCounter
 

Definition at line 78 of file sysptes.c.

Referenced by MiFlushPteList(), MiInitializeSystemPtes(), MiReleaseSystemPtes(), and MiReserveSystemPtes().

PMMPTE MmFlushPte1
 

Definition at line 76 of file sysptes.c.

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

MMPTE MmFreeSysPteListBySize[MM_SYS_PTE_TABLES_MAX]
 

Definition at line 101 of file sysptes.c.

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

PMMPTE MmLastSysPteListBySize[MM_SYS_PTE_TABLES_MAX]
 

Definition at line 102 of file sysptes.c.

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

ULONG MmSysPteIndex[MM_SYS_PTE_TABLES_MAX] = {1,2,4,8,16}
 

Definition at line 96 of file sysptes.c.

Referenced by MiFeedSysPtePool(), MiInitializeSystemPtes(), MiReleaseSystemPtes(), and MiReserveSystemPtes().

ULONG MmSysPteListBySizeCount[MM_SYS_PTE_TABLES_MAX]
 

Definition at line 103 of file sysptes.c.

Referenced by MiGetSystemPteAvailability(), MiGetSystemPteListCount(), MiReleaseSystemPtes(), and MiReserveSystemPtes().

ULONG MmSysPteMinimumFree[MM_SYS_PTE_TABLES_MAX] = {100,50,30,20,20}
 

Definition at line 104 of file sysptes.c.

Referenced by MiGetSystemPteAvailability(), MiReleaseSystemPtes(), and MiReserveSystemPtes().

UCHAR MmSysPteTables[17] = {0,0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4}
 

Definition at line 98 of file sysptes.c.

Referenced by MiGetSystemPteAvailability(), MiGetSystemPteListCount(), MiReleaseSystemPtes(), and MiReserveSystemPtes().

PMMPTE MmSystemPtesEnd[MaximumPtePoolTypes]
 

Definition at line 71 of file sysptes.c.

PMMPTE MmSystemPtesStart[MaximumPtePoolTypes]
 

Definition at line 70 of file sysptes.c.

ULONG MmTotalFreeSystemPtes[MaximumPtePoolTypes]
 

Definition at line 69 of file sysptes.c.


Generated on Sat May 15 19:45:44 2004 for test by doxygen 1.3.7