NT4/private/ntos/mm/mi.h
2020-09-30 17:12:29 +02:00

3302 lines
68 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
mi.h
Abstract:
This module contains the private data structures and procedure
prototypes for the memory management system.
Author:
Lou Perazzoli (loup) 20-Mar-1989
Revision History:
--*/
#ifndef _MI_
#define _MI_
#include "ntos.h"
#include "ntimage.h"
#include "ki.h"
#include "fsrtl.h"
#include "zwapi.h"
#include "pool.h"
#include "ntiodump.h"
#include "stdio.h"
#include "string.h"
#if defined(_X86_)
#include "..\mm\i386\mi386.h"
#elif defined(_MIPS_)
#include "..\mm\mips\mir4000.h"
#elif defined(_ALPHA_)
#include "..\mm\alpha\mialpha.h"
#elif defined(_PPC_)
#include "..\mm\ppc\mippc.h"
#else
#error "mm: a target architecture must be defined."
#endif
#define MM_EMPTY_LIST ((ULONG)0xFFFFFFFF)
#define MM_EMPTY_PTE_LIST ((ULONG)0xFFFFF)
// #define MM_DELETED_PFN ((PMMPTE)0xFFFFFFFF)
#define MM_FREE_WSLE_SHIFT 4
#define WSLE_NULL_INDEX ((ULONG)0xFFFFFFF)
#define MM_FREE_POOL_SIGNATURE (0x50554F4C)
#define MM_MINIMUM_PAGED_POOL_NTAS ((ULONG)(48*1024*1024))
#define MM_ALLOCATION_FILLS_VAD ((PMMPTE)0xFFFFFFFC)
#define MM_WORKING_SET_LIST_SEARCH 17
#define MM_FLUID_WORKING_SET 8
#define MM_FLUID_PHYSICAL_PAGES 32 //see MmResidentPages below.
#define MM_USABLE_PAGES_FREE 32
#define MM_WSLE_MAX_HASH_SIZE \
(((MM_WORKING_SET_END - (ULONG)(PAGE_SIZE + (ULONG)WORKING_SET_LIST \
+ sizeof(MMWSL) + \
((ULONG)MM_MAXIMUM_WORKING_SET * sizeof(MMWSLE)))) & ~(PAGE_SIZE - 1)) / \
sizeof(MMWSLE_HASH))
#define X64K (ULONG)65536
#define SEC_PHYSICAL_MEMORY (ULONG)0x80000000
#define MM_HIGHEST_VAD_ADDRESS ((PVOID)((ULONG)MM_HIGHEST_USER_ADDRESS - (64*1024)))
#define MM_NO_WS_EXPANSION ((PLIST_ENTRY)0)
#define MM_WS_EXPANSION_IN_PROGRESS ((PLIST_ENTRY)35)
#define MM_WS_SWAPPED_OUT ((PLIST_ENTRY)37)
#define MM_IO_IN_PROGRESS ((PLIST_ENTRY)97) // MUST HAVE THE HIGHEST VALUE
#define MM_PAGES_REQUIRED_FOR_MAPPED_IO 7
#define MMSECTOR_SHIFT 9 //MUST BE LESS THAN OR EQUAL TO PAGE_SHIFT
#define MMSECTOR_MASK 0x1ff
#define MM_LOCK_BY_REFCOUNT 0
#define MM_LOCK_BY_NONPAGE 1
#define MM_FORCE_TRIM 6
#define MM_GROW_WSLE_HASH 20
#define MM_MAXIMUM_WRITE_CLUSTER (MM_MAXIMUM_DISK_IO_SIZE / PAGE_SIZE)
//
// Number of PTEs to flush singularly before flushing the entire TB.
//
#define MM_MAXIMUM_FLUSH_COUNT (FLUSH_MULTIPLE_MAXIMUM-1)
//
// Page protections
//
#define MM_ZERO_ACCESS 0 // this value is not used.
#define MM_READONLY 1
#define MM_EXECUTE 2
#define MM_EXECUTE_READ 3
#define MM_READWRITE 4 // bit 2 is set if this is writeable.
#define MM_WRITECOPY 5
#define MM_EXECUTE_READWRITE 6
#define MM_EXECUTE_WRITECOPY 7
#define MM_NOCACHE 0x8
#define MM_GUARD_PAGE 0x10
#define MM_DECOMMIT 0x10 //NO_ACCESS, Guard page
#define MM_NOACCESS 0x18 //no_access, guard_page, nocache.
#define MM_UNKNOWN_PROTECTION 0x100 //bigger than 5 bits!
#define MM_LARGE_PAGES 0x111
#define MM_PROTECTION_WRITE_MASK 4
#define MM_PROTECTION_COPY_MASK 1
#define MM_PROTECTION_OPERATION_MASK 7 // mask off guard page and nocache.
#define MM_PROTECTION_EXECUTE_MASK 2
#define MM_SECURE_DELETE_CHECK 0x55
//
// Debug flags
//
#define MM_DBG_WRITEFAULT 0x1
#define MM_DBG_PTE_UPDATE 0x2
#define MM_DBG_DUMP_WSL 0x4
#define MM_DBG_PAGEFAULT 0x8
#define MM_DBG_WS_EXPANSION 0x10
#define MM_DBG_MOD_WRITE 0x20
#define MM_DBG_CHECK_PTE 0x40
#define MM_DBG_VAD_CONFLICT 0x80
#define MM_DBG_SECTIONS 0x100
#define MM_DBG_SYS_PTES 0x400
#define MM_DBG_CLEAN_PROCESS 0x800
#define MM_DBG_COLLIDED_PAGE 0x1000
#define MM_DBG_DUMP_BOOT_PTES 0x2000
#define MM_DBG_FORK 0x4000
#define MM_DBG_DIR_BASE 0x8000
#define MM_DBG_FLUSH_SECTION 0x10000
#define MM_DBG_PRINTS_MODWRITES 0x20000
#define MM_DBG_PAGE_IN_LIST 0x40000
#define MM_DBG_CHECK_PFN_LOCK 0x80000
#define MM_DBG_PRIVATE_PAGES 0x100000
#define MM_DBG_WALK_VAD_TREE 0x200000
#define MM_DBG_SWAP_PROCESS 0x400000
#define MM_DBG_LOCK_CODE 0x800000
#define MM_DBG_STOP_ON_ACCVIO 0x1000000
#define MM_DBG_PAGE_REF_COUNT 0x2000000
#define MM_DBG_SHOW_NT_CALLS 0x10000000
#define MM_DBG_SHOW_FAULTS 0x40000000
//
// if the PTE.protection & MM_COPY_ON_WRITE_MASK == MM_COPY_ON_WRITE_MASK
// then the pte is copy on write.
//
#define MM_COPY_ON_WRITE_MASK 5
extern ULONG MmProtectToValue[32];
extern ULONG MmProtectToPteMask[32];
extern ULONG MmMakeProtectNotWriteCopy[32];
extern ACCESS_MASK MmMakeSectionAccess[8];
extern ACCESS_MASK MmMakeFileAccess[8];
//
// Time constants
//
extern LARGE_INTEGER MmSevenMinutes;
extern LARGE_INTEGER MmWorkingSetProtectionTime;
extern LARGE_INTEGER MmOneSecond;
extern LARGE_INTEGER MmTwentySeconds;
extern LARGE_INTEGER MmShortTime;
extern LARGE_INTEGER MmHalfSecond;
extern LARGE_INTEGER Mm30Milliseconds;
extern LARGE_INTEGER MmCriticalSectionTimeout;
//
// A month worth
//
extern ULONG MmCritsectTimeoutSeconds;
//++
//
// ULONG
// MI_CONVERT_FROM_PTE_PROTECTION (
// IN ULONG PROTECTION_MASK
// )
//
// Routine Description:
//
// This routine converts a PTE protection into a Protect value.
//
// Arguments:
//
//
// Return Value:
//
// Returns the
//
//--
#define MI_CONVERT_FROM_PTE_PROTECTION(PROTECTION_MASK) \
(MmProtectToValue[PROTECTION_MASK])
#define MI_MASK_TO_PTE(PMASK) MmProtectToPteMask[PROTECTION_MASK]
#define MI_IS_PTE_PROTECTION_COPY_WRITE(PROTECTION_MASK) \
(((PROTECTION_MASK) & MM_COPY_ON_WRITE_MASK) == MM_COPY_ON_WRITE_MASK)
//++
//
// ULONG
// MI_ROUND_TO_64K (
// IN ULONG LENGTH
// )
//
// Routine Description:
//
//
// The ROUND_TO_64k macro takes a LENGTH in bytes and rounds it up to a multiple
// of 64K.
//
// Arguments:
//
// LENGTH - LENGTH in bytes to round up to 64k.
//
// Return Value:
//
// Returns the LENGTH rounded up to a multiple of 64k.
//
//--
#define MI_ROUND_TO_64K(LENGTH) (((ULONG)(LENGTH) + X64K - 1) & ~(X64K - 1))
//++
//
// ULONG
// MI_ROUND_TO_SIZE (
// IN ULONG LENGTH,
// IN ULONG ALIGNMENT
// )
//
// Routine Description:
//
//
// The ROUND_TO_SIZE macro takes a LENGTH in bytes and rounds it up to a
// multiple of the alignment.
//
// Arguments:
//
// LENGTH - LENGTH in bytes to round up to.
//
// ALIGNMENT - aligment to round to, must be a power of 2, e.g, 2**n.
//
// Return Value:
//
// Returns the LENGTH rounded up to a multiple of the aligment.
//
//--
#define MI_ROUND_TO_SIZE(LENGTH,ALIGNMENT) \
(((ULONG)(LENGTH) + (ALIGNMENT) - 1) & ~((ALIGNMENT) - 1))
//++
//
// PVOID
// MI_64K_ALIGN (
// IN PVOID VA
// )
//
// Routine Description:
//
//
// The MI_64K_ALIGN macro takes a virtual address and returns a 64k-aligned
// virtual address for that page.
//
// Arguments:
//
// VA - Virtual address.
//
// Return Value:
//
// Returns the 64k aligned virtual address.
//
//--
#define MI_64K_ALIGN(VA) ((PVOID)((ULONG)(VA) & ~(X64K - 1)))
//++
//
// PVOID
// MI_ALIGN_TO_SIZE (
// IN PVOID VA
// IN ULONG ALIGNMENT
// )
//
// Routine Description:
//
//
// The MI_ALIGN_TO_SIZE macro takes a virtual address and returns a
// virtual address for that page with the specified alignment.
//
// Arguments:
//
// VA - Virtual address.
//
// ALIGNMENT - aligment to round to, must be a power of 2, e.g, 2**n.
//
// Return Value:
//
// Returns the aligned virtual address.
//
//--
#define MI_ALIGN_TO_SIZE(VA,ALIGNMENT) ((PVOID)((ULONG)(VA) & ~(ALIGNMENT - 1)))
//++
//
// LONGLONG
// MI_STARTING_OFFSET (
// IN PSUBSECTION SUBSECT
// IN PMMPTE PTE
// )
//
// Routine Description:
//
// This macro takes a pointer to a PTE within a subsection and a pointer
// to that subsection and calculates the offset for that PTE within the
// file.
//
// Arguments:
//
// PTE - PTE within subsection.
//
// SUBSECT - Subsection
//
// Return Value:
//
// Offset for issuing I/O from.
//
//--
#define MI_STARTING_OFFSET(SUBSECT,PTE) \
(((LONGLONG)((ULONG)((PTE) - ((SUBSECT)->SubsectionBase))) << PAGE_SHIFT) + \
((LONGLONG)((SUBSECT)->StartingSector) << MMSECTOR_SHIFT));
// PVOID
// MiFindEmptyAddressRangeDown (
// IN ULONG SizeOfRange,
// IN PVOID HighestAddressToEndAt,
// IN ULONG Alignment
// )
//
//
// Routine Description:
//
// The function examines the virtual address descriptors to locate
// an unused range of the specified size and returns the starting
// address of the range. This routine looks from the top down.
//
// Arguments:
//
// SizeOfRange - Supplies the size in bytes of the range to locate.
//
// HighestAddressToEndAt - Supplies the virtual address to begin looking
// at.
//
// Alignment - Supplies the alignment for the address. Must be
// a power of 2 and greater than the page_size.
//
//Return Value:
//
// Returns the starting address of a suitable range.
//
#define MiFindEmptyAddressRangeDown(SizeOfRange,HighestAddressToEndAt,Alignment) \
(MiFindEmptyAddressRangeDownTree( \
(SizeOfRange), \
(HighestAddressToEndAt), \
(Alignment), \
(PMMADDRESS_NODE)(PsGetCurrentProcess()->VadRoot)))
// PMMVAD
// MiGetPreviousVad (
// IN PMMVAD Vad
// )
//
// Routine Description:
//
// This function locates the virtual address descriptor which contains
// the address range which logically precedes the specified virtual
// address descriptor.
//
// Arguments:
//
// Vad - Supplies a pointer to a virtual address descriptor.
//
// Return Value:
//
// Returns a pointer to the virtual address descriptor containing the
// next address range, NULL if none.
//
//
#define MiGetPreviousVad(VAD) ((PMMVAD)MiGetPreviousNode((PMMADDRESS_NODE)(VAD)))
// PMMVAD
// MiGetNextVad (
// IN PMMVAD Vad
// )
//
// Routine Description:
//
// This function locates the virtual address descriptor which contains
// the address range which logically follows the specified address range.
//
// Arguments:
//
// VAD - Supplies a pointer to a virtual address descriptor.
//
// Return Value:
//
// Returns a pointer to the virtual address descriptor containing the
// next address range, NULL if none.
//
#define MiGetNextVad(VAD) ((PMMVAD)MiGetNextNode((PMMADDRESS_NODE)(VAD)))
// PMMVAD
// MiGetFirstVad (
// Process
// )
//
// Routine Description:
//
// This function locates the virtual address descriptor which contains
// the address range which logically is first within the address space.
//
// Arguments:
//
// Process - Specifies the process in which to locate the VAD.
//
// Return Value:
//
// Returns a pointer to the virtual address descriptor containing the
// first address range, NULL if none.
#define MiGetFirstVad(Process) \
((PMMVAD)MiGetFirstNode((PMMADDRESS_NODE)(Process->VadRoot)))
// PMMVAD
// MiCheckForConflictingVad (
// IN PVOID StartingAddress,
// IN PVOID EndingAddress
// )
//
// Routine Description:
//
// The function determines if any addresses between a given starting and
// ending address is contained within a virtual address descriptor.
//
// Arguments:
//
// StartingAddress - Supplies the virtual address to locate a containing
// descriptor.
//
// EndingAddress - Supplies the virtual address to locate a containing
// descriptor.
//
// Return Value:
//
// Returns a pointer to the first conflicting virtual address descriptor
// if one is found, othersize a NULL value is returned.
//
#define MiCheckForConflictingVad(StartingAddress,EndingAddress) \
((PMMVAD)MiCheckForConflictingNode( \
(StartingAddress), \
(EndingAddress), \
(PMMADDRESS_NODE)(PsGetCurrentProcess()->VadRoot)))
// PMMCLONE_DESCRIPTOR
// MiGetNextClone (
// IN PMMCLONE_DESCRIPTOR Clone
// )
//
// Routine Description:
//
// This function locates the virtual address descriptor which contains
// the address range which logically follows the specified address range.
//
// Arguments:
//
// Clone - Supplies a pointer to a virtual address descriptor.
//
// Return Value:
//
// Returns a pointer to the virtual address descriptor containing the
// next address range, NULL if none.
//
//
#define MiGetNextClone(CLONE) \
((PMMCLONE_DESCRIPTOR)MiGetNextNode((PMMADDRESS_NODE)(CLONE)))
// PMMCLONE_DESCRIPTOR
// MiGetPreviousClone (
// IN PMMCLONE_DESCRIPTOR Clone
// )
//
// Routine Description:
//
// This function locates the virtual address descriptor which contains
// the address range which logically precedes the specified virtual
// address descriptor.
//
// Arguments:
//
// Clone - Supplies a pointer to a virtual address descriptor.
//
// Return Value:
//
// Returns a pointer to the virtual address descriptor containing the
// next address range, NULL if none.
#define MiGetPreviousClone(CLONE) \
((PMMCLONE_DESCRIPTOR)MiGetPreviousNode((PMMADDRESS_NODE)(CLONE)))
// PMMCLONE_DESCRIPTOR
// MiGetFirstClone (
// )
//
// Routine Description:
//
// This function locates the virtual address descriptor which contains
// the address range which logically is first within the address space.
//
// Arguments:
//
// None.
//
// Return Value:
//
// Returns a pointer to the virtual address descriptor containing the
// first address range, NULL if none.
//
#define MiGetFirstClone() \
((PMMCLONE_DESCRIPTOR)MiGetFirstNode((PMMADDRESS_NODE)(PsGetCurrentProcess()->CloneRoot)))
// VOID
// MiInsertClone (
// IN PMMCLONE_DESCRIPTOR Clone
// )
//
// Routine Description:
//
// This function inserts a virtual address descriptor into the tree and
// reorders the splay tree as appropriate.
//
// Arguments:
//
// Clone - Supplies a pointer to a virtual address descriptor
//
//
// Return Value:
//
// None.
//
#define MiInsertClone(CLONE) \
{ \
ASSERT ((CLONE)->NumberOfPtes != 0); \
MiInsertNode(((PMMADDRESS_NODE)(CLONE)),(PMMADDRESS_NODE *)&(PsGetCurrentProcess()->CloneRoot)); \
}
// VOID
// MiRemoveClone (
// IN PMMCLONE_DESCRIPTOR Clone
// )
//
// Routine Description:
//
// This function removes a virtual address descriptor from the tree and
// reorders the splay tree as appropriate.
//
// Arguments:
//
// Clone - Supplies a pointer to a virtual address descriptor.
//
// Return Value:
//
// None.
//
#define MiRemoveClone(CLONE) \
MiRemoveNode((PMMADDRESS_NODE)(CLONE),(PMMADDRESS_NODE *)&(PsGetCurrentProcess()->CloneRoot));
// PMMCLONE_DESCRIPTOR
// MiLocateCloneAddress (
// IN PVOID VirtualAddress
// )
//
// /*++
//
// Routine Description:
//
// The function locates the virtual address descriptor which describes
// a given address.
//
// Arguments:
//
// VirtualAddress - Supplies the virtual address to locate a descriptor
// for.
//
// Return Value:
//
// Returns a pointer to the virtual address descriptor which contains
// the supplied virtual address or NULL if none was located.
//
#define MiLocateCloneAddress(VA) \
(PsGetCurrentProcess()->CloneRoot ? \
((PMMCLONE_DESCRIPTOR)MiLocateAddressInTree((VA), \
(PMMADDRESS_NODE *)&(PsGetCurrentProcess()->CloneRoot))) : \
((PMMCLONE_DESCRIPTOR)NULL))
// PMMCLONE_DESCRIPTOR
// MiCheckForConflictingClone (
// IN PVOID StartingAddress,
// IN PVOID EndingAddress
// )
//
// Routine Description:
//
// The function determines if any addresses between a given starting and
// ending address is contained within a virtual address descriptor.
//
// Arguments:
//
// StartingAddress - Supplies the virtual address to locate a containing
// descriptor.
//
// EndingAddress - Supplies the virtual address to locate a containing
// descriptor.
//
// Return Value:
//
// Returns a pointer to the first conflicting virtual address descriptor
// if one is found, othersize a NULL value is returned.
//
#define MiCheckForConflictingClone(START,END) \
((PMMCLONE_DESCRIPTOR)(MiCheckForConflictingNode(START,END, \
(PMMADDRESS_NODE)(PsGetCurrentProcess()->CloneRoot))))
//
// MiGetVirtualPageNumber returns the virtual page number
// for a given address.
//
#define MiGetVirtualPageNumber(va) ((ULONG)(va) >> PAGE_SHIFT)
#define MI_VA_TO_PAGE(va) ((ULONG)(va) >> PAGE_SHIFT)
#define MI_BYTES_TO_64K_PAGES(Size) (((ULONG)Size + X64K - 1) >> 16)
#define MiGetByteOffset(va) ((ULONG)(va) & (PAGE_SIZE - 1))
//
// In order to avoid using the multiply unit to calculate pfn database
// elements the following macro is used. Note that it assumes
// that each PFN database element is 24 bytes in size.
//
#define MI_PFN_ELEMENT(index) ((PMMPFN)(((PUCHAR)(MmPfnDatabase)) + \
(((ULONG)(index)) << 3) + (((ULONG)(index)) << 4)))
//
// Make a write-copy PTE, only writable.
//
#define MI_MAKE_PROTECT_NOT_WRITE_COPY(PROTECT) \
(MmMakeProtectNotWriteCopy[PROTECT])
// #define LOCK_PFN KeWaitForSingleObject(&MmPfnMutex,
// FreePage,
// KernelMode,
// FALSE,
// (PLARGE_INTEGER)NULL)
//
// #define UNLOCK_PFN KeReleaseMutex(&MmPfnMutex,FALSE)
//
// #define UNLOCK_PFN_AND_THEN_WAIT KeReleaseMutex(&MmPfnMutex,TRUE)
//if ((MmDebug) && ((MmInfoCounters.PageFaultCount & 0xf) == 0)) KeDelayExecutionThread (KernelMode, FALSE, &MmShortTime);
#if DBG
#define LOCK_PFN(OLDIRQL) ASSERT (KeGetCurrentIrql() <= APC_LEVEL); \
ExAcquireSpinLock ( &MmPfnLock, &OLDIRQL );
#else
#define LOCK_PFN(OLDIRQL) ExAcquireSpinLock ( &MmPfnLock, &OLDIRQL );
#endif //DBG
#define LOCK_PFN_WITH_TRY(OLDIRQL) \
ASSERT (KeGetCurrentIrql() <= APC_LEVEL); \
do { \
} while (KeTryToAcquireSpinLock(&MmPfnLock, &OLDIRQL) == FALSE)
#define UNLOCK_PFN(OLDIRQL) ExReleaseSpinLock ( &MmPfnLock, OLDIRQL ); \
ASSERT (KeGetCurrentIrql() <= APC_LEVEL);
#define UNLOCK_PFN_AND_THEN_WAIT(OLDIRQL) \
{ \
KIRQL XXX; \
ASSERT (KeGetCurrentIrql() == 2); \
ASSERT (OLDIRQL <= APC_LEVEL); \
KeAcquireSpinLock (&KiDispatcherLock,&XXX); \
KiReleaseSpinLock (&MmPfnLock); \
(KeGetCurrentThread())->WaitIrql = OLDIRQL; \
(KeGetCurrentThread())->WaitNext = TRUE; \
}
#define LOCK_PFN2(OLDIRQL) ASSERT (KeGetCurrentIrql() <= DISPATCH_LEVEL); \
ExAcquireSpinLock ( &MmPfnLock, &OLDIRQL );
#define UNLOCK_PFN2(OLDIRQL) ExReleaseSpinLock (&MmPfnLock, OLDIRQL); \
ASSERT (KeGetCurrentIrql() <= DISPATCH_LEVEL);
#if DBG
#define MM_PFN_LOCK_ASSERT() \
if (MmDebug & 0x80000) { \
ASSERT (KeGetCurrentIrql() == 2); \
}
#else
#define MM_PFN_LOCK_ASSERT()
#endif //DBG
#define LOCK_EXPANSION(OLDIRQL) ASSERT (KeGetCurrentIrql() <= APC_LEVEL); \
ExAcquireSpinLock ( &MmExpansionLock, &OLDIRQL );
#define UNLOCK_EXPANSION(OLDIRQL) ExReleaseSpinLock ( &MmExpansionLock, OLDIRQL ); \
ASSERT (KeGetCurrentIrql() <= APC_LEVEL);
#define UNLOCK_EXPANSION_AND_THEN_WAIT(OLDIRQL) \
{ \
KIRQL XXX; \
ASSERT (KeGetCurrentIrql() == 2); \
ASSERT (OLDIRQL <= APC_LEVEL); \
KeAcquireSpinLock (&KiDispatcherLock,&XXX); \
KiReleaseSpinLock (&MmExpansionLock); \
(KeGetCurrentThread())->WaitIrql = OLDIRQL; \
(KeGetCurrentThread())->WaitNext = TRUE; \
}
#ifdef _ALPHA_
#define LOCK_EXPANSION_IF_ALPHA(OLDIRQL) \
ExAcquireSpinLock ( &MmExpansionLock, &OLDIRQL )
#else
#define LOCK_EXPANSION_IF_ALPHA(OLDIRQL)
#endif //ALPHA
#ifdef _ALPHA_
#define UNLOCK_EXPANSION_IF_ALPHA(OLDIRQL) \
ExReleaseSpinLock ( &MmExpansionLock, OLDIRQL )
#else
#define UNLOCK_EXPANSION_IF_ALPHA(OLDIRQL)
#endif //ALPHA
extern PETHREAD MmSystemLockOwner;
#if DBG
#define LOCK_SYSTEM_WS(OLDIRQL) ASSERT (KeGetCurrentIrql() <= APC_LEVEL); \
KeRaiseIrql(APC_LEVEL,&OLDIRQL); \
ExAcquireResourceExclusive(&MmSystemWsLock,TRUE); \
ASSERT (MmSystemLockOwner == NULL); \
MmSystemLockOwner = PsGetCurrentThread();
#else
#define LOCK_SYSTEM_WS(OLDIRQL) \
KeRaiseIrql(APC_LEVEL,&OLDIRQL); \
ExAcquireResourceExclusive(&MmSystemWsLock,TRUE); \
MmSystemLockOwner = PsGetCurrentThread();
#endif //DBG
#if DBG
#define UNLOCK_SYSTEM_WS(OLDIRQL) \
ASSERT (MmSystemLockOwner == PsGetCurrentThread()); \
MmSystemLockOwner = NULL; \
ExReleaseResource (&MmSystemWsLock); \
KeLowerIrql (OLDIRQL); \
ASSERT (KeGetCurrentIrql() <= APC_LEVEL);
#else
#define UNLOCK_SYSTEM_WS(OLDIRQL) \
MmSystemLockOwner = NULL; \
ExReleaseResource (&MmSystemWsLock); \
KeLowerIrql (OLDIRQL);
#endif //DBG
#if DBG
#define MM_SYSTEM_WS_LOCK_ASSERT() \
//ASSERT (PsGetCurrentThread() == MmSystemLockOwner);
#else
#define MM_SYSTEM_WS_LOCK_ASSERT()
#endif //DBG
#define LOCK_HYPERSPACE(OLDIRQL) \
ExAcquireSpinLock ( &(PsGetCurrentProcess())->HyperSpaceLock, OLDIRQL );
#define UNLOCK_HYPERSPACE(OLDIRQL) \
ExReleaseSpinLock ( &(PsGetCurrentProcess())->HyperSpaceLock, OLDIRQL );
#define LOCK_WS(PROCESS) \
ExAcquireFastMutex( &((PROCESS)->WorkingSetLock))
#define UNLOCK_WS(PROCESS) \
ExReleaseFastMutex(&((PROCESS)->WorkingSetLock))
#define LOCK_ADDRESS_SPACE(PROCESS) \
ExAcquireFastMutex( &((PROCESS)->AddressCreationLock))
#define LOCK_WS_AND_ADDRESS_SPACE(PROCESS) \
LOCK_ADDRESS_SPACE(PROCESS); \
LOCK_WS(PROCESS);
#define UNLOCK_ADDRESS_SPACE(PROCESS) \
ExReleaseFastMutex( &((PROCESS)->AddressCreationLock))
#define ZERO_LARGE(LargeInteger) \
(LargeInteger).LowPart = 0; \
(LargeInteger).HighPart = 0;
//++
//
// ULONG
// MI_CHECK_BIT (
// IN PULONG ARRAY
// IN ULONG BIT
// )
//
// Routine Description:
//
// The MI_CHECK_BIT macro checks to see if the specified bit is
// set within the specified array.
//
// Arguments:
//
// ARRAY - First element of the array to check.
//
// BIT - bit number (first bit is 0) to check.
//
// Return Value:
//
// Returns the value of the bit (0 or 1).
//
//--
#define MI_CHECK_BIT(ARRAY,BIT) \
(((ULONG)ARRAY[(BIT) / (sizeof(ULONG)*8)] >> ((BIT) & 0x1F)) & 1)
//++
//
// VOID
// MI_SET_BIT (
// IN PULONG ARRAY
// IN ULONG BIT
// )
//
// Routine Description:
//
// The MI_SET_BIT macro sets the specified bit within the
// specified array.
//
// Arguments:
//
// ARRAY - First element of the array to set.
//
// BIT - bit number.
//
// Return Value:
//
// None.
//
//--
#define MI_SET_BIT(ARRAY,BIT) \
(ULONG)ARRAY[(BIT) / (sizeof(ULONG)*8)] |= (1 << ((BIT) & 0x1F))
//++
//
// VOID
// MI_CLEAR_BIT (
// IN PULONG ARRAY
// IN ULONG BIT
// )
//
// Routine Description:
//
// The MI_CLEAR_BIT macro sets the specified bit within the
// specified array.
//
// Arguments:
//
// ARRAY - First element of the array to clear.
//
// BIT - bit number.
//
// Return Value:
//
// None.
//
//--
#define MI_CLEAR_BIT(ARRAY,BIT) \
(ULONG)ARRAY[(BIT) / (sizeof(ULONG)*8)] &= ~(1 << ((BIT) & 0x1F))
//
// PFN database element.
//
//
// Define pseudo fields for start and end of allocation.
//
#define StartOfAllocation ReadInProgress
#define EndOfAllocation WriteInProgress
//
// The PteFrame field size determines the largest physical page that
// can be supported on the system. On a 4k page sized machine, 20 bits
// limits it to 4GBs.
//
typedef struct _MMPFNENTRY {
ULONG Modified : 1;
ULONG ReadInProgress : 1;
ULONG WriteInProgress : 1;
ULONG PrototypePte: 1;
ULONG PageColor : 3;
ULONG ParityError : 1;
ULONG PageLocation : 3;
ULONG InPageError : 1;
ULONG Reserved : 4;
ULONG DontUse : 16; //overlays USHORT for reference count field.
} MMPFNENTRY;
typedef struct _MMPFN {
union {
ULONG Flink;
ULONG WsIndex;
PKEVENT Event;
NTSTATUS ReadStatus;
struct _MMPFN *NextStackPfn;
} u1;
PMMPTE PteAddress;
union {
ULONG Blink;
ULONG ShareCount;
ULONG SecondaryColorFlink;
} u2;
union {
MMPFNENTRY e1;
struct {
USHORT ShortFlags;
USHORT ReferenceCount;
} e2;
} u3;
MMPTE OriginalPte;
ULONG PteFrame;
} MMPFN;
typedef MMPFN *PMMPFN;
typedef enum _MMSHARE_TYPE {
Normal,
ShareCountOnly,
AndValid
} MMSHARE_TYPE;
typedef struct _MMWSLE_HASH {
ULONG Key;
ULONG Index;
} MMWSLE_HASH, *PMMWSLE_HASH;
//
// Working Set List Entry.
//
typedef struct _MMWSLENTRY {
ULONG Valid : 1;
ULONG LockedInWs : 1;
ULONG LockedInMemory : 1;
ULONG WasInTree : 1;
ULONG Protection : 5;
ULONG SameProtectAsProto : 1;
ULONG Direct : 1;
ULONG Filler : (32 - (MM_VIRTUAL_PAGE_SHIFT + 11));
ULONG VirtualPageNumber : MM_VIRTUAL_PAGE_SHIFT;
} MMWSLENTRY;
typedef struct _MMWSLE {
union {
PVOID VirtualAddress;
ULONG Long;
MMWSLENTRY e1;
} u1;
} MMWSLE;
typedef MMWSLE *PMMWSLE;
//
// Working Set List. Must be quadword sized.
//
typedef struct _MMWSL {
ULONG Quota;
ULONG FirstFree;
ULONG FirstDynamic;
ULONG LastEntry;
ULONG NextSlot;
PMMWSLE Wsle;
ULONG NumberOfCommittedPageTables;
ULONG LastInitializedWsle;
ULONG NonDirectCount;
PMMWSLE_HASH HashTable;
ULONG HashTableSize;
PKEVENT WaitingForImageMapping;
//MUST BE QUADWORD ALIGNEDED AT THIS POINT!
USHORT UsedPageTableEntries[MM_USER_PAGE_TABLE_PAGES]; //this must be at
// the end.
// not used in system cache
// working set list.
ULONG CommittedPageTables[MM_USER_PAGE_TABLE_PAGES/(sizeof(ULONG)*8)];
} MMWSL;
typedef MMWSL *PMMWSL;
//
// Memory Management Object structures.
//
typedef enum _SECTION_CHECK_TYPE {
CheckDataSection,
CheckImageSection,
CheckUserDataSection,
CheckBothSection
} SECTION_CHECK_TYPE;
typedef struct _SEGMENT {
PVOID SegmentBaseAddress;
ULONG TotalNumberOfPtes;
LARGE_INTEGER SizeOfSegment;
ULONG NonExtendedPtes;
ULONG ImageCommitment;
struct _CONTROL_AREA *ControlArea;
SECTION_IMAGE_INFORMATION ImageInformation;
PVOID SystemImageBase;
ULONG NumberOfCommittedPages;
MMPTE SegmentPteTemplate;
PVOID BasedAddress;
PMMPTE PrototypePte;
MMPTE ThePtes[MM_PROTO_PTE_ALIGNMENT / PAGE_SIZE];
} SEGMENT, *PSEGMENT;
typedef struct _EVENT_COUNTER {
ULONG RefCount;
KEVENT Event;
LIST_ENTRY ListEntry;
} EVENT_COUNTER, *PEVENT_COUNTER;
typedef struct _MMSECTION_FLAGS {
unsigned BeingDeleted : 1;
unsigned BeingCreated : 1;
unsigned BeingPurged : 1;
unsigned NoModifiedWriting : 1;
unsigned FailAllIo : 1;
unsigned Image : 1;
unsigned Based : 1;
unsigned File : 1;
unsigned Networked : 1;
unsigned NoCache : 1;
unsigned PhysicalMemory : 1;
unsigned CopyOnWrite : 1;
unsigned Reserve : 1; // not a spare bit!
unsigned Commit : 1;
unsigned FloppyMedia : 1;
unsigned WasPurged : 1;
unsigned UserReference : 1;
unsigned GlobalMemory : 1;
unsigned DeleteOnClose : 1;
unsigned FilePointerNull : 1;
unsigned DebugSymbolsLoaded : 1;
unsigned SetMappedFileIoComplete : 1;
unsigned CollidedFlush : 1;
unsigned NoChange : 1;
unsigned HadUserReference : 1;
unsigned ImageMappedInSystemSpace : 1;
unsigned filler : 6;
} MMSECTION_FLAGS;
typedef struct _CONTROL_AREA { // must be quadword sized.
PSEGMENT Segment;
LIST_ENTRY DereferenceList;
ULONG NumberOfSectionReferences;
ULONG NumberOfPfnReferences;
ULONG NumberOfMappedViews;
USHORT NumberOfSubsections;
USHORT FlushInProgressCount;
ULONG NumberOfUserReferences;
union {
ULONG LongFlags;
MMSECTION_FLAGS Flags;
} u;
PFILE_OBJECT FilePointer;
PEVENT_COUNTER WaitingForDeletion;
USHORT ModifiedWriteCount;
USHORT NumberOfSystemCacheViews;
} CONTROL_AREA;
typedef CONTROL_AREA *PCONTROL_AREA;
typedef struct _MMSUBSECTION_FLAGS {
unsigned ReadOnly : 1;
unsigned ReadWrite : 1;
unsigned CopyOnWrite : 1;
unsigned GlobalMemory: 1;
unsigned Protection : 5;
unsigned LargePages : 1;
unsigned filler1 : 6;
unsigned SectorEndOffset : 9;
unsigned filler2: 7;
} MMSUBSECTION_FLAGS;
typedef struct _SUBSECTION { // Must start on quadword boundary and be quad sized
PCONTROL_AREA ControlArea;
union {
ULONG LongFlags;
MMSUBSECTION_FLAGS SubsectionFlags;
} u;
ULONG StartingSector;
ULONG EndingSector;
PMMPTE SubsectionBase;
ULONG UnusedPtes;
ULONG PtesInSubsection;
struct _SUBSECTION *NextSubsection;
} SUBSECTION;
typedef SUBSECTION *PSUBSECTION;
typedef struct _MMDEREFERENCE_SEGMENT_HEADER {
KSPIN_LOCK Lock;
KSEMAPHORE Semaphore;
LIST_ENTRY ListHead;
} MMDEREFERENCE_SEGMENT_HEADER;
//
// This entry is used for calling the segment dereference thread
// to perform page file expansion. It has a similar structure
// to a control area to allow either a contol area or a page file
// expansion entry to be placed on the list. Note that for a control
// area the segment pointer is valid whereas for page file expansion
// it is null.
//
typedef struct _MMPAGE_FILE_EXPANSION {
PSEGMENT Segment;
LIST_ENTRY DereferenceList;
ULONG RequestedExpansionSize;
ULONG ActualExpansion;
KEVENT Event;
ULONG InProgress;
} MMPAGE_FILE_EXPANSION;
typedef MMPAGE_FILE_EXPANSION *PMMPAGE_FILE_EXPANSION;
typedef struct _MMWORKING_SET_EXPANSION_HEAD {
LIST_ENTRY ListHead;
} MMWORKING_SET_EXPANSION_HEAD;
#define SUBSECTION_READ_ONLY 1L
#define SUBSECTION_READ_WRITE 2L
#define SUBSECTION_COPY_ON_WRITE 4L
#define SUBSECTION_SHARE_ALLOW 8L
typedef struct _MMFLUSH_BLOCK {
LARGE_INTEGER ErrorOffset;
IO_STATUS_BLOCK IoStatus;
KEVENT IoEvent;
ULONG IoCount;
} MMFLUSH_BLOCK, *PMMFLUSH_BLOCK;
typedef struct _MMINPAGE_SUPPORT {
KEVENT Event;
IO_STATUS_BLOCK IoStatus;
LARGE_INTEGER ReadOffset;
ULONG WaitCount;
union {
PETHREAD Thread;
PMMFLUSH_BLOCK Flush;
} u;
PFILE_OBJECT FilePointer;
PMMPTE BasePte;
PMMPFN Pfn;
MDL Mdl;
ULONG Page[MM_MAXIMUM_READ_CLUSTER_SIZE + 1];
LIST_ENTRY ListEntry;
} MMINPAGE_SUPPORT;
typedef MMINPAGE_SUPPORT *PMMINPAGE_SUPPORT;
typedef struct _MMPAGE_READ {
LARGE_INTEGER ReadOffset;
PFILE_OBJECT FilePointer;
PMMPTE BasePte;
PMMPFN Pfn;
MDL Mdl;
ULONG Page[MM_MAXIMUM_READ_CLUSTER_SIZE + 1];
} MMPAGE_READ, *PMMPAGE_READ;
//
// Address Node.
//
typedef struct _MMADDRESS_NODE {
PVOID StartingVa;
PVOID EndingVa;
struct _MMADDRESS_NODE *Parent;
struct _MMADDRESS_NODE *LeftChild;
struct _MMADDRESS_NODE *RightChild;
} MMADDRESS_NODE;
typedef MMADDRESS_NODE *PMMADDRESS_NODE;
typedef struct _SECTION {
MMADDRESS_NODE Address;
PSEGMENT Segment;
LARGE_INTEGER SizeOfSection;
union {
ULONG LongFlags;
MMSECTION_FLAGS Flags;
} u;
ULONG InitialPageProtection;
} SECTION;
typedef SECTION *PSECTION;
//
// Banked memory descriptor. Pointed to by VAD which has
// the PhyiscalMemory flags set and the Banked pointer field as
// non-NULL.
//
typedef struct _MMBANKED_SECTION {
ULONG BasePhysicalPage;
PMMPTE BasedPte;
ULONG BankSize;
ULONG BankShift; //shift for PTEs to calculate bank number
PBANKED_SECTION_ROUTINE BankedRoutine;
PVOID Context;
PMMPTE CurrentMappedPte;
MMPTE BankTemplate[1];
} MMBANKED_SECTION, *PMMBANKED_SECTION;
//
// Virtual address descriptor
//
// ***** NOTE **********
// The first part of a virtual address descriptor is a MMADDRESS_NODE!!!
//
#define COMMIT_SIZE 19
#if ((COMMIT_SIZE + PAGE_SHIFT) < 31)
#error COMMIT_SIZE too small
#endif
#define MM_MAX_COMMIT ((1 << COMMIT_SIZE) - 1)
#define MM_VIEW_UNMAP 0
#define MM_VIEW_SHARE 1
typedef struct _MMVAD_FLAGS {
unsigned CommitCharge : COMMIT_SIZE; //limits system to 4k pages or bigger!
unsigned PhysicalMapping : 1;
unsigned ImageMap : 1;
unsigned Inherit : 1; //1 = ViewShare, 0 = ViewUnmap
unsigned NoChange : 1;
unsigned CopyOnWrite : 1;
unsigned Protection : 5;
unsigned LargePages : 1;
unsigned MemCommit: 1;
unsigned PrivateMemory : 1; //used to tell VAD from VAD_SHORT
} MMVAD_FLAGS;
typedef struct _MMVAD_FLAGS2 {
unsigned SecNoChange : 1; // set if SEC_NOCHANGE specified
unsigned OneSecured : 1; // set if u3 field is a range
unsigned MultipleSecured : 1; // set if u3 field is a list head
unsigned ReadOnly : 1; // protected as ReadOnly
unsigned StoredInVad : 1; // set if secure is stored in VAD
unsigned Reserved : 27;
} MMVAD_FLAGS2;
typedef struct _MMADDRESS_LIST {
PVOID StartVa;
PVOID EndVa;
} MMADDRESS_LIST, *PMMADDRESS_LIST;
typedef struct _MMSECURE_ENTRY {
union {
ULONG LongFlags2;
MMVAD_FLAGS2 VadFlags2;
} u2;
PVOID StartVa;
PVOID EndVa;
LIST_ENTRY List;
} MMSECURE_ENTRY, *PMMSECURE_ENTRY;
typedef struct _MMVAD {
PVOID StartingVa;
PVOID EndingVa;
struct _MMVAD *Parent;
struct _MMVAD *LeftChild;
struct _MMVAD *RightChild;
union {
ULONG LongFlags;
MMVAD_FLAGS VadFlags;
} u;
PCONTROL_AREA ControlArea;
PMMPTE FirstPrototypePte;
PMMPTE LastContiguousPte;
union {
ULONG LongFlags2;
MMVAD_FLAGS2 VadFlags2;
} u2;
union {
LIST_ENTRY List;
MMADDRESS_LIST Secured;
} u3;
PMMBANKED_SECTION Banked;
} MMVAD, *PMMVAD;
typedef struct _MMVAD_SHORT {
PVOID StartingVa;
PVOID EndingVa;
struct _MMVAD *Parent;
struct _MMVAD *LeftChild;
struct _MMVAD *RightChild;
union {
ULONG LongFlags;
MMVAD_FLAGS VadFlags;
} u;
} MMVAD_SHORT, *PMMVAD_SHORT;
//
// Stuff for support of POSIX Fork.
//
typedef struct _MMCLONE_BLOCK {
MMPTE ProtoPte;
LONG CloneRefCount;
} MMCLONE_BLOCK;
typedef MMCLONE_BLOCK *PMMCLONE_BLOCK;
typedef struct _MMCLONE_HEADER {
ULONG NumberOfPtes;
ULONG NumberOfProcessReferences;
PMMCLONE_BLOCK ClonePtes;
} MMCLONE_HEADER;
typedef MMCLONE_HEADER *PMMCLONE_HEADER;
typedef struct _MMCLONE_DESCRIPTOR {
PVOID StartingVa;
PVOID EndingVa;
struct _MMCLONE_DESCRIPTOR *Parent;
struct _MMCLONE_DESCRIPTOR *LeftChild;
struct _MMCLONE_DESCRIPTOR *RightChild;
PMMCLONE_HEADER CloneHeader;
ULONG NumberOfPtes;
ULONG NumberOfReferences;
ULONG PagedPoolQuotaCharge;
} MMCLONE_DESCRIPTOR;
typedef MMCLONE_DESCRIPTOR *PMMCLONE_DESCRIPTOR;
//
// The following macro will allocate and initialize a bitmap from the
// specified pool of the specified size
//
// VOID
// MiCreateBitMap (
// OUT PRTL_BITMAP *BitMapHeader,
// IN ULONG SizeOfBitMap,
// IN POOL_TYPE PoolType
// );
//
#define MiCreateBitMap(BMH,S,P) { \
ULONG _S; \
_S = sizeof(RTL_BITMAP) + ((((S) + 31) / 32) * 4); \
*(BMH) = (PRTL_BITMAP)ExAllocatePoolWithTag( (P), _S, ' mM'); \
RtlInitializeBitMap( *(BMH), (PULONG)((*(BMH))+1), S); \
}
#define MI_INITIALIZE_ZERO_MDL(MDL) { \
MDL->Next = (PMDL) NULL; \
MDL->MdlFlags = 0; \
MDL->StartVa = NULL; \
MDL->ByteOffset = 0; \
MDL->ByteCount = 0; \
}
//
// Page File structures.
//
typedef struct _MMMOD_WRITER_LISTHEAD {
LIST_ENTRY ListHead;
KEVENT Event;
} MMMOD_WRITER_LISTHEAD, *PMMMOD_WRITER_LISTHEAD;
typedef struct _MMMOD_WRITER_MDL_ENTRY {
LIST_ENTRY Links;
LARGE_INTEGER WriteOffset;
union {
IO_STATUS_BLOCK IoStatus;
LARGE_INTEGER LastByte;
} u;
PIRP Irp;
ULONG LastPageToWrite;
PMMMOD_WRITER_LISTHEAD PagingListHead;
PLIST_ENTRY CurrentList;
struct _MMPAGING_FILE *PagingFile;
PFILE_OBJECT File;
PCONTROL_AREA ControlArea;
PERESOURCE FileResource;
MDL Mdl;
ULONG Page[1];
} MMMOD_WRITER_MDL_ENTRY, *PMMMOD_WRITER_MDL_ENTRY;
#define MM_PAGING_FILE_MDLS 2
typedef struct _MMPAGING_FILE {
ULONG Size;
ULONG MaximumSize;
ULONG MinimumSize;
ULONG FreeSpace;
ULONG CurrentUsage;
ULONG PeakUsage;
ULONG Hint;
ULONG HighestPage;
PMMMOD_WRITER_MDL_ENTRY Entry[MM_PAGING_FILE_MDLS];
PRTL_BITMAP Bitmap;
PFILE_OBJECT File;
ULONG PageFileNumber;
UNICODE_STRING PageFileName;
BOOLEAN Extended;
BOOLEAN HintSetToZero;
} MMPAGING_FILE, *PMMPAGING_FILE;
typedef struct _MMINPAGE_SUPPORT_LIST {
LIST_ENTRY ListHead;
ULONG Count;
} MMINPAGE_SUPPORT_LIST, *PMMINPAGE_SUPPORT_LIST;
typedef struct _MMEVENT_COUNT_LIST {
LIST_ENTRY ListHead;
ULONG Count;
} MMEVENT_COUNT_LIST, *PMMEVENT_COUNT_LIST;
//
// System PTE structures.
//
#define MM_SYS_PTE_TABLES_MAX 5
typedef enum _MMSYSTEM_PTE_POOL_TYPE {
SystemPteSpace,
NonPagedPoolExpansion,
MaximumPtePoolTypes
} MMSYSTEM_PTE_POOL_TYPE;
typedef struct _MMFREE_POOL_ENTRY {
LIST_ENTRY List;
ULONG Size;
ULONG Signature;
struct _MMFREE_POOL_ENTRY *Owner;
} MMFREE_POOL_ENTRY, *PMMFREE_POOL_ENTRY;
//
// List for flushing TBs singularly.
//
typedef struct _MMPTE_FLUSH_LIST {
ULONG Count;
PMMPTE FlushPte[MM_MAXIMUM_FLUSH_COUNT];
PVOID FlushVa[MM_MAXIMUM_FLUSH_COUNT];
} MMPTE_FLUSH_LIST, *PMMPTE_FLUSH_LIST;
VOID
MiInitMachineDependent (
IN PLOADER_PARAMETER_BLOCK LoaderBlock
);
VOID
MiBuildPagedPool (
VOID
);
VOID
MiInitializeNonPagedPool (
PVOID StartOfNonPagedPool
);
VOID
MiInitializeSystemSpaceMap (
VOID
);
VOID
MiFindInitializationCode (
OUT PVOID *StartVa,
OUT PVOID *EndVa
);
VOID
MiFreeInitializationCode (
IN PVOID StartVa,
IN PVOID EndVa
);
ULONG
MiSectionInitialization (
VOID
);
VOID
FASTCALL
MiDecrementReferenceCount (
IN ULONG PageFrameIndex
);
VOID
FASTCALL
MiDecrementShareCount2 (
IN ULONG PageFrameIndex
);
#define MiDecrementShareCount(P) MiDecrementShareCount2(P)
#define MiDecrementShareCountOnly(P) MiDecrementShareCount2(P)
#define MiDecrementShareAndValidCount(P) MiDecrementShareCount2(P)
//
// Routines which operate on the Page Frame Database Lists
//
VOID
FASTCALL
MiInsertPageInList (
IN PMMPFNLIST ListHead,
IN ULONG PageFrameIndex
);
VOID
FASTCALL
MiInsertStandbyListAtFront (
IN ULONG PageFrameIndex
);
ULONG //PageFrameIndex
FASTCALL
MiRemovePageFromList (
IN PMMPFNLIST ListHead
);
VOID
FASTCALL
MiUnlinkPageFromList (
IN PMMPFN Pfn
);
VOID
MiUnlinkFreeOrZeroedPage (
IN ULONG Page
);
VOID
FASTCALL
MiInsertFrontModifiedNoWrite (
IN ULONG PageFrameIndex
);
ULONG
FASTCALL
MiEnsureAvailablePageOrWait (
IN PEPROCESS Process,
IN PVOID VirtualAddress
);
ULONG //PageFrameIndex
FASTCALL
MiRemoveZeroPage (
IN ULONG PageColor
);
#define MiRemoveZeroPageIfAny(COLOR) \
(MmFreePagesByColor[ZeroedPageList][COLOR].Flink != MM_EMPTY_LIST) ? \
MiRemoveZeroPage(COLOR) : 0
ULONG //PageFrameIndex
FASTCALL
MiRemoveAnyPage (
IN ULONG PageColor
);
//
// Routines which operate on the page frame database entry.
//
VOID
MiInitializePfn (
IN ULONG PageFrameIndex,
IN PMMPTE PointerPte,
IN ULONG ModifiedState
);
VOID
MiInitializePfnForOtherProcess (
IN ULONG PageFrameIndex,
IN PMMPTE PointerPte,
IN ULONG ContainingPageFrame
);
VOID
MiInitializeCopyOnWritePfn (
IN ULONG PageFrameIndex,
IN PMMPTE PointerPte,
IN ULONG WorkingSetIndex
);
VOID
MiInitializeTransitionPfn (
IN ULONG PageFrameIndex,
IN PMMPTE PointerPte,
IN ULONG WorkingSetIndex
);
VOID
MiFlushInPageSupportBlock (
);
VOID
MiFreeInPageSupportBlock (
IN PMMINPAGE_SUPPORT Support
);
PMMINPAGE_SUPPORT
MiGetInPageSupportBlock (
ULONG OkToReleasePfn
);
//
// Routines which require a physical page to be mapped into hyperspace
// within the current process.
//
VOID
FASTCALL
MiZeroPhysicalPage (
IN ULONG PageFrameIndex,
IN ULONG Color
);
VOID
FASTCALL
MiRestoreTransitionPte (
IN ULONG PageFrameIndex
);
PSUBSECTION
MiGetSubsectionAndProtoFromPte (
IN PMMPTE PointerPte,
IN PMMPTE *ProtoPte,
IN PEPROCESS Process
);
PVOID
MiMapPageInHyperSpace (
IN ULONG PageFrameIndex,
OUT PKIRQL OldIrql
);
#define MiUnmapPageInHyperSpace(OLDIRQL) UNLOCK_HYPERSPACE(OLDIRQL)
PVOID
MiMapImageHeaderInHyperSpace (
IN ULONG PageFrameIndex
);
VOID
MiUnmapImageHeaderInHyperSpace (
VOID
);
VOID
MiUpdateImageHeaderPage (
IN PMMPTE PointerPte,
IN ULONG PageFrameNumber,
IN PCONTROL_AREA ControlArea
);
ULONG
MiGetPageForHeader (
VOID
);
VOID
MiRemoveImageHeaderPage (
IN ULONG PageFrameNumber
);
PVOID
MiMapPageToZeroInHyperSpace (
IN ULONG PageFrameIndex
);
//
// Routines to obtain and release system PTEs.
//
PMMPTE
MiReserveSystemPtes (
IN ULONG NumberOfPtes,
IN MMSYSTEM_PTE_POOL_TYPE SystemPteType,
IN ULONG Alignment,
IN ULONG Offset,
IN ULONG BugCheckOnFailure
);
VOID
MiReleaseSystemPtes (
IN PMMPTE StartingPte,
IN ULONG NumberOfPtes,
IN MMSYSTEM_PTE_POOL_TYPE SystemPteType
);
VOID
MiInitializeSystemPtes (
IN PMMPTE StartingPte,
IN ULONG NumberOfPtes,
IN MMSYSTEM_PTE_POOL_TYPE SystemPteType
);
//
// Access Fault routines.
//
NTSTATUS
MiDispatchFault (
IN BOOLEAN StoreInstrution,
IN PVOID VirtualAdress,
IN PMMPTE PointerPte,
IN PMMPTE PointerProtoPte,
IN PEPROCESS Process
);
NTSTATUS
MiResolveDemandZeroFault (
IN PVOID VirtualAddress,
IN PMMPTE PointerPte,
IN PEPROCESS Process,
IN ULONG PrototypePte
);
NTSTATUS
MiResolveTransitionFault (
IN PVOID FaultingAddress,
IN PMMPTE PointerPte,
IN PEPROCESS Process,
IN ULONG PfnLockHeld
);
NTSTATUS
MiResolvePageFileFault (
IN PVOID FaultingAddress,
IN PMMPTE PointerPte,
IN PMMINPAGE_SUPPORT *ReadBlock,
IN PEPROCESS Process
);
NTSTATUS
MiResolveProtoPteFault (
IN BOOLEAN StoreInstruction,
IN PVOID VirtualAddress,
IN PMMPTE PointerPte,
IN PMMPTE PointerProtoPte,
IN PMMINPAGE_SUPPORT *ReadBlock,
IN PEPROCESS Process
);
NTSTATUS
MiResolveMappedFileFault (
IN PVOID FaultingAddress,
IN PMMPTE PointerPte,
IN PMMINPAGE_SUPPORT *ReadBlock,
IN PEPROCESS Process
);
VOID
MiAddValidPageToWorkingSet (
IN PVOID VirtualAddress,
IN PMMPTE PointerPte,
IN PMMPFN Pfn1,
IN ULONG WsleMask
);
NTSTATUS
MiWaitForInPageComplete (
IN PMMPFN Pfn,
IN PMMPTE PointerPte,
IN PVOID FaultingAddress,
IN PMMPTE PointerPteContents,
IN PMMINPAGE_SUPPORT InPageSupport,
IN PEPROCESS CurrentProcess
);
NTSTATUS
FASTCALL
MiCopyOnWrite (
IN PVOID FaultingAddress,
IN PMMPTE PointerPte
);
VOID
MiSetDirtyBit (
IN PVOID FaultingAddress,
IN PMMPTE PointerPte,
IN ULONG PfnHeld
);
VOID
MiSetModifyBit (
IN PMMPFN Pfn
);
PMMPTE
MiFindActualFaultingPte (
IN PVOID FaultingAddress
);
VOID
MiInitializeReadInProgressPfn (
IN PMDL Mdl,
IN PMMPTE BasePte,
IN PKEVENT Event,
IN ULONG WorkingSetIndex
);
NTSTATUS
MiAccessCheck (
IN PMMPTE PointerPte,
IN BOOLEAN WriteOperation,
IN KPROCESSOR_MODE PreviousMode,
IN ULONG Protection
);
NTSTATUS
FASTCALL
MiCheckForUserStackOverflow (
IN PVOID FaultingAddress
);
PMMPTE
MiCheckVirtualAddress (
IN PVOID VirtualAddress,
OUT PULONG ProtectCode
);
NTSTATUS
FASTCALL
MiCheckPdeForPagedPool (
IN PVOID VirtualAddress
);
VOID
MiInitializeMustSucceedPool (
VOID
);
//
// Routines which operate on an address tree.
//
PMMADDRESS_NODE
FASTCALL
MiGetNextNode (
IN PMMADDRESS_NODE Node
);
PMMADDRESS_NODE
FASTCALL
MiGetPreviousNode (
IN PMMADDRESS_NODE Node
);
PMMADDRESS_NODE
FASTCALL
MiGetFirstNode (
IN PMMADDRESS_NODE Root
);
PMMADDRESS_NODE
MiGetLastNode (
IN PMMADDRESS_NODE Root
);
VOID
FASTCALL
MiInsertNode (
IN PMMADDRESS_NODE Node,
IN OUT PMMADDRESS_NODE *Root
);
VOID
FASTCALL
MiRemoveNode (
IN PMMADDRESS_NODE Node,
IN OUT PMMADDRESS_NODE *Root
);
PMMADDRESS_NODE
FASTCALL
MiLocateAddressInTree (
IN PVOID VirtualAddress,
IN PMMADDRESS_NODE *Root
);
PMMADDRESS_NODE
MiCheckForConflictingNode (
IN PVOID StartingAddress,
IN PVOID EndingAddress,
IN PMMADDRESS_NODE Root
);
PVOID
MiFindEmptyAddressRangeInTree (
IN ULONG SizeOfRange,
IN ULONG Alignment,
IN PMMADDRESS_NODE Root,
OUT PMMADDRESS_NODE *PreviousVad
);
PVOID
MiFindEmptyAddressRangeDownTree (
IN ULONG SizeOfRange,
IN PVOID HighestAddressToEndAt,
IN ULONG Alignment,
IN PMMADDRESS_NODE Root
);
VOID
NodeTreeWalk (
PMMADDRESS_NODE Start
);
//
// Routine which operate on tree of virtual address descriptors.
//
VOID
MiInsertVad (
IN PMMVAD Vad
);
VOID
MiRemoveVad (
IN PMMVAD Vad
);
PMMVAD
FASTCALL
MiLocateAddress (
IN PVOID Vad
);
PVOID
MiFindEmptyAddressRange (
IN ULONG SizeOfRange,
IN ULONG Alignment,
IN ULONG QuickCheck
);
//
// routines which operate on the clone tree structure
//
NTSTATUS
MiCloneProcessAddressSpace (
IN PEPROCESS ProcessToClone,
IN PEPROCESS ProcessToInitialize,
IN ULONG PdePhysicalPage,
IN ULONG HyperPhysicalPage
);
ULONG
MiDecrementCloneBlockReference (
IN PMMCLONE_DESCRIPTOR CloneDescriptor,
IN PMMCLONE_BLOCK CloneBlock,
IN PEPROCESS CurrentProcess
);
VOID
MiWaitForForkToComplete (
IN PEPROCESS CurrentProcess
);
//
// Routines which operate of the working set list.
//
ULONG
MiLocateAndReserveWsle (
IN PMMSUPPORT WsInfo
);
VOID
MiReleaseWsle (
IN ULONG WorkingSetIndex,
IN PMMSUPPORT WsInfo
);
VOID
MiUpdateWsle (
IN PULONG DesiredIndex,
IN PVOID VirtualAddress,
IN PMMWSL WorkingSetList,
IN PMMPFN Pfn
);
VOID
MiInitializeWorkingSetList (
IN PEPROCESS CurrentProcess
);
VOID
MiGrowWsleHash (
IN PMMSUPPORT WsInfo,
IN ULONG PfnLockHeld
);
ULONG
MiTrimWorkingSet (
ULONG Reduction,
IN PMMSUPPORT WsInfo,
IN ULONG ForcedReduction
);
VOID
FASTCALL
MiInsertWsle (
IN ULONG Entry,
IN PMMWSL WorkingSetList
);
VOID
FASTCALL
MiRemoveWsle (
IN ULONG Entry,
IN PMMWSL WorkingSetList
);
VOID
MiFreeWorkingSetRange (
IN PVOID StartVa,
IN PVOID EndVa,
IN PMMSUPPORT WsInfo
);
ULONG
FASTCALL
MiLocateWsle (
IN PVOID VirtualAddress,
IN PMMWSL WorkingSetList,
IN ULONG WsPfnIndex
);
ULONG
MiFreeWsle (
IN ULONG WorkingSetIndex,
IN PMMSUPPORT WsInfo,
IN PMMPTE PointerPte
);
VOID
MiSwapWslEntries (
IN ULONG SwapEntry,
IN ULONG Entry,
IN PMMSUPPORT WsInfo
);
VOID
MiRemoveWsleFromFreeList (
IN ULONG Entry,
IN PMMWSLE Wsle,
IN PMMWSL WorkingSetList
);
ULONG
MiRemovePageFromWorkingSet (
IN PMMPTE PointerPte,
IN PMMPFN Pfn1,
IN PMMSUPPORT WsInfo
);
VOID
MiTakePageFromWorkingSet (
IN ULONG Entry,
IN PMMSUPPORT WsInfo,
IN PMMPTE PointerPte
);
NTSTATUS
MiEmptyWorkingSet (
IN PMMSUPPORT WsInfo
);
ULONG
MiDeleteSystemPagableVm (
IN PMMPTE PointerPte,
IN ULONG NumberOfPtes,
IN ULONG NewPteValue,
OUT PULONG ResidentPages
);
VOID
MiLockCode (
IN PMMPTE FirstPte,
IN PMMPTE LastPte,
IN ULONG LockType
);
PLDR_DATA_TABLE_ENTRY
MiLookupDataTableEntry (
IN PVOID AddressWithinSection,
IN ULONG ResourceHeld
);
//
// Routines which perform working set management.
//
VOID
MiObtainFreePages (
VOID
);
VOID
MiModifiedPageWriter (
IN PVOID StartContext
);
ULONG
MiExtendPagingFiles (
IN ULONG ExtendSize
);
VOID
MiContractPagingFiles (
VOID
);
VOID
MiAttemptPageFileReduction (
VOID
);
//
// Routines to delete address space.
//
VOID
MiDeleteVirtualAddresses (
IN PUCHAR StartingAddress,
IN PUCHAR EndingAddress,
IN ULONG AddressSpaceDeletion,
IN PMMVAD Vad
);
VOID
MiDeletePte (
IN PMMPTE PointerPte,
IN PVOID VirtualAddress,
IN ULONG AddressSpaceDeletion,
IN PEPROCESS CurrentProcess,
IN PMMPTE PrototypePte,
IN PMMPTE_FLUSH_LIST PteFlushList OPTIONAL
);
VOID
MiFlushPteList (
IN PMMPTE_FLUSH_LIST PteFlushList,
IN ULONG AllProcessors,
IN MMPTE FillPte
);
ULONG
FASTCALL
MiReleasePageFileSpace (
IN MMPTE PteContents
);
VOID
FASTCALL
MiUpdateModifiedWriterMdls (
IN ULONG PageFileNumber
);
//
// General support routines.
//
ULONG
MiDoesPdeExistAndMakeValid (
IN PMMPTE PointerPde,
IN PEPROCESS TargetProcess,
IN ULONG PfnMutexHeld
);
ULONG
MiMakePdeExistAndMakeValid (
IN PMMPTE PointerPde,
IN PEPROCESS TargetProcess,
IN ULONG PfnMutexHeld
);
ULONG
FASTCALL
MiMakeSystemAddressValid (
IN PVOID VirtualAddress,
IN PEPROCESS CurrentProcess
);
ULONG
FASTCALL
MiMakeSystemAddressValidPfnWs (
IN PVOID VirtualAddress,
IN PEPROCESS CurrentProcess OPTIONAL
);
ULONG
FASTCALL
MiMakeSystemAddressValidPfn (
IN PVOID VirtualAddress
);
ULONG
FASTCALL
MiLockPagedAddress (
IN PVOID VirtualAddress,
IN ULONG PfnLockHeld
);
VOID
FASTCALL
MiUnlockPagedAddress (
IN PVOID VirtualAddress,
IN ULONG PfnLockHeld
);
ULONG
FASTCALL
MiIsPteDecommittedPage (
IN PMMPTE PointerPte
);
ULONG
FASTCALL
MiIsProtectionCompatible (
IN ULONG OldProtect,
IN ULONG NewProtect
);
ULONG
FASTCALL
MiMakeProtectionMask (
IN ULONG Protect
);
ULONG
MiIsEntireRangeCommitted (
IN PVOID StartingAddress,
IN PVOID EndingAddress,
IN PMMVAD Vad,
IN PEPROCESS Process
);
ULONG
MiIsEntireRangeDecommitted (
IN PVOID StartingAddress,
IN PVOID EndingAddress,
IN PMMVAD Vad,
IN PEPROCESS Process
);
PMMPTE
FASTCALL
MiGetProtoPteAddressExtended (
IN PMMVAD Vad,
IN PVOID VirtualAddress
);
PSUBSECTION
FASTCALL
MiLocateSubsection (
IN PMMVAD Vad,
IN PVOID VirtualAddress
);
ULONG
MiInitializeSystemCache (
IN ULONG SizeOfSystemCacheInPages,
IN ULONG MinimumWorkingSet,
IN ULONG MaximumWorkingSet
);
VOID
MiAdjustWorkingSetManagerParameters(
BOOLEAN WorkStation
);
//
// Section support
//
VOID
FASTCALL
MiInsertBasedSection (
IN PSECTION Section
);
VOID
FASTCALL
MiRemoveBasedSection (
IN PSECTION Section
);
VOID
MiRemoveMappedView (
IN PEPROCESS CurrentProcess,
IN PMMVAD Vad
);
PVOID
MiFindEmptySectionBaseDown (
IN ULONG SizeOfRange,
IN PVOID HighestAddressToEndAt
);
VOID
MiSegmentDelete (
PSEGMENT Segment
);
VOID
MiSectionDelete (
PVOID Object
);
VOID
MiDereferenceSegmentThread (
IN PVOID StartContext
);
NTSTATUS
MiCreateImageFileMap (
IN PFILE_OBJECT File,
OUT PSEGMENT *Segment
);
NTSTATUS
MiCreateDataFileMap (
IN PFILE_OBJECT File,
OUT PSEGMENT *Segment,
IN PLARGE_INTEGER MaximumSize,
IN ULONG SectionPageProtection,
IN ULONG AllocationAttributes,
IN ULONG IgnoreFileSizing
);
NTSTATUS
MiCreatePagingFileMap (
OUT PSEGMENT *Segment,
IN PLARGE_INTEGER MaximumSize,
IN ULONG ProtectionMask,
IN ULONG AllocationAttributes
);
VOID
MiPurgeSubsectionInternal (
IN PSUBSECTION Subsection,
IN ULONG PteOffset
);
VOID
MiPurgeImageSection (
IN PCONTROL_AREA ControlArea,
IN PEPROCESS Process
);
VOID
MiCleanSection (
IN PCONTROL_AREA ControlArea
);
VOID
MiCheckControlArea (
IN PCONTROL_AREA ControlArea,
IN PEPROCESS CurrentProcess,
IN KIRQL PreviousIrql
);
VOID
MiCheckForControlAreaDeletion (
IN PCONTROL_AREA ControlArea
);
ULONG
MiCheckControlAreaStatus (
IN SECTION_CHECK_TYPE SectionCheckType,
IN PSECTION_OBJECT_POINTERS SectionObjectPointers,
IN ULONG DelayClose,
OUT PCONTROL_AREA *ControlArea,
OUT PKIRQL OldIrql
);
PEVENT_COUNTER
MiGetEventCounter (
);
VOID
MiFlushEventCounter (
);
VOID
MiFreeEventCounter (
IN PEVENT_COUNTER Support,
IN ULONG Flush
);
ULONG
MmCanFileBeTruncatedInternal (
IN PSECTION_OBJECT_POINTERS SectionPointer,
IN PLARGE_INTEGER NewFileSize OPTIONAL,
OUT PKIRQL PreviousIrql
);
//
// protection stuff...
//
NTSTATUS
MiProtectVirtualMemory (
IN PEPROCESS Process,
IN PVOID *CapturedBase,
IN PULONG CapturedRegionSize,
IN ULONG Protect,
IN PULONG LastProtect
);
ULONG
MiGetPageProtection (
IN PMMPTE PointerPte,
IN PEPROCESS Process
);
ULONG
MiSetProtectionOnSection (
IN PEPROCESS Process,
IN PMMVAD Vad,
IN PVOID StartingAddress,
IN PVOID EndingAddress,
IN ULONG NewProtect,
OUT PULONG CapturedOldProtect,
IN ULONG DontCharge
);
NTSTATUS
MiCheckSecuredVad (
IN PMMVAD Vad,
IN PVOID Base,
IN ULONG Size,
IN ULONG ProtectionMask
);
ULONG
MiChangeNoAccessForkPte (
IN PMMPTE PointerPte,
IN ULONG ProtectionMask
);
//
// Routines for charging quota and committment.
//
ULONG
FASTCALL
MiChargePageFileQuota (
IN ULONG QuotaCharge,
IN PEPROCESS CurrentProcess
);
VOID
MiReturnPageFileQuota (
IN ULONG QuotaCharge,
IN PEPROCESS CurrentProcess
);
VOID
FASTCALL
MiChargeCommitment (
IN ULONG QuotaCharge,
IN PEPROCESS Process OPTIONAL
);
VOID
FASTCALL
MiChargeCommitmentCantExpand (
IN ULONG QuotaCharge,
IN ULONG MustSucceed
);
VOID
FASTCALL
MiReturnCommitment (
IN ULONG QuotaCharge
);
ULONG
MiCalculatePageCommitment (
IN PVOID StartingAddress,
IN PVOID EndingAddress,
IN PMMVAD Vad,
IN PEPROCESS Process
);
VOID
MiReturnPageTablePageCommitment (
IN PVOID StartingAddress,
IN PVOID EndingAddress,
IN PEPROCESS CurrentProcess,
IN PMMVAD PreviousVad,
IN PMMVAD NextVad
);
VOID
MiEmptyAllWorkingSets (
VOID
);
VOID
MiFlushAllPages (
VOID
);
//
// hack stuff for testing.
//
VOID
MiDumpValidAddresses (
VOID
);
VOID
MiDumpPfn ( VOID );
VOID
MiDumpWsl ( VOID );
VOID
MiFormatPte (
IN PMMPTE PointerPte
);
VOID
MiCheckPfn ( VOID );
VOID
MiCheckPte ( VOID );
VOID
MiFormatPfn (
IN PMMPFN PointerPfn
);
extern MMPTE ZeroPte;
extern MMPTE ZeroKernelPte;
extern MMPTE ValidKernelPte;
extern MMPTE ValidKernelPde;
extern MMPTE ValidUserPte;
extern MMPTE ValidPtePte;
extern MMPTE ValidPdePde;
extern MMPTE DemandZeroPde;
extern MMPTE DemandZeroPte;
extern MMPTE KernelPrototypePte;
extern MMPTE TransitionPde;
extern MMPTE PrototypePte;
extern MMPTE NoAccessPte;
extern ULONG MmSubsectionBase;
extern ULONG MmSubsectionTopPage;
// extern MMPTE UserNoCommitPte;
//
// Virtual alignment for PTEs (machine specific) minimum value is
// 4k maximum value is 64k. The maximum value can be raised by
// changing the MM_PROTO_PTE_ALIGMENT constant and adding more
// reserved mapping PTEs in hyperspace.
//
//
// Total number of physical pages on the system.
//
extern ULONG MmNumberOfPhysicalPages;
//
// Lowest physical page number on the system.
//
extern ULONG MmLowestPhysicalPage;
//
// Higest physical page number on the system.
//
extern ULONG MmHighestPhysicalPage;
//
// Total number of available pages on the system. This
// is the sum of the pages on the zeroed, free and standby lists.
//
extern ULONG MmAvailablePages;
//
// Total number of free pages to base working set trimming on.
//
extern ULONG MmMoreThanEnoughFreePages;
//
// System wide count of the number of pages faults.
//
//extern ULONG MmPageFaultCount;
//
// Total number phyisical pages which would be usable if every process
// was at it's minimum working set size. This value is initialized
// at system initialization to MmAvailablePages - MM_FLUID_PHYSICAL_PAGES.
// Everytime a thread is created, the kernel stack is subtracted from
// this and every time a process is created, the minimim 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.
//
extern LONG MmResidentAvailablePages;
//
// The total number of pages which would be removed from working sets
// if every working set was at its minimum.
//
extern ULONG MmPagesAboveWsMinimum;
//
// The total number of pages which would be removed from working sets
// if every working set above its maximum was at its maximum.
//
extern ULONG MmPagesAboveWsMaximum;
//
// If memory is becoming short and MmPagesAboveWsMinimum is
// greater than MmPagesAboveWsThreshold, trim working sets.
//
extern ULONG MmPagesAboveWsThreshold;
//
// The number of pages to add to a working set if there are ample
// available pages and the working set is below its maximum.
//
extern ULONG MmWorkingSetSizeIncrement;
//
// 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.
extern ULONG MmWorkingSetSizeExpansion;
//
// The number of pages required to be freed by working set reduction
// before working set reduction is attempted.
//
extern ULONG MmWsAdjustThreshold;
//
// The number of pages available to allow the working set to be
// expanded above its maximum.
//
extern ULONG MmWsExpandThreshold;
//
// The total number of pages to reduce by working set trimming.
//
extern ULONG MmWsTrimReductionGoal;
extern PMMPFN MmPfnDatabase;
extern MMPFNLIST MmZeroedPageListHead;
extern MMPFNLIST MmFreePageListHead;
extern MMPFNLIST MmStandbyPageListHead;
extern MMPFNLIST MmStandbyPageListByColor[MM_MAXIMUM_NUMBER_OF_COLORS];
extern MMPFNLIST MmModifiedPageListHead;
extern MMPFNLIST MmModifiedNoWritePageListHead;
extern MMPFNLIST MmBadPageListHead;
extern PMMPFNLIST MmPageLocationList[NUMBER_OF_PAGE_LISTS];
extern MMPFNLIST MmModifiedPageListByColor[MM_MAXIMUM_NUMBER_OF_COLORS];
extern ULONG MmModNoWriteInsert;
//
// Event for available pages, set means pages are available.
//
extern KEVENT MmAvailablePagesEvent;
extern KEVENT MmAvailablePagesEventHigh;
//
// Event for the zeroing page thread.
//
extern 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.
//
extern BOOLEAN MmZeroingPageThreadActive;
//
// Minimum number of free pages before zeroing page thread starts.
//
extern ULONG MmMinimumFreePagesToZero;
//
// Global event to synchronize mapped writing with cleaning segments.
//
extern KEVENT MmMappedFileIoComplete;
//
// Hyper space items.
//
extern PMMPTE MmFirstReservedMappingPte;
extern PMMPTE MmLastReservedMappingPte;
//
// 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.
//
extern PVOID MmNonPagedSystemStart;
extern PCHAR MmSystemSpaceViewStart;
//
// Pool sizes.
//
extern ULONG MmSizeOfNonPagedPoolInBytes;
extern ULONG MmMinimumNonPagedPoolSize;
extern ULONG MmDefaultMaximumNonPagedPool;
extern ULONG MmMinAdditionNonPagedPoolPerMb;
extern ULONG MmMaxAdditionNonPagedPoolPerMb;
extern ULONG MmSizeOfPagedPoolInBytes;
extern ULONG MmMaximumNonPagedPoolInBytes;
extern ULONG MmSizeOfNonPagedMustSucceed;
extern PVOID MmNonPagedPoolExpansionStart;
extern ULONG MmExpandedPoolBitPosition;
extern ULONG MmNumberOfFreeNonPagedPool;
extern ULONG MmMustSucceedPoolBitPosition;
extern ULONG MmNumberOfSystemPtes;
extern ULONG MmTotalFreeSystemPtes[MaximumPtePoolTypes];
extern ULONG MmLockLimitInBytes;
extern ULONG MmLockPagesLimit;
extern PMMPTE MmFirstPteForPagedPool;
extern PMMPTE MmLastPteForPagedPool;
extern PMMPTE MmSystemPagePtes;
extern ULONG MmSystemPageDirectory;
extern PMMPTE MmPagedPoolBasePde;
extern LIST_ENTRY MmNonPagedPoolFreeListHead;
//
// Counter for flushes of the entire TB.
//
extern MMPTE MmFlushCounter;
//
// Pool start and end.
//
extern PVOID MmNonPagedPoolStart;
extern PVOID MmNonPagedPoolEnd;
extern PVOID MmPagedPoolStart;
extern PVOID MmPagedPoolEnd;
extern PVOID MmNonPagedMustSucceed;
//
// Pool bit maps and other related structures.
//
extern PRTL_BITMAP MmPagedPoolAllocationMap;
extern PRTL_BITMAP MmEndOfPagedPoolBitmap;
extern PVOID MmPageAlignedPoolBase[2];
//
// MmFirstFreeSystemPte contains the offset from the
// Nonpaged system base to the first free system PTE.
// Note, that an offset of zero indicates an empty list.
//
extern MMPTE MmFirstFreeSystemPte[MaximumPtePoolTypes];
extern PMMPTE MmNextPteForPagedPoolExpansion;
//
// System cache sizes.
//
//extern MMSUPPORT MmSystemCacheWs;
extern PMMWSL MmSystemCacheWorkingSetList;
extern PMMWSLE MmSystemCacheWsle;
extern PVOID MmSystemCacheStart;
extern PVOID MmSystemCacheEnd;
extern PRTL_BITMAP MmSystemCacheAllocationMap;
extern PRTL_BITMAP MmSystemCacheEndingMap;
extern ULONG MmSystemCacheBitMapHint;
extern ULONG MmSizeOfSystemCacheInPages;
extern ULONG MmSystemCacheWsMinimum;
extern ULONG MmSystemCacheWsMaximum;
//
// Virtual alignment for PTEs (machine specific) minimum value is
// 0 (no alignment) maximum value is 64k. The maximum value can be raised by
// changing the MM_PROTO_PTE_ALIGMENT constant and adding more
// reserved mapping PTEs in hyperspace.
//
extern ULONG MmAliasAlignment;
//
// Mask to AND with virtual address to get an offset to go
// with the alignment. This value is page aligned.
//
extern ULONG MmAliasAlignmentOffset;
//
// Mask to and with PTEs to determine if the alias mapping is compatable.
// This value is usually (MmAliasAlignment - 1)
//
extern ULONG MmAliasAlignmentMask;
//
// Cells to track unused thread kernel stacks to avoid TB flushes
// every time a thread terminates.
//
extern ULONG MmNumberDeadKernelStacks;
extern ULONG MmMaximumDeadKernelStacks;
extern PMMPFN MmFirstDeadKernelStack;
//
// 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.
//
extern PMMPTE MmSystemPteBase;
extern PMMWSL MmWorkingSetList;
extern PMMWSLE MmWsle;
//
// Root of system space virtual address descriptors. These define
// the pageable portion of the system.
//
extern PMMVAD MmVirtualAddressDescriptorRoot;
extern PMMADDRESS_NODE MmSectionBasedRoot;
extern PVOID MmHighSectionBase;
//
// Section commit mutex.
//
extern FAST_MUTEX MmSectionCommitMutex;
//
// Section base address mutex.
//
extern FAST_MUTEX MmSectionBasedMutex;
//
// Resource for section extension.
//
extern ERESOURCE MmSectionExtendResource;
extern ERESOURCE MmSectionExtendSetResource;
//
// Event to sychronize threads within process mapping images via hyperspace.
//
extern KEVENT MmImageMappingPteEvent;
//
// Inpage cluster sizes for executable pages (set based on memory size).
//
extern ULONG MmDataClusterSize;
extern ULONG MmCodeClusterSize;
//
// Pagefile creation mutex.
//
extern FAST_MUTEX MmPageFileCreationLock;
//
// Event to set when first paging file is created.
//
extern PKEVENT MmPagingFileCreated;
//
// Spinlock which guards PFN database. This spinlock is used by
// memory mangement for accessing the PFN database. The I/O
// system makes use of it for unlocking pages during I/O complete.
//
extern KSPIN_LOCK MmPfnLock;
//
// Spinlock which guards the working set list for the system shared
// address space (paged pool, system cache, pagable drivers).
//
extern ERESOURCE MmSystemWsLock;
//
// Spin lock for allocating non-paged PTEs from system space.
//
extern KSPIN_LOCK MmSystemSpaceLock;
//
// Spin lock for operating on page file commit charges.
//
extern KSPIN_LOCK MmChargeCommitmentLock;
//
// Spin lock for allowing working set expansion.
//
extern KSPIN_LOCK MmExpansionLock;
//
// To prevent optimizations.
//
extern MMPTE GlobalPte;
//
// Page color for system working set.
//
extern ULONG MmSystemPageColor;
extern ULONG MmSecondaryColors;
extern ULONG MmProcessColorSeed;
//
// 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
// data base server.
//
extern ULONG MmDisablePagingExecutive;
//
// For debugging.
#if DBG
extern ULONG MmDebug;
#endif
//
// List heads
//
extern MMDEREFERENCE_SEGMENT_HEADER MmDereferenceSegmentHeader;
extern LIST_ENTRY MmUnusedSegmentList;
extern ULONG MmUnusedSegmentCount;
extern KEVENT MmUnusedSegmentCleanup;
extern ULONG MmUnusedSegmentCountMaximum;
extern ULONG MmUnusedSegmentCountGoal;
extern MMWORKING_SET_EXPANSION_HEAD MmWorkingSetExpansionHead;
extern MMPAGE_FILE_EXPANSION MmAttemptForCantExtend;
//
// Paging files
//
extern MMMOD_WRITER_LISTHEAD MmPagingFileHeader;
extern MMMOD_WRITER_LISTHEAD MmMappedFileHeader;
extern PMMPAGING_FILE MmPagingFile[MAX_PAGE_FILES];
#define MM_MAPPED_FILE_MDLS 4
extern PMMMOD_WRITER_MDL_ENTRY MmMappedFileMdl[MM_MAPPED_FILE_MDLS];
extern LIST_ENTRY MmFreePagingSpaceLow;
extern ULONG MmNumberOfActiveMdlEntries;
extern ULONG MmNumberOfPagingFiles;
extern KEVENT MmModifiedPageWriterEvent;
extern KEVENT MmCollidedFlushEvent;
extern KEVENT MmCollidedLockEvent;
//
// Total number of committed pages.
//
extern ULONG MmTotalCommittedPages;
extern ULONG MmTotalCommitLimit;
extern ULONG MmOverCommit;
//
// Modified page writer.
//
extern ULONG MmMinimumFreePages;
extern ULONG MmFreeGoal;
extern ULONG MmModifiedPageMaximum;
extern ULONG MmModifiedPageMinimum;
extern ULONG MmModifiedWriteClusterSize;
extern ULONG MmMinimumFreeDiskSpace;
extern ULONG MmPageFileExtension;
extern ULONG MmMinimumPageFileReduction;
//
// System process working set sizes.
//
extern ULONG MmSystemProcessWorkingSetMin;
extern ULONG MmSystemProcessWorkingSetMax;
extern ULONG MmMinimumWorkingSetSize;
//
// Support for debugger's mapping phyiscal memory.
//
extern PMMPTE MmDebugPte;
extern PMMPTE MmCrashDumpPte;
extern ULONG MiOverCommitCallCount;
#if DBG
extern PRTL_EVENT_ID_INFO MiAllocVmEventId;
extern PRTL_EVENT_ID_INFO MiFreeVmEventId;
#endif // DBG
#endif // MI