mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3301 lines
68 KiB
3301 lines
68 KiB
/*++
|
|
|
|
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
|