990 lines
24 KiB
C
990 lines
24 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
|
|
Landy Wang (landyw) 02-June-1997
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
#include "mi.h"
|
|
|
|
//
|
|
// Highest user address;
|
|
//
|
|
|
|
PVOID MmHighestUserAddress;
|
|
|
|
//
|
|
// Start of system address range.
|
|
//
|
|
|
|
PVOID MmSystemRangeStart;
|
|
|
|
//
|
|
// User probe address;
|
|
//
|
|
|
|
ULONG_PTR MmUserProbeAddress;
|
|
|
|
#if !defined(_WIN64)
|
|
|
|
//
|
|
// Virtual bias applied during the loading of the kernel image.
|
|
//
|
|
|
|
ULONG_PTR MmVirtualBias;
|
|
|
|
#endif
|
|
|
|
//
|
|
// Number of secondary colors, based on level 2 d cache size.
|
|
//
|
|
|
|
ULONG MmSecondaryColors;
|
|
|
|
//
|
|
// The starting color index seed, incremented at each process creation.
|
|
//
|
|
|
|
ULONG MmProcessColorSeed = 0x12345678;
|
|
|
|
//
|
|
// Total number of physical pages available on the system.
|
|
//
|
|
|
|
PFN_COUNT MmNumberOfPhysicalPages;
|
|
|
|
//
|
|
// Lowest physical page number in the system.
|
|
//
|
|
|
|
PFN_NUMBER MmLowestPhysicalPage = (PFN_NUMBER)-1;
|
|
|
|
//
|
|
// Highest physical page number in the system.
|
|
//
|
|
|
|
PFN_NUMBER MmHighestPhysicalPage;
|
|
|
|
//
|
|
// Highest possible physical page number in the system.
|
|
//
|
|
|
|
PFN_NUMBER MmHighestPossiblePhysicalPage;
|
|
|
|
//
|
|
// 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;
|
|
|
|
//
|
|
// Highest VAD index used to create bitmaps.
|
|
//
|
|
|
|
ULONG MiLastVadBit = 1;
|
|
|
|
//
|
|
// System wide memory management statistics block.
|
|
//
|
|
|
|
MMINFO_COUNTERS MmInfoCounters;
|
|
|
|
//
|
|
// 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 = 768;
|
|
|
|
//
|
|
// The following values are frequently used together. They tend
|
|
// not to be modified once the system has initialized so should
|
|
// not be grouped with data whose values change frequently to
|
|
// eliminate false sharing.
|
|
//
|
|
|
|
ULONG MmSecondaryColorMask;
|
|
UCHAR MmSecondaryColorNodeShift;
|
|
|
|
//
|
|
// 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
|
|
};
|
|
|
|
//
|
|
// Note the ROM page listhead is deliberately not in the set
|
|
// of MmPageLocationList ranges.
|
|
//
|
|
|
|
MMPFNLIST MmRomPageListHead = {
|
|
0, // Total
|
|
StandbyPageList, // ListName
|
|
MM_EMPTY_LIST, //Flink
|
|
MM_EMPTY_LIST // Blink
|
|
};
|
|
|
|
|
|
PMMPFNLIST MmPageLocationList[NUMBER_OF_PAGE_LISTS] = {
|
|
&MmZeroedPageListHead,
|
|
&MmFreePageListHead,
|
|
&MmStandbyPageListHead,
|
|
&MmModifiedPageListHead,
|
|
&MmModifiedNoWritePageListHead,
|
|
&MmBadPageListHead,
|
|
NULL,
|
|
NULL };
|
|
|
|
PMMPTE MiHighestUserPte;
|
|
PMMPTE MiHighestUserPde;
|
|
#if (_MI_PAGING_LEVELS >= 4)
|
|
PMMPTE MiHighestUserPpe;
|
|
PMMPTE MiHighestUserPxe;
|
|
#endif
|
|
|
|
PMMPTE MiSessionBasePte;
|
|
PMMPTE MiSessionLastPte;
|
|
|
|
//
|
|
// Hyper space items.
|
|
//
|
|
|
|
PMMPTE MmFirstReservedMappingPte;
|
|
|
|
PMMPTE MmLastReservedMappingPte;
|
|
|
|
//
|
|
// Event for available pages, set means pages are available.
|
|
//
|
|
|
|
KEVENT MmAvailablePagesEvent;
|
|
|
|
//
|
|
// Event for the zeroing page thread.
|
|
//
|
|
|
|
KEVENT MmZeroingPageEvent;
|
|
|
|
//
|
|
// 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;
|
|
|
|
//
|
|
// This is set in the registry to the maximum number of gigabytes of RAM
|
|
// that can be added to this machine (ie: #of DIMM slots times maximum
|
|
// supported DIMM size). This lets configurations that won't use the absolute
|
|
// maximum indicate that a smaller (virtually) PFN database size can be used
|
|
// thus leaving more virtual address space for things like system PTEs, etc.
|
|
//
|
|
|
|
PFN_NUMBER MmDynamicPfn;
|
|
|
|
#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;
|
|
|
|
KSPIN_LOCK MiTrackLockedPagesLock;
|
|
|
|
//
|
|
// 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;
|
|
|
|
ULONG MmMaximumNonPagedPoolPercent;
|
|
|
|
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.
|
|
|
|
ULONG MmNumberOfSystemPtes;
|
|
|
|
ULONG MiRequestedSystemPtes;
|
|
|
|
PMMPTE MmFirstPteForPagedPool;
|
|
|
|
PMMPTE MmLastPteForPagedPool;
|
|
|
|
//
|
|
// Pool bit maps and other related structures.
|
|
//
|
|
|
|
PVOID MmPageAlignedPoolBase[2];
|
|
|
|
ULONG MmExpandedPoolBitPosition;
|
|
|
|
PFN_NUMBER MmNumberOfFreeNonPagedPool;
|
|
|
|
//
|
|
// MmFirstFreeSystemPte contains the offset from the
|
|
// Nonpaged system base to the first free system PTE.
|
|
// Note that an offset of -1 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.
|
|
//
|
|
|
|
ULONG_PTR 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 MmMaximumDeadKernelStacks = 5;
|
|
SLIST_HEADER MmDeadStackSListHead;
|
|
|
|
//
|
|
// Cells to track control area synchronization.
|
|
//
|
|
|
|
SLIST_HEADER MmEventCountSListHead;
|
|
|
|
SLIST_HEADER MmInPageSupportSListHead;
|
|
|
|
//
|
|
// 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;
|
|
|
|
PMMADDRESS_NODE MmSectionBasedRoot;
|
|
|
|
PVOID MmHighSectionBase;
|
|
|
|
//
|
|
// Section object type.
|
|
//
|
|
|
|
POBJECT_TYPE MmSectionObjectType;
|
|
|
|
//
|
|
// Section commit mutex.
|
|
//
|
|
|
|
FAST_MUTEX MmSectionCommitMutex;
|
|
|
|
//
|
|
// Section base address mutex.
|
|
//
|
|
|
|
FAST_MUTEX MmSectionBasedMutex;
|
|
|
|
//
|
|
// Resource for section extension.
|
|
//
|
|
|
|
ERESOURCE MmSectionExtendResource;
|
|
ERESOURCE MmSectionExtendSetResource;
|
|
|
|
//
|
|
// Pagefile creation lock.
|
|
//
|
|
|
|
FAST_MUTEX MmPageFileCreationLock;
|
|
|
|
MMDEREFERENCE_SEGMENT_HEADER MmDereferenceSegmentHeader;
|
|
|
|
LIST_ENTRY MmUnusedSegmentList;
|
|
|
|
LIST_ENTRY MmUnusedSubsectionList;
|
|
|
|
KEVENT MmUnusedSegmentCleanup;
|
|
|
|
ULONG MmUnusedSegmentCount;
|
|
|
|
ULONG MmUnusedSubsectionCount;
|
|
|
|
ULONG MmUnusedSubsectionCountPeak;
|
|
|
|
SIZE_T MiUnusedSubsectionPagedPool;
|
|
|
|
SIZE_T MiUnusedSubsectionPagedPoolPeak;
|
|
|
|
//
|
|
// If more than this percentage of pool is consumed and pool allocations
|
|
// might fail, then trim unused segments & subsections to get back to
|
|
// this percentage.
|
|
//
|
|
|
|
ULONG MmConsumedPoolPercentage;
|
|
|
|
MMWORKING_SET_EXPANSION_HEAD MmWorkingSetExpansionHead;
|
|
|
|
MMPAGE_FILE_EXPANSION MmAttemptForCantExtend;
|
|
|
|
//
|
|
// Paging files
|
|
//
|
|
|
|
MMMOD_WRITER_LISTHEAD MmPagingFileHeader;
|
|
|
|
MMMOD_WRITER_LISTHEAD MmMappedFileHeader;
|
|
|
|
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;
|
|
|
|
//
|
|
// Minimum size in pages to extend the paging file by.
|
|
//
|
|
|
|
ULONG MmPageFileExtension = 256;
|
|
|
|
//
|
|
// Size to reduce the paging file by.
|
|
//
|
|
|
|
ULONG MmMinimumPageFileReduction = 256; //256 pages (1mb)
|
|
|
|
//
|
|
// Number of pages to write in a single I/O.
|
|
//
|
|
|
|
ULONG MmModifiedWriteClusterSize = MM_MAXIMUM_WRITE_CLUSTER;
|
|
|
|
//
|
|
// Number of pages to read in a single I/O if possible.
|
|
//
|
|
|
|
ULONG MmReadClusterSize = 7;
|
|
|
|
const ULONG MMSECT = 'tSmM'; // This is exported to special pool.
|
|
|
|
//
|
|
// This resource 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;
|
|
|
|
//
|
|
// System process working set sizes.
|
|
//
|
|
|
|
PFN_NUMBER MmSystemProcessWorkingSetMin = 50;
|
|
|
|
PFN_NUMBER MmSystemProcessWorkingSetMax = 450;
|
|
|
|
WSLE_NUMBER MmMaximumWorkingSetSize;
|
|
|
|
PFN_NUMBER MmMinimumWorkingSetSize = 20;
|
|
|
|
|
|
//
|
|
// Page color for system working set.
|
|
//
|
|
|
|
ULONG MmSystemPageColor;
|
|
|
|
//
|
|
// Time constants
|
|
//
|
|
|
|
const LARGE_INTEGER MmSevenMinutes = {0, -1};
|
|
|
|
//
|
|
// Note that the following constant is initialized to five seconds,
|
|
// but is set to 3 on very small workstations.
|
|
//
|
|
|
|
LARGE_INTEGER MmWorkingSetProtectionTime = {5 * 1000 * 1000 * 10, 0};
|
|
|
|
const LARGE_INTEGER MmOneSecond = {(ULONG)(-1 * 1000 * 1000 * 10), -1};
|
|
const LARGE_INTEGER MmTwentySeconds = {(ULONG)(-20 * 1000 * 1000 * 10), -1};
|
|
const LARGE_INTEGER MmShortTime = {(ULONG)(-10 * 1000 * 10), -1}; // 10 milliseconds
|
|
const LARGE_INTEGER MmHalfSecond = {(ULONG)(-5 * 100 * 1000 * 10), -1};
|
|
const LARGE_INTEGER Mm30Milliseconds = {(ULONG)(-30 * 1000 * 10), -1};
|
|
|
|
//
|
|
// Parameters for user mode passed up via PEB in MmCreatePeb.
|
|
//
|
|
|
|
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
|
|
};
|
|
|
|
#if (defined(_WIN64) || defined(_X86PAE_))
|
|
ULONGLONG
|
|
#else
|
|
ULONG
|
|
#endif
|
|
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.
|
|
//
|
|
|
|
ULONG_PTR MmSessionBase;
|
|
|
|
PMM_SESSION_SPACE MmSessionSpace;
|
|
|
|
ULONG_PTR MiSessionSpaceWs;
|
|
|
|
SIZE_T MmSessionSize;
|
|
|
|
LIST_ENTRY MiSessionWsList;
|
|
|
|
ULONG_PTR MiSystemViewStart;
|
|
|
|
SIZE_T MmSystemViewSize;
|
|
|
|
ULONG_PTR MiSessionPoolStart;
|
|
|
|
ULONG_PTR MiSessionPoolEnd;
|
|
|
|
ULONG_PTR MiSessionSpaceEnd;
|
|
|
|
ULONG_PTR MiSessionViewStart;
|
|
|
|
ULONG MiSessionSpacePageTables;
|
|
|
|
SIZE_T MmSessionViewSize;
|
|
|
|
SIZE_T MmSessionPoolSize;
|
|
|
|
ULONG_PTR MiSessionImageStart;
|
|
|
|
ULONG_PTR MiSessionImageEnd;
|
|
|
|
PMMPTE MiSessionImagePteStart;
|
|
|
|
PMMPTE MiSessionImagePteEnd;
|
|
|
|
SIZE_T MmSessionImageSize;
|
|
|
|
//
|
|
// Cache control stuff. Note this may be overridden by deficient hardware
|
|
// platforms at startup.
|
|
//
|
|
|
|
MI_PFN_CACHE_ATTRIBUTE MiPlatformCacheAttributes[2 * MmMaximumCacheType] =
|
|
{
|
|
//
|
|
// Memory space
|
|
//
|
|
|
|
MiNonCached,
|
|
MiCached,
|
|
MiWriteCombined,
|
|
MiCached,
|
|
MiNonCached,
|
|
MiWriteCombined,
|
|
|
|
//
|
|
// I/O space
|
|
//
|
|
|
|
MiNonCached,
|
|
MiCached,
|
|
MiWriteCombined,
|
|
MiCached,
|
|
MiNonCached,
|
|
MiWriteCombined
|
|
};
|
|
|
|
//
|
|
// Note the Driver Verifier can reinitialize the mask values.
|
|
//
|
|
|
|
ULONG MiIoRetryMask = 0x1f;
|
|
ULONG MiFaultRetryMask = 0x1f;
|
|
ULONG MiUserFaultRetryMask = 0xF;
|
|
|
|
#if defined (_MI_INSTRUMENT_PFN)
|
|
|
|
//
|
|
// Instrumentation code to track PFN lock duration.
|
|
//
|
|
|
|
ULONG MiPfnTimings;
|
|
ULONG_PTR MiPfnAcquiredAddress;
|
|
LARGE_INTEGER MiPfnAcquired;
|
|
LARGE_INTEGER MiPfnThreshold;
|
|
|
|
MMPFNTIMINGS MiPfnSorted[MI_MAX_PFN_CALLERS];
|
|
ULONG MiMaxPfnTimings = MI_MAX_PFN_CALLERS;
|
|
|
|
ULONG_PTR
|
|
MiGetExecutionAddress(
|
|
VOID
|
|
)
|
|
{
|
|
#if defined(_X86_)
|
|
_asm {
|
|
push dword ptr [esp]
|
|
pop eax
|
|
}
|
|
#else
|
|
PVOID CallingAddress;
|
|
PVOID CallersCaller;
|
|
|
|
RtlGetCallersAddress (&CallingAddress, &CallersCaller);
|
|
return (ULONG_PTR) CallingAddress;
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
#ifdef ALLOC_DATA_PRAGMA
|
|
#pragma data_seg("INIT")
|
|
#endif
|
|
|
|
WCHAR MmVerifyDriverBuffer[MI_SUSPECT_DRIVER_BUFFER_LENGTH] = {0};
|
|
ULONG MmVerifyDriverBufferType = REG_NONE;
|
|
ULONG MmVerifyDriverLevel = (ULONG)-1;
|
|
ULONG MmCritsectTimeoutSeconds = 2592000;
|
|
|
|
#ifdef ALLOC_DATA_PRAGMA
|
|
#pragma data_seg()
|
|
#endif
|
|
|
|
ULONG MmVerifyDriverBufferLength = sizeof(MmVerifyDriverBuffer);
|
|
|
|
|