3302 lines
68 KiB
C
3302 lines
68 KiB
C
/*++
|
||
|
||
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
|