554 lines
22 KiB
C
554 lines
22 KiB
C
|
/*++
|
||
|
Copyright (c) 1989 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
miglobal.c
|
||
|
|
||
|
Abstract:
|
||
|
This module contains the private global storage for the memory management subsystem.
|
||
|
|
||
|
Author:
|
||
|
Lou Perazzoli (loup) 6-Apr-1989
|
||
|
--*/
|
||
|
#include "mi.h"
|
||
|
|
||
|
PVOID MmHighestUserAddress;// Highest user address;
|
||
|
PVOID MmSystemRangeStart;// Start of system address range.
|
||
|
ULONG_PTR MmUserProbeAddress;// User probe address;
|
||
|
ULONG_PTR MmVirtualBias;// Virtual bias applied during the loading of the kernel image.
|
||
|
ULONG MmSecondaryColors;// Number of secondary colors, based on level 2 d cache size.
|
||
|
ULONG MmProcessColorSeed = 0x12345678;// The starting color index seed, incremented at each process creation.
|
||
|
PFN_COUNT MmNumberOfPhysicalPages;// Total number of physical pages available on the system.
|
||
|
PFN_NUMBER MmLowestPhysicalPage = (PFN_NUMBER)-1;// Lowest physical page number in the system.
|
||
|
PFN_NUMBER MmHighestPhysicalPage;// Highest physical page number in the system.
|
||
|
PFN_NUMBER MmHighestPossiblePhysicalPage;// Highest possible physical page number in the system.
|
||
|
|
||
|
|
||
|
// Total number of available pages in the system.
|
||
|
// This is the sum of the pages on the zeroed, free and standby lists.
|
||
|
PFN_COUNT MmAvailablePages;
|
||
|
PFN_NUMBER MmThrottleTop;
|
||
|
PFN_NUMBER MmThrottleBottom;
|
||
|
|
||
|
MMINFO_COUNTERS MmInfoCounters;// System wide memory management statistics block.
|
||
|
|
||
|
|
||
|
// Total number of physical pages which would be usable if every process was at its minimum working set size.
|
||
|
// This value is initialized at system initialization to MmAvailablePages - MM_FLUID_PHYSICAL_PAGES.
|
||
|
// Every time a thread is created, the kernel stack is subtracted from
|
||
|
// this and every time a process is created, the minimum working set is subtracted from this.
|
||
|
// If the value would become negative, the operation (create process/kernel stack/ adjust working set) fails.
|
||
|
// The PFN LOCK must be owned to manipulate this value.
|
||
|
SPFN_NUMBER MmResidentAvailablePages;
|
||
|
|
||
|
// The total number of pages which would be removed from working sets if every working set was at its minimum.
|
||
|
PFN_NUMBER MmPagesAboveWsMinimum;
|
||
|
|
||
|
// The total number of pages which would be removed from working sets
|
||
|
// if every working set above its maximum was at its maximum.
|
||
|
PFN_NUMBER MmPagesAboveWsMaximum;
|
||
|
|
||
|
// The number of pages to add to a working set if there are ample
|
||
|
// available pages and the working set is below its maximum.
|
||
|
|
||
|
// If memory is becoming short and MmPagesAboveWsMinimum is greater than MmPagesAboveWsThreshold, trim working sets.
|
||
|
PFN_NUMBER MmPagesAboveWsThreshold = 37;
|
||
|
PFN_NUMBER MmWorkingSetSizeIncrement = 6;
|
||
|
|
||
|
// The number of pages to extend the maximum working set size by
|
||
|
// if the working set at its maximum and there are ample available pages.
|
||
|
PFN_NUMBER MmWorkingSetSizeExpansion = 20;
|
||
|
|
||
|
// The number of pages required to be freed by working set reduction before working set reduction is attempted.
|
||
|
PFN_NUMBER MmWsAdjustThreshold = 45;
|
||
|
|
||
|
// The number of pages available to allow the working set to be expanded above its maximum.
|
||
|
PFN_NUMBER MmWsExpandThreshold = 90;
|
||
|
|
||
|
// The total number of pages to reduce by working set trimming.
|
||
|
PFN_NUMBER MmWsTrimReductionGoal = 29;
|
||
|
|
||
|
// The total number of pages needed for the loader to successfully hibernate.
|
||
|
PFN_NUMBER MmHiberPages = 512;
|
||
|
|
||
|
// Registry-settable threshold for using large pages. x86 only.
|
||
|
ULONG MmLargePageMinimum;
|
||
|
|
||
|
PMMPFN MmPfnDatabase;
|
||
|
|
||
|
MMPFNLIST MmZeroedPageListHead = {
|
||
|
0, // Total
|
||
|
ZeroedPageList, // ListName
|
||
|
MM_EMPTY_LIST, //Flink
|
||
|
MM_EMPTY_LIST // Blink
|
||
|
};
|
||
|
|
||
|
MMPFNLIST MmFreePageListHead = {
|
||
|
0, // Total
|
||
|
FreePageList, // ListName
|
||
|
MM_EMPTY_LIST, //Flink
|
||
|
MM_EMPTY_LIST // Blink
|
||
|
};
|
||
|
|
||
|
MMPFNLIST MmStandbyPageListHead = {
|
||
|
0, // Total
|
||
|
StandbyPageList, // ListName
|
||
|
MM_EMPTY_LIST, //Flink
|
||
|
MM_EMPTY_LIST // Blink
|
||
|
};
|
||
|
|
||
|
MMPFNLIST MmModifiedPageListHead = {
|
||
|
0, // Total
|
||
|
ModifiedPageList, // ListName
|
||
|
MM_EMPTY_LIST, //Flink
|
||
|
MM_EMPTY_LIST // Blink
|
||
|
};
|
||
|
|
||
|
MMPFNLIST MmModifiedNoWritePageListHead = {
|
||
|
0, // Total
|
||
|
ModifiedNoWritePageList, // ListName
|
||
|
MM_EMPTY_LIST, //Flink
|
||
|
MM_EMPTY_LIST // Blink
|
||
|
};
|
||
|
|
||
|
MMPFNLIST MmBadPageListHead = {
|
||
|
0, // Total
|
||
|
BadPageList, // ListName
|
||
|
MM_EMPTY_LIST, //Flink
|
||
|
MM_EMPTY_LIST // Blink
|
||
|
};
|
||
|
|
||
|
PMMPFNLIST MmPageLocationList[NUMBER_OF_PAGE_LISTS] = {
|
||
|
&MmZeroedPageListHead,
|
||
|
&MmFreePageListHead,
|
||
|
&MmStandbyPageListHead,
|
||
|
&MmModifiedPageListHead,
|
||
|
&MmModifiedNoWritePageListHead,
|
||
|
&MmBadPageListHead,
|
||
|
NULL,
|
||
|
NULL };
|
||
|
|
||
|
// PMMPFNLIST MmPageLocationList[FreePageList] = &MmFreePageListHead;
|
||
|
// PMMPFNLIST MmPageLocationList[ZeroedPageList] = &MmZeroedPageListHead;
|
||
|
// PMMPFNLIST MmPageLocationList[StandbyPageList] = &MmStandbyPageListHead;
|
||
|
// PMMPFNLIST MmPageLocationList[ModifiedPageList] = &MmModifiedPageListHead;
|
||
|
// PMMPFNLIST MmPageLocationList[ModifiedNoWritePageList] = &MmModifiedNoWritePageListHead;
|
||
|
// PMMPFNLIST MmPageLocationList[BadPageList] = &MmBadPageListHead;
|
||
|
// PMMPFNLIST MmPageLocationList[ActiveAndValid] = NULL;
|
||
|
// PMMPFNLIST MmPageLocationList[TransitionPage] = NULL;
|
||
|
|
||
|
PMMPTE MiHighestUserPte;
|
||
|
PMMPTE MiHighestUserPde;
|
||
|
|
||
|
PMMPTE MiSessionBasePte;
|
||
|
PMMPTE MiSessionLastPte;
|
||
|
|
||
|
// Hyper space items.
|
||
|
PMMPTE MmFirstReservedMappingPte;
|
||
|
PMMPTE MmLastReservedMappingPte;
|
||
|
PMMWSL MmWorkingSetList;
|
||
|
PMMWSLE MmWsle;
|
||
|
|
||
|
KEVENT MmAvailablePagesEvent;// Event for available pages, set means pages are available.
|
||
|
KEVENT MmZeroingPageEvent;// Event for the zeroing page thread.
|
||
|
|
||
|
// Boolean to indicate if the zeroing page thread is currently
|
||
|
// active. This is set to true when the zeroing page event is
|
||
|
// set and set to false when the zeroing page thread is done zeroing all the pages on the free list.
|
||
|
BOOLEAN MmZeroingPageThreadActive;
|
||
|
|
||
|
// Minimum number of free pages before zeroing page thread starts.
|
||
|
PFN_NUMBER MmMinimumFreePagesToZero = 8;
|
||
|
|
||
|
// System space sizes - MmNonPagedSystemStart to MM_NON_PAGED_SYSTEM_END
|
||
|
// defines the ranges of PDEs which must be copied into a new process's address space.
|
||
|
|
||
|
PVOID MmNonPagedSystemStart;
|
||
|
LOGICAL MmProtectFreedNonPagedPool;
|
||
|
LOGICAL MmDynamicPfn = FALSE;
|
||
|
|
||
|
#if PFN_CONSISTENCY
|
||
|
PMMPTE MiPfnStartPte;
|
||
|
PFN_NUMBER MiPfnPtes;
|
||
|
BOOLEAN MiPfnProtectionEnabled;
|
||
|
PETHREAD MiPfnLockOwner;
|
||
|
#endif
|
||
|
|
||
|
#ifdef MM_BUMP_COUNTER_MAX
|
||
|
SIZE_T MmResTrack[MM_BUMP_COUNTER_MAX];
|
||
|
#endif
|
||
|
|
||
|
#ifdef MM_COMMIT_COUNTER_MAX
|
||
|
SIZE_T MmTrackCommit[MM_COMMIT_COUNTER_MAX];
|
||
|
#endif
|
||
|
|
||
|
// Set via the registry to identify which drivers are leaking locked pages.
|
||
|
LOGICAL MmTrackLockedPages;
|
||
|
|
||
|
// Set via the registry to identify drivers which unload without releasing resources or still have active timers, etc.
|
||
|
LOGICAL MmSnapUnloads = TRUE;
|
||
|
|
||
|
#if DBG
|
||
|
PETHREAD MiExpansionLockOwner;
|
||
|
#endif
|
||
|
|
||
|
// Pool sizes.
|
||
|
SIZE_T MmSizeOfNonPagedPoolInBytes;
|
||
|
SIZE_T MmMaximumNonPagedPoolInBytes;
|
||
|
SIZE_T MmMinimumNonPagedPoolSize = 256 * 1024; // 256k
|
||
|
ULONG MmMinAdditionNonPagedPoolPerMb = 32 * 1024; // 32k
|
||
|
SIZE_T MmDefaultMaximumNonPagedPool = 1024 * 1024; // 1mb
|
||
|
ULONG MmMaxAdditionNonPagedPoolPerMb = 400 * 1024; //400k
|
||
|
SIZE_T MmSizeOfPagedPoolInBytes = 32 * 1024 * 1024; // 32 MB.
|
||
|
PFN_NUMBER MmSizeOfNonPagedMustSucceed = 4 * PAGE_SIZE; // 4 pages
|
||
|
ULONG MmNumberOfSystemPtes;
|
||
|
ULONG MiRequestedSystemPtes;
|
||
|
ULONG MmLockPagesPercentage;
|
||
|
PFN_NUMBER MmLockPagesLimit;
|
||
|
PMMPTE MmFirstPteForPagedPool;
|
||
|
PMMPTE MmLastPteForPagedPool;
|
||
|
PMMPTE MmPagedPoolBasePde;
|
||
|
|
||
|
// Pool bit maps and other related structures.
|
||
|
PVOID MmPageAlignedPoolBase[2];
|
||
|
PVOID MmNonPagedMustSucceed;
|
||
|
ULONG MmExpandedPoolBitPosition;
|
||
|
PFN_NUMBER MmNumberOfFreeNonPagedPool;
|
||
|
ULONG MmMustSucceedPoolBitPosition;
|
||
|
|
||
|
// MmFirstFreeSystemPte contains the offset from the Nonpaged system base to the first free system PTE.
|
||
|
// Note that an offset of FFFFF indicates an empty list.
|
||
|
MMPTE MmFirstFreeSystemPte[MaximumPtePoolTypes];
|
||
|
|
||
|
// System cache sizes.
|
||
|
PMMWSL MmSystemCacheWorkingSetList = (PMMWSL)MM_SYSTEM_CACHE_WORKING_SET;
|
||
|
MMSUPPORT MmSystemCacheWs;
|
||
|
PMMWSLE MmSystemCacheWsle;
|
||
|
PVOID MmSystemCacheStart = (PVOID)MM_SYSTEM_CACHE_START;
|
||
|
PVOID MmSystemCacheEnd;
|
||
|
PRTL_BITMAP MmSystemCacheAllocationMap;
|
||
|
PRTL_BITMAP MmSystemCacheEndingMap;
|
||
|
|
||
|
// This value should not be greater than 256MB in a system with 1GB of system space.
|
||
|
PFN_COUNT MmSizeOfSystemCacheInPages = 64 * 256; //64MB.
|
||
|
|
||
|
// Default sizes for the system cache.
|
||
|
PFN_NUMBER MmSystemCacheWsMinimum = 288;
|
||
|
PFN_NUMBER MmSystemCacheWsMaximum = 350;
|
||
|
|
||
|
// Cells to track unused thread kernel stacks to avoid TB flushes every time a thread terminates.
|
||
|
ULONG MmNumberDeadKernelStacks;
|
||
|
ULONG MmMaximumDeadKernelStacks = 5;
|
||
|
PMMPFN MmFirstDeadKernelStack = (PMMPFN)NULL;
|
||
|
|
||
|
// MmSystemPteBase contains the address of 1 PTE before the first free system PTE (zero indicates an empty list).
|
||
|
// The value of this field does not change once set.
|
||
|
|
||
|
PMMPTE MmSystemPteBase;
|
||
|
PMMWSL MmWorkingSetList;
|
||
|
PMMWSLE MmWsle;
|
||
|
PMMADDRESS_NODE MmSectionBasedRoot;
|
||
|
PVOID MmHighSectionBase;
|
||
|
|
||
|
POBJECT_TYPE MmSectionObjectType;// Section object type.
|
||
|
FAST_MUTEX MmSectionCommitMutex;// Section commit mutex.
|
||
|
FAST_MUTEX MmSectionBasedMutex;// Section base address mutex.
|
||
|
|
||
|
// Resource for section extension.
|
||
|
ERESOURCE MmSectionExtendResource;
|
||
|
ERESOURCE MmSectionExtendSetResource;
|
||
|
|
||
|
// Pagefile creation lock.
|
||
|
FAST_MUTEX MmPageFileCreationLock;
|
||
|
MMDEREFERENCE_SEGMENT_HEADER MmDereferenceSegmentHeader;
|
||
|
LIST_ENTRY MmUnusedSegmentList;
|
||
|
KEVENT MmUnusedSegmentCleanup;
|
||
|
ULONG MmUnusedSegmentCount;
|
||
|
|
||
|
SIZE_T MmMaxUnusedSegmentPagedPoolUsage;// Maximum amount of paged pool to keep in unused segments.
|
||
|
|
||
|
// Amount of paged pool used by unused segments.
|
||
|
SIZE_T MmUnusedSegmentPagedPoolUsage;
|
||
|
SIZE_T MiUnusedSegmentPagedPoolUsage;
|
||
|
|
||
|
SIZE_T MmUnusedSegmentPagedPoolReduction;// Amount to reduce paged pool by when it starts getting low.
|
||
|
SIZE_T MmMaxUnusedSegmentNonPagedPoolUsage;// Maximum amount of nonpaged pool to keep in unused segments.
|
||
|
|
||
|
// Amount of nonpaged pool used by unused segments.
|
||
|
SIZE_T MmUnusedSegmentNonPagedPoolUsage;
|
||
|
SIZE_T MiUnusedSegmentNonPagedPoolUsage;
|
||
|
|
||
|
// Amount to reduce nonpaged pool by when it starts getting low.
|
||
|
SIZE_T MmUnusedSegmentNonPagedPoolReduction;
|
||
|
|
||
|
// Unused File Cache trim level - this is the percentage of pool consumed by unused file segments.
|
||
|
// The minimum is 5%, the maximum (ie: largest caching)
|
||
|
// is 40%. Under 20% is almost always the correct value.
|
||
|
|
||
|
ULONG MmUnusedSegmentTrimLevel = 18;
|
||
|
MMWORKING_SET_EXPANSION_HEAD MmWorkingSetExpansionHead;
|
||
|
MMPAGE_FILE_EXPANSION MmAttemptForCantExtend;
|
||
|
|
||
|
// Paging files
|
||
|
MMMOD_WRITER_LISTHEAD MmPagingFileHeader;
|
||
|
MMMOD_WRITER_LISTHEAD MmMappedFileHeader;
|
||
|
PMMMOD_WRITER_MDL_ENTRY MmMappedFileMdl[MM_MAPPED_FILE_MDLS]; ;
|
||
|
LIST_ENTRY MmFreePagingSpaceLow;
|
||
|
ULONG MmNumberOfActiveMdlEntries;
|
||
|
PMMPAGING_FILE MmPagingFile[MAX_PAGE_FILES];
|
||
|
ULONG MmNumberOfPagingFiles;
|
||
|
KEVENT MmModifiedPageWriterEvent;
|
||
|
KEVENT MmWorkingSetManagerEvent;
|
||
|
KEVENT MmCollidedFlushEvent;
|
||
|
|
||
|
// Total number of committed pages.
|
||
|
SIZE_T MmTotalCommittedPages;
|
||
|
|
||
|
// Limit on committed pages. When MmTotalCommittedPages would become
|
||
|
// greater than or equal to this number the paging files must be expanded.
|
||
|
SIZE_T MmTotalCommitLimit;
|
||
|
SIZE_T MmTotalCommitLimitMaximum;
|
||
|
|
||
|
// Number of pages to overcommit without expanding the paging file.
|
||
|
// MmTotalCommitLimit = (total paging file space) + MmOverCommit.
|
||
|
SIZE_T MmOverCommit;
|
||
|
|
||
|
// Modified page writer.
|
||
|
|
||
|
// Minimum number of free pages before working set trimming and aggressive modified page writing is started.
|
||
|
PFN_NUMBER MmMinimumFreePages = 26;
|
||
|
|
||
|
// Stop writing modified pages when MmFreeGoal pages exist.
|
||
|
PFN_NUMBER MmFreeGoal = 100;
|
||
|
|
||
|
// Start writing pages if more than this number of pages is on the modified page list.
|
||
|
PFN_NUMBER MmModifiedPageMaximum;
|
||
|
|
||
|
// Minimum number of modified pages required before the modified page writer is started.
|
||
|
PFN_NUMBER MmModifiedPageMinimum;
|
||
|
|
||
|
// Amount of disk space that must be free after the paging file is extended.
|
||
|
ULONG MmMinimumFreeDiskSpace = 1024 * 1024;
|
||
|
|
||
|
// Size to extend the paging file by.
|
||
|
ULONG MmPageFileExtension = 128; //128 pages
|
||
|
|
||
|
// Size to reduce the paging file by.
|
||
|
ULONG MmMinimumPageFileReduction = 256; //256 pages (1mb)
|
||
|
|
||
|
ULONG MmModifiedWriteClusterSize = MM_MAXIMUM_WRITE_CLUSTER;// Number of pages to write in a single I/O.
|
||
|
ULONG MmReadClusterSize = 7;// Number of pages to read in a single I/O if possible.
|
||
|
|
||
|
// Spin locks.
|
||
|
|
||
|
// Spinlock which guards PFN database.
|
||
|
// This spinlock is used by memory management for accessing the PFN database.
|
||
|
// The I/O system makes use of it for unlocking pages during I/O completion.
|
||
|
|
||
|
// KSPIN_LOCK MmPfnLock;
|
||
|
|
||
|
// Spinlock which guards the working set list for the system shared address space (paged pool, system cache, pagable drivers).
|
||
|
ERESOURCE MmSystemWsLock;
|
||
|
PETHREAD MmSystemLockOwner;
|
||
|
|
||
|
// Spin lock for allowing working set expansion.
|
||
|
KSPIN_LOCK MmExpansionLock;
|
||
|
|
||
|
// Spin lock for protecting hyper space access.
|
||
|
|
||
|
// System process working set sizes.
|
||
|
PFN_NUMBER MmSystemProcessWorkingSetMin = 50;
|
||
|
PFN_NUMBER MmSystemProcessWorkingSetMax = 450;
|
||
|
PFN_NUMBER MmMaximumWorkingSetSize;
|
||
|
PFN_NUMBER MmMinimumWorkingSetSize = 20;
|
||
|
|
||
|
ULONG MmSystemPageColor;// Page color for system working set.
|
||
|
LARGE_INTEGER MmSevenMinutes = { 0, -1 };// Time constants
|
||
|
|
||
|
// note that the following constant is initialized to five seconds, but is set to 3 on very small workstations.
|
||
|
// The constant used to be called MmFiveSecondsAbsolute, but since its value changes depending on
|
||
|
// the system type and size, I decided to change the name to reflect this
|
||
|
LARGE_INTEGER MmWorkingSetProtectionTime = { 5 * 1000 * 1000 * 10, 0 };
|
||
|
|
||
|
LARGE_INTEGER MmOneSecond = { (ULONG)(-1 * 1000 * 1000 * 10), -1 };
|
||
|
LARGE_INTEGER MmTwentySeconds = { (ULONG)(-20 * 1000 * 1000 * 10), -1 };
|
||
|
LARGE_INTEGER MmShortTime = { (ULONG)(-10 * 1000 * 10), -1 };// 10 milliseconds
|
||
|
LARGE_INTEGER MmHalfSecond = { (ULONG)(-5 * 100 * 1000 * 10), -1 };
|
||
|
LARGE_INTEGER Mm30Milliseconds = { (ULONG)(-30 * 1000 * 10), -1 };
|
||
|
|
||
|
// Parameters for user mode passed up via PEB in MmCreatePeb
|
||
|
ULONG MmCritsectTimeoutSeconds = 2592000;
|
||
|
LARGE_INTEGER MmCriticalSectionTimeout;// Filled in by mminit.c
|
||
|
SIZE_T MmHeapSegmentReserve = 1024 * 1024;
|
||
|
SIZE_T MmHeapSegmentCommit = PAGE_SIZE * 2;
|
||
|
SIZE_T MmHeapDeCommitTotalFreeThreshold = 64 * 1024;
|
||
|
SIZE_T MmHeapDeCommitFreeBlockThreshold = PAGE_SIZE;
|
||
|
|
||
|
// Set from ntos\config\CMDAT3.C Used by customers to disable paging of executive on machines with lots of memory.
|
||
|
// Worth a few TPS on a database server.
|
||
|
ULONG MmDisablePagingExecutive;
|
||
|
BOOLEAN Mm64BitPhysicalAddress;
|
||
|
|
||
|
#if DBG
|
||
|
ULONG MmDebug;
|
||
|
#endif
|
||
|
|
||
|
// Map a page protection from the Pte.Protect field into a protection mask.
|
||
|
ULONG MmProtectToValue[32] = {
|
||
|
PAGE_NOACCESS,
|
||
|
PAGE_READONLY,
|
||
|
PAGE_EXECUTE,
|
||
|
PAGE_EXECUTE_READ,
|
||
|
PAGE_READWRITE,
|
||
|
PAGE_WRITECOPY,
|
||
|
PAGE_EXECUTE_READWRITE,
|
||
|
PAGE_EXECUTE_WRITECOPY,
|
||
|
PAGE_NOACCESS,
|
||
|
PAGE_NOCACHE | PAGE_READONLY,
|
||
|
PAGE_NOCACHE | PAGE_EXECUTE,
|
||
|
PAGE_NOCACHE | PAGE_EXECUTE_READ,
|
||
|
PAGE_NOCACHE | PAGE_READWRITE,
|
||
|
PAGE_NOCACHE | PAGE_WRITECOPY,
|
||
|
PAGE_NOCACHE | PAGE_EXECUTE_READWRITE,
|
||
|
PAGE_NOCACHE | PAGE_EXECUTE_WRITECOPY,
|
||
|
PAGE_NOACCESS,
|
||
|
PAGE_GUARD | PAGE_READONLY,
|
||
|
PAGE_GUARD | PAGE_EXECUTE,
|
||
|
PAGE_GUARD | PAGE_EXECUTE_READ,
|
||
|
PAGE_GUARD | PAGE_READWRITE,
|
||
|
PAGE_GUARD | PAGE_WRITECOPY,
|
||
|
PAGE_GUARD | PAGE_EXECUTE_READWRITE,
|
||
|
PAGE_GUARD | PAGE_EXECUTE_WRITECOPY,
|
||
|
PAGE_NOACCESS,
|
||
|
PAGE_NOCACHE | PAGE_GUARD | PAGE_READONLY,
|
||
|
PAGE_NOCACHE | PAGE_GUARD | PAGE_EXECUTE,
|
||
|
PAGE_NOCACHE | PAGE_GUARD | PAGE_EXECUTE_READ,
|
||
|
PAGE_NOCACHE | PAGE_GUARD | PAGE_READWRITE,
|
||
|
PAGE_NOCACHE | PAGE_GUARD | PAGE_WRITECOPY,
|
||
|
PAGE_NOCACHE | PAGE_GUARD | PAGE_EXECUTE_READWRITE,
|
||
|
PAGE_NOCACHE | PAGE_GUARD | PAGE_EXECUTE_WRITECOPY
|
||
|
};
|
||
|
|
||
|
ULONG MmProtectToPteMask[32] = {
|
||
|
MM_PTE_NOACCESS,
|
||
|
MM_PTE_READONLY | MM_PTE_CACHE,
|
||
|
MM_PTE_EXECUTE | MM_PTE_CACHE,
|
||
|
MM_PTE_EXECUTE_READ | MM_PTE_CACHE,
|
||
|
MM_PTE_READWRITE | MM_PTE_CACHE,
|
||
|
MM_PTE_WRITECOPY | MM_PTE_CACHE,
|
||
|
MM_PTE_EXECUTE_READWRITE | MM_PTE_CACHE,
|
||
|
MM_PTE_EXECUTE_WRITECOPY | MM_PTE_CACHE,
|
||
|
MM_PTE_NOACCESS,
|
||
|
MM_PTE_NOCACHE | MM_PTE_READONLY,
|
||
|
MM_PTE_NOCACHE | MM_PTE_EXECUTE,
|
||
|
MM_PTE_NOCACHE | MM_PTE_EXECUTE_READ,
|
||
|
MM_PTE_NOCACHE | MM_PTE_READWRITE,
|
||
|
MM_PTE_NOCACHE | MM_PTE_WRITECOPY,
|
||
|
MM_PTE_NOCACHE | MM_PTE_EXECUTE_READWRITE,
|
||
|
MM_PTE_NOCACHE | MM_PTE_EXECUTE_WRITECOPY,
|
||
|
MM_PTE_NOACCESS,
|
||
|
MM_PTE_GUARD | MM_PTE_READONLY | MM_PTE_CACHE,
|
||
|
MM_PTE_GUARD | MM_PTE_EXECUTE | MM_PTE_CACHE,
|
||
|
MM_PTE_GUARD | MM_PTE_EXECUTE_READ | MM_PTE_CACHE,
|
||
|
MM_PTE_GUARD | MM_PTE_READWRITE | MM_PTE_CACHE,
|
||
|
MM_PTE_GUARD | MM_PTE_WRITECOPY | MM_PTE_CACHE,
|
||
|
MM_PTE_GUARD | MM_PTE_EXECUTE_READWRITE | MM_PTE_CACHE,
|
||
|
MM_PTE_GUARD | MM_PTE_EXECUTE_WRITECOPY | MM_PTE_CACHE,
|
||
|
MM_PTE_NOACCESS,
|
||
|
MM_PTE_NOCACHE | MM_PTE_GUARD | MM_PTE_READONLY,
|
||
|
MM_PTE_NOCACHE | MM_PTE_GUARD | MM_PTE_EXECUTE,
|
||
|
MM_PTE_NOCACHE | MM_PTE_GUARD | MM_PTE_EXECUTE_READ,
|
||
|
MM_PTE_NOCACHE | MM_PTE_GUARD | MM_PTE_READWRITE,
|
||
|
MM_PTE_NOCACHE | MM_PTE_GUARD | MM_PTE_WRITECOPY,
|
||
|
MM_PTE_NOCACHE | MM_PTE_GUARD | MM_PTE_EXECUTE_READWRITE,
|
||
|
MM_PTE_NOCACHE | MM_PTE_GUARD | MM_PTE_EXECUTE_WRITECOPY
|
||
|
};
|
||
|
|
||
|
// Conversion which takes a Pte.Protect and builds a new Pte.Protect which is not copy-on-write.
|
||
|
ULONG MmMakeProtectNotWriteCopy[32] = {
|
||
|
MM_NOACCESS,
|
||
|
MM_READONLY,
|
||
|
MM_EXECUTE,
|
||
|
MM_EXECUTE_READ,
|
||
|
MM_READWRITE,
|
||
|
MM_READWRITE, //not copy
|
||
|
MM_EXECUTE_READWRITE,
|
||
|
MM_EXECUTE_READWRITE,
|
||
|
MM_NOACCESS,
|
||
|
MM_NOCACHE | MM_READONLY,
|
||
|
MM_NOCACHE | MM_EXECUTE,
|
||
|
MM_NOCACHE | MM_EXECUTE_READ,
|
||
|
MM_NOCACHE | MM_READWRITE,
|
||
|
MM_NOCACHE | MM_READWRITE,
|
||
|
MM_NOCACHE | MM_EXECUTE_READWRITE,
|
||
|
MM_NOCACHE | MM_EXECUTE_READWRITE,
|
||
|
MM_NOACCESS,
|
||
|
MM_GUARD_PAGE | MM_READONLY,
|
||
|
MM_GUARD_PAGE | MM_EXECUTE,
|
||
|
MM_GUARD_PAGE | MM_EXECUTE_READ,
|
||
|
MM_GUARD_PAGE | MM_READWRITE,
|
||
|
MM_GUARD_PAGE | MM_READWRITE,
|
||
|
MM_GUARD_PAGE | MM_EXECUTE_READWRITE,
|
||
|
MM_GUARD_PAGE | MM_EXECUTE_READWRITE,
|
||
|
MM_NOACCESS,
|
||
|
MM_NOCACHE | MM_GUARD_PAGE | MM_READONLY,
|
||
|
MM_NOCACHE | MM_GUARD_PAGE | MM_EXECUTE,
|
||
|
MM_NOCACHE | MM_GUARD_PAGE | MM_EXECUTE_READ,
|
||
|
MM_NOCACHE | MM_GUARD_PAGE | MM_READWRITE,
|
||
|
MM_NOCACHE | MM_GUARD_PAGE | MM_READWRITE,
|
||
|
MM_NOCACHE | MM_GUARD_PAGE | MM_EXECUTE_READWRITE,
|
||
|
MM_NOCACHE | MM_GUARD_PAGE | MM_EXECUTE_READWRITE
|
||
|
};
|
||
|
|
||
|
// Converts a protection code to an access right for section access.
|
||
|
// This uses only the lower 3 bits of the 5 bit protection code.
|
||
|
ACCESS_MASK MmMakeSectionAccess[8] = { SECTION_MAP_READ,
|
||
|
SECTION_MAP_READ,
|
||
|
SECTION_MAP_EXECUTE,
|
||
|
SECTION_MAP_EXECUTE | SECTION_MAP_READ,
|
||
|
SECTION_MAP_WRITE,
|
||
|
SECTION_MAP_READ,
|
||
|
SECTION_MAP_EXECUTE | SECTION_MAP_WRITE,
|
||
|
SECTION_MAP_EXECUTE | SECTION_MAP_READ };
|
||
|
|
||
|
// Converts a protection code to an access right for file access.
|
||
|
// This uses only the lower 3 bits of the 5 bit protection code.
|
||
|
ACCESS_MASK MmMakeFileAccess[8] = { FILE_READ_DATA,
|
||
|
FILE_READ_DATA,
|
||
|
FILE_EXECUTE,
|
||
|
FILE_EXECUTE | FILE_READ_DATA,
|
||
|
FILE_WRITE_DATA | FILE_READ_DATA,
|
||
|
FILE_READ_DATA,
|
||
|
FILE_EXECUTE | FILE_WRITE_DATA | FILE_READ_DATA,
|
||
|
FILE_EXECUTE | FILE_READ_DATA };
|
||
|
|
||
|
MM_PAGED_POOL_INFO MmPagedPoolInfo;
|
||
|
|
||
|
// Some Hydra variables.
|
||
|
BOOLEAN MiHydra;
|
||
|
ULONG_PTR MmSessionBase;
|
||
|
PMM_SESSION_SPACE MmSessionSpace;
|
||
|
LIST_ENTRY MiSessionWsList;
|
||
|
ULONG_PTR MiSystemViewStart;
|
||
|
|
||
|
// Both retry level and initial count must both be initialized to the same value.
|
||
|
// Note that the Driver Verifier can override these.
|
||
|
|
||
|
ULONG MiIoRetryLevel = 25;
|
||
|
ULONG MiFaultRetries = 25;
|
||
|
ULONG MiUserIoRetryLevel = 10;
|
||
|
ULONG MiUserFaultRetries = 10;
|
||
|
|
||
|
#ifdef ALLOC_DATA_PRAGMA
|
||
|
#pragma data_seg("INIT")
|
||
|
#endif
|
||
|
|
||
|
WCHAR MmVerifyDriverBuffer[MI_SUSPECT_DRIVER_BUFFER_LENGTH];
|
||
|
ULONG MmVerifyDriverBufferLength = sizeof(MmVerifyDriverBuffer);
|
||
|
ULONG MmVerifyDriverBufferType = REG_NONE;
|
||
|
ULONG MmVerifyDriverLevel = (ULONG)-1;
|
||
|
|
||
|
#ifdef ALLOC_DATA_PRAGMA
|
||
|
#pragma data_seg()
|
||
|
#endif
|