Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

mi.h File Reference

#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"
#include "safeboot.h"
#include "triage.h"

Go to the source code of this file.

Classes

struct  _MMPFNENTRY
struct  _MMPFN
struct  _MMWSLE_HASH
struct  _MMWSLENTRY
struct  _MMWSLE
struct  _MMWSL
struct  _MI_NEXT_ESTIMATION_SLOT_CONST
struct  _MMEXTEND_INFO
struct  _SEGMENT
struct  _EVENT_COUNTER
struct  _MMSECTION_FLAGS
struct  _CONTROL_AREA
struct  _LARGE_CONTROL_AREA
struct  _MMSUBSECTION_FLAGS
struct  _SUBSECTION
struct  _MMDEREFERENCE_SEGMENT_HEADER
struct  _MMPAGE_FILE_EXPANSION
struct  _MMWORKING_SET_EXPANSION_HEAD
struct  _MMFLUSH_BLOCK
struct  _MMINPAGE_SUPPORT
struct  _MMPAGE_READ
struct  _MMADDRESS_NODE
struct  _SECTION
struct  _MMBANKED_SECTION
struct  _MMVAD_FLAGS
struct  _MMVAD_FLAGS2
struct  _MMADDRESS_LIST
struct  _MMSECURE_ENTRY
struct  _MMVAD
struct  _MMVAD_SHORT
struct  _MI_PHYSICAL_VIEW
struct  _MMCLONE_BLOCK
struct  _MMCLONE_HEADER
struct  _MMCLONE_DESCRIPTOR
struct  _MMMOD_WRITER_LISTHEAD
struct  _MMMOD_WRITER_MDL_ENTRY
struct  _MMPAGING_FILE
struct  _MMINPAGE_SUPPORT_LIST
struct  _MMEVENT_COUNT_LIST
struct  _MMFREE_POOL_ENTRY
struct  _MMLOCK_CONFLICT
struct  _MMVIEW
struct  _MMSESSION
struct  _MMPTE_FLUSH_LIST
struct  _LOCK_TRACKER
struct  _LOCK_HEADER
struct  _UNLOADED_DRIVERS
struct  _VI_POOL_ENTRY_INUSE
struct  _VI_POOL_ENTRY
struct  _MI_VERIFIER_DRIVER_ENTRY
struct  _MI_VERIFIER_POOL_HEADER
struct  _MM_DRIVER_VERIFIER_DATA
struct  _MI_FREED_SPECIAL_POOL
struct  _MM_PAGED_POOL_INFO
struct  _MM_SESSION_SPACE_FLAGS
struct  _MM_SESSION_SPACE
struct  _IMAGE_ENTRY_IN_SESSION

Defines

#define ASSERT32(exp)   ASSERT(exp)
#define ASSERT64(exp)
#define MI_SPECIAL_POOL_PAGABLE   0x8000
#define MI_SPECIAL_POOL_VERIFIER   0x4000
#define MI_SPECIAL_POOL_PTE_PAGABLE   0x0002
#define MI_SPECIAL_POOL_PTE_NONPAGABLE   0x0004
#define _2gb   0x80000000
#define _4gb   0x100000000
#define MM_FLUSH_COUNTER_MASK   (0xFFFFF)
#define MM_FREE_WSLE_SHIFT   4
#define WSLE_NULL_INDEX   ((ULONG)0xFFFFFFF)
#define MM_FREE_POOL_SIGNATURE   (0x50554F4C)
#define MM_MINIMUM_PAGED_POOL_NTAS   ((SIZE_T)(48*1024*1024))
#define MM_ALLOCATION_FILLS_VAD   ((PMMPTE)(ULONG_PTR)~3)
#define MM_WORKING_SET_LIST_SEARCH   17
#define MM_FLUID_WORKING_SET   8
#define MM_FLUID_PHYSICAL_PAGES   32
#define MM_USABLE_PAGES_FREE   32
#define X64K   (ULONG)65536
#define MM_HIGHEST_VAD_ADDRESS   ((PVOID)((ULONG_PTR)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)
#define MM_PAGES_REQUIRED_FOR_MAPPED_IO   7
#define MM4K_SHIFT   12
#define MM4K_MASK   0xfff
#define MMSECTOR_SHIFT   9
#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)
#define MM_MAXIMUM_FLUSH_COUNT   (FLUSH_MULTIPLE_MAXIMUM-1)
#define MM_ZERO_ACCESS   0
#define MM_READONLY   1
#define MM_EXECUTE   2
#define MM_EXECUTE_READ   3
#define MM_READWRITE   4
#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
#define MM_NOACCESS   0x18
#define MM_UNKNOWN_PROTECTION   0x100
#define MM_LARGE_PAGES   0x111
#define PROTECT_KSTACKS   1
#define MM_KSTACK_OUTSWAPPED   0x1F
#define MM_PROTECTION_WRITE_MASK   4
#define MM_PROTECTION_COPY_MASK   1
#define MM_PROTECTION_OPERATION_MASK   7
#define MM_PROTECTION_EXECUTE_MASK   2
#define MM_SECURE_DELETE_CHECK   0x55
#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
#define MM_DBG_SESSIONS   0x80000000
#define MM_COPY_ON_WRITE_MASK   5
#define MmIsRetryIoStatus(S)
#define MI_CONVERT_FROM_PTE_PROTECTION(PROTECTION_MASK)   (MmProtectToValue[PROTECTION_MASK])
#define MI_MASK_TO_PTE(PROTECTION_MASK)   MmProtectToPteMask[PROTECTION_MASK]
#define MI_IS_PTE_PROTECTION_COPY_WRITE(PROTECTION_MASK)   (((PROTECTION_MASK) & MM_COPY_ON_WRITE_MASK) == MM_COPY_ON_WRITE_MASK)
#define MI_ROUND_TO_64K(LENGTH)   (((LENGTH) + X64K - 1) & ~(X64K - 1))
#define MI_ROUND_TO_SIZE(LENGTH, ALIGNMENT)   (((LENGTH) + ((ALIGNMENT) - 1)) & ~((ALIGNMENT) - 1))
#define MI_64K_ALIGN(VA)   ((PVOID)((ULONG_PTR)(VA) & ~((LONG)X64K - 1)))
#define MI_ALIGN_TO_SIZE(VA, ALIGNMENT)   ((PVOID)((ULONG_PTR)(VA) & ~((ULONG_PTR) ALIGNMENT - 1)))
#define MI_STARTING_OFFSET(SUBSECT, PTE)
#define MiFindEmptyAddressRangeDown(SizeOfRange, HighestAddressToEndAt, Alignment)
#define MiGetPreviousVad(VAD)   ((PMMVAD)MiGetPreviousNode((PMMADDRESS_NODE)(VAD)))
#define MiGetNextVad(VAD)   ((PMMVAD)MiGetNextNode((PMMADDRESS_NODE)(VAD)))
#define MiGetFirstVad(Process)   ((PMMVAD)MiGetFirstNode((PMMADDRESS_NODE)(Process->VadRoot)))
#define MiCheckForConflictingVad(StartingAddress, EndingAddress)
#define MiGetNextClone(CLONE)   ((PMMCLONE_DESCRIPTOR)MiGetNextNode((PMMADDRESS_NODE)(CLONE)))
#define MiGetPreviousClone(CLONE)   ((PMMCLONE_DESCRIPTOR)MiGetPreviousNode((PMMADDRESS_NODE)(CLONE)))
#define MiGetFirstClone()   ((PMMCLONE_DESCRIPTOR)MiGetFirstNode((PMMADDRESS_NODE)(PsGetCurrentProcess()->CloneRoot)))
#define MiInsertClone(CLONE)
#define MiRemoveClone(CLONE)   MiRemoveNode((PMMADDRESS_NODE)(CLONE),(PMMADDRESS_NODE *)&(PsGetCurrentProcess()->CloneRoot));
#define MiLocateCloneAddress(VA)
#define MiCheckForConflictingClone(START, END)
#define MI_VA_TO_PAGE(va)   ((ULONG_PTR)(va) >> PAGE_SHIFT)
#define MI_VA_TO_VPN(va)   ((ULONG_PTR)(va) >> PAGE_SHIFT)
#define MI_VPN_TO_VA(vpn)   (PVOID)((vpn) << PAGE_SHIFT)
#define MI_VPN_TO_VA_ENDING(vpn)   (PVOID)(((vpn) << PAGE_SHIFT) | (PAGE_SIZE - 1))
#define MiGetByteOffset(va)   ((ULONG_PTR)(va) & (PAGE_SIZE - 1))
#define MI_PFN_ELEMENT(index)   (&MmPfnDatabase[index])
#define MI_MAKE_PROTECT_NOT_WRITE_COPY(PROTECT)   (MmMakeProtectNotWriteCopy[PROTECT])
#define MiLockPfnDatabase(OldIrql)   ExAcquireSpinLock(&MmPfnLock, &OldIrql)
#define MiUnlockPfnDatabase(OldIrql)   ExReleaseSpinLock(&MmPfnLock, OldIrql)
#define MiTryToLockPfnDatabase(OldIrql)   KeTryToAcquireSpinLock(&MmPfnLock, &OldIrql)
#define MiReleasePfnLock()   KiReleaseSpinLock(&MmPfnLock)
#define MiLockSystemSpace(OldIrql)   ExAcquireSpinLock(&MmSystemSpaceLock, &OldIrql)
#define MiUnlockSystemSpace(OldIrql)   ExReleaseSpinLock(&MmSystemSpaceLock, OldIrql)
#define MiLockSystemSpaceAtDpcLevel()   ExAcquireSpinLockAtDpcLevel(&MmSystemSpaceLock)
#define MiUnlockSystemSpaceFromDpcLevel()   ExReleaseSpinLockFromDpcLevel(&MmSystemSpaceLock)
#define CONSISTENCY_LOCK_PFN(OLDIRQL)
#define CONSISTENCY_UNLOCK_PFN(OLDIRQL)
#define CONSISTENCY_LOCK_PFN2(OLDIRQL)
#define CONSISTENCY_UNLOCK_PFN2(OLDIRQL)
#define PFN_CONSISTENCY_SET
#define PFN_CONSISTENCY_UNSET
#define LOCK_PFN(OLDIRQL)
#define LOCK_PFN_WITH_TRY(OLDIRQL)
#define UNLOCK_PFN(OLDIRQL)
#define LOCK_PFN2(OLDIRQL)
#define UNLOCK_PFN2(OLDIRQL)
#define UNLOCK_PFN_AND_THEN_WAIT(OLDIRQL)
#define LOCK_AWE(PROCESS, OldIrql)   ExAcquireSpinLock(&((PROCESS)->AweLock), &OldIrql)
#define UNLOCK_AWE(PROCESS, OldIrql)   ExReleaseSpinLock(&((PROCESS)->AweLock), OldIrql)
#define SYSLOAD_LOCK_OWNED_BY_ME()
#define MM_PFN_LOCK_ASSERT()
#define MM_SET_EXPANSION_OWNER()
#define MM_CLEAR_EXPANSION_OWNER()
#define LOCK_EXPANSION(OLDIRQL)
#define UNLOCK_EXPANSION(OLDIRQL)
#define UNLOCK_EXPANSION_AND_THEN_WAIT(OLDIRQL)
#define LOCK_EXPANSION_IF_ALPHA(OLDIRQL)
#define UNLOCK_EXPANSION_IF_ALPHA(OLDIRQL)
#define LOCK_SYSTEM_WS(OLDIRQL)
#define UNLOCK_SYSTEM_WS(OLDIRQL)
#define UNLOCK_SYSTEM_WS_NO_IRQL()
#define MM_SYSTEM_WS_LOCK_ASSERT()   ASSERT (PsGetCurrentThread() == MmSystemLockOwner);
#define LOCK_HYPERSPACE(OLDIRQL)   ExAcquireSpinLock ( &(PsGetCurrentProcess())->HyperSpaceLock, OLDIRQL );
#define UNLOCK_HYPERSPACE(OLDIRQL)   ExReleaseSpinLock ( &(PsGetCurrentProcess())->HyperSpaceLock, OLDIRQL );
#define MI_WS_OWNER(PROCESS)   1
#define MI_NOT_WS_OWNER(PROCESS)   1
#define MI_MUTEX_ACQUIRED_UNSAFE   0x88
#define MI_IS_WS_UNSAFE(PROCESS)   ((PROCESS)->WorkingSetLock.OldIrql == MI_MUTEX_ACQUIRED_UNSAFE)
#define LOCK_WS(PROCESS)
#define LOCK_WS_UNSAFE(PROCESS)
#define MI_MUST_BE_UNSAFE(PROCESS)
#define MI_MUST_BE_SAFE(PROCESS)
#define UNLOCK_WS(PROCESS)
#define UNLOCK_WS_UNSAFE(PROCESS)
#define LOCK_ADDRESS_SPACE(PROCESS)   ExAcquireFastMutex( &((PROCESS)->AddressCreationLock))
#define LOCK_WS_AND_ADDRESS_SPACE(PROCESS)
#define UNLOCK_WS_AND_ADDRESS_SPACE(PROCESS)
#define UNLOCK_ADDRESS_SPACE(PROCESS)   ExReleaseFastMutex( &((PROCESS)->AddressCreationLock))
#define UNLOCK_WS_REGARDLESS(PROCESS, WSHELDSAFE)
#define LOCK_WS_REGARDLESS(PROCESS, WSHELDSAFE)
#define ZERO_LARGE(LargeInteger)
#define MI_CHECK_BIT(ARRAY, BIT)   (((ULONG)ARRAY[(BIT) / (sizeof(ULONG)*8)] >> ((BIT) & 0x1F)) & 1)
#define MI_SET_BIT(ARRAY, BIT)   (ULONG)ARRAY[(BIT) / (sizeof(ULONG)*8)] |= (1 << ((BIT) & 0x1F))
#define MI_CLEAR_BIT(ARRAY, BIT)   (ULONG)ARRAY[(BIT) / (sizeof(ULONG)*8)] &= ~(1 << ((BIT) & 0x1F))
#define MI_MAGIC_AWE_PTEFRAME   0xffffedcb
#define MI_PFN_IS_AWE(Pfn1)
#define StartOfAllocation   ReadInProgress
#define EndOfAllocation   WriteInProgress
#define LargeSessionAllocation   PrototypePte
#define MI_CAPTURE_USED_PAGETABLE_ENTRIES(PFN)
#define MI_RETRIEVE_USED_PAGETABLE_ENTRIES_FROM_PTE(RBL, PTE)
#define MI_ZERO_USED_PAGETABLE_ENTRIES_IN_INPAGE_SUPPORT(INPAGE_SUPPORT)
#define MI_ZERO_USED_PAGETABLE_ENTRIES_IN_PFN(PFN)
#define MI_INSERT_USED_PAGETABLE_ENTRIES_IN_PFN(PFN, INPAGE_SUPPORT)
#define MI_GET_USED_PTES_HANDLE(VA)   ((PVOID)&MmWorkingSetList->UsedPageTableEntries[MiGetPpePdeOffset(VA)])
#define MI_GET_USED_PTES_FROM_HANDLE(PDSHORT)   ((ULONG)(*(PUSHORT)(PDSHORT)))
#define MI_INCREMENT_USED_PTES_BY_HANDLE(PDSHORT)
#define MI_DECREMENT_USED_PTES_BY_HANDLE(PDSHORT)
#define MI_MARK_PFN_AS_LOCK_CHARGED(Pfn, CallerId)
#define MI_UNMARK_PFN_AS_LOCK_CHARGED(Pfn, CallerId)
#define MI_ADD_LOCKED_PAGE_CHARGE(Pfn, CallerId)
#define MI_ADD_LOCKED_PAGE_CHARGE_FOR_MODIFIED_PAGE(Pfn, CallerId)
#define MI_ADD_LOCKED_PAGE_CHARGE_FOR_TRANSITION_PAGE(Pfn, CallerId)
#define MI_REMOVE_LOCKED_PAGE_CHARGE(Pfn, CallerId)
#define MI_ZERO_WSINDEX(Pfn)   Pfn->u1.Event = NULL;
#define MI_WSLE_HASH(Address, Wsl)
#define MI_GET_PROTECTION_FROM_WSLE(Wsl)   ((Wsl)->u1.e1.Protection)
#define MI_USE_AGE_COUNT   4
#define MI_USE_AGE_MAX   (MI_USE_AGE_COUNT - 1)
#define MI_REPLACEMENT_FREE_GROWTH_SHIFT   5
#define MI_REPLACEMENT_CLAIM_THRESHOLD_SHIFT   3
#define MI_REPLACEMENT_EAVAIL_THRESHOLD_SHIFT   3
#define MI_IMMEDIATE_REPLACEMENT_AGE   2
#define MI_MAX_TRIM_PASSES   4
#define MI_PASS0_TRIM_AGE   2
#define MI_PASS1_TRIM_AGE   1
#define MI_PASS2_TRIM_AGE   1
#define MI_PASS3_TRIM_AGE   1
#define MI_PASS4_TRIM_AGE   0
#define MI_TRIM_AGE_THRESHOLD   2
#define MI_FOREGROUND_CLAIM_AVAILABLE_SHIFT   3
#define MI_BACKGROUND_CLAIM_AVAILABLE_SHIFT   1
#define MI_CALC_NEXT_ESTIMATION_SLOT_CONST(NextEstimationSlotConst, WorkingSetList)   (NextEstimationSlotConst).Stride = 1 << MiEstimationShift;
#define MI_NEXT_VALID_ESTIMATION_SLOT(Previous, StartEntry, Minimum, Maximum, NextEstimationSlotConst, Wsle)
#define MI_NEXT_VALID_AGING_SLOT(Previous, Minimum, Maximum, Wsle)
#define MI_CALCULATE_USAGE_ESTIMATE(SampledAgeCounts)
#define MI_RESET_WSLE_AGE(PointerPte, Wsle)   (Wsle)->u1.e1.Age = 0;
#define MI_GET_WSLE_AGE(PointerPte, Wsle)   ((Wsle)->u1.e1.Age)
#define MI_INC_WSLE_AGE(PointerPte, Wsle)
#define MI_UPDATE_USE_ESTIMATE(PointerPte, Wsle, SampledAgeCounts)   (SampledAgeCounts)[(Wsle)->u1.e1.Age] += 1;
#define MI_WS_GROWING_TOO_FAST(VmSupport)
#define SECTION_BASE_ADDRESS(_NtSection)   (*((PVOID *)&(_NtSection)->PointerToRelocations))
#define MI_MAXIMUM_SECTION_SIZE   ((UINT64)16*1024*1024*1024*1024*1024 - (1<<MM4K_SHIFT))
#define Mi4KStartForSubsection(address, subsection)
#define Mi4KStartFromSubsection(address, subsection)
#define MI_EXTEND_ANY_PAGEFILE   ((ULONG)-1)
#define SUBSECTION_READ_ONLY   1L
#define SUBSECTION_READ_WRITE   2L
#define SUBSECTION_COPY_ON_WRITE   4L
#define SUBSECTION_SHARE_ALLOW   8L
#define COMMIT_SIZE   19
#define MM_MAX_COMMIT   (((ULONG_PTR) 1 << COMMIT_SIZE) - 1)
#define MM_VIEW_UNMAP   0
#define MM_VIEW_SHARE   1
#define MI_GET_PROTECTION_FROM_VAD(_Vad)   ((ULONG)(_Vad)->u.VadFlags.Protection)
#define MI_PHYSICAL_VIEW_KEY   'vpmM'
#define MI_WRITEWATCH_VIEW_KEY   'wWmM'
#define MiCreateBitMap(BMH, S, P)
#define MiRemoveBitMap(BMH)
#define MI_INITIALIZE_ZERO_MDL(MDL)
#define MM_PAGING_FILE_MDLS   2
#define MM_SYS_PTE_TABLES_MAX   5
#define LOCK_SYSTEM_VIEW_SPACE(_Session)   ExAcquireFastMutex (_Session->SystemSpaceViewLockPointer)
#define UNLOCK_SYSTEM_VIEW_SPACE(_Session)   ExReleaseFastMutex (_Session->SystemSpaceViewLockPointer)
#define MI_UNLOADED_DRIVERS   50
#define MiDecrementShareCountOnly(P)   MiDecrementShareCount(P)
#define MiDecrementShareAndValidCount(P)   MiDecrementShareCount(P)
#define MiRemoveZeroPageIfAny(COLOR)
#define MiUnmapPageInHyperSpace(OLDIRQL)   UNLOCK_HYPERSPACE(OLDIRQL)
#define MiMakePpeExistAndMakeValid(PDE, PROCESS, PFNMUTEXHELD)
#define MiGetProtoPteAddress(VAD, VPN)
#define STATUS_MAPPED_WRITER_COLLISION   (0xC0033333)
#define MM_SPECIAL_POOL_PTES   25000
#define MI_SUSPECT_DRIVER_BUFFER_LENGTH   512
#define VI_POOL_FREELIST_END   ((ULONG_PTR)-1)
#define MI_VERIFIER_ENTRY_SIGNATURE   0x98761940
#define VI_VERIFYING_DIRECTLY   0x1
#define VI_VERIFYING_INVERSELY   0x2
#define MM_TRACK_COMMIT(_index, bump)
#define MI_FREED_SPECIAL_POOL_SIGNATURE   0x98764321
#define MI_STACK_BYTES   1024
#define MM_DBG_COMMIT_NONPAGED_POOL_EXPANSION   0
#define MM_DBG_COMMIT_PAGED_POOL_PAGETABLE   1
#define MM_DBG_COMMIT_PAGED_POOL_PAGES   2
#define MM_DBG_COMMIT_SESSION_POOL_PAGE_TABLES   3
#define MM_DBG_COMMIT_ALLOCVM1   4
#define MM_DBG_COMMIT_ALLOCVM2   5
#define MM_DBG_COMMIT_IMAGE   6
#define MM_DBG_COMMIT_PAGEFILE_BACKED_SHMEM   7
#define MM_DBG_COMMIT_INDEPENDENT_PAGES   8
#define MM_DBG_COMMIT_CONTIGUOUS_PAGES   9
#define MM_DBG_COMMIT_MDL_PAGES   10
#define MM_DBG_COMMIT_NONCACHED_PAGES   11
#define MM_DBG_COMMIT_MAPVIEW_DATA   12
#define MM_DBG_COMMIT_FILL_SYSTEM_DIRECTORY   13
#define MM_DBG_COMMIT_EXTRA_SYSTEM_PTES   14
#define MM_DBG_COMMIT_DRIVER_PAGING_AT_INIT   15
#define MM_DBG_COMMIT_PAGEFILE_FULL   16
#define MM_DBG_COMMIT_PROCESS_CREATE   17
#define MM_DBG_COMMIT_KERNEL_STACK_CREATE   18
#define MM_DBG_COMMIT_SET_PROTECTION   19
#define MM_DBG_COMMIT_SESSION_CREATE   20
#define MM_DBG_COMMIT_SESSION_IMAGE_PAGES   21
#define MM_DBG_COMMIT_SESSION_PAGETABLE_PAGES   22
#define MM_DBG_COMMIT_SESSION_SHARED_IMAGE   23
#define MM_DBG_COMMIT_DRIVER_PAGES   24
#define MM_DBG_COMMIT_INSERT_VAD   25
#define MM_DBG_COMMIT_SESSION_WS_INIT   26
#define MM_DBG_COMMIT_SESSION_ADDITIONAL_WS_PAGES   27
#define MM_DBG_COMMIT_SESSION_ADDITIONAL_WS_HASHPAGES   28
#define MM_DBG_COMMIT_RETURN_NONPAGED_POOL_EXPANSION   29
#define MM_DBG_COMMIT_RETURN_PAGED_POOL_PAGES   30
#define MM_DBG_COMMIT_RETURN_SESSION_POOL_PAGE_TABLES   31
#define MM_DBG_COMMIT_RETURN_ALLOCVM1   32
#define MM_DBG_COMMIT_RETURN_ALLOCVM2   33
#define MM_DBG_COMMIT_RETURN_ALLOCVM3   34
#define MM_DBG_COMMIT_RETURN_IMAGE_NO_LARGE_CA   35
#define MM_DBG_COMMIT_RETURN_PAGEFILE_BACKED_SHMEM   36
#define MM_DBG_COMMIT_RETURN_NTFREEVM1   37
#define MM_DBG_COMMIT_RETURN_NTFREEVM2   38
#define MM_DBG_COMMIT_RETURN_NTFREEVM3   39
#define MM_DBG_COMMIT_RETURN_NTFREEVM4   40
#define MM_DBG_COMMIT_RETURN_MDL_PAGES   41
#define MM_DBG_COMMIT_RETURN_NONCACHED_PAGES   42
#define MM_DBG_COMMIT_RETURN_MAPVIEW_DATA   43
#define MM_DBG_COMMIT_RETURN_PAGETABLES   44
#define MM_DBG_COMMIT_RETURN_PROTECTION   45
#define MM_DBG_COMMIT_RETURN_SEGMENT_DELETE1   46
#define MM_DBG_COMMIT_RETURN_SEGMENT_DELETE2   47
#define MM_DBG_COMMIT_RETURN_SESSION_CREATE_FAILURE1   48
#define MM_DBG_COMMIT_RETURN_SESSION_DEREFERENCE   49
#define MM_DBG_COMMIT_RETURN_SESSION_IMAGE_FAILURE1   50
#define MM_DBG_COMMIT_RETURN_SESSION_PAGETABLE_PAGES   51
#define MM_DBG_COMMIT_RETURN_VAD   52
#define MM_DBG_COMMIT_RETURN_SESSION_WSL_FAILURE   54
#define MM_DBG_COMMIT_RETURN_PROCESS_CREATE_FAILURE1   55
#define MM_DBG_COMMIT_RETURN_PROCESS_DELETE   56
#define MM_DBG_COMMIT_RETURN_PROCESS_CLEAN_PAGETABLES   57
#define MM_DBG_COMMIT_RETURN_KERNEL_STACK_FAILURE1   58
#define MM_DBG_COMMIT_RETURN_KERNEL_STACK_FAILURE2   59
#define MM_DBG_COMMIT_RETURN_KERNEL_STACK_DELETE   60
#define MM_DBG_COMMIT_RETURN_SESSION_DRIVER_LOAD_FAILURE1   61
#define MM_DBG_COMMIT_RETURN_DRIVER_INIT_CODE   62
#define MM_DBG_COMMIT_RETURN_DRIVER_UNLOAD   63
#define MM_DBG_COMMIT_RETURN_DRIVER_UNLOAD1   64
#define MM_BUMP_COUNTER_MAX   60
#define MM_BUMP_COUNTER(_index, bump)
#define MI_NONPAGABLE_MEMORY_AVAILABLE()
#define MI_MAX_FREE_LIST_HEADS   4
#define MI_UNUSED_SEGMENTS_COUNT_UPDATE(_count)   MmUnusedSegmentCount += (_count);
#define MI_FILESYSTEM_NONPAGED_POOL_CHARGE   150
#define MI_FILESYSTEM_PAGED_POOL_CHARGE   1024
#define MI_UNUSED_SEGMENTS_SURPLUS()
#define MI_UNUSED_SEGMENTS_INSERT_CHARGE(_ControlArea)
#define MI_UNUSED_SEGMENTS_REMOVE_CHARGE(_ControlArea)
#define MM_MAPPED_FILE_MDLS   4
#define HYDRA_PROCESS   ((PEPROCESS)1)
#define MI_SESSION_SPACE_STRUCT_SIZE   MM_ALLOCATION_GRANULARITY
#define MI_SESSION_SPACE_WS_SIZE   (4*1024*1024 - MI_SESSION_SPACE_STRUCT_SIZE)
#define MI_SESSION_IMAGE_SIZE   (8*1024*1024)
#define MI_SESSION_VIEW_SIZE   (20*1024*1024)
#define MI_SESSION_POOL_SIZE   (16*1024*1024)
#define MM_SESSION_SPACE_DATA_SIZE   PAGE_SIZE
#define MI_SESSION_SPACE_TOTAL_SIZE
#define MI_SESSION_MAXIMUM_WORKING_SET   ((ULONG)(MI_SESSION_SPACE_TOTAL_SIZE >> PAGE_SHIFT))
#define MI_SESSION_SPACE_PAGE_TABLES   (MI_SESSION_SPACE_TOTAL_SIZE / MM_VA_MAPPED_BY_PDE)
#define MI_SESSION_IMAGE_OFFSET   (0)
#define MI_SESSION_DATA_OFFSET   (8*1024*1024)
#define MI_SESSION_WS_OFFSET   (8*1024*1024 + MI_SESSION_SPACE_STRUCT_SIZE)
#define MI_SESSION_VIEW_OFFSET   (12*1024*1024)
#define MI_SESSION_POOL_OFFSET   (32*1024*1024)
#define MI_SESSION_IMAGE_START   ((ULONG_PTR)MmSessionBase)
#define MI_SESSION_SPACE_WS   (MmSessionBase + MI_SESSION_WS_OFFSET)
#define MI_SESSION_VIEW_START   (MmSessionBase + MI_SESSION_VIEW_OFFSET)
#define MI_SESSION_POOL   (MmSessionBase + MI_SESSION_POOL_OFFSET)
#define MI_SESSION_SPACE_END
#define MI_IS_SESSION_IMAGE_ADDRESS(VirtualAddress)   (MiHydra == TRUE && (PVOID)(VirtualAddress) >= (PVOID)MI_SESSION_IMAGE_START && (PVOID)(VirtualAddress) < (PVOID)(MI_SESSION_IMAGE_START + MI_SESSION_IMAGE_SIZE))
#define MI_IS_SESSION_POOL_ADDRESS(VirtualAddress)   (MiHydra == TRUE && (PVOID)(VirtualAddress) >= (PVOID)MI_SESSION_POOL && (PVOID)(VirtualAddress) < (PVOID)(MI_SESSION_POOL + MI_SESSION_POOL_SIZE))
#define MI_IS_SESSION_ADDRESS(_VirtualAddress)   (MiHydra == TRUE && (PVOID)(_VirtualAddress) >= (PVOID)MmSessionBase && (PVOID)(_VirtualAddress) < (PVOID)(MI_SESSION_SPACE_END))
#define MI_IS_SESSION_PTE(_Pte)   (MiHydra == TRUE && (PMMPTE)(_Pte) >= MiSessionBasePte && (PMMPTE)(_Pte) < MiSessionLastPte)
#define SESSION_GLOBAL(_Session)   (_Session->GlobalVirtualAddress)
#define MM_DBG_SESSION_INITIAL_PAGETABLE_ALLOC   0
#define MM_DBG_SESSION_INITIAL_PAGETABLE_FREE_RACE   1
#define MM_DBG_SESSION_INITIAL_PAGE_ALLOC   2
#define MM_DBG_SESSION_INITIAL_PAGE_FREE_FAIL1   3
#define MM_DBG_SESSION_INITIAL_PAGETABLE_FREE_FAIL1   4
#define MM_DBG_SESSION_WS_PAGE_FREE   5
#define MM_DBG_SESSION_PAGETABLE_ALLOC   6
#define MM_DBG_SESSION_SYSMAPPED_PAGES_ALLOC   7
#define MM_DBG_SESSION_WS_PAGETABLE_ALLOC   8
#define MM_DBG_SESSION_PAGEDPOOL_PAGETABLE_ALLOC   9
#define MM_DBG_SESSION_PAGEDPOOL_PAGETABLE_FREE_FAIL1   10
#define MM_DBG_SESSION_WS_PAGE_ALLOC   11
#define MM_DBG_SESSION_WS_PAGE_ALLOC_GROWTH   12
#define MM_DBG_SESSION_INITIAL_PAGE_FREE   13
#define MM_DBG_SESSION_PAGETABLE_FREE   14
#define MM_DBG_SESSION_PAGEDPOOL_PAGETABLE_ALLOC1   15
#define MM_DBG_SESSION_DRIVER_PAGES_LOCKED   16
#define MM_DBG_SESSION_DRIVER_PAGES_UNLOCKED   17
#define MM_DBG_SESSION_WS_HASHPAGE_ALLOC   18
#define MM_DBG_SESSION_SYSMAPPED_PAGES_COMMITTED   19
#define MM_DBG_SESSION_COMMIT_PAGEDPOOL_PAGES   30
#define MM_DBG_SESSION_COMMIT_DELETE_VM_RETURN   31
#define MM_DBG_SESSION_COMMIT_POOL_FREED   32
#define MM_DBG_SESSION_COMMIT_IMAGE_UNLOAD   33
#define MM_DBG_SESSION_COMMIT_IMAGELOAD_FAILED1   34
#define MM_DBG_SESSION_COMMIT_IMAGELOAD_FAILED2   35
#define MM_DBG_SESSION_COMMIT_IMAGELOAD_NOACCESS   36
#define MM_BUMP_SESS_COUNTER(_index, bump)
#define MM_SNAP_SESS_MEMORY_COUNTERS(_index)
#define MM_SESSION_FAILURE_NO_IDS   0
#define MM_SESSION_FAILURE_NO_COMMIT   1
#define MM_SESSION_FAILURE_NO_RESIDENT   2
#define MM_SESSION_FAILURE_RACE_DETECTED   3
#define MM_SESSION_FAILURE_NO_SYSPTES   4
#define MM_SESSION_FAILURE_NO_PAGED_POOL   5
#define MM_SESSION_FAILURE_NO_NONPAGED_POOL   6
#define MM_SESSION_FAILURE_NO_IMAGE_VA_SPACE   7
#define MM_SESSION_FAILURE_NO_SESSION_PAGED_POOL   8
#define MM_SESSION_FAILURE_CAUSES   9
#define MM_BUMP_SESSION_FAILURES(_index)   MmSessionFailureCauses[_index] += 1;
#define MI_FLUSH_SESSION_TB(OLDIRQL)
#define MM_SET_SESSION_LOCK_OWNER()
#define MM_CLEAR_SESSION_LOCK_OWNER()
#define LOCK_SESSION(OLDIRQL)
#define UNLOCK_SESSION(OLDIRQL)
#define MI_SESSION_SPACE_WORKING_SET_MINIMUM   20
#define MI_SESSION_SPACE_WORKING_SET_MAXIMUM   384
#define MM_SET_SESSION_RESOURCE_OWNER()
#define MM_CLEAR_SESSION_RESOURCE_OWNER()
#define MM_SESSION_SPACE_WS_LOCK_ASSERT()   ASSERT (MmSessionSpace->WorkingSetLockOwner == PsGetCurrentThread())
#define LOCK_SESSION_SPACE_WS(OLDIRQL)
#define UNLOCK_SESSION_SPACE_WS(OLDIRQL)
#define MiGetPdeSessionIndex(va)   ((ULONG)(((ULONG_PTR)(va) - (ULONG_PTR)MmSessionBase) >> PDI_SHIFT))
#define MI_GET_DIRECTORY_FRAME_FROM_PROCESS(_Process)   MI_GET_PAGE_FRAME_FROM_PTE((PMMPTE)(&((_Process)->Pcb.DirectoryTableBase[0])))

Typedefs

typedef ULONG WSLE_NUMBER
typedef ULONG * PWSLE_NUMBER
typedef _MMPFNENTRY MMPFNENTRY
typedef _MMPFN MMPFN
typedef _MMPFNPMMPFN
typedef enum _MMSHARE_TYPE MMSHARE_TYPE
typedef _MMWSLE_HASH MMWSLE_HASH
typedef _MMWSLE_HASHPMMWSLE_HASH
typedef _MMWSLENTRY MMWSLENTRY
typedef _MMWSLE MMWSLE
typedef MMWSLEPMMWSLE
typedef _MMWSL MMWSL
typedef _MMWSLPMMWSL
typedef _MI_NEXT_ESTIMATION_SLOT_CONST MI_NEXT_ESTIMATION_SLOT_CONST
typedef enum _SECTION_CHECK_TYPE SECTION_CHECK_TYPE
typedef _MMEXTEND_INFO MMEXTEND_INFO
typedef _MMEXTEND_INFOPMMEXTEND_INFO
typedef _SEGMENT SEGMENT
typedef _SEGMENTPSEGMENT
typedef _EVENT_COUNTER EVENT_COUNTER
typedef _EVENT_COUNTERPEVENT_COUNTER
typedef _MMSECTION_FLAGS MMSECTION_FLAGS
typedef _CONTROL_AREA CONTROL_AREA
typedef _CONTROL_AREAPCONTROL_AREA
typedef _LARGE_CONTROL_AREA LARGE_CONTROL_AREA
typedef _LARGE_CONTROL_AREAPLARGE_CONTROL_AREA
typedef _MMSUBSECTION_FLAGS MMSUBSECTION_FLAGS
typedef _SUBSECTION SUBSECTION
typedef _SUBSECTIONPSUBSECTION
typedef _MMDEREFERENCE_SEGMENT_HEADER MMDEREFERENCE_SEGMENT_HEADER
typedef _MMPAGE_FILE_EXPANSION MMPAGE_FILE_EXPANSION
typedef _MMPAGE_FILE_EXPANSIONPMMPAGE_FILE_EXPANSION
typedef _MMWORKING_SET_EXPANSION_HEAD MMWORKING_SET_EXPANSION_HEAD
typedef _MMFLUSH_BLOCK MMFLUSH_BLOCK
typedef _MMFLUSH_BLOCKPMMFLUSH_BLOCK
typedef _MMINPAGE_SUPPORT MMINPAGE_SUPPORT
typedef _MMINPAGE_SUPPORTPMMINPAGE_SUPPORT
typedef _MMPAGE_READ MMPAGE_READ
typedef _MMPAGE_READPMMPAGE_READ
typedef _MMADDRESS_NODE MMADDRESS_NODE
typedef _MMADDRESS_NODEPMMADDRESS_NODE
typedef _SECTION SECTION
typedef _SECTIONPSECTION
typedef _MMBANKED_SECTION MMBANKED_SECTION
typedef _MMBANKED_SECTIONPMMBANKED_SECTION
typedef _MMVAD_FLAGS MMVAD_FLAGS
typedef _MMVAD_FLAGS2 MMVAD_FLAGS2
typedef _MMADDRESS_LIST MMADDRESS_LIST
typedef _MMADDRESS_LISTPMMADDRESS_LIST
typedef _MMSECURE_ENTRY MMSECURE_ENTRY
typedef _MMSECURE_ENTRYPMMSECURE_ENTRY
typedef _MMVAD MMVAD
typedef _MMVADPMMVAD
typedef _MMVAD_SHORT MMVAD_SHORT
typedef _MMVAD_SHORTPMMVAD_SHORT
typedef _MI_PHYSICAL_VIEW MI_PHYSICAL_VIEW
typedef _MI_PHYSICAL_VIEWPMI_PHYSICAL_VIEW
typedef _MMCLONE_BLOCK MMCLONE_BLOCK
typedef MMCLONE_BLOCKPMMCLONE_BLOCK
typedef _MMCLONE_HEADER MMCLONE_HEADER
typedef _MMCLONE_HEADERPMMCLONE_HEADER
typedef _MMCLONE_DESCRIPTOR MMCLONE_DESCRIPTOR
typedef _MMCLONE_DESCRIPTORPMMCLONE_DESCRIPTOR
typedef _MMMOD_WRITER_LISTHEAD MMMOD_WRITER_LISTHEAD
typedef _MMMOD_WRITER_LISTHEADPMMMOD_WRITER_LISTHEAD
typedef _MMMOD_WRITER_MDL_ENTRY MMMOD_WRITER_MDL_ENTRY
typedef _MMMOD_WRITER_MDL_ENTRYPMMMOD_WRITER_MDL_ENTRY
typedef _MMPAGING_FILE MMPAGING_FILE
typedef _MMPAGING_FILEPMMPAGING_FILE
typedef _MMINPAGE_SUPPORT_LIST MMINPAGE_SUPPORT_LIST
typedef _MMINPAGE_SUPPORT_LISTPMMINPAGE_SUPPORT_LIST
typedef _MMEVENT_COUNT_LIST MMEVENT_COUNT_LIST
typedef _MMEVENT_COUNT_LISTPMMEVENT_COUNT_LIST
typedef enum _MMSYSTEM_PTE_POOL_TYPE MMSYSTEM_PTE_POOL_TYPE
typedef _MMFREE_POOL_ENTRY MMFREE_POOL_ENTRY
typedef _MMFREE_POOL_ENTRYPMMFREE_POOL_ENTRY
typedef _MMLOCK_CONFLICT MMLOCK_CONFLICT
typedef _MMLOCK_CONFLICTPMMLOCK_CONFLICT
typedef _MMVIEW MMVIEW
typedef _MMVIEWPMMVIEW
typedef _MMSESSION MMSESSION
typedef _MMSESSIONPMMSESSION
typedef _MMPTE_FLUSH_LIST MMPTE_FLUSH_LIST
typedef _MMPTE_FLUSH_LISTPMMPTE_FLUSH_LIST
typedef _LOCK_TRACKER LOCK_TRACKER
typedef _LOCK_TRACKERPLOCK_TRACKER
typedef _LOCK_HEADER LOCK_HEADER
typedef _LOCK_HEADERPLOCK_HEADER
typedef _UNLOADED_DRIVERS UNLOADED_DRIVERS
typedef _UNLOADED_DRIVERSPUNLOADED_DRIVERS
typedef _VI_POOL_ENTRY_INUSE VI_POOL_ENTRY_INUSE
typedef _VI_POOL_ENTRY_INUSEPVI_POOL_ENTRY_INUSE
typedef _VI_POOL_ENTRY VI_POOL_ENTRY
typedef _VI_POOL_ENTRYPVI_POOL_ENTRY
typedef _MI_VERIFIER_DRIVER_ENTRY MI_VERIFIER_DRIVER_ENTRY
typedef _MI_VERIFIER_DRIVER_ENTRYPMI_VERIFIER_DRIVER_ENTRY
typedef _MI_VERIFIER_POOL_HEADER MI_VERIFIER_POOL_HEADER
typedef _MI_VERIFIER_POOL_HEADERPMI_VERIFIER_POOL_HEADER
typedef _MM_DRIVER_VERIFIER_DATA MM_DRIVER_VERIFIER_DATA
typedef _MM_DRIVER_VERIFIER_DATAPMM_DRIVER_VERIFIER_DATA
typedef _MI_FREED_SPECIAL_POOL MI_FREED_SPECIAL_POOL
typedef _MI_FREED_SPECIAL_POOLPMI_FREED_SPECIAL_POOL
typedef _MM_PAGED_POOL_INFO MM_PAGED_POOL_INFO
typedef _MM_PAGED_POOL_INFOPMM_PAGED_POOL_INFO
typedef _MM_SESSION_SPACE_FLAGS MM_SESSION_SPACE_FLAGS
typedef _MM_SESSION_SPACE MM_SESSION_SPACE
typedef _MM_SESSION_SPACEPMM_SESSION_SPACE
typedef _IMAGE_ENTRY_IN_SESSION IMAGE_ENTRY_IN_SESSION
typedef _IMAGE_ENTRY_IN_SESSIONPIMAGE_ENTRY_IN_SESSION

Enumerations

enum  _MMSHARE_TYPE { Normal, ShareCountOnly, AndValid }
enum  _SECTION_CHECK_TYPE { CheckDataSection, CheckImageSection, CheckUserDataSection, CheckBothSection }
enum  _MMSYSTEM_PTE_POOL_TYPE { SystemPteSpace, NonPagedPoolExpansion, MaximumPtePoolTypes }

Functions

VOID MiCaptureWriteWatchDirtyBit (IN PEPROCESS Process, IN PVOID VirtualAddress)
VOID MiMarkProcessAsWriteWatch (IN PEPROCESS Process)
VOID MiRemoveConflictFromList (IN PMMLOCK_CONFLICT Conflict)
VOID MiInsertConflictInList (IN PMMLOCK_CONFLICT Conflict)
VOID MiInitMachineDependent (IN PLOADER_PARAMETER_BLOCK LoaderBlock)
VOID MiBuildPagedPool (VOID)
VOID MiInitializeNonPagedPool (VOID)
BOOLEAN MiInitializeSystemSpaceMap (PVOID Session OPTIONAL)
VOID MiFindInitializationCode (OUT PVOID *StartVa, OUT PVOID *EndVa)
VOID MiFreeInitializationCode (IN PVOID StartVa, IN PVOID EndVa)
ULONG MiSectionInitialization (VOID)
VOID FASTCALL MiDecrementReferenceCount (IN PFN_NUMBER PageFrameIndex)
VOID FASTCALL MiDecrementShareCount (IN PFN_NUMBER PageFrameIndex)
VOID FASTCALL MiInsertPageInList (IN PMMPFNLIST ListHead, IN PFN_NUMBER PageFrameIndex)
VOID FASTCALL MiInsertStandbyListAtFront (IN PFN_NUMBER PageFrameIndex)
PFN_NUMBER FASTCALL MiRemovePageFromList (IN PMMPFNLIST ListHead)
VOID FASTCALL MiUnlinkPageFromList (IN PMMPFN Pfn)
VOID MiUnlinkFreeOrZeroedPage (IN PFN_NUMBER Page)
VOID FASTCALL MiInsertFrontModifiedNoWrite (IN PFN_NUMBER PageFrameIndex)
ULONG FASTCALL MiEnsureAvailablePageOrWait (IN PEPROCESS Process, IN PVOID VirtualAddress)
PFN_NUMBER FASTCALL MiRemoveZeroPage (IN ULONG PageColor)
PFN_NUMBER FASTCALL MiRemoveAnyPage (IN ULONG PageColor)
PVOID MiFindContiguousMemory (IN PFN_NUMBER LowestPfn, IN PFN_NUMBER HighestPfn, IN PFN_NUMBER BoundaryPfn, IN PFN_NUMBER SizeInPages, IN PVOID CallingAddress)
PVOID MiCheckForContiguousMemory (IN PVOID BaseAddress, IN PFN_NUMBER BaseAddressPages, IN PFN_NUMBER SizeInPages, IN PFN_NUMBER LowestPfn, IN PFN_NUMBER HighestPfn, IN PFN_NUMBER BoundaryPfn)
VOID MiInitializePfn (IN PFN_NUMBER PageFrameIndex, IN PMMPTE PointerPte, IN ULONG ModifiedState)
VOID MiInitializePfnForOtherProcess (IN PFN_NUMBER PageFrameIndex, IN PMMPTE PointerPte, IN PFN_NUMBER ContainingPageFrame)
VOID MiInitializeCopyOnWritePfn (IN PFN_NUMBER PageFrameIndex, IN PMMPTE PointerPte, IN WSLE_NUMBER WorkingSetIndex, IN PVOID SessionSpace)
VOID MiInitializeTransitionPfn (IN PFN_NUMBER PageFrameIndex, IN PMMPTE PointerPte, IN WSLE_NUMBER WorkingSetIndex)
VOID MiFlushInPageSupportBlock ()
VOID MiFreeInPageSupportBlock (IN PMMINPAGE_SUPPORT Support)
VOID FASTCALL MiZeroPhysicalPage (IN PFN_NUMBER PageFrameIndex, IN ULONG Color)
VOID FASTCALL MiRestoreTransitionPte (IN PFN_NUMBER PageFrameIndex)
PSUBSECTION MiGetSubsectionAndProtoFromPte (IN PMMPTE PointerPte, IN PMMPTE *ProtoPte, IN PEPROCESS Process)
PVOID MiMapPageInHyperSpace (IN PFN_NUMBER PageFrameIndex, OUT PKIRQL OldIrql)
PVOID MiMapImageHeaderInHyperSpace (IN PFN_NUMBER PageFrameIndex)
VOID MiUnmapImageHeaderInHyperSpace (VOID)
VOID MiUpdateImageHeaderPage (IN PMMPTE PointerPte, IN PFN_NUMBER PageFrameNumber, IN PCONTROL_AREA ControlArea)
PFN_NUMBER MiGetPageForHeader (VOID)
VOID MiRemoveImageHeaderPage (IN PFN_NUMBER PageFrameNumber)
PVOID MiMapPageToZeroInHyperSpace (IN PFN_NUMBER PageFrameIndex)
NTSTATUS MiGetWritablePagesInSection (IN PSECTION Section, OUT PULONG WritablePages)
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)
VOID MiAddMappedPtes (IN PMMPTE FirstPte, IN ULONG NumberOfPtes, IN PCONTROL_AREA ControlArea)
VOID MiInitializeIoTrackers (VOID)
PVOID MiMapSinglePage (IN PVOID VirtualAddress OPTIONAL, IN PFN_NUMBER PageFrameIndex, IN MEMORY_CACHING_TYPE CacheType, IN MM_PAGE_PRIORITY Priority)
VOID MiUnmapSinglePage (IN PVOID BaseAddress)
NTSTATUS MiDispatchFault (IN BOOLEAN StoreInstrution, IN PVOID VirtualAdress, IN PMMPTE PointerPte, IN PMMPTE PointerProtoPte, IN PEPROCESS Process, OUT PLOGICAL ApcNeeded)
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, OUT PLOGICAL ApcNeeded)
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, OUT PLOGICAL ApcNeeded)
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 WSLE_NUMBER WorkingSetIndex)
NTSTATUS MiAccessCheck (IN PMMPTE PointerPte, IN BOOLEAN WriteOperation, IN KPROCESSOR_MODE PreviousMode, IN ULONG Protection, IN BOOLEAN CallerHoldsPfnLock)
NTSTATUS FASTCALL MiCheckForUserStackOverflow (IN PVOID FaultingAddress)
PMMPTE MiCheckVirtualAddress (IN PVOID VirtualAddress, OUT PULONG ProtectCode)
NTSTATUS FASTCALL MiCheckPdeForPagedPool (IN PVOID VirtualAddress)
VOID MiInitializeMustSucceedPool (VOID)
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 ULONG_PTR Vpn, IN PMMADDRESS_NODE *Root)
PMMADDRESS_NODE MiCheckForConflictingNode (IN ULONG_PTR StartVpn, IN ULONG_PTR EndVpn, IN PMMADDRESS_NODE Root)
PVOID MiFindEmptyAddressRangeInTree (IN SIZE_T SizeOfRange, IN ULONG_PTR Alignment, IN PMMADDRESS_NODE Root, OUT PMMADDRESS_NODE *PreviousVad)
PVOID MiFindEmptyAddressRangeDownTree (IN SIZE_T SizeOfRange, IN PVOID HighestAddressToEndAt, IN ULONG_PTR Alignment, IN PMMADDRESS_NODE Root)
VOID NodeTreeWalk (PMMADDRESS_NODE Start)
VOID MiInsertVad (IN PMMVAD Vad)
VOID MiRemoveVad (IN PMMVAD Vad)
PMMVAD FASTCALL MiLocateAddress (IN PVOID Vad)
PVOID MiFindEmptyAddressRange (IN SIZE_T SizeOfRange, IN ULONG_PTR Alignment, IN ULONG QuickCheck)
NTSTATUS MiCloneProcessAddressSpace (IN PEPROCESS ProcessToClone, IN PEPROCESS ProcessToInitialize, IN PFN_NUMBER PdePhysicalPage, IN PFN_NUMBER HyperPhysicalPage)
ULONG MiDecrementCloneBlockReference (IN PMMCLONE_DESCRIPTOR CloneDescriptor, IN PMMCLONE_BLOCK CloneBlock, IN PEPROCESS CurrentProcess)
VOID MiWaitForForkToComplete (IN PEPROCESS CurrentProcess)
WSLE_NUMBER MiLocateAndReserveWsle (IN PMMSUPPORT WsInfo)
VOID MiReleaseWsle (IN WSLE_NUMBER WorkingSetIndex, IN PMMSUPPORT WsInfo)
VOID MiUpdateWsle (IN PWSLE_NUMBER DesiredIndex, IN PVOID VirtualAddress, IN PMMWSL WorkingSetList, IN PMMPFN Pfn)
VOID MiInitializeWorkingSetList (IN PEPROCESS CurrentProcess)
VOID MiGrowWsleHash (IN PMMSUPPORT WsInfo)
ULONG MiTrimWorkingSet (ULONG Reduction, IN PMMSUPPORT WsInfo, IN ULONG ForcedReduction)
VOID MiRemoveWorkingSetPages (IN PMMWSL WorkingSetList, IN PMMSUPPORT WsInfo)
VOID FASTCALL MiInsertWsle (IN WSLE_NUMBER Entry, IN PMMWSL WorkingSetList)
VOID FASTCALL MiRemoveWsle (IN WSLE_NUMBER Entry, IN PMMWSL WorkingSetList)
VOID MiFreeWorkingSetRange (IN PVOID StartVa, IN PVOID EndVa, IN PMMSUPPORT WsInfo)
WSLE_NUMBER FASTCALL MiLocateWsle (IN PVOID VirtualAddress, IN PMMWSL WorkingSetList, IN WSLE_NUMBER WsPfnIndex)
ULONG MiFreeWsle (IN WSLE_NUMBER WorkingSetIndex, IN PMMSUPPORT WsInfo, IN PMMPTE PointerPte)
VOID MiSwapWslEntries (IN WSLE_NUMBER SwapEntry, IN WSLE_NUMBER 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)
PFN_NUMBER MiDeleteSystemPagableVm (IN PMMPTE PointerPte, IN PFN_NUMBER NumberOfPtes, IN MMPTE NewPteValue, IN LOGICAL SessionAllocation, OUT PPFN_NUMBER ResidentPages OPTIONAL)
VOID MiLockCode (IN PMMPTE FirstPte, IN PMMPTE LastPte, IN ULONG LockType)
PLDR_DATA_TABLE_ENTRY MiLookupDataTableEntry (IN PVOID AddressWithinSection, IN ULONG ResourceHeld)
VOID MiFlushTb (VOID)
VOID MiObtainFreePages (VOID)
VOID MiModifiedPageWriter (IN PVOID StartContext)
VOID MiMappedPageWriter (IN PVOID StartContext)
LOGICAL MiIssuePageExtendRequest (IN PMMPAGE_FILE_EXPANSION PageExtend)
VOID MiIssuePageExtendRequestNoWait (IN PFN_NUMBER SizeInPages)
SIZE_T MiExtendPagingFiles (IN PMMPAGE_FILE_EXPANSION PageExpand)
VOID MiContractPagingFiles (VOID)
VOID MiAttemptPageFileReduction (VOID)
LOGICAL MiCancelWriteOfMappedPfn (IN PFN_NUMBER PageToStop)
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 MiDeletePageTablesForPhysicalRange (IN PVOID StartingAddress, IN PVOID EndingAddress)
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)
VOID MiRemoveUserPhysicalPagesVad (IN PMMVAD_SHORT FoundVad)
VOID MiCleanPhysicalProcessPages (IN PEPROCESS Process)
VOID MiPhysicalViewRemover (IN PEPROCESS Process, IN PMMVAD Vad)
VOID MiPhysicalViewAdjuster (IN PEPROCESS Process, IN PMMVAD OldVad, IN PMMVAD NewVad)
ULONG MiDoesPdeExistAndMakeValid (IN PMMPTE PointerPde, IN PEPROCESS TargetProcess, IN ULONG PfnMutexHeld, OUT PULONG Waited)
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 MiMakeSystemAddressValidPfnSystemWs (IN PVOID VirtualAddress)
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 ULONG_PTR Vpn)
PSUBSECTION FASTCALL MiLocateSubsection (IN PMMVAD Vad, IN ULONG_PTR Vpn)
VOID MiInitializeSystemCache (IN ULONG MinimumWorkingSet, IN ULONG MaximumWorkingSet)
VOID MiAdjustWorkingSetManagerParameters (BOOLEAN WorkStation)
VOID FASTCALL MiInsertBasedSection (IN PSECTION Section)
NTSTATUS MiMapViewOfPhysicalSection (IN PCONTROL_AREA ControlArea, IN PEPROCESS Process, IN PVOID *CapturedBase, IN PLARGE_INTEGER SectionOffset, IN PSIZE_T CapturedViewSize, IN ULONG ProtectionMask, IN ULONG_PTR ZeroBits, IN ULONG AllocationType, IN BOOLEAN WriteCombined, OUT PBOOLEAN ReleasedWsMutex)
VOID MiRemoveImageSectionObject (IN PFILE_OBJECT File, IN PCONTROL_AREA ControlArea)
VOID MiAddSystemPtes (IN PMMPTE StartingPte, IN ULONG NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType)
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 PUINT64 MaximumSize, IN ULONG SectionPageProtection, IN ULONG AllocationAttributes, IN ULONG IgnoreFileSizing)
NTSTATUS MiCreatePagingFileMap (OUT PSEGMENT *Segment, IN PUINT64 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, IN LOGICAL DirtyDataPagesOk)
VOID MiCheckControlArea (IN PCONTROL_AREA ControlArea, IN PEPROCESS CurrentProcess, IN KIRQL PreviousIrql)
LOGICAL MiCheckPurgeAndUpMapCount (IN PCONTROL_AREA ControlArea)
VOID MiCheckForControlAreaDeletion (IN PCONTROL_AREA ControlArea)
BOOLEAN 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 MiCanFileBeTruncatedInternal (IN PSECTION_OBJECT_POINTERS SectionPointer, IN PLARGE_INTEGER NewFileSize OPTIONAL, IN LOGICAL BlockNewViews, OUT PKIRQL PreviousIrql)
NTSTATUS MiFlushSectionInternal (IN PMMPTE StartingPte, IN PMMPTE FinalPte, IN PSUBSECTION FirstSubsection, IN PSUBSECTION LastSubsection, IN ULONG Synchronize, IN LOGICAL WriteInProgressOk, OUT PIO_STATUS_BLOCK IoStatus)
NTSTATUS MiProtectVirtualMemory (IN PEPROCESS Process, IN PVOID *CapturedBase, IN PSIZE_T 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_PTR Size, IN ULONG ProtectionMask)
ULONG MiChangeNoAccessForkPte (IN PMMPTE PointerPte, IN ULONG ProtectionMask)
VOID MiSetImageProtect (IN PSEGMENT Segment, IN ULONG Protection)
ULONG FASTCALL MiChargePageFileQuota (IN SIZE_T QuotaCharge, IN PEPROCESS CurrentProcess)
VOID MiReturnPageFileQuota (IN SIZE_T QuotaCharge, IN PEPROCESS CurrentProcess)
LOGICAL FASTCALL MiChargeCommitment (IN SIZE_T QuotaCharge, IN PEPROCESS Process OPTIONAL)
LOGICAL FASTCALL MiChargeCommitmentCantExpand (IN SIZE_T QuotaCharge, IN ULONG MustSucceed)
VOID FASTCALL MiReturnCommitment (IN SIZE_T QuotaCharge)
SIZE_T 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)
VOID MiModifiedPageWriterTimerDispatch (IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
LONGLONG MiStartingOffset (IN PSUBSECTION Subsection, IN PMMPTE PteAddress)
LARGE_INTEGER MiEndingOffset (IN PSUBSECTION Subsection)
VOID MiReloadBootLoadedDrivers (IN PLOADER_PARAMETER_BLOCK LoaderBlock)
LOGICAL MiInitializeLoadedModuleList (IN PLOADER_PARAMETER_BLOCK LoaderBlock)
VOID MiEnableRandomSpecialPool (IN LOGICAL Enable)
LOGICAL MiTriageSystem (IN PLOADER_PARAMETER_BLOCK LoaderBlock)
LOGICAL MiTriageAddDrivers (IN PLOADER_PARAMETER_BLOCK LoaderBlock)
LOGICAL MiTriageVerifyDriver (IN PLDR_DATA_TABLE_ENTRY DataTableEntry)
LOGICAL MiInitializeDriverVerifierList (IN PLOADER_PARAMETER_BLOCK LoaderBlock)
LOGICAL MiApplyDriverVerifier (IN PLDR_DATA_TABLE_ENTRY, IN PMI_VERIFIER_DRIVER_ENTRY Verifier)
VOID MiVerifyingDriverUnloading (IN PLDR_DATA_TABLE_ENTRY DataTableEntry)
VOID MiVerifierCheckThunks (IN PLDR_DATA_TABLE_ENTRY DataTableEntry)
VOID MiEnableKernelVerifier (VOID)
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)
NTSTATUS MiSessionCommitPageTables (PVOID StartVa, PVOID EndVa)
NTSTATUS MiInitializeSessionPool (VOID)
VOID MiCheckSessionPoolAllocations (VOID)
VOID MiFreeSessionPoolBitMaps (VOID)
VOID MiDetachSession (VOID)
VOID MiAttachSession (IN PMM_SESSION_SPACE SessionGlobal)
NTSTATUS MiEmptyWorkingSet (IN PMMSUPPORT WsInfo, IN LOGICAL WaitOk)
NTSTATUS FASTCALL MiCheckPdeForSessionSpace (IN PVOID VirtualAddress)
NTSTATUS MiShareSessionImage (IN PSECTION Section, IN OUT PSIZE_T ViewSize)
VOID MiSessionWideInitializeAddresses (VOID)
NTSTATUS MiSessionWideReserveImageAddress (IN PUNICODE_STRING pImageName, IN PSECTION Section, IN ULONG_PTR Alignment, OUT PVOID *ppAddr, OUT PBOOLEAN pAlreadyLoaded)
VOID MiInitializeSessionIds (VOID)
VOID MiInitializeSessionWsSupport (VOID)
VOID MiSessionAddProcess (IN PEPROCESS NewProcess)
VOID MiSessionRemoveProcess (VOID)
NTSTATUS MiRemovePsLoadedModule (PLDR_DATA_TABLE_ENTRY DataTableEntry)
NTSTATUS MiRemoveImageSessionWide (IN PVOID BaseAddr)
NTSTATUS MiDeleteSessionVirtualAddresses (IN PVOID VirtualAddress, IN SIZE_T NumberOfBytes)
NTSTATUS MiUnloadSessionImageByForce (IN SIZE_T NumberOfPtes, IN PVOID ImageBase)
NTSTATUS MiSessionWideGetImageSize (IN PVOID BaseAddress, OUT PSIZE_T NumberOfBytes OPTIONAL, OUT PSIZE_T CommitPages OPTIONAL)
PIMAGE_ENTRY_IN_SESSION MiSessionLookupImage (IN PVOID BaseAddress)
NTSTATUS MiSessionCommitImagePages (PVOID BaseAddr, SIZE_T Size)
VOID MiSessionUnloadAllImages (VOID)
VOID MiFreeSessionSpaceMap (VOID)
NTSTATUS MiSessionInitializeWorkingSetList (VOID)
VOID MiSessionUnlinkWorkingSet (VOID)
NTSTATUS MiSessionCopyOnWrite (IN PMM_SESSION_SPACE SessionSpace, IN PVOID FaultingAddress, IN PMMPTE PointerPte)
VOID MiSessionOutSwapProcess (IN PEPROCESS Process)
VOID MiSessionInSwapProcess (IN PEPROCESS Process)

Variables

ULONG MmProtectToValue [32]
ULONG MmProtectToPteMask [32]
ULONG MmMakeProtectNotWriteCopy [32]
ACCESS_MASK MmMakeSectionAccess [8]
ACCESS_MASK MmMakeFileAccess [8]
LARGE_INTEGER MmSevenMinutes
LARGE_INTEGER MmWorkingSetProtectionTime
LARGE_INTEGER MmOneSecond
LARGE_INTEGER MmTwentySeconds
LARGE_INTEGER MmShortTime
LARGE_INTEGER MmHalfSecond
LARGE_INTEGER Mm30Milliseconds
LARGE_INTEGER MmCriticalSectionTimeout
ULONG MmCritsectTimeoutSeconds
PEPROCESS ExpDefaultErrorPortProcess
SIZE_T MmExtendedCommit
PFN_NUMBER MmHiberPages
ULONG MiIoRetryLevel
ULONG MiFaultRetries
ULONG MiUserIoRetryLevel
ULONG MiUserFaultRetries
KMUTANT MmSystemLoadLock
LIST_ENTRY MmLockConflictList
PETHREAD MmSystemLockOwner
LOGICAL MmDynamicPfn
FAST_MUTEX MmDynamicMemoryMutex
PFN_NUMBER MmSystemLockPagesCount
ULONG_PTR MiActiveWriteWatch
MMSESSION MmSession
LOGICAL MmTrackLockedPages
BOOLEAN MiTrackingAborted
LOGICAL MmSnapUnloads
PUNLOADED_DRIVERS MiUnloadedDrivers
PMMINPAGE_SUPPORT MiGetInPageSupportBlock (VOID)
SIZE_T MmPeakCommitment
SIZE_T MmTotalCommitLimitMaximum
WCHAR MmVerifyDriverBuffer []
ULONG MmVerifyDriverBufferLength
ULONG MmVerifyDriverLevel
LOGICAL MmDontVerifyRandomDrivers
LOGICAL MmProtectFreedNonPagedPool
ULONG MmEnforceWriteProtection
LOGICAL MmTrackPtes
ULONG MiActiveVerifierThunks
LIST_ENTRY MiSuspectDriverList
LOGICAL KernelVerifier
MM_DRIVER_VERIFIER_DATA MmVerifierData
ULONG MiSpecialPagesNonPaged
ULONG MiSpecialPagesNonPagedMaximum
ULONG MmLockPagesPercentage
ULONG MmLargePageMinimum
MMPTE ZeroPte
MMPTE ZeroKernelPte
MMPTE ValidKernelPteLocal
MMPTE ValidKernelPte
MMPTE ValidKernelPde
MMPTE ValidKernelPdeLocal
MMPTE ValidUserPte
MMPTE ValidPtePte
MMPTE ValidPdePde
MMPTE DemandZeroPde
MMPTE DemandZeroPte
MMPTE KernelPrototypePte
MMPTE TransitionPde
MMPTE PrototypePte
MMPTE NoAccessPte
ULONG_PTR MmSubsectionBase
ULONG_PTR MmSubsectionTopPage
BOOLEAN MiHydra
ULONG ExpMultiUserTS
PFN_COUNT MmNumberOfPhysicalPages
PFN_NUMBER MmLowestPhysicalPage
PFN_NUMBER MmHighestPhysicalPage
PFN_NUMBER MmHighestPossiblePhysicalPage
PFN_COUNT MmAvailablePages
PFN_NUMBER MmMoreThanEnoughFreePages
SPFN_NUMBER MmResidentAvailablePages
PFN_NUMBER MmPagesAboveWsMinimum
PFN_NUMBER MmPagesAboveWsMaximum
PFN_NUMBER MmPagesAboveWsThreshold
PFN_NUMBER MmWorkingSetSizeIncrement
PFN_NUMBER MmWorkingSetSizeExpansion
PFN_NUMBER MmWsAdjustThreshold
PFN_NUMBER MmWsExpandThreshold
PFN_NUMBER MmWsTrimReductionGoal
ULONG MiDelayPageFaults
PMMPFN MmPfnDatabase
MMPFNLIST MmZeroedPageListHead
MMPFNLIST MmFreePageListHead
MMPFNLIST MmStandbyPageListHead
MMPFNLIST MmModifiedPageListHead
MMPFNLIST MmModifiedNoWritePageListHead
MMPFNLIST MmBadPageListHead
PMMPFNLIST MmPageLocationList [NUMBER_OF_PAGE_LISTS]
MMPFNLIST MmModifiedPageListByColor [MM_MAXIMUM_NUMBER_OF_COLORS]
ULONG MmModNoWriteInsert
KEVENT MmAvailablePagesEvent
KEVENT MmAvailablePagesEventHigh
KEVENT MmZeroingPageEvent
BOOLEAN MmZeroingPageThreadActive
PFN_NUMBER MmMinimumFreePagesToZero
KEVENT MmMappedFileIoComplete
PMMPTE MmFirstReservedMappingPte
PMMPTE MmLastReservedMappingPte
PVOID MmNonPagedSystemStart
PCHAR MmSystemSpaceViewStart
SIZE_T MmSizeOfNonPagedPoolInBytes
SIZE_T MmMinimumNonPagedPoolSize
SIZE_T MmDefaultMaximumNonPagedPool
ULONG MmMinAdditionNonPagedPoolPerMb
ULONG MmMaxAdditionNonPagedPoolPerMb
SIZE_T MmSizeOfPagedPoolInBytes
SIZE_T MmMaximumNonPagedPoolInBytes
PFN_NUMBER MmAllocatedNonPagedPool
PFN_NUMBER MmSizeOfNonPagedMustSucceed
PVOID MmNonPagedPoolExpansionStart
ULONG MmExpandedPoolBitPosition
PFN_NUMBER MmNumberOfFreeNonPagedPool
ULONG MmMustSucceedPoolBitPosition
ULONG MmNumberOfSystemPtes
ULONG MiRequestedSystemPtes
ULONG MmTotalFreeSystemPtes [MaximumPtePoolTypes]
SIZE_T MmLockPagesLimit
PMMPTE MmSystemPagePtes
ULONG MmSystemPageDirectory
PMMPTE MmPagedPoolBasePde
SIZE_T MmHeapSegmentReserve
SIZE_T MmHeapSegmentCommit
SIZE_T MmHeapDeCommitTotalFreeThreshold
SIZE_T MmHeapDeCommitFreeBlockThreshold
LIST_ENTRY MmNonPagedPoolFreeListHead [MI_MAX_FREE_LIST_HEADS]
ULONG MmFlushCounter
PVOID MmNonPagedPoolStart
PVOID MmNonPagedPoolEnd
PVOID MmPagedPoolStart
PVOID MmPagedPoolEnd
PVOID MmNonPagedMustSucceed
MM_PAGED_POOL_INFO MmPagedPoolInfo
PVOID MmPageAlignedPoolBase [2]
PRTL_BITMAP VerifierLargePagedPoolMap
MMPTE MmFirstFreeSystemPte [MaximumPtePoolTypes]
ULONG_PTR MiSystemViewStart
PMMWSL MmSystemCacheWorkingSetList
PMMWSLE MmSystemCacheWsle
PVOID MmSystemCacheStart
PVOID MmSystemCacheEnd
PRTL_BITMAP MmSystemCacheAllocationMap
PRTL_BITMAP MmSystemCacheEndingMap
PFN_NUMBER MmSystemCacheWsMinimum
PFN_NUMBER MmSystemCacheWsMaximum
ULONG MmAliasAlignment
ULONG MmAliasAlignmentOffset
ULONG MmAliasAlignmentMask
ULONG MmNumberDeadKernelStacks
ULONG MmMaximumDeadKernelStacks
PMMPFN MmFirstDeadKernelStack
PMMPTE MmSystemPteBase
PMMWSL MmWorkingSetList
PMMWSLE MmWsle
PMMVAD MmVirtualAddressDescriptorRoot
PMMADDRESS_NODE MmSectionBasedRoot
PVOID MmHighSectionBase
FAST_MUTEX MmSectionCommitMutex
FAST_MUTEX MmSectionBasedMutex
ERESOURCE MmSectionExtendResource
ERESOURCE MmSectionExtendSetResource
KEVENT MmImageMappingPteEvent
ULONG MmDataClusterSize
ULONG MmCodeClusterSize
FAST_MUTEX MmPageFileCreationLock
PKEVENT MmPagingFileCreated
ULONG_PTR MmPagingFileDebug []
KSPIN_LOCK MmPfnLock
ERESOURCE MmSystemWsLock
KSPIN_LOCK MmSystemSpaceLock
KSPIN_LOCK MmChargeCommitmentLock
KSPIN_LOCK MmExpansionLock
MMPTE GlobalPte
ULONG MmSystemPageColor
ULONG MmSecondaryColors
ULONG MmProcessColorSeed
ULONG MmDisablePagingExecutive
MMDEREFERENCE_SEGMENT_HEADER MmDereferenceSegmentHeader
LIST_ENTRY MmUnusedSegmentList
KEVENT MmUnusedSegmentCleanup
SIZE_T MmMaxUnusedSegmentPagedPoolUsage
SIZE_T MmUnusedSegmentPagedPoolUsage
SIZE_T MiUnusedSegmentPagedPoolUsage
SIZE_T MmUnusedSegmentPagedPoolReduction
SIZE_T MmMaxUnusedSegmentNonPagedPoolUsage
SIZE_T MmUnusedSegmentNonPagedPoolUsage
SIZE_T MiUnusedSegmentNonPagedPoolUsage
SIZE_T MmUnusedSegmentNonPagedPoolReduction
ULONG MmUnusedSegmentTrimLevel
ULONG MmUnusedSegmentCount
MMWORKING_SET_EXPANSION_HEAD MmWorkingSetExpansionHead
MMPAGE_FILE_EXPANSION MmAttemptForCantExtend
MMMOD_WRITER_LISTHEAD MmPagingFileHeader
MMMOD_WRITER_LISTHEAD MmMappedFileHeader
PMMPAGING_FILE MmPagingFile [MAX_PAGE_FILES]
PMMMOD_WRITER_MDL_ENTRY MmMappedFileMdl [MM_MAPPED_FILE_MDLS]
LIST_ENTRY MmFreePagingSpaceLow
ULONG MmNumberOfActiveMdlEntries
ULONG MmNumberOfPagingFiles
KEVENT MmModifiedPageWriterEvent
KEVENT MmCollidedFlushEvent
KEVENT MmCollidedLockEvent
SIZE_T MmTotalCommittedPages
SIZE_T MmTotalCommitLimit
SIZE_T MmOverCommit
SIZE_T MmSharedCommit
PFN_NUMBER MmMinimumFreePages
PFN_NUMBER MmFreeGoal
PFN_NUMBER MmModifiedPageMaximum
PFN_NUMBER MmModifiedPageMinimum
ULONG MmModifiedWriteClusterSize
ULONG MmMinimumFreeDiskSpace
ULONG MmPageFileExtension
ULONG MmMinimumPageFileReduction
LARGE_INTEGER MiModifiedPageLife
BOOLEAN MiTimerPending
KEVENT MiMappedPagesTooOldEvent
KDPC MiModifiedPageWriterTimerDpc
KTIMER MiModifiedPageWriterTimer
PFN_NUMBER MmSystemProcessWorkingSetMin
PFN_NUMBER MmSystemProcessWorkingSetMax
PFN_NUMBER MmMinimumWorkingSetSize
PMMPTE MmDebugPte
PMMPTE MmCrashDumpPte
ULONG MiOverCommitCallCount
SIZE_T MmResTrack [MM_BUMP_COUNTER_MAX]
PPAGE_FAULT_NOTIFY_ROUTINE MmPageFaultNotifyRoutine
PHARD_FAULT_NOTIFY_ROUTINE MmHardFaultNotifyRoutine
ULONG_PTR MmSessionBase
ULONG MmSessionFailureCauses [MM_SESSION_FAILURE_CAUSES]
PMM_SESSION_SPACE MmSessionSpace
ULONG MiSessionCount
PMMPTE MiHighestUserPte
PMMPTE MiHighestUserPde
PMMPTE MiSessionBasePte
PMMPTE MiSessionLastPte
LIST_ENTRY MiSessionWsList


Define Documentation

#define _2gb   0x80000000
 

Definition at line 71 of file mi.h.

Referenced by MmInitializeProcessAddressSpace().

#define _4gb   0x100000000
 

Definition at line 72 of file mi.h.

#define ASSERT32 exp   )     ASSERT(exp)
 

Definition at line 58 of file mi.h.

Referenced by MiGrowWsleHash(), and MiUpdateWsle().

#define ASSERT64 exp   ) 
 

Definition at line 59 of file mi.h.

Referenced by MiGrowWsleHash(), MiUnmapLockedPagesInUserSpace(), MmAddPhysicalMemory(), and MmRemovePhysicalMemory().

#define COMMIT_SIZE   19
 

Definition at line 2331 of file mi.h.

#define CONSISTENCY_LOCK_PFN OLDIRQL   ) 
 

Definition at line 875 of file mi.h.

Referenced by MiAddWorkingSetPage(), MiAddWsleHash(), MiInitializeWorkingSetList(), MiMakeSpecialPoolPagable(), MiMapViewOfPhysicalSection(), MiRemoveWorkingSetPages(), MiResolveDemandZeroFault(), MiSessionInitializeWorkingSetList(), MiUpdateWsle(), MmAccessFault(), and MmCreateProcessAddressSpace().

#define CONSISTENCY_LOCK_PFN2 OLDIRQL   ) 
 

Definition at line 878 of file mi.h.

Referenced by MiAllocatePoolPages(), and MiFreePoolPages().

#define CONSISTENCY_UNLOCK_PFN OLDIRQL   ) 
 

Definition at line 876 of file mi.h.

Referenced by MiAddWorkingSetPage(), MiAddWsleHash(), MiGetPageForHeader(), MiInitializeWorkingSetList(), MiMakeSpecialPoolPagable(), MiMapViewOfPhysicalSection(), MiRemoveWorkingSetPages(), MiResolveDemandZeroFault(), MiSessionInitializeWorkingSetList(), MiUpdateWsle(), MmAccessFault(), and MmCreateProcessAddressSpace().

#define CONSISTENCY_UNLOCK_PFN2 OLDIRQL   ) 
 

Definition at line 879 of file mi.h.

Referenced by MiAllocatePoolPages(), and MiFreePoolPages().

#define EndOfAllocation   WriteInProgress
 

Definition at line 1243 of file mi.h.

#define HYDRA_PROCESS   ((PEPROCESS)1)
 

Definition at line 5179 of file mi.h.

Referenced by MiDispatchFault(), MiEnsureAvailablePageOrWait(), MiResolveDemandZeroFault(), MiResolveMappedFileFault(), MiResolvePageFileFault(), MiResolveTransitionFault(), MiSessionCopyOnWrite(), MiWaitForInPageComplete(), and MmAccessFault().

#define LargeSessionAllocation   PrototypePte
 

Definition at line 1245 of file mi.h.

#define LOCK_ADDRESS_SPACE PROCESS   )     ExAcquireFastMutex( &((PROCESS)->AddressCreationLock))
 

Definition at line 1090 of file mi.h.

Referenced by MiCloneProcessAddressSpace(), MiWaitForForkToComplete(), MmMapViewOfSection(), MmSecureVirtualMemory(), MmUnsecureVirtualMemory(), and NtAreMappedFilesTheSame().

#define LOCK_AWE PROCESS,
OldIrql   )     ExAcquireSpinLock(&((PROCESS)->AweLock), &OldIrql)
 

Definition at line 922 of file mi.h.

Referenced by MiMapViewOfPhysicalSection(), MiPhysicalViewAdjuster(), MiPhysicalViewInserter(), MiPhysicalViewRemover(), MiRemoveMappedView(), MiRemoveUserPhysicalPagesVad(), NtAllocateUserPhysicalPages(), NtFreeUserPhysicalPages(), NtMapUserPhysicalPages(), and NtMapUserPhysicalPagesScatter().

#define LOCK_EXPANSION OLDIRQL   ) 
 

Value:

ASSERT (KeGetCurrentIrql() <= APC_LEVEL); \ ExAcquireSpinLock (&MmExpansionLock, &OLDIRQL);\ MM_SET_EXPANSION_OWNER ();

Definition at line 957 of file mi.h.

Referenced by MiCheckAndSetSystemTrimCriteria(), MiCheckSystemTrimEndCriteria(), MiDereferenceSession(), MiEmptyAllWorkingSets(), MiEmptyAllWorkingSetsWorker(), MiLoadImageSection(), MiRearrangeWorkingSetExpansionList(), MiSessionAddProcess(), MiSessionInitializeWorkingSetList(), MiSessionInSwapProcess(), MiSessionOutSwapProcess(), MiSessionRemoveProcess(), MmAllowWorkingSetExpansion(), MmCleanProcessAddressSpace(), MmEnforceWorkingSetLimit(), MmInSwapProcess(), MmOutSwapProcess(), MmSessionCreate(), MmSetMemoryPriorityProcess(), MmTrimAllSystemPagableMemory(), and MmWorkingSetManager().

#define LOCK_EXPANSION_IF_ALPHA OLDIRQL   ) 
 

Definition at line 982 of file mi.h.

Referenced by MiAddWorkingSetPage(), MiDoReplacement(), MiInsertWsle(), MiMakeSpecialPoolPagable(), MiRemoveWorkingSetPages(), MmAccessFault(), and MmCleanProcessAddressSpace().

#define LOCK_HYPERSPACE OLDIRQL   )     ExAcquireSpinLock ( &(PsGetCurrentProcess())->HyperSpaceLock, OLDIRQL );
 

Definition at line 1020 of file mi.h.

Referenced by MiMapPageInHyperSpace().

#define LOCK_PFN OLDIRQL   ) 
 

Value:

ASSERT (KeGetCurrentIrql() <= APC_LEVEL); \ MiLockPfnDatabase(OLDIRQL); \ PFN_CONSISTENCY_SET;

Definition at line 886 of file mi.h.

Referenced by MiAccessCheck(), MiAddWorkingSetPage(), MiAddWsleHash(), MiAllocatePoolPages(), MiAttemptPageFileExtension(), MiAttemptPageFileReduction(), MiBuildForkPageTable(), MiBuildPagedPool(), MiCancelWriteOfMappedPfn(), MiCanFileBeTruncatedInternal(), MiCaptureSystemPte(), MiCheckAndSetSystemTrimCriteria(), MiCheckControlAreaStatus(), MiCheckPageFileMapping(), MiCheckPurgeAndUpMapCount(), MiCleanSection(), MiCopyOnWrite(), MiCreatePageTablesForPhysicalRange(), MiDecommitPages(), MiDecrementCloneBlockReference(), MiDeleteAddressesInWorkingSet(), MiDeleteFreeVm(), MiDeletePageTablesForPhysicalRange(), MiDeleteSystemPagableVm(), MiDeleteVirtualAddresses(), MiDereferenceSession(), MiDispatchFault(), MiDoesPdeExistAndMakeValid(), MiDoneWithThisPageGetAnother(), MiDownPfnReferenceCount(), MiDownShareCountFlushEntireTb(), MiEnablePagingOfDriverAtInit(), MiEnsureAvailablePageOrWait(), MiExtendPagingFileMaximum(), MiFillSystemPageDirectory(), MiFlushAcquire(), MiFlushDataSection(), MiFlushDirtyBitsToPfn(), MiFlushEventCounter(), MiFlushInPageSupportBlock(), MiFlushRelease(), MiFlushSectionInternal(), MiFlushTbAndCapture(), MiFreeInitializationCode(), MiFreeWsle(), MiGatherMappedPages(), MiGatherPagefilePages(), MiGetEventCounter(), MiGetInPageSupportBlock(), MiGetPageForHeader(), MiGetSystemCacheSubsection(), MiGrowWsleHash(), MiHandleForkTransitionPte(), MiInitializeSessionPool(), MiInitializeSpecialPool(), MiInitializeSystemCache(), MiInitializeWorkingSetList(), MiInitMachineDependent(), MiInsertPageFileInList(), MiLoadImageSection(), MiLockCode(), MiMakeOutswappedPageResident(), MiMakePdeExistAndMakeValid(), MiMakeSystemAddressValidPfn(), MiMakeSystemAddressValidPfnSystemWs(), MiMakeSystemAddressValidPfnWs(), MiMapImageHeaderInHyperSpace(), MiMappedPageWriter(), MiMapViewInSystemSpace(), MiMapViewOfDataSection(), MiMapViewOfImageSection(), MiMapViewOfPhysicalSection(), MiModifiedPageWriterWorker(), MiPageFileFull(), MiProcessValidPteList(), MiPurgeImageSection(), MiReleaseModifiedWriter(), MiReloadBootLoadedDrivers(), MiRemoveImageHeaderPage(), MiRemoveMappedPtes(), MiRemoveMappedView(), MiRemovePageFromWorkingSet(), MiRemoveUnusedSegments(), MiRemoveWorkingSetPages(), MiResetVirtualMemory(), MiResolveDemandZeroFault(), MiResolveTransitionFault(), MiSectionDelete(), MiSegmentDelete(), MiSessionCommitImagePages(), MiSessionCommitPageTables(), MiSessionCopyOnWrite(), MiSessionCreateInternal(), MiSessionInitializeWorkingSetList(), MiSetPageModified(), MiSetPagingOfDriver(), MiSetProtectionOnTransitionPte(), MiSetSystemCodeProtection(), MiShareSessionImage(), MiSuperSectionDelete(), MiSwapWslEntries(), MiUnmapImageHeaderInHyperSpace(), MiUnmapLockedPagesInUserSpace(), MiUpCloneProcessRefCount(), MiUpCloneProtoRefCount(), MiUpControlAreaRefs(), MiUpdateImageHeaderPage(), MiUpdateVadPhysicalPages(), MiUpForkPageShareCount(), MiUpPfnReferenceCount(), MiWaitForForkToComplete(), MiWaitForInPageComplete(), MiWriteComplete(), MmAccessFault(), MmAddPhysicalMemory(), MmAdjustWorkingSetSize(), MmAllocateIndependentPages(), MmAllocateNonCachedMemory(), MmAllocatePagesForMdl(), MmCheckCachedPageState(), MmCleanProcessAddressSpace(), MmCopyToCachedPage(), MmCreateKernelStack(), MmCreateProcessAddressSpace(), MmCreateSection(), MmDeleteKernelStack(), MmDeleteProcessAddressSpace(), MmDisableModifiedWriteOfSection(), MmFlushImageSection(), MmFlushSection(), MmFreeLoaderBlock(), MmFreeNonCachedMemory(), MmFreePagesFromMdl(), MmGetPhysicalMemoryRanges(), MmGrowKernelStack(), MmInitializeProcessAddressSpace(), MmInitSystem(), MmInPageKernelStack(), MmInSwapProcess(), MmLockPagedPool(), MmMapUserAddressesToPage(), MmMapViewInSystemCache(), MmOutPageKernelStack(), MmOutSwapProcess(), MmPurgeSection(), MmRemovePhysicalMemory(), MmResetDriverPaging(), MmSetPageProtection(), MmShutdownSystem(), MmTrimAllSystemPagableMemory(), MmUnloadSystemImage(), MmUnlockCachedPage(), MmUnmapViewInSystemCache(), NtAllocateUserPhysicalPages(), and NtCreateSuperSection().

#define LOCK_PFN2 OLDIRQL   ) 
 

Value:

ASSERT (KeGetCurrentIrql() <= DISPATCH_LEVEL); \ MiLockPfnDatabase(OLDIRQL); \ PFN_CONSISTENCY_SET;

Definition at line 901 of file mi.h.

Referenced by MiAddMdlTracker(), MiAllocatePoolPages(), MiAllocateSpecialPool(), MiFindContiguousMemory(), MiFreeMdlTracker(), MiFreeNonPagedPool(), MiLockPagedAddress(), MiMapViewOfPhysicalSection(), MiModifiedPageWriterTimerDispatch(), MiPhysicalViewAdjuster(), MiPhysicalViewInserter(), MiPhysicalViewRemover(), MiProtectSpecialPool(), MiRemoveUserPhysicalPagesVad(), MiUnlockPagedAddress(), MmFreeSpecialPool(), MmGatherMemoryForHibernate(), MmLockPagableSectionByHandle(), MmMapLockedPagesSpecifyCache(), MmProbeAndLockPages(), MmResourcesAvailable(), MmReturnMemoryForHibernate(), MmSetAddressRangeModified(), MmSetSpecialPool(), MmUnlockPagableImageSection(), MmUnlockPagedPool(), MmUnlockPages(), MmUnmapLockedPages(), and NtFreeUserPhysicalPages().

#define LOCK_PFN_WITH_TRY OLDIRQL   ) 
 

Value:

ASSERT (KeGetCurrentIrql() <= APC_LEVEL); \ do { \ } while (MiTryToLockPfnDatabase(OLDIRQL) == FALSE); \ PFN_CONSISTENCY_SET;

Definition at line 890 of file mi.h.

Referenced by MmZeroPageThread().

#define LOCK_SESSION OLDIRQL   ) 
 

Value:

ExAcquireSpinLock (&((SESSION_GLOBAL(MmSessionSpace))->SpinLock), &OLDIRQL); \ MM_SET_SESSION_LOCK_OWNER ();

Definition at line 5632 of file mi.h.

Referenced by MiDereferenceSession(), and MiSessionAddProcess().

#define LOCK_SESSION_SPACE_WS OLDIRQL   ) 
 

Value:

ASSERT (KeGetCurrentIrql() <= APC_LEVEL); \ KeRaiseIrql(APC_LEVEL,&OLDIRQL); \ ExAcquireResourceExclusive(&MmSessionSpace->WsLock, TRUE); \ MM_SET_SESSION_RESOURCE_OWNER ();

Definition at line 5688 of file mi.h.

Referenced by MiAllocatePoolPages(), MiDeleteSystemPagableVm(), MiDispatchFault(), MiEmptyWorkingSet(), MiEnsureAvailablePageOrWait(), MiFreePoolPages(), MiLoadImageSection(), MiMakeSystemAddressValidPfnSystemWs(), MiMapViewInSystemSpace(), MiSessionCommitImagePages(), MiSessionInsertImage(), MiSessionLookupImage(), MiSessionRemoveImage(), MiSetPagingOfDriver(), MiShareSessionImage(), MiUnmapViewInSystemSpace(), MiWaitForInPageComplete(), MmAccessFault(), and MmUnloadSystemImage().

#define LOCK_SYSTEM_VIEW_SPACE _Session   )     ExAcquireFastMutex (_Session->SystemSpaceViewLockPointer)
 

Definition at line 2644 of file mi.h.

Referenced by MiFreeSessionSpaceMap(), MiInsertInSystemSpace(), MiMapViewInSystemSpace(), and MiUnmapViewInSystemSpace().

#define LOCK_SYSTEM_WS OLDIRQL   ) 
 

Value:

ASSERT (KeGetCurrentIrql() <= APC_LEVEL); \ KeRaiseIrql(APC_LEVEL,&OLDIRQL); \ ExAcquireResourceExclusive(&MmSystemWsLock,TRUE); \ ASSERT (MmSystemLockOwner == NULL); \ MmSystemLockOwner = PsGetCurrentThread();

Definition at line 998 of file mi.h.

Referenced by MiDeleteSystemPagableVm(), MiDispatchFault(), MiEmptyWorkingSet(), MiEnablePagingOfDriverAtInit(), MiEnsureAvailablePageOrWait(), MiInitializeSystemCache(), MiMakeSpecialPoolPagable(), MiMakeSystemAddressValidPfnSystemWs(), MiProtectSpecialPool(), MiRemoveMappedPtes(), MiSetPagingOfDriver(), MiWaitForInPageComplete(), MmAccessFault(), MmAdjustWorkingSetSize(), MmCheckCachedPageState(), MmCopyToCachedPage(), MmEnforceWorkingSetLimit(), MmLockPagableSectionByHandle(), MmLockPagedPool(), MmResetDriverPaging(), and MmUnmapViewInSystemCache().

#define LOCK_WS PROCESS   ) 
 

Value:

ASSERT (MI_NOT_WS_OWNER(PROCESS)); \ ExAcquireFastMutex( &((PROCESS)->WorkingSetLock)); \ ASSERT (!MI_IS_WS_UNSAFE(PROCESS));

Definition at line 1039 of file mi.h.

Referenced by MiChargeCommitment(), MiCloneProcessAddressSpace(), MiEmptyWorkingSet(), MiGetWorkingSetInfo(), MiMapViewOfPhysicalSection(), MiWaitForInPageComplete(), MmAccessFault(), MmAdjustWorkingSetSize(), MmCreateProcessAddressSpace(), MmEnforceWorkingSetLimit(), MmFlushVirtualMemory(), MmSetMemoryPriorityProcess(), NtAllocateUserPhysicalPages(), and NtFreeUserPhysicalPages().

#define LOCK_WS_AND_ADDRESS_SPACE PROCESS   ) 
 

Value:

LOCK_ADDRESS_SPACE(PROCESS); \ LOCK_WS_UNSAFE(PROCESS);

Definition at line 1093 of file mi.h.

Referenced by MiCreatePebOrTeb(), MiMapLockedPagesInUserSpace(), MiProtectVirtualMemory(), MiUnmapLockedPagesInUserSpace(), MmAssignProcessToJob(), MmCleanProcessAddressSpace(), MmDeleteTeb(), MmFlushVirtualMemory(), MmMapUserAddressesToPage(), MmSetBankedSection(), MmUnmapViewOfSection(), NtAllocateVirtualMemory(), NtFreeVirtualMemory(), NtLockVirtualMemory(), NtQueryVirtualMemory(), and NtUnlockVirtualMemory().

#define LOCK_WS_REGARDLESS PROCESS,
WSHELDSAFE   ) 
 

Value:

if (WSHELDSAFE == TRUE) { \ LOCK_WS (PROCESS); \ } \ else { \ LOCK_WS_UNSAFE (PROCESS); \ }

Definition at line 1120 of file mi.h.

Referenced by MiChargeCommitment(), MiDecrementCloneBlockReference(), MiEnsureAvailablePageOrWait(), MiMakeSystemAddressValid(), MiMakeSystemAddressValidPfnWs(), and MiWaitForForkToComplete().

#define LOCK_WS_UNSAFE PROCESS   ) 
 

Value:

ASSERT (MI_NOT_WS_OWNER(PROCESS)); \ ASSERT (KeGetCurrentIrql() == APC_LEVEL); \ ExAcquireFastMutexUnsafe( &((PROCESS)->WorkingSetLock));\ (PROCESS)->WorkingSetLock.OldIrql = MI_MUTEX_ACQUIRED_UNSAFE;

Definition at line 1044 of file mi.h.

Referenced by MiChargeCommitment(), MiCheckControlArea(), MiMapViewOfDataSection(), MiMapViewOfImageSection(), MiMapViewOfPhysicalSection(), MiProtectVirtualMemory(), MiSetProtectionOnSection(), MmSecureVirtualMemory(), MmUnmapViewOfSection(), NtAllocateVirtualMemory(), and NtLockVirtualMemory().

#define Mi4KStartForSubsection address,
subsection   ) 
 

Value:

subsection->StartingSector = ((PLARGE_INTEGER)address)->LowPart; \ subsection->u.SubsectionFlags.StartingSector4132 = \ (((PLARGE_INTEGER)(address))->HighPart & 0x3ff);

Definition at line 2161 of file mi.h.

Referenced by MiCreateDataFileMap(), and MmExtendSection().

#define Mi4KStartFromSubsection address,
subsection   ) 
 

Value:

((PLARGE_INTEGER)address)->LowPart = subsection->StartingSector; \ ((PLARGE_INTEGER)address)->HighPart = subsection->u.SubsectionFlags.StartingSector4132;

Definition at line 2190 of file mi.h.

Referenced by MiEndingOffset(), MiStartingOffset(), and MmExtendSection().

#define MI_64K_ALIGN VA   )     ((PVOID)((ULONG_PTR)(VA) & ~((LONG)X64K - 1)))
 

Definition at line 360 of file mi.h.

Referenced by MiInsertInSystemSpace(), MiMapViewOfImageSection(), MiMapViewOfPhysicalSection(), and NtAllocateVirtualMemory().

#define MI_ADD_LOCKED_PAGE_CHARGE Pfn,
CallerId   ) 
 

Value:

ASSERT (Pfn->u3.e2.ReferenceCount != 0); \ if (Pfn->u3.e2.ReferenceCount == 1) { \ if (Pfn->u2.ShareCount != 0) { \ ASSERT (Pfn->u3.e1.PageLocation == ActiveAndValid); \ MI_MARK_PFN_AS_LOCK_CHARGED(Pfn, CallerId); \ MmSystemLockPagesCount += 1; \ } \ else { \ ASSERT (Pfn->u3.e1.LockCharged == 1); \ } \ }

Definition at line 1417 of file mi.h.

Referenced by MiFlushSectionInternal(), MiLockCode(), MiLockPagedAddress(), MiSetSystemCodeProtection(), MmAccessFault(), MmCopyToCachedPage(), and MmProbeAndLockPages().

#define MI_ADD_LOCKED_PAGE_CHARGE_FOR_MODIFIED_PAGE Pfn,
CallerId   ) 
 

Value:

ASSERT (Pfn->u3.e1.PageLocation != ActiveAndValid); \ ASSERT (Pfn->u2.ShareCount == 0); \ if (Pfn->u3.e2.ReferenceCount == 0) { \ MI_MARK_PFN_AS_LOCK_CHARGED(Pfn, CallerId); \ MmSystemLockPagesCount += 1; \ }

Definition at line 1430 of file mi.h.

Referenced by MiCleanSection(), MiFlushSectionInternal(), MiGatherMappedPages(), MiGatherPagefilePages(), MiInitializeReadInProgressPfn(), MiResolveTransitionFault(), MmCopyToCachedPage(), and MmShutdownSystem().

#define MI_ADD_LOCKED_PAGE_CHARGE_FOR_TRANSITION_PAGE Pfn,
CallerId   ) 
 

Value:

ASSERT (Pfn->u3.e1.PageLocation == ActiveAndValid); \ ASSERT (Pfn->u2.ShareCount == 0); \ ASSERT (Pfn->u3.e2.ReferenceCount != 0); \ if (Pfn->u3.e2.ReferenceCount == 1) { \ MI_MARK_PFN_AS_LOCK_CHARGED(Pfn, CallerId); \ MmSystemLockPagesCount += 1; \ }

Definition at line 1438 of file mi.h.

#define MI_ALIGN_TO_SIZE VA,
ALIGNMENT   )     ((PVOID)((ULONG_PTR)(VA) & ~((ULONG_PTR) ALIGNMENT - 1)))
 

Definition at line 389 of file mi.h.

Referenced by MiFindEmptyAddressRangeDownTree(), and MiMapViewOfDataSection().

#define MI_BACKGROUND_CLAIM_AVAILABLE_SHIFT   1
 

Definition at line 1704 of file mi.h.

Referenced by MiDetermineWsTrimAmount(), and MiDoReplacement().

#define MI_CALC_NEXT_ESTIMATION_SLOT_CONST NextEstimationSlotConst,
WorkingSetList   )     (NextEstimationSlotConst).Stride = 1 << MiEstimationShift;
 

Definition at line 1752 of file mi.h.

#define MI_CALCULATE_USAGE_ESTIMATE SampledAgeCounts   ) 
 

Value:

(((SampledAgeCounts)[1] + \ (SampledAgeCounts)[2] + (SampledAgeCounts)[3]) \ << MiEstimationShift)

Definition at line 1839 of file mi.h.

#define MI_CAPTURE_USED_PAGETABLE_ENTRIES PFN   ) 
 

Definition at line 1348 of file mi.h.

Referenced by MiRestoreTransitionPte().

#define MI_CHECK_BIT ARRAY,
BIT   )     (((ULONG)ARRAY[(BIT) / (sizeof(ULONG)*8)] >> ((BIT) & 0x1F)) & 1)
 

Definition at line 1157 of file mi.h.

Referenced by MiInsertVad(), and MiReturnPageTablePageCommitment().

#define MI_CLEAR_BIT ARRAY,
BIT   )     (ULONG)ARRAY[(BIT) / (sizeof(ULONG)*8)] &= ~(1 << ((BIT) & 0x1F))
 

Definition at line 1215 of file mi.h.

Referenced by MiReturnPageTablePageCommitment().

#define MI_CONVERT_FROM_PTE_PROTECTION PROTECTION_MASK   )     (MmProtectToValue[PROTECTION_MASK])
 

Definition at line 274 of file mi.h.

Referenced by MiGetPageProtection(), MiProtectVirtualMemory(), MiQueryAddressState(), MiSetProtectionOnSection(), and NtQueryVirtualMemory().

#define MI_DECREMENT_USED_PTES_BY_HANDLE PDSHORT   ) 
 

Value:

((*(PUSHORT)(PDSHORT)) -= 1); \ ASSERT (((*(PUSHORT)(PDSHORT)) < PTE_PER_PAGE))

Definition at line 1362 of file mi.h.

Referenced by MiDeletePageTablesForPhysicalRange(), MiDeleteVirtualAddresses(), MiRemoveMappedView(), and MiUnmapLockedPagesInUserSpace().

#define MI_EXTEND_ANY_PAGEFILE   ((ULONG)-1)
 

Definition at line 2219 of file mi.h.

Referenced by MiChargeCommitment(), MiExtendPagingFiles(), and MmInitSystem().

#define MI_FILESYSTEM_NONPAGED_POOL_CHARGE   150
 

Definition at line 4971 of file mi.h.

#define MI_FILESYSTEM_PAGED_POOL_CHARGE   1024
 

Definition at line 4973 of file mi.h.

#define MI_FLUSH_SESSION_TB OLDIRQL   ) 
 

Value:

KeRaiseIrql (DISPATCH_LEVEL, &OLDIRQL); \ KeFlushEntireTb (TRUE, TRUE); \ KeLowerIrql (OLDIRQL);

Definition at line 5617 of file mi.h.

Referenced by MiDereferenceSession(), and MiDetachSession().

#define MI_FOREGROUND_CLAIM_AVAILABLE_SHIFT   3
 

Definition at line 1698 of file mi.h.

Referenced by MiDetermineWsTrimAmount(), and MiDoReplacement().

#define MI_FREED_SPECIAL_POOL_SIGNATURE   0x98764321
 

Definition at line 4225 of file mi.h.

Referenced by MmFreeSpecialPool().

#define MI_GET_DIRECTORY_FRAME_FROM_PROCESS _Process   )     MI_GET_PAGE_FRAME_FROM_PTE((PMMPTE)(&((_Process)->Pcb.DirectoryTableBase[0])))
 

Definition at line 5898 of file mi.h.

Referenced by MiSessionInSwapProcess(), MiSessionOutSwapProcess(), and MmDeleteProcessAddressSpace().

#define MI_GET_PROTECTION_FROM_VAD _Vad   )     ((ULONG)(_Vad)->u.VadFlags.Protection)
 

Definition at line 2423 of file mi.h.

Referenced by MiCheckVirtualAddress().

#define MI_GET_PROTECTION_FROM_WSLE Wsl   )     ((Wsl)->u1.e1.Protection)
 

Definition at line 1589 of file mi.h.

Referenced by MiCloneProcessAddressSpace(), and MiEliminateWorkingSetEntry().

#define MI_GET_USED_PTES_FROM_HANDLE PDSHORT   )     ((ULONG)(*(PUSHORT)(PDSHORT)))
 

Definition at line 1357 of file mi.h.

Referenced by MiDeletePageTablesForPhysicalRange(), MiDeleteVirtualAddresses(), MiMapViewOfPhysicalSection(), MiRemoveMappedView(), and MiUnmapLockedPagesInUserSpace().

#define MI_GET_USED_PTES_HANDLE VA   )     ((PVOID)&MmWorkingSetList->UsedPageTableEntries[MiGetPpePdeOffset(VA)])
 

Definition at line 1355 of file mi.h.

Referenced by MiCreatePageTablesForPhysicalRange(), MiDecommitPages(), MiDeletePageTablesForPhysicalRange(), MiDeleteVirtualAddresses(), MiMapLockedPagesInUserSpace(), MiMapViewOfPhysicalSection(), MiProtectVirtualMemory(), MiRemoveMappedView(), MiSetProtectionOnSection(), MiUnmapLockedPagesInUserSpace(), MmAccessFault(), and NtAllocateVirtualMemory().

#define MI_GET_WSLE_AGE PointerPte,
Wsle   )     ((Wsle)->u1.e1.Age)
 

Definition at line 1892 of file mi.h.

Referenced by MiTrimWorkingSet().

#define MI_IMMEDIATE_REPLACEMENT_AGE   2
 

Definition at line 1675 of file mi.h.

#define MI_INC_WSLE_AGE PointerPte,
Wsle   ) 
 

Value:

if ((Wsle)->u1.e1.Age < 3) { \ (Wsle)->u1.e1.Age += 1; \ }

Definition at line 1919 of file mi.h.

#define MI_INCREMENT_USED_PTES_BY_HANDLE PDSHORT   ) 
 

Value:

((*(PUSHORT)(PDSHORT)) += 1); \ ASSERT (((*(PUSHORT)(PDSHORT)) <= PTE_PER_PAGE))

Definition at line 1359 of file mi.h.

Referenced by MiCloneProcessAddressSpace(), MiCreatePageTablesForPhysicalRange(), MiDecommitPages(), MiMapLockedPagesInUserSpace(), MiMapViewOfPhysicalSection(), MiProtectVirtualMemory(), MiSetProtectionOnSection(), MmAccessFault(), and NtAllocateVirtualMemory().

#define MI_INITIALIZE_ZERO_MDL MDL   ) 
 

Value:

{ \ MDL->Next = (PMDL) NULL; \ MDL->MdlFlags = 0; \ MDL->StartVa = NULL; \ MDL->ByteOffset = 0; \ MDL->ByteCount = 0; \ }

Definition at line 2510 of file mi.h.

Referenced by MiCleanSection(), and MiFlushSectionInternal().

#define MI_INSERT_USED_PAGETABLE_ENTRIES_IN_PFN PFN,
INPAGE_SUPPORT   ) 
 

Definition at line 1353 of file mi.h.

Referenced by MiWaitForInPageComplete().

#define MI_IS_PTE_PROTECTION_COPY_WRITE PROTECTION_MASK   )     (((PROTECTION_MASK) & MM_COPY_ON_WRITE_MASK) == MM_COPY_ON_WRITE_MASK)
 

Definition at line 280 of file mi.h.

Referenced by MiMapViewOfDataSection(), MiSetProtectionOnSection(), and NtAllocateVirtualMemory().

#define MI_IS_SESSION_ADDRESS _VirtualAddress   )     (MiHydra == TRUE && (PVOID)(_VirtualAddress) >= (PVOID)MmSessionBase && (PVOID)(_VirtualAddress) < (PVOID)(MI_SESSION_SPACE_END))
 

Definition at line 5293 of file mi.h.

Referenced by MiAddValidPageToWorkingSet(), MiCheckPdeForPagedPool(), MiCheckPdeForSessionSpace(), MiCheckVirtualAddress(), MiDispatchFault(), MiFreeWsle(), MiLoadSystemImage(), MiSetSystemCodeProtection(), MiUpdateWsle(), MiWriteProtectSystemImage(), MmAccessFault(), MmFlushVirtualMemory(), MmFreeDriverInitialization(), and MmIsHydraAddress().

#define MI_IS_SESSION_IMAGE_ADDRESS VirtualAddress   )     (MiHydra == TRUE && (PVOID)(VirtualAddress) >= (PVOID)MI_SESSION_IMAGE_START && (PVOID)(VirtualAddress) < (PVOID)(MI_SESSION_IMAGE_START + MI_SESSION_IMAGE_SIZE))
 

Definition at line 5287 of file mi.h.

Referenced by MiCompleteProtoPteFault(), MiEliminateWorkingSetEntry(), MiLockCode(), MiMakeSystemAddressValidPfnSystemWs(), MmAccessFault(), MmPageEntireDriver(), and MmUnloadSystemImage().

#define MI_IS_SESSION_POOL_ADDRESS VirtualAddress   )     (MiHydra == TRUE && (PVOID)(VirtualAddress) >= (PVOID)MI_SESSION_POOL && (PVOID)(VirtualAddress) < (PVOID)(MI_SESSION_POOL + MI_SESSION_POOL_SIZE))
 

Definition at line 5290 of file mi.h.

Referenced by MiFreePoolPages(), MiSessionPoolAllocated(), MiSessionPoolFreed(), and MmDeterminePoolType().

#define MI_IS_SESSION_PTE _Pte   )     (MiHydra == TRUE && (PMMPTE)(_Pte) >= MiSessionBasePte && (PMMPTE)(_Pte) < MiSessionLastPte)
 

Definition at line 5296 of file mi.h.

Referenced by MiAddValidPageToWorkingSet(), MiCheckPdeForPagedPool(), MiCheckPdeForSessionSpace(), MiDetermineUserGlobalPteMask(), MiEnablePagingOfDriverAtInit(), and MiRestoreTransitionPte().

#define MI_IS_WS_UNSAFE PROCESS   )     ((PROCESS)->WorkingSetLock.OldIrql == MI_MUTEX_ACQUIRED_UNSAFE)
 

Definition at line 1037 of file mi.h.

#define MI_MAGIC_AWE_PTEFRAME   0xffffedcb
 

Definition at line 1219 of file mi.h.

Referenced by MiDispatchFault(), MiFreePoolPages(), MiRemoveAnyPage(), MiRemovePhysicalPages(), MiRemoveZeroPage(), MiWaitForInPageComplete(), MmAllocatePagesForMdl(), MmCopyToCachedPage(), and MmFreePagesFromMdl().

#define MI_MAKE_PROTECT_NOT_WRITE_COPY PROTECT   )     (MmMakeProtectNotWriteCopy[PROTECT])
 

Definition at line 775 of file mi.h.

Referenced by MiCopyOnWrite(), and MiInitializeCopyOnWritePfn().

#define MI_MARK_PFN_AS_LOCK_CHARGED Pfn,
CallerId   ) 
 

Definition at line 1391 of file mi.h.

#define MI_MASK_TO_PTE PROTECTION_MASK   )     MmProtectToPteMask[PROTECTION_MASK]
 

Definition at line 277 of file mi.h.

#define MI_MAX_FREE_LIST_HEADS   4
 

Definition at line 4688 of file mi.h.

Referenced by MiAllocatePoolPages(), MiFindContiguousMemory(), MiFreePoolPages(), MiInitializeNonPagedPool(), and MmSetKernelDumpRange().

#define MI_MAX_TRIM_PASSES   4
 

Definition at line 1681 of file mi.h.

Referenced by MiCheckSystemTrimEndCriteria().

#define MI_MAXIMUM_SECTION_SIZE   ((UINT64)16*1024*1024*1024*1024*1024 - (1<<MM4K_SHIFT))
 

Definition at line 2127 of file mi.h.

Referenced by MiCreateDataFileMap(), and MmExtendSection().

#define MI_MUST_BE_SAFE PROCESS   ) 
 

Value:

ASSERT (MI_WS_OWNER(PROCESS)); \ ASSERT (!MI_IS_WS_UNSAFE(PROCESS));

Definition at line 1055 of file mi.h.

#define MI_MUST_BE_UNSAFE PROCESS   ) 
 

Value:

ASSERT (KeGetCurrentIrql() == APC_LEVEL); \ ASSERT (MI_WS_OWNER(PROCESS)); \ ASSERT (MI_IS_WS_UNSAFE(PROCESS));

Definition at line 1050 of file mi.h.

#define MI_MUTEX_ACQUIRED_UNSAFE   0x88
 

Definition at line 1035 of file mi.h.

#define MI_NEXT_VALID_AGING_SLOT Previous,
Minimum,
Maximum,
Wsle   ) 
 

Value:

ASSERT(((Previous) >= Minimum) && ((Previous) <= Maximum)); \ do { \ (Previous) += 1; \ if ((Previous) > Maximum) { \ Previous = Minimum; \ } \ } while ((Wsle[Previous].u1.e1.Valid == 0));

Definition at line 1806 of file mi.h.

#define MI_NEXT_VALID_ESTIMATION_SLOT Previous,
StartEntry,
Minimum,
Maximum,
NextEstimationSlotConst,
Wsle   ) 
 

Value:

ASSERT(((Previous) >= Minimum) && ((Previous) <= Maximum)); \ ASSERT(((StartEntry) >= Minimum) && ((StartEntry) <= Maximum)); \ do { \ (Previous) += (NextEstimationSlotConst).Stride; \ if ((Previous) > Maximum) { \ (Previous) = Minimum + ((Previous + 1) & (NextEstimationSlotConst.Stride - 1)); \ StartEntry += 1; \ (Previous) = StartEntry; \ } \ if ((Previous) > Maximum || (Previous) < Minimum) { \ StartEntry = Minimum; \ (Previous) = StartEntry; \ } \ } while (Wsle[Previous].u1.e1.Valid == 0);

Definition at line 1755 of file mi.h.

 
#define MI_NONPAGABLE_MEMORY_AVAILABLE  ) 
 

Value:

Definition at line 4360 of file mi.h.

Referenced by MiCreatePageTablesForPhysicalRange(), MiSessionCommitImagePages(), MiSessionCommitPageTables(), MiSessionCreateInternal(), MiSessionInitializeWorkingSetList(), MmAdjustWorkingSetSize(), MmAllocateIndependentPages(), MmAllocateNonCachedMemory(), MmAllocatePagesForMdl(), MmProbeAndLockPages(), and MmRemovePhysicalMemory().

#define MI_NOT_WS_OWNER PROCESS   )     1
 

Definition at line 1032 of file mi.h.

#define MI_PASS0_TRIM_AGE   2
 

Definition at line 1682 of file mi.h.

Referenced by MiDetermineWsTrimAmount(), and MiDoReplacement().

#define MI_PASS1_TRIM_AGE   1
 

Definition at line 1683 of file mi.h.

Referenced by MiDetermineWsTrimAmount().

#define MI_PASS2_TRIM_AGE   1
 

Definition at line 1684 of file mi.h.

Referenced by MiDetermineWsTrimAmount().

#define MI_PASS3_TRIM_AGE   1
 

Definition at line 1685 of file mi.h.

Referenced by MiDetermineWsTrimAmount().

#define MI_PASS4_TRIM_AGE   0
 

Definition at line 1686 of file mi.h.

Referenced by MiDetermineWsTrimAmount(), and MiDoReplacement().

#define MI_PFN_ELEMENT index   )     (&MmPfnDatabase[index])
 

Definition at line 769 of file mi.h.

Referenced by ExFreePool(), MiAccessCheck(), MiAddWorkingSetPage(), MiAddWsleHash(), MiAllocatePoolPages(), MiBuildForkPageTable(), MiBuildPagedPool(), MiCheckForCrashDump(), MiCheckProtoPtePageState(), MiCleanPhysicalProcessPages(), MiCleanSection(), MiCloneProcessAddressSpace(), MiCompleteProtoPteFault(), MiCopyOnWrite(), MiCreatePageTablesForPhysicalRange(), MiDecommitPages(), MiDecrementCloneBlockReference(), MiDecrementReferenceCount(), MiDecrementShareCount(), MiDeleteAddressesInWorkingSet(), MiDeletePageTablesForPhysicalRange(), MiDeletePte(), MiDeleteSystemPagableVm(), MiDeleteValidAddress(), MiDereferenceSession(), MiDispatchFault(), MiEmptyWorkingSet(), MiEnablePagingOfDriverAtInit(), MiEnsureAvailablePageOrWait(), MiFindContiguousMemory(), MiFlushDirtyBitsToPfn(), MiFlushSectionInternal(), MiFreeInitializationCode(), MiFreeNonPagedPool(), MiFreePoolPages(), MiFreeWsle(), MiGatherMappedPages(), MiGatherPagefilePages(), MiGetPageForHeader(), MiGetPageProtection(), MiGetSubsectionAndProtoFromPte(), MiGetWorkingSetInfo(), MiHandleForkTransitionPte(), MiInitializeCopyOnWritePfn(), MiInitializePfn(), MiInitializePfnForOtherProcess(), MiInitializeReadInProgressPfn(), MiInitializeSessionPool(), MiInitializeTransitionPfn(), MiInitializeWorkingSetList(), MiInitMachineDependent(), MiInsertFrontModifiedNoWrite(), MiInsertPageInList(), MiInsertStandbyListAtFront(), MiLoadImageSection(), MiLockCode(), MiLockPagedAddress(), MiMakeOutswappedPageResident(), MiMakeSpecialPoolPagable(), MiMapLockedPagesInUserSpace(), MiMapPageInHyperSpace(), MiMapViewOfPhysicalSection(), MiModifiedPageWriterWorker(), MiProcessValidPteList(), MiProtectSpecialPool(), MiProtectVirtualMemory(), MiPurgeImageSection(), MiReloadBootLoadedDrivers(), MiRemoveAnyPage(), MiRemoveMappedPtes(), MiRemovePageByColor(), MiRemovePageFromList(), MiRemovePageFromWorkingSet(), MiRemovePhysicalPages(), MiRemoveUserPhysicalPagesVad(), MiRemoveWorkingSetPages(), MiRemoveZeroPage(), MiResetVirtualMemory(), MiResolveDemandZeroFault(), MiResolveMappedFileFault(), MiResolvePageFileFault(), MiResolveProtoPteFault(), MiResolveTransitionFault(), MiRestoreTransitionPte(), MiSegmentDelete(), MiSessionCommitImagePages(), MiSessionCommitPageTables(), MiSessionCopyOnWrite(), MiSessionCreateInternal(), MiSessionDeletePde(), MiSessionInitializeWorkingSetList(), MiSetDirtyBit(), MiSetPageModified(), MiSetPagingOfDriver(), MiSetProtectionOnSection(), MiSetProtectionOnTransitionPte(), MiSetSystemCodeProtection(), MiSwapWslEntries(), MiUnlinkFreeOrZeroedPage(), MiUnlinkPageFromList(), MiUnlockPagedAddress(), MiUpPfnReferenceCount(), MiWaitForInPageComplete(), MiWriteComplete(), MmAccessFault(), MmAddPhysicalMemory(), MmAllocatePagesForMdl(), MmCheckCachedPageState(), MmCleanProcessAddressSpace(), MmCopyToCachedPage(), MmCreateProcessAddressSpace(), MmDbgTranslatePhysicalAddress(), MmDbgTranslatePhysicalAddress64(), MmDeleteKernelStack(), MmDeleteProcessAddressSpace(), MmFreeLoaderBlock(), MmFreeNonCachedMemory(), MmFreePagesFromMdl(), MmFreeSpecialPool(), MmGatherMemoryForHibernate(), MmGetVirtualForPhysical(), MmInitSystem(), MmInSwapProcess(), MmMapLockedPagesSpecifyCache(), MmOutPageKernelStack(), MmOutSwapProcess(), MmProbeAndLockPages(), MmPurgeSection(), MmRemovePhysicalMemory(), MmSetAddressRangeModified(), MmShutdownSystem(), MmTrimAllSystemPagableMemory(), MmUnlockCachedPage(), MmUnlockPagableImageSection(), MmUnlockPagedPool(), MmUnlockPages(), MmUnmapLockedPages(), MmUnmapViewInSystemCache(), MmZeroPageThread(), NtAllocateUserPhysicalPages(), NtFreeUserPhysicalPages(), NtLockVirtualMemory(), NtMapUserPhysicalPages(), NtMapUserPhysicalPagesScatter(), and NtUnlockVirtualMemory().

#define MI_PFN_IS_AWE Pfn1   ) 
 

Value:

((Pfn1->u2.ShareCount <= 3) && \ (Pfn1->u3.e1.PageLocation == ActiveAndValid) && \ (Pfn1->u3.e1.VerifierAllocation == 0) && \ (Pfn1->u3.e1.LargeSessionAllocation == 0) && \ (Pfn1->u3.e1.StartOfAllocation == 1) && \ (Pfn1->u3.e1.EndOfAllocation == 1) && \ (Pfn1->PteFrame == MI_MAGIC_AWE_PTEFRAME))

Definition at line 1221 of file mi.h.

Referenced by MiCleanPhysicalProcessPages(), MiRemoveUserPhysicalPagesVad(), MmFreePagesFromMdl(), NtAllocateUserPhysicalPages(), NtFreeUserPhysicalPages(), NtMapUserPhysicalPages(), and NtMapUserPhysicalPagesScatter().

#define MI_PHYSICAL_VIEW_KEY   'vpmM'
 

Definition at line 2433 of file mi.h.

Referenced by MiMapLockedPagesInUserSpace(), MiMapViewOfPhysicalSection(), and NtAllocateVirtualMemory().

#define MI_REMOVE_LOCKED_PAGE_CHARGE Pfn,
CallerId   ) 
 

Definition at line 1470 of file mi.h.

Referenced by MiCleanSection(), MiDispatchFault(), MiFlushSectionInternal(), MiLockCode(), MiResolveTransitionFault(), MiSetSystemCodeProtection(), MiUnlockPagedAddress(), MiWriteComplete(), MmAccessFault(), MmCopyToCachedPage(), MmShutdownSystem(), MmUnlockCachedPage(), MmUnlockPagableImageSection(), MmUnlockPagedPool(), and MmUnlockPages().

#define MI_REPLACEMENT_CLAIM_THRESHOLD_SHIFT   3
 

Definition at line 1661 of file mi.h.

#define MI_REPLACEMENT_EAVAIL_THRESHOLD_SHIFT   3
 

Definition at line 1668 of file mi.h.

#define MI_REPLACEMENT_FREE_GROWTH_SHIFT   5
 

Definition at line 1654 of file mi.h.

#define MI_RESET_WSLE_AGE PointerPte,
Wsle   )     (Wsle)->u1.e1.Age = 0;
 

Definition at line 1867 of file mi.h.

#define MI_RETRIEVE_USED_PAGETABLE_ENTRIES_FROM_PTE RBL,
PTE   ) 
 

Definition at line 1349 of file mi.h.

Referenced by MiResolvePageFileFault().

#define MI_ROUND_TO_64K LENGTH   )     (((LENGTH) + X64K - 1) & ~(X64K - 1))
 

Definition at line 306 of file mi.h.

#define MI_ROUND_TO_SIZE LENGTH,
ALIGNMENT   )     (((LENGTH) + ((ALIGNMENT) - 1)) & ~((ALIGNMENT) - 1))
 

Definition at line 334 of file mi.h.

Referenced by MiCreateImageFileMap(), MiFindEmptyAddressRange(), MiFindEmptyAddressRangeDownTree(), MiFindEmptyAddressRangeInTree(), MiGetWritablePagesInSection(), MiSessionWideInsertImageAddress(), MiSessionWideReserveImageAddress(), and VeAllocatePoolWithTagPriority().

#define MI_SESSION_DATA_OFFSET   (8*1024*1024)
 

Definition at line 5258 of file mi.h.

#define MI_SESSION_IMAGE_OFFSET   (0)
 

Definition at line 5256 of file mi.h.

#define MI_SESSION_IMAGE_SIZE   (8*1024*1024)
 

Definition at line 5221 of file mi.h.

Referenced by MiDereferenceSession(), MiSessionWideReserveImageAddress(), and MmInitSystem().

#define MI_SESSION_IMAGE_START   ((ULONG_PTR)MmSessionBase)
 

Definition at line 5272 of file mi.h.

Referenced by MiDereferenceSession(), and MiSessionWideReserveImageAddress().

#define MI_SESSION_MAXIMUM_WORKING_SET   ((ULONG)(MI_SESSION_SPACE_TOTAL_SIZE >> PAGE_SHIFT))
 

Definition at line 5241 of file mi.h.

Referenced by MiDoReplacement(), and MiSessionInitializeWorkingSetList().

#define MI_SESSION_POOL   (MmSessionBase + MI_SESSION_POOL_OFFSET)
 

Definition at line 5278 of file mi.h.

Referenced by MiInitializeSessionPool(), and MiSessionCreateInternal().

#define MI_SESSION_POOL_OFFSET   (32*1024*1024)
 

Definition at line 5264 of file mi.h.

#define MI_SESSION_POOL_SIZE   (16*1024*1024)
 

Definition at line 5225 of file mi.h.

Referenced by MiInitializeSessionPool(), and MmResourcesAvailable().

#define MI_SESSION_SPACE_END
 

Value:

Definition at line 5280 of file mi.h.

Referenced by MiAttachSession(), MiDereferenceSession(), MiDetachSession(), MiInitMachineDependent(), MiSessionCommitPageTables(), MmInitSystem(), and MmSessionCreate().

#define MI_SESSION_SPACE_PAGE_TABLES   (MI_SESSION_SPACE_TOTAL_SIZE / MM_VA_MAPPED_BY_PDE)
 

Definition at line 5248 of file mi.h.

Referenced by MiAttachSession(), MiDereferenceSession(), MiDetachSession(), and MiSessionCommitPageTables().

#define MI_SESSION_SPACE_STRUCT_SIZE   MM_ALLOCATION_GRANULARITY
 

Definition at line 5217 of file mi.h.

#define MI_SESSION_SPACE_TOTAL_SIZE
 

Value:

Definition at line 5229 of file mi.h.

Referenced by MmInitSystem().

#define MI_SESSION_SPACE_WORKING_SET_MAXIMUM   384
 

Definition at line 5644 of file mi.h.

Referenced by MiSessionInitializeWorkingSetList().

#define MI_SESSION_SPACE_WORKING_SET_MINIMUM   20
 

Definition at line 5642 of file mi.h.

Referenced by MiDereferenceSession(), MiSessionCreateInternal(), and MiSessionInitializeWorkingSetList().

#define MI_SESSION_SPACE_WS   (MmSessionBase + MI_SESSION_WS_OFFSET)
 

Definition at line 5274 of file mi.h.

Referenced by MiDereferenceSession(), and MiSessionInitializeWorkingSetList().

#define MI_SESSION_SPACE_WS_SIZE   (4*1024*1024 - MI_SESSION_SPACE_STRUCT_SIZE)
 

Definition at line 5219 of file mi.h.

#define MI_SESSION_VIEW_OFFSET   (12*1024*1024)
 

Definition at line 5262 of file mi.h.

#define MI_SESSION_VIEW_SIZE   (20*1024*1024)
 

Definition at line 5223 of file mi.h.

Referenced by MiDereferenceSession(), and MiInitializeSystemSpaceMap().

#define MI_SESSION_VIEW_START   (MmSessionBase + MI_SESSION_VIEW_OFFSET)
 

Definition at line 5276 of file mi.h.

Referenced by MiDereferenceSession(), MiInitializeSystemSpaceMap(), and MiSessionInitializeWorkingSetList().

#define MI_SESSION_WS_OFFSET   (8*1024*1024 + MI_SESSION_SPACE_STRUCT_SIZE)
 

Definition at line 5260 of file mi.h.

#define MI_SET_BIT ARRAY,
BIT   )     (ULONG)ARRAY[(BIT) / (sizeof(ULONG)*8)] |= (1 << ((BIT) & 0x1F))
 

Definition at line 1186 of file mi.h.

Referenced by MiInsertVad().

#define MI_SPECIAL_POOL_PAGABLE   0x8000
 

Definition at line 65 of file mi.h.

Referenced by MiAllocateSpecialPool(), MmFreeSpecialPool(), and MmQuerySpecialPoolBlockSize().

#define MI_SPECIAL_POOL_PTE_NONPAGABLE   0x0004
 

Definition at line 68 of file mi.h.

Referenced by MiAllocateSpecialPool(), MiProtectSpecialPool(), MmFreeSpecialPool(), and MmIsSpecialPoolAddressFree().

#define MI_SPECIAL_POOL_PTE_PAGABLE   0x0002
 

Definition at line 67 of file mi.h.

Referenced by MiAllocateSpecialPool(), MiProtectSpecialPool(), MmFreeSpecialPool(), and MmIsSpecialPoolAddressFree().

#define MI_SPECIAL_POOL_VERIFIER   0x4000
 

Definition at line 66 of file mi.h.

Referenced by MiAllocateSpecialPool(), MmFreeSpecialPool(), MmQuerySpecialPoolBlockSize(), and ViPostPoolAllocation().

#define MI_STACK_BYTES   1024
 

Definition at line 4227 of file mi.h.

Referenced by MmFreeSpecialPool().

#define MI_STARTING_OFFSET SUBSECT,
PTE   ) 
 

Value:

(((LONGLONG)((ULONG_PTR)((PTE) - ((SUBSECT)->SubsectionBase))) << PAGE_SHIFT) + \ ((LONGLONG)((SUBSECT)->StartingSector) << MMSECTOR_SHIFT));

Definition at line 417 of file mi.h.

Referenced by MiCompleteProtoPteFault(), and MiStartingOffset().

#define MI_SUSPECT_DRIVER_BUFFER_LENGTH   512
 

Definition at line 4068 of file mi.h.

#define MI_TRIM_AGE_THRESHOLD   2
 

Definition at line 1692 of file mi.h.

#define MI_UNLOADED_DRIVERS   50
 

Definition at line 2685 of file mi.h.

Referenced by MiRememberUnloadedDriver(), and MmLocateUnloadedDriver().

#define MI_UNMARK_PFN_AS_LOCK_CHARGED Pfn,
CallerId   ) 
 

Definition at line 1392 of file mi.h.

#define MI_UNUSED_SEGMENTS_COUNT_UPDATE _count   )     MmUnusedSegmentCount += (_count);
 

Definition at line 4968 of file mi.h.

#define MI_UNUSED_SEGMENTS_INSERT_CHARGE _ControlArea   ) 
 

Value:

{ \ MM_PFN_LOCK_ASSERT(); \ ASSERT (_ControlArea->PagedPoolUsage >= sizeof(SEGMENT)); \ ASSERT (_ControlArea->NonPagedPoolUsage >= sizeof(CONTROL_AREA) + sizeof(SUBSECTION)); \ ASSERT (MiUnusedSegmentNonPagedPoolUsage + _ControlArea->NonPagedPoolUsage > MiUnusedSegmentNonPagedPoolUsage); \ ASSERT (MiUnusedSegmentPagedPoolUsage + _ControlArea->PagedPoolUsage > MiUnusedSegmentPagedPoolUsage); \ MiUnusedSegmentPagedPoolUsage += _ControlArea->PagedPoolUsage; \ MiUnusedSegmentNonPagedPoolUsage += _ControlArea->NonPagedPoolUsage;\ MmUnusedSegmentPagedPoolUsage += (_ControlArea->PagedPoolUsage + MI_FILESYSTEM_PAGED_POOL_CHARGE); \ MmUnusedSegmentNonPagedPoolUsage += (_ControlArea->NonPagedPoolUsage + MI_FILESYSTEM_NONPAGED_POOL_CHARGE);\ MI_UNUSED_SEGMENTS_COUNT_UPDATE(1); \ }

Definition at line 5019 of file mi.h.

Referenced by MiCheckControlArea(), and MiRemoveUnusedSegments().

#define MI_UNUSED_SEGMENTS_REMOVE_CHARGE _ControlArea   ) 
 

Value:

{ \ MM_PFN_LOCK_ASSERT(); \ ASSERT (_ControlArea->PagedPoolUsage >= sizeof(SEGMENT)); \ ASSERT (_ControlArea->NonPagedPoolUsage >= sizeof(CONTROL_AREA) + sizeof(SUBSECTION)); \ ASSERT (MmUnusedSegmentNonPagedPoolUsage - _ControlArea->NonPagedPoolUsage < MmUnusedSegmentNonPagedPoolUsage); \ ASSERT (MmUnusedSegmentPagedPoolUsage - _ControlArea->PagedPoolUsage < MmUnusedSegmentPagedPoolUsage); \ MiUnusedSegmentPagedPoolUsage -= _ControlArea->PagedPoolUsage; \ MiUnusedSegmentNonPagedPoolUsage -= _ControlArea->NonPagedPoolUsage;\ MmUnusedSegmentPagedPoolUsage -= (_ControlArea->PagedPoolUsage + MI_FILESYSTEM_PAGED_POOL_CHARGE); \ MmUnusedSegmentNonPagedPoolUsage -= (_ControlArea->NonPagedPoolUsage + MI_FILESYSTEM_NONPAGED_POOL_CHARGE);\ MI_UNUSED_SEGMENTS_COUNT_UPDATE(-1); \ }

Definition at line 5053 of file mi.h.

Referenced by MiCheckForControlAreaDeletion(), MiRemoveUnusedSegments(), MiSegmentDelete(), and MmCreateSection().

 
#define MI_UNUSED_SEGMENTS_SURPLUS  ) 
 

Value:

Definition at line 4995 of file mi.h.

Referenced by MiAllocatePoolPages(), and MmResourcesAvailable().

#define MI_UPDATE_USE_ESTIMATE PointerPte,
Wsle,
SampledAgeCounts   )     (SampledAgeCounts)[(Wsle)->u1.e1.Age] += 1;
 

Definition at line 1951 of file mi.h.

#define MI_USE_AGE_COUNT   4
 

Definition at line 1646 of file mi.h.

#define MI_USE_AGE_MAX   (MI_USE_AGE_COUNT - 1)
 

Definition at line 1647 of file mi.h.

#define MI_VA_TO_PAGE va   )     ((ULONG_PTR)(va) >> PAGE_SHIFT)
 

Definition at line 759 of file mi.h.

#define MI_VA_TO_VPN va   )     ((ULONG_PTR)(va) >> PAGE_SHIFT)
 

Definition at line 761 of file mi.h.

Referenced by MiAllocateVad(), MiCheckVirtualAddress(), MiCreatePebOrTeb(), MiDeleteVirtualAddresses(), MiFindEmptyAddressRangeDownTree(), MiFindEmptyAddressRangeInTree(), MiInsertVad(), MiLocateAddress(), MiMapLockedPagesInUserSpace(), MiMapViewOfDataSection(), MiMapViewOfImageSection(), MiMapViewOfPhysicalSection(), MiProtectVirtualMemory(), MiQueryAddressState(), MiResetVirtualMemory(), MiSetProtectionOnSection(), MmCleanProcessAddressSpace(), MmDeleteTeb(), MmFlushVirtualMemory(), MmMapUserAddressesToPage(), MmSecureVirtualMemory(), MmSetBankedSection(), NtAllocateVirtualMemory(), NtFreeVirtualMemory(), and NtQueryVirtualMemory().

#define MI_VERIFIER_ENTRY_SIGNATURE   0x98761940
 

Definition at line 4097 of file mi.h.

Referenced by VerifierFreeTrackedPool(), and ViInitializeEntry().

#define MI_VPN_TO_VA vpn   )     (PVOID)((vpn) << PAGE_SHIFT)
 

Definition at line 763 of file mi.h.

Referenced by MiCloneProcessAddressSpace(), MiDecommitPages(), MiFindEmptyAddressRange(), MiFindEmptyAddressRangeDownTree(), MiFindEmptyAddressRangeInTree(), MiInsertVad(), MiMapViewOfImageSection(), MiRemoveMappedView(), MiRemoveUserPhysicalPagesVad(), MiReturnPageTablePageCommitment(), MmCleanProcessAddressSpace(), MmMapUserAddressesToPage(), MmSetBankedSection(), MmUnmapViewOfSection(), NtAllocateVirtualMemory(), NtFreeVirtualMemory(), NtLockVirtualMemory(), NtQueryVirtualMemory(), and NtUnlockVirtualMemory().

#define MI_VPN_TO_VA_ENDING vpn   )     (PVOID)(((vpn) << PAGE_SHIFT) | (PAGE_SIZE - 1))
 

Definition at line 765 of file mi.h.

Referenced by MiCreatePebOrTeb(), MiFindEmptyAddressRange(), MiFindEmptyAddressRangeDownTree(), MiFindEmptyAddressRangeInTree(), MiRemoveMappedView(), MiRemoveUserPhysicalPagesVad(), MmCleanProcessAddressSpace(), MmFlushVirtualMemory(), MmMapUserAddressesToPage(), MmUnmapViewOfSection(), NtFreeVirtualMemory(), and NtQueryVirtualMemory().

#define MI_WRITEWATCH_VIEW_KEY   'wWmM'
 

Definition at line 2434 of file mi.h.

Referenced by NtAllocateVirtualMemory().

#define MI_WS_GROWING_TOO_FAST VmSupport   ) 
 

Value:

((VmSupport)->GrowthSinceLastEstimate > \ (((MI_CLAIM_INCR * (MmAvailablePages*MmAvailablePages)) / (64*64)) + 1))

Definition at line 1977 of file mi.h.

Referenced by MiDoReplacement().

#define MI_WS_OWNER PROCESS   )     1
 

Definition at line 1031 of file mi.h.

#define MI_WSLE_HASH Address,
Wsl   ) 
 

Value:

((WSLE_NUMBER)(((ULONG_PTR)PAGE_ALIGN(Address) >> (PAGE_SHIFT - 2)) % \ ((Wsl)->HashTableSize - 1)))

Definition at line 1559 of file mi.h.

Referenced by MiGrowWsleHash(), MiInsertWsle(), MiLocateWsle(), MiLookupWsleHashIndex(), and MiRemoveWsle().

#define MI_ZERO_USED_PAGETABLE_ENTRIES_IN_INPAGE_SUPPORT INPAGE_SUPPORT   ) 
 

Definition at line 1350 of file mi.h.

Referenced by MiResolveMappedFileFault().

#define MI_ZERO_USED_PAGETABLE_ENTRIES_IN_PFN PFN   ) 
 

Definition at line 1351 of file mi.h.

Referenced by MiWaitForInPageComplete().

#define MI_ZERO_WSINDEX Pfn   )     Pfn->u1.Event = NULL;
 

Definition at line 1521 of file mi.h.

Referenced by MiEliminateWorkingSetEntry(), MiEnablePagingOfDriverAtInit(), MiLockCode(), and MiUpdateWsle().

#define MiCheckForConflictingClone START,
END   ) 
 

Value:

Definition at line 747 of file mi.h.

#define MiCheckForConflictingVad StartingAddress,
EndingAddress   ) 
 

Value:

((PMMVAD)MiCheckForConflictingNode( \ MI_VA_TO_VPN(StartingAddress), \ MI_VA_TO_VPN(EndingAddress), \ (PMMADDRESS_NODE)(PsGetCurrentProcess()->VadRoot)))

Definition at line 556 of file mi.h.

Referenced by MiMapLockedPagesInUserSpace(), MiMapViewOfDataSection(), MiMapViewOfImageSection(), MiMapViewOfPhysicalSection(), MiProtectVirtualMemory(), MmInitializeProcessAddressSpace(), and NtAllocateVirtualMemory().

#define MiCreateBitMap BMH,
S,
 ) 
 

Value:

{ \ ULONG _S; \ _S = sizeof(RTL_BITMAP) + (ULONG)((((S) + 31) / 32) * 4); \ *(BMH) = (PRTL_BITMAP)ExAllocatePoolWithTag( (P), _S, ' mM'); \ if (*(BMH)) { \ RtlInitializeBitMap( *(BMH), (PULONG)((*(BMH))+1), (ULONG)S); \ } \ }

Definition at line 2496 of file mi.h.

Referenced by MiBuildPagedPool(), MiInitializeSessionIds(), MiInitializeSessionPool(), MiInitializeSystemSpaceMap(), MiInitMachineDependent(), and NtCreatePagingFile().

#define MiDecrementShareAndValidCount  )     MiDecrementShareCount(P)
 

Definition at line 2759 of file mi.h.

Referenced by MiDeletePte(), MiDeleteSystemPagableVm(), MiDeleteValidAddress(), MiDereferenceSession(), MiEliminateWorkingSetEntry(), MiInitializeSessionPool(), MiLoadImageSection(), MiProcessValidPteList(), MiReloadBootLoadedDrivers(), MiRemoveMappedPtes(), MiRemoveMappedView(), MiSessionCreateInternal(), MiSessionDeletePde(), MiUnmapLockedPagesInUserSpace(), MmDeleteKernelStack(), MmDeleteProcessAddressSpace(), MmFreeNonCachedMemory(), MmOutPageKernelStack(), and MmUnmapViewInSystemCache().

#define MiDecrementShareCountOnly  )     MiDecrementShareCount(P)
 

Definition at line 2757 of file mi.h.

Referenced by ExFreePool(), MiDeletePte(), MiDeleteSystemPagableVm(), MiDeleteValidAddress(), MiDereferenceSession(), MiDoneWithThisPageGetAnother(), MiDownShareCountFlushEntireTb(), MiInitializeSessionPool(), MiLoadImageSection(), MiProcessValidPteList(), MiReloadBootLoadedDrivers(), MiSessionCreateInternal(), MiSessionDeletePde(), MmDeleteKernelStack(), MmDeleteProcessAddressSpace(), MmFreeLoaderBlock(), MmFreeNonCachedMemory(), and MmOutPageKernelStack().

#define MiFindEmptyAddressRangeDown SizeOfRange,
HighestAddressToEndAt,
Alignment   ) 
 

Value:

(MiFindEmptyAddressRangeDownTree( \ (SizeOfRange), \ (HighestAddressToEndAt), \ (Alignment), \ (PMMADDRESS_NODE)(PsGetCurrentProcess()->VadRoot)))

Definition at line 451 of file mi.h.

Referenced by MiCreatePebOrTeb(), MiMapViewOfDataSection(), and NtAllocateVirtualMemory().

#define MiGetByteOffset va   )     ((ULONG_PTR)(va) & (PAGE_SIZE - 1))
 

Definition at line 767 of file mi.h.

Referenced by MiDecrementShareCount(), MiInsertPageInList(), MiInsertStandbyListAtFront(), and MiRestoreTransitionPte().

 
#define MiGetFirstClone  )     ((PMMCLONE_DESCRIPTOR)MiGetFirstNode((PMMADDRESS_NODE)(PsGetCurrentProcess()->CloneRoot)))
 

Definition at line 634 of file mi.h.

Referenced by MiCloneProcessAddressSpace().

#define MiGetFirstVad Process   )     ((PMMVAD)MiGetFirstNode((PMMADDRESS_NODE)(Process->VadRoot)))
 

Definition at line 526 of file mi.h.

Referenced by MiCloneProcessAddressSpace().

#define MiGetNextClone CLONE   )     ((PMMCLONE_DESCRIPTOR)MiGetNextNode((PMMADDRESS_NODE)(CLONE)))
 

Definition at line 583 of file mi.h.

Referenced by MiCloneProcessAddressSpace().

#define MiGetNextVad VAD   )     ((PMMVAD)MiGetNextNode((PMMADDRESS_NODE)(VAD)))
 

Definition at line 503 of file mi.h.

Referenced by MiCloneProcessAddressSpace(), MiFindEmptyAddressRange(), MmUnmapViewOfSection(), NtFreeVirtualMemory(), and NtQueryVirtualMemory().

#define MiGetPdeSessionIndex va   )     ((ULONG)(((ULONG_PTR)(va) - (ULONG_PTR)MmSessionBase) >> PDI_SHIFT))
 

Definition at line 5733 of file mi.h.

Referenced by MiCheckPdeForSessionSpace(), MiDereferenceSession(), MiInitializeSessionPool(), MiSessionCommitPageTables(), and MiSessionInitializeWorkingSetList().

#define MiGetPreviousClone CLONE   )     ((PMMCLONE_DESCRIPTOR)MiGetPreviousNode((PMMADDRESS_NODE)(CLONE)))
 

Definition at line 609 of file mi.h.

#define MiGetPreviousVad VAD   )     ((PMMVAD)MiGetPreviousNode((PMMADDRESS_NODE)(VAD)))
 

Definition at line 480 of file mi.h.

Referenced by MiRemoveVad(), MmUnmapViewOfSection(), and NtFreeVirtualMemory().

#define MiGetProtoPteAddress VAD,
VPN   ) 
 

Value:

((((((VPN) - (VAD)->StartingVpn) << PTE_SHIFT) + \ (ULONG_PTR)(VAD)->FirstPrototypePte) <= (ULONG_PTR)(VAD)->LastContiguousPte) ? \ ((PMMPTE)(((((VPN) - (VAD)->StartingVpn) << PTE_SHIFT) + \ (ULONG_PTR)(VAD)->FirstPrototypePte))) : \ MiGetProtoPteAddressExtended ((VAD),(VPN)))

Definition at line 3696 of file mi.h.

Referenced by MiCheckVirtualAddress(), MiDeleteVirtualAddresses(), MiProtectVirtualMemory(), MiQueryAddressState(), MiResetVirtualMemory(), MiSetProtectionOnSection(), MmFlushVirtualMemory(), and NtAllocateVirtualMemory().

#define MiInsertClone CLONE   ) 
 

Value:

{ \ ASSERT ((CLONE)->NumberOfPtes != 0); \ MiInsertNode(((PMMADDRESS_NODE)(CLONE)),(PMMADDRESS_NODE *)&(PsGetCurrentProcess()->CloneRoot)); \ }

Definition at line 659 of file mi.h.

Referenced by MiCloneProcessAddressSpace().

#define MiLocateCloneAddress VA   ) 
 

Value:

Definition at line 715 of file mi.h.

Referenced by MiCloneProcessAddressSpace(), MiCopyOnWrite(), MiDeletePte(), and MiDeleteValidAddress().

#define MiLockPfnDatabase OldIrql   )     ExAcquireSpinLock(&MmPfnLock, &OldIrql)
 

Definition at line 810 of file mi.h.

#define MiLockSystemSpace OldIrql   )     ExAcquireSpinLock(&MmSystemSpaceLock, &OldIrql)
 

Definition at line 822 of file mi.h.

Referenced by MiReleaseSystemPtes(), MiReserveSystemPtes(), MiReserveSystemPtes2(), MmCleanProcessAddressSpace(), MmCopyVirtualMemory(), MmMapIoSpace(), MmMapLockedPagesSpecifyCache(), MmUnmapIoSpace(), and MmUnmapLockedPages().

 
#define MiLockSystemSpaceAtDpcLevel  )     ExAcquireSpinLockAtDpcLevel(&MmSystemSpaceLock)
 

Definition at line 828 of file mi.h.

Referenced by MiFlushPteList().

#define MiMakePpeExistAndMakeValid PDE,
PROCESS,
PFNMUTEXHELD   ) 
 

Definition at line 3591 of file mi.h.

Referenced by MiCreatePageTablesForPhysicalRange(), MiDecommitPages(), MiMapLockedPagesInUserSpace(), MiMapViewOfPhysicalSection(), MiProtectVirtualMemory(), MiSetProtectionOnSection(), and NtAllocateVirtualMemory().

 
#define MiReleasePfnLock  )     KiReleaseSpinLock(&MmPfnLock)
 

Definition at line 819 of file mi.h.

#define MiRemoveBitMap BMH   ) 
 

Value:

{ \ ExFreePool(*(BMH)); \ *(BMH) = NULL; \ }

Definition at line 2505 of file mi.h.

Referenced by MiFreeSessionSpaceMap(), MiInitializeSystemSpaceMap(), and NtCreatePagingFile().

#define MiRemoveClone CLONE   )     MiRemoveNode((PMMADDRESS_NODE)(CLONE),(PMMADDRESS_NODE *)&(PsGetCurrentProcess()->CloneRoot));
 

Definition at line 687 of file mi.h.

Referenced by MiCloneProcessAddressSpace(), and MiDecrementCloneBlockReference().

#define MiRemoveZeroPageIfAny COLOR   ) 
 

Value:

Definition at line 2814 of file mi.h.

Referenced by MiInitMachineDependent(), MiResolveDemandZeroFault(), MiSessionCommitImagePages(), MiSessionCommitPageTables(), MiSessionCreateInternal(), MiSessionInitializeWorkingSetList(), MmAccessFault(), and MmCreateProcessAddressSpace().

#define MiTryToLockPfnDatabase OldIrql   )     KeTryToAcquireSpinLock(&MmPfnLock, &OldIrql)
 

Definition at line 816 of file mi.h.

#define MiUnlockPfnDatabase OldIrql   )     ExReleaseSpinLock(&MmPfnLock, OldIrql)
 

Definition at line 813 of file mi.h.

#define MiUnlockSystemSpace OldIrql   )     ExReleaseSpinLock(&MmSystemSpaceLock, OldIrql)
 

Definition at line 825 of file mi.h.

Referenced by MiReleaseSystemPtes(), MiReserveSystemPtes(), MiReserveSystemPtes2(), MmCleanProcessAddressSpace(), MmCopyVirtualMemory(), MmMapIoSpace(), MmMapLockedPagesSpecifyCache(), MmUnmapIoSpace(), and MmUnmapLockedPages().

 
#define MiUnlockSystemSpaceFromDpcLevel  )     ExReleaseSpinLockFromDpcLevel(&MmSystemSpaceLock)
 

Definition at line 831 of file mi.h.

Referenced by MiFlushPteList().

#define MiUnmapPageInHyperSpace OLDIRQL   )     UNLOCK_HYPERSPACE(OLDIRQL)
 

Definition at line 2922 of file mi.h.

Referenced by MiBuildPagedPool(), MiCopyOnWrite(), MiDecrementShareCount(), MiGatherMappedPages(), MiInsertPageInList(), MiInsertStandbyListAtFront(), MiMakeOutswappedPageResident(), MiRestoreTransitionPte(), MiSessionCopyOnWrite(), MiSessionDeletePde(), MiSessionInSwapProcess(), MiSessionOutSwapProcess(), MiWaitForInPageComplete(), MiZeroPhysicalPage(), MmCreateProcessAddressSpace(), MmDeleteProcessAddressSpace(), MmInSwapProcess(), and MmOutSwapProcess().

#define MM4K_MASK   0xfff
 

Definition at line 107 of file mi.h.

Referenced by MiCreateDataFileMap(), and MmExtendSection().

#define MM4K_SHIFT   12
 

Definition at line 106 of file mi.h.

Referenced by MiCreateDataFileMap(), MiEndingOffset(), MiStartingOffset(), and MmExtendSection().

#define MM_ALLOCATION_FILLS_VAD   ((PMMPTE)(ULONG_PTR)~3)
 

Definition at line 84 of file mi.h.

Referenced by MiMapViewOfImageSection().

#define MM_BUMP_COUNTER _index,
bump   ) 
 

Value:

if (_index >= MM_BUMP_COUNTER_MAX) { \ DbgPrint("Mm: Invalid bump counter %d %d\n", _index, MM_BUMP_COUNTER_MAX); \ DbgBreakPoint(); \ } \ else { \ MmResTrack[_index] += (bump); \ }

Definition at line 4317 of file mi.h.

Referenced by MiAddWorkingSetPage(), MiAllocatePoolPages(), MiAllocateSpecialPool(), MiCreatePageTablesForPhysicalRange(), MiDeletePageTablesForPhysicalRange(), MiDereferenceSession(), MiFindContiguousMemory(), MiFreeNonPagedPool(), MiInitializeSessionPool(), MiLoadImageSection(), MiLockCode(), MiSessionCommitImagePages(), MiSessionCommitPageTables(), MiSessionCreateInternal(), MiSessionInitializeWorkingSetList(), MiSetPagingOfDriver(), MmAdjustWorkingSetSize(), MmAllocateIndependentPages(), MmAllocateNonCachedMemory(), MmAllocatePagesForMdl(), MmCleanProcessAddressSpace(), MmCreateKernelStack(), MmCreateProcessAddressSpace(), MmDeleteKernelStack(), MmDeleteProcessAddressSpace(), MmFreeDriverInitialization(), MmFreeNonCachedMemory(), MmFreePagesFromMdl(), MmFreeSpecialPool(), MmGrowKernelStack(), MmOutPageKernelStack(), and MmUnloadSystemImage().

#define MM_BUMP_COUNTER_MAX   60
 

Definition at line 4315 of file mi.h.

#define MM_BUMP_SESS_COUNTER _index,
bump   ) 
 

Definition at line 5361 of file mi.h.

Referenced by MiAddWorkingSetPage(), MiAddWsleHash(), MiAllocatePoolPages(), MiDereferenceSession(), MiFreePoolPages(), MiInitializeSessionPool(), MiLoadImageSection(), MiSessionCommitImagePages(), MiSessionCommitPageTables(), MiSessionCreateInternal(), MiSessionInitializeWorkingSetList(), MiSetPagingOfDriver(), MiShareSessionImage(), and MmUnloadSystemImage().

#define MM_BUMP_SESSION_FAILURES _index   )     MmSessionFailureCauses[_index] += 1;
 

Definition at line 5380 of file mi.h.

Referenced by MiInitializeSessionPool(), MiInitializeSystemSpaceMap(), MiSessionCommitImagePages(), MiSessionCommitPageTables(), MiSessionCreateInternal(), MiSessionInitializeWorkingSetList(), MiSessionInsertImage(), MiSessionWideInsertImageAddress(), MiSessionWideReserveImageAddress(), and MiShareSessionImage().

 
#define MM_CLEAR_EXPANSION_OWNER  ) 
 

Definition at line 953 of file mi.h.

 
#define MM_CLEAR_SESSION_LOCK_OWNER  ) 
 

Definition at line 5629 of file mi.h.

 
#define MM_CLEAR_SESSION_RESOURCE_OWNER  ) 
 

Value:

Definition at line 5681 of file mi.h.

#define MM_COPY_ON_WRITE_MASK   5
 

Definition at line 198 of file mi.h.

Referenced by MiCreateImageFileMap(), MiResolveProtoPteFault(), MiSetProtectionOnSection(), and MiWriteComplete().

#define MM_DBG_CHECK_PFN_LOCK   0x80000
 

Definition at line 182 of file mi.h.

Referenced by MmInitSystem().

#define MM_DBG_CHECK_PTE   0x40
 

Definition at line 170 of file mi.h.

#define MM_DBG_CLEAN_PROCESS   0x800
 

Definition at line 174 of file mi.h.

#define MM_DBG_COLLIDED_PAGE   0x1000
 

Definition at line 175 of file mi.h.

Referenced by MiResolveTransitionFault().

#define MM_DBG_COMMIT_ALLOCVM1   4
 

Definition at line 4250 of file mi.h.

Referenced by NtAllocateVirtualMemory().

#define MM_DBG_COMMIT_ALLOCVM2   5
 

Definition at line 4251 of file mi.h.

Referenced by NtAllocateVirtualMemory().

#define MM_DBG_COMMIT_CONTIGUOUS_PAGES   9
 

Definition at line 4255 of file mi.h.

Referenced by MiFindContiguousMemory().

#define MM_DBG_COMMIT_DRIVER_PAGES   24
 

Definition at line 4270 of file mi.h.

Referenced by MiLoadImageSection().

#define MM_DBG_COMMIT_DRIVER_PAGING_AT_INIT   15
 

Definition at line 4261 of file mi.h.

#define MM_DBG_COMMIT_EXTRA_SYSTEM_PTES   14
 

Definition at line 4260 of file mi.h.

Referenced by MmInitSystem().

#define MM_DBG_COMMIT_FILL_SYSTEM_DIRECTORY   13
 

Definition at line 4259 of file mi.h.

Referenced by MiFillSystemPageDirectory().

#define MM_DBG_COMMIT_IMAGE   6
 

Definition at line 4252 of file mi.h.

Referenced by MiCreateImageFileMap().

#define MM_DBG_COMMIT_INDEPENDENT_PAGES   8
 

Definition at line 4254 of file mi.h.

Referenced by MmAllocateIndependentPages().

#define MM_DBG_COMMIT_INSERT_VAD   25
 

Definition at line 4271 of file mi.h.

Referenced by MiInsertVad().

#define MM_DBG_COMMIT_KERNEL_STACK_CREATE   18
 

Definition at line 4264 of file mi.h.

Referenced by MmCreateKernelStack().

#define MM_DBG_COMMIT_MAPVIEW_DATA   12
 

Definition at line 4258 of file mi.h.

Referenced by MiMapViewOfDataSection().

#define MM_DBG_COMMIT_MDL_PAGES   10
 

Definition at line 4256 of file mi.h.

Referenced by MmAllocatePagesForMdl().

#define MM_DBG_COMMIT_NONCACHED_PAGES   11
 

Definition at line 4257 of file mi.h.

Referenced by MmAllocateNonCachedMemory().

#define MM_DBG_COMMIT_NONPAGED_POOL_EXPANSION   0
 

Definition at line 4246 of file mi.h.

Referenced by MiAllocatePoolPages().

#define MM_DBG_COMMIT_PAGED_POOL_PAGES   2
 

Definition at line 4248 of file mi.h.

Referenced by MiAllocatePoolPages().

#define MM_DBG_COMMIT_PAGED_POOL_PAGETABLE   1
 

Definition at line 4247 of file mi.h.

Referenced by MiAllocatePoolPages().

#define MM_DBG_COMMIT_PAGEFILE_BACKED_SHMEM   7
 

Definition at line 4253 of file mi.h.

Referenced by MiCreatePagingFileMap().

#define MM_DBG_COMMIT_PAGEFILE_FULL   16
 

Definition at line 4262 of file mi.h.

Referenced by MiPageFileFull().

#define MM_DBG_COMMIT_PROCESS_CREATE   17
 

Definition at line 4263 of file mi.h.

Referenced by MmCreateProcessAddressSpace().

#define MM_DBG_COMMIT_RETURN_ALLOCVM1   32
 

Definition at line 4279 of file mi.h.

Referenced by NtAllocateVirtualMemory().

#define MM_DBG_COMMIT_RETURN_ALLOCVM2   33
 

Definition at line 4280 of file mi.h.

Referenced by NtAllocateVirtualMemory().

#define MM_DBG_COMMIT_RETURN_ALLOCVM3   34
 

Definition at line 4281 of file mi.h.

Referenced by NtAllocateVirtualMemory().

#define MM_DBG_COMMIT_RETURN_DRIVER_INIT_CODE   62
 

Definition at line 4308 of file mi.h.

Referenced by MmFreeDriverInitialization().

#define MM_DBG_COMMIT_RETURN_DRIVER_UNLOAD   63
 

Definition at line 4309 of file mi.h.

Referenced by MmUnloadSystemImage().

#define MM_DBG_COMMIT_RETURN_DRIVER_UNLOAD1   64
 

Definition at line 4310 of file mi.h.

Referenced by MmUnloadSystemImage().

#define MM_DBG_COMMIT_RETURN_IMAGE_NO_LARGE_CA   35
 

Definition at line 4282 of file mi.h.

Referenced by MiCreateImageFileMap().

#define MM_DBG_COMMIT_RETURN_KERNEL_STACK_DELETE   60
 

Definition at line 4306 of file mi.h.

Referenced by MmDeleteKernelStack().

#define MM_DBG_COMMIT_RETURN_KERNEL_STACK_FAILURE1   58
 

Definition at line 4304 of file mi.h.

Referenced by MmCreateKernelStack().

#define MM_DBG_COMMIT_RETURN_KERNEL_STACK_FAILURE2   59
 

Definition at line 4305 of file mi.h.

Referenced by MmCreateKernelStack().

#define MM_DBG_COMMIT_RETURN_MAPVIEW_DATA   43
 

Definition at line 4290 of file mi.h.

Referenced by MiMapViewOfDataSection().

#define MM_DBG_COMMIT_RETURN_MDL_PAGES   41
 

Definition at line 4288 of file mi.h.

Referenced by MmFreePagesFromMdl().

#define MM_DBG_COMMIT_RETURN_NONCACHED_PAGES   42
 

Definition at line 4289 of file mi.h.

Referenced by MmFreeNonCachedMemory().

#define MM_DBG_COMMIT_RETURN_NONPAGED_POOL_EXPANSION   29
 

Definition at line 4276 of file mi.h.

Referenced by MiFreeNonPagedPool().

#define MM_DBG_COMMIT_RETURN_NTFREEVM1   37
 

Definition at line 4284 of file mi.h.

Referenced by NtFreeVirtualMemory().

#define MM_DBG_COMMIT_RETURN_NTFREEVM2   38
 

Definition at line 4285 of file mi.h.

Referenced by NtFreeVirtualMemory().

#define MM_DBG_COMMIT_RETURN_NTFREEVM3   39
 

Definition at line 4286 of file mi.h.

Referenced by NtFreeVirtualMemory().

#define MM_DBG_COMMIT_RETURN_NTFREEVM4   40
 

Definition at line 4287 of file mi.h.

Referenced by NtFreeVirtualMemory().

#define MM_DBG_COMMIT_RETURN_PAGED_POOL_PAGES   30
 

Definition at line 4277 of file mi.h.

Referenced by MiFreePoolPages(), and MiInitializeSessionPool().

#define MM_DBG_COMMIT_RETURN_PAGEFILE_BACKED_SHMEM   36
 

Definition at line 4283 of file mi.h.

Referenced by MiCreatePagingFileMap().

#define MM_DBG_COMMIT_RETURN_PAGETABLES   44
 

Definition at line 4291 of file mi.h.

Referenced by MiReturnPageTablePageCommitment().

#define MM_DBG_COMMIT_RETURN_PROCESS_CLEAN_PAGETABLES   57
 

Definition at line 4303 of file mi.h.

Referenced by MmCleanProcessAddressSpace().

#define MM_DBG_COMMIT_RETURN_PROCESS_CREATE_FAILURE1   55
 

Definition at line 4301 of file mi.h.

Referenced by MmCreateProcessAddressSpace().

#define MM_DBG_COMMIT_RETURN_PROCESS_DELETE   56
 

Definition at line 4302 of file mi.h.

Referenced by MmDeleteProcessAddressSpace().

#define MM_DBG_COMMIT_RETURN_PROTECTION   45
 

Definition at line 4292 of file mi.h.

Referenced by MiSetProtectionOnSection().

#define MM_DBG_COMMIT_RETURN_SEGMENT_DELETE1   46
 

Definition at line 4293 of file mi.h.

Referenced by MiSegmentDelete().

#define MM_DBG_COMMIT_RETURN_SEGMENT_DELETE2   47
 

Definition at line 4294 of file mi.h.

Referenced by MiSegmentDelete().

#define MM_DBG_COMMIT_RETURN_SESSION_CREATE_FAILURE1   48
 

Definition at line 4295 of file mi.h.

Referenced by MiSessionCreateInternal().

#define MM_DBG_COMMIT_RETURN_SESSION_DEREFERENCE   49
 

Definition at line 4296 of file mi.h.

Referenced by MiDereferenceSession().

#define MM_DBG_COMMIT_RETURN_SESSION_DRIVER_LOAD_FAILURE1   61
 

Definition at line 4307 of file mi.h.

Referenced by MiLoadImageSection().

#define MM_DBG_COMMIT_RETURN_SESSION_IMAGE_FAILURE1   50
 

Definition at line 4297 of file mi.h.

Referenced by MiSessionCommitImagePages().

#define MM_DBG_COMMIT_RETURN_SESSION_PAGETABLE_PAGES   51
 

Definition at line 4298 of file mi.h.

Referenced by MiSessionCommitPageTables().

#define MM_DBG_COMMIT_RETURN_SESSION_POOL_PAGE_TABLES   31
 

Definition at line 4278 of file mi.h.

Referenced by MiInitializeSessionPool().

#define MM_DBG_COMMIT_RETURN_SESSION_WSL_FAILURE   54
 

Definition at line 4300 of file mi.h.

Referenced by MiSessionInitializeWorkingSetList().

#define MM_DBG_COMMIT_RETURN_VAD   52
 

Definition at line 4299 of file mi.h.

Referenced by MiRemoveVad().

#define MM_DBG_COMMIT_SESSION_ADDITIONAL_WS_HASHPAGES   28
 

Definition at line 4274 of file mi.h.

Referenced by MiAddWsleHash().

#define MM_DBG_COMMIT_SESSION_ADDITIONAL_WS_PAGES   27
 

Definition at line 4273 of file mi.h.

Referenced by MiAddWorkingSetPage().

#define MM_DBG_COMMIT_SESSION_CREATE   20
 

Definition at line 4266 of file mi.h.

Referenced by MiSessionCreateInternal().

#define MM_DBG_COMMIT_SESSION_IMAGE_PAGES   21
 

Definition at line 4267 of file mi.h.

Referenced by MiSessionCommitImagePages().

#define MM_DBG_COMMIT_SESSION_PAGETABLE_PAGES   22
 

Definition at line 4268 of file mi.h.

Referenced by MiSessionCommitPageTables().

#define MM_DBG_COMMIT_SESSION_POOL_PAGE_TABLES   3
 

Definition at line 4249 of file mi.h.

Referenced by MiInitializeSessionPool().

#define MM_DBG_COMMIT_SESSION_SHARED_IMAGE   23
 

Definition at line 4269 of file mi.h.

Referenced by MiShareSessionImage().

#define MM_DBG_COMMIT_SESSION_WS_INIT   26
 

Definition at line 4272 of file mi.h.

Referenced by MiSessionInitializeWorkingSetList().

#define MM_DBG_COMMIT_SET_PROTECTION   19
 

Definition at line 4265 of file mi.h.

Referenced by MiSetProtectionOnSection().

#define MM_DBG_DIR_BASE   0x8000
 

Definition at line 178 of file mi.h.

#define MM_DBG_DUMP_BOOT_PTES   0x2000
 

Definition at line 176 of file mi.h.

Referenced by MmInitSystem().

#define MM_DBG_DUMP_WSL   0x4
 

Definition at line 166 of file mi.h.

Referenced by MiRemoveWsle().

#define MM_DBG_FLUSH_SECTION   0x10000
 

Definition at line 179 of file mi.h.

Referenced by MiCleanSection(), MiFlushSectionInternal(), and MmPurgeSection().

#define MM_DBG_FORK   0x4000
 

Definition at line 177 of file mi.h.

Referenced by MiCloneProcessAddressSpace(), and MiDecrementCloneBlockReference().

#define MM_DBG_LOCK_CODE   0x800000
 

Definition at line 186 of file mi.h.

Referenced by MmLockPagableDataSection().

#define MM_DBG_MOD_WRITE   0x20
 

Definition at line 169 of file mi.h.

Referenced by MiGatherPagefilePages(), and MiWriteComplete().

#define MM_DBG_PAGE_IN_LIST   0x40000
 

Definition at line 181 of file mi.h.

Referenced by MiUnlinkPageFromList().

#define MM_DBG_PAGE_REF_COUNT   0x2000000
 

Definition at line 188 of file mi.h.

Referenced by MiInsertPageInList(), and MiInsertStandbyListAtFront().

#define MM_DBG_PAGEFAULT   0x8
 

Definition at line 167 of file mi.h.

Referenced by MiDispatchFault().

#define MM_DBG_PRINTS_MODWRITES   0x20000
 

Definition at line 180 of file mi.h.

Referenced by MiWriteComplete().

#define MM_DBG_PRIVATE_PAGES   0x100000
 

Definition at line 183 of file mi.h.

Referenced by MmCleanProcessAddressSpace().

#define MM_DBG_PTE_UPDATE   0x2
 

Definition at line 165 of file mi.h.

Referenced by MiCopyOnWrite(), MiDeletePte(), MiInsertWsle(), MiRemoveWsle(), MiResolveMappedFileFault(), MiResolveProtoPteFault(), MmAccessFault(), and MmInitializeProcessAddressSpace().

#define MM_DBG_SECTIONS   0x100
 

Definition at line 172 of file mi.h.

Referenced by MiDereferenceSegmentThread(), MiRemoveUnusedSegments(), MiSectionDelete(), MiSegmentDelete(), MmCreateSection(), and NtCreateSection().

#define MM_DBG_SESSION_COMMIT_DELETE_VM_RETURN   31
 

Definition at line 5324 of file mi.h.

#define MM_DBG_SESSION_COMMIT_IMAGE_UNLOAD   33
 

Definition at line 5326 of file mi.h.

Referenced by MmUnloadSystemImage().

#define MM_DBG_SESSION_COMMIT_IMAGELOAD_FAILED1   34
 

Definition at line 5327 of file mi.h.

Referenced by MiLoadImageSection().

#define MM_DBG_SESSION_COMMIT_IMAGELOAD_FAILED2   35
 

Definition at line 5328 of file mi.h.

Referenced by MiLoadImageSection().

#define MM_DBG_SESSION_COMMIT_IMAGELOAD_NOACCESS   36
 

Definition at line 5329 of file mi.h.

Referenced by MiLoadImageSection().

#define MM_DBG_SESSION_COMMIT_PAGEDPOOL_PAGES   30
 

Definition at line 5323 of file mi.h.

Referenced by MiAllocatePoolPages().

#define MM_DBG_SESSION_COMMIT_POOL_FREED   32
 

Definition at line 5325 of file mi.h.

Referenced by MiFreePoolPages().

#define MM_DBG_SESSION_DRIVER_PAGES_LOCKED   16
 

Definition at line 5318 of file mi.h.

Referenced by MiSessionCommitImagePages().

#define MM_DBG_SESSION_DRIVER_PAGES_UNLOCKED   17
 

Definition at line 5319 of file mi.h.

Referenced by MiSetPagingOfDriver().

#define MM_DBG_SESSION_INITIAL_PAGE_ALLOC   2
 

Definition at line 5304 of file mi.h.

Referenced by MiSessionCreateInternal().

#define MM_DBG_SESSION_INITIAL_PAGE_FREE   13
 

Definition at line 5315 of file mi.h.

Referenced by MiDereferenceSession().

#define MM_DBG_SESSION_INITIAL_PAGE_FREE_FAIL1   3
 

Definition at line 5305 of file mi.h.

Referenced by MiSessionCreateInternal().

#define MM_DBG_SESSION_INITIAL_PAGETABLE_ALLOC   0
 

Definition at line 5302 of file mi.h.

Referenced by MiSessionCreateInternal().

#define MM_DBG_SESSION_INITIAL_PAGETABLE_FREE_FAIL1   4
 

Definition at line 5306 of file mi.h.

Referenced by MiSessionCreateInternal().

#define MM_DBG_SESSION_INITIAL_PAGETABLE_FREE_RACE   1
 

Definition at line 5303 of file mi.h.

Referenced by MiSessionCreateInternal().

#define MM_DBG_SESSION_PAGEDPOOL_PAGETABLE_ALLOC   9
 

Definition at line 5311 of file mi.h.

Referenced by MiInitializeSessionPool().

#define MM_DBG_SESSION_PAGEDPOOL_PAGETABLE_ALLOC1   15
 

Definition at line 5317 of file mi.h.

Referenced by MiAllocatePoolPages().

#define MM_DBG_SESSION_PAGEDPOOL_PAGETABLE_FREE_FAIL1   10
 

Definition at line 5312 of file mi.h.

Referenced by MiInitializeSessionPool().

#define MM_DBG_SESSION_PAGETABLE_ALLOC   6
 

Definition at line 5308 of file mi.h.

Referenced by MiSessionCommitPageTables().

#define MM_DBG_SESSION_PAGETABLE_FREE   14
 

Definition at line 5316 of file mi.h.

Referenced by MiDereferenceSession().

#define MM_DBG_SESSION_SYSMAPPED_PAGES_ALLOC   7
 

Definition at line 5309 of file mi.h.

Referenced by MiShareSessionImage().

#define MM_DBG_SESSION_SYSMAPPED_PAGES_COMMITTED   19
 

Definition at line 5321 of file mi.h.

Referenced by MiShareSessionImage().

#define MM_DBG_SESSION_WS_HASHPAGE_ALLOC   18
 

Definition at line 5320 of file mi.h.

Referenced by MiAddWsleHash().

#define MM_DBG_SESSION_WS_PAGE_ALLOC   11
 

Definition at line 5313 of file mi.h.

Referenced by MiSessionInitializeWorkingSetList().

#define MM_DBG_SESSION_WS_PAGE_ALLOC_GROWTH   12
 

Definition at line 5314 of file mi.h.

Referenced by MiAddWorkingSetPage().

#define MM_DBG_SESSION_WS_PAGE_FREE   5
 

Definition at line 5307 of file mi.h.

Referenced by MiDereferenceSession().

#define MM_DBG_SESSION_WS_PAGETABLE_ALLOC   8
 

Definition at line 5310 of file mi.h.

Referenced by MiSessionInitializeWorkingSetList().

#define MM_DBG_SESSIONS   0x80000000
 

Definition at line 191 of file mi.h.

Referenced by MiRearrangeWorkingSetExpansionList(), MiSessionCommitImagePages(), MiSessionCreateInternal(), MiSessionInSwapProcess(), MiSessionOutSwapProcess(), and MiSessionWideReserveImageAddress().

#define MM_DBG_SHOW_FAULTS   0x40000000
 

Definition at line 190 of file mi.h.

Referenced by MmAccessFault().

#define MM_DBG_SHOW_NT_CALLS   0x10000000
 

Definition at line 189 of file mi.h.

Referenced by MmCreateSection(), NtAllocateVirtualMemory(), NtCreateSection(), NtFreeVirtualMemory(), NtMapViewOfSection(), NtProtectVirtualMemory(), and NtQueryVirtualMemory().

#define MM_DBG_STOP_ON_ACCVIO   0x1000000
 

Definition at line 187 of file mi.h.

Referenced by MiResolveProtoPteFault(), and MmAccessFault().

#define MM_DBG_SWAP_PROCESS   0x400000
 

Definition at line 185 of file mi.h.

Referenced by MmOutSwapProcess().

#define MM_DBG_SYS_PTES   0x400
 

Definition at line 173 of file mi.h.

Referenced by MiReleaseSystemPtes(), MiReserveSystemPtes(), and MiReserveSystemPtes2().

#define MM_DBG_VAD_CONFLICT   0x80
 

Definition at line 171 of file mi.h.

#define MM_DBG_WALK_VAD_TREE   0x200000
 

Definition at line 184 of file mi.h.

Referenced by MiMapViewOfImageSection().

#define MM_DBG_WRITEFAULT   0x1
 

Definition at line 164 of file mi.h.

Referenced by MiCopyOnWrite().

#define MM_DBG_WS_EXPANSION   0x10
 

Definition at line 168 of file mi.h.

Referenced by MiCheckAndSetSystemTrimCriteria(), MiCheckProcessTrimCriteria(), MiRearrangeWorkingSetExpansionList(), and MmWorkingSetManager().

#define MM_DECOMMIT   0x10
 

Definition at line 144 of file mi.h.

Referenced by MiCloneProcessAddressSpace(), MiIsPteDecommittedPage(), and NtAllocateVirtualMemory().

#define MM_EXECUTE   2
 

Definition at line 135 of file mi.h.

Referenced by MiEnablePagingOfDriverAtInit(), MiInitMachineDependent(), MiLoadImageSection(), and MiSetPagingOfDriver().

#define MM_EXECUTE_READ   3
 

Definition at line 136 of file mi.h.

Referenced by MiInitMachineDependent(), MiSetSystemCodeProtection(), and MiShareSessionImage().

#define MM_EXECUTE_READWRITE   6
 

Definition at line 139 of file mi.h.

Referenced by MiCreateDataFileMap(), MiCreatePebOrTeb(), MiInitializeCopyOnWritePfn(), MiInitializePfn(), MiInitMachineDependent(), MiLoadSystemImage(), MiReloadBootLoadedDrivers(), and MmSecureVirtualMemory().

#define MM_EXECUTE_WRITECOPY   7
 

Definition at line 140 of file mi.h.

Referenced by MiCheckVirtualAddress(), MiCreateImageFileMap(), MiInitMachineDependent(), MiMapViewOfImageSection(), MiProtectSpecialPool(), MmAccessFault(), and MmSecureVirtualMemory().

#define MM_FLUID_PHYSICAL_PAGES   32
 

Definition at line 90 of file mi.h.

Referenced by MmInitSystem().

#define MM_FLUID_WORKING_SET   8
 

Definition at line 88 of file mi.h.

Referenced by MmAdjustWorkingSetSize(), and NtLockVirtualMemory().

#define MM_FLUSH_COUNTER_MASK   (0xFFFFF)
 

Definition at line 74 of file mi.h.

Referenced by MiFlushPteList(), and MiReserveSystemPtes().

#define MM_FORCE_TRIM   6
 

Definition at line 117 of file mi.h.

Referenced by MiDoReplacement(), and MmWorkingSetManager().

#define MM_FREE_POOL_SIGNATURE   (0x50554F4C)
 

Definition at line 80 of file mi.h.

Referenced by MiAllocatePoolPages(), MiFindContiguousMemory(), MiFreePoolPages(), MiInitializeNonPagedPool(), and MmSetKernelDumpRange().

#define MM_FREE_WSLE_SHIFT   4
 

Definition at line 76 of file mi.h.

Referenced by MiAddWorkingSetPage(), MiEmptyWorkingSet(), MiFreeWsle(), MiInitializeSystemCache(), MiInitializeWorkingSetList(), MiLocateAndReserveWsle(), MiReleaseWsle(), MiRemoveWorkingSetPages(), MiRemoveWsleFromFreeList(), MiSessionInitializeWorkingSetList(), MiSwapWslEntries(), and MiUpdateWsle().

#define MM_GROW_WSLE_HASH   20
 

Definition at line 119 of file mi.h.

Referenced by MiAddWorkingSetPage(), MiInsertWsle(), MiMakeSpecialPoolPagable(), MiRemoveWorkingSetPages(), and MmAccessFault().

#define MM_GUARD_PAGE   0x10
 

Definition at line 143 of file mi.h.

Referenced by MiAccessCheck(), MiCheckSecuredVad(), MiInitMachineDependent(), MiMakeProtectionMask(), and MmAccessFault().

#define MM_HIGHEST_VAD_ADDRESS   ((PVOID)((ULONG_PTR)MM_HIGHEST_USER_ADDRESS - (64 * 1024)))
 

Definition at line 96 of file mi.h.

Referenced by MiCreatePebOrTeb(), MiFindEmptyAddressRangeDownTree(), MiFindEmptyAddressRangeInTree(), MiMapLockedPagesInUserSpace(), MiMapViewOfDataSection(), MiMapViewOfImageSection(), NtAllocateVirtualMemory(), NtMapViewOfSection(), and NtQueryVirtualMemory().

#define MM_IO_IN_PROGRESS   ((PLIST_ENTRY)97)
 

Definition at line 102 of file mi.h.

Referenced by MiGatherPagefilePages(), MiUpdateModifiedWriterMdls(), and MmOutSwapProcess().

#define MM_KSTACK_OUTSWAPPED   0x1F
 

Definition at line 151 of file mi.h.

Referenced by MmAccessFault(), MmCreateKernelStack(), MmGrowKernelStack(), MmInPageKernelStack(), and MmOutPageKernelStack().

#define MM_LARGE_PAGES   0x111
 

Definition at line 147 of file mi.h.

Referenced by MiCheckVirtualAddress(), and MmAccessFault().

#define MM_LOCK_BY_NONPAGE   1
 

Definition at line 115 of file mi.h.

Referenced by MmResetDriverPaging().

#define MM_LOCK_BY_REFCOUNT   0
 

Definition at line 113 of file mi.h.

Referenced by MiLockCode(), MmLockPagableSectionByHandle(), and MmLockPagedPool().

#define MM_MAPPED_FILE_MDLS   4
 

Definition at line 5085 of file mi.h.

Referenced by MiModifiedPageWriter().

#define MM_MAX_COMMIT   (((ULONG_PTR) 1 << COMMIT_SIZE) - 1)
 

Definition at line 2338 of file mi.h.

Referenced by MiAllocateVad(), MiCloneProcessAddressSpace(), MiInsertVad(), MiRemoveVad(), and NtAllocateVirtualMemory().

#define MM_MAXIMUM_FLUSH_COUNT   (FLUSH_MULTIPLE_MAXIMUM-1)
 

Definition at line 127 of file mi.h.

Referenced by MiDeletePte(), MiDeleteSystemPagableVm(), MiFlushPteList(), MiFlushUserPhysicalPteList(), MiProcessValidPteList(), MiReleaseSystemPtes(), MiRemoveMappedPtes(), MiRemoveMappedView(), MiRemoveUserPhysicalPagesVad(), MiReserveSystemPtes2(), MmOutPageKernelStack(), MmSetAddressRangeModified(), NtAllocateUserPhysicalPages(), NtFreeUserPhysicalPages(), NtMapUserPhysicalPages(), and NtMapUserPhysicalPagesScatter().

#define MM_MAXIMUM_WRITE_CLUSTER   (MM_MAXIMUM_DISK_IO_SIZE / PAGE_SIZE)
 

Definition at line 121 of file mi.h.

Referenced by MiCleanSection(), and MmShutdownSystem().

#define MM_MINIMUM_PAGED_POOL_NTAS   ((SIZE_T)(48*1024*1024))
 

Definition at line 82 of file mi.h.

Referenced by MiBuildPagedPool().

#define MM_NO_WS_EXPANSION   ((PLIST_ENTRY)0)
 

Definition at line 99 of file mi.h.

Referenced by MiDoReplacement(), MiEmptyAllWorkingSetsWorker(), MmCleanProcessAddressSpace(), MmTrimAllSystemPagableMemory(), and MmWorkingSetManager().

#define MM_NOACCESS   0x18
 

Definition at line 145 of file mi.h.

Referenced by MiChangeNoAccessForkPte(), MiCheckVirtualAddress(), MiLoadImageSection(), MiMakeProtectionMask(), MiProtectSpecialPool(), MmAccessFault(), MmFreeSpecialPool(), and MmSecureVirtualMemory().

#define MM_NOCACHE   0x8
 

Definition at line 142 of file mi.h.

Referenced by MiInitializePfn(), MiMakeProtectionMask(), MiProtectSpecialPool(), and MmMapVideoDisplay().

#define MM_PAGES_REQUIRED_FOR_MAPPED_IO   7
 

Definition at line 104 of file mi.h.

#define MM_PAGING_FILE_MDLS   2
 

Definition at line 2547 of file mi.h.

Referenced by MiUpdateModifiedWriterMdls().

 
#define MM_PFN_LOCK_ASSERT  ) 
 

Definition at line 951 of file mi.h.

Referenced by MiCheckControlArea(), MiCheckForControlAreaDeletion(), MiCompleteProtoPteFault(), MiDecrementReferenceCount(), MiDeletePte(), MiDeleteVirtualAddresses(), MiEliminateWorkingSetEntry(), MiEnsureAvailablePageOrWait(), MiFindImageSectionObject(), MiFlushEventCounter(), MiFlushInPageSupportBlock(), MiFlushPteList(), MiFreeEventCounter(), MiFreeInPageSupportBlock(), MiGetEventCounter(), MiGetInPageSupportBlock(), MiInitializeCopyOnWritePfn(), MiInitializePfn(), MiInitializePfnForOtherProcess(), MiInitializeReadInProgressPfn(), MiInitializeTransitionPfn(), MiInsertFrontModifiedNoWrite(), MiInsertImageSectionObject(), MiInsertPageInList(), MiInsertStandbyListAtFront(), MiLockCode(), MiMakeOutswappedPageResident(), MiMapPageToZeroInHyperSpace(), MiPageFileFull(), MiReleasePageFileSpace(), MiRemoveAnyPage(), MiRemoveImageSectionObject(), MiRemovePageByColor(), MiRemovePageFromList(), MiRemovePhysicalPages(), MiRemoveZeroPage(), MiResolveDemandZeroFault(), MiResolvePageFileFault(), MiResolveProtoPteFault(), MiUnlinkFreeOrZeroedPage(), and MiUnlinkPageFromList().

#define MM_PROTECTION_COPY_MASK   1
 

Definition at line 154 of file mi.h.

Referenced by MiProtectVirtualMemory(), MiSetProtectionOnSection(), and NtAllocateVirtualMemory().

#define MM_PROTECTION_EXECUTE_MASK   2
 

Definition at line 156 of file mi.h.

Referenced by MiResolveMappedFileFault().

#define MM_PROTECTION_OPERATION_MASK   7
 

Definition at line 155 of file mi.h.

#define MM_PROTECTION_WRITE_MASK   4
 

Definition at line 153 of file mi.h.

Referenced by MiCompleteProtoPteFault(), MiCreateImageFileMap(), MiGetWritablePagesInSection(), MiSetImageProtect(), and MiWriteComplete().

#define MM_READONLY   1
 

Definition at line 134 of file mi.h.

Referenced by MiAllocateVad(), MiCheckVirtualAddress(), MiCreateImageFileMap(), MiInitMachineDependent(), MmAccessFault(), and MmInitSystem().

#define MM_READWRITE   4
 

Definition at line 137 of file mi.h.

Referenced by MiAddWorkingSetPage(), MiAddWsleHash(), MiCheckVirtualAddress(), MiInitializePfn(), MiInitializeWorkingSetList(), MiInitMachineDependent(), MiMakeOutswappedPageResident(), MiMapLockedPagesInUserSpace(), MmAccessFault(), MmAllocateIndependentPages(), MmAllocateNonCachedMemory(), MmCreateKernelStack(), MmDbgWriteCheck(), MmGrowKernelStack(), MmInitializeProcessAddressSpace(), MmMakeKernelResourceSectionWritable(), MmMapVideoDisplay(), MmOutSwapProcess(), MmProbeAndLockPages(), MmSecureVirtualMemory(), MmSetBankedSection(), NtMapUserPhysicalPages(), and NtMapUserPhysicalPagesScatter().

#define MM_SECURE_DELETE_CHECK   0x55
 

Definition at line 158 of file mi.h.

Referenced by MiCheckSecuredVad(), MmUnmapViewOfSection(), and NtFreeVirtualMemory().

#define MM_SESSION_FAILURE_CAUSES   9
 

Definition at line 5376 of file mi.h.

#define MM_SESSION_FAILURE_NO_COMMIT   1
 

Definition at line 5367 of file mi.h.

Referenced by MiInitializeSessionPool(), MiSessionCommitImagePages(), MiSessionCommitPageTables(), MiSessionCreateInternal(), MiSessionInitializeWorkingSetList(), and MiShareSessionImage().

#define MM_SESSION_FAILURE_NO_IDS   0
 

Definition at line 5366 of file mi.h.

Referenced by MiSessionCreateInternal().

#define MM_SESSION_FAILURE_NO_IMAGE_VA_SPACE   7
 

Definition at line 5373 of file mi.h.

Referenced by MiSessionWideReserveImageAddress().

#define MM_SESSION_FAILURE_NO_NONPAGED_POOL   6
 

Definition at line 5372 of file mi.h.

Referenced by MiInitializeSessionPool(), MiInitializeSystemSpaceMap(), MiSessionInsertImage(), and MiSessionWideInsertImageAddress().

#define MM_SESSION_FAILURE_NO_PAGED_POOL   5
 

Definition at line 5371 of file mi.h.

Referenced by MiSessionWideInsertImageAddress().

#define MM_SESSION_FAILURE_NO_RESIDENT   2
 

Definition at line 5368 of file mi.h.

Referenced by MiInitializeSessionPool(), MiSessionCommitImagePages(), MiSessionCommitPageTables(), MiSessionCreateInternal(), and MiSessionInitializeWorkingSetList().

#define MM_SESSION_FAILURE_NO_SESSION_PAGED_POOL   8
 

Definition at line 5374 of file mi.h.

Referenced by MiInitializeSystemSpaceMap().

#define MM_SESSION_FAILURE_NO_SYSPTES   4
 

Definition at line 5370 of file mi.h.

Referenced by MiSessionCreateInternal().

#define MM_SESSION_FAILURE_RACE_DETECTED   3
 

Definition at line 5369 of file mi.h.

Referenced by MiSessionCreateInternal().

#define MM_SESSION_SPACE_DATA_SIZE   PAGE_SIZE
 

Definition at line 5227 of file mi.h.

 
#define MM_SESSION_SPACE_WS_LOCK_ASSERT  )     ASSERT (MmSessionSpace->WorkingSetLockOwner == PsGetCurrentThread())
 

Definition at line 5685 of file mi.h.

Referenced by MiCheckVirtualAddress(), MiSessionCommitPageTables(), and MmAccessFault().

 
#define MM_SET_EXPANSION_OWNER  ) 
 

Definition at line 952 of file mi.h.

Referenced by MmTrimAllSystemPagableMemory().

 
#define MM_SET_SESSION_LOCK_OWNER  ) 
 

Definition at line 5628 of file mi.h.

 
#define MM_SET_SESSION_RESOURCE_OWNER  ) 
 

Value:

Definition at line 5677 of file mi.h.

Referenced by MiEmptyWorkingSet(), and MmWorkingSetManager().

#define MM_SNAP_SESS_MEMORY_COUNTERS _index   ) 
 

Definition at line 5362 of file mi.h.

Referenced by MiDereferenceSession().

#define MM_SPECIAL_POOL_PTES   25000
 

Definition at line 4065 of file mi.h.

Referenced by MiInitializeSpecialPool(), and MmInitSystem().

#define MM_SYS_PTE_TABLES_MAX   5
 

Definition at line 2581 of file mi.h.

Referenced by MiInitializeSystemPtes().

 
#define MM_SYSTEM_WS_LOCK_ASSERT  )     ASSERT (PsGetCurrentThread() == MmSystemLockOwner);
 

Definition at line 1017 of file mi.h.

Referenced by MiAddWorkingSetPage(), MiDoReplacement(), MiFreeWsle(), MiReleaseWsle(), MiTrimWorkingSet(), and MiUpdateWsle().

#define MM_TRACK_COMMIT _index,
bump   ) 
 

Definition at line 4221 of file mi.h.

Referenced by MiAddWorkingSetPage(), MiAddWsleHash(), MiAllocatePoolPages(), MiCreateImageFileMap(), MiCreatePagingFileMap(), MiDereferenceSession(), MiFillSystemPageDirectory(), MiFindContiguousMemory(), MiFreeNonPagedPool(), MiFreePoolPages(), MiInitializeSessionPool(), MiInsertVad(), MiLoadImageSection(), MiMapViewOfDataSection(), MiPageFileFull(), MiRemoveVad(), MiReturnPageTablePageCommitment(), MiSegmentDelete(), MiSessionCommitImagePages(), MiSessionCommitPageTables(), MiSessionCreateInternal(), MiSessionInitializeWorkingSetList(), MiSetProtectionOnSection(), MiShareSessionImage(), MmAllocateIndependentPages(), MmAllocateNonCachedMemory(), MmAllocatePagesForMdl(), MmCleanProcessAddressSpace(), MmCreateKernelStack(), MmCreateProcessAddressSpace(), MmDeleteKernelStack(), MmDeleteProcessAddressSpace(), MmFreeDriverInitialization(), MmFreeNonCachedMemory(), MmFreePagesFromMdl(), MmInitSystem(), MmUnloadSystemImage(), NtAllocateVirtualMemory(), and NtFreeVirtualMemory().

#define MM_UNKNOWN_PROTECTION   0x100
 

Definition at line 146 of file mi.h.

Referenced by MiCheckVirtualAddress(), and MmAccessFault().

#define MM_USABLE_PAGES_FREE   32
 

Definition at line 92 of file mi.h.

Referenced by MiReleasePageFileSpace(), and MiWriteComplete().

#define MM_VIEW_SHARE   1
 

Definition at line 2341 of file mi.h.

Referenced by MiCloneProcessAddressSpace().

#define MM_VIEW_UNMAP   0
 

Definition at line 2340 of file mi.h.

Referenced by MiMapViewOfPhysicalSection().

#define MM_WORKING_SET_LIST_SEARCH   17
 

Definition at line 86 of file mi.h.

Referenced by MiReplaceWorkingSetEntryUsingFaultInfo().

#define MM_WRITECOPY   5
 

Definition at line 138 of file mi.h.

Referenced by MiInitMachineDependent(), and MiProtectSpecialPool().

#define MM_WS_EXPANSION_IN_PROGRESS   ((PLIST_ENTRY)35)
 

Definition at line 100 of file mi.h.

Referenced by MiEmptyAllWorkingSetsWorker(), MmCleanProcessAddressSpace(), MmTrimAllSystemPagableMemory(), and MmWorkingSetManager().

#define MM_WS_SWAPPED_OUT   ((PLIST_ENTRY)37)
 

Definition at line 101 of file mi.h.

Referenced by MmInSwapProcess(), and MmOutSwapProcess().

#define MM_ZERO_ACCESS   0
 

Definition at line 133 of file mi.h.

#define MmIsRetryIoStatus  ) 
 

Value:

(((S) == STATUS_INSUFFICIENT_RESOURCES) || \ ((S) == STATUS_WORKING_SET_QUOTA) || \ ((S) == STATUS_NO_MEMORY))

Definition at line 250 of file mi.h.

Referenced by MiDispatchFault(), MiFlushSectionInternal(), MiMakeOutswappedPageResident(), MiResolveProtoPteFault(), and MiWaitForInPageComplete().

#define MMSECTOR_MASK   0x1ff
 

Definition at line 111 of file mi.h.

Referenced by MiCreateImageFileMap().

#define MMSECTOR_SHIFT   9
 

Definition at line 109 of file mi.h.

Referenced by MiCreateImageFileMap(), MiEndingOffset(), and MiPurgeImageSection().

#define PFN_CONSISTENCY_SET
 

Definition at line 881 of file mi.h.

#define PFN_CONSISTENCY_UNSET
 

Definition at line 882 of file mi.h.

#define PROTECT_KSTACKS   1
 

Definition at line 149 of file mi.h.

#define SECTION_BASE_ADDRESS _NtSection   )     (*((PVOID *)&(_NtSection)->PointerToRelocations))
 

Definition at line 1985 of file mi.h.

Referenced by MiEnablePagingTheExecutive(), MiLocateKernelSections(), MmLockPagableDataSection(), MmLockPagableSectionByHandle(), and MmUnlockPagableImageSection().

#define SESSION_GLOBAL _Session   )     (_Session->GlobalVirtualAddress)
 

Definition at line 5300 of file mi.h.

Referenced by MiDereferenceSession(), MiInitializeSessionPool(), MiLoadImageSection(), MiSessionAddProcess(), MiSessionCreateInternal(), MiSessionInitializeWorkingSetList(), and MiSessionRemoveProcess().

#define StartOfAllocation   ReadInProgress
 

Definition at line 1241 of file mi.h.

#define STATUS_MAPPED_WRITER_COLLISION   (0xC0033333)
 

Definition at line 3882 of file mi.h.

Referenced by MiFlushSectionInternal(), and MiRemoveUnusedSegments().

#define SUBSECTION_COPY_ON_WRITE   4L
 

Definition at line 2227 of file mi.h.

#define SUBSECTION_READ_ONLY   1L
 

Definition at line 2225 of file mi.h.

#define SUBSECTION_READ_WRITE   2L
 

Definition at line 2226 of file mi.h.

#define SUBSECTION_SHARE_ALLOW   8L
 

Definition at line 2228 of file mi.h.

 
#define SYSLOAD_LOCK_OWNED_BY_ME  ) 
 

Definition at line 933 of file mi.h.

Referenced by MiRemoveImageSessionWide(), MiSessionCommitImagePages(), MiSessionInsertImage(), MiSessionLookupImage(), MiSessionRemoveImage(), MiSessionWideDereferenceImage(), MiSessionWideGetImageSize(), MiSessionWideInsertImageAddress(), MiSessionWideReserveImageAddress(), and MiShareSessionImage().

#define UNLOCK_ADDRESS_SPACE PROCESS   )     ExReleaseFastMutex( &((PROCESS)->AddressCreationLock))
 

Definition at line 1101 of file mi.h.

Referenced by MiCloneProcessAddressSpace(), MiProtectVirtualMemory(), MiWaitForForkToComplete(), MmMapViewOfSection(), MmSecureVirtualMemory(), MmUnsecureVirtualMemory(), NtAllocateVirtualMemory(), NtAreMappedFilesTheSame(), NtFreeVirtualMemory(), NtLockVirtualMemory(), and NtQueryVirtualMemory().

#define UNLOCK_AWE PROCESS,
OldIrql   )     ExReleaseSpinLock(&((PROCESS)->AweLock), OldIrql)
 

Definition at line 925 of file mi.h.

Referenced by MiMapViewOfPhysicalSection(), MiPhysicalViewAdjuster(), MiPhysicalViewInserter(), MiPhysicalViewRemover(), MiRemoveMappedView(), MiRemoveUserPhysicalPagesVad(), NtAllocateUserPhysicalPages(), NtFreeUserPhysicalPages(), NtMapUserPhysicalPages(), and NtMapUserPhysicalPagesScatter().

#define UNLOCK_EXPANSION OLDIRQL   ) 
 

Value:

MM_CLEAR_EXPANSION_OWNER (); \ ExReleaseSpinLock (&MmExpansionLock, OLDIRQL); \ ASSERT (KeGetCurrentIrql() <= APC_LEVEL);

Definition at line 961 of file mi.h.

Referenced by MiCheckAndSetSystemTrimCriteria(), MiCheckSystemTrimEndCriteria(), MiDereferenceSession(), MiEmptyAllWorkingSets(), MiEmptyAllWorkingSetsWorker(), MiLoadImageSection(), MiRearrangeWorkingSetExpansionList(), MiSessionAddProcess(), MiSessionInitializeWorkingSetList(), MiSessionInSwapProcess(), MiSessionOutSwapProcess(), MiSessionRemoveProcess(), MmAllowWorkingSetExpansion(), MmCleanProcessAddressSpace(), MmEnforceWorkingSetLimit(), MmInSwapProcess(), MmOutSwapProcess(), MmSessionCreate(), MmSetMemoryPriorityProcess(), MmTrimAllSystemPagableMemory(), and MmWorkingSetManager().

#define UNLOCK_EXPANSION_AND_THEN_WAIT OLDIRQL   ) 
 

Value:

{ \ KIRQL XXX; \ ASSERT (KeGetCurrentIrql() == 2); \ ASSERT (OLDIRQL <= APC_LEVEL); \ KiLockDispatcherDatabase (&XXX); \ MM_CLEAR_EXPANSION_OWNER (); \ KiReleaseSpinLock (&MmExpansionLock); \ (KeGetCurrentThread())->WaitIrql = OLDIRQL; \ (KeGetCurrentThread())->WaitNext = TRUE; \ }

Definition at line 965 of file mi.h.

Referenced by MiDereferenceSession(), and MmCleanProcessAddressSpace().

#define UNLOCK_EXPANSION_IF_ALPHA OLDIRQL   ) 
 

Definition at line 991 of file mi.h.

Referenced by MiAddWorkingSetPage(), MiDoReplacement(), MiInsertWsle(), MiMakeSpecialPoolPagable(), MiRemoveWorkingSetPages(), MmAccessFault(), and MmCleanProcessAddressSpace().

#define UNLOCK_HYPERSPACE OLDIRQL   )     ExReleaseSpinLock ( &(PsGetCurrentProcess())->HyperSpaceLock, OLDIRQL );
 

Definition at line 1024 of file mi.h.

#define UNLOCK_PFN OLDIRQL   ) 
 

Value:

PFN_CONSISTENCY_UNSET; \ MiUnlockPfnDatabase(OLDIRQL); \ ASSERT(KeGetCurrentIrql() <= APC_LEVEL);

Definition at line 896 of file mi.h.

Referenced by MiAccessCheck(), MiAddWorkingSetPage(), MiAddWsleHash(), MiAllocatePoolPages(), MiAttemptPageFileExtension(), MiAttemptPageFileReduction(), MiBuildForkPageTable(), MiBuildPagedPool(), MiCancelWriteOfMappedPfn(), MiCanFileBeTruncatedInternal(), MiCaptureSystemPte(), MiCheckAndSetSystemTrimCriteria(), MiCheckControlArea(), MiCheckControlAreaStatus(), MiCheckPageFileMapping(), MiCheckPurgeAndUpMapCount(), MiCleanSection(), MiCompleteProtoPteFault(), MiCopyOnWrite(), MiCreatePageTablesForPhysicalRange(), MiDecommitPages(), MiDecrementCloneBlockReference(), MiDeleteAddressesInWorkingSet(), MiDeleteFreeVm(), MiDeletePageTablesForPhysicalRange(), MiDeleteSystemPagableVm(), MiDeleteVirtualAddresses(), MiDereferenceSession(), MiDispatchFault(), MiDoesPdeExistAndMakeValid(), MiDoneWithThisPageGetAnother(), MiDownPfnReferenceCount(), MiDownShareCountFlushEntireTb(), MiEnablePagingOfDriverAtInit(), MiEnsureAvailablePageOrWait(), MiExtendPagingFileMaximum(), MiFillSystemPageDirectory(), MiFlushAcquire(), MiFlushDataSection(), MiFlushDirtyBitsToPfn(), MiFlushEventCounter(), MiFlushInPageSupportBlock(), MiFlushSectionInternal(), MiFlushTbAndCapture(), MiFreeInitializationCode(), MiFreeWsle(), MiGatherMappedPages(), MiGatherPagefilePages(), MiGetEventCounter(), MiGetInPageSupportBlock(), MiGetPageForHeader(), MiGetSystemCacheSubsection(), MiGrowWsleHash(), MiHandleForkTransitionPte(), MiInitializeSessionPool(), MiInitializeSpecialPool(), MiInitializeSystemCache(), MiInitializeWorkingSetList(), MiInitMachineDependent(), MiInsertPageFileInList(), MiLoadImageSection(), MiLockCode(), MiMakeOutswappedPageResident(), MiMakePdeExistAndMakeValid(), MiMakeSystemAddressValidPfn(), MiMakeSystemAddressValidPfnSystemWs(), MiMakeSystemAddressValidPfnWs(), MiMapImageHeaderInHyperSpace(), MiMappedPageWriter(), MiMapViewInSystemSpace(), MiMapViewOfImageSection(), MiMapViewOfPhysicalSection(), MiModifiedPageWriterWorker(), MiPageFileFull(), MiProcessValidPteList(), MiPurgeImageSection(), MiReleaseModifiedWriter(), MiReloadBootLoadedDrivers(), MiRemoveImageHeaderPage(), MiRemoveMappedPtes(), MiRemoveMappedView(), MiRemovePageFromWorkingSet(), MiRemoveUnusedSegments(), MiRemoveWorkingSetPages(), MiResetVirtualMemory(), MiResolveDemandZeroFault(), MiResolvePageFileFault(), MiResolveProtoPteFault(), MiResolveTransitionFault(), MiSegmentDelete(), MiSessionCommitImagePages(), MiSessionCommitPageTables(), MiSessionCopyOnWrite(), MiSessionCreateInternal(), MiSessionInitializeWorkingSetList(), MiSetPageModified(), MiSetPagingOfDriver(), MiSetProtectionOnTransitionPte(), MiSetSystemCodeProtection(), MiShareSessionImage(), MiSuperSectionDelete(), MiSwapWslEntries(), MiUnmapImageHeaderInHyperSpace(), MiUnmapLockedPagesInUserSpace(), MiUpCloneProcessRefCount(), MiUpCloneProtoRefCount(), MiUpControlAreaRefs(), MiUpdateImageHeaderPage(), MiUpdateVadPhysicalPages(), MiUpForkPageShareCount(), MiUpPfnReferenceCount(), MiWaitForForkToComplete(), MiWriteComplete(), MmAccessFault(), MmAddPhysicalMemory(), MmAdjustWorkingSetSize(), MmAllocateIndependentPages(), MmAllocateNonCachedMemory(), MmAllocatePagesForMdl(), MmCanFileBeTruncated(), MmCheckCachedPageState(), MmCleanProcessAddressSpace(), MmCopyToCachedPage(), MmCreateKernelStack(), MmCreateProcessAddressSpace(), MmCreateSection(), MmDeleteKernelStack(), MmDeleteProcessAddressSpace(), MmDisableModifiedWriteOfSection(), MmFlushImageSection(), MmFlushSection(), MmForceSectionClosed(), MmFreeLoaderBlock(), MmFreeNonCachedMemory(), MmFreePagesFromMdl(), MmGetPhysicalMemoryRanges(), MmGrowKernelStack(), MmInitializeProcessAddressSpace(), MmInitSystem(), MmInPageKernelStack(), MmInSwapProcess(), MmLockPagedPool(), MmMapUserAddressesToPage(), MmMapViewInSystemCache(), MmOutPageKernelStack(), MmOutSwapProcess(), MmPurgeSection(), MmRemovePhysicalMemory(), MmResetDriverPaging(), MmSetPageProtection(), MmShutdownSystem(), MmTrimAllSystemPagableMemory(), MmUnloadSystemImage(), MmUnlockCachedPage(), MmUnmapViewInSystemCache(), MmZeroPageThread(), NtAllocateUserPhysicalPages(), and NtCreateSuperSection().

#define UNLOCK_PFN2 OLDIRQL   ) 
 

Value:

PFN_CONSISTENCY_UNSET; \ MiUnlockPfnDatabase(OLDIRQL); \ ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);

Definition at line 905 of file mi.h.

Referenced by MiAddMdlTracker(), MiAllocatePoolPages(), MiAllocateSpecialPool(), MiFindContiguousMemory(), MiFreeMdlTracker(), MiFreeNonPagedPool(), MiLockPagedAddress(), MiMapViewOfPhysicalSection(), MiModifiedPageWriterTimerDispatch(), MiPhysicalViewAdjuster(), MiPhysicalViewInserter(), MiPhysicalViewRemover(), MiProtectSpecialPool(), MiRemoveUserPhysicalPagesVad(), MiUnlockPagedAddress(), MmFreeSpecialPool(), MmGatherMemoryForHibernate(), MmLockPagableSectionByHandle(), MmMapLockedPagesSpecifyCache(), MmProbeAndLockPages(), MmResourcesAvailable(), MmReturnMemoryForHibernate(), MmSetAddressRangeModified(), MmSetSpecialPool(), MmUnlockPagableImageSection(), MmUnlockPagedPool(), MmUnlockPages(), MmUnmapLockedPages(), and NtFreeUserPhysicalPages().

#define UNLOCK_PFN_AND_THEN_WAIT OLDIRQL   ) 
 

Value:

{ \ KIRQL XXX; \ ASSERT (KeGetCurrentIrql() == 2); \ ASSERT (OLDIRQL <= APC_LEVEL); \ KiLockDispatcherDatabase (&XXX); \ PFN_CONSISTENCY_UNSET; \ MiReleasePfnLock(); \ (KeGetCurrentThread())->WaitIrql = OLDIRQL; \ (KeGetCurrentThread())->WaitNext = TRUE; \ }

Definition at line 910 of file mi.h.

Referenced by MiCheckControlAreaStatus(), MiCheckPurgeAndUpMapCount(), MiCleanSection(), MiFlushSectionInternal(), MiMapImageHeaderInHyperSpace(), MmLockPagableSectionByHandle(), and MmPurgeSection().

#define UNLOCK_SESSION OLDIRQL   ) 
 

Value:

MM_CLEAR_SESSION_LOCK_OWNER (); \ ExReleaseSpinLock (&((SESSION_GLOBAL(MmSessionSpace))->SpinLock), OLDIRQL);

Definition at line 5635 of file mi.h.

Referenced by MiDereferenceSession(), and MiSessionAddProcess().

#define UNLOCK_SESSION_SPACE_WS OLDIRQL   ) 
 

Value:

MM_CLEAR_SESSION_RESOURCE_OWNER (); \ ExReleaseResource (&MmSessionSpace->WsLock); \ KeLowerIrql (OLDIRQL); \ ASSERT (KeGetCurrentIrql() <= APC_LEVEL);

Definition at line 5694 of file mi.h.

Referenced by MiAllocatePoolPages(), MiDeleteSystemPagableVm(), MiDispatchFault(), MiEmptyWorkingSet(), MiEnsureAvailablePageOrWait(), MiFreePoolPages(), MiLoadImageSection(), MiMakeSystemAddressValidPfnSystemWs(), MiMapViewInSystemSpace(), MiResolveTransitionFault(), MiSessionCommitImagePages(), MiSessionInsertImage(), MiSessionLookupImage(), MiSessionRemoveImage(), MiSetPagingOfDriver(), MiShareSessionImage(), MiUnmapViewInSystemSpace(), MmAccessFault(), MmUnloadSystemImage(), and MmWorkingSetManager().

#define UNLOCK_SYSTEM_VIEW_SPACE _Session   )     ExReleaseFastMutex (_Session->SystemSpaceViewLockPointer)
 

Definition at line 2647 of file mi.h.

Referenced by MiFreeSessionSpaceMap(), MiInsertInSystemSpace(), MiMapViewInSystemSpace(), and MiUnmapViewInSystemSpace().

#define UNLOCK_SYSTEM_WS OLDIRQL   ) 
 

Value:

ASSERT (MmSystemLockOwner == PsGetCurrentThread()); \ MmSystemLockOwner = NULL; \ ExReleaseResource (&MmSystemWsLock); \ KeLowerIrql (OLDIRQL); \ ASSERT (KeGetCurrentIrql() <= APC_LEVEL);

Definition at line 1005 of file mi.h.

Referenced by MiDeleteSystemPagableVm(), MiDispatchFault(), MiEmptyWorkingSet(), MiEnablePagingOfDriverAtInit(), MiEnsureAvailablePageOrWait(), MiInitializeSystemCache(), MiMakeSpecialPoolPagable(), MiMakeSystemAddressValidPfnSystemWs(), MiProtectSpecialPool(), MiRemoveMappedPtes(), MiResolveTransitionFault(), MiSetPagingOfDriver(), MmAccessFault(), MmAdjustWorkingSetSize(), MmCheckCachedPageState(), MmCopyToCachedPage(), MmEnforceWorkingSetLimit(), MmLockPagableSectionByHandle(), MmLockPagedPool(), MmResetDriverPaging(), MmUnmapViewInSystemCache(), and MmWorkingSetManager().

 
#define UNLOCK_SYSTEM_WS_NO_IRQL  ) 
 

Value:

ASSERT (MmSystemLockOwner == PsGetCurrentThread()); \ MmSystemLockOwner = NULL; \ ExReleaseResource (&MmSystemWsLock);

Definition at line 1012 of file mi.h.

Referenced by MmLockPagableSectionByHandle().

#define UNLOCK_WS PROCESS   ) 
 

Value:

MI_MUST_BE_SAFE(PROCESS); \ ExReleaseFastMutex(&((PROCESS)->WorkingSetLock));

Definition at line 1081 of file mi.h.

Referenced by MiCloneProcessAddressSpace(), MiDispatchFault(), MiEmptyWorkingSet(), MiGetWorkingSetInfo(), MiMapViewOfPhysicalSection(), MiResolveTransitionFault(), MmAccessFault(), MmAdjustWorkingSetSize(), MmCreateProcessAddressSpace(), MmEnforceWorkingSetLimit(), MmFlushVirtualMemory(), MmSetMemoryPriorityProcess(), MmWorkingSetManager(), NtAllocateUserPhysicalPages(), and NtFreeUserPhysicalPages().

#define UNLOCK_WS_AND_ADDRESS_SPACE PROCESS   ) 
 

Value:

UNLOCK_WS_UNSAFE(PROCESS); \ UNLOCK_ADDRESS_SPACE(PROCESS);

Definition at line 1097 of file mi.h.

Referenced by MiCreatePebOrTeb(), MiMapLockedPagesInUserSpace(), MiProtectVirtualMemory(), MiUnmapLockedPagesInUserSpace(), MmAssignProcessToJob(), MmCleanProcessAddressSpace(), MmDeleteTeb(), MmFlushVirtualMemory(), MmMapUserAddressesToPage(), MmMapViewOfSection(), MmSetBankedSection(), MmUnmapViewOfSection(), NtAllocateVirtualMemory(), NtFreeVirtualMemory(), NtLockVirtualMemory(), NtQueryVirtualMemory(), and NtUnlockVirtualMemory().

#define UNLOCK_WS_REGARDLESS PROCESS,
WSHELDSAFE   ) 
 

Value:

ASSERT (MI_WS_OWNER (PROCESS)); \ if (MI_IS_WS_UNSAFE (PROCESS)) { \ UNLOCK_WS_UNSAFE (PROCESS); \ WSHELDSAFE = FALSE; \ } \ else { \ UNLOCK_WS (PROCESS); \ WSHELDSAFE = TRUE; \ }

Definition at line 1109 of file mi.h.

Referenced by MiChargeCommitment(), MiDecrementCloneBlockReference(), MiEnsureAvailablePageOrWait(), MiMakeSystemAddressValid(), MiMakeSystemAddressValidPfnWs(), and MiWaitForForkToComplete().

#define UNLOCK_WS_UNSAFE PROCESS   ) 
 

Value:

MI_MUST_BE_UNSAFE(PROCESS); \ ExReleaseFastMutexUnsafe(&((PROCESS)->WorkingSetLock)); \ ASSERT (KeGetCurrentIrql() == APC_LEVEL);

Definition at line 1085 of file mi.h.

Referenced by MiCheckControlArea(), MiMapViewOfDataSection(), MiMapViewOfImageSection(), MiMapViewOfPhysicalSection(), MiProtectVirtualMemory(), MiSetProtectionOnSection(), MmSecureVirtualMemory(), MmUnmapViewOfSection(), NtAllocateVirtualMemory(), NtFreeVirtualMemory(), NtLockVirtualMemory(), and NtQueryVirtualMemory().

#define VI_POOL_FREELIST_END   ((ULONG_PTR)-1)
 

Definition at line 4081 of file mi.h.

Referenced by MiVerifyingDriverUnloading(), ViCancelPoolAllocation(), ViInitializeEntry(), and ViInsertPoolAllocation().

#define VI_VERIFYING_DIRECTLY   0x1
 

Definition at line 4108 of file mi.h.

Referenced by MiApplyDriverVerifier(), MiInitializeDriverVerifierList(), MmGetVerifierInformation(), VeAllocatePoolWithTagPriority(), VerifierAllocatePool(), VerifierAllocatePoolWithQuota(), VerifierAllocatePoolWithQuotaTag(), VerifierAllocatePoolWithTag(), and VerifierAllocatePoolWithTagPriority().

#define VI_VERIFYING_INVERSELY   0x2
 

Definition at line 4109 of file mi.h.

Referenced by MiApplyDriverVerifier().

#define WSLE_NULL_INDEX   ((ULONG)0xFFFFFFF)
 

Definition at line 78 of file mi.h.

Referenced by MiAddWorkingSetPage(), MiCloneProcessAddressSpace(), MiCopyOnWrite(), MiDeletePte(), MiDeleteSystemPagableVm(), MiEmptyWorkingSet(), MiFreeWsle(), MiInitializeSystemCache(), MiInitializeWorkingSetList(), MiLocateAndReserveWsle(), MiReleaseWsle(), MiRemoveMappedPtes(), MiRemovePageFromWorkingSet(), MiRemoveWorkingSetPages(), MiRemoveWsleFromFreeList(), MiSessionInitializeWorkingSetList(), MiSwapWslEntries(), MiUpdateWsle(), MmAdjustWorkingSetSize(), NtLockVirtualMemory(), and NtUnlockVirtualMemory().

#define X64K   (ULONG)65536
 

Definition at line 94 of file mi.h.

Referenced by MiCreateDataFileMap(), MiCreateImageFileMap(), MiFindEmptyAddressRangeInTree(), MiFindEmptySectionBaseDown(), MiGetPageForHeader(), MiInitializeSystemSpaceMap(), MiInitMachineDependent(), MiInsertInSystemSpace(), MiInsertVad(), MiLoadSystemImage(), MiMapLockedPagesInUserSpace(), MiMapViewInSystemSpace(), MiMapViewOfDataSection(), MiMapViewOfImageSection(), MiMapViewOfPhysicalSection(), MiUnmapViewInSystemSpace(), MmMapVideoDisplay(), MmUnmapVideoDisplay(), NtAllocateVirtualMemory(), and NtMapViewOfSection().

#define ZERO_LARGE LargeInteger   ) 
 

Value:

(LargeInteger).LowPart = 0; \ (LargeInteger).HighPart = 0;

Definition at line 1128 of file mi.h.

Referenced by MiCreateImageFileMap(), MiLoadImageSection(), MmGetPhysicalAddress(), MmInitializeProcessAddressSpace(), NtCreateSection(), and NtMapViewOfSection().


Typedef Documentation

typedef struct _CONTROL_AREA CONTROL_AREA
 

Referenced by MiCreateImageFileMap(), MiCreatePagingFileMap(), MiSectionInitialization(), and MmCreateSection().

typedef struct _EVENT_COUNTER EVENT_COUNTER
 

typedef struct _IMAGE_ENTRY_IN_SESSION IMAGE_ENTRY_IN_SESSION
 

Referenced by MiSessionInsertImage().

typedef struct _LARGE_CONTROL_AREA LARGE_CONTROL_AREA
 

Referenced by MiCreateImageFileMap(), and MmCreateSection().

typedef struct _LOCK_HEADER LOCK_HEADER
 

Referenced by MmInitializeProcessAddressSpace().

typedef struct _LOCK_TRACKER LOCK_TRACKER
 

Referenced by MiAddMdlTracker().

typedef struct _MI_FREED_SPECIAL_POOL MI_FREED_SPECIAL_POOL
 

typedef struct _MI_NEXT_ESTIMATION_SLOT_CONST MI_NEXT_ESTIMATION_SLOT_CONST
 

typedef struct _MI_PHYSICAL_VIEW MI_PHYSICAL_VIEW
 

Referenced by NtAllocateVirtualMemory().

typedef struct _MI_VERIFIER_DRIVER_ENTRY MI_VERIFIER_DRIVER_ENTRY
 

Referenced by MiApplyDriverVerifier(), and MiInitializeDriverVerifierList().

typedef struct _MI_VERIFIER_POOL_HEADER MI_VERIFIER_POOL_HEADER
 

Referenced by MmFreeSpecialPool(), and ViPostPoolAllocation().

typedef struct _MM_DRIVER_VERIFIER_DATA MM_DRIVER_VERIFIER_DATA
 

typedef struct _MM_PAGED_POOL_INFO MM_PAGED_POOL_INFO
 

typedef struct _MM_SESSION_SPACE MM_SESSION_SPACE
 

typedef struct _MM_SESSION_SPACE_FLAGS MM_SESSION_SPACE_FLAGS
 

typedef struct _MMADDRESS_LIST MMADDRESS_LIST
 

typedef struct _MMADDRESS_NODE MMADDRESS_NODE
 

typedef struct _MMBANKED_SECTION MMBANKED_SECTION
 

Referenced by MmSetBankedSection().

typedef struct _MMCLONE_BLOCK MMCLONE_BLOCK
 

Referenced by MiCloneProcessAddressSpace().

typedef struct _MMCLONE_DESCRIPTOR MMCLONE_DESCRIPTOR
 

Referenced by MiCloneProcessAddressSpace().

typedef struct _MMCLONE_HEADER MMCLONE_HEADER
 

Referenced by MiCloneProcessAddressSpace().

typedef struct _MMDEREFERENCE_SEGMENT_HEADER MMDEREFERENCE_SEGMENT_HEADER
 

typedef struct _MMEVENT_COUNT_LIST MMEVENT_COUNT_LIST
 

typedef struct _MMEXTEND_INFO MMEXTEND_INFO
 

Referenced by MiMapViewOfDataSection().

typedef struct _MMFLUSH_BLOCK MMFLUSH_BLOCK
 

typedef struct _MMFREE_POOL_ENTRY MMFREE_POOL_ENTRY
 

Referenced by MiAllocatePoolPages(), and MmSetKernelDumpRange().

typedef struct _MMINPAGE_SUPPORT MMINPAGE_SUPPORT
 

typedef struct _MMINPAGE_SUPPORT_LIST MMINPAGE_SUPPORT_LIST
 

typedef struct _MMLOCK_CONFLICT MMLOCK_CONFLICT
 

Referenced by NtLockVirtualMemory().

typedef struct _MMMOD_WRITER_LISTHEAD MMMOD_WRITER_LISTHEAD
 

typedef struct _MMMOD_WRITER_MDL_ENTRY MMMOD_WRITER_MDL_ENTRY
 

Referenced by NtCreatePagingFile().

typedef struct _MMPAGE_FILE_EXPANSION MMPAGE_FILE_EXPANSION
 

typedef struct _MMPAGE_READ MMPAGE_READ
 

typedef struct _MMPAGING_FILE MMPAGING_FILE
 

Referenced by NtCreatePagingFile().

typedef struct _MMPFN MMPFN
 

Referenced by MiInitMachineDependent(), and MmSetKernelDumpRange().

typedef struct _MMPFNENTRY MMPFNENTRY
 

typedef struct _MMPTE_FLUSH_LIST MMPTE_FLUSH_LIST
 

typedef struct _MMSECTION_FLAGS MMSECTION_FLAGS
 

typedef struct _MMSECURE_ENTRY MMSECURE_ENTRY
 

Referenced by MmSecureVirtualMemory().

typedef struct _MMSESSION MMSESSION
 

typedef enum _MMSHARE_TYPE MMSHARE_TYPE
 

typedef struct _MMSUBSECTION_FLAGS MMSUBSECTION_FLAGS
 

typedef enum _MMSYSTEM_PTE_POOL_TYPE MMSYSTEM_PTE_POOL_TYPE
 

typedef struct _MMVAD MMVAD
 

Referenced by MiInsertVad(), MiMapViewOfDataSection(), MiMapViewOfImageSection(), MiMapViewOfPhysicalSection(), and MmSecureVirtualMemory().

typedef struct _MMVAD_FLAGS MMVAD_FLAGS
 

typedef struct _MMVAD_FLAGS2 MMVAD_FLAGS2
 

typedef struct _MMVAD_SHORT MMVAD_SHORT
 

Referenced by NtAllocateVirtualMemory().

typedef struct _MMVIEW MMVIEW
 

Referenced by MiInsertInSystemSpace().

typedef struct _MMWORKING_SET_EXPANSION_HEAD MMWORKING_SET_EXPANSION_HEAD
 

typedef struct _MMWSL MMWSL
 

Referenced by MiInitMachineDependent().

typedef struct _MMWSLE MMWSLE
 

Referenced by MiInitializeSystemCache().

typedef struct _MMWSLE_HASH MMWSLE_HASH
 

Referenced by MiGrowWsleHash(), and MiRemoveWorkingSetPages().

typedef struct _MMWSLENTRY MMWSLENTRY
 

Referenced by MiDeletePte().

typedef struct _CONTROL_AREA * PCONTROL_AREA
 

typedef struct _EVENT_COUNTER * PEVENT_COUNTER
 

typedef struct _IMAGE_ENTRY_IN_SESSION * PIMAGE_ENTRY_IN_SESSION
 

typedef struct _LARGE_CONTROL_AREA * PLARGE_CONTROL_AREA
 

Referenced by MiCreateImageFileMap().

typedef struct _LOCK_HEADER * PLOCK_HEADER
 

Referenced by MiAddMdlTracker().

typedef struct _LOCK_TRACKER * PLOCK_TRACKER
 

Referenced by MiAddMdlTracker().

typedef struct _MI_FREED_SPECIAL_POOL * PMI_FREED_SPECIAL_POOL
 

Referenced by MmFreeSpecialPool().

typedef struct _MI_PHYSICAL_VIEW * PMI_PHYSICAL_VIEW
 

typedef struct _MI_VERIFIER_DRIVER_ENTRY * PMI_VERIFIER_DRIVER_ENTRY
 

typedef struct _MI_VERIFIER_POOL_HEADER * PMI_VERIFIER_POOL_HEADER
 

Referenced by ViPostPoolAllocation().

typedef struct _MM_DRIVER_VERIFIER_DATA * PMM_DRIVER_VERIFIER_DATA
 

typedef struct _MM_PAGED_POOL_INFO * PMM_PAGED_POOL_INFO
 

Referenced by MiAllocatePoolPages().

typedef struct _MM_SESSION_SPACE * PMM_SESSION_SPACE
 

typedef struct _MMADDRESS_LIST * PMMADDRESS_LIST
 

typedef struct _MMADDRESS_NODE * PMMADDRESS_NODE
 

typedef struct _MMBANKED_SECTION * PMMBANKED_SECTION
 

Referenced by MmSetBankedSection().

typedef MMCLONE_BLOCK* PMMCLONE_BLOCK
 

Definition at line 2463 of file mi.h.

Referenced by MiDeletePte(), and MiDeleteValidAddress().

typedef struct _MMCLONE_DESCRIPTOR * PMMCLONE_DESCRIPTOR
 

Referenced by MiDeletePte().

typedef struct _MMCLONE_HEADER * PMMCLONE_HEADER
 

Referenced by MiCloneProcessAddressSpace().

typedef struct _MMEVENT_COUNT_LIST * PMMEVENT_COUNT_LIST
 

typedef struct _MMEXTEND_INFO * PMMEXTEND_INFO
 

Referenced by MiRemoveMappedView().

typedef struct _MMFLUSH_BLOCK * PMMFLUSH_BLOCK
 

typedef struct _MMFREE_POOL_ENTRY * PMMFREE_POOL_ENTRY
 

Referenced by MiAllocatePoolPages().

typedef struct _MMINPAGE_SUPPORT * PMMINPAGE_SUPPORT
 

typedef struct _MMINPAGE_SUPPORT_LIST * PMMINPAGE_SUPPORT_LIST
 

typedef struct _MMLOCK_CONFLICT * PMMLOCK_CONFLICT
 

Referenced by MiCheckForUserStackOverflow(), and MiInsertConflictInList().

typedef struct _MMMOD_WRITER_LISTHEAD * PMMMOD_WRITER_LISTHEAD
 

typedef struct _MMMOD_WRITER_MDL_ENTRY * PMMMOD_WRITER_MDL_ENTRY
 

Referenced by MiUpdateModifiedWriterMdls().

typedef struct _MMPAGE_FILE_EXPANSION * PMMPAGE_FILE_EXPANSION
 

typedef struct _MMPAGE_READ * PMMPAGE_READ
 

typedef struct _MMPAGING_FILE * PMMPAGING_FILE
 

typedef struct _MMPFN * PMMPFN
 

Referenced by MiAccessCheck().

typedef struct _MMPTE_FLUSH_LIST * PMMPTE_FLUSH_LIST
 

Referenced by MiDeletePte().

typedef struct _MMSECURE_ENTRY * PMMSECURE_ENTRY
 

Referenced by MmSecureVirtualMemory().

typedef struct _MMSESSION * PMMSESSION
 

typedef struct _MMVAD * PMMVAD
 

typedef struct _MMVAD_SHORT * PMMVAD_SHORT
 

Referenced by MiCloneProcessAddressSpace().

typedef struct _MMVIEW * PMMVIEW
 

Referenced by MiInsertInSystemSpace().

typedef struct _MMWSL * PMMWSL
 

typedef MMWSLE* PMMWSLE
 

Definition at line 1591 of file mi.h.

typedef struct _MMWSLE_HASH * PMMWSLE_HASH
 

typedef struct _SECTION * PSECTION
 

typedef struct _SEGMENT * PSEGMENT
 

typedef struct _SUBSECTION * PSUBSECTION
 

typedef struct _UNLOADED_DRIVERS * PUNLOADED_DRIVERS
 

typedef struct _VI_POOL_ENTRY * PVI_POOL_ENTRY
 

Referenced by ViReservePoolAllocation().

typedef struct _VI_POOL_ENTRY_INUSE * PVI_POOL_ENTRY_INUSE
 

typedef ULONG * PWSLE_NUMBER
 

Definition at line 1231 of file mi.h.

Referenced by MiUpdateWsle().

typedef struct _SECTION SECTION
 

Referenced by CmpAppendSection(), MiSectionInitialization(), MmCreateSection(), and NtAllocateVirtualMemory().

typedef enum _SECTION_CHECK_TYPE SECTION_CHECK_TYPE
 

typedef struct _SEGMENT SEGMENT
 

Referenced by MiCreateDataFileMap(), MiCreateImageFileMap(), MiCreatePagingFileMap(), and MiSectionInitialization().

typedef struct _SUBSECTION SUBSECTION
 

Referenced by MiCreateDataFileMap(), MiCreateImageFileMap(), MiCreatePagingFileMap(), MmCreateSection(), and MmExtendSection().

typedef struct _UNLOADED_DRIVERS UNLOADED_DRIVERS
 

typedef struct _VI_POOL_ENTRY VI_POOL_ENTRY
 

Referenced by ViReservePoolAllocation().

typedef struct _VI_POOL_ENTRY_INUSE VI_POOL_ENTRY_INUSE
 

typedef ULONG WSLE_NUMBER
 

Definition at line 1231 of file mi.h.

Referenced by MiAddValidPageToWorkingSet(), MiAddWorkingSetPage(), MiAddWsleHash(), MiCloneProcessAddressSpace(), MiCopyOnWrite(), MiDeleteSystemPagableVm(), MiInitializeWorkingSetList(), MiInsertWsle(), MiLocateAndReserveWsle(), MiLocateWsle(), MiLockCode(), MiProtectSpecialPool(), MiRemovePageFromWorkingSet(), MiRemoveWorkingSetPages(), MiRemoveWsleFromFreeList(), MiSessionCopyOnWrite(), MiSessionInitializeWorkingSetList(), MiSwapWslEntries(), MiUpdateWsle(), MmAccessFault(), MmAdjustWorkingSetSize(), MmCheckCachedPageState(), MmCopyToCachedPage(), MmTrimAllSystemPagableMemory(), and MmUnmapViewInSystemCache().


Enumeration Type Documentation

enum _MMSHARE_TYPE
 

Enumeration values:
Normal 
ShareCountOnly 
AndValid 

Definition at line 1524 of file mi.h.

01526 : 01527 // 01528 // Pfn - the PFN index to operate on. //

enum _MMSYSTEM_PTE_POOL_TYPE
 

Enumeration values:
SystemPteSpace 
NonPagedPoolExpansion 
MaximumPtePoolTypes 

Definition at line 2583 of file mi.h.

02587 {

enum _SECTION_CHECK_TYPE
 

Enumeration values:
CheckDataSection 
CheckImageSection 
CheckUserDataSection 
CheckBothSection 

Definition at line 1988 of file mi.h.

02003 {


Function Documentation

NTSTATUS MiAccessCheck IN PMMPTE  PointerPte,
IN BOOLEAN  WriteOperation,
IN KPROCESSOR_MODE  PreviousMode,
IN ULONG  Protection,
IN BOOLEAN  CallerHoldsPfnLock
 

Definition at line 42 of file acceschk.c.

References ASSERT, FALSE, KeIsAttachedProcess, KPROCESSOR_MODE, LOCK_PFN, MI_PFN_ELEMENT, MiHighestUserPte, MM_GUARD_PAGE, MmReadWrite, _MMPFN::OriginalPte, PMMPFN, _MMPTE::u, _MMPFN::u3, UNLOCK_PFN, and UserMode.

Referenced by MiResolveProtoPteFault(), and MmAccessFault().

00052 : 00053 00054 00055 00056 Arguments: 00057 00058 PointerPte - Supplies the pointer to the PTE which caused the 00059 page fault. 00060 00061 WriteOperation - Supplies 1 if the operation is a write, 0 if 00062 the operation is a read. 00063 00064 PreviousMode - Supplies the previous mode, one of UserMode or KernelMode. 00065 00066 Protection - Supplies the protection mask to check. 00067 00068 CallerHoldsPfnLock - Supplies TRUE if the PFN lock is held, FALSE otherwise. 00069 00070 Return Value: 00071 00072 Returns TRUE if access to the page is allowed, FALSE otherwise. 00073 00074 Environment: 00075 00076 Kernel mode, APCs disabled. 00077 00078 --*/ 00079 00080 { 00081 MMPTE PteContents; 00082 KIRQL OldIrql; 00083 PMMPFN Pfn1; 00084 00085 // 00086 // Check to see if the owner bit allows access to the previous mode. 00087 // Access is not allowed if the owner is kernel and the previous 00088 // mode is user. Access is also disallowed if the write operation 00089 // is true and the write field in the PTE is false. 00090 // 00091 00092 // 00093 // If both an access violation and a guard page violation could 00094 // occur for the page, the access violation must be returned. 00095 // 00096 00097 if (PreviousMode == UserMode) { 00098 if (PointerPte > MiHighestUserPte) { 00099 return STATUS_ACCESS_VIOLATION; 00100 } 00101 } 00102 00103 PteContents = *PointerPte; 00104 00105 if (PteContents.u.Hard.Valid == 1) { 00106 00107 // 00108 // Valid pages cannot be guard page violations. 00109 // 00110 00111 if (WriteOperation) { 00112 if ((PteContents.u.Hard.Write == 1) || 00113 (PteContents.u.Hard.CopyOnWrite == 1)) { 00114 return STATUS_SUCCESS; 00115 } else { 00116 return STATUS_ACCESS_VIOLATION; 00117 } 00118 } else { 00119 return STATUS_SUCCESS; 00120 } 00121 00122 } else { 00123 00124 if ((MmReadWrite[Protection] - (CCHAR)WriteOperation) < 10) { 00125 return STATUS_ACCESS_VIOLATION; 00126 } else { 00127 00128 // 00129 // Check for a guard page fault. 00130 // 00131 00132 if (Protection & MM_GUARD_PAGE) { 00133 00134 // 00135 // If this thread is attached to a different process, 00136 // return an access violation rather than a guard 00137 // page exception. The prevents problems with unwanted 00138 // stack expansion and unexpected guard page behavior 00139 // from debuggers. 00140 00141 if (KeIsAttachedProcess()) { 00142 return STATUS_ACCESS_VIOLATION; 00143 } 00144 00145 // 00146 // Check to see if this is a transition PTE, if so, 00147 // the PFN database original contents field needs to be 00148 // updated. 00149 // 00150 00151 if ((PteContents.u.Soft.Transition == 1) && 00152 (PteContents.u.Soft.Prototype == 0)) { 00153 00154 // 00155 // Acquire the PFN mutex and check to see if the 00156 // PTE is still in the transition state, and, if so 00157 // update the original PTE in the pfn database. 00158 // 00159 00160 if (CallerHoldsPfnLock == FALSE) { 00161 LOCK_PFN (OldIrql); 00162 } 00163 PteContents = *(volatile MMPTE *)PointerPte; 00164 if ((PteContents.u.Soft.Transition == 1) && 00165 (PteContents.u.Soft.Prototype == 0)) { 00166 00167 // 00168 // Still in transition, update the PFN database. 00169 // 00170 00171 Pfn1 = MI_PFN_ELEMENT ( 00172 PteContents.u.Trans.PageFrameNumber); 00173 00174 ASSERT (Pfn1->u3.e1.PrototypePte == 0); 00175 Pfn1->OriginalPte.u.Soft.Protection = 00176 Protection & ~MM_GUARD_PAGE; 00177 } 00178 if (CallerHoldsPfnLock == FALSE) { 00179 UNLOCK_PFN (OldIrql); 00180 } 00181 } 00182 00183 PointerPte->u.Soft.Protection = Protection & ~MM_GUARD_PAGE; 00184 00185 return STATUS_GUARD_PAGE_VIOLATION; 00186 } 00187 return STATUS_SUCCESS; 00188 } 00189 } 00190 }

VOID MiAddMappedPtes IN PMMPTE  FirstPte,
IN ULONG  NumberOfPtes,
IN PCONTROL_AREA  ControlArea
 

Definition at line 287 of file mapcache.c.

References ASSERT, MiProtoAddressForKernelPte, MM_COLOR_MASK, _SUBSECTION::NextSubsection, PTE_SHIFT, _SUBSECTION::PtesInSubsection, _SUBSECTION::SubsectionBase, _MMPTE::u, and ZeroKernelPte.

Referenced by MiMapViewInSystemSpace(), and MiShareSessionImage().

00295 : 00296 00297 This function maps a view in the current address space to the 00298 specified control area. The page protection is identical to that 00299 of the prototype PTE. 00300 00301 This routine assumes the caller has called MiCheckPurgeAndUpMapCount, 00302 hence the PFN lock is not needed here. 00303 00304 Arguments: 00305 00306 FirstPte - Supplies a pointer to the first PTE of the current address 00307 space to initialize. 00308 00309 NumberOfPtes - Supplies the number of PTEs to initialize. 00310 00311 ControlArea - Supplies the control area to point the PTEs at. 00312 00313 Return Value: 00314 00315 None. 00316 00317 Environment: 00318 00319 Kernel mode. 00320 00321 --*/ 00322 00323 { 00324 PMMPTE PointerPte; 00325 PMMPTE ProtoPte; 00326 PMMPTE LastProto; 00327 PMMPTE LastPte; 00328 PSUBSECTION Subsection; 00329 00330 if (ControlArea->u.Flags.GlobalOnlyPerSession == 0) { 00331 Subsection = (PSUBSECTION)(ControlArea + 1); 00332 } 00333 else { 00334 Subsection = (PSUBSECTION)((PLARGE_CONTROL_AREA)ControlArea + 1); 00335 } 00336 00337 PointerPte = FirstPte; 00338 ASSERT (NumberOfPtes != 0); 00339 LastPte = FirstPte + NumberOfPtes; 00340 00341 ASSERT (ControlArea->NumberOfMappedViews >= 1); 00342 ASSERT (ControlArea->NumberOfUserReferences >= 1); 00343 ASSERT (ControlArea->u.Flags.HadUserReference == 1); 00344 ASSERT (ControlArea->NumberOfSectionReferences != 0); 00345 00346 ASSERT (ControlArea->u.Flags.BeingCreated == 0); 00347 ASSERT (ControlArea->u.Flags.BeingDeleted == 0); 00348 ASSERT (ControlArea->u.Flags.BeingPurged == 0); 00349 00350 ProtoPte = Subsection->SubsectionBase; 00351 00352 LastProto = &Subsection->SubsectionBase[Subsection->PtesInSubsection]; 00353 00354 while (PointerPte < LastPte) { 00355 00356 if (ProtoPte >= LastProto) { 00357 00358 // 00359 // Handle extended subsections. 00360 // 00361 00362 Subsection = Subsection->NextSubsection; 00363 ProtoPte = Subsection->SubsectionBase; 00364 LastProto = &Subsection->SubsectionBase[ 00365 Subsection->PtesInSubsection]; 00366 } 00367 ASSERT (PointerPte->u.Long == ZeroKernelPte.u.Long); 00368 PointerPte->u.Long = MiProtoAddressForKernelPte (ProtoPte); 00369 00370 ASSERT (((ULONG_PTR)PointerPte & (MM_COLOR_MASK << PTE_SHIFT)) == 00371 (((ULONG_PTR)ProtoPte & (MM_COLOR_MASK << PTE_SHIFT)))); 00372 00373 PointerPte += 1; 00374 ProtoPte += 1; 00375 } 00376 00377 return; 00378 }

VOID MiAddSystemPtes IN PMMPTE  StartingPte,
IN ULONG  NumberOfPtes,
IN MMSYSTEM_PTE_POOL_TYPE  SystemPtePoolType
 

Definition at line 1907 of file sysptes.c.

References ASSERT, Index, MiFillMemoryPte, MiReleaseSystemPtes(), MM_KERNEL_NOACCESS_PTE, MmSystemPtesEnd, MmSystemPtesStart, NULL, SystemPteSpace, TRUE, and USHORT.

Referenced by MiInitMachineDependent(), and MmInitSystem().

01915 : 01916 01917 This routine adds newly created PTEs to the specified pool. 01918 01919 Arguments: 01920 01921 StartingPte - Supplies the address of the first PTE to put in the pool. 01922 01923 NumberOfPtes - Supplies the number of PTEs to put in the pool. 01924 01925 SystemPtePoolType - Supplies the PTE type of the pool to expand, one of 01926 SystemPteSpace or NonPagedPoolExpansion. 01927 01928 Return Value: 01929 01930 None. 01931 01932 Environment: 01933 01934 Kernel mode. 01935 01936 --*/ 01937 01938 { 01939 PMMPTE EndingPte; 01940 01941 EndingPte = StartingPte + NumberOfPtes - 1; 01942 01943 #ifdef _MI_SYSPTE_DEBUG_ 01944 MiRebuildPteTracker (StartingPte, NumberOfPtes); 01945 #endif 01946 01947 if (StartingPte < MmSystemPtesStart[SystemPtePoolType]) { 01948 MmSystemPtesStart[SystemPtePoolType] = StartingPte; 01949 } 01950 01951 if (EndingPte > MmSystemPtesEnd[SystemPtePoolType]) { 01952 MmSystemPtesEnd[SystemPtePoolType] = EndingPte; 01953 } 01954 01955 #ifdef _MI_SYSPTE_DEBUG_ 01956 01957 if (SystemPtePoolType == SystemPteSpace && MiPteTracker != NULL) { 01958 01959 ULONG i; 01960 ULONG_PTR Index; 01961 PMMPTE_TRACKER Tracker; 01962 01963 Index = StartingPte - MmSystemPtesStart[SystemPteSpace]; 01964 Tracker = &MiPteTracker[Index]; 01965 01966 ASSERT (NumberOfPtes < 0x10000); 01967 Tracker->NumberOfPtes = (USHORT)NumberOfPtes; 01968 01969 for (i = 0; i < NumberOfPtes; i += 1) { 01970 Tracker->InUse = TRUE; 01971 Tracker += 1; 01972 } 01973 } 01974 01975 MiFillMemoryPte (StartingPte, NumberOfPtes * sizeof (MMPTE), MM_KERNEL_NOACCESS_PTE); 01976 #endif 01977 01978 #ifdef _MI_GUARD_PTE_ 01979 MiReleaseSystemPtes (StartingPte, NumberOfPtes - 1, SystemPtePoolType); 01980 #else 01981 MiReleaseSystemPtes (StartingPte, NumberOfPtes, SystemPtePoolType); 01982 #endif 01983 }

VOID MiAddValidPageToWorkingSet IN PVOID  VirtualAddress,
IN PMMPTE  PointerPte,
IN PMMPFN  Pfn1,
IN ULONG  WsleMask
 

Definition at line 4056 of file pagfault.c.

References ASSERT, _MMWSLE::e1, FALSE, MI_IS_PAGE_TABLE_ADDRESS, MI_IS_PROCESS_SPACE_ADDRESS, MI_IS_SESSION_ADDRESS, MI_IS_SESSION_PTE, MI_IS_SYSTEM_CACHE_ADDRESS, MI_SET_PTE_IN_WORKING_SET, MiLocateAndReserveWsle(), MiUpdateWsle(), MmSessionSpace, MmSystemCacheWs, MmSystemCacheWsle, MmWsle, PERFINFO_ADDTOWS, PsGetCurrentProcess, _MMWSLENTRY::SameProtectAsProto, _MMWSLE::u1, _EPROCESS::UniqueProcessId, _MM_SESSION_SPACE::Vm, _EPROCESS::Vm, _MMSUPPORT::VmWorkingSetList, _MM_SESSION_SPACE::Wsle, and WSLE_NUMBER.

Referenced by MiAllocatePoolPages(), MiCompleteProtoPteFault(), MiDispatchFault(), MiMakeSpecialPoolPagable(), MiResolveDemandZeroFault(), MiResolveTransitionFault(), and MiSessionCommitPageTables().

04065 : 04066 04067 This routine adds the specified virtual address into the 04068 appropriate working set list. 04069 04070 Arguments: 04071 04072 VirtualAddress - Supplies the address to add to the working set list. 04073 04074 PointerPte - Supplies a pointer to the pte that is now valid. 04075 04076 Pfn1 - Supplies the PFN database element for the physical page 04077 mapped by the virtual address. 04078 04079 WsleMask - Supplies a mask (protection and flags) to OR into the 04080 working set list entry. 04081 04082 Return Value: 04083 04084 None. 04085 04086 Environment: 04087 04088 Kernel mode, APCs disabled, working set lock. PFN lock NOT held. 04089 04090 --*/ 04091 04092 { 04093 WSLE_NUMBER WorkingSetIndex; 04094 PEPROCESS Process; 04095 PMMSUPPORT WsInfo; 04096 PMMWSLE Wsle; 04097 04098 ASSERT (MI_IS_PAGE_TABLE_ADDRESS(PointerPte)); 04099 ASSERT (PointerPte->u.Hard.Valid == 1); 04100 04101 if (MI_IS_SESSION_ADDRESS (VirtualAddress) || MI_IS_SESSION_PTE (VirtualAddress)) { 04102 // 04103 // Current process's session space working set. 04104 // 04105 04106 WsInfo = &MmSessionSpace->Vm; 04107 Wsle = MmSessionSpace->Wsle; 04108 } 04109 else if (MI_IS_PROCESS_SPACE_ADDRESS(VirtualAddress)) { 04110 04111 // 04112 // Per process working set. 04113 // 04114 04115 Process = PsGetCurrentProcess(); 04116 WsInfo = &Process->Vm; 04117 Wsle = MmWsle; 04118 04119 PERFINFO_ADDTOWS(Pfn1, VirtualAddress, Process->UniqueProcessId) 04120 } else { 04121 04122 // 04123 // System cache working set. 04124 // 04125 04126 WsInfo = &MmSystemCacheWs; 04127 Wsle = MmSystemCacheWsle; 04128 04129 PERFINFO_ADDTOWS(Pfn1, VirtualAddress, (HANDLE) -1); 04130 } 04131 04132 WorkingSetIndex = MiLocateAndReserveWsle (WsInfo); 04133 MiUpdateWsle (&WorkingSetIndex, 04134 VirtualAddress, 04135 WsInfo->VmWorkingSetList, 04136 Pfn1); 04137 Wsle[WorkingSetIndex].u1.Long |= WsleMask; 04138 04139 #if DBG 04140 if (MI_IS_SYSTEM_CACHE_ADDRESS(VirtualAddress)) { 04141 ASSERT (MmSystemCacheWsle[WorkingSetIndex].u1.e1.SameProtectAsProto); 04142 } 04143 #endif //DBG 04144 04145 MI_SET_PTE_IN_WORKING_SET (PointerPte, WorkingSetIndex); 04146 04147 KeFillEntryTb ((PHARDWARE_PTE)PointerPte, VirtualAddress, FALSE); 04148 return; 04149 }

VOID MiAdjustWorkingSetManagerParameters BOOLEAN  WorkStation  ) 
 

Definition at line 259 of file wsmanage.c.

References FALSE, KeInitializeEvent, MiIdealPassFaultCountDisable, MiWaitForEmptyEvent, MiWaitingForWorkingSetEmpty, MmNumberOfPhysicalPages, MmWorkingSetReductionMax, MmWorkingSetReductionMin, MmWorkingSetVolReductionMax, PAGE_SIZE, and TRUE.

Referenced by MmInitSystem().

00264 : 00265 00266 This function is called from MmInitSystem to adjust the working set manager 00267 trim algorithms based on system type and size. 00268 00269 Arguments: 00270 00271 WorkStation - TRUE if this is a workstation, FALSE if not. 00272 00273 Return Value: 00274 00275 None. 00276 00277 Environment: 00278 00279 Kernel mode 00280 00281 --*/ 00282 { 00283 00284 #ifdef _MI_USE_CLAIMS_ 00285 00286 if (WorkStation && MmNumberOfPhysicalPages <= 63*1024*1024/PAGE_SIZE) { 00287 MiAgingShift = 4; 00288 MiEstimationShift = 5; 00289 } 00290 else { 00291 MiAgingShift = 5; 00292 MiEstimationShift = 6; 00293 } 00294 00295 if (MmNumberOfPhysicalPages >= 63*1024*1024/PAGE_SIZE) { 00296 MmPlentyFreePages *= 2; 00297 } 00298 #else 00299 00300 if (WorkStation && (MmNumberOfPhysicalPages <= (31*1024*1024/PAGE_SIZE))) { 00301 00302 // 00303 // To get fault protection, you have to take 45 faults instead of 00304 // the old 15 fault protection threshold. 00305 // 00306 00307 MiIdealPassFaultCountDisable = 45; 00308 00309 // 00310 // Take more away when you are over your working set in both 00311 // forced and voluntary mode, but leave cache WS trim amounts 00312 // alone. 00313 // 00314 00315 MmWorkingSetVolReductionMax = 100; 00316 MmWorkingSetReductionMax = 100; 00317 00318 // 00319 // In forced mode, even if you are within your working set, take 00320 // memory away more aggressively. 00321 // 00322 00323 MmWorkingSetReductionMin = 40; 00324 } 00325 else { 00326 MiIdealPassFaultCountDisable = 15; 00327 } 00328 #endif 00329 00330 MiWaitingForWorkingSetEmpty = FALSE; 00331 KeInitializeEvent (&MiWaitForEmptyEvent, NotificationEvent, TRUE); 00332 }

LOGICAL MiApplyDriverVerifier IN  PLDR_DATA_TABLE_ENTRY,
IN PMI_VERIFIER_DRIVER_ENTRY  Verifier
 

Definition at line 3448 of file verifier.c.

References ExAllocatePoolWithTag, FALSE, KernelVerifier, KiStackProtectTime, MI_VERIFIER_DRIVER_ENTRY, MiActiveVerifies, MiEnableRandomSpecialPool(), MiEnableVerifier(), MiFaultRetries, MiIoRetryLevel, MiSuspectDriverList, MiUserFaultRetries, MiUserIoRetryLevel, MiVerifierStackProtectTime, MiVerifyAllDrivers, MiVerifyRandomDrivers, MmVerifierData, NonPagedPool, NULL, RtlEqualUnicodeString(), RtlUpcaseUnicodeChar(), TRUE, VI_VERIFYING_DIRECTLY, VI_VERIFYING_INVERSELY, ViInitializeEntry(), ViInsertVerifierEntry(), and ViPrintString().

Referenced by MiInitializeDriverVerifierList(), and MiLoadSystemImage().

03455 : 03456 03457 This function is called as each module is loaded. If the module being 03458 loaded is in the suspect list, thunk it here. 03459 03460 Arguments: 03461 03462 DataTableEntry - Supplies the data table entry for the module. 03463 03464 Verifier - Non-NULL if verification must be applied. FALSE indicates 03465 that the driver name must match for verification to be 03466 applied. 03467 03468 Return Value: 03469 03470 TRUE if thunking was applied, FALSE if not. 03471 03472 Environment: 03473 03474 Kernel mode, Phase 0 Initialization and normal runtime. 03475 Non paged pool exists in Phase0, but paged pool does not. 03476 Post-Phase0 serialization is provided by the MmSystemLoadLock. 03477 03478 --*/ 03479 03480 { 03481 WCHAR FirstChar; 03482 LOGICAL Found; 03483 PLIST_ENTRY NextEntry; 03484 ULONG VerifierFlags; 03485 03486 if (Verifier != NULL) { 03487 Found = TRUE; 03488 } 03489 else { 03490 Found = FALSE; 03491 NextEntry = MiSuspectDriverList.Flink; 03492 while (NextEntry != &MiSuspectDriverList) { 03493 03494 Verifier = CONTAINING_RECORD(NextEntry, 03495 MI_VERIFIER_DRIVER_ENTRY, 03496 Links); 03497 03498 if (RtlEqualUnicodeString (&Verifier->BaseName, 03499 &DataTableEntry->BaseDllName, 03500 TRUE)) { 03501 03502 Found = TRUE; 03503 ViInitializeEntry (Verifier, FALSE); 03504 break; 03505 } 03506 NextEntry = NextEntry->Flink; 03507 } 03508 } 03509 03510 if (Found == FALSE) { 03511 VerifierFlags = VI_VERIFYING_DIRECTLY; 03512 if (MiVerifyAllDrivers == TRUE) { 03513 if (KernelVerifier == TRUE) { 03514 VerifierFlags = VI_VERIFYING_INVERSELY; 03515 } 03516 Found = TRUE; 03517 } 03518 else if (MiVerifyRandomDrivers != (WCHAR)0) { 03519 03520 // 03521 // Wildcard match drivers randomly. 03522 // 03523 03524 FirstChar = RtlUpcaseUnicodeChar(DataTableEntry->BaseDllName.Buffer[0]); 03525 03526 if (MiVerifyRandomDrivers == FirstChar) { 03527 Found = TRUE; 03528 } 03529 else if (MiVerifyRandomDrivers == (WCHAR)'X') { 03530 if ((FirstChar >= (WCHAR)'0') && (FirstChar <= (WCHAR)'9')) { 03531 Found = TRUE; 03532 } 03533 } 03534 } 03535 03536 if (Found == FALSE) { 03537 return FALSE; 03538 } 03539 03540 Verifier = (PMI_VERIFIER_DRIVER_ENTRY)ExAllocatePoolWithTag ( 03541 NonPagedPool, 03542 sizeof (MI_VERIFIER_DRIVER_ENTRY) + 03543 DataTableEntry->BaseDllName.MaximumLength, 03544 'dLmM'); 03545 03546 if (Verifier == NULL) { 03547 return FALSE; 03548 } 03549 03550 Verifier->BaseName.Buffer = (PWSTR)((PCHAR)Verifier + 03551 sizeof (MI_VERIFIER_DRIVER_ENTRY)); 03552 Verifier->BaseName.Length = DataTableEntry->BaseDllName.Length; 03553 Verifier->BaseName.MaximumLength = DataTableEntry->BaseDllName.MaximumLength; 03554 03555 RtlMoveMemory (Verifier->BaseName.Buffer, 03556 DataTableEntry->BaseDllName.Buffer, 03557 DataTableEntry->BaseDllName.Length); 03558 03559 ViInitializeEntry (Verifier, TRUE); 03560 03561 Verifier->Flags = VerifierFlags; 03562 03563 ViInsertVerifierEntry (Verifier); 03564 } 03565 03566 Verifier->StartAddress = DataTableEntry->DllBase; 03567 Verifier->EndAddress = (PVOID)((ULONG_PTR)DataTableEntry->DllBase + DataTableEntry->SizeOfImage); 03568 03569 if (MiEnableVerifier (DataTableEntry) == TRUE) { 03570 03571 if (Verifier->Flags & VI_VERIFYING_DIRECTLY) { 03572 ViPrintString (&DataTableEntry->BaseDllName); 03573 } 03574 03575 MmVerifierData.Loads += 1; 03576 03577 Verifier->Loads += 1; 03578 03579 DataTableEntry->Flags |= LDRP_IMAGE_VERIFYING; 03580 MiActiveVerifies += 1; 03581 03582 if (MiActiveVerifies == 1) { 03583 03584 // 03585 // Up the retry mechanism for potential injection failures. 03586 // 03587 03588 MiIoRetryLevel = (ULONG)-1; 03589 MiFaultRetries = MiIoRetryLevel; 03590 MiUserIoRetryLevel = (ULONG)-1; 03591 MiUserFaultRetries = MiUserIoRetryLevel; 03592 03593 #ifndef NO_POOL_CHECKS 03594 03595 // 03596 // If a loaded driver(s) is undergoing validation, the default 03597 // special pool randomizer is disabled as the precious virtual 03598 // address space and physical memory is being put to specific 03599 // use. 03600 // 03601 03602 MiEnableRandomSpecialPool (FALSE); 03603 #endif 03604 if (MmVerifierData.Level & DRIVER_VERIFIER_FORCE_IRQL_CHECKING) { 03605 03606 // 03607 // Page out all thread stacks as soon as possible to 03608 // catch drivers using local events that do usermode waits. 03609 // 03610 03611 if (KernelVerifier == FALSE) { 03612 MiVerifierStackProtectTime = KiStackProtectTime; 03613 KiStackProtectTime = 0; 03614 } 03615 } 03616 } 03617 } 03618 03619 return Found; 03620 }

VOID MiAttachSession IN PMM_SESSION_SPACE  SessionGlobal  ) 
 

Definition at line 1181 of file session.c.

References ASSERT, KeAttachSessionSpace(), MI_SESSION_SPACE_END, MI_SESSION_SPACE_PAGE_TABLES, MI_WRITE_VALID_PTE, MiGetPdeAddress, MiGetPpeAddress, MiHydra, MmSessionBase, PsGetCurrentProcess, TRUE, _MMPTE::u, and ZeroKernelPte.

Referenced by MiEmptyAllWorkingSetsWorker(), and MmWorkingSetManager().

01187 : 01188 01189 Attaches to the specified session space. 01190 01191 Arguments: 01192 01193 SessionGlobal - Supplies a pointer to the session to attach to. 01194 01195 Return Value: 01196 01197 None. 01198 01199 Environment: 01200 01201 Kernel mode. No locks held. Current process must not have a session 01202 space - ie: the caller should be the system process or smss.exe. 01203 01204 --*/ 01205 01206 { 01207 PMMPTE PointerPde; 01208 #if DBG 01209 PMMPTE EndPde; 01210 01211 ASSERT (MiHydra == TRUE); 01212 01213 ASSERT (PsGetCurrentProcess()->Vm.u.Flags.ProcessInSession == 0); 01214 01215 #if defined (_WIN64) 01216 01217 PointerPde = MiGetPpeAddress (MmSessionBase); 01218 ASSERT (PointerPde->u.Long == ZeroKernelPte.u.Long); 01219 01220 #else 01221 PointerPde = MiGetPdeAddress (MmSessionBase); 01222 EndPde = MiGetPdeAddress (MI_SESSION_SPACE_END); 01223 01224 while (PointerPde < EndPde) { 01225 ASSERT (PointerPde->u.Long == ZeroKernelPte.u.Long); 01226 PointerPde += 1; 01227 } 01228 #endif 01229 01230 #endif 01231 01232 #if defined (_WIN64) 01233 01234 PointerPde = MiGetPpeAddress (MmSessionBase); 01235 MI_WRITE_VALID_PTE (PointerPde, SessionGlobal->PageDirectory); 01236 01237 #else 01238 01239 PointerPde = MiGetPdeAddress (MmSessionBase); 01240 01241 RtlCopyMemory (PointerPde, 01242 &SessionGlobal->PageTables[0], 01243 MI_SESSION_SPACE_PAGE_TABLES * sizeof (MMPTE)); 01244 #endif 01245 01246 #if defined(_IA64_) 01247 KeAttachSessionSpace(&SessionGlobal->SessionMapInfo); 01248 #endif 01249 }

VOID MiAttemptPageFileReduction VOID   ) 
 

Definition at line 1940 of file modwrite.c.

References ASSERT, DbgPrint, DISPATCH_LEVEL, _MMPAGING_FILE::Entry, FALSE, File, _MMPAGING_FILE::FreeSpace, IoSetInformation(), _MMMOD_WRITER_MDL_ENTRY::LastPageToWrite, LOCK_PFN, _MMPAGING_FILE::MinimumSize, MmChargeCommitmentLock, MmMinimumPageFileReduction, MmNumberOfPagingFiles, MmPagingFile, MmTotalCommitLimit, MmTotalCommittedPages, NTSTATUS(), PAGE_SHIFT, PAGE_SIZE, RtlAreBitsClear(), RtlClearBits(), RtlSetBits(), _MMPAGING_FILE::Size, Size, TRUE, and UNLOCK_PFN.

Referenced by MiDereferenceSegmentThread().

01946 : 01947 01948 This routine attempts to reduce the size of the paging files to 01949 their minimum levels. 01950 01951 Note - Page file expansion and page file reduction are synchronized 01952 because a single thread is responsible for performing the 01953 operation. Hence, while expansion is occurring, a reduction 01954 request will be queued to the thread. 01955 01956 Arguments: 01957 01958 None. 01959 01960 Return Value: 01961 01962 None. 01963 01964 --*/ 01965 01966 { 01967 BOOLEAN Reduce; 01968 KIRQL OldIrql; 01969 ULONG i; 01970 PFN_NUMBER StartReduction; 01971 PFN_NUMBER ReductionSize; 01972 PFN_NUMBER TryBit; 01973 PFN_NUMBER TryReduction; 01974 SIZE_T MaxReduce; 01975 FILE_ALLOCATION_INFORMATION FileAllocationInfo; 01976 NTSTATUS status; 01977 01978 Reduce = FALSE; 01979 01980 ExAcquireSpinLock (&MmChargeCommitmentLock, &OldIrql); 01981 01982 // 01983 // Make sure the commit limit is greater than the number of committed 01984 // pages by twice the minimum page file reduction. Keep the 01985 // difference between the two at least minimum page file reduction. 01986 // 01987 01988 if ((MmTotalCommittedPages + (2 * MmMinimumPageFileReduction)) < 01989 MmTotalCommitLimit) { 01990 01991 MaxReduce = MmTotalCommitLimit - 01992 (MmMinimumPageFileReduction + MmTotalCommittedPages); 01993 ASSERT ((LONG)MaxReduce >= 0); 01994 01995 i = 0; 01996 do { 01997 01998 if (MaxReduce < MmMinimumPageFileReduction) { 01999 02000 // 02001 // Don't reduce any more paging files. 02002 // 02003 02004 break; 02005 } 02006 02007 if (MmPagingFile[i]->MinimumSize != MmPagingFile[i]->Size) { 02008 02009 if (MmPagingFile[i]->FreeSpace > MmMinimumPageFileReduction) { 02010 02011 // 02012 // Attempt to reduce this paging file. 02013 // 02014 02015 ExReleaseSpinLock (&MmChargeCommitmentLock, OldIrql); 02016 02017 // 02018 // Lock the PFN database and check to see if ample pages 02019 // are free at the end of the paging file. 02020 // 02021 02022 TryBit = MmPagingFile[i]->Size - MmMinimumPageFileReduction; 02023 TryReduction = MmMinimumPageFileReduction; 02024 02025 if (TryBit <= MmPagingFile[i]->MinimumSize) { 02026 TryBit = MmPagingFile[i]->MinimumSize; 02027 TryReduction = MmPagingFile[i]->Size - 02028 MmPagingFile[i]->MinimumSize; 02029 } 02030 02031 StartReduction = 0; 02032 ReductionSize = 0; 02033 02034 LOCK_PFN (OldIrql); 02035 02036 while (TRUE) { 02037 02038 // 02039 // Try to reduce. 02040 // 02041 02042 if ((ReductionSize + TryReduction) > MaxReduce) { 02043 02044 // 02045 // The reduction attempt would remove more 02046 // than MaxReduce pages. 02047 // 02048 02049 break; 02050 } 02051 02052 if (RtlAreBitsClear (MmPagingFile[i]->Bitmap, 02053 (ULONG)TryBit, 02054 (ULONG)TryReduction)) { 02055 02056 // 02057 // Can reduce it by TryReduction, see if it can 02058 // be made smaller. 02059 // 02060 02061 StartReduction = TryBit; 02062 ReductionSize += TryReduction; 02063 02064 if (StartReduction == MmPagingFile[i]->MinimumSize) { 02065 break; 02066 } 02067 02068 TryBit = StartReduction - MmMinimumPageFileReduction; 02069 02070 if (TryBit <= MmPagingFile[i]->MinimumSize) { 02071 TryReduction -= 02072 MmPagingFile[i]->MinimumSize - TryBit; 02073 TryBit = MmPagingFile[i]->MinimumSize; 02074 } else { 02075 TryReduction = MmMinimumPageFileReduction; 02076 } 02077 } else { 02078 02079 // 02080 // Reduction has failed. 02081 // 02082 02083 break; 02084 } 02085 } //end while 02086 02087 // 02088 // Make sure there are no outstanding writes to 02089 // pages within the start reduction range. 02090 // 02091 02092 if (StartReduction != 0) { 02093 02094 // 02095 // There is an outstanding write past where the 02096 // new end of the paging file should be. This 02097 // is a very rare condition, so just punt shrinking 02098 // the file. 02099 // 02100 02101 if ((MmPagingFile[i]->Entry[0]->LastPageToWrite > 02102 StartReduction) || 02103 (MmPagingFile[i]->Entry[1]->LastPageToWrite > 02104 StartReduction)) { 02105 StartReduction = 0; 02106 } 02107 } 02108 02109 // 02110 // Are there any pages to remove? 02111 // 02112 02113 if (StartReduction != 0) { 02114 02115 // 02116 // Reduce the paging file's size and free space. 02117 // 02118 02119 ASSERT (ReductionSize == (MmPagingFile[i]->Size - StartReduction)); 02120 02121 MmPagingFile[i]->Size = StartReduction; 02122 MmPagingFile[i]->FreeSpace -= ReductionSize; 02123 MaxReduce -= ReductionSize; 02124 ASSERT ((LONG)MaxReduce >= 0); 02125 02126 RtlSetBits (MmPagingFile[i]->Bitmap, 02127 (ULONG)StartReduction, 02128 (ULONG)ReductionSize ); 02129 02130 // 02131 // Release the PFN lock now that the size info 02132 // has been updated. 02133 // 02134 02135 UNLOCK_PFN (OldIrql); 02136 02137 // 02138 // Change the commit limit to reflect the returned 02139 // page file space. 02140 // 02141 02142 ExAcquireSpinLock (&MmChargeCommitmentLock, &OldIrql); 02143 02144 // 02145 // Now that the commit lock is again held, recheck 02146 // the commit to ensure it is still safe to contract 02147 // the paging files. 02148 // 02149 02150 if ((MmTotalCommittedPages + (2 * MmMinimumPageFileReduction)) >= 02151 MmTotalCommitLimit) { 02152 02153 ExReleaseSpinLock (&MmChargeCommitmentLock, OldIrql); 02154 LOCK_PFN (OldIrql); 02155 02156 MmPagingFile[i]->Size = StartReduction + ReductionSize; 02157 MmPagingFile[i]->FreeSpace += ReductionSize; 02158 MaxReduce += ReductionSize; 02159 ASSERT ((LONG)MaxReduce >= 0); 02160 02161 RtlClearBits (MmPagingFile[i]->Bitmap, 02162 (ULONG)StartReduction, 02163 (ULONG)ReductionSize ); 02164 02165 UNLOCK_PFN (OldIrql); 02166 02167 ExAcquireSpinLock (&MmChargeCommitmentLock, &OldIrql); 02168 break; 02169 } 02170 02171 MmTotalCommitLimit -= ReductionSize; 02172 02173 ExReleaseSpinLock (&MmChargeCommitmentLock, OldIrql); 02174 02175 #if defined (_WIN64) || defined (_X86PAE_) 02176 FileAllocationInfo.AllocationSize.QuadPart = 02177 ((ULONG64)StartReduction << PAGE_SHIFT); 02178 02179 #else 02180 FileAllocationInfo.AllocationSize.LowPart = 02181 StartReduction * PAGE_SIZE; 02182 02183 // 02184 // Set high part to zero, paging files are 02185 // limited to 4gb. 02186 // 02187 02188 FileAllocationInfo.AllocationSize.HighPart = 0; 02189 #endif 02190 02191 // 02192 // Reduce the allocated size of the paging file 02193 // thereby actually freeing the space and 02194 // setting a new end of file. 02195 // 02196 02197 02198 ASSERT (KeGetCurrentIrql() < DISPATCH_LEVEL); 02199 status = IoSetInformation ( 02200 MmPagingFile[i]->File, 02201 FileAllocationInformation, 02202 sizeof(FILE_ALLOCATION_INFORMATION), 02203 &FileAllocationInfo 02204 ); 02205 #if DBG 02206 02207 // 02208 // Ignore errors on truncating the paging file 02209 // as we can always have less space in the bitmap 02210 // than the pagefile holds. 02211 // 02212 02213 if (status != STATUS_SUCCESS) { 02214 DbgPrint ("MM: pagefile truncate status %lx\n", 02215 status); 02216 } 02217 #endif 02218 } else { 02219 UNLOCK_PFN (OldIrql); 02220 } 02221 02222 ExAcquireSpinLock (&MmChargeCommitmentLock, &OldIrql); 02223 } 02224 } 02225 i += 1; 02226 } while (i < MmNumberOfPagingFiles); 02227 } 02228 02229 ExReleaseSpinLock (&MmChargeCommitmentLock, OldIrql); 02230 return; 02231 }

VOID MiBuildPagedPool VOID   ) 
 

Definition at line 2184 of file mminit.c.

02190 : 02191 02192 This function is called to build the structures required for paged 02193 pool and initialize the pool. Once this routine is called, paged 02194 pool may be allocated. 02195 02196 Arguments: 02197 02198 None. 02199 02200 Return Value: 02201 02202 None. 02203 02204 Environment: 02205 02206 Kernel Mode Only. System initialization. 02207 02208 --*/ 02209 02210 { 02211 SIZE_T Size; 02212 PMMPTE PointerPte; 02213 PMMPTE PointerPde; 02214 PMMPTE PointerPpe; 02215 PMMPTE PointerPpeEnd; 02216 MMPTE TempPte; 02217 PMMPFN Pfn1; 02218 PFN_NUMBER PageFrameIndex; 02219 KIRQL OldIrql; 02220 ULONG i; 02221 02222 #if !defined (_WIN64) 02223 02224 // 02225 // Double map system page directory page. 02226 // 02227 02228 #if defined (_X86PAE_) 02229 02230 PointerPte = MiGetPteAddress(PDE_BASE); 02231 02232 for (i = 0 ; i < PD_PER_SYSTEM; i += 1) { 02233 MmSystemPageDirectory[i] = MI_GET_PAGE_FRAME_FROM_PTE (PointerPte); 02234 Pfn1 = MI_PFN_ELEMENT(MmSystemPageDirectory[i]); 02235 Pfn1->OriginalPte.u.Long = MM_DEMAND_ZERO_WRITE_PTE; 02236 PointerPte += 1; 02237 } 02238 02239 // 02240 // Was not mapped physically, map it virtually in system space. 02241 // 02242 02243 PointerPte = MiReserveSystemPtes ( 02244 PD_PER_SYSTEM, 02245 SystemPteSpace, 02246 MM_COLOR_ALIGNMENT, 02247 ((ULONG_PTR)PDE_BASE & MM_COLOR_MASK_VIRTUAL), 02248 TRUE); 02249 02250 MmSystemPagePtes = (PMMPTE)MiGetVirtualAddressMappedByPte (PointerPte); 02251 02252 TempPte = ValidKernelPde; 02253 02254 for (i = 0 ; i < PD_PER_SYSTEM; i += 1) { 02255 TempPte.u.Hard.PageFrameNumber = MmSystemPageDirectory[i]; 02256 MI_WRITE_VALID_PTE (PointerPte, TempPte); 02257 PointerPte += 1; 02258 } 02259 02260 #else 02261 02262 MmSystemPageDirectory = MI_GET_PAGE_FRAME_FROM_PTE (MiGetPteAddress(PDE_BASE)); 02263 02264 Pfn1 = MI_PFN_ELEMENT(MmSystemPageDirectory); 02265 02266 Pfn1->OriginalPte.u.Long = MM_DEMAND_ZERO_WRITE_PTE; 02267 02268 MmSystemPagePtes = (PMMPTE)MiMapPageInHyperSpace (MmSystemPageDirectory, 02269 &OldIrql); 02270 MiUnmapPageInHyperSpace (OldIrql); 02271 02272 if (!MI_IS_PHYSICAL_ADDRESS(MmSystemPagePtes)) { 02273 02274 // 02275 // Was not mapped physically, map it virtually in system space. 02276 // 02277 02278 PointerPte = MiReserveSystemPtes ( 02279 1, 02280 SystemPteSpace, 02281 MM_COLOR_ALIGNMENT, 02282 ((ULONG_PTR)PDE_BASE & MM_COLOR_MASK_VIRTUAL), 02283 TRUE); 02284 TempPte = ValidKernelPde; 02285 TempPte.u.Hard.PageFrameNumber = MmSystemPageDirectory; 02286 MI_WRITE_VALID_PTE (PointerPte, TempPte); 02287 MmSystemPagePtes = (PMMPTE)MiGetVirtualAddressMappedByPte (PointerPte); 02288 } 02289 #endif 02290 02291 #endif 02292 02293 if (MmPagedPoolMaximumDesired == TRUE) { 02294 MmSizeOfPagedPoolInBytes = 02295 ((PCHAR)MmNonPagedSystemStart - (PCHAR)MmPagedPoolStart); 02296 } 02297 02298 // 02299 // A size of 0 means size the pool based on physical memory. 02300 // 02301 02302 if (MmSizeOfPagedPoolInBytes == 0) { 02303 MmSizeOfPagedPoolInBytes = 2 * MmMaximumNonPagedPoolInBytes; 02304 } 02305 02306 if (MmIsThisAnNtAsSystem()) { 02307 if ((MmNumberOfPhysicalPages > ((24*1024*1024) >> PAGE_SHIFT)) && 02308 (MmSizeOfPagedPoolInBytes < MM_MINIMUM_PAGED_POOL_NTAS)) { 02309 02310 MmSizeOfPagedPoolInBytes = MM_MINIMUM_PAGED_POOL_NTAS; 02311 } 02312 } 02313 02314 if (MmSizeOfPagedPoolInBytes > 02315 (ULONG_PTR)((PCHAR)MmNonPagedSystemStart - (PCHAR)MmPagedPoolStart)) { 02316 MmSizeOfPagedPoolInBytes = 02317 ((PCHAR)MmNonPagedSystemStart - (PCHAR)MmPagedPoolStart); 02318 } 02319 02320 Size = BYTES_TO_PAGES(MmSizeOfPagedPoolInBytes); 02321 02322 if (Size < MM_MIN_INITIAL_PAGED_POOL) { 02323 Size = MM_MIN_INITIAL_PAGED_POOL; 02324 } 02325 02326 if (Size > (MM_MAX_PAGED_POOL >> PAGE_SHIFT)) { 02327 Size = MM_MAX_PAGED_POOL >> PAGE_SHIFT; 02328 } 02329 02330 Size = (Size + (PTE_PER_PAGE - 1)) / PTE_PER_PAGE; 02331 MmSizeOfPagedPoolInBytes = (ULONG_PTR)Size * PAGE_SIZE * PTE_PER_PAGE; 02332 02333 ASSERT ((MmSizeOfPagedPoolInBytes + (PCHAR)MmPagedPoolStart) <= 02334 (PCHAR)MmNonPagedSystemStart); 02335 02336 // 02337 // Set size to the number of pages in the pool. 02338 // 02339 02340 Size = Size * PTE_PER_PAGE; 02341 02342 MmPagedPoolEnd = (PVOID)(((PUCHAR)MmPagedPoolStart + 02343 MmSizeOfPagedPoolInBytes) - 1); 02344 02345 MmPageAlignedPoolBase[PagedPool] = MmPagedPoolStart; 02346 02347 // 02348 // Build page table page for paged pool. 02349 // 02350 02351 PointerPde = MiGetPdeAddress (MmPagedPoolStart); 02352 MmPagedPoolBasePde = PointerPde; 02353 02354 TempPte = ValidKernelPde; 02355 02356 #if defined (_WIN64) 02357 02358 // 02359 // Map in all the page directory pages to span all of paged pool. 02360 // This removes the need for a system lookup directory. 02361 // 02362 02363 PointerPpe = MiGetPpeAddress (MmPagedPoolStart); 02364 PointerPpeEnd = MiGetPpeAddress (MmPagedPoolEnd); 02365 02366 while (PointerPpe <= PointerPpeEnd) { 02367 02368 if (PointerPpe->u.Hard.Valid == 0) { 02369 PageFrameIndex = MiRemoveAnyPage( 02370 MI_GET_PAGE_COLOR_FROM_PTE (PointerPpe)); 02371 TempPte.u.Hard.PageFrameNumber = PageFrameIndex; 02372 *PointerPpe = TempPte; 02373 02374 Pfn1 = MI_PFN_ELEMENT(PageFrameIndex); 02375 Pfn1->PteFrame = MI_GET_PAGE_FRAME_FROM_PTE ( 02376 MiGetPteAddress(PDE_KTBASE)); 02377 Pfn1->PteAddress = PointerPpe; 02378 Pfn1->u2.ShareCount = 1; 02379 Pfn1->u3.e2.ReferenceCount = 1; 02380 Pfn1->u3.e1.PageLocation = ActiveAndValid; 02381 Pfn1->OriginalPte.u.Long = MM_DEMAND_ZERO_WRITE_PTE; 02382 } 02383 02384 PointerPpe += 1; 02385 } 02386 02387 #endif 02388 02389 PointerPte = MiGetPteAddress (MmPagedPoolStart); 02390 MmPagedPoolInfo.FirstPteForPagedPool = PointerPte; 02391 MmPagedPoolInfo.LastPteForPagedPool = MiGetPteAddress (MmPagedPoolEnd); 02392 02393 MiFillMemoryPte (PointerPde, 02394 sizeof(MMPTE) * 02395 (1 + MiGetPdeAddress (MmPagedPoolEnd) - PointerPde), 02396 MM_KERNEL_NOACCESS_PTE); 02397 02398 LOCK_PFN (OldIrql); 02399 02400 // 02401 // Map in a page table page. 02402 // 02403 02404 PageFrameIndex = MiRemoveAnyPage( 02405 MI_GET_PAGE_COLOR_FROM_PTE (PointerPde)); 02406 TempPte.u.Hard.PageFrameNumber = PageFrameIndex; 02407 MI_WRITE_VALID_PTE (PointerPde, TempPte); 02408 02409 Pfn1 = MI_PFN_ELEMENT(PageFrameIndex); 02410 #if defined (_WIN64) 02411 Pfn1->PteFrame = MI_GET_PAGE_FRAME_FROM_PTE(MiGetPpeAddress (MmPagedPoolStart)); 02412 #else 02413 #if !defined (_X86PAE_) 02414 Pfn1->PteFrame = MmSystemPageDirectory; 02415 #else 02416 Pfn1->PteFrame = MmSystemPageDirectory[(PointerPde - MiGetPdeAddress(0)) / PDE_PER_PAGE]; 02417 #endif 02418 #endif 02419 Pfn1->PteAddress = PointerPde; 02420 Pfn1->u2.ShareCount = 1; 02421 Pfn1->u3.e2.ReferenceCount = 1; 02422 Pfn1->u3.e1.PageLocation = ActiveAndValid; 02423 Pfn1->OriginalPte.u.Long = MM_DEMAND_ZERO_WRITE_PTE; 02424 MiFillMemoryPte (PointerPte, PAGE_SIZE, MM_KERNEL_NOACCESS_PTE); 02425 02426 UNLOCK_PFN (OldIrql); 02427 02428 MmPagedPoolInfo.NextPdeForPagedPoolExpansion = PointerPde + 1; 02429 02430 // 02431 // Build bitmaps for paged pool. 02432 // 02433 02434 MiCreateBitMap (&MmPagedPoolInfo.PagedPoolAllocationMap, Size, NonPagedPool); 02435 RtlSetAllBits (MmPagedPoolInfo.PagedPoolAllocationMap); 02436 02437 // 02438 // Indicate first page worth of PTEs are available. 02439 // 02440 02441 RtlClearBits (MmPagedPoolInfo.PagedPoolAllocationMap, 0, PTE_PER_PAGE); 02442 02443 MiCreateBitMap (&MmPagedPoolInfo.EndOfPagedPoolBitmap, Size, NonPagedPool); 02444 RtlClearAllBits (MmPagedPoolInfo.EndOfPagedPoolBitmap); 02445 02446 // 02447 // If verifier is present then build the verifier paged pool bitmap. 02448 // 02449 02450 if (MmVerifyDriverBufferLength != (ULONG)-1) { 02451 MiCreateBitMap (&VerifierLargePagedPoolMap, Size, NonPagedPool); 02452 RtlClearAllBits (VerifierLargePagedPoolMap); 02453 } 02454 02455 // 02456 // Initialize paged pool. 02457 // 02458 02459 InitializePool (PagedPool, 0L); 02460 02461 MiInitializeSpecialPool(); 02462 02463 // 02464 // Allow mapping of views into system space. 02465 // 02466 02467 MiInitializeSystemSpaceMap ((PVOID)0); 02468 02469 return; 02470 }

SIZE_T MiCalculatePageCommitment IN PVOID  StartingAddress,
IN PVOID  EndingAddress,
IN PMMVAD  Vad,
IN PEPROCESS  Process
 

Definition at line 519 of file mmquota.c.

References BYTES_TO_PAGES, FALSE, MiDoesPdeExistAndMakeValid(), MiDoesPpeExistAndMakeValid, MiGetPdeAddress, MiGetPpeAddress, MiGetPteAddress, MiGetVirtualAddressMappedByPte, MiIsPteDecommittedPage(), MiIsPteOnPdeBoundary, and _MMPTE::u.

Referenced by NtAllocateVirtualMemory(), and NtFreeVirtualMemory().

00528 : 00529 00530 This routine examines the range of pages from the starting address 00531 up to and including the ending address and returns the commit charge 00532 for the pages within the range. 00533 00534 Arguments: 00535 00536 StartingAddress - Supplies the starting address of the range. 00537 00538 EndingAddress - Supplies the ending address of the range. 00539 00540 Vad - Supplies the virtual address descriptor which describes the range. 00541 00542 Process - Supplies the current process. 00543 00544 Return Value: 00545 00546 Commitment charge for the range. 00547 00548 Environment: 00549 00550 Kernel mode, APCs disabled, WorkingSetLock and AddressCreation mutexes 00551 held. 00552 00553 --*/ 00554 00555 { 00556 PMMPTE PointerPte; 00557 PMMPTE LastPte; 00558 PMMPTE PointerPde; 00559 PMMPTE PointerPpe; 00560 PMMPTE TempEnd; 00561 SIZE_T NumberOfCommittedPages; 00562 ULONG Waited; 00563 00564 NumberOfCommittedPages = 0; 00565 00566 PointerPpe = MiGetPpeAddress (StartingAddress); 00567 PointerPde = MiGetPdeAddress (StartingAddress); 00568 PointerPte = MiGetPteAddress (StartingAddress); 00569 00570 if (Vad->u.VadFlags.MemCommit == 1) { 00571 00572 TempEnd = EndingAddress; 00573 00574 // 00575 // All the pages are committed within this range. 00576 // 00577 00578 NumberOfCommittedPages = BYTES_TO_PAGES ((PCHAR)TempEnd - 00579 (PCHAR)StartingAddress); 00580 00581 00582 // 00583 // Examine the PTEs to determine how many pages are committed. 00584 // 00585 00586 LastPte = MiGetPteAddress (TempEnd); 00587 00588 do { 00589 00590 while (!MiDoesPpeExistAndMakeValid (PointerPpe, 00591 Process, 00592 FALSE, 00593 &Waited)) { 00594 00595 // 00596 // No PPE exists for the starting address, therefore the page 00597 // is not committed. 00598 // 00599 00600 PointerPpe += 1; 00601 PointerPde = MiGetVirtualAddressMappedByPte (PointerPpe); 00602 PointerPte = MiGetVirtualAddressMappedByPte (PointerPde); 00603 if (PointerPte > LastPte) { 00604 goto DoneCommit; 00605 } 00606 } 00607 00608 Waited = 0; 00609 00610 while (!MiDoesPdeExistAndMakeValid (PointerPde, 00611 Process, 00612 FALSE, 00613 &Waited)) { 00614 00615 // 00616 // No PDE exists for the starting address, therefore the page 00617 // is not committed. 00618 // 00619 00620 PointerPde += 1; 00621 PointerPpe = MiGetPteAddress (PointerPde); 00622 PointerPte = MiGetVirtualAddressMappedByPte (PointerPde); 00623 if (PointerPte > LastPte) { 00624 goto DoneCommit; 00625 } 00626 #if defined (_WIN64) 00627 if (MiIsPteOnPdeBoundary (PointerPde)) { 00628 Waited = 1; 00629 break; 00630 } 00631 #endif 00632 } 00633 00634 } while (Waited != 0); 00635 00636 restart: 00637 00638 while (PointerPte <= LastPte) { 00639 00640 if (MiIsPteOnPdeBoundary (PointerPte)) { 00641 00642 // 00643 // This is a PDE boundary, check to see if the entire 00644 // PPE/PDE pages exist. 00645 // 00646 00647 PointerPde = MiGetPteAddress (PointerPte); 00648 PointerPpe = MiGetPteAddress (PointerPde); 00649 00650 do { 00651 00652 if (!MiDoesPpeExistAndMakeValid (PointerPpe, 00653 Process, 00654 FALSE, 00655 &Waited)) { 00656 00657 // 00658 // No PDE exists for the starting address, check the VAD 00659 // to see if the pages are not committed. 00660 // 00661 00662 PointerPpe += 1; 00663 PointerPde = MiGetVirtualAddressMappedByPte (PointerPpe); 00664 PointerPte = MiGetVirtualAddressMappedByPte (PointerPde); 00665 00666 // 00667 // Check next page. 00668 // 00669 00670 goto restart; 00671 } 00672 00673 Waited = 0; 00674 00675 if (!MiDoesPdeExistAndMakeValid (PointerPde, 00676 Process, 00677 FALSE, 00678 &Waited)) { 00679 00680 // 00681 // No PDE exists for the starting address, check the VAD 00682 // to see if the pages are not committed. 00683 // 00684 00685 PointerPde += 1; 00686 PointerPpe = MiGetPteAddress (PointerPde); 00687 PointerPte = MiGetVirtualAddressMappedByPte (PointerPde); 00688 00689 // 00690 // Check next page. 00691 // 00692 00693 goto restart; 00694 } 00695 } while (Waited != 0); 00696 } 00697 00698 // 00699 // The PDE exists, examine the PTE. 00700 // 00701 00702 if (PointerPte->u.Long != 0) { 00703 00704 // 00705 // Has this page been explicitly decommitted? 00706 // 00707 00708 if (MiIsPteDecommittedPage (PointerPte)) { 00709 00710 // 00711 // This page is decommitted, remove it from the count. 00712 // 00713 00714 NumberOfCommittedPages -= 1; 00715 00716 } 00717 } 00718 00719 PointerPte += 1; 00720 } 00721 00722 DoneCommit: 00723 00724 if (TempEnd == EndingAddress) { 00725 return NumberOfCommittedPages; 00726 } 00727 00728 } 00729 00730 // 00731 // Examine non committed range. 00732 // 00733 00734 LastPte = MiGetPteAddress (EndingAddress); 00735 00736 do { 00737 00738 while (!MiDoesPpeExistAndMakeValid (PointerPpe, 00739 Process, 00740 FALSE, 00741 &Waited)) { 00742 00743 00744 // 00745 // No PDE exists for the starting address, therefore the page 00746 // is not committed. 00747 // 00748 00749 PointerPpe += 1; 00750 PointerPde = MiGetVirtualAddressMappedByPte (PointerPpe); 00751 PointerPte = MiGetVirtualAddressMappedByPte (PointerPde); 00752 if (PointerPte > LastPte) { 00753 return NumberOfCommittedPages; 00754 } 00755 } 00756 00757 Waited = 0; 00758 00759 while (!MiDoesPdeExistAndMakeValid (PointerPde, 00760 Process, 00761 FALSE, 00762 &Waited)) { 00763 00764 // 00765 // No PDE exists for the starting address, therefore the page 00766 // is not committed. 00767 // 00768 00769 PointerPde += 1; 00770 PointerPte = MiGetVirtualAddressMappedByPte (PointerPde); 00771 if (PointerPte > LastPte) { 00772 return NumberOfCommittedPages; 00773 } 00774 #if defined (_WIN64) 00775 if (MiIsPteOnPdeBoundary (PointerPde)) { 00776 PointerPpe = MiGetPteAddress (PointerPde); 00777 Waited = 1; 00778 break; 00779 } 00780 #endif 00781 } 00782 00783 } while (Waited != 0); 00784 00785 restart2: 00786 00787 while (PointerPte <= LastPte) { 00788 00789 if (MiIsPteOnPdeBoundary (PointerPte)) { 00790 00791 // 00792 // This is a PDE boundary, check to see if the entire 00793 // PPE/PDE pages exist. 00794 // 00795 00796 PointerPde = MiGetPteAddress (PointerPte); 00797 PointerPpe = MiGetPteAddress (PointerPde); 00798 00799 do { 00800 00801 if (!MiDoesPpeExistAndMakeValid (PointerPpe, 00802 Process, 00803 FALSE, 00804 &Waited)) { 00805 00806 // 00807 // No PPE exists for the starting address, check the VAD 00808 // to see if the pages are not committed. 00809 // 00810 00811 PointerPpe += 1; 00812 PointerPde = MiGetVirtualAddressMappedByPte (PointerPpe); 00813 PointerPte = MiGetVirtualAddressMappedByPte (PointerPde); 00814 00815 // 00816 // Check next page. 00817 // 00818 00819 goto restart2; 00820 } 00821 00822 Waited = 0; 00823 00824 if (!MiDoesPdeExistAndMakeValid (PointerPde, 00825 Process, 00826 FALSE, 00827 &Waited)) { 00828 00829 // 00830 // No PDE exists for the starting address, check the VAD 00831 // to see if the pages are not committed. 00832 // 00833 00834 PointerPde += 1; 00835 PointerPpe = MiGetPteAddress (PointerPde); 00836 PointerPte = MiGetVirtualAddressMappedByPte (PointerPde); 00837 00838 // 00839 // Check next page. 00840 // 00841 00842 goto restart2; 00843 } 00844 00845 } while (Waited != 0); 00846 } 00847 00848 // 00849 // The PDE exists, examine the PTE. 00850 // 00851 00852 if ((PointerPte->u.Long != 0) && 00853 (!MiIsPteDecommittedPage (PointerPte))) { 00854 00855 // 00856 // This page is committed, count it. 00857 // 00858 00859 NumberOfCommittedPages += 1; 00860 } 00861 00862 PointerPte += 1; 00863 } 00864 00865 return NumberOfCommittedPages; 00866 }

LOGICAL MiCancelWriteOfMappedPfn IN PFN_NUMBER  PageToStop  ) 
 

Definition at line 2579 of file modwrite.c.

References APC_LEVEL, _MDL::ByteCount, FALSE, LOCK_PFN, _MMMOD_WRITER_MDL_ENTRY::Mdl, MiWriteComplete(), MmMappedPageWriterList, PAGE_SHIFT, TRUE, _MMMOD_WRITER_MDL_ENTRY::u, and UNLOCK_PFN.

Referenced by MmPurgeSection().

02585 : 02586 02587 This routine attempts to stop a pending mapped page writer write for the 02588 specified PFN. Note that if the write can be stopped, any other pages 02589 that may be clustered with the write are also stopped. 02590 02591 Arguments: 02592 02593 PageToStop - Supplies the frame number that the caller wants to stop. 02594 02595 Return Value: 02596 02597 TRUE if the write was stopped, FALSE if not. 02598 02599 Environment: 02600 02601 Kernel mode, PFN lock held. The PFN lock is released and reacquired if 02602 the write was stopped. 02603 02604 N.B. No other locks may be held as IRQL is lowered to APC_LEVEL here. 02605 02606 --*/ 02607 02608 { 02609 ULONG i; 02610 ULONG PageCount; 02611 KIRQL OldIrql; 02612 PPFN_NUMBER Page; 02613 PLIST_ENTRY NextEntry; 02614 PMDL MemoryDescriptorList; 02615 PMMMOD_WRITER_MDL_ENTRY ModWriterEntry; 02616 02617 // 02618 // Walk the MmMappedPageWriterList looking for an MDL which contains 02619 // the argument page. If found, remove it and cancel the write. 02620 // 02621 02622 NextEntry = MmMappedPageWriterList.Flink; 02623 while (NextEntry != &MmMappedPageWriterList) { 02624 02625 ModWriterEntry = CONTAINING_RECORD(NextEntry, 02626 MMMOD_WRITER_MDL_ENTRY, 02627 Links); 02628 02629 MemoryDescriptorList = &ModWriterEntry->Mdl; 02630 PageCount = (MemoryDescriptorList->ByteCount >> PAGE_SHIFT); 02631 Page = (PPFN_NUMBER)(MemoryDescriptorList + 1); 02632 02633 for (i = 0; i < PageCount; i += 1) { 02634 if (*Page == PageToStop) { 02635 RemoveEntryList (NextEntry); 02636 goto CancelWrite; 02637 } 02638 Page += 1; 02639 } 02640 02641 NextEntry = NextEntry->Flink; 02642 } 02643 02644 return FALSE; 02645 02646 CancelWrite: 02647 02648 UNLOCK_PFN (APC_LEVEL); 02649 02650 // 02651 // File lock conflict to indicate an error has occurred, 02652 // but that future I/Os should be allowed. Keep APCs disabled and 02653 // call the write completion routine. 02654 // 02655 02656 ModWriterEntry->u.IoStatus.Status = STATUS_FILE_LOCK_CONFLICT; 02657 ModWriterEntry->u.IoStatus.Information = 0; 02658 02659 MiWriteComplete ((PVOID)ModWriterEntry, 02660 &ModWriterEntry->u.IoStatus, 02661 0 ); 02662 02663 LOCK_PFN (OldIrql); 02664 02665 return TRUE; 02666 }

ULONG MiCanFileBeTruncatedInternal IN PSECTION_OBJECT_POINTERS  SectionPointer,
IN PLARGE_INTEGER NewFileSize  OPTIONAL,
IN LOGICAL  BlockNewViews,
OUT PKIRQL  PreviousIrql
 

Definition at line 2614 of file sectsup.c.

References ASSERT, _SUBSECTION::ControlArea, FALSE, LOCK_PFN, MiEndingOffset(), MmFlushForWrite, MmFlushImageSection(), _SUBSECTION::NextSubsection, NULL, _CONTROL_AREA::NumberOfMappedViews, _CONTROL_AREA::NumberOfUserReferences, PAGE_SIZE, TRUE, _CONTROL_AREA::u, and UNLOCK_PFN.

Referenced by MmCanFileBeTruncated(), and MmPurgeSection().

02623 : 02624 02625 This routine does the following: 02626 02627 1. Checks to see if a image section is in use for the file, 02628 if so it returns FALSE. 02629 02630 2. Checks to see if a user section exists for the file, if 02631 it does, it checks to make sure the new file size is greater 02632 than the size of the file, if not it returns FALSE. 02633 02634 3. If no image section exists, and no user created data section 02635 exists or the files size is greater, then TRUE is returned. 02636 02637 Arguments: 02638 02639 SectionPointer - Supplies a pointer to the section object pointers 02640 from the file object. 02641 02642 NewFileSize - Supplies a pointer to the size the file is getting set to. 02643 02644 BlockNewViews - Supplies TRUE if the caller will block new views while 02645 the operation (usually a purge) proceeds. This allows 02646 this routine to return TRUE even if the user has section 02647 references, provided the user currently has no mapped views. 02648 02649 PreviousIrql - If returning TRUE, returns Irql to use when unlocking 02650 Pfn database. 02651 02652 Return Value: 02653 02654 TRUE if the file can be truncated (PFN locked). 02655 FALSE if it cannot be truncated (PFN not locked). 02656 02657 Environment: 02658 02659 Kernel mode. 02660 02661 --*/ 02662 02663 { 02664 KIRQL OldIrql; 02665 LARGE_INTEGER SegmentSize; 02666 PCONTROL_AREA ControlArea; 02667 PSUBSECTION Subsection; 02668 02669 if (!MmFlushImageSection (SectionPointer, MmFlushForWrite)) { 02670 return FALSE; 02671 } 02672 02673 LOCK_PFN (OldIrql); 02674 02675 ControlArea = (PCONTROL_AREA)(SectionPointer->DataSectionObject); 02676 02677 if (ControlArea != NULL) { 02678 02679 if (ControlArea->u.Flags.BeingCreated || 02680 ControlArea->u.Flags.BeingDeleted) { 02681 goto UnlockAndReturn; 02682 } 02683 02684 // 02685 // If there are user references and the size is less than the 02686 // size of the user view, don't allow the truncation. 02687 // 02688 02689 if ((ControlArea->NumberOfUserReferences != 0) && 02690 ((BlockNewViews == FALSE) || (ControlArea->NumberOfMappedViews != 0))) { 02691 02692 // 02693 // You cannot truncate the entire section if there is a user 02694 // reference. 02695 // 02696 02697 if (!ARGUMENT_PRESENT(NewFileSize)) { 02698 goto UnlockAndReturn; 02699 } 02700 02701 // 02702 // Locate last subsection and get total size. 02703 // 02704 02705 if (ControlArea->u.Flags.GlobalOnlyPerSession == 0) { 02706 Subsection = (PSUBSECTION)(ControlArea + 1); 02707 } 02708 else { 02709 Subsection = (PSUBSECTION)((PLARGE_CONTROL_AREA)ControlArea + 1); 02710 } 02711 02712 while (Subsection->NextSubsection != NULL) { 02713 Subsection = Subsection->NextSubsection; 02714 } 02715 02716 ASSERT (Subsection->ControlArea->u.Flags.Image == 0); 02717 02718 SegmentSize = MiEndingOffset(Subsection); 02719 02720 if ((UINT64)NewFileSize->QuadPart < (UINT64)SegmentSize.QuadPart) { 02721 goto UnlockAndReturn; 02722 } 02723 02724 // 02725 // If there are mapped views, we will skip the last page 02726 // of the section if the size passed in falls in that page. 02727 // The caller (like Cc) may want to clear this fractional page. 02728 // 02729 02730 SegmentSize.QuadPart += PAGE_SIZE - 1; 02731 SegmentSize.LowPart &= ~(PAGE_SIZE - 1); 02732 if ((UINT64)NewFileSize->QuadPart < (UINT64)SegmentSize.QuadPart) { 02733 *NewFileSize = SegmentSize; 02734 } 02735 } 02736 } 02737 02738 *PreviousIrql = OldIrql; 02739 return TRUE; 02740 02741 UnlockAndReturn: 02742 UNLOCK_PFN (OldIrql); 02743 return FALSE; 02744 }

VOID MiCaptureWriteWatchDirtyBit IN PEPROCESS  Process,
IN PVOID  VirtualAddress
 

Referenced by MiEliminateWorkingSetEntry(), and MiFlushTbAndCapture().

ULONG MiChangeNoAccessForkPte IN PMMPTE  PointerPte,
IN ULONG  ProtectionMask
 

Definition at line 2032 of file protect.c.

References FALSE, MM_NOACCESS, PAGED_CODE, and TRUE.

Referenced by MiProtectVirtualMemory(), and MiSetProtectionOnSection().

02039 : 02040 02041 02042 Arguments: 02043 02044 PointerPte - Supplies a pointer to the current PTE. 02045 02046 ProtectionMask - Supplies the protection mask to set. 02047 02048 Return Value: 02049 02050 FALSE if the loop should be repeated for this PTE, TRUE 02051 if protection has been set. 02052 02053 02054 Environment: 02055 02056 Kernel mode, address creation mutex held, APCs disabled. 02057 02058 --*/ 02059 02060 { 02061 PAGED_CODE(); 02062 02063 if (ProtectionMask == MM_NOACCESS) { 02064 02065 // 02066 // No need to change the page protection. 02067 // 02068 02069 return TRUE; 02070 } 02071 02072 PointerPte->u.Proto.ReadOnly = 1; 02073 02074 return FALSE; 02075 }

LOGICAL FASTCALL MiChargeCommitment IN SIZE_T  QuotaCharge,
IN PEPROCESS Process  OPTIONAL
 

Definition at line 191 of file mmquota.c.

References _MMPAGE_FILE_EXPANSION::ActualExpansion, ASSERT, _MMPAGE_FILE_EXPANSION::Event, FALSE, KeInitializeEvent, LOCK_WS, LOCK_WS_REGARDLESS, LOCK_WS_UNSAFE, MI_EXTEND_ANY_PAGEFILE, MiCauseOverCommitPopup(), MiChargeCommitmentCantExpand(), MiIssuePageExtendRequest(), MM_EXTEND_COMMIT, MM_MAXIMUM_QUOTA_OVERCHARGE, MmChargeCommitmentLock, MmPageFileFullExtendPages, MmPeakCommitment, MmTotalCommitLimit, MmTotalCommittedPages, NULL, _MMPAGE_FILE_EXPANSION::PageFileNumber, _MMPAGE_FILE_EXPANSION::RequestedExpansionSize, _MMPAGE_FILE_EXPANSION::Segment, TRUE, and UNLOCK_WS_REGARDLESS.

Referenced by MiCreateImageFileMap(), MiCreatePagingFileMap(), MiInitializeSessionPool(), MiInsertVad(), MiMapViewOfDataSection(), MiSessionCommitImagePages(), MiSessionCommitPageTables(), MiSessionCreateInternal(), MiSessionInitializeWorkingSetList(), MiSetProtectionOnSection(), MiShareSessionImage(), MmCreateKernelStack(), MmCreateProcessAddressSpace(), NtAllocateVirtualMemory(), and NtCreatePagingFile().

00198 : 00199 00200 This routine checks to ensure the system has sufficient page file 00201 space remaining. 00202 00203 Arguments: 00204 00205 QuotaCharge - Supplies the quota amount to charge. 00206 00207 Process - Optionally supplies the current process IF AND ONLY IF 00208 the working set mutex is held. If the paging file 00209 is being extended, the working set mutex is released if 00210 this is non-null. 00211 00212 Return Value: 00213 00214 TRUE if there is sufficient space, FALSE if not. 00215 00216 Environment: 00217 00218 Kernel mode, APCs disabled, WorkingSetLock and AddressCreation mutexes 00219 held. 00220 00221 --*/ 00222 00223 { 00224 KIRQL OldIrql; 00225 SIZE_T NewCommitValue; 00226 MMPAGE_FILE_EXPANSION PageExtend; 00227 LOGICAL WsHeldSafe; 00228 00229 #if !defined (_WIN64) 00230 ASSERT (QuotaCharge < 0x100000); 00231 #endif 00232 00233 ExAcquireFastLock (&MmChargeCommitmentLock, &OldIrql); 00234 00235 NewCommitValue = MmTotalCommittedPages + QuotaCharge; 00236 00237 while (NewCommitValue > MmTotalCommitLimit) { 00238 00239 ExReleaseFastLock (&MmChargeCommitmentLock, OldIrql); 00240 00241 if (Process != NULL) { 00242 00243 // 00244 // The working set lock may have been acquired safely or unsafely 00245 // by our caller. Handle both cases here and below. 00246 // 00247 00248 UNLOCK_WS_REGARDLESS(Process, WsHeldSafe); 00249 } 00250 00251 // 00252 // Queue a message to the segment dereferencing / pagefile extending 00253 // thread to see if the page file can be extended. This is done 00254 // in the context of a system thread due to mutexes which may 00255 // currently be held. 00256 // 00257 00258 PageExtend.RequestedExpansionSize = QuotaCharge; 00259 PageExtend.Segment = NULL; 00260 PageExtend.PageFileNumber = MI_EXTEND_ANY_PAGEFILE; 00261 KeInitializeEvent (&PageExtend.Event, NotificationEvent, FALSE); 00262 00263 if (MiIssuePageExtendRequest (&PageExtend) == FALSE) { 00264 00265 if (Process != NULL) { 00266 LOCK_WS_REGARDLESS(Process, WsHeldSafe); 00267 } 00268 00269 // 00270 // If the quota is small enough, commit it anyway. Otherwise 00271 // return an error. 00272 // 00273 00274 if (QuotaCharge < MM_MAXIMUM_QUOTA_OVERCHARGE) { 00275 00276 // 00277 // Try the can't expand routine. 00278 // 00279 00280 if (MiChargeCommitmentCantExpand (QuotaCharge, FALSE) == FALSE) { 00281 return FALSE; 00282 } 00283 } else { 00284 00285 // 00286 // Put up a popup and grant an extension if possible. 00287 // 00288 00289 if (MiCauseOverCommitPopup (QuotaCharge, MM_EXTEND_COMMIT) == FALSE) { 00290 return FALSE; 00291 } 00292 } 00293 return TRUE; 00294 } 00295 00296 if (Process != NULL) { 00297 if (WsHeldSafe == TRUE) { 00298 LOCK_WS (Process); 00299 } 00300 else { 00301 LOCK_WS_UNSAFE (Process); 00302 } 00303 } 00304 00305 if (PageExtend.ActualExpansion == 0) { 00306 if (MiCauseOverCommitPopup (QuotaCharge, MM_EXTEND_COMMIT) == FALSE) { 00307 return FALSE; 00308 } 00309 return TRUE; 00310 } 00311 00312 ExAcquireFastLock (&MmChargeCommitmentLock, &OldIrql); 00313 NewCommitValue = MmTotalCommittedPages + QuotaCharge; 00314 } 00315 00316 MmTotalCommittedPages = NewCommitValue; 00317 if ((MmTotalCommittedPages > MmPeakCommitment) && 00318 (MmPageFileFullExtendPages == 0)) { 00319 MmPeakCommitment = MmTotalCommittedPages; 00320 } 00321 00322 ExReleaseFastLock (&MmChargeCommitmentLock, OldIrql); 00323 00324 return TRUE; 00325 }

LOGICAL FASTCALL MiChargeCommitmentCantExpand IN SIZE_T  QuotaCharge,
IN ULONG  MustSucceed
 

Definition at line 329 of file mmquota.c.

References _MMPAGE_FILE_EXPANSION::DereferenceList, FALSE, _MMPAGE_FILE_EXPANSION::InProgress, KeReleaseSemaphore(), L, _MMDEREFERENCE_SEGMENT_HEADER::ListHead, _MMDEREFERENCE_SEGMENT_HEADER::Lock, MM_DONT_EXTEND_SIZE, MmAttemptForCantExtend, MmChargeCommitmentLock, MmDereferenceSegmentHeader, MmTotalCommitLimit, MmTotalCommitLimitMaximum, MmTotalCommittedPages, _MMPAGE_FILE_EXPANSION::RequestedExpansionSize, _MMDEREFERENCE_SEGMENT_HEADER::Semaphore, and TRUE.

Referenced by MiAddWorkingSetPage(), MiAddWsleHash(), MiAllocatePoolPages(), MiAllocateSpecialPool(), MiChargeCommitment(), MiFillSystemPageDirectory(), MiFindContiguousMemory(), MiLoadImageSection(), MiPageFileFull(), MmAllocateIndependentPages(), MmAllocateNonCachedMemory(), MmAllocatePagesForMdl(), and MmInitSystem().

00336 : 00337 00338 This routine charges the specified commitment without attempting 00339 to expand paging file and waiting for the expansion. The routine 00340 determines if the paging file space is exhausted, and if so, 00341 it attempts to ascertain if the paging file space could be expanded. 00342 00343 Arguments: 00344 00345 QuotaCharge - Supplies the quota amount to charge. 00346 00347 MustSucceed - Supplies TRUE if the charge must succeed. 00348 00349 Return Value: 00350 00351 TRUE if the commitment was permitted, FALSE if not. 00352 00353 Environment: 00354 00355 Kernel mode, APCs disabled. 00356 00357 --*/ 00358 00359 { 00360 KIRQL OldIrql; 00361 SIZE_T NewCommitValue; 00362 SIZE_T ExtendAmount; 00363 00364 ExAcquireFastLock (&MmChargeCommitmentLock, &OldIrql); 00365 00366 // 00367 // If the overcommitment is bigger than 512 pages, don't extend. 00368 // 00369 00370 NewCommitValue = MmTotalCommittedPages + QuotaCharge; 00371 00372 if (!MustSucceed) { 00373 00374 if (NewCommitValue > MmTotalCommitLimit) { 00375 00376 if ((NewCommitValue - MmTotalCommitLimit > MM_DONT_EXTEND_SIZE) || 00377 (NewCommitValue < MmTotalCommittedPages) || 00378 (NewCommitValue > MmTotalCommitLimitMaximum)) { 00379 00380 ExReleaseFastLock (&MmChargeCommitmentLock, OldIrql); 00381 return FALSE; 00382 } 00383 } 00384 else if (NewCommitValue > MmTotalCommitLimitMaximum) { 00385 ExReleaseFastLock (&MmChargeCommitmentLock, OldIrql); 00386 return FALSE; 00387 } 00388 } 00389 00390 ExtendAmount = NewCommitValue - MmTotalCommitLimit; 00391 MmTotalCommittedPages = NewCommitValue; 00392 00393 if (NewCommitValue > (MmTotalCommitLimit + 20)) { 00394 00395 // 00396 // Attempt to expand the paging file, but don't wait 00397 // to see if it succeeds. 00398 // 00399 00400 if (MmAttemptForCantExtend.InProgress != FALSE) { 00401 00402 // 00403 // An expansion request is already in progress, assume 00404 // this will succeed. 00405 // 00406 00407 ExReleaseFastLock (&MmChargeCommitmentLock, OldIrql); 00408 return TRUE; 00409 } 00410 00411 MmAttemptForCantExtend.InProgress = TRUE; 00412 ExReleaseFastLock (&MmChargeCommitmentLock, OldIrql); 00413 00414 // 00415 // Queue a message to the segment dereferencing / pagefile extending 00416 // thread to see if the page file can be extended. This is done 00417 // in the context of a system thread due to mutexes which may 00418 // currently be held. 00419 // 00420 00421 if (QuotaCharge > ExtendAmount) { 00422 ExtendAmount = QuotaCharge; 00423 } 00424 00425 MmAttemptForCantExtend.RequestedExpansionSize = ExtendAmount; 00426 ExAcquireFastLock (&MmDereferenceSegmentHeader.Lock, &OldIrql); 00427 InsertTailList ( &MmDereferenceSegmentHeader.ListHead, 00428 &MmAttemptForCantExtend.DereferenceList); 00429 ExReleaseFastLock (&MmDereferenceSegmentHeader.Lock, OldIrql); 00430 00431 KeReleaseSemaphore (&MmDereferenceSegmentHeader.Semaphore, 0L, 1L, FALSE); 00432 } 00433 else { 00434 ExReleaseFastLock (&MmChargeCommitmentLock, OldIrql); 00435 } 00436 00437 return TRUE; 00438 }

ULONG FASTCALL MiChargePageFileQuota IN SIZE_T  QuotaCharge,
IN PEPROCESS  CurrentProcess
 

Definition at line 58 of file mmquota.c.

References ExRaiseStatus(), _EPROCESS_QUOTA_BLOCK::PagefileLimit, _EPROCESS_QUOTA_BLOCK::PagefileUsage, _EPROCESS_QUOTA_BLOCK::PeakPagefileUsage, PEPROCESS_QUOTA_BLOCK, PspDefaultQuotaBlock, _EPROCESS_QUOTA_BLOCK::QuotaLock, and TRUE.

Referenced by MiInsertVad(), MiSetProtectionOnSection(), and NtAllocateVirtualMemory().

00065 : 00066 00067 This routine checks to ensure the user has sufficient page file 00068 quota remaining and, if so, charges the quota. If not an exception 00069 is raised. 00070 00071 Arguments: 00072 00073 QuotaCharge - Supplies the quota amount to charge. 00074 00075 CurrentProcess - Supplies a pointer to the current process. 00076 00077 Return Value: 00078 00079 TRUE if the quota was successfully charged, raises an exception 00080 otherwise. 00081 00082 Environment: 00083 00084 Kernel mode, APCs disabled, WorkingSetLock and AddressCreation mutexes 00085 held. 00086 00087 --*/ 00088 00089 { 00090 SIZE_T NewPagefileValue; 00091 PEPROCESS_QUOTA_BLOCK QuotaBlock; 00092 KIRQL OldIrql; 00093 00094 QuotaBlock = CurrentProcess->QuotaBlock; 00095 00096 retry_charge: 00097 if ( QuotaBlock != &PspDefaultQuotaBlock) { 00098 ExAcquireFastLock (&QuotaBlock->QuotaLock,&OldIrql); 00099 do_charge: 00100 NewPagefileValue = QuotaBlock->PagefileUsage + QuotaCharge; 00101 00102 if (NewPagefileValue > QuotaBlock->PagefileLimit) { 00103 ExReleaseFastLock (&QuotaBlock->QuotaLock,OldIrql); 00104 ExRaiseStatus (STATUS_PAGEFILE_QUOTA_EXCEEDED); 00105 } 00106 00107 QuotaBlock->PagefileUsage = NewPagefileValue; 00108 00109 if (NewPagefileValue > QuotaBlock->PeakPagefileUsage) { 00110 QuotaBlock->PeakPagefileUsage = NewPagefileValue; 00111 } 00112 00113 NewPagefileValue = CurrentProcess->PagefileUsage + QuotaCharge; 00114 CurrentProcess->PagefileUsage = NewPagefileValue; 00115 00116 if (NewPagefileValue > CurrentProcess->PeakPagefileUsage) { 00117 CurrentProcess->PeakPagefileUsage = NewPagefileValue; 00118 } 00119 ExReleaseFastLock (&QuotaBlock->QuotaLock,OldIrql); 00120 } else { 00121 ExAcquireFastLock (&PspDefaultQuotaBlock.QuotaLock,&OldIrql); 00122 00123 if ( (QuotaBlock = CurrentProcess->QuotaBlock) != &PspDefaultQuotaBlock) { 00124 ExReleaseFastLock(&PspDefaultQuotaBlock.QuotaLock,OldIrql); 00125 goto retry_charge; 00126 } 00127 goto do_charge; 00128 } 00129 return TRUE; 00130 }

VOID MiCheckControlArea IN PCONTROL_AREA  ControlArea,
IN PEPROCESS  CurrentProcess,
IN KIRQL  PreviousIrql
 

Definition at line 1823 of file sectsup.c.

References ASSERT, _EVENT_COUNTER::Event, FALSE, KeSetEvent(), LOCK_WS_UNSAFE, MI_UNUSED_SEGMENTS_INSERT_CHARGE, MiCleanSection(), MiHydra, MiPurgeImageSection(), MiRemoveImageSectionObject(), MiSegmentDelete(), MM_PFN_LOCK_ASSERT, MmMaxUnusedSegmentNonPagedPoolUsage, MmMaxUnusedSegmentPagedPoolUsage, MmUnusedSegmentCleanup, MmUnusedSegmentList, MmUnusedSegmentNonPagedPoolUsage, MmUnusedSegmentPagedPoolUsage, NULL, TRUE, UNLOCK_PFN, and UNLOCK_WS_UNSAFE.

Referenced by MiFlushRelease(), MiMapViewInSystemSpace(), MiMapViewOfDataSection(), MiMapViewOfImageSection(), MiRemoveMappedPtes(), MiRemoveMappedView(), MiSectionDelete(), MiShareSessionImage(), MiWriteComplete(), MmCreateSection(), MmFlushImageSection(), MmFlushSection(), MmPurgeSection(), MmShutdownSystem(), and MmUnmapViewInSystemCache().

01831 : 01832 01833 This routine checks the reference counts for the specified 01834 control area, and if the counts are all zero, it marks the 01835 control area for deletion and queues it to the deletion thread. 01836 01837 01838 *********************** NOTE ******************************** 01839 This routine returns with the PFN LOCK RELEASED!!!!! 01840 01841 Arguments: 01842 01843 ControlArea - Supplies a pointer to the control area to check. 01844 01845 CurrentProcess - Supplies a pointer to the current process if and ONLY 01846 IF the working set lock is held. 01847 01848 PreviousIrql - Supplies the previous IRQL. 01849 01850 Return Value: 01851 01852 NONE. 01853 01854 Environment: 01855 01856 Kernel mode, PFN lock held, PFN lock released upon return!!! 01857 01858 --*/ 01859 01860 { 01861 PEVENT_COUNTER PurgeEvent; 01862 ULONG DeleteOnClose; 01863 ULONG DereferenceSegment; 01864 01865 PurgeEvent = NULL; 01866 DeleteOnClose = FALSE; 01867 DereferenceSegment = FALSE; 01868 01869 MM_PFN_LOCK_ASSERT(); 01870 if ((ControlArea->NumberOfMappedViews == 0) && 01871 (ControlArea->NumberOfSectionReferences == 0)) { 01872 01873 ASSERT (ControlArea->NumberOfUserReferences == 0); 01874 01875 if (ControlArea->FilePointer != (PFILE_OBJECT)NULL) { 01876 01877 if (ControlArea->NumberOfPfnReferences == 0) { 01878 01879 // 01880 // There are no views and no physical pages referenced 01881 // by the Segment, dereference the Segment object. 01882 // 01883 01884 ControlArea->u.Flags.BeingDeleted = 1; 01885 DereferenceSegment = TRUE; 01886 01887 ASSERT (ControlArea->u.Flags.FilePointerNull == 0); 01888 ControlArea->u.Flags.FilePointerNull = 1; 01889 01890 if (ControlArea->u.Flags.Image) { 01891 01892 if (MiHydra == TRUE) { 01893 MiRemoveImageSectionObject (ControlArea->FilePointer, ControlArea); 01894 } 01895 else { 01896 ((PCONTROL_AREA)(ControlArea->FilePointer->SectionObjectPointer->ImageSectionObject)) = NULL; 01897 } 01898 01899 } 01900 else { 01901 01902 ASSERT (((PCONTROL_AREA)(ControlArea->FilePointer->SectionObjectPointer->DataSectionObject)) != NULL); 01903 ((PCONTROL_AREA)(ControlArea->FilePointer->SectionObjectPointer->DataSectionObject)) = NULL; 01904 01905 } 01906 } else { 01907 01908 // 01909 // Insert this segment into the unused segment list (unless 01910 // it is already on the list). 01911 // 01912 01913 if (ControlArea->DereferenceList.Flink == NULL) { 01914 InsertTailList ( &MmUnusedSegmentList, 01915 &ControlArea->DereferenceList); 01916 MI_UNUSED_SEGMENTS_INSERT_CHARGE (ControlArea); 01917 } 01918 01919 // 01920 // Indicate if this section should be deleted now that 01921 // the reference counts are zero. 01922 // 01923 01924 DeleteOnClose = ControlArea->u.Flags.DeleteOnClose; 01925 01926 // 01927 // The number of mapped views are zero, the number of 01928 // section references are zero, but there are some 01929 // pages of the file still resident. If this is 01930 // an image with Global Memory, "purge" the subsections 01931 // which contain the global memory and reset them to 01932 // point back to the file. 01933 // 01934 01935 if (ControlArea->u.Flags.GlobalMemory == 1) { 01936 ASSERT (ControlArea->u.Flags.Image == 1); 01937 01938 ControlArea->u.Flags.BeingPurged = 1; 01939 ControlArea->NumberOfMappedViews = 1; 01940 01941 MiPurgeImageSection (ControlArea, CurrentProcess); 01942 01943 ControlArea->u.Flags.BeingPurged = 0; 01944 ControlArea->NumberOfMappedViews -= 1; 01945 if ((ControlArea->NumberOfMappedViews == 0) && 01946 (ControlArea->NumberOfSectionReferences == 0) && 01947 (ControlArea->NumberOfPfnReferences == 0)) { 01948 01949 ControlArea->u.Flags.BeingDeleted = 1; 01950 DereferenceSegment = TRUE; 01951 ControlArea->u.Flags.FilePointerNull = 1; 01952 01953 if (MiHydra == TRUE) { 01954 MiRemoveImageSectionObject (ControlArea->FilePointer, ControlArea); 01955 } 01956 else { 01957 ((PCONTROL_AREA)(ControlArea->FilePointer->SectionObjectPointer->ImageSectionObject)) = NULL; 01958 } 01959 01960 } else { 01961 01962 PurgeEvent = ControlArea->WaitingForDeletion; 01963 ControlArea->WaitingForDeletion = NULL; 01964 } 01965 } 01966 01967 // 01968 // If delete on close is set and the segment was 01969 // not deleted, up the count of mapped views so the 01970 // control area will not be deleted when the PFN lock 01971 // is released. 01972 // 01973 01974 if (DeleteOnClose && !DereferenceSegment) { 01975 ControlArea->NumberOfMappedViews = 1; 01976 ControlArea->u.Flags.BeingDeleted = 1; 01977 } 01978 } 01979 01980 } else { 01981 01982 // 01983 // This Segment is backed by a paging file, dereference the 01984 // Segment object when the number of views goes from 1 to 0 01985 // without regard to the number of PFN references. 01986 // 01987 01988 ControlArea->u.Flags.BeingDeleted = 1; 01989 DereferenceSegment = TRUE; 01990 } 01991 } 01992 else if (ControlArea->WaitingForDeletion != NULL) { 01993 PurgeEvent = ControlArea->WaitingForDeletion; 01994 ControlArea->WaitingForDeletion = NULL; 01995 } 01996 01997 UNLOCK_PFN (PreviousIrql); 01998 01999 if (DereferenceSegment || DeleteOnClose) { 02000 02001 // 02002 // Release the working set mutex, if it is held as the object 02003 // management routines may page fault, etc.. 02004 // 02005 02006 if (CurrentProcess) { 02007 UNLOCK_WS_UNSAFE (CurrentProcess); 02008 } 02009 02010 if (DereferenceSegment) { 02011 02012 // 02013 // Delete the segment. 02014 // 02015 02016 MiSegmentDelete (ControlArea->Segment); 02017 02018 } else { 02019 02020 // 02021 // The segment should be forced closed now. 02022 // 02023 02024 MiCleanSection (ControlArea, TRUE); 02025 } 02026 02027 ASSERT (PurgeEvent == NULL); 02028 02029 // 02030 // Reacquire the working set lock, if a process was specified. 02031 // 02032 02033 if (CurrentProcess) { 02034 LOCK_WS_UNSAFE (CurrentProcess); 02035 } 02036 02037 } else { 02038 02039 // 02040 // If any threads are waiting for the segment, indicate the 02041 // the purge operation has completed. 02042 // 02043 02044 if (PurgeEvent != NULL) { 02045 KeSetEvent (&PurgeEvent->Event, 0, FALSE); 02046 } 02047 02048 if (MmUnusedSegmentPagedPoolUsage > MmMaxUnusedSegmentPagedPoolUsage || 02049 MmUnusedSegmentNonPagedPoolUsage > MmMaxUnusedSegmentNonPagedPoolUsage) { 02050 KeSetEvent (&MmUnusedSegmentCleanup, 0, FALSE); 02051 } 02052 } 02053 02054 return; 02055 }

BOOLEAN MiCheckControlAreaStatus IN SECTION_CHECK_TYPE  SectionCheckType,
IN PSECTION_OBJECT_POINTERS  SectionObjectPointers,
IN ULONG  DelayClose,
OUT PCONTROL_AREA ControlArea,
OUT PKIRQL  OldIrql
 

Definition at line 2149 of file sectsup.c.

References CheckBothSection, CheckImageSection, CheckUserDataSection, _EVENT_COUNTER::Event, FALSE, KeDelayExecutionThread(), KeEnterCriticalRegion, KeLeaveCriticalRegion, KernelMode, KeWaitForSingleObject(), LOCK_PFN, MiFreeEventCounter(), MiGetEventCounter(), MmShortTime, NULL, _CONTROL_AREA::NumberOfMappedViews, _CONTROL_AREA::NumberOfSectionReferences, _CONTROL_AREA::NumberOfUserReferences, _EVENT_COUNTER::RefCount, TRUE, _CONTROL_AREA::u, UNLOCK_PFN, UNLOCK_PFN_AND_THEN_WAIT, _CONTROL_AREA::WaitingForDeletion, and WrPageOut.

Referenced by MmFlushImageSection(), and MmForceSectionClosed().

02159 : 02160 02161 This routine checks the status of the control area for the specified 02162 SectionObjectPointers. If the control area is in use, that is, the 02163 number of section references and the number of mapped views are not 02164 both zero, no action is taken and the function returns FALSE. 02165 02166 If there is no control area associated with the specified 02167 SectionObjectPointers or the control area is in the process of being 02168 created or deleted, no action is taken and the value TRUE is returned. 02169 02170 If, there are no section objects and the control area is not being 02171 created or deleted, the address of the control area is returned 02172 in the ControlArea argument, the address of a pool block to free 02173 is returned in the SegmentEventOut argument and the PFN_LOCK is 02174 still held at the return. 02175 02176 Arguments: 02177 02178 *SegmentEventOut - Returns a pointer to NonPaged Pool which much be 02179 freed by the caller when the PFN_LOCK is released. 02180 This value is NULL if no pool is allocated and the 02181 PFN_LOCK is not held. 02182 02183 SectionCheckType - Supplies the type of section to check on, one of 02184 CheckImageSection, CheckDataSection, CheckBothSection. 02185 02186 SectionObjectPointers - Supplies the section object pointers through 02187 which the control area can be located. 02188 02189 DelayClose - Supplies a boolean which if TRUE and the control area 02190 is being used, the delay on close field should be set 02191 in the control area. 02192 02193 *ControlAreaOut - Returns the address of the control area. 02194 02195 PreviousIrql - Returns, in the case the PFN_LOCK is held, the previous 02196 IRQL so the lock can be released properly. 02197 02198 Return Value: 02199 02200 FALSE if the control area is in use, TRUE if the control area is gone or 02201 in the process or being created or deleted. 02202 02203 Environment: 02204 02205 Kernel mode, PFN lock NOT held. 02206 02207 --*/ 02208 02209 02210 { 02211 PEVENT_COUNTER IoEvent; 02212 PEVENT_COUNTER SegmentEvent; 02213 ULONG DeallocateSegmentEvent = TRUE; 02214 PCONTROL_AREA ControlArea; 02215 ULONG SectRef; 02216 KIRQL OldIrql; 02217 02218 // 02219 // Allocate an event to wait on in case the segment is in the 02220 // process of being deleted. This event cannot be allocated 02221 // with the PFN database locked as pool expansion would deadlock. 02222 // 02223 02224 *ControlAreaOut = NULL; 02225 02226 // 02227 // Acquire the PFN lock and examine the section object pointer 02228 // value within the file object. 02229 // 02230 02231 // 02232 // File control blocks live in non-paged pool. 02233 // 02234 02235 LOCK_PFN (OldIrql); 02236 02237 SegmentEvent = MiGetEventCounter (); 02238 02239 while (SegmentEvent == NULL) { 02240 UNLOCK_PFN (OldIrql); 02241 KeDelayExecutionThread (KernelMode, FALSE, (PLARGE_INTEGER)&MmShortTime); 02242 LOCK_PFN (OldIrql); 02243 SegmentEvent = MiGetEventCounter (); 02244 } 02245 02246 if (SectionCheckType != CheckImageSection) { 02247 ControlArea = ((PCONTROL_AREA)(SectionObjectPointers->DataSectionObject)); 02248 } else { 02249 ControlArea = ((PCONTROL_AREA)(SectionObjectPointers->ImageSectionObject)); 02250 } 02251 02252 if (ControlArea == NULL) { 02253 02254 if (SectionCheckType != CheckBothSection) { 02255 02256 // 02257 // This file no longer has an associated segment. 02258 // 02259 02260 MiFreeEventCounter (SegmentEvent, TRUE); 02261 UNLOCK_PFN (OldIrql); 02262 return TRUE; 02263 } else { 02264 ControlArea = ((PCONTROL_AREA)(SectionObjectPointers->ImageSectionObject)); 02265 if (ControlArea == NULL) { 02266 02267 // 02268 // This file no longer has an associated segment. 02269 // 02270 02271 MiFreeEventCounter (SegmentEvent, TRUE); 02272 UNLOCK_PFN (OldIrql); 02273 return TRUE; 02274 } 02275 } 02276 } 02277 02278 // 02279 // Depending on the type of section, check for the pertinent 02280 // reference count being non-zero. 02281 // 02282 02283 if (SectionCheckType != CheckUserDataSection) { 02284 SectRef = ControlArea->NumberOfSectionReferences; 02285 } else { 02286 SectRef = ControlArea->NumberOfUserReferences; 02287 } 02288 02289 if ((SectRef != 0) || 02290 (ControlArea->NumberOfMappedViews != 0) || 02291 (ControlArea->u.Flags.BeingCreated)) { 02292 02293 02294 // 02295 // The segment is currently in use or being created. 02296 // 02297 02298 if (DelayClose) { 02299 02300 // 02301 // The section should be deleted when the reference 02302 // counts are zero, set the delete on close flag. 02303 // 02304 02305 ControlArea->u.Flags.DeleteOnClose = 1; 02306 } 02307 02308 MiFreeEventCounter (SegmentEvent, TRUE); 02309 UNLOCK_PFN (OldIrql); 02310 return FALSE; 02311 } 02312 02313 // 02314 // The segment has no references, delete it. If the segment 02315 // is already being deleted, set the event field in the control 02316 // area and wait on the event. 02317 // 02318 02319 if (ControlArea->u.Flags.BeingDeleted) { 02320 02321 // 02322 // The segment object is in the process of being deleted. 02323 // Check to see if another thread is waiting for the deletion, 02324 // otherwise create and event object to wait upon. 02325 // 02326 02327 if (ControlArea->WaitingForDeletion == NULL) { 02328 02329 // 02330 // Create an event and put its address in the control area. 02331 // 02332 02333 DeallocateSegmentEvent = FALSE; 02334 ControlArea->WaitingForDeletion = SegmentEvent; 02335 IoEvent = SegmentEvent; 02336 } else { 02337 IoEvent = ControlArea->WaitingForDeletion; 02338 IoEvent->RefCount += 1; 02339 } 02340 02341 // 02342 // Release the mutex and wait for the event. 02343 // 02344 02345 KeEnterCriticalRegion(); 02346 UNLOCK_PFN_AND_THEN_WAIT(OldIrql); 02347 02348 KeWaitForSingleObject(&IoEvent->Event, 02349 WrPageOut, 02350 KernelMode, 02351 FALSE, 02352 (PLARGE_INTEGER)NULL); 02353 02354 LOCK_PFN (OldIrql); 02355 KeLeaveCriticalRegion(); 02356 02357 MiFreeEventCounter (IoEvent, TRUE); 02358 if (DeallocateSegmentEvent) { 02359 MiFreeEventCounter (SegmentEvent, TRUE); 02360 } 02361 UNLOCK_PFN (OldIrql); 02362 return TRUE; 02363 } 02364 02365 // 02366 // Return with the PFN database locked. 02367 // 02368 02369 MiFreeEventCounter (SegmentEvent, FALSE); 02370 *ControlAreaOut = ControlArea; 02371 *PreviousIrql = OldIrql; 02372 return FALSE; 02373 }

PMMADDRESS_NODE MiCheckForConflictingNode IN ULONG_PTR  StartVpn,
IN ULONG_PTR  EndVpn,
IN PMMADDRESS_NODE  Root
 

Definition at line 1068 of file addrsup.c.

References _MMADDRESS_NODE::EndingVpn, _MMADDRESS_NODE::LeftChild, NULL, _MMADDRESS_NODE::RightChild, and _MMADDRESS_NODE::StartingVpn.

01076 : 01077 01078 The function determines if any addresses between a given starting and 01079 ending address is contained within a virtual address descriptor. 01080 01081 Arguments: 01082 01083 StartVpn - Supplies the virtual address to locate a containing 01084 descriptor. 01085 01086 EndVpn - Supplies the virtual address to locate a containing 01087 descriptor. 01088 01089 Return Value: 01090 01091 Returns a pointer to the first conflicting virtual address descriptor 01092 if one is found, otherwise a NULL value is returned. 01093 01094 --*/ 01095 01096 { 01097 PMMADDRESS_NODE Node; 01098 01099 Node = Root; 01100 01101 for (;;) { 01102 01103 if (Node == (PMMADDRESS_NODE)NULL) { 01104 return (PMMADDRESS_NODE)NULL; 01105 } 01106 01107 if (StartVpn > Node->EndingVpn) { 01108 Node = Node->RightChild; 01109 01110 } else if (EndVpn < Node->StartingVpn) { 01111 Node = Node->LeftChild; 01112 01113 } else { 01114 01115 // 01116 // The starting address is less than or equal to the end VA 01117 // and the ending address is greater than or equal to the 01118 // start va. Return this node. 01119 // 01120 01121 return Node; 01122 } 01123 } 01124 }

PVOID MiCheckForContiguousMemory IN PVOID  BaseAddress,
IN PFN_NUMBER  BaseAddressPages,
IN PFN_NUMBER  SizeInPages,
IN PFN_NUMBER  LowestPfn,
IN PFN_NUMBER  HighestPfn,
IN PFN_NUMBER  BoundaryPfn
 

Definition at line 6052 of file iosup.c.

References ASSERT, MI_CONVERT_PHYSICAL_TO_PFN, MI_GET_PAGE_FRAME_FROM_PTE, MI_IS_PHYSICAL_ADDRESS, MiGetPteAddress, MiGetVirtualAddressMappedByPte, NULL, PAGE_SHIFT, and _MMPTE::u.

Referenced by MiAllocateContiguousMemory(), and MiFindContiguousMemory().

06063 : 06064 06065 This routine checks to see if the physical memory mapped 06066 by the specified BaseAddress for the specified size is 06067 contiguous and that the first page is greater than or equal to 06068 the specified LowestPfn and that the last page of the physical memory is 06069 less than or equal to the specified HighestPfn. 06070 06071 Arguments: 06072 06073 BaseAddress - Supplies the base address to start checking at. 06074 06075 BaseAddressPages - Supplies the number of pages to scan from the 06076 BaseAddress. 06077 06078 SizeInPages - Supplies the number of pages in the range. 06079 06080 LowestPfn - Supplies lowest PFN acceptable as a physical page. 06081 06082 HighestPfn - Supplies the highest PFN acceptable as a physical page. 06083 06084 BoundaryPfn - Supplies the PFN multiple the allocation must 06085 not cross. 0 indicates it can cross any boundary. 06086 06087 Return Value: 06088 06089 Returns the usable virtual address within the argument range that the 06090 caller should return to his caller. NULL if there is no usable address. 06091 06092 Environment: 06093 06094 Kernel mode, memory management internal. 06095 06096 --*/ 06097 06098 { 06099 PMMPTE PointerPte; 06100 PMMPTE LastPte; 06101 PFN_NUMBER PreviousPage; 06102 PFN_NUMBER Page; 06103 PFN_NUMBER HighestStartPage; 06104 PFN_NUMBER LastPage; 06105 PFN_NUMBER OriginalPage; 06106 PFN_NUMBER OriginalLastPage; 06107 PVOID BoundaryAllocation; 06108 PFN_NUMBER BoundaryMask; 06109 ULONG PageCount; 06110 MMPTE PteContents; 06111 06112 BoundaryMask = ~(BoundaryPfn - 1); 06113 06114 if (LowestPfn > HighestPfn) { 06115 return NULL; 06116 } 06117 06118 if (LowestPfn + SizeInPages <= LowestPfn) { 06119 return NULL; 06120 } 06121 06122 if (LowestPfn + SizeInPages > HighestPfn + 1) { 06123 return NULL; 06124 } 06125 06126 if (BaseAddressPages < SizeInPages) { 06127 return NULL; 06128 } 06129 06130 if (MI_IS_PHYSICAL_ADDRESS (BaseAddress)) { 06131 06132 OriginalPage = MI_CONVERT_PHYSICAL_TO_PFN(BaseAddress); 06133 OriginalLastPage = OriginalPage + BaseAddressPages; 06134 06135 Page = OriginalPage; 06136 LastPage = OriginalLastPage; 06137 06138 // 06139 // Close the gaps, then examine the range for a fit. 06140 // 06141 06142 if (Page < LowestPfn) { 06143 Page = LowestPfn; 06144 } 06145 06146 if (LastPage > HighestPfn + 1) { 06147 LastPage = HighestPfn + 1; 06148 } 06149 06150 HighestStartPage = LastPage - SizeInPages; 06151 06152 if (Page > HighestStartPage) { 06153 return NULL; 06154 } 06155 06156 if (BoundaryPfn != 0) { 06157 do { 06158 if (((Page ^ (Page + SizeInPages - 1)) & BoundaryMask) == 0) { 06159 06160 // 06161 // This portion of the range meets the alignment 06162 // requirements. 06163 // 06164 06165 break; 06166 } 06167 Page |= (BoundaryPfn - 1); 06168 Page += 1; 06169 } while (Page <= HighestStartPage); 06170 06171 if (Page > HighestStartPage) { 06172 return NULL; 06173 } 06174 BoundaryAllocation = (PVOID)((PCHAR)BaseAddress + ((Page - OriginalPage) << PAGE_SHIFT)); 06175 06176 // 06177 // The request can be satisfied. Since specific alignment was 06178 // requested, return the fit now without getting fancy. 06179 // 06180 06181 return BoundaryAllocation; 06182 } 06183 06184 // 06185 // If possible return a chunk on the end to reduce fragmentation. 06186 // 06187 06188 if (LastPage == OriginalLastPage) { 06189 return (PVOID)((PCHAR)BaseAddress + ((BaseAddressPages - SizeInPages) << PAGE_SHIFT)); 06190 } 06191 06192 // 06193 // The end chunk did not satisfy the requirements. The next best option 06194 // is to return a chunk from the beginning. Since that's where the search 06195 // began, just return the current chunk. 06196 // 06197 06198 return (PVOID)((PCHAR)BaseAddress + ((Page - OriginalPage) << PAGE_SHIFT)); 06199 } 06200 06201 // 06202 // Check the virtual addresses for physical contiguity. 06203 // 06204 06205 PointerPte = MiGetPteAddress (BaseAddress); 06206 LastPte = PointerPte + BaseAddressPages; 06207 06208 HighestStartPage = HighestPfn + 1 - SizeInPages; 06209 PageCount = 0; 06210 06211 while (PointerPte < LastPte) { 06212 06213 PteContents = *PointerPte; 06214 ASSERT (PteContents.u.Hard.Valid == 1); 06215 Page = MI_GET_PAGE_FRAME_FROM_PTE (&PteContents); 06216 06217 // 06218 // Before starting a new run, ensure that it 06219 // can satisfy the location & boundary requirements (if any). 06220 // 06221 06222 if (PageCount == 0) { 06223 06224 if ((Page >= LowestPfn) && (Page <= HighestStartPage)) { 06225 06226 if (BoundaryPfn == 0) { 06227 PageCount += 1; 06228 } 06229 else if (((Page ^ (Page + SizeInPages - 1)) & BoundaryMask) == 0) { 06230 // 06231 // This run's physical address meets the alignment 06232 // requirement. 06233 // 06234 06235 PageCount += 1; 06236 } 06237 } 06238 06239 if (PageCount == SizeInPages) { 06240 06241 // 06242 // Success - found a single page satifying the requirements. 06243 // 06244 06245 BaseAddress = MiGetVirtualAddressMappedByPte (PointerPte); 06246 return BaseAddress; 06247 } 06248 06249 PreviousPage = Page; 06250 PointerPte += 1; 06251 continue; 06252 } 06253 06254 if (Page != PreviousPage + 1) { 06255 06256 // 06257 // This page is not physically contiguous. Start over. 06258 // 06259 06260 PageCount = 0; 06261 continue; 06262 } 06263 06264 PageCount += 1; 06265 06266 if (PageCount == SizeInPages) { 06267 06268 // 06269 // Success - found a page range satifying the requirements. 06270 // 06271 06272 BaseAddress = MiGetVirtualAddressMappedByPte (PointerPte - PageCount + 1); 06273 return BaseAddress; 06274 } 06275 06276 PointerPte += 1; 06277 } 06278 06279 return NULL; 06280 }

VOID MiCheckForControlAreaDeletion IN PCONTROL_AREA  ControlArea  ) 
 

Definition at line 2059 of file sectsup.c.

References ASSERT, FALSE, KeReleaseSemaphore(), L, _MMDEREFERENCE_SEGMENT_HEADER::ListHead, _MMDEREFERENCE_SEGMENT_HEADER::Lock, MI_UNUSED_SEGMENTS_REMOVE_CHARGE, MiHydra, MiRemoveImageSectionObject(), MM_PFN_LOCK_ASSERT, MmDereferenceSegmentHeader, NULL, _MMDEREFERENCE_SEGMENT_HEADER::Semaphore, and TRUE.

Referenced by MiRestoreTransitionPte().

02065 : 02066 02067 This routine checks the reference counts for the specified 02068 control area, and if the counts are all zero, it marks the 02069 control area for deletion and queues it to the deletion thread. 02070 02071 Arguments: 02072 02073 ControlArea - Supplies a pointer to the control area to check. 02074 02075 Return Value: 02076 02077 None. 02078 02079 Environment: 02080 02081 Kernel mode, PFN lock held. 02082 02083 --*/ 02084 02085 { 02086 KIRQL OldIrql; 02087 02088 MM_PFN_LOCK_ASSERT(); 02089 if ((ControlArea->NumberOfPfnReferences == 0) && 02090 (ControlArea->NumberOfMappedViews == 0) && 02091 (ControlArea->NumberOfSectionReferences == 0 )) { 02092 02093 // 02094 // This segment is no longer mapped in any address space 02095 // nor are there any prototype PTEs within the segment 02096 // which are valid or in a transition state. Queue 02097 // the segment to the segment-dereferencer thread 02098 // which will dereference the segment object, potentially 02099 // causing the segment to be deleted. 02100 // 02101 02102 ControlArea->u.Flags.BeingDeleted = 1; 02103 ASSERT (ControlArea->u.Flags.FilePointerNull == 0); 02104 ControlArea->u.Flags.FilePointerNull = 1; 02105 02106 if (ControlArea->u.Flags.Image) { 02107 02108 if (MiHydra == TRUE) { 02109 MiRemoveImageSectionObject (ControlArea->FilePointer, 02110 ControlArea); 02111 } 02112 else { 02113 ((PCONTROL_AREA)(ControlArea->FilePointer->SectionObjectPointer->ImageSectionObject)) = NULL; 02114 } 02115 02116 } 02117 else { 02118 ((PCONTROL_AREA)(ControlArea->FilePointer->SectionObjectPointer->DataSectionObject)) = 02119 NULL; 02120 } 02121 02122 ExAcquireSpinLock (&MmDereferenceSegmentHeader.Lock, &OldIrql); 02123 02124 ASSERT (ControlArea->DereferenceList.Flink != NULL); 02125 02126 // 02127 // Remove the entry from the unused segment list and put it 02128 // on the dereference list. 02129 // 02130 02131 RemoveEntryList (&ControlArea->DereferenceList); 02132 02133 MI_UNUSED_SEGMENTS_REMOVE_CHARGE (ControlArea); 02134 02135 InsertTailList (&MmDereferenceSegmentHeader.ListHead, 02136 &ControlArea->DereferenceList); 02137 ExReleaseSpinLock (&MmDereferenceSegmentHeader.Lock, OldIrql); 02138 02139 KeReleaseSemaphore (&MmDereferenceSegmentHeader.Semaphore, 02140 0L, 02141 1L, 02142 FALSE); 02143 } 02144 return; 02145 }

NTSTATUS FASTCALL MiCheckForUserStackOverflow IN PVOID  FaultingAddress  ) 
 

Definition at line 194 of file acceschk.c.

References ASSERT, EXCEPTION_EXECUTE_HANDLER, ExpDefaultErrorPortProcess, _MMLOCK_CONFLICT::List, MmChargeCommitmentLock, MmExtendedCommit, MmLockConflictList, MmTotalCommitLimit, NT_SUCCESS, NTSTATUS(), NULL, PAGE_ALIGN, PAGE_SIZE, PMMLOCK_CONFLICT, ProbeForRead, PsGetCurrentProcess, PsGetCurrentThread, and _MMLOCK_CONFLICT::Thread.

Referenced by MmAccessFault().

00200 : 00201 00202 This routine checks to see if the faulting address is within 00203 the stack limits and if so tries to create another guard 00204 page on the stack. A stack over flow is returned if the 00205 creation of a new guard page fails or if the stack is in 00206 the following form: 00207 00208 00209 stack +----------------+ 00210 growth | | StackBase 00211 | +----------------+ 00212 v | | 00213 | allocated | 00214 | | 00215 | ... | 00216 | | 00217 +----------------+ 00218 | old guard page | <- faulting address is in this page. 00219 +----------------+ 00220 | | 00221 +----------------+ 00222 | | last page of stack (always no access) 00223 +----------------+ 00224 00225 In this case, the page before the last page is committed, but 00226 not as a guard page and a STACK_OVERFLOW condition is returned. 00227 00228 Arguments: 00229 00230 FaultingAddress - Supplies the virtual address of the page which 00231 was a guard page. 00232 00233 Return Value: 00234 00235 None. 00236 00237 Environment: 00238 00239 Kernel mode. No mutexes held. 00240 00241 --*/ 00242 00243 { 00244 PTEB Teb; 00245 ULONG_PTR NextPage; 00246 SIZE_T RegionSize; 00247 NTSTATUS status; 00248 KIRQL OldIrql; 00249 PMMLOCK_CONFLICT Next; 00250 PVOID DeallocationStack; 00251 PVOID *StackLimit; 00252 00253 #if defined(WX86) || defined(_AXP64_) 00254 PWX86TIB Wx86Tib; 00255 #endif 00256 #if defined(_WIN64) 00257 PTEB32 Teb32; 00258 #endif 00259 00260 // 00261 // Make sure we are not recursing with the address space or 00262 // working set lock held. 00263 // 00264 00265 if (!IsListEmpty (&MmLockConflictList)) { 00266 ExAcquireSpinLock (&MmChargeCommitmentLock, &OldIrql); 00267 Next = (PMMLOCK_CONFLICT)MmLockConflictList.Flink; 00268 00269 while ((PVOID)Next != &MmLockConflictList) { 00270 00271 if (Next->Thread == PsGetCurrentThread()) { 00272 ExReleaseSpinLock (&MmChargeCommitmentLock, OldIrql); 00273 return STATUS_GUARD_PAGE_VIOLATION; 00274 } 00275 Next = (PMMLOCK_CONFLICT)Next->List.Flink; 00276 } 00277 ExReleaseSpinLock (&MmChargeCommitmentLock, OldIrql); 00278 } 00279 00280 // 00281 // Create an exception handler as the TEB is within the user's 00282 // address space. 00283 // 00284 00285 try { 00286 00287 Teb = NtCurrentTeb(); 00288 00289 #if defined(_IA64_) 00290 00291 if ((Teb->NtTib.StackBase <= FaultingAddress) && 00292 (Teb->DeallocationBStore > FaultingAddress)) { 00293 00294 // 00295 // check to see if the faulting address is within 00296 // the bstore limits and if so tries to create another guard 00297 // page on the bstore. 00298 // 00299 // 00300 // +----------------+ 00301 // | | last page of stack (always no access) 00302 // +----------------+ 00303 // | | 00304 // | | 00305 // | | 00306 // +----------------+ 00307 // | old guard page | <- faulting address is in this page. | 00308 // +----------------+ 00309 // bstore | | 00310 // growth | ...... | 00311 // | | 00312 // ^ | allocated | 00313 // | | | StackBase 00314 // +----------------+ 00315 // 00316 // 00317 00318 NextPage = (ULONG_PTR)PAGE_ALIGN(FaultingAddress) + PAGE_SIZE; 00319 00320 RegionSize = PAGE_SIZE; 00321 00322 if ((NextPage + PAGE_SIZE) >= (ULONG_PTR)PAGE_ALIGN(Teb->DeallocationBStore)) { 00323 00324 // 00325 // There is no more room for expansion, attempt to 00326 // commit the page before the last page of the 00327 // stack. 00328 // 00329 00330 NextPage = (ULONG_PTR)PAGE_ALIGN(Teb->DeallocationBStore) - PAGE_SIZE; 00331 00332 status = ZwAllocateVirtualMemory (NtCurrentProcess(), 00333 (PVOID *)&NextPage, 00334 0, 00335 &RegionSize, 00336 MEM_COMMIT, 00337 PAGE_READWRITE); 00338 if ( NT_SUCCESS(status) ) { 00339 Teb->BStoreLimit = (PVOID)( (PUCHAR)NextPage); 00340 } 00341 00342 return STATUS_STACK_OVERFLOW; 00343 } 00344 00345 Teb->BStoreLimit = (PVOID)((PUCHAR)(NextPage)); 00346 00347 } else { 00348 00349 #endif 00350 00351 DeallocationStack = Teb->DeallocationStack; 00352 StackLimit = &Teb->NtTib.StackLimit; 00353 00354 // 00355 // The stack base and the stack limit are both within the stack. 00356 // 00357 00358 if ((Teb->NtTib.StackBase <= FaultingAddress) || 00359 (DeallocationStack > FaultingAddress)) { 00360 00361 #if defined(WX86) 00362 // 00363 // Also check the Wx86 i386 stack on risc. 00364 // 00365 Wx86Tib = Teb->Vdm; 00366 if (Wx86Tib) { 00367 ProbeForRead(Wx86Tib, sizeof(WX86TIB), sizeof(ULONG)); 00368 if (Wx86Tib->Size == sizeof(WX86TIB) && 00369 Wx86Tib->StackBase > FaultingAddress && 00370 Wx86Tib->DeallocationStack <= FaultingAddress) { 00371 00372 DeallocationStack = Wx86Tib->DeallocationStack; 00373 StackLimit = &Wx86Tib->StackLimit; 00374 } else { 00375 // 00376 // Not within the stack. 00377 // 00378 00379 return STATUS_GUARD_PAGE_VIOLATION; 00380 } 00381 } else 00382 #endif 00383 #if defined(_WIN64) 00384 // 00385 // Also check for the 32-bit native stack on NT64 00386 // 00387 if ((Teb32 = (PTEB32)Teb->NtTib.ExceptionList) != NULL) { 00388 ProbeForRead(Teb32, sizeof(TEB32), sizeof(ULONG)); 00389 if ((ULONG_PTR)Teb32->NtTib.StackBase > (ULONG_PTR)FaultingAddress && 00390 (ULONG_PTR)Teb32->DeallocationStack <= (ULONG_PTR)FaultingAddress) { 00391 DeallocationStack = (PVOID)ULongToPtr(Teb32->DeallocationStack); 00392 00393 StackLimit = (PVOID *)&Teb32->NtTib.StackLimit; 00394 } else 00395 #if defined(_AXP64_) 00396 // 00397 // Also check the Wx86 i386 stack on risc. 00398 // 00399 if (Wx86Tib = (PWX86TIB)ULongToPtr(Teb32->Vdm)) { 00400 ProbeForRead(Wx86Tib, sizeof(WX86TIB), sizeof(ULONG)); 00401 if (Wx86Tib->Size == sizeof(WX86TIB) && 00402 (ULONG_PTR)Wx86Tib->StackBase > (ULONG_PTR)FaultingAddress && 00403 (ULONG_PTR)Wx86Tib->DeallocationStack <= (ULONG_PTR)FaultingAddress) { 00404 00405 DeallocationStack = Wx86Tib->DeallocationStack; 00406 StackLimit = (PVOID *)(&Wx86Tib->StackLimit); 00407 } else { 00408 // 00409 // Not within the stack. 00410 // 00411 00412 return STATUS_GUARD_PAGE_VIOLATION; 00413 } 00414 } else 00415 #endif 00416 { 00417 // 00418 // Not within the stack. 00419 // 00420 00421 return STATUS_GUARD_PAGE_VIOLATION; 00422 } 00423 } else 00424 #endif 00425 { 00426 // 00427 // Not within the stack. 00428 // 00429 00430 return STATUS_GUARD_PAGE_VIOLATION; 00431 } 00432 } 00433 00434 // 00435 // This address is within the current stack, check to see 00436 // if there is ample room for another guard page and 00437 // if so attempt to commit a new guard page. 00438 // 00439 00440 NextPage = ((ULONG_PTR)PAGE_ALIGN(FaultingAddress) - PAGE_SIZE); 00441 00442 RegionSize = PAGE_SIZE; 00443 00444 if ((NextPage - PAGE_SIZE) <= (ULONG_PTR)PAGE_ALIGN(DeallocationStack)) { 00445 00446 // 00447 // There is no more room for expansion, attempt to 00448 // commit the page before the last page of the 00449 // stack. 00450 // 00451 00452 NextPage = (ULONG_PTR)PAGE_ALIGN(DeallocationStack) + PAGE_SIZE; 00453 00454 status = ZwAllocateVirtualMemory (NtCurrentProcess(), 00455 (PVOID *)&NextPage, 00456 0, 00457 &RegionSize, 00458 MEM_COMMIT, 00459 PAGE_READWRITE); 00460 if ( NT_SUCCESS(status) ) { 00461 00462 #if defined(_WIN64) 00463 if (Teb32) { 00464 // update the 32-bit stacklimit 00465 *(ULONG *)StackLimit = PtrToUlong((PUCHAR)NextPage); 00466 } else { 00467 *StackLimit = (PVOID)( (PUCHAR)NextPage); 00468 } 00469 #else 00470 *StackLimit = (PVOID)( (PUCHAR)NextPage); 00471 #endif 00472 00473 } 00474 00475 return STATUS_STACK_OVERFLOW; 00476 } 00477 #if defined(_WIN64) 00478 if (Teb32) { 00479 // Update the 32-bit stacklimit 00480 *(ULONG *)StackLimit = PtrToUlong((PUCHAR)(NextPage + PAGE_SIZE)); 00481 } else { 00482 *StackLimit = (PVOID)((PUCHAR)(NextPage + PAGE_SIZE)); 00483 } 00484 #else 00485 *StackLimit = (PVOID)((PUCHAR)(NextPage + PAGE_SIZE)); 00486 #endif 00487 00488 #if defined(_IA64_) 00489 } 00490 #endif // _IA64_ 00491 00492 retry: 00493 status = ZwAllocateVirtualMemory (NtCurrentProcess(), 00494 (PVOID *)&NextPage, 00495 0, 00496 &RegionSize, 00497 MEM_COMMIT, 00498 PAGE_READWRITE | PAGE_GUARD); 00499 00500 00501 if (NT_SUCCESS(status) || (status == STATUS_ALREADY_COMMITTED)) { 00502 00503 // 00504 // The guard page is now committed or stack space is 00505 // already present, return success. 00506 // 00507 00508 return STATUS_PAGE_FAULT_GUARD_PAGE; 00509 } 00510 00511 if (PsGetCurrentProcess() == ExpDefaultErrorPortProcess) { 00512 00513 // 00514 // Don't let CSRSS process get any stack overflows due to 00515 // commitment. Increase the commitment by a page and 00516 // try again. 00517 // 00518 00519 ASSERT (status == STATUS_COMMITMENT_LIMIT); 00520 00521 ExAcquireSpinLock (&MmChargeCommitmentLock, &OldIrql); 00522 MmTotalCommitLimit += 1; 00523 MmExtendedCommit += 1; 00524 ExReleaseSpinLock (&MmChargeCommitmentLock, OldIrql); 00525 goto retry; 00526 } 00527 00528 return STATUS_STACK_OVERFLOW; 00529 00530 } except (EXCEPTION_EXECUTE_HANDLER) { 00531 00532 // 00533 // An exception has occurred during the referencing of the 00534 // TEB or TIB, just return a guard page violation and 00535 // don't deal with the stack overflow. 00536 // 00537 00538 return STATUS_GUARD_PAGE_VIOLATION; 00539 } 00540 } }

NTSTATUS FASTCALL MiCheckPdeForPagedPool IN PVOID  VirtualAddress  ) 
 

Definition at line 3125 of file pagfault.c.

References FALSE, MI_IS_KERNEL_PAGE_TABLE_ADDRESS, MI_IS_SESSION_ADDRESS, MI_IS_SESSION_PTE, MI_WRITE_VALID_PTE, MiCheckPdeForSessionSpace(), MiGetPdeAddress, MiGetPteAddress, MiGetVirtualAddressMappedByPte, MiHydra, MMPTE, MmSystemPagePtes, MmSystemRangeStart, NTSTATUS(), PDE_PER_PAGE, TRUE, and _MMPTE::u.

Referenced by MiCheckProtoPtePageState(), MiCloneProcessAddressSpace(), MiDeletePte(), MiDeleteSystemPagableVm(), MiEliminateWorkingSetEntry(), MiHandleForkTransitionPte(), MiInitializeCopyOnWritePfn(), MiInitializePfn(), MiInitializeReadInProgressPfn(), MiInitializeTransitionPfn(), and MmAccessFault().

03131 : 03132 03133 This function copies the Page Table Entry for the corresponding 03134 virtual address from the system process's page directory. 03135 03136 This allows page table pages to be lazily evaluated for things 03137 like paged pool and per-session mappings. 03138 03139 Arguments: 03140 03141 VirtualAddress - Supplies the virtual address in question. 03142 03143 Return Value: 03144 03145 Either success or access violation. 03146 03147 Environment: 03148 03149 Kernel mode, DISPATCH level or below. 03150 03151 --*/ 03152 { 03153 PMMPTE PointerPde; 03154 PMMPTE PointerPte; 03155 NTSTATUS status; 03156 03157 if (MiHydra == TRUE) { 03158 03159 if (MI_IS_SESSION_ADDRESS (VirtualAddress) == TRUE) { 03160 03161 // 03162 // Virtual address in the session space range. 03163 // 03164 03165 return MiCheckPdeForSessionSpace (VirtualAddress); 03166 } 03167 03168 if (MI_IS_SESSION_PTE (VirtualAddress) == TRUE) { 03169 03170 // 03171 // PTE for the session space range. 03172 // 03173 03174 return MiCheckPdeForSessionSpace (VirtualAddress); 03175 } 03176 } 03177 03178 status = STATUS_SUCCESS; 03179 03180 if (MI_IS_KERNEL_PAGE_TABLE_ADDRESS(VirtualAddress)) { 03181 03182 // 03183 // PTE for paged pool. 03184 // 03185 03186 PointerPde = MiGetPteAddress (VirtualAddress); 03187 status = STATUS_WAIT_1; 03188 } else if (VirtualAddress < MmSystemRangeStart) { 03189 03190 return STATUS_ACCESS_VIOLATION; 03191 03192 } else { 03193 03194 // 03195 // Virtual address in paged pool range. 03196 // 03197 03198 PointerPde = MiGetPdeAddress (VirtualAddress); 03199 } 03200 03201 // 03202 // Locate the PDE for this page and make it valid. 03203 // 03204 03205 if (PointerPde->u.Hard.Valid == 0) { 03206 PointerPte = MiGetVirtualAddressMappedByPte (PointerPde); 03207 #if !defined (_X86PAE_) 03208 MI_WRITE_VALID_PTE (PointerPde, 03209 MmSystemPagePtes [((ULONG_PTR)PointerPde & 03210 ((sizeof(MMPTE) * PDE_PER_PAGE) - 1)) / sizeof(MMPTE)]); 03211 #else 03212 MI_WRITE_VALID_PTE (PointerPde, 03213 MmSystemPagePtes [((ULONG_PTR)PointerPde & 03214 (PD_PER_SYSTEM * (sizeof(MMPTE) * PDE_PER_PAGE) - 1)) / sizeof(MMPTE)]); 03215 #endif 03216 KeFillEntryTb ((PHARDWARE_PTE)PointerPde, PointerPte, FALSE); 03217 } 03218 return status; 03219 }

NTSTATUS FASTCALL MiCheckPdeForSessionSpace IN PVOID  VirtualAddress  ) 
 

Definition at line 3224 of file pagfault.c.

References ASSERT, DbgPrint, FALSE, Index, MI_IS_SESSION_ADDRESS, MI_IS_SESSION_PTE, MiGetPdeAddress, MiGetPdeSessionIndex, MiGetPteAddress, MiGetVirtualAddressMappedByPte, MiHydra, MmSessionSpace, _MM_SESSION_SPACE::PageTables, TRUE, and _MMPTE::u.

Referenced by MiCheckPdeForPagedPool(), and MmAccessFault().

03230 : 03231 03232 This function copies the Page Table Entry for the corresponding 03233 session virtual address from the current session's data structures. 03234 03235 This allows page table pages to be lazily evaluated for session mappings. 03236 The caller must check for the current process having a session space. 03237 03238 Arguments: 03239 03240 VirtualAddress - Supplies the virtual address in question. 03241 03242 Return Value: 03243 03244 STATUS_WAIT_1 - The mapping has been made valid, retry the fault. 03245 03246 STATUS_SUCCESS - Did not handle the fault, continue further processing. 03247 03248 !STATUS_SUCCESS - An access violation has occurred - raise an exception. 03249 03250 Environment: 03251 03252 Kernel mode, DISPATCH level or below. 03253 03254 --*/ 03255 03256 { 03257 PMMPTE PointerPde; 03258 PVOID SessionVirtualAddress; 03259 ULONG Index; 03260 03261 // 03262 // Caller should have checked for this. 03263 // 03264 03265 ASSERT (MiHydra == TRUE); 03266 03267 // 03268 // First check whether the reference was to a page table page which maps 03269 // session space. If so, the PDE is retrieved from the session space 03270 // data structure and made valid. 03271 // 03272 03273 if (MI_IS_SESSION_PTE (VirtualAddress) == TRUE) { 03274 03275 // 03276 // Verify that the current process has a session space. 03277 // 03278 03279 PointerPde = MiGetPdeAddress (MmSessionSpace); 03280 03281 if (PointerPde->u.Hard.Valid == 0) { 03282 03283 #if DBG 03284 DbgPrint("MiCheckPdeForSessionSpace: No current session for PTE %p\n", 03285 VirtualAddress); 03286 03287 DbgBreakPoint(); 03288 #endif 03289 return STATUS_ACCESS_VIOLATION; 03290 } 03291 03292 SessionVirtualAddress = MiGetVirtualAddressMappedByPte ((PMMPTE) VirtualAddress); 03293 03294 PointerPde = MiGetPteAddress (VirtualAddress); 03295 03296 if (PointerPde->u.Hard.Valid == 1) { 03297 03298 // 03299 // The PDE is already valid - another thread must have 03300 // won the race. Just return. 03301 // 03302 03303 return STATUS_WAIT_1; 03304 } 03305 03306 // 03307 // Calculate the session space PDE index and load the 03308 // PDE from the session space table for this session. 03309 // 03310 03311 Index = MiGetPdeSessionIndex (SessionVirtualAddress); 03312 03313 PointerPde->u.Long = MmSessionSpace->PageTables[Index].u.Long; 03314 03315 if (PointerPde->u.Hard.Valid == 1) { 03316 KeFillEntryTb ((PHARDWARE_PTE)PointerPde, VirtualAddress, FALSE); 03317 return STATUS_WAIT_1; 03318 } 03319 03320 #if DBG 03321 DbgPrint("MiCheckPdeForSessionSpace: No Session PDE for PTE %p, %p\n", 03322 PointerPde->u.Long, SessionVirtualAddress); 03323 03324 DbgBreakPoint(); 03325 #endif 03326 return STATUS_ACCESS_VIOLATION; 03327 } 03328 03329 if (MI_IS_SESSION_ADDRESS (VirtualAddress) == FALSE) { 03330 03331 // 03332 // Not a session space fault - tell the caller to try other handlers. 03333 // 03334 03335 return STATUS_SUCCESS; 03336 } 03337 03338 // 03339 // Handle PDE faults for references in the session space. 03340 // Verify that the current process has a session space. 03341 // 03342 03343 PointerPde = MiGetPdeAddress (MmSessionSpace); 03344 03345 if (PointerPde->u.Hard.Valid == 0) { 03346 03347 #if DBG 03348 DbgPrint("MiCheckPdeForSessionSpace: No current session for VA %p\n", 03349 VirtualAddress); 03350 03351 DbgBreakPoint(); 03352 #endif 03353 return STATUS_ACCESS_VIOLATION; 03354 } 03355 03356 PointerPde = MiGetPdeAddress (VirtualAddress); 03357 03358 if (PointerPde->u.Hard.Valid == 0) { 03359 03360 // 03361 // Calculate the session space PDE index and load the 03362 // PDE from the session space table for this session. 03363 // 03364 03365 Index = MiGetPdeSessionIndex (VirtualAddress); 03366 03367 PointerPde->u.Long = MmSessionSpace->PageTables[Index].u.Long; 03368 03369 if (PointerPde->u.Hard.Valid == 1) { 03370 03371 KeFillEntryTb ((PHARDWARE_PTE)PointerPde, 03372 MiGetPteAddress(VirtualAddress), 03373 FALSE); 03374 03375 return STATUS_WAIT_1; 03376 } 03377 03378 #if DBG 03379 DbgPrint("MiCheckPdeForSessionSpace: No Session PDE for VA %p, %p\n", 03380 PointerPde->u.Long, VirtualAddress); 03381 03382 DbgBreakPoint(); 03383 #endif 03384 03385 return STATUS_ACCESS_VIOLATION; 03386 } 03387 03388 // 03389 // Tell the caller to continue with other fault handlers. 03390 // 03391 03392 return STATUS_SUCCESS; 03393 } #endif

VOID MiCheckPfn VOID   ) 
 

VOID MiCheckPte VOID   ) 
 

LOGICAL MiCheckPurgeAndUpMapCount IN PCONTROL_AREA  ControlArea  ) 
 

Definition at line 2809 of file mapview.c.

References ASSERT, _EVENT_COUNTER::Event, FALSE, KeEnterCriticalRegion, KeLeaveCriticalRegion, KernelMode, KeWaitForSingleObject(), LOCK_PFN, MiFreeEventCounter(), MiGetEventCounter(), NULL, _EVENT_COUNTER::RefCount, TRUE, UNLOCK_PFN, UNLOCK_PFN_AND_THEN_WAIT, and WrVirtualMemory.

Referenced by MiMapViewInSystemSpace(), MiMapViewOfDataSection(), MiMapViewOfImageSection(), and MiShareSessionImage().

02815 : 02816 02817 This routine synchronizes with any on going purge operations 02818 on the same segment (identified via the control area). If 02819 another purge operation is occurring, the function blocks until 02820 it is completed. 02821 02822 When this function returns the MappedView and the NumberOfUserReferences 02823 count for the control area will be incremented thereby referencing 02824 the control area. 02825 02826 Arguments: 02827 02828 ControlArea - Supplies the control area for the segment to be purged. 02829 02830 Return Value: 02831 02832 TRUE if the synchronization was successful. 02833 FALSE if the synchronization did not occur due to low resources, etc. 02834 02835 Environment: 02836 02837 Kernel Mode. 02838 02839 --*/ 02840 02841 { 02842 KIRQL OldIrql; 02843 PEVENT_COUNTER PurgedEvent; 02844 PEVENT_COUNTER WaitEvent; 02845 ULONG OldRef; 02846 02847 PurgedEvent = NULL; 02848 OldRef = 1; 02849 02850 LOCK_PFN (OldIrql); 02851 02852 while (ControlArea->u.Flags.BeingPurged != 0) { 02853 02854 // 02855 // A purge operation is in progress. 02856 // 02857 02858 if (PurgedEvent == NULL) { 02859 02860 // 02861 // Release the locks and allocate pool for the event. 02862 // 02863 02864 PurgedEvent = MiGetEventCounter (); 02865 if (PurgedEvent == NULL) { 02866 UNLOCK_PFN (OldIrql); 02867 return FALSE; 02868 } 02869 02870 continue; 02871 } 02872 02873 if (ControlArea->WaitingForDeletion == NULL) { 02874 ControlArea->WaitingForDeletion = PurgedEvent; 02875 WaitEvent = PurgedEvent; 02876 PurgedEvent = NULL; 02877 } else { 02878 WaitEvent = ControlArea->WaitingForDeletion; 02879 WaitEvent->RefCount += 1; 02880 } 02881 02882 // 02883 // Release the pfn lock and wait for the event. 02884 // 02885 02886 KeEnterCriticalRegion(); 02887 UNLOCK_PFN_AND_THEN_WAIT(OldIrql); 02888 02889 KeWaitForSingleObject(&WaitEvent->Event, 02890 WrVirtualMemory, 02891 KernelMode, 02892 FALSE, 02893 (PLARGE_INTEGER)NULL); 02894 LOCK_PFN (OldIrql); 02895 KeLeaveCriticalRegion(); 02896 MiFreeEventCounter (WaitEvent, FALSE); 02897 } 02898 02899 // 02900 // Indicate another file is mapped for the segment. 02901 // 02902 02903 ControlArea->NumberOfMappedViews += 1; 02904 ControlArea->NumberOfUserReferences += 1; 02905 ControlArea->u.Flags.HadUserReference = 1; 02906 ASSERT (ControlArea->NumberOfSectionReferences != 0); 02907 02908 if (PurgedEvent != NULL) { 02909 MiFreeEventCounter (PurgedEvent, TRUE); 02910 } 02911 UNLOCK_PFN (OldIrql); 02912 02913 return TRUE; 02914 }

NTSTATUS MiCheckSecuredVad IN PMMVAD  Vad,
IN PVOID  Base,
IN ULONG_PTR  Size,
IN ULONG  ProtectionMask
 

VOID MiCheckSessionPoolAllocations VOID   ) 
 

Definition at line 4116 of file allocpag.c.

References ASSERT, DbgPrint, else, KeBugCheckEx(), MiGetPdeAddress, MiGetVirtualAddressMappedByPte, MM_KERNEL_NOACCESS_PTE, MmSessionSpace, _MM_SESSION_SPACE::NonPagedPoolAllocations, _MM_SESSION_SPACE::NonPagedPoolBytes, PAGED_CODE, _MM_SESSION_SPACE::PagedPoolAllocations, _MM_SESSION_SPACE::PagedPoolBytes, _MM_SESSION_SPACE::PagedPoolEnd, _MM_SESSION_SPACE::PagedPoolStart, PTE_PER_PAGE, _MM_SESSION_SPACE::SessionId, and _MMPTE::u.

Referenced by MiDereferenceSession().

04122 : 04123 04124 Ensure that the current session has no pool allocations since it is about 04125 to exit. All session allocations must be freed prior to session exit. 04126 04127 Arguments: 04128 04129 None. 04130 04131 Return Value: 04132 04133 None. 04134 04135 Environment: 04136 04137 Kernel mode. 04138 04139 --*/ 04140 04141 { 04142 ULONG i; 04143 PMMPTE StartPde; 04144 PMMPTE EndPde; 04145 PMMPTE PointerPte; 04146 PVOID VirtualAddress; 04147 04148 PAGED_CODE(); 04149 04150 if (MmSessionSpace->NonPagedPoolBytes || MmSessionSpace->PagedPoolBytes) { 04151 04152 // 04153 // All page tables for this session's paged pool must be freed by now. 04154 // Being here means they aren't - this is fatal. Force in any valid 04155 // pages so that a debugger can show who the guilty party is. 04156 // 04157 04158 StartPde = MiGetPdeAddress (MmSessionSpace->PagedPoolStart); 04159 EndPde = MiGetPdeAddress (MmSessionSpace->PagedPoolEnd); 04160 04161 while (StartPde <= EndPde) { 04162 04163 if (StartPde->u.Long != 0 && StartPde->u.Long != MM_KERNEL_NOACCESS_PTE) { 04164 // 04165 // Hunt through the page table page for valid pages and force 04166 // them in. Note this also forces in the page table page if 04167 // it is not already. 04168 // 04169 04170 PointerPte = MiGetVirtualAddressMappedByPte (StartPde); 04171 04172 for (i = 0; i < PTE_PER_PAGE; i += 1) { 04173 if (PointerPte->u.Long != 0 && PointerPte->u.Long != MM_KERNEL_NOACCESS_PTE) { 04174 VirtualAddress = MiGetVirtualAddressMappedByPte (PointerPte); 04175 *(volatile BOOLEAN *)VirtualAddress = *(volatile BOOLEAN *)VirtualAddress; 04176 04177 #if DBG 04178 DbgPrint("MiCheckSessionPoolAllocations: Address %p still valid\n", 04179 VirtualAddress); 04180 #endif 04181 } 04182 PointerPte += 1; 04183 } 04184 04185 } 04186 04187 StartPde += 1; 04188 } 04189 04190 #if DBG 04191 DbgPrint ("MiCheckSessionPoolAllocations: This exiting session (ID %d) is leaking pool !\n", MmSessionSpace->SessionId); 04192 04193 DbgPrint ("This means win32k.sys, rdpdd.sys, atmfd.sys or a video/font driver is broken\n"); 04194 04195 DbgPrint ("%d nonpaged allocation leaks for %d bytes and %d paged allocation leaks for %d bytes\n", 04196 MmSessionSpace->NonPagedPoolAllocations, 04197 MmSessionSpace->NonPagedPoolBytes, 04198 MmSessionSpace->PagedPoolAllocations, 04199 MmSessionSpace->PagedPoolBytes); 04200 #endif 04201 04202 KeBugCheckEx (SESSION_HAS_VALID_POOL_ON_EXIT, 04203 (ULONG_PTR)MmSessionSpace->SessionId, 04204 MmSessionSpace->PagedPoolBytes, 04205 MmSessionSpace->NonPagedPoolBytes, 04206 #if defined (_WIN64) 04207 (MmSessionSpace->NonPagedPoolAllocations << 32) | 04208 (MmSessionSpace->PagedPoolAllocations) 04209 #else 04210 (MmSessionSpace->NonPagedPoolAllocations << 16) | 04211 (MmSessionSpace->PagedPoolAllocations) 04212 #endif 04213 ); 04214 } 04215 04216 ASSERT (MmSessionSpace->NonPagedPoolAllocations == 0); 04217 ASSERT (MmSessionSpace->PagedPoolAllocations == 0); 04218 }

PMMPTE MiCheckVirtualAddress IN PVOID  VirtualAddress,
OUT PULONG  ProtectCode
 

Definition at line 2880 of file pagfault.c.

References _IMAGE_ENTRY_IN_SESSION::Address, ASSERT, DISPATCH_LEVEL, _MMVAD::FirstPrototypePte, _MM_SESSION_SPACE::ImageList, KeFlushEntireTb(), KeLowerIrql(), KeRaiseIrql(), _IMAGE_ENTRY_IN_SESSION::LastAddress, MI_GET_PROTECTION_FROM_VAD, MI_IS_PAGE_TABLE_ADDRESS, MI_IS_SESSION_ADDRESS, MI_VA_TO_VPN, MiGetProtoPteAddress, MiGetPteAddress, MiHandleBankedSection(), MiLocateAddress(), MM_EXECUTE_WRITECOPY, MM_LARGE_PAGES, MM_NOACCESS, MM_PAGED_POOL_START, MM_READONLY, MM_READWRITE, MM_SESSION_SPACE_WS_LOCK_ASSERT, MM_UNKNOWN_PROTECTION, MmPagedPoolInfo, MmSessionSpace, MmSharedUserDataPte, NULL, PAGE_ALIGN, PAGE_SHIFT, _IMAGE_ENTRY_IN_SESSION::PrototypePtes, _MMVAD::StartingVpn, TRUE, _MMVAD::u, _SUBSECTION::u, _MMPTE::u, _MMVAD::u2, _MMVAD::u4, and ZeroPte.

Referenced by MiFindActualFaultingPte(), MiWaitForInPageComplete(), and MmAccessFault().

02887 : 02888 02889 This function examines the virtual address descriptors to see 02890 if the specified virtual address is contained within any of 02891 the descriptors. If a virtual address descriptor is found 02892 which contains the specified virtual address, a PTE is built 02893 from information within the virtual address descriptor and 02894 returned to the caller. 02895 02896 Arguments: 02897 02898 VirtualAddress - Supplies the virtual address to locate within 02899 a virtual address descriptor. 02900 02901 Return Value: 02902 02903 Returns the PTE which corresponds to the supplied virtual address. 02904 If no virtual address descriptor is found, a zero pte is returned. 02905 02906 Environment: 02907 02908 Kernel mode, APCs disabled, working set mutex held. 02909 02910 --*/ 02911 02912 { 02913 PMMVAD Vad; 02914 PMMPTE PointerPte; 02915 PLIST_ENTRY NextEntry; 02916 PIMAGE_ENTRY_IN_SESSION Image; 02917 02918 if (VirtualAddress <= MM_HIGHEST_USER_ADDRESS) { 02919 02920 #if defined(MM_SHARED_USER_DATA_VA) 02921 02922 if (PAGE_ALIGN(VirtualAddress) == (PVOID) MM_SHARED_USER_DATA_VA) { 02923 02924 // 02925 // This is the page that is double mapped between 02926 // user mode and kernel mode. Map in as read only. 02927 // On MIPS this is hardwired in the TB. 02928 // 02929 02930 *ProtectCode = MM_READONLY; 02931 return &MmSharedUserDataPte; 02932 } 02933 02934 #endif 02935 02936 Vad = MiLocateAddress (VirtualAddress); 02937 if (Vad == (PMMVAD)NULL) { 02938 02939 *ProtectCode = MM_NOACCESS; 02940 return NULL; 02941 } 02942 02943 // 02944 // A virtual address descriptor which contains the virtual address 02945 // has been located. Build the PTE from the information within 02946 // the virtual address descriptor. 02947 // 02948 02949 #ifdef LARGE_PAGES 02950 02951 if (Vad->u.VadFlags.LargePages == 1) { 02952 02953 KIRQL OldIrql; 02954 PSUBSECTION Subsection; 02955 02956 // 02957 // The first prototype PTE points to the subsection for the 02958 // large page mapping. 02959 02960 Subsection = (PSUBSECTION)Vad->FirstPrototypePte; 02961 02962 ASSERT (Subsection->u.SubsectionFlags.LargePages == 1); 02963 02964 KeRaiseIrql (DISPATCH_LEVEL, &OldIrql); 02965 KeFlushEntireTb (TRUE, TRUE); 02966 KeFillLargeEntryTb ((PHARDWARE_PTE)(Subsection + 1), 02967 VirtualAddress, 02968 Subsection->StartingSector); 02969 02970 KeLowerIrql (OldIrql); 02971 *ProtectCode = MM_LARGE_PAGES; 02972 return NULL; 02973 } 02974 #endif //LARGE_PAGES 02975 02976 if (Vad->u.VadFlags.PhysicalMapping == 1) { 02977 02978 // 02979 // This is a banked section. 02980 // 02981 02982 MiHandleBankedSection (VirtualAddress, Vad); 02983 *ProtectCode = MM_NOACCESS; 02984 return NULL; 02985 } 02986 02987 if (Vad->u.VadFlags.PrivateMemory == 1) { 02988 02989 // 02990 // This is a private region of memory. Check to make 02991 // sure the virtual address has been committed. Note that 02992 // addresses are dense from the bottom up. 02993 // 02994 02995 if (Vad->u.VadFlags.UserPhysicalPages == 1) { 02996 02997 // 02998 // These mappings only fault if the access is bad. 02999 // 03000 03001 ASSERT (MiGetPteAddress(VirtualAddress)->u.Long == ZeroPte.u.Long); 03002 *ProtectCode = MM_NOACCESS; 03003 return NULL; 03004 } 03005 03006 if (Vad->u.VadFlags.MemCommit == 1) { 03007 *ProtectCode = MI_GET_PROTECTION_FROM_VAD(Vad); 03008 return NULL; 03009 } 03010 03011 // 03012 // The address is reserved but not committed. 03013 // 03014 03015 *ProtectCode = MM_NOACCESS; 03016 return NULL; 03017 03018 } else { 03019 03020 // 03021 // This virtual address descriptor refers to a 03022 // section, calculate the address of the prototype PTE 03023 // and construct a pointer to the PTE. 03024 // 03025 //******************************************************* 03026 //******************************************************* 03027 // well here's an interesting problem, how do we know 03028 // how to set the attributes on the PTE we are creating 03029 // when we can't look at the prototype PTE without 03030 // potentially incurring a page fault. In this case 03031 // PteTemplate would be zero. 03032 //******************************************************* 03033 //******************************************************* 03034 // 03035 03036 if (Vad->u.VadFlags.ImageMap == 1) { 03037 03038 // 03039 // PTE and proto PTEs have the same protection for images. 03040 // 03041 03042 *ProtectCode = MM_UNKNOWN_PROTECTION; 03043 } else { 03044 *ProtectCode = MI_GET_PROTECTION_FROM_VAD(Vad); 03045 } 03046 PointerPte = (PMMPTE)MiGetProtoPteAddress(Vad, 03047 MI_VA_TO_VPN (VirtualAddress)); 03048 if (PointerPte == NULL) { 03049 *ProtectCode = MM_NOACCESS; 03050 } 03051 if (Vad->u2.VadFlags2.ExtendableFile) { 03052 03053 // 03054 // Make sure the data has been committed. 03055 // 03056 03057 if ((MI_VA_TO_VPN (VirtualAddress) - Vad->StartingVpn) > 03058 (ULONG_PTR)((Vad->u4.ExtendedInfo->CommittedSize - 1) 03059 >> PAGE_SHIFT)) { 03060 *ProtectCode = MM_NOACCESS; 03061 } 03062 } 03063 return PointerPte; 03064 } 03065 03066 } else if (MI_IS_PAGE_TABLE_ADDRESS(VirtualAddress)) { 03067 03068 // 03069 // The virtual address is within the space occupied by PDEs, 03070 // make the PDE valid. 03071 // 03072 03073 if (((PMMPTE)VirtualAddress >= MiGetPteAddress (MM_PAGED_POOL_START)) && 03074 ((PMMPTE)VirtualAddress <= MmPagedPoolInfo.LastPteForPagedPool)) { 03075 03076 *ProtectCode = MM_NOACCESS; 03077 return NULL; 03078 } 03079 03080 *ProtectCode = MM_READWRITE; 03081 return NULL; 03082 } 03083 else if (MI_IS_SESSION_ADDRESS (VirtualAddress) == TRUE) { 03084 03085 // 03086 // See if the session space address is copy on write. 03087 // 03088 03089 MM_SESSION_SPACE_WS_LOCK_ASSERT (); 03090 03091 PointerPte = NULL; 03092 *ProtectCode = MM_NOACCESS; 03093 03094 NextEntry = MmSessionSpace->ImageList.Flink; 03095 03096 while (NextEntry != &MmSessionSpace->ImageList) { 03097 03098 Image = CONTAINING_RECORD(NextEntry, IMAGE_ENTRY_IN_SESSION, Link); 03099 03100 if ((VirtualAddress >= Image->Address) && (VirtualAddress <= Image->LastAddress)) { 03101 PointerPte = Image->PrototypePtes + 03102 (((PCHAR)VirtualAddress - (PCHAR)Image->Address) >> PAGE_SHIFT); 03103 *ProtectCode = MM_EXECUTE_WRITECOPY; 03104 break; 03105 } 03106 03107 NextEntry = NextEntry->Flink; 03108 } 03109 03110 return PointerPte; 03111 } 03112 03113 // 03114 // Address is in system space. 03115 // 03116 03117 *ProtectCode = MM_NOACCESS; 03118 return NULL; 03119 }

VOID MiCleanPhysicalProcessPages IN PEPROCESS  Process  ) 
 

Definition at line 2313 of file physical.c.

References APC_LEVEL, ASSERT, BitMap, COPY_STACK_SIZE, ExFreePool(), LOWEST_USABLE_PHYSICAL_PAGE, MI_BITMAP_INDEX_TO_FRAME, MI_PFN_ELEMENT, MI_PFN_IS_AWE, MI_SET_PFN_DELETED, MiUpdateVadPhysicalPages(), MmFreePagesFromMdl(), MmHighestPossiblePhysicalPage, MmInitializeMdl, NonPagedPool, NULL, PAGE_SHIFT, PsReturnPoolQuota(), _MMPFN::PteAddress, RtlFindSetBits(), TRUE, and _MMPFN::u2.

Referenced by MmCleanProcessAddressSpace().

02319 : 02320 02321 This routine frees the VadPhysicalBitMap, any remaining physical pages (as 02322 they may not have been currently mapped into any Vads) and returns the 02323 bitmap quota. 02324 02325 Arguments: 02326 02327 Process - Supplies the process to clean. 02328 02329 Return Value: 02330 02331 None. 02332 02333 Environment: 02334 02335 Kernel mode, APC level, working set mutex held. Called only on process 02336 exit, so the AWE lock is not needed here. 02337 02338 --*/ 02339 02340 { 02341 PMMPFN Pfn1; 02342 ULONG BitMapSize; 02343 ULONG BitMapIndex; 02344 ULONG BitMapHint; 02345 PRTL_BITMAP BitMap; 02346 PPFN_NUMBER MdlPage; 02347 PFN_NUMBER MdlHack[(sizeof(MDL) / sizeof(PFN_NUMBER)) + COPY_STACK_SIZE]; 02348 ULONG_PTR MdlPages; 02349 ULONG_PTR NumberOfPages; 02350 ULONG_PTR TotalFreedPages; 02351 PMDL MemoryDescriptorList; 02352 PFN_NUMBER PageFrameIndex; 02353 #if DBG 02354 ULONG_PTR ActualPages = 0; 02355 ULONG_PTR ExpectedPages = 0; 02356 #endif 02357 02358 ASSERT (KeGetCurrentIrql() == APC_LEVEL); 02359 02360 #if DBG 02361 ExpectedPages = Process->VadPhysicalPages; 02362 #else 02363 if (Process->VadPhysicalPages == 0) { 02364 return; 02365 } 02366 #endif 02367 02368 TotalFreedPages = 0; 02369 BitMap = Process->VadPhysicalPagesBitMap; 02370 02371 if (BitMap != NULL) { 02372 02373 MdlPages = COPY_STACK_SIZE; 02374 MemoryDescriptorList = (PMDL)&MdlHack[0]; 02375 02376 MdlPage = (PPFN_NUMBER)(MemoryDescriptorList + 1); 02377 NumberOfPages = 0; 02378 02379 BitMapHint = 0; 02380 02381 while (TRUE) { 02382 02383 BitMapIndex = RtlFindSetBits (BitMap, 1, BitMapHint); 02384 02385 if (BitMapIndex < BitMapHint) { 02386 break; 02387 } 02388 02389 if (BitMapIndex == 0xFFFFFFFF) { 02390 break; 02391 } 02392 02393 PageFrameIndex = MI_BITMAP_INDEX_TO_FRAME(BitMapIndex); 02394 02395 #if defined (_WIN64) 02396 02397 // 02398 // This may become a problem for 64-bit systems with > 32tb 02399 // of physical memory as the 3rd parameter to RtlFindSetBits is 02400 // a ULONG. 02401 // 02402 02403 ASSERT (PageFrameIndex < 0x100000000); 02404 #endif 02405 02406 // 02407 // The bitmap search wraps, so handle it here. 02408 // Note PFN 0 is illegal. 02409 // 02410 02411 ASSERT (PageFrameIndex != 0); 02412 ASSERT (PageFrameIndex >= LOWEST_USABLE_PHYSICAL_PAGE); 02413 02414 ASSERT (ExpectedPages != 0); 02415 Pfn1 = MI_PFN_ELEMENT(PageFrameIndex); 02416 ASSERT (Pfn1->u2.ShareCount == 1); 02417 ASSERT (Pfn1->PteAddress == (PMMPTE)0); 02418 02419 ASSERT (MI_PFN_IS_AWE (Pfn1)); 02420 02421 MI_SET_PFN_DELETED(Pfn1); 02422 02423 *MdlPage = PageFrameIndex; 02424 MdlPage += 1; 02425 NumberOfPages += 1; 02426 #if DBG 02427 ActualPages += 1; 02428 #endif 02429 02430 if (NumberOfPages == COPY_STACK_SIZE) { 02431 02432 // 02433 // Free the pages in the full MDL. 02434 // 02435 02436 MmInitializeMdl (MemoryDescriptorList, 02437 0, 02438 NumberOfPages << PAGE_SHIFT); 02439 02440 MmFreePagesFromMdl (MemoryDescriptorList); 02441 02442 MdlPage = (PPFN_NUMBER)(MemoryDescriptorList + 1); 02443 Process->VadPhysicalPages -= NumberOfPages; 02444 TotalFreedPages += NumberOfPages; 02445 NumberOfPages = 0; 02446 } 02447 02448 BitMapHint = BitMapIndex + 1; 02449 if (BitMapHint >= BitMap->SizeOfBitMap) { 02450 break; 02451 } 02452 } 02453 02454 // 02455 // Free any straggling MDL pages here. 02456 // 02457 02458 if (NumberOfPages != 0) { 02459 MmInitializeMdl (MemoryDescriptorList, 02460 0, 02461 NumberOfPages << PAGE_SHIFT); 02462 02463 MmFreePagesFromMdl (MemoryDescriptorList); 02464 Process->VadPhysicalPages -= NumberOfPages; 02465 TotalFreedPages += NumberOfPages; 02466 } 02467 02468 ASSERT (ExpectedPages == ActualPages); 02469 02470 BitMapSize = sizeof(RTL_BITMAP) + (ULONG)((((MmHighestPossiblePhysicalPage + 1) + 31) / 32) * 4); 02471 02472 Process->VadPhysicalPagesBitMap = NULL; 02473 ExFreePool (BitMap); 02474 PsReturnPoolQuota (Process, NonPagedPool, BitMapSize); 02475 } 02476 02477 ASSERT (ExpectedPages == ActualPages); 02478 ASSERT (Process->VadPhysicalPages == 0); 02479 02480 if (TotalFreedPages != 0) { 02481 MiUpdateVadPhysicalPages (TotalFreedPages); 02482 } 02483 02484 return; 02485 }

VOID MiCleanSection IN PCONTROL_AREA  ControlArea,
IN LOGICAL  DirtyDataPagesOk
 

Definition at line 1075 of file sectsup.c.

References ASSERT, _MDL::ByteCount, _SUBSECTION::ControlArea, DbgPrint, FALSE, FreePageList, IoSynchronousPageWrite(), IS_PTE_NOT_DEMAND_ZERO, KeBugCheckEx(), KeClearEvent, KeDelayExecutionThread(), KeEnterCriticalRegion, KeInitializeEvent, KeLeaveCriticalRegion, KernelMode, KeWaitForSingleObject(), LOCK_PFN, _MDL::MappedSystemVa, MDL_MAPPED_TO_SYSTEM_VA, MDL_PAGES_LOCKED, _MDL::MdlFlags, MI_ADD_LOCKED_PAGE_CHARGE_FOR_MODIFIED_PAGE, MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE, MI_INITIALIZE_ZERO_MDL, MI_IS_PFN_DELETED, MI_PFN_ELEMENT, MI_REMOVE_LOCKED_PAGE_CHARGE, MI_SET_PFN_DELETED, MiCheckProtoPtePageState(), MiDecrementReferenceCount(), MiDecrementShareCount(), MiEndingOffset(), MiGetSubsectionAddress, MiHydra, MiInsertPageInList(), MiIsPteOnPdeBoundary, MiMakeSystemAddressValidPfn(), MiReleasePageFileSpace(), MiRemoveImageSectionObject(), MiSegmentDelete(), MiStartingOffset(), MiUnlinkPageFromList(), MM_DBG_FLUSH_SECTION, MM_MAXIMUM_WRITE_CLUSTER, MmMappedFileIoComplete, MmModifiedWriteClusterSize, MmPageLocationList, MmShortTime, MmUnmapLockedPages(), _SUBSECTION::NextSubsection, NT_SUCCESS, NTSTATUS(), NULL, _MMPFN::OriginalPte, PAGE_SHIFT, PAGE_SIZE, _MMPFN::PteAddress, _MMPFN::PteFrame, _SUBSECTION::PtesInSubsection, _MDL::Size, _MDL::StartVa, Status, _SUBSECTION::SubsectionBase, TRUE, _MMPTE::u, _CONTROL_AREA::u, _MMPFN::u3, UNLOCK_PFN, UNLOCK_PFN_AND_THEN_WAIT, and WrPageOut.

Referenced by MiCheckControlArea(), MiRemoveUnusedSegments(), MmFlushImageSection(), and MmForceSectionClosed().

01082 : 01083 01084 This function examines each prototype PTE in the section and 01085 takes the appropriate action to "delete" the prototype PTE. 01086 01087 If the PTE is dirty and is backed by a file (not a paging file), 01088 the corresponding page is written to the file. 01089 01090 At the completion of this service, the section which was 01091 operated upon is no longer usable. 01092 01093 NOTE - ALL I/O ERRORS ARE IGNORED. IF ANY WRITES FAIL, THE 01094 DIRTY PAGES ARE MARKED CLEAN AND THE SECTION IS DELETED. 01095 01096 Arguments: 01097 01098 ControlArea - Supplies a pointer to the control area for the section. 01099 01100 DirtyDataPagesOk - Supplies TRUE if dirty data pages are ok. If FALSE 01101 is specified then no dirty data pages are expected (as 01102 this is a dereference operation) so any encountered 01103 must be due to pool corruption so bugcheck. 01104 01105 Note that dirty image pages are always discarded. 01106 This should only happen for images that were either 01107 read in from floppies or images with shared global 01108 subsections. 01109 01110 Return Value: 01111 01112 None. 01113 01114 --*/ 01115 01116 { 01117 PMMPTE PointerPte; 01118 PMMPTE LastPte; 01119 PMMPTE LastWritten; 01120 MMPTE PteContents; 01121 PMMPFN Pfn1; 01122 PMMPFN Pfn2; 01123 PMMPTE WrittenPte; 01124 MMPTE WrittenContents; 01125 KIRQL OldIrql; 01126 PMDL Mdl; 01127 PSUBSECTION Subsection; 01128 PPFN_NUMBER Page; 01129 PPFN_NUMBER LastPage; 01130 LARGE_INTEGER StartingOffset; 01131 LARGE_INTEGER TempOffset; 01132 NTSTATUS Status; 01133 IO_STATUS_BLOCK IoStatus; 01134 ULONG WriteNow; 01135 ULONG ImageSection; 01136 ULONG DelayCount; 01137 ULONG First; 01138 KEVENT IoEvent; 01139 PFN_NUMBER MdlHack[(sizeof(MDL)/sizeof(PFN_NUMBER)) + MM_MAXIMUM_WRITE_CLUSTER]; 01140 01141 WriteNow = FALSE; 01142 ImageSection = FALSE; 01143 DelayCount = 0; 01144 01145 if (ControlArea->u.Flags.Image) { 01146 ImageSection = TRUE; 01147 } 01148 ASSERT (ControlArea->FilePointer); 01149 01150 PointerPte = ControlArea->Segment->PrototypePte; 01151 LastPte = PointerPte + ControlArea->Segment->NonExtendedPtes; 01152 01153 Mdl = (PMDL)&MdlHack; 01154 01155 KeInitializeEvent (&IoEvent, NotificationEvent, FALSE); 01156 01157 LastWritten = NULL; 01158 ASSERT (MmModifiedWriteClusterSize == MM_MAXIMUM_WRITE_CLUSTER); 01159 LastPage = NULL; 01160 01161 if (ControlArea->u.Flags.GlobalOnlyPerSession == 0) { 01162 Subsection = (PSUBSECTION)(ControlArea + 1); 01163 } 01164 else { 01165 Subsection = (PSUBSECTION)((PLARGE_CONTROL_AREA)ControlArea + 1); 01166 } 01167 01168 // 01169 // The PFN lock is required for deallocating pages from a paging 01170 // file and for deleting transition PTEs. 01171 // 01172 01173 LOCK_PFN (OldIrql); 01174 01175 // 01176 // Stop the modified page writer from writing pages to this 01177 // file, and if any paging I/O is in progress, wait for it 01178 // to complete. 01179 // 01180 01181 ControlArea->u.Flags.NoModifiedWriting = 1; 01182 01183 while (ControlArea->ModifiedWriteCount != 0) { 01184 01185 // 01186 // There is modified page writing in progess. Set the 01187 // flag in the control area indicating the modified page 01188 // writer should signal when a write to this control area 01189 // is complete. Release the PFN LOCK and wait in an 01190 // atomic operation. Once the wait is satisfied, recheck 01191 // to make sure it was this file's I/O that was written. 01192 // 01193 01194 ControlArea->u.Flags.SetMappedFileIoComplete = 1; 01195 KeEnterCriticalRegion(); 01196 UNLOCK_PFN_AND_THEN_WAIT(OldIrql); 01197 01198 KeWaitForSingleObject(&MmMappedFileIoComplete, 01199 WrPageOut, 01200 KernelMode, 01201 FALSE, 01202 (PLARGE_INTEGER)NULL); 01203 LOCK_PFN (OldIrql); 01204 KeLeaveCriticalRegion(); 01205 } 01206 01207 for (;;) { 01208 01209 First = TRUE; 01210 while (PointerPte < LastPte) { 01211 01212 if ((MiIsPteOnPdeBoundary(PointerPte)) || (First)) { 01213 01214 First = FALSE; 01215 01216 if ((ImageSection) || 01217 (MiCheckProtoPtePageState(PointerPte, FALSE))) { 01218 MiMakeSystemAddressValidPfn (PointerPte); 01219 } else { 01220 01221 // 01222 // Paged pool page is not resident, hence no transition or 01223 // valid prototype PTEs can be present in it. Skip it. 01224 // 01225 01226 PointerPte = (PMMPTE)((((ULONG_PTR)PointerPte | PAGE_SIZE - 1)) + 1); 01227 if (LastWritten != NULL) { 01228 WriteNow = TRUE; 01229 } 01230 goto WriteItOut; 01231 } 01232 } 01233 01234 PteContents = *PointerPte; 01235 01236 // 01237 // Prototype PTEs for Segments backed by paging file 01238 // are either in demand zero, page file format, or transition. 01239 // 01240 01241 if (PteContents.u.Hard.Valid == 1) { 01242 KeBugCheckEx (POOL_CORRUPTION_IN_FILE_AREA, 01243 0x0, 01244 (ULONG_PTR)ControlArea, 01245 (ULONG_PTR)PointerPte, 01246 (ULONG_PTR)PteContents.u.Long); 01247 } 01248 01249 if (PteContents.u.Soft.Prototype == 1) { 01250 01251 // 01252 // This is a normal prototype PTE in mapped file format. 01253 // 01254 01255 if (LastWritten != NULL) { 01256 WriteNow = TRUE; 01257 } 01258 } 01259 else if (PteContents.u.Soft.Transition == 1) { 01260 01261 // 01262 // Prototype PTE in transition, there are 3 possible cases: 01263 // 1. The page is part of an image which is sharable and 01264 // refers to the paging file - dereference page file 01265 // space and free the physical page. 01266 // 2. The page refers to the segment but is not modified - 01267 // free the physical page. 01268 // 3. The page refers to the segment and is modified - 01269 // write the page to the file and free the physical page. 01270 // 01271 01272 Pfn1 = MI_PFN_ELEMENT (PteContents.u.Trans.PageFrameNumber); 01273 01274 if (Pfn1->u3.e2.ReferenceCount != 0) { 01275 if (DelayCount < 20) { 01276 01277 // 01278 // There must be an I/O in progress on this 01279 // page. Wait for the I/O operation to complete. 01280 // 01281 01282 UNLOCK_PFN (OldIrql); 01283 01284 KeDelayExecutionThread (KernelMode, FALSE, (PLARGE_INTEGER)&MmShortTime); 01285 01286 DelayCount += 1; 01287 01288 // 01289 // Redo the loop, if the delay count is greater than 01290 // 20, assume that this thread is deadlocked and 01291 // don't purge this page. The file system can deal 01292 // with the write operation in progress. 01293 // 01294 01295 LOCK_PFN (OldIrql); 01296 MiMakeSystemAddressValidPfn (PointerPte); 01297 continue; 01298 } 01299 #if DBG 01300 // 01301 // The I/O still has not completed, just ignore 01302 // the fact that the I/O is in progress and 01303 // delete the page. 01304 // 01305 01306 KdPrint(("MM:CLEAN - page number %lx has i/o outstanding\n", 01307 PteContents.u.Trans.PageFrameNumber)); 01308 #endif 01309 } 01310 01311 if (Pfn1->OriginalPte.u.Soft.Prototype == 0) { 01312 01313 // 01314 // Paging file reference (case 1). 01315 // 01316 01317 MI_SET_PFN_DELETED (Pfn1); 01318 01319 if (!ImageSection) { 01320 01321 // 01322 // This is not an image section, it must be a 01323 // page file backed section, therefore decrement 01324 // the PFN reference count for the control area. 01325 // 01326 01327 ControlArea->NumberOfPfnReferences -= 1; 01328 ASSERT ((LONG)ControlArea->NumberOfPfnReferences >= 0); 01329 } 01330 #if DBG 01331 else { 01332 // 01333 // This should only happen for images with shared 01334 // global subsections. 01335 // 01336 } 01337 #endif 01338 01339 MiDecrementShareCount (Pfn1->PteFrame); 01340 01341 // 01342 // Check the reference count for the page, if the // reference count is zero and the page is not on the 01343 // freelist, move the page to the free list, if the 01344 // reference count is not zero, ignore this page. When 01345 // the reference count goes to zero, it will be placed 01346 // on the free list. 01347 // 01348 01349 if ((Pfn1->u3.e2.ReferenceCount == 0) && 01350 (Pfn1->u3.e1.PageLocation != FreePageList)) { 01351 01352 MiUnlinkPageFromList (Pfn1); 01353 MiReleasePageFileSpace (Pfn1->OriginalPte); 01354 MiInsertPageInList (MmPageLocationList[FreePageList], 01355 MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE (&PteContents)); 01356 01357 } 01358 PointerPte->u.Long = 0; 01359 01360 // 01361 // If a cluster of pages to write has been completed, 01362 // set the WriteNow flag. 01363 // 01364 01365 if (LastWritten != NULL) { 01366 WriteNow = TRUE; 01367 } 01368 01369 } else { 01370 01371 if ((Pfn1->u3.e1.Modified == 0) || (ImageSection)) { 01372 01373 // 01374 // Non modified or image file page (case 2). 01375 // 01376 01377 MI_SET_PFN_DELETED (Pfn1); 01378 ControlArea->NumberOfPfnReferences -= 1; 01379 ASSERT ((LONG)ControlArea->NumberOfPfnReferences >= 0); 01380 01381 MiDecrementShareCount (Pfn1->PteFrame); 01382 01383 // 01384 // Check the reference count for the page, if the 01385 // reference count is zero and the page is not on 01386 // the freelist, move the page to the free list, 01387 // if the reference count is not zero, ignore this 01388 // page. When the reference count goes to zero, it 01389 // will be placed on the free list. 01390 // 01391 01392 if ((Pfn1->u3.e2.ReferenceCount == 0) && 01393 (Pfn1->u3.e1.PageLocation != FreePageList)) { 01394 01395 MiUnlinkPageFromList (Pfn1); 01396 MiReleasePageFileSpace (Pfn1->OriginalPte); 01397 MiInsertPageInList (MmPageLocationList[FreePageList], 01398 MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE (&PteContents)); 01399 } 01400 01401 PointerPte->u.Long = 0; 01402 01403 // 01404 // If a cluster of pages to write has been 01405 // completed, set the WriteNow flag. 01406 // 01407 01408 if (LastWritten != NULL) { 01409 WriteNow = TRUE; 01410 } 01411 01412 } else { 01413 01414 // 01415 // Modified page backed by the file (case 3). 01416 // Check to see if this is the first page of a 01417 // cluster. 01418 // 01419 01420 if (LastWritten == NULL) { 01421 LastPage = (PPFN_NUMBER)(Mdl + 1); 01422 ASSERT (MiGetSubsectionAddress(&Pfn1->OriginalPte) == 01423 Subsection); 01424 01425 // 01426 // Calculate the offset to read into the file. 01427 // offset = base + ((thispte - basepte) << PAGE_SHIFT) 01428 // 01429 01430 ASSERT (Subsection->ControlArea->u.Flags.Image == 0); 01431 StartingOffset.QuadPart = MiStartingOffset( 01432 Subsection, 01433 Pfn1->PteAddress); 01434 01435 MI_INITIALIZE_ZERO_MDL (Mdl); 01436 Mdl->MdlFlags |= MDL_PAGES_LOCKED; 01437 01438 Mdl->StartVa = 01439 (PVOID)ULongToPtr(Pfn1->u3.e1.PageColor << PAGE_SHIFT); 01440 Mdl->Size = (CSHORT)(sizeof(MDL) + 01441 (sizeof(PFN_NUMBER) * MmModifiedWriteClusterSize)); 01442 } 01443 01444 LastWritten = PointerPte; 01445 Mdl->ByteCount += PAGE_SIZE; 01446 01447 // 01448 // If the cluster is now full, 01449 // set the write now flag. 01450 // 01451 01452 if (Mdl->ByteCount == (PAGE_SIZE * MmModifiedWriteClusterSize)) { 01453 WriteNow = TRUE; 01454 } 01455 01456 MiUnlinkPageFromList (Pfn1); 01457 Pfn1->u3.e1.Modified = 0; 01458 01459 // 01460 // Up the reference count for the physical page as 01461 // there is I/O in progress. 01462 // 01463 01464 MI_ADD_LOCKED_PAGE_CHARGE_FOR_MODIFIED_PAGE(Pfn1, 22); 01465 Pfn1->u3.e2.ReferenceCount += 1; 01466 01467 // 01468 // Clear the modified bit for the page and set the 01469 // write in progress bit. 01470 // 01471 01472 *LastPage = MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE (&PteContents); 01473 01474 LastPage += 1; 01475 } 01476 } 01477 } else { 01478 01479 if (IS_PTE_NOT_DEMAND_ZERO (PteContents)) { 01480 MiReleasePageFileSpace (PteContents); 01481 } 01482 PointerPte->u.Long = 0; 01483 01484 // 01485 // If a cluster of pages to write has been completed, 01486 // set the WriteNow flag. 01487 // 01488 01489 if (LastWritten != NULL) { 01490 WriteNow = TRUE; 01491 } 01492 } 01493 01494 // 01495 // Write the current cluster if it is complete, 01496 // full, or the loop is now complete. 01497 // 01498 01499 PointerPte += 1; 01500 WriteItOut: 01501 DelayCount = 0; 01502 01503 if ((WriteNow) || 01504 ((PointerPte == LastPte) && (LastWritten != NULL))) { 01505 01506 // 01507 // Issue the write request. 01508 // 01509 01510 UNLOCK_PFN (OldIrql); 01511 01512 if (DirtyDataPagesOk == FALSE) { 01513 KeBugCheckEx (POOL_CORRUPTION_IN_FILE_AREA, 01514 0x1, 01515 (ULONG_PTR)ControlArea, 01516 (ULONG_PTR)Mdl, 01517 (ULONG_PTR)0); 01518 } 01519 01520 WriteNow = FALSE; 01521 01522 KeClearEvent (&IoEvent); 01523 01524 // 01525 // Make sure the write does not go past the 01526 // end of file. (segment size). 01527 // 01528 01529 ASSERT (Subsection->ControlArea->u.Flags.Image == 0); 01530 01531 TempOffset = MiEndingOffset(Subsection); 01532 01533 if (((UINT64)StartingOffset.QuadPart + Mdl->ByteCount) > 01534 (UINT64)TempOffset.QuadPart) { 01535 01536 ASSERT ((ULONG)(TempOffset.QuadPart - 01537 StartingOffset.QuadPart) > 01538 (Mdl->ByteCount - PAGE_SIZE)); 01539 01540 Mdl->ByteCount = (ULONG)(TempOffset.QuadPart - 01541 StartingOffset.QuadPart); 01542 } 01543 01544 #if DBG 01545 if (MmDebug & MM_DBG_FLUSH_SECTION) { 01546 DbgPrint("MM:flush page write begun %lx\n", 01547 Mdl->ByteCount); 01548 } 01549 #endif //DBG 01550 01551 Status = IoSynchronousPageWrite (ControlArea->FilePointer, 01552 Mdl, 01553 &StartingOffset, 01554 &IoEvent, 01555 &IoStatus ); 01556 01557 if (NT_SUCCESS(Status)) { 01558 01559 KeWaitForSingleObject (&IoEvent, 01560 WrPageOut, 01561 KernelMode, 01562 FALSE, 01563 (PLARGE_INTEGER)NULL); 01564 } 01565 01566 if (Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA) { 01567 MmUnmapLockedPages (Mdl->MappedSystemVa, Mdl); 01568 } 01569 01570 Page = (PPFN_NUMBER)(Mdl + 1); 01571 01572 LOCK_PFN (OldIrql); 01573 01574 if (MiIsPteOnPdeBoundary(PointerPte) == 0) { 01575 01576 // 01577 // The next PTE is not in a different page, make 01578 // sure this page did not leave memory when the 01579 // I/O was in progress. 01580 // 01581 01582 MiMakeSystemAddressValidPfn (PointerPte); 01583 } 01584 01585 // 01586 // I/O complete unlock pages. 01587 // 01588 // NOTE that the error status is ignored. 01589 // 01590 01591 while (Page < LastPage) { 01592 01593 Pfn2 = MI_PFN_ELEMENT (*Page); 01594 01595 // 01596 // Make sure the page is still transition. 01597 // 01598 01599 WrittenPte = Pfn2->PteAddress; 01600 01601 MI_REMOVE_LOCKED_PAGE_CHARGE (Pfn2, 23); 01602 MiDecrementReferenceCount (*Page); 01603 01604 if (!MI_IS_PFN_DELETED (Pfn2)) { 01605 01606 // 01607 // Make sure the prototype PTE is 01608 // still in the working set. 01609 // 01610 01611 MiMakeSystemAddressValidPfn (WrittenPte); 01612 01613 if (Pfn2->PteAddress != WrittenPte) { 01614 01615 // 01616 // The PFN lock was released to make the 01617 // page table page valid, and while it 01618 // was released, the physical page 01619 // was reused. Go onto the next one. 01620 // 01621 01622 Page += 1; 01623 continue; 01624 } 01625 01626 WrittenContents = *WrittenPte; 01627 01628 if ((WrittenContents.u.Soft.Prototype == 0) && 01629 (WrittenContents.u.Soft.Transition == 1)) { 01630 01631 MI_SET_PFN_DELETED (Pfn2); 01632 ControlArea->NumberOfPfnReferences -= 1; 01633 ASSERT ((LONG)ControlArea->NumberOfPfnReferences >= 0); 01634 01635 MiDecrementShareCount (Pfn2->PteFrame); 01636 01637 // 01638 // Check the reference count for the page, 01639 // if the reference count is zero and the 01640 // page is not on the freelist, move the page 01641 // to the free list, if the reference 01642 // count is not zero, ignore this page. 01643 // When the reference count goes to zero, 01644 // it will be placed on the free list. 01645 // 01646 01647 if ((Pfn2->u3.e2.ReferenceCount == 0) && 01648 (Pfn2->u3.e1.PageLocation != FreePageList)) { 01649 01650 MiUnlinkPageFromList (Pfn2); 01651 MiReleasePageFileSpace (Pfn2->OriginalPte); 01652 MiInsertPageInList ( 01653 MmPageLocationList[FreePageList], 01654 *Page); 01655 } 01656 } 01657 WrittenPte->u.Long = 0; 01658 } 01659 Page += 1; 01660 } 01661 01662 // 01663 // Indicate that there is no current cluster being built. 01664 // 01665 01666 LastWritten = NULL; 01667 } 01668 01669 } // end while 01670 01671 // 01672 // Get the next subsection if any. 01673 // 01674 01675 if (Subsection->NextSubsection == (PSUBSECTION)NULL) { 01676 break; 01677 } 01678 01679 Subsection = Subsection->NextSubsection; 01680 PointerPte = Subsection->SubsectionBase; 01681 LastPte = PointerPte + Subsection->PtesInSubsection; 01682 01683 } // end for 01684 01685 ControlArea->NumberOfMappedViews = 0; 01686 01687 ASSERT (ControlArea->NumberOfPfnReferences == 0); 01688 01689 if (ControlArea->u.Flags.FilePointerNull == 0) { 01690 ControlArea->u.Flags.FilePointerNull = 1; 01691 01692 if (ControlArea->u.Flags.Image) { 01693 01694 if (MiHydra == TRUE) { 01695 MiRemoveImageSectionObject (ControlArea->FilePointer, 01696 ControlArea); 01697 } 01698 else { 01699 ControlArea->FilePointer->SectionObjectPointer->ImageSectionObject = NULL; 01700 } 01701 } 01702 else { 01703 01704 ASSERT (((PCONTROL_AREA)(ControlArea->FilePointer->SectionObjectPointer->DataSectionObject)) != NULL); 01705 ControlArea->FilePointer->SectionObjectPointer->DataSectionObject = NULL; 01706 01707 } 01708 } 01709 UNLOCK_PFN (OldIrql); 01710 01711 // 01712 // Delete the segment structure. 01713 // 01714 01715 MiSegmentDelete (ControlArea->Segment); 01716 01717 return; 01718 }

NTSTATUS MiCloneProcessAddressSpace IN PEPROCESS  ProcessToClone,
IN PEPROCESS  ProcessToInitialize,
IN PFN_NUMBER  PdePhysicalPage,
IN PFN_NUMBER  HyperPhysicalPage
 

Definition at line 100 of file forksup.c.

References _EPROCESS::AddressSpaceDeleted, ASSERT, BYTE_OFFSET, _MMCLONE_DESCRIPTOR::CloneHeader, _MMCLONE_HEADER::ClonePtes, _MMVAD::ControlArea, DbgPrint, _MMVAD::EndingVpn, _MMCLONE_DESCRIPTOR::EndingVpn, ExAllocatePoolWithTag, EXCEPTION_EXECUTE_HANDLER, ExFreePool(), FALSE, _EPROCESS::ForkInProgress, _EPROCESS::ForkWasSuccessful, HighPagePriority, IS_PTE_NOT_DEMAND_ZERO, KeAttachProcess(), KeBugCheckEx(), KeDelayExecutionThread(), KeDetachProcess(), KernelMode, LOCK_ADDRESS_SPACE, LOCK_WS, MDL_PAGES_LOCKED, _MDL::MdlFlags, MI_GET_PAGE_FRAME_FROM_PTE, MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE, MI_GET_PROTECTION_FROM_SOFT_PTE, MI_GET_PROTECTION_FROM_WSLE, MI_INCREMENT_USED_PTES_BY_HANDLE, MI_MAKE_PROTECT_WRITE_COPY, MI_MAKE_VALID_PTE_WRITE_COPY, MI_PFN_ELEMENT, MI_PTE_LOOKUP_NEEDED, MI_VPN_TO_VA, MI_WRITE_INVALID_PTE, MiBuildForkPageTable(), MiCheckPdeForPagedPool(), MiDoesPdeExistAndMakeValid(), MiDoesPpeExistAndMakeValid, MiDoneWithThisPageGetAnother(), MiDownPfnReferenceCount(), MiDownShareCountFlushEntireTb(), MiGetFirstClone, MiGetFirstVad, MiGetNextClone, MiGetNextVad, MiGetPdeAddress, MiGetPdeOffset, MiGetPpePdeOffset, MiGetPteAddress, MiGetPteOffset, MiGetVirtualAddressMappedByPte, MiHandleForkTransitionPte(), MiInsertClone, MiInsertVad(), MiIsPteOnPdeBoundary, MiLocateCloneAddress, MiLocateWsle(), MiLockPagedAddress(), MiMakeSystemAddressValid(), MiMapSinglePage(), MiProtoAddressForPte, MiPteToProto, MiRemoveClone, MiRetrievePageDirectoryFrames(), MiUnlockPagedAddress(), MiUnmapSinglePage(), MiUpCloneProcessRefCount(), MiUpCloneProtoRefCount(), MiUpControlAreaRefs(), MiUpForkPageShareCount(), MiUpPfnReferenceCount(), MM_DBG_FORK, MM_DECOMMIT, MM_FORK_FAILED, MM_FORK_SUCCEEDED, MM_MAX_COMMIT, MM_VIEW_SHARE, MmCached, MMCLONE_BLOCK, MMCLONE_DESCRIPTOR, MMCLONE_HEADER, MmInitializeMdl, MmMapLockedPagesSpecifyCache(), MmShortTime, MmUnmapLockedPages(), MmWorkingSetList, MmWsle, NonPagedPool, NT_SUCCESS, NTSTATUS(), NULL, _EPROCESS::NumberOfPrivatePages, _MMCLONE_HEADER::NumberOfProcessReferences, _MMCLONE_DESCRIPTOR::NumberOfPtes, _MMCLONE_HEADER::NumberOfPtes, _MMCLONE_DESCRIPTOR::NumberOfReferences, _MMPFN::OriginalPte, PAGE_ALIGN, PAGE_SHIFT, PAGE_SIZE, PAGED_CODE, PagedPool, _MMCLONE_DESCRIPTOR::PagedPoolQuotaCharge, _MMCLONE_DESCRIPTOR::Parent, _MMVAD::Parent, _EPROCESS::PeakVirtualSize, _EPROCESS::PhysicalVadList, PMMCLONE_HEADER, PMMVAD_SHORT, PsChargePoolQuota(), PsGetCurrentProcess, PsGetCurrentThread, PsReturnPoolQuota(), _MMPFN::PteAddress, _MMPFN::PteFrame, _MMVAD::StartingVpn, _MMCLONE_DESCRIPTOR::StartingVpn, TRUE, _MMPTE::u, _MMVAD::u, _MMSUPPORT::u, _MMWSLE::u1, _MMPFN::u1, _MMVAD::u2, _MMPFN::u3, _MMVAD::u3, UNLOCK_ADDRESS_SPACE, UNLOCK_WS, _MMWSL::UsedPageTableEntries, _MI_PHYSICAL_VIEW::Vad, _EPROCESS::VirtualSize, _EPROCESS::Vm, WSLE_NULL_INDEX, and WSLE_NUMBER.

Referenced by MmInitializeProcessAddressSpace().

00109 : 00110 00111 This routine stands on its head to produce a copy of the specified 00112 process's address space in the process to initialize. This 00113 is done by examining each virtual address descriptor's inherit 00114 attributes. If the pages described by the VAD should be inherited, 00115 each PTE is examined and copied into the new address space. 00116 00117 For private pages, fork prototype PTEs are constructed and the pages 00118 become shared, copy-on-write, between the two processes. 00119 00120 00121 Arguments: 00122 00123 ProcessToClone - Supplies the process whose address space should be 00124 cloned. 00125 00126 ProcessToInitialize - Supplies the process whose address space is to 00127 be created. 00128 00129 RootPhysicalPage - Supplies the physical page number of the top level 00130 page (parent on 64-bit systems) directory 00131 of the process to initialize. 00132 00133 HyperPhysicalPage - Supplies the physical page number of the page table 00134 page which maps hyperspace for the process to 00135 initialize. This is only needed for 32-bit systems. 00136 00137 Return Value: 00138 00139 None. 00140 00141 Environment: 00142 00143 Kernel mode, APCs disabled. 00144 00145 --*/ 00146 00147 { 00148 PFN_NUMBER PpePhysicalPage; 00149 PFN_NUMBER PdePhysicalPage; 00150 PEPROCESS CurrentProcess; 00151 PMMPTE PdeBase; 00152 PMMCLONE_HEADER CloneHeader; 00153 PMMCLONE_BLOCK CloneProtos; 00154 PMMCLONE_DESCRIPTOR CloneDescriptor; 00155 PMMVAD NewVad; 00156 PMMVAD Vad; 00157 PMMVAD NextVad; 00158 PMMVAD *VadList; 00159 PMMVAD FirstNewVad; 00160 PMMCLONE_DESCRIPTOR *CloneList; 00161 PMMCLONE_DESCRIPTOR FirstNewClone; 00162 PMMCLONE_DESCRIPTOR Clone; 00163 PMMCLONE_DESCRIPTOR NextClone; 00164 PMMCLONE_DESCRIPTOR NewClone; 00165 ULONG Attached; 00166 ULONG CloneFailed; 00167 ULONG VadInsertFailed; 00168 WSLE_NUMBER WorkingSetIndex; 00169 PVOID VirtualAddress; 00170 NTSTATUS status; 00171 PMMPFN Pfn2; 00172 PMMPFN PfnPdPage; 00173 MMPTE TempPte; 00174 MMPTE PteContents; 00175 #if defined (_X86PAE_) 00176 PMDL MdlPageDirectory; 00177 PPFN_NUMBER MdlPageFrames; 00178 PFN_NUMBER PageDirectoryFrames[PD_PER_SYSTEM]; 00179 PFN_NUMBER MdlHackPageDirectory[(sizeof(MDL)/sizeof(PFN_NUMBER)) + PD_PER_SYSTEM]; 00180 #endif 00181 PFN_NUMBER MdlPage; 00182 PFN_NUMBER MdlDirPage; 00183 PMMPTE PointerPte; 00184 PMMPTE PointerPde; 00185 PMMPTE PointerPpe; 00186 PMMPTE LastPte; 00187 PMMPTE PointerNewPte; 00188 PMMPTE NewPteMappedAddress; 00189 PMMPTE PointerNewPde; 00190 PLIST_ENTRY NextEntry; 00191 PMI_PHYSICAL_VIEW PhysicalView; 00192 PFN_NUMBER PageFrameIndex; 00193 PFN_NUMBER PageDirFrameIndex; 00194 PMMCLONE_BLOCK ForkProtoPte; 00195 PMMCLONE_BLOCK CloneProto; 00196 PMMCLONE_BLOCK LockedForkPte; 00197 PMMPTE ContainingPte; 00198 ULONG NumberOfForkPtes; 00199 PFN_NUMBER NumberOfPrivatePages; 00200 PFN_NUMBER PageTablePage; 00201 SIZE_T TotalPagedPoolCharge; 00202 SIZE_T TotalNonPagedPoolCharge; 00203 PMMPFN PfnForkPtePage; 00204 PVOID UsedPageTableEntries; 00205 ULONG ReleasedWorkingSetMutex; 00206 ULONG FirstTime; 00207 ULONG Waited; 00208 ULONG i; 00209 ULONG PpePdeOffset; 00210 #if defined (_WIN64) 00211 PVOID UsedPageDirectoryEntries; 00212 PMMPTE PointerNewPpe; 00213 PMMPTE PpeBase; 00214 PMMPFN PfnPpPage; 00215 #else 00216 PMMWSL HyperBase; 00217 #endif 00218 00219 PageTablePage = 2; 00220 NumberOfForkPtes = 0; 00221 Attached = FALSE; 00222 PageFrameIndex = (PFN_NUMBER)-1; 00223 PageDirFrameIndex = (PFN_NUMBER)-1; 00224 00225 #if DBG 00226 if (MmDebug & MM_DBG_FORK) { 00227 DbgPrint("beginning clone operation process to clone = %lx\n", 00228 ProcessToClone); 00229 } 00230 #endif //DBG 00231 00232 PAGED_CODE(); 00233 00234 if (ProcessToClone != PsGetCurrentProcess()) { 00235 Attached = TRUE; 00236 KeAttachProcess (&ProcessToClone->Pcb); 00237 } 00238 00239 #if defined (_X86PAE_) 00240 MiRetrievePageDirectoryFrames (RootPhysicalPage, PageDirectoryFrames); 00241 #endif 00242 00243 CurrentProcess = ProcessToClone; 00244 00245 // 00246 // Get the working set mutex and the address creation mutex 00247 // of the process to clone. This prevents page faults while we 00248 // are examining the address map and prevents virtual address space 00249 // from being created or deleted. 00250 // 00251 00252 LOCK_ADDRESS_SPACE (CurrentProcess); 00253 00254 // 00255 // Write-watch VAD bitmaps are not currently duplicated 00256 // so fork is not allowed. 00257 // 00258 00259 if (CurrentProcess->Vm.u.Flags.WriteWatch == 1) { 00260 status = STATUS_INVALID_PAGE_PROTECTION; 00261 goto ErrorReturn1; 00262 } 00263 00264 // 00265 // Check for AWE regions as they are not duplicated so fork is not allowed. 00266 // Note that since this is a readonly list walk, the address space mutex 00267 // is sufficient to synchronize properly. 00268 // 00269 00270 NextEntry = CurrentProcess->PhysicalVadList.Flink; 00271 while (NextEntry != &CurrentProcess->PhysicalVadList) { 00272 00273 PhysicalView = CONTAINING_RECORD(NextEntry, 00274 MI_PHYSICAL_VIEW, 00275 ListEntry); 00276 00277 if (PhysicalView->Vad->u.VadFlags.UserPhysicalPages == 1) { 00278 status = STATUS_INVALID_PAGE_PROTECTION; 00279 goto ErrorReturn1; 00280 } 00281 00282 NextEntry = NextEntry->Flink; 00283 } 00284 00285 // 00286 // Make sure the address space was not deleted, if so, return an error. 00287 // 00288 00289 if (CurrentProcess->AddressSpaceDeleted != 0) { 00290 status = STATUS_PROCESS_IS_TERMINATING; 00291 goto ErrorReturn1; 00292 } 00293 00294 // 00295 // Attempt to acquire the needed pool before starting the 00296 // clone operation, this allows an easier failure path in 00297 // the case of insufficient system resources. 00298 // 00299 00300 NumberOfPrivatePages = CurrentProcess->NumberOfPrivatePages; 00301 00302 CloneProtos = ExAllocatePoolWithTag (PagedPool, sizeof(MMCLONE_BLOCK) * 00303 NumberOfPrivatePages, 00304 'lCmM'); 00305 if (CloneProtos == NULL) { 00306 status = STATUS_INSUFFICIENT_RESOURCES; 00307 goto ErrorReturn1; 00308 } 00309 00310 CloneHeader = ExAllocatePoolWithTag (NonPagedPool, 00311 sizeof(MMCLONE_HEADER), 00312 ' mM'); 00313 if (CloneHeader == NULL) { 00314 status = STATUS_INSUFFICIENT_RESOURCES; 00315 goto ErrorReturn2; 00316 } 00317 00318 CloneDescriptor = ExAllocatePoolWithTag (NonPagedPool, 00319 sizeof(MMCLONE_DESCRIPTOR), 00320 ' mM'); 00321 if (CloneDescriptor == NULL) { 00322 status = STATUS_INSUFFICIENT_RESOURCES; 00323 goto ErrorReturn3; 00324 } 00325 00326 Vad = MiGetFirstVad (CurrentProcess); 00327 VadList = &FirstNewVad; 00328 00329 while (Vad != (PMMVAD)NULL) { 00330 00331 // 00332 // If the VAD does not go to the child, ignore it. 00333 // 00334 00335 if ((Vad->u.VadFlags.UserPhysicalPages == 0) && 00336 00337 ((Vad->u.VadFlags.PrivateMemory == 1) || 00338 (Vad->u2.VadFlags2.Inherit == MM_VIEW_SHARE))) { 00339 00340 NewVad = ExAllocatePoolWithTag (NonPagedPool, sizeof(MMVAD), ' daV'); 00341 00342 if (NewVad == NULL) { 00343 00344 // 00345 // Unable to allocate pool for all the VADs. Deallocate 00346 // all VADs and other pool obtained so far. 00347 // 00348 00349 *VadList = (PMMVAD)NULL; 00350 status = STATUS_INSUFFICIENT_RESOURCES; 00351 goto ErrorReturn4; 00352 } 00353 *VadList = NewVad; 00354 VadList = &NewVad->Parent; 00355 } 00356 Vad = MiGetNextVad (Vad); 00357 } 00358 00359 // 00360 // Terminate list of VADs for new process. 00361 // 00362 00363 *VadList = (PMMVAD)NULL; 00364 00365 // 00366 // Charge the current process the quota for the paged and nonpaged 00367 // global structures. This consists of the array of clone blocks 00368 // in paged pool and the clone header in non-paged pool. 00369 // 00370 00371 try { 00372 PsChargePoolQuota (CurrentProcess, PagedPool, sizeof(MMCLONE_BLOCK) * 00373 NumberOfPrivatePages); 00374 PageTablePage = 1; 00375 PsChargePoolQuota (CurrentProcess, NonPagedPool, sizeof(MMCLONE_HEADER)); 00376 PageTablePage = 0; 00377 00378 } except (EXCEPTION_EXECUTE_HANDLER) { 00379 00380 // 00381 // Unable to charge quota for the clone blocks. 00382 // 00383 00384 status = GetExceptionCode(); 00385 goto ErrorReturn4; 00386 } 00387 00388 LOCK_WS (CurrentProcess); 00389 00390 ASSERT (CurrentProcess->ForkInProgress == NULL); 00391 00392 // 00393 // Indicate to the pager that the current process is being 00394 // forked. This blocks other threads in that process from 00395 // modifying clone blocks counts and contents. 00396 // 00397 00398 CurrentProcess->ForkInProgress = PsGetCurrentThread(); 00399 00400 #if defined (_WIN64) 00401 00402 // 00403 // Increment the reference count for the pages which are being "locked" 00404 // in MDLs. This prevents the page from being reused while it is 00405 // being double mapped. Note we have a count of 3 below because in addition 00406 // to the PPE, we also set up a initial dummy PDE and PTE. 00407 // 00408 00409 MiUpPfnReferenceCount (RootPhysicalPage, 3); 00410 00411 // 00412 // Map the page directory parent page into the system address 00413 // space. This is accomplished by building an MDL to describe the 00414 // Page directory parent page. 00415 // 00416 00417 PpeBase = (PMMPTE)MiMapSinglePage (NULL, 00418 RootPhysicalPage, 00419 MmCached, 00420 HighPagePriority); 00421 00422 if (PpeBase == NULL) { 00423 MiDownPfnReferenceCount (RootPhysicalPage, 3); 00424 CurrentProcess->ForkInProgress = NULL; 00425 UNLOCK_WS (CurrentProcess); 00426 status = STATUS_INSUFFICIENT_RESOURCES; 00427 goto ErrorReturn4; 00428 } 00429 00430 PfnPpPage = MI_PFN_ELEMENT (RootPhysicalPage); 00431 00432 #else 00433 00434 #if !defined (_X86PAE_) 00435 MiUpPfnReferenceCount (RootPhysicalPage, 1); 00436 #endif 00437 00438 #endif 00439 00440 // 00441 // Initialize a page directory map so it can be 00442 // unlocked in the loop and the end of the loop without 00443 // any testing to see if has a valid value the first time through. 00444 // Note this is a dummy map for 64-bit systems and a real one for 32-bit. 00445 // 00446 00447 #if !defined (_X86PAE_) 00448 00449 MdlDirPage = RootPhysicalPage; 00450 00451 PdePhysicalPage = RootPhysicalPage; 00452 00453 PdeBase = (PMMPTE)MiMapSinglePage (NULL, 00454 MdlDirPage, 00455 MmCached, 00456 HighPagePriority); 00457 00458 if (PdeBase == NULL) { 00459 #if defined (_WIN64) 00460 MiDownPfnReferenceCount (RootPhysicalPage, 3); 00461 MiUnmapSinglePage (PpeBase); 00462 #else 00463 MiDownPfnReferenceCount (RootPhysicalPage, 1); 00464 #endif 00465 CurrentProcess->ForkInProgress = NULL; 00466 UNLOCK_WS (CurrentProcess); 00467 status = STATUS_INSUFFICIENT_RESOURCES; 00468 goto ErrorReturn4; 00469 } 00470 00471 #else 00472 00473 // 00474 // All 4 page directory pages need to be mapped for PAE so the heavyweight 00475 // mapping must be used. 00476 // 00477 00478 MdlPageDirectory = (PMDL)&MdlHackPageDirectory[0]; 00479 00480 MmInitializeMdl(MdlPageDirectory, (PVOID)PDE_BASE, PD_PER_SYSTEM * PAGE_SIZE); 00481 MdlPageDirectory->MdlFlags |= MDL_PAGES_LOCKED; 00482 00483 MdlPageFrames = (PPFN_NUMBER)(MdlPageDirectory + 1); 00484 00485 for (i = 0; i < PD_PER_SYSTEM; i += 1) { 00486 *(MdlPageFrames + i) = PageDirectoryFrames[i]; 00487 MiUpPfnReferenceCount (PageDirectoryFrames[i], 1); 00488 } 00489 00490 PdePhysicalPage = RootPhysicalPage; 00491 00492 PdeBase = (PMMPTE)MmMapLockedPagesSpecifyCache (MdlPageDirectory, 00493 KernelMode, 00494 MmCached, 00495 NULL, 00496 FALSE, 00497 HighPagePriority); 00498 00499 if (PdeBase == NULL) { 00500 for (i = 0; i < PD_PER_SYSTEM; i += 1) { 00501 MiDownPfnReferenceCount (PageDirectoryFrames[i], 1); 00502 } 00503 CurrentProcess->ForkInProgress = NULL; 00504 UNLOCK_WS (CurrentProcess); 00505 status = STATUS_INSUFFICIENT_RESOURCES; 00506 goto ErrorReturn4; 00507 } 00508 00509 #endif 00510 00511 PfnPdPage = MI_PFN_ELEMENT (RootPhysicalPage); 00512 00513 #if !defined (_WIN64) 00514 00515 // 00516 // Map hyperspace so target UsedPageTable entries can be incremented. 00517 // 00518 00519 MiUpPfnReferenceCount (HyperPhysicalPage, 2); 00520 00521 HyperBase = (PMMWSL)MiMapSinglePage (NULL, 00522 HyperPhysicalPage, 00523 MmCached, 00524 HighPagePriority); 00525 00526 if (HyperBase == NULL) { 00527 MiDownPfnReferenceCount (HyperPhysicalPage, 2); 00528 #if !defined (_X86PAE_) 00529 MiDownPfnReferenceCount (RootPhysicalPage, 1); 00530 MiUnmapSinglePage (PdeBase); 00531 #else 00532 for (i = 0; i < PD_PER_SYSTEM; i += 1) { 00533 MiDownPfnReferenceCount (PageDirectoryFrames[i], 1); 00534 } 00535 MmUnmapLockedPages (PdeBase, MdlPageDirectory); 00536 #endif 00537 CurrentProcess->ForkInProgress = NULL; 00538 UNLOCK_WS (CurrentProcess); 00539 status = STATUS_INSUFFICIENT_RESOURCES; 00540 goto ErrorReturn4; 00541 } 00542 #endif 00543 00544 // 00545 // Initialize a page table MDL to lock and map the hyperspace page so it 00546 // can be unlocked in the loop and the end of the loop without 00547 // any testing to see if has a valid value the first time through. 00548 // 00549 00550 #if defined (_WIN64) 00551 MdlPage = RootPhysicalPage; 00552 #else 00553 MdlPage = HyperPhysicalPage; 00554 #endif 00555 00556 NewPteMappedAddress = (PMMPTE)MiMapSinglePage (NULL, 00557 MdlPage, 00558 MmCached, 00559 HighPagePriority); 00560 00561 if (NewPteMappedAddress == NULL) { 00562 00563 #if defined (_WIN64) 00564 00565 MiDownPfnReferenceCount (RootPhysicalPage, 3); 00566 MiUnmapSinglePage (PpeBase); 00567 MiUnmapSinglePage (PdeBase); 00568 00569 #else 00570 MiDownPfnReferenceCount (HyperPhysicalPage, 2); 00571 MiUnmapSinglePage (HyperBase); 00572 #if !defined (_X86PAE_) 00573 MiDownPfnReferenceCount (RootPhysicalPage, 1); 00574 MiUnmapSinglePage (PdeBase); 00575 #else 00576 for (i = 0; i < PD_PER_SYSTEM; i += 1) { 00577 MiDownPfnReferenceCount (PageDirectoryFrames[i], 1); 00578 } 00579 MmUnmapLockedPages (PdeBase, MdlPageDirectory); 00580 #endif 00581 00582 #endif 00583 00584 CurrentProcess->ForkInProgress = NULL; 00585 UNLOCK_WS (CurrentProcess); 00586 status = STATUS_INSUFFICIENT_RESOURCES; 00587 goto ErrorReturn4; 00588 } 00589 00590 PointerNewPte = NewPteMappedAddress; 00591 00592 // 00593 // Build new clone prototype PTE block and descriptor, note that 00594 // each prototype PTE has a reference count following it. 00595 // 00596 00597 ForkProtoPte = CloneProtos; 00598 00599 LockedForkPte = ForkProtoPte; 00600 MiLockPagedAddress (LockedForkPte, FALSE); 00601 00602 CloneHeader->NumberOfPtes = (ULONG)NumberOfPrivatePages; 00603 CloneHeader->NumberOfProcessReferences = 1; 00604 CloneHeader->ClonePtes = CloneProtos; 00605 00606 00607 00608 CloneDescriptor->StartingVpn = (ULONG_PTR)CloneProtos; 00609 CloneDescriptor->EndingVpn = (ULONG_PTR)((ULONG_PTR)CloneProtos + 00610 NumberOfPrivatePages * 00611 sizeof(MMCLONE_BLOCK)); 00612 CloneDescriptor->NumberOfReferences = 0; 00613 CloneDescriptor->NumberOfPtes = (ULONG)NumberOfPrivatePages; 00614 CloneDescriptor->CloneHeader = CloneHeader; 00615 CloneDescriptor->PagedPoolQuotaCharge = sizeof(MMCLONE_BLOCK) * 00616 NumberOfPrivatePages; 00617 00618 // 00619 // Insert the clone descriptor for this fork operation into the 00620 // process which was cloned. 00621 // 00622 00623 MiInsertClone (CloneDescriptor); 00624 00625 // 00626 // Examine each virtual address descriptor and create the 00627 // proper structures for the new process. 00628 // 00629 00630 Vad = MiGetFirstVad (CurrentProcess); 00631 NewVad = FirstNewVad; 00632 00633 while (Vad != (PMMVAD)NULL) { 00634 00635 // 00636 // Examine the VAD to determine its type and inheritance 00637 // attribute. 00638 // 00639 00640 if ((Vad->u.VadFlags.UserPhysicalPages == 0) && 00641 00642 ((Vad->u.VadFlags.PrivateMemory == 1) || 00643 (Vad->u2.VadFlags2.Inherit == MM_VIEW_SHARE))) { 00644 00645 // 00646 // The virtual address descriptor should be shared in the 00647 // forked process. 00648 // 00649 00650 // 00651 // Make a copy of the VAD for the new process, the new VADs 00652 // are preallocated and linked together through the parent 00653 // field. 00654 // 00655 00656 NextVad = NewVad->Parent; 00657 00658 00659 if (Vad->u.VadFlags.PrivateMemory == 1) { 00660 *(PMMVAD_SHORT)NewVad = *(PMMVAD_SHORT)Vad; 00661 NewVad->u.VadFlags.NoChange = 0; 00662 } else { 00663 *NewVad = *Vad; 00664 } 00665 00666 if (NewVad->u.VadFlags.NoChange) { 00667 if ((NewVad->u2.VadFlags2.OneSecured) || 00668 (NewVad->u2.VadFlags2.MultipleSecured)) { 00669 00670 // 00671 // Eliminate these as the memory was secured 00672 // only in this process, not in the new one. 00673 // 00674 00675 NewVad->u2.VadFlags2.OneSecured = 0; 00676 NewVad->u2.VadFlags2.MultipleSecured = 0; 00677 NewVad->u2.VadFlags2.StoredInVad = 0; 00678 NewVad->u3.List.Flink = NULL; 00679 NewVad->u3.List.Blink = NULL; 00680 } 00681 if (NewVad->u2.VadFlags2.SecNoChange == 0) { 00682 NewVad->u.VadFlags.NoChange = 0; 00683 } 00684 } 00685 NewVad->Parent = NextVad; 00686 00687 // 00688 // If the VAD refers to a section, up the view count for that 00689 // section. This requires the PFN mutex to be held. 00690 // 00691 00692 if ((Vad->u.VadFlags.PrivateMemory == 0) && 00693 (Vad->ControlArea != (PCONTROL_AREA)NULL)) { 00694 00695 // 00696 // Increment the count of the number of views for the 00697 // section object. This requires the PFN mutex to be held. 00698 // 00699 00700 MiUpControlAreaRefs (Vad->ControlArea); 00701 } 00702 00703 // 00704 // Examine each PTE and create the appropriate PTE for the 00705 // new process. 00706 // 00707 00708 PointerPde = MiGetPdeAddress (MI_VPN_TO_VA (Vad->StartingVpn)); 00709 PointerPte = (volatile PMMPTE) MiGetPteAddress ( 00710 MI_VPN_TO_VA (Vad->StartingVpn)); 00711 LastPte = MiGetPteAddress (MI_VPN_TO_VA (Vad->EndingVpn)); 00712 FirstTime = TRUE; 00713 00714 while ((PMMPTE)PointerPte <= LastPte) { 00715 00716 // 00717 // For each PTE contained in the VAD check the page table 00718 // page, and if non-zero, make the appropriate modifications 00719 // to copy the PTE to the new process. 00720 // 00721 00722 if ((FirstTime) || MiIsPteOnPdeBoundary (PointerPte)) { 00723 00724 PointerPpe = MiGetPdeAddress (PointerPte); 00725 PointerPde = MiGetPteAddress (PointerPte); 00726 00727 do { 00728 00729 while (!MiDoesPpeExistAndMakeValid (PointerPpe, 00730 CurrentProcess, 00731 FALSE, 00732 &Waited)) { 00733 00734 // 00735 // Page directory parent is empty, go to the next one. 00736 // 00737 00738 PointerPpe += 1; 00739 PointerPde = MiGetVirtualAddressMappedByPte (PointerPpe); 00740 PointerPte = MiGetVirtualAddressMappedByPte (PointerPde); 00741 00742 if ((PMMPTE)PointerPte > LastPte) { 00743 00744 // 00745 // All done with this VAD, exit loop. 00746 // 00747 00748 goto AllDone; 00749 } 00750 } 00751 00752 Waited = 0; 00753 00754 while (!MiDoesPdeExistAndMakeValid (PointerPde, 00755 CurrentProcess, 00756 FALSE, 00757 &Waited)) { 00758 00759 // 00760 // This page directory is empty, go to the next one. 00761 // 00762 00763 PointerPde += 1; 00764 PointerPte = MiGetVirtualAddressMappedByPte (PointerPde); 00765 00766 if ((PMMPTE)PointerPte > LastPte) { 00767 00768 // 00769 // All done with this VAD, exit loop. 00770 // 00771 00772 goto AllDone; 00773 } 00774 #if defined (_WIN64) 00775 if (MiIsPteOnPdeBoundary (PointerPde)) { 00776 PointerPpe = MiGetPteAddress (PointerPde); 00777 Waited = 1; 00778 break; 00779 } 00780 #endif 00781 } 00782 00783 } while (Waited != 0); 00784 00785 FirstTime = FALSE; 00786 00787 #if defined (_WIN64) 00788 // 00789 // Calculate the address of the PPE in the new process's 00790 // page directory parent page. 00791 // 00792 00793 PointerNewPpe = &PpeBase[MiGetPdeOffset(PointerPte)]; 00794 00795 if (PointerNewPpe->u.Long == 0) { 00796 00797 // 00798 // No physical page has been allocated yet, get a page 00799 // and map it in as a transition page. This will 00800 // become a page table page for the new process. 00801 // 00802 00803 ReleasedWorkingSetMutex = 00804 MiDoneWithThisPageGetAnother (&PageDirFrameIndex, 00805 PointerPpe, 00806 CurrentProcess); 00807 00808 MI_ZERO_USED_PAGETABLE_ENTRIES (MI_PFN_ELEMENT(PageDirFrameIndex)); 00809 00810 if (ReleasedWorkingSetMutex) { 00811 00812 do { 00813 00814 MiDoesPpeExistAndMakeValid (PointerPpe, 00815 CurrentProcess, 00816 FALSE, 00817 &Waited); 00818 00819 Waited = 0; 00820 00821 MiDoesPdeExistAndMakeValid (PointerPde, 00822 CurrentProcess, 00823 FALSE, 00824 &Waited); 00825 } while (Waited != 0); 00826 } 00827 00828 // 00829 // Hand initialize this PFN as normal initialization 00830 // would do it for the process whose context we are 00831 // attached to. 00832 // 00833 // The PFN lock must be held while initializing the 00834 // frame to prevent those scanning the database for 00835 // free frames from taking it after we fill in the 00836 // u2 field. 00837 // 00838 00839 MiBuildForkPageTable (PageDirFrameIndex, 00840 PointerPpe, 00841 PointerNewPpe, 00842 RootPhysicalPage, 00843 PfnPpPage); 00844 00845 // 00846 // Map the new page directory page into the system 00847 // portion of the address space. Note that hyperspace 00848 // cannot be used as other operations (allocating 00849 // nonpaged pool at DPC level) could cause the 00850 // hyperspace page being used to be reused. 00851 // 00852 00853 MiDownPfnReferenceCount (MdlDirPage, 1); 00854 00855 MdlDirPage = PageDirFrameIndex; 00856 00857 ASSERT (PdeBase != NULL); 00858 00859 PdeBase = (PMMPTE)MiMapSinglePage (PdeBase, 00860 MdlDirPage, 00861 MmCached, 00862 HighPagePriority); 00863 00864 MiUpPfnReferenceCount (MdlDirPage, 1); 00865 00866 PointerNewPde = PdeBase; 00867 } 00868 else { 00869 ASSERT (PointerNewPpe->u.Hard.Valid == 1 || 00870 PointerNewPpe->u.Soft.Transition == 1); 00871 00872 if (PointerNewPpe->u.Hard.Valid == 1) { 00873 PageDirFrameIndex = MI_GET_PAGE_FRAME_FROM_PTE (PointerNewPpe); 00874 } 00875 else { 00876 PageDirFrameIndex = MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE (PointerNewPpe); 00877 } 00878 } 00879 00880 // 00881 // Calculate the address of the new PDE to build. 00882 // Note that FirstTime could be true, yet the page 00883 // directory page might already be built. 00884 // 00885 00886 PointerNewPde = (PMMPTE)((ULONG_PTR)PAGE_ALIGN(PointerNewPde) | 00887 BYTE_OFFSET (PointerPde)); 00888 00889 PdePhysicalPage = PageDirFrameIndex; 00890 00891 PfnPdPage = MI_PFN_ELEMENT (PdePhysicalPage); 00892 00893 UsedPageDirectoryEntries = (PVOID)PfnPdPage; 00894 #endif 00895 00896 // 00897 // Calculate the address of the PDE in the new process's 00898 // page directory page. 00899 // 00900 00901 PpePdeOffset = MiGetPpePdeOffset(MiGetVirtualAddressMappedByPte(PointerPte)); 00902 PointerNewPde = &PdeBase[PpePdeOffset]; 00903 00904 if (PointerNewPde->u.Long == 0) { 00905 00906 // 00907 // No physical page has been allocated yet, get a page 00908 // and map it in as a transition page. This will 00909 // become a page table page for the new process. 00910 // 00911 00912 ReleasedWorkingSetMutex = 00913 MiDoneWithThisPageGetAnother (&PageFrameIndex, 00914 PointerPde, 00915 CurrentProcess); 00916 00917 if (ReleasedWorkingSetMutex) { 00918 00919 do { 00920 00921 MiDoesPpeExistAndMakeValid (PointerPpe, 00922 CurrentProcess, 00923 FALSE, 00924 &Waited); 00925 00926 Waited = 0; 00927 00928 MiDoesPdeExistAndMakeValid (PointerPde, 00929 CurrentProcess, 00930 FALSE, 00931 &Waited); 00932 } while (Waited != 0); 00933 } 00934 00935 // 00936 // Hand initialize this PFN as normal initialization 00937 // would do it for the process whose context we are 00938 // attached to. 00939 // 00940 // The PFN lock must be held while initializing the 00941 // frame to prevent those scanning the database for 00942 // free frames from taking it after we fill in the 00943 // u2 field. 00944 // 00945 00946 #if defined (_X86PAE_) 00947 PdePhysicalPage = PageDirectoryFrames[MiGetPdPteOffset(MiGetVirtualAddressMappedByPte(PointerPte))]; 00948 PfnPdPage = MI_PFN_ELEMENT (PdePhysicalPage); 00949 #endif 00950 00951 MiBuildForkPageTable (PageFrameIndex, 00952 PointerPde, 00953 PointerNewPde, 00954 PdePhysicalPage, 00955 PfnPdPage); 00956 00957 #if defined (_WIN64) 00958 MI_INCREMENT_USED_PTES_BY_HANDLE (UsedPageDirectoryEntries); 00959 #endif 00960 00961 // 00962 // Map the new page table page into the system portion 00963 // of the address space. Note that hyperspace 00964 // cannot be used as other operations (allocating 00965 // nonpaged pool at DPC level) could cause the 00966 // hyperspace page being used to be reused. 00967 // 00968 00969 ASSERT (NewPteMappedAddress != NULL); 00970 00971 MiDownPfnReferenceCount (MdlPage, 1); 00972 00973 MdlPage = PageFrameIndex; 00974 00975 PointerNewPte = (PMMPTE)MiMapSinglePage (NewPteMappedAddress, 00976 MdlPage, 00977 MmCached, 00978 HighPagePriority); 00979 00980 ASSERT (PointerNewPte != NULL); 00981 00982 MiUpPfnReferenceCount (MdlPage, 1); 00983 } 00984 00985 // 00986 // Calculate the address of the new PTE to build. 00987 // Note that FirstTime could be true, yet the page 00988 // table page already built. 00989 // 00990 00991 PointerNewPte = (PMMPTE)((ULONG_PTR)PAGE_ALIGN(PointerNewPte) | 00992 BYTE_OFFSET (PointerPte)); 00993 00994 #ifdef _WIN64 00995 UsedPageTableEntries = (PVOID)MI_PFN_ELEMENT((PFN_NUMBER)PointerNewPde->u.Hard.PageFrameNumber); 00996 #else 00997 #if !defined (_X86PAE_) 00998 UsedPageTableEntries = (PVOID)&HyperBase->UsedPageTableEntries 00999 [MiGetPteOffset( PointerPte )]; 01000 #else 01001 UsedPageTableEntries = (PVOID)&HyperBase->UsedPageTableEntries 01002 [MiGetPpePdeOffset(MiGetVirtualAddressMappedByPte(PointerPte))]; 01003 #endif 01004 #endif 01005 01006 } 01007 01008 // 01009 // Make the fork prototype PTE location resident. 01010 // 01011 01012 if (PAGE_ALIGN (ForkProtoPte) != PAGE_ALIGN (LockedForkPte)) { 01013 MiUnlockPagedAddress (LockedForkPte, FALSE); 01014 LockedForkPte = ForkProtoPte; 01015 MiLockPagedAddress (LockedForkPte, FALSE); 01016 } 01017 01018 MiMakeSystemAddressValid (PointerPte, CurrentProcess); 01019 01020 PteContents = *PointerPte; 01021 01022 // 01023 // Check each PTE. 01024 // 01025 01026 if (PteContents.u.Long == 0) { 01027 NOTHING; 01028 01029 } else if (PteContents.u.Hard.Valid == 1) { 01030 01031 // 01032 // Valid. 01033 // 01034 01035 Pfn2 = MI_PFN_ELEMENT (PteContents.u.Hard.PageFrameNumber); 01036 VirtualAddress = MiGetVirtualAddressMappedByPte (PointerPte); 01037 WorkingSetIndex = MiLocateWsle (VirtualAddress, 01038 MmWorkingSetList, 01039 Pfn2->u1.WsIndex); 01040 01041 ASSERT (WorkingSetIndex != WSLE_NULL_INDEX); 01042 01043 if (Pfn2->u3.e1.PrototypePte == 1) { 01044 01045 // 01046 // This PTE is already in prototype PTE format. 01047 // 01048 01049 // 01050 // This is a prototype PTE. The PFN database does 01051 // not contain the contents of this PTE it contains 01052 // the contents of the prototype PTE. This PTE must 01053 // be reconstructed to contain a pointer to the 01054 // prototype PTE. 01055 // 01056 // The working set list entry contains information about 01057 // how to reconstruct the PTE. 01058 // 01059 01060 if (MmWsle[WorkingSetIndex].u1.e1.SameProtectAsProto 01061 == 0) { 01062 01063 // 01064 // The protection for the prototype PTE is in the 01065 // WSLE. 01066 // 01067 01068 TempPte.u.Long = 0; 01069 TempPte.u.Soft.Protection = 01070 MI_GET_PROTECTION_FROM_WSLE(&MmWsle[WorkingSetIndex]); 01071 TempPte.u.Soft.PageFileHigh = MI_PTE_LOOKUP_NEEDED; 01072 01073 } else { 01074 01075 // 01076 // The protection is in the prototype PTE. 01077 // 01078 01079 TempPte.u.Long = MiProtoAddressForPte ( 01080 Pfn2->PteAddress); 01081 // TempPte.u.Proto.ForkType = 01082 // MmWsle[WorkingSetIndex].u1.e1.ForkType; 01083 } 01084 01085 TempPte.u.Proto.Prototype = 1; 01086 MI_WRITE_INVALID_PTE (PointerNewPte, TempPte); 01087 01088 // 01089 // A PTE is now non-zero, increment the used page 01090 // table entries counter. 01091 // 01092 01093 MI_INCREMENT_USED_PTES_BY_HANDLE (UsedPageTableEntries); 01094 01095 // 01096 // Check to see if this is a fork prototype PTE, 01097 // and if it is increment the reference count 01098 // which is in the longword following the PTE. 01099 // 01100 01101 if (MiLocateCloneAddress ((PVOID)Pfn2->PteAddress) != 01102 (PMMCLONE_DESCRIPTOR)NULL) { 01103 01104 // 01105 // The reference count field, or the prototype PTE 01106 // for that matter may not be in the working set. 01107 // 01108 01109 CloneProto = (PMMCLONE_BLOCK)Pfn2->PteAddress; 01110 01111 MiUpCloneProtoRefCount (CloneProto, 01112 CurrentProcess); 01113 01114 if (PAGE_ALIGN (ForkProtoPte) != 01115 PAGE_ALIGN (LockedForkPte)) { 01116 MiUnlockPagedAddress (LockedForkPte, FALSE); 01117 LockedForkPte = ForkProtoPte; 01118 MiLockPagedAddress (LockedForkPte, FALSE); 01119 } 01120 01121 MiMakeSystemAddressValid (PointerPte, 01122 CurrentProcess); 01123 } 01124 01125 } else { 01126 01127 // 01128 // This is a private page, create a fork prototype PTE 01129 // which becomes the "prototype" PTE for this page. 01130 // The protection is the same as that in the prototype' 01131 // PTE so the WSLE does not need to be updated. 01132 // 01133 01134 MI_MAKE_VALID_PTE_WRITE_COPY (PointerPte); 01135 01136 ForkProtoPte->ProtoPte = *PointerPte; 01137 ForkProtoPte->CloneRefCount = 2; 01138 01139 // 01140 // Transform the PFN element to reference this new fork 01141 // prototype PTE. 01142 // 01143 01144 Pfn2->PteAddress = &ForkProtoPte->ProtoPte; 01145 Pfn2->u3.e1.PrototypePte = 1; 01146 01147 ContainingPte = MiGetPteAddress(&ForkProtoPte->ProtoPte); 01148 if (ContainingPte->u.Hard.Valid == 0) { 01149 #if !defined (_WIN64) 01150 if (!NT_SUCCESS(MiCheckPdeForPagedPool (&ForkProtoPte->ProtoPte))) { 01151 #endif 01152 KeBugCheckEx (MEMORY_MANAGEMENT, 01153 0x61940, 01154 (ULONG_PTR)&ForkProtoPte->ProtoPte, 01155 (ULONG_PTR)ContainingPte->u.Long, 01156 (ULONG_PTR)MiGetVirtualAddressMappedByPte(&ForkProtoPte->ProtoPte)); 01157 #if !defined (_WIN64) 01158 } 01159 #endif 01160 } 01161 Pfn2->PteFrame = MI_GET_PAGE_FRAME_FROM_PTE (ContainingPte); 01162 01163 01164 // 01165 // Increment the share count for the page containing the 01166 // fork prototype PTEs as we have just placed a valid 01167 // PTE into the page. 01168 // 01169 01170 PfnForkPtePage = MI_PFN_ELEMENT ( 01171 ContainingPte->u.Hard.PageFrameNumber ); 01172 01173 MiUpForkPageShareCount (PfnForkPtePage); 01174 01175 // 01176 // Change the protection in the PFN database to COPY 01177 // on write, if writable. 01178 // 01179 01180 MI_MAKE_PROTECT_WRITE_COPY (Pfn2->OriginalPte); 01181 01182 // 01183 // Put the protection into the WSLE and mark the WSLE 01184 // to indicate that the protection field for the PTE 01185 // is the same as the prototype PTE. 01186 // 01187 01188 MmWsle[WorkingSetIndex].u1.e1.Protection = 01189 MI_GET_PROTECTION_FROM_SOFT_PTE(&Pfn2->OriginalPte); 01190 01191 MmWsle[WorkingSetIndex].u1.e1.SameProtectAsProto = 1; 01192 01193 TempPte.u.Long = MiProtoAddressForPte (Pfn2->PteAddress); 01194 TempPte.u.Proto.Prototype = 1; 01195 MI_WRITE_INVALID_PTE (PointerNewPte, TempPte); 01196 01197 // 01198 // A PTE is now non-zero, increment the used page 01199 // table entries counter. 01200 // 01201 01202 MI_INCREMENT_USED_PTES_BY_HANDLE (UsedPageTableEntries); 01203 01204 // 01205 // One less private page (it's now shared). 01206 // 01207 01208 CurrentProcess->NumberOfPrivatePages -= 1; 01209 01210 ForkProtoPte += 1; 01211 NumberOfForkPtes += 1; 01212 01213 } 01214 01215 } else if (PteContents.u.Soft.Prototype == 1) { 01216 01217 // 01218 // Prototype PTE, check to see if this is a fork 01219 // prototype PTE already. Note that if COW is set, 01220 // the PTE can just be copied (fork compatible format). 01221 // 01222 01223 MI_WRITE_INVALID_PTE (PointerNewPte, PteContents); 01224 01225 // 01226 // A PTE is now non-zero, increment the used page 01227 // table entries counter. 01228 // 01229 01230 MI_INCREMENT_USED_PTES_BY_HANDLE (UsedPageTableEntries); 01231 01232 // 01233 // Check to see if this is a fork prototype PTE, 01234 // and if it is increment the reference count 01235 // which is in the longword following the PTE. 01236 // 01237 01238 CloneProto = (PMMCLONE_BLOCK)(MiPteToProto(PointerPte)); 01239 01240 if (MiLocateCloneAddress ((PVOID)CloneProto) != 01241 (PMMCLONE_DESCRIPTOR)NULL) { 01242 01243 // 01244 // The reference count field, or the prototype PTE 01245 // for that matter may not be in the working set. 01246 // 01247 01248 MiUpCloneProtoRefCount (CloneProto, 01249 CurrentProcess); 01250 01251 if (PAGE_ALIGN (ForkProtoPte) != 01252 PAGE_ALIGN (LockedForkPte)) { 01253 MiUnlockPagedAddress (LockedForkPte, FALSE); 01254 LockedForkPte = ForkProtoPte; 01255 MiLockPagedAddress (LockedForkPte, FALSE); 01256 } 01257 01258 MiMakeSystemAddressValid (PointerPte, 01259 CurrentProcess); 01260 } 01261 01262 } else if (PteContents.u.Soft.Transition == 1) { 01263 01264 // 01265 // Transition. 01266 // 01267 01268 if (MiHandleForkTransitionPte (PointerPte, 01269 PointerNewPte, 01270 ForkProtoPte)) { 01271 // 01272 // PTE is no longer transition, try again. 01273 // 01274 01275 continue; 01276 } 01277 01278 // 01279 // A PTE is now non-zero, increment the used page 01280 // table entries counter. 01281 // 01282 01283 MI_INCREMENT_USED_PTES_BY_HANDLE (UsedPageTableEntries); 01284 01285 // 01286 // One less private page (it's now shared). 01287 // 01288 01289 CurrentProcess->NumberOfPrivatePages -= 1; 01290 01291 ForkProtoPte += 1; 01292 NumberOfForkPtes += 1; 01293 01294 } else { 01295 01296 // 01297 // Page file format (may be demand zero). 01298 // 01299 01300 if (IS_PTE_NOT_DEMAND_ZERO (PteContents)) { 01301 01302 if (PteContents.u.Soft.Protection == MM_DECOMMIT) { 01303 01304 // 01305 // This is a decommitted PTE, just move it 01306 // over to the new process. Don't increment 01307 // the count of private pages. 01308 // 01309 01310 MI_WRITE_INVALID_PTE (PointerNewPte, PteContents); 01311 } else { 01312 01313 // 01314 // The PTE is not demand zero, move the PTE to 01315 // a fork prototype PTE and make this PTE and 01316 // the new processes PTE refer to the fork 01317 // prototype PTE. 01318 // 01319 01320 ForkProtoPte->ProtoPte = PteContents; 01321 01322 // 01323 // Make the protection write-copy if writable. 01324 // 01325 01326 MI_MAKE_PROTECT_WRITE_COPY (ForkProtoPte->ProtoPte); 01327 01328 ForkProtoPte->CloneRefCount = 2; 01329 01330 TempPte.u.Long = 01331 MiProtoAddressForPte (&ForkProtoPte->ProtoPte); 01332 01333 TempPte.u.Proto.Prototype = 1; 01334 01335 MI_WRITE_INVALID_PTE (PointerPte, TempPte); 01336 MI_WRITE_INVALID_PTE (PointerNewPte, TempPte); 01337 01338 // 01339 // One less private page (it's now shared). 01340 // 01341 01342 CurrentProcess->NumberOfPrivatePages -= 1; 01343 01344 ForkProtoPte += 1; 01345 NumberOfForkPtes += 1; 01346 } 01347 } else { 01348 01349 // 01350 // The page is demand zero, make the new process's 01351 // page demand zero. 01352 // 01353 01354 MI_WRITE_INVALID_PTE (PointerNewPte, PteContents); 01355 } 01356 01357 // 01358 // A PTE is now non-zero, increment the used page 01359 // table entries counter. 01360 // 01361 01362 MI_INCREMENT_USED_PTES_BY_HANDLE (UsedPageTableEntries); 01363 } 01364 01365 PointerPte += 1; 01366 PointerNewPte += 1; 01367 01368 } // end while for PTEs 01369 AllDone: 01370 NewVad = NewVad->Parent; 01371 } 01372 Vad = MiGetNextVad (Vad); 01373 01374 } // end while for VADs 01375 01376 // 01377 // Unlock paged pool page. 01378 // 01379 01380 MiUnlockPagedAddress (LockedForkPte, FALSE); 01381 01382 // 01383 // Unmap the PD Page and hyper space page. 01384 // 01385 01386 #if defined (_WIN64) 01387 MiUnmapSinglePage (PpeBase); 01388 #endif 01389 01390 #if !defined (_X86PAE_) 01391 MiUnmapSinglePage (PdeBase); 01392 #else 01393 MmUnmapLockedPages (PdeBase, MdlPageDirectory); 01394 #endif 01395 01396 #if !defined (_WIN64) 01397 MiUnmapSinglePage (HyperBase); 01398 #endif 01399 01400 MiUnmapSinglePage (NewPteMappedAddress); 01401 01402 #if defined (_WIN64) 01403 MiDownPfnReferenceCount (RootPhysicalPage, 1); 01404 #endif 01405 01406 #if defined (_X86PAE_) 01407 for (i = 0; i < PD_PER_SYSTEM; i += 1) { 01408 MiDownPfnReferenceCount (PageDirectoryFrames[i], 1); 01409 } 01410 #else 01411 MiDownPfnReferenceCount (MdlDirPage, 1); 01412 #endif 01413 01414 #if !defined (_WIN64) 01415 MiDownPfnReferenceCount (HyperPhysicalPage, 1); 01416 #endif 01417 01418 MiDownPfnReferenceCount (MdlPage, 1); 01419 01420 // 01421 // Make the count of private pages match between the two processes. 01422 // 01423 01424 ASSERT ((SPFN_NUMBER)CurrentProcess->NumberOfPrivatePages >= 0); 01425 01426 ProcessToInitialize->NumberOfPrivatePages = 01427 CurrentProcess->NumberOfPrivatePages; 01428 01429 ASSERT (NumberOfForkPtes <= CloneDescriptor->NumberOfPtes); 01430 01431 if (NumberOfForkPtes != 0) { 01432 01433 // 01434 // The number of fork PTEs is non-zero, set the values 01435 // into the structures. 01436 // 01437 01438 CloneHeader->NumberOfPtes = NumberOfForkPtes; 01439 CloneDescriptor->NumberOfReferences = NumberOfForkPtes; 01440 CloneDescriptor->NumberOfPtes = NumberOfForkPtes; 01441 01442 } else { 01443 01444 // 01445 // There were no fork PTEs created. Remove the clone descriptor 01446 // from this process and clean up the related structures. 01447 // Note - must be holding the working set mutex and not holding 01448 // the PFN lock. 01449 // 01450 01451 MiRemoveClone (CloneDescriptor); 01452 01453 UNLOCK_WS (CurrentProcess); 01454 01455 ExFreePool (CloneDescriptor->CloneHeader->ClonePtes); 01456 01457 ExFreePool (CloneDescriptor->CloneHeader); 01458 01459 // 01460 // Return the pool for the global structures referenced by the 01461 // clone descriptor. 01462 // 01463 01464 PsReturnPoolQuota (CurrentProcess, 01465 PagedPool, 01466 CloneDescriptor->PagedPoolQuotaCharge); 01467 01468 PsReturnPoolQuota (CurrentProcess, NonPagedPool, sizeof(MMCLONE_HEADER)); 01469 01470 ExFreePool (CloneDescriptor); 01471 01472 LOCK_WS (CurrentProcess); 01473 } 01474 01475 MiDownShareCountFlushEntireTb (PageFrameIndex); 01476 01477 #if defined (_WIN64) 01478 MiDownShareCountFlushEntireTb (PageDirFrameIndex); 01479 #endif 01480 01481 PageFrameIndex = (PFN_NUMBER)-1; 01482 PageDirFrameIndex = (PFN_NUMBER)-1; 01483 01484 // 01485 // Copy the clone descriptors from this process to the new process. 01486 // 01487 01488 Clone = MiGetFirstClone (); 01489 CloneList = &FirstNewClone; 01490 CloneFailed = FALSE; 01491 01492 while (Clone != (PMMCLONE_DESCRIPTOR)NULL) { 01493 01494 // 01495 // Increment the count of processes referencing this clone block. 01496 // 01497 01498 MiUpCloneProcessRefCount (Clone); 01499 01500 do { 01501 NewClone = ExAllocatePoolWithTag (NonPagedPool, 01502 sizeof( MMCLONE_DESCRIPTOR), 01503 ' mM'); 01504 01505 if (NewClone != NULL) { 01506 break; 01507 } 01508 01509 // 01510 // There are insufficient resources to continue this operation, 01511 // however, to properly clean up at this point, all the 01512 // clone headers must be allocated, so when the cloned process 01513 // is deleted, the clone headers will be found. if the pool 01514 // is not readily available, loop periodically trying for it. 01515 // Force the clone operation to fail so the pool will soon be 01516 // released. 01517 // 01518 01519 CloneFailed = TRUE; 01520 status = STATUS_INSUFFICIENT_RESOURCES; 01521 01522 KeDelayExecutionThread (KernelMode, 01523 FALSE, 01524 (PLARGE_INTEGER)&MmShortTime); 01525 continue; 01526 } while (TRUE); 01527 01528 *NewClone = *Clone; 01529 01530 *CloneList = NewClone; 01531 CloneList = &NewClone->Parent; 01532 Clone = MiGetNextClone (Clone); 01533 } 01534 01535 *CloneList = (PMMCLONE_DESCRIPTOR)NULL; 01536 01537 // 01538 // Release the working set mutex and the address creation mutex from 01539 // the current process as all the necessary information is now 01540 // captured. 01541 // 01542 01543 UNLOCK_WS (CurrentProcess); 01544 01545 CurrentProcess->ForkInProgress = NULL; 01546 01547 UNLOCK_ADDRESS_SPACE (CurrentProcess); 01548 01549 // 01550 // As we have updated many PTEs to clear dirty bits, flush the 01551 // TB cache. Note that this was not done every time we changed 01552 // a valid PTE so other threads could be modifying the address 01553 // space without causing copy on writes. (Too bad). 01554 // 01555 01556 01557 // 01558 // Attach to the process to initialize and insert the vad and clone 01559 // descriptors into the tree. 01560 // 01561 01562 if (Attached) { 01563 KeDetachProcess (); 01564 Attached = FALSE; 01565 } 01566 01567 if (PsGetCurrentProcess() != ProcessToInitialize) { 01568 Attached = TRUE; 01569 KeAttachProcess (&ProcessToInitialize->Pcb); 01570 } 01571 01572 CurrentProcess = ProcessToInitialize; 01573 01574 // 01575 // We are now in the context of the new process, build the 01576 // VAD list and the clone list. 01577 // 01578 01579 Vad = FirstNewVad; 01580 VadInsertFailed = FALSE; 01581 01582 LOCK_WS (CurrentProcess); 01583 01584 while (Vad != (PMMVAD)NULL) { 01585 01586 NextVad = Vad->Parent; 01587 01588 try { 01589 01590 if (VadInsertFailed) { 01591 Vad->u.VadFlags.CommitCharge = MM_MAX_COMMIT; 01592 } 01593 01594 MiInsertVad (Vad); 01595 01596 } except (EXCEPTION_EXECUTE_HANDLER) { 01597 01598 // 01599 // Charging quota for the VAD failed, set the 01600 // remaining quota fields in this VAD and all 01601 // subsequent VADs to zero so the VADs can be 01602 // inserted and later deleted. 01603 // 01604 01605 VadInsertFailed = TRUE; 01606 status = GetExceptionCode(); 01607 01608 // 01609 // Do the loop again for this VAD. 01610 // 01611 01612 continue; 01613 } 01614 01615 // 01616 // Update the current virtual size. 01617 // 01618 01619 CurrentProcess->VirtualSize += PAGE_SIZE + 01620 ((Vad->EndingVpn - Vad->StartingVpn) >> PAGE_SHIFT); 01621 01622 Vad = NextVad; 01623 } 01624 01625 UNLOCK_WS (CurrentProcess); 01626 //MmUnlockCode (MiCloneProcessAddressSpace, 5000); 01627 01628 // 01629 // Update the peak virtual size. 01630 // 01631 01632 CurrentProcess->PeakVirtualSize = CurrentProcess->VirtualSize; 01633 01634 Clone = FirstNewClone; 01635 TotalPagedPoolCharge = 0; 01636 TotalNonPagedPoolCharge = 0; 01637 01638 while (Clone != (PMMCLONE_DESCRIPTOR)NULL) { 01639 01640 NextClone = Clone->Parent; 01641 MiInsertClone (Clone); 01642 01643 // 01644 // Calculate the page pool and non-paged pool to charge for these 01645 // operations. 01646 // 01647 01648 TotalPagedPoolCharge += Clone->PagedPoolQuotaCharge; 01649 TotalNonPagedPoolCharge += sizeof(MMCLONE_HEADER); 01650 01651 Clone = NextClone; 01652 } 01653 01654 if (CloneFailed || VadInsertFailed) { 01655 01656 CurrentProcess->ForkWasSuccessful = MM_FORK_FAILED; 01657 01658 if (Attached) { 01659 KeDetachProcess (); 01660 } 01661 KdPrint(("MMFORK: vad insert failed\n")); 01662 01663 return status; 01664 } 01665 01666 try { 01667 01668 PageTablePage = 1; 01669 PsChargePoolQuota (CurrentProcess, PagedPool, TotalPagedPoolCharge); 01670 PageTablePage = 0; 01671 PsChargePoolQuota (CurrentProcess, NonPagedPool, TotalNonPagedPoolCharge); 01672 01673 } except (EXCEPTION_EXECUTE_HANDLER) { 01674 01675 if (PageTablePage == 0) { 01676 PsReturnPoolQuota (CurrentProcess, PagedPool, TotalPagedPoolCharge); 01677 } 01678 KdPrint(("MMFORK: pool quota failed\n")); 01679 01680 CurrentProcess->ForkWasSuccessful = MM_FORK_FAILED; 01681 01682 if (Attached) { 01683 KeDetachProcess (); 01684 } 01685 return GetExceptionCode(); 01686 } 01687 01688 ASSERT (ProcessToClone->ForkWasSuccessful == MM_FORK_SUCCEEDED); 01689 ASSERT (CurrentProcess->ForkWasSuccessful == MM_FORK_SUCCEEDED); 01690 01691 if (Attached) { 01692 KeDetachProcess (); 01693 } 01694 01695 #if DBG 01696 if (MmDebug & MM_DBG_FORK) { 01697 DbgPrint("ending clone operation process to clone = %lx\n", 01698 ProcessToClone); 01699 } 01700 #endif //DBG 01701 01702 return STATUS_SUCCESS; 01703 01704 // 01705 // Error returns. 01706 // 01707 01708 ErrorReturn4: 01709 if (PageTablePage == 2) { 01710 NOTHING; 01711 } 01712 else if (PageTablePage == 1) { 01713 PsReturnPoolQuota (CurrentProcess, PagedPool, sizeof(MMCLONE_BLOCK) * 01714 NumberOfPrivatePages); 01715 } 01716 else { 01717 ASSERT (PageTablePage == 0); 01718 PsReturnPoolQuota (CurrentProcess, PagedPool, sizeof(MMCLONE_BLOCK) * 01719 NumberOfPrivatePages); 01720 PsReturnPoolQuota (CurrentProcess, NonPagedPool, sizeof(MMCLONE_HEADER)); 01721 } 01722 01723 NewVad = FirstNewVad; 01724 while (NewVad != NULL) { 01725 Vad = NewVad->Parent; 01726 ExFreePool (NewVad); 01727 NewVad = Vad; 01728 } 01729 01730 ExFreePool (CloneDescriptor); 01731 ErrorReturn3: 01732 ExFreePool (CloneHeader); 01733 ErrorReturn2: 01734 ExFreePool (CloneProtos); 01735 ErrorReturn1: 01736 UNLOCK_ADDRESS_SPACE (CurrentProcess); 01737 ASSERT (CurrentProcess->ForkWasSuccessful == MM_FORK_SUCCEEDED); 01738 if (Attached) { 01739 KeDetachProcess (); 01740 } 01741 return status; 01742 }

VOID MiContractPagingFiles VOID   ) 
 

Definition at line 1864 of file modwrite.c.

References _MMPAGE_FILE_EXPANSION::DereferenceList, ExAllocatePoolWithTag, FALSE, _MMPAGING_FILE::FreeSpace, KeReleaseSemaphore(), L, _MMDEREFERENCE_SEGMENT_HEADER::ListHead, _MMDEREFERENCE_SEGMENT_HEADER::Lock, _MMPAGING_FILE::MinimumSize, MmChargeCommitmentLock, MmDereferenceSegmentHeader, MmMinimumPageFileReduction, MmNumberOfPagingFiles, MmPagingFile, MmTotalCommitLimit, MmTotalCommittedPages, NonPagedPool, NULL, _MMPAGE_FILE_EXPANSION::RequestedExpansionSize, _MMPAGE_FILE_EXPANSION::Segment, _MMDEREFERENCE_SEGMENT_HEADER::Semaphore, _MMPAGING_FILE::Size, and TRUE.

Referenced by MmDeleteProcessAddressSpace().

01870 : 01871 01872 This routine checks to see if ample space is no longer committed 01873 and if so, does enough free space exist in any paging file. IF 01874 the answer to both these is affirmative, a reduction in the 01875 paging file size(s) is attempted. 01876 01877 Arguments: 01878 01879 None. 01880 01881 Return Value: 01882 01883 None. 01884 01885 --*/ 01886 01887 { 01888 BOOLEAN Reduce; 01889 PMMPAGE_FILE_EXPANSION PageReduce; 01890 KIRQL OldIrql; 01891 ULONG i; 01892 01893 Reduce = FALSE; 01894 01895 ExAcquireSpinLock (&MmChargeCommitmentLock, &OldIrql); 01896 01897 if ((MmTotalCommitLimit - MmMinimumPageFileReduction) > 01898 MmTotalCommittedPages) { 01899 01900 for (i = 0;i < MmNumberOfPagingFiles; i += 1) { 01901 if (MmPagingFile[i]->Size != MmPagingFile[i]->MinimumSize) { 01902 if (MmPagingFile[i]->FreeSpace > MmMinimumPageFileReduction) { 01903 Reduce = TRUE; 01904 break; 01905 } 01906 } 01907 } 01908 01909 ExReleaseSpinLock (&MmChargeCommitmentLock, OldIrql); 01910 01911 if (!Reduce) { 01912 return; 01913 } 01914 01915 PageReduce = ExAllocatePoolWithTag (NonPagedPool, 01916 sizeof(MMPAGE_FILE_EXPANSION), 01917 ' mM'); 01918 01919 if (PageReduce == NULL) { 01920 return; 01921 } 01922 01923 PageReduce->Segment = NULL; 01924 PageReduce->RequestedExpansionSize = 0xFFFFFFFF; 01925 01926 ExAcquireSpinLock (&MmDereferenceSegmentHeader.Lock, &OldIrql); 01927 InsertTailList ( &MmDereferenceSegmentHeader.ListHead, 01928 &PageReduce->DereferenceList); 01929 ExReleaseSpinLock (&MmDereferenceSegmentHeader.Lock, OldIrql); 01930 01931 KeReleaseSemaphore (&MmDereferenceSegmentHeader.Semaphore, 0L, 1L, FALSE); 01932 return; 01933 } 01934 01935 ExReleaseSpinLock (&MmChargeCommitmentLock, OldIrql); 01936 return; 01937 }

NTSTATUS FASTCALL MiCopyOnWrite IN PVOID  FaultingAddress,
IN PMMPTE  PointerPte
 

Definition at line 25 of file wrtfault.c.

References ASSERT, _MMINFO_COUNTERS::CopyOnWriteCount, DbgPrint, _MMWSLE::e1, FALSE, _EPROCESS::ForkInProgress, KeFlushSingleTb(), LOCK_PFN, MI_CAPTURE_DIRTY_BIT_TO_PFN, MI_GET_PAGE_FRAME_FROM_PTE, MI_GET_SECONDARY_COLOR, MI_MAKE_PROTECT_NOT_WRITE_COPY, MI_PFN_ELEMENT, MI_SET_ACCESSED_IN_PTE, MI_SET_PTE_DIRTY, MI_WRITE_VALID_PTE_NEW_PROTECTION, MiDecrementCloneBlockReference(), MiDecrementShareCount(), MiEnsureAvailablePageOrWait(), MiFormatPfn(), MiFormatPte(), MiGetPteAddress, MiGetVirtualAddressMappedByPte, MiInitializeCopyOnWritePfn(), MiLocateCloneAddress, MiLocateWsle(), MiMapPageInHyperSpace(), MiReleasePageFileSpace(), MiRemoveAnyPage(), MiUnmapPageInHyperSpace, MiWaitForForkToComplete(), MM_DBG_PTE_UPDATE, MM_DBG_WRITEFAULT, MmInfoCounters, MmWorkingSetList, MmWsle, NULL, _EPROCESS::NumberOfPrivatePages, _MMPFN::OriginalPte, PAGE_SIZE, PERFINFO_PRIVATE_COPY_ON_WRITE, _MMWSLENTRY::Protection, PsGetCurrentProcess, PsGetCurrentThread, _MMPFN::PteAddress, _MMPFN::PteFrame, TRUE, _MMPTE::u, _MMPFN::u1, _MMPFN::u2, _MMPFN::u3, UNLOCK_PFN, WSLE_NULL_INDEX, and WSLE_NUMBER.

Referenced by MiProtectVirtualMemory(), MiSetProtectionOnSection(), and MmAccessFault().

00032 : 00033 00034 This routine performs a copy on write operation for the specified 00035 virtual address. 00036 00037 Arguments: 00038 00039 FaultingAddress - Supplies the virtual address which caused the 00040 fault. 00041 00042 PointerPte - Supplies the pointer to the PTE which caused the 00043 page fault. 00044 00045 00046 Return Value: 00047 00048 Returns the status of the fault handling operation. Can be one of: 00049 - Success. 00050 - In-page Error. 00051 00052 Environment: 00053 00054 Kernel mode, APC's disabled, Working set mutex held. 00055 00056 --*/ 00057 00058 { 00059 MMPTE TempPte; 00060 PFN_NUMBER PageFrameIndex; 00061 PFN_NUMBER NewPageIndex; 00062 PULONG CopyTo; 00063 PULONG CopyFrom; 00064 KIRQL OldIrql; 00065 PMMPFN Pfn1; 00066 // PMMPTE PointerPde; 00067 PEPROCESS CurrentProcess; 00068 PMMCLONE_BLOCK CloneBlock; 00069 PMMCLONE_DESCRIPTOR CloneDescriptor; 00070 PVOID VirtualAddress; 00071 WSLE_NUMBER WorkingSetIndex; 00072 LOGICAL FakeCopyOnWrite; 00073 00074 FakeCopyOnWrite = FALSE; 00075 00076 // 00077 // This is called from MmAccessFault, the PointerPte is valid 00078 // and the working set mutex ensures it cannot change state. 00079 // 00080 00081 #if DBG 00082 if (MmDebug & MM_DBG_WRITEFAULT) { 00083 DbgPrint("**copy on write Fault va %lx proc %lx thread %lx\n", 00084 (ULONG_PTR)FaultingAddress, 00085 (ULONG_PTR)PsGetCurrentProcess(), (ULONG_PTR)PsGetCurrentThread()); 00086 } 00087 00088 if (MmDebug & MM_DBG_PTE_UPDATE) { 00089 MiFormatPte(PointerPte); 00090 } 00091 #endif //DBG 00092 00093 ASSERT (PsGetCurrentProcess()->ForkInProgress == NULL); 00094 00095 // 00096 // Capture the PTE contents to TempPte. 00097 // 00098 00099 TempPte = *PointerPte; 00100 00101 // 00102 // Check to see if this is a prototype PTE with copy on write 00103 // enabled. 00104 // 00105 00106 if (TempPte.u.Hard.CopyOnWrite == 0) { 00107 00108 // 00109 // This is a fork page which is being made private in order 00110 // to change the protection of the page. 00111 // Do not make the page writable. 00112 // 00113 00114 FakeCopyOnWrite = TRUE; 00115 } 00116 00117 PageFrameIndex = MI_GET_PAGE_FRAME_FROM_PTE (&TempPte); 00118 Pfn1 = MI_PFN_ELEMENT (PageFrameIndex); 00119 CurrentProcess = PsGetCurrentProcess(); 00120 00121 // 00122 // Acquire the PFN mutex. 00123 // 00124 00125 VirtualAddress = MiGetVirtualAddressMappedByPte (PointerPte); 00126 WorkingSetIndex = MiLocateWsle (VirtualAddress, MmWorkingSetList, 00127 Pfn1->u1.WsIndex); 00128 00129 LOCK_PFN (OldIrql); 00130 00131 // 00132 // The page must be copied into a new page. 00133 // 00134 00135 // 00136 // If a fork operation is in progress and the faulting thread 00137 // is not the thread performing the fork operation, block until 00138 // the fork is completed. 00139 // 00140 00141 if ((CurrentProcess->ForkInProgress != NULL) && 00142 (CurrentProcess->ForkInProgress != PsGetCurrentThread())) { 00143 MiWaitForForkToComplete (CurrentProcess); 00144 UNLOCK_PFN (OldIrql); 00145 return STATUS_SUCCESS; 00146 } 00147 00148 if (MiEnsureAvailablePageOrWait(CurrentProcess, NULL)) { 00149 00150 // 00151 // A wait operation was performed to obtain an available 00152 // page and the working set mutex and pfn mutexes have 00153 // been released and various things may have changed for 00154 // the worse. Rather than examine all the conditions again, 00155 // return and if things are still proper, the fault we 00156 // be taken again. 00157 // 00158 00159 UNLOCK_PFN (OldIrql); 00160 return STATUS_SUCCESS; 00161 } 00162 00163 // 00164 // Increment the number of private pages. 00165 // 00166 00167 CurrentProcess->NumberOfPrivatePages += 1; 00168 00169 MmInfoCounters.CopyOnWriteCount += 1; 00170 00171 // 00172 // A page is being copied and made private, the global state of 00173 // the shared page needs to be updated at this point on certain 00174 // hardware. This is done by ORing the dirty bit into the modify bit in 00175 // the PFN element. 00176 // 00177 00178 MI_CAPTURE_DIRTY_BIT_TO_PFN (PointerPte, Pfn1); 00179 00180 // 00181 // This must be a prototype PTE. Perform the copy on write. 00182 // 00183 00184 #if DBG 00185 if (Pfn1->u3.e1.PrototypePte == 0) { 00186 DbgPrint("writefault - PTE indicates cow but not protopte\n"); 00187 MiFormatPte(PointerPte); 00188 MiFormatPfn(Pfn1); 00189 } 00190 #endif 00191 00192 CloneBlock = (PMMCLONE_BLOCK)Pfn1->PteAddress; 00193 00194 // 00195 // If the share count for the physical page is one, the reference 00196 // count is one, and the modified flag is clear the current page 00197 // can be stolen to satisfy the copy on write. 00198 // 00199 00200 #if 0 00201 // COMMENTED OUT **************************************************** 00202 // COMMENTED OUT **************************************************** 00203 // COMMENTED OUT **************************************************** 00204 if ((Pfn1->u2.ShareCount == 1) && (Pfn1->u3.e2.ReferenceCount == 1) 00205 && (Pfn1->u3.e1.Modified == 0)) { 00206 00207 // 00208 // Make this page a private page and return the prototype 00209 // PTE into its original contents. The PFN database for 00210 // this page now points to this PTE. 00211 // 00212 00213 // 00214 // Note that a page fault could occur referencing the prototype 00215 // PTE, so we map it into hyperspace to prevent a fault. 00216 // 00217 00218 MiRestorePrototypePte (Pfn1); 00219 00220 Pfn1->PteAddress = PointerPte; 00221 00222 // 00223 // Get the protection for the page. 00224 // 00225 00226 VirtualAddress = MiGetVirtualAddressMappedByPte (PointerPte); 00227 WorkingSetIndex = MiLocateWsle (VirtualAddress, MmWorkingSetList, 00228 Pfn1->u1.WsIndex); 00229 00230 ASSERT (WorkingSetIndex != WSLE_NULL_INDEX) { 00231 00232 Pfn1->OriginalPte.u.Long = 0; 00233 Pfn1->OriginalPte.u.Soft.Protection = 00234 MI_MAKE_PROTECT_NOT_WRITE_COPY ( 00235 MmWsle[WorkingSetIndex].u1.e1.Protection); 00236 00237 PointerPde = MiGetPteAddress(PointerPte); 00238 Pfn1->u3.e1.PrototypePte = 0; 00239 Pfn1->PteFrame = MI_GET_PAGE_FRAME_FROM_PTE (PointerPde); 00240 00241 if (!FakeCopyOnWrite) { 00242 00243 // 00244 // If the page was Copy On Write and stolen or if the page was not 00245 // copy on write, update the PTE setting both the dirty bit and the 00246 // accessed bit. Note, that as this PTE is in the TB, the TB must 00247 // be flushed. 00248 // 00249 00250 MI_SET_PTE_DIRTY (TempPte); 00251 TempPte.u.Hard.Write = 1; 00252 MI_SET_ACCESSED_IN_PTE (&TempPte, 1); 00253 TempPte.u.Hard.CopyOnWrite = 0; 00254 MI_WRITE_VALID_PTE_NEW_PROTECTION (PointerPte, TempPte); 00255 00256 // 00257 // This is a copy on write operation, set the modify bit 00258 // in the PFN database and deallocate any page file space. 00259 // 00260 00261 Pfn1->u3.e1.Modified = 1; 00262 00263 if ((Pfn1->OriginalPte.u.Soft.Prototype == 0) && 00264 (Pfn1->u3.e1.WriteInProgress == 0)) { 00265 00266 // 00267 // This page is in page file format, deallocate the page 00268 // file space. 00269 // 00270 00271 MiReleasePageFileSpace (Pfn1->OriginalPte); 00272 00273 // 00274 // Change original PTE to indicate no page file space is 00275 // reserved, otherwise the space will be deallocated when 00276 // the PTE is deleted. 00277 // 00278 00279 Pfn1->OriginalPte.u.Soft.PageFileHigh = 0; 00280 } 00281 } 00282 00283 // 00284 // The TB entry must be flushed as the valid PTE with the dirty 00285 // bit clear has been fetched into the TB. If it isn't flushed, 00286 // another fault is generated as the dirty bit is not set in 00287 // the cached TB entry. 00288 // 00289 00290 00291 KeFillEntryTb ((PHARDWARE_PTE)PointerPte, FaultingAddress, TRUE); 00292 00293 CloneDescriptor = MiLocateCloneAddress ((PVOID)CloneBlock); 00294 00295 if (CloneDescriptor != (PMMCLONE_DESCRIPTOR)NULL) { 00296 00297 // 00298 // Decrement the reference count for the clone block, 00299 // note that this could release and reacquire 00300 // the mutexes. 00301 // 00302 00303 MiDecrementCloneBlockReference ( CloneDescriptor, 00304 CloneBlock, 00305 CurrentProcess ); 00306 } 00307 00308 ] else [ 00309 00310 // ABOVE COMMENTED OUT **************************************************** 00311 // ABOVE COMMENTED OUT **************************************************** 00312 #endif 00313 00314 // 00315 // Get a new page with the same color as this page. 00316 // 00317 00318 NewPageIndex = MiRemoveAnyPage ( 00319 MI_GET_SECONDARY_COLOR (PageFrameIndex, 00320 Pfn1)); 00321 MiInitializeCopyOnWritePfn (NewPageIndex, PointerPte, WorkingSetIndex, NULL); 00322 00323 UNLOCK_PFN (OldIrql); 00324 00325 CopyTo = (PULONG)MiMapPageInHyperSpace (NewPageIndex, &OldIrql); 00326 00327 #if defined(_MIALT4K_) 00328 00329 // 00330 // Should avoid accessing the user space. Accessing the user space may potentially 00331 // cause a page fault on the alternate table. 00332 // 00333 00334 CopyFrom = KSEG_ADDRESS(PointerPte->u.Hard.PageFrameNumber); 00335 00336 #else 00337 CopyFrom = (PULONG)MiGetVirtualAddressMappedByPte (PointerPte); 00338 #endif 00339 00340 RtlCopyMemory ( CopyTo, CopyFrom, PAGE_SIZE); 00341 00342 PERFINFO_PRIVATE_COPY_ON_WRITE(CopyFrom, PAGE_SIZE); 00343 00344 MiUnmapPageInHyperSpace (OldIrql); 00345 00346 if (!FakeCopyOnWrite) { 00347 00348 // 00349 // If the page was really a copy on write page, make it 00350 // accessed, dirty and writable. Also, clear the copy-on-write 00351 // bit in the PTE. 00352 // 00353 00354 MI_SET_PTE_DIRTY (TempPte); 00355 TempPte.u.Hard.Write = 1; 00356 MI_SET_ACCESSED_IN_PTE (&TempPte, 1); 00357 TempPte.u.Hard.CopyOnWrite = 0; 00358 TempPte.u.Hard.PageFrameNumber = NewPageIndex; 00359 00360 } else { 00361 00362 // 00363 // The page was not really a copy on write, just change 00364 // the frame field of the PTE. 00365 // 00366 00367 TempPte.u.Hard.PageFrameNumber = NewPageIndex; 00368 } 00369 00370 // 00371 // If the modify bit is set in the PFN database for the 00372 // page, the data cache must be flushed. This is due to the 00373 // fact that this process may have been cloned and the cache 00374 // still contains stale data destined for the page we are 00375 // going to remove. 00376 // 00377 00378 ASSERT (TempPte.u.Hard.Valid == 1); 00379 00380 LOCK_PFN (OldIrql); 00381 00382 // 00383 // Flush the TB entry for this page. 00384 // 00385 00386 KeFlushSingleTb (FaultingAddress, 00387 TRUE, 00388 FALSE, 00389 (PHARDWARE_PTE)PointerPte, 00390 TempPte.u.Flush); 00391 00392 // 00393 // Decrement the share count for the page which was copied 00394 // as this pte no longer refers to it. 00395 // 00396 00397 MiDecrementShareCount (PageFrameIndex); 00398 00399 CloneDescriptor = MiLocateCloneAddress ((PVOID)CloneBlock); 00400 00401 if (CloneDescriptor != (PMMCLONE_DESCRIPTOR)NULL) { 00402 00403 // 00404 // Decrement the reference count for the clone block, 00405 // note that this could release and reacquire 00406 // the mutexes. 00407 // 00408 00409 MiDecrementCloneBlockReference ( CloneDescriptor, 00410 CloneBlock, 00411 CurrentProcess ); 00412 } 00413 00414 UNLOCK_PFN (OldIrql); 00415 return STATUS_SUCCESS; 00416 } }

NTSTATUS MiCreateDataFileMap IN PFILE_OBJECT  File,
OUT PSEGMENT Segment,
IN PUINT64  MaximumSize,
IN ULONG  SectionPageProtection,
IN ULONG  AllocationAttributes,
IN ULONG  IgnoreFileSizing
 

Definition at line 3553 of file creasect.c.

References ASSERT, _SUBSECTION::ControlArea, EX_REAL_POOL_USAGE, ExAllocatePoolWithTag, ExFreePool(), FALSE, File, _CONTROL_AREA::FilePointer, FsRtlGetFileSize(), FsRtlSetFileSize(), Mi4KStartForSubsection, MI_MAXIMUM_SECTION_SIZE, MiFillMemoryPte, MiGetSubsectionAddressForPte, MM4K_MASK, MM4K_SHIFT, MM_ALLOCATION_FRAGMENT, MM_EXECUTE_READWRITE, MM_PROTO_PTE_ALIGNMENT, MMPTE, MMSECT, _SUBSECTION::NextSubsection, NonPagedPool, NT_SUCCESS, NTSTATUS(), NULL, _SUBSECTION::NumberOfFullSectors, _CONTROL_AREA::NumberOfSectionReferences, _CONTROL_AREA::NumberOfSubsections, _CONTROL_AREA::NumberOfUserReferences, PAGE_SHIFT, PAGE_SIZE, PAGED_CODE, PagedPool, _CONTROL_AREA::PagedPoolUsage, PTE_SHIFT, _SUBSECTION::PtesInSubsection, ROUND_TO_PAGES, SEGMENT, _CONTROL_AREA::Segment, Size, Status, SUBSECTION, _SUBSECTION::SubsectionBase, TRUE, _SUBSECTION::u, _MMPTE::u, _CONTROL_AREA::u, _SUBSECTION::UnusedPtes, USHORT, and X64K.

Referenced by MmCreateSection().

03564 : 03565 03566 This function creates the necessary structures to allow the mapping 03567 of a data file. 03568 03569 The data file is accessed to verify desired access, a segment 03570 object is created and initialized. 03571 03572 Arguments: 03573 03574 File - Supplies the file object for the image file. 03575 03576 Segment - Returns the segment object. 03577 03578 FileHandle - Supplies the handle to the image file. 03579 03580 MaximumSize - Supplies the maximum size for the mapping. 03581 03582 SectionPageProtection - Supplies the initial page protection. 03583 03584 AllocationAttributes - Supplies the allocation attributes for the 03585 mapping. 03586 03587 Return Value: 03588 03589 Returns the status value. 03590 03591 TBS 03592 03593 03594 --*/ 03595 03596 { 03597 03598 NTSTATUS Status; 03599 ULONG NumberOfPtes; 03600 ULONG SizeOfSegment; 03601 ULONG j; 03602 ULONG Size; 03603 ULONG PartialSize; 03604 ULONG First; 03605 PCONTROL_AREA ControlArea; 03606 PSEGMENT NewSegment; 03607 PSUBSECTION Subsection; 03608 PSUBSECTION ExtendedSubsection; 03609 PMMPTE PointerPte; 03610 MMPTE TempPte; 03611 ULONG NumberOfPtesWithAlignment; 03612 UINT64 EndOfFile; 03613 UINT64 LastFileChunk; 03614 UINT64 FileOffset; 03615 UINT64 NumberOfPtesForEntireFile; 03616 ULONG ExtendedSubsections; 03617 PSUBSECTION FirstSubsection; 03618 PSUBSECTION Last; 03619 ULONG NumberOfNewSubsections; 03620 03621 PAGED_CODE(); 03622 03623 ExtendedSubsections = 0; 03624 FirstSubsection = NULL; 03625 NumberOfNewSubsections = 0; 03626 03627 // ************************************************************* 03628 // Create mapped file section. 03629 // ************************************************************* 03630 03631 if (!IgnoreFileSizing) { 03632 03633 Status = FsRtlGetFileSize (File, (PLARGE_INTEGER)&EndOfFile); 03634 03635 if (Status == STATUS_FILE_IS_A_DIRECTORY) { 03636 03637 // 03638 // Can't map a directory as a section. Return error. 03639 // 03640 03641 return STATUS_INVALID_FILE_FOR_SECTION; 03642 } 03643 03644 if (!NT_SUCCESS (Status)) { 03645 return Status; 03646 } 03647 03648 if (EndOfFile == 0 && *MaximumSize == 0) { 03649 03650 // 03651 // Can't map a zero length without specifying the maximum 03652 // size as non-zero. 03653 // 03654 03655 return STATUS_MAPPED_FILE_SIZE_ZERO; 03656 } 03657 03658 // 03659 // Make sure this file is big enough for the section. 03660 // 03661 03662 if (*MaximumSize > EndOfFile) { 03663 03664 // 03665 // If the maximum size is greater than the end-of-file, 03666 // and the user did not request page_write or page_execute_readwrite 03667 // to the section, reject the request. 03668 // 03669 03670 if (((SectionPageProtection & PAGE_READWRITE) | 03671 (SectionPageProtection & PAGE_EXECUTE_READWRITE)) == 0) { 03672 03673 return STATUS_SECTION_TOO_BIG; 03674 } 03675 03676 // 03677 // Check to make sure that the allocation size large enough 03678 // to contain all the data, if not set a new allocation size. 03679 // 03680 03681 EndOfFile = *MaximumSize; 03682 03683 Status = FsRtlSetFileSize (File, (PLARGE_INTEGER)&EndOfFile); 03684 03685 if (!NT_SUCCESS (Status)) { 03686 return Status; 03687 } 03688 } 03689 } else { 03690 03691 // 03692 // Ignore the file size, this call is from the cache manager. 03693 // 03694 03695 EndOfFile = *MaximumSize; 03696 } 03697 03698 // 03699 // Calculate the number of prototype PTEs to build for this section. 03700 // 03701 03702 // 03703 // Each subsection is limited to 16TB - 64K because the NumberOfFullSectors 03704 // and various other fields in the subsection are ULONGs. For NT64, the 03705 // allocation could be split into multiple subsections as needed to 03706 // conform to this limit - this is not worth doing for NT32 unless 03707 // sparse prototype PTE allocations are supported. 03708 // 03709 // This must be a multiple of the size of prototype pte allocation so any 03710 // given prototype pte allocation will have the same subsection for all 03711 // PTEs. 03712 // 03713 // The total section size is limited to 16PB - 4K because of the 03714 // StartingSector4132 field in each subsection. 03715 // 03716 03717 NumberOfPtesForEntireFile = (EndOfFile + PAGE_SIZE - 1) >> PAGE_SHIFT; 03718 03719 NumberOfPtes = (ULONG)NumberOfPtesForEntireFile; 03720 03721 if (EndOfFile > MI_MAXIMUM_SECTION_SIZE) { 03722 return STATUS_SECTION_TOO_BIG; 03723 } 03724 03725 if (NumberOfPtesForEntireFile > (UINT64)((MAXULONG_PTR / sizeof(MMPTE)) - sizeof (SEGMENT))) { 03726 return STATUS_SECTION_TOO_BIG; 03727 } 03728 03729 if (NumberOfPtesForEntireFile > EndOfFile) { 03730 return STATUS_SECTION_TOO_BIG; 03731 } 03732 03733 // 03734 // Calculate the number of PTEs to allocate to maintain the 03735 // desired alignment. On x86 and R3000 no additional PTEs are 03736 // needed; on MIPS, the desired alignment is 64k to avoid cache 03737 // problems. 03738 // 03739 03740 NumberOfPtesWithAlignment = (NumberOfPtes + 03741 ((MM_PROTO_PTE_ALIGNMENT >> PAGE_SHIFT) - 1)) & 03742 (~((MM_PROTO_PTE_ALIGNMENT >> PAGE_SHIFT) - 1)); 03743 03744 if (NumberOfPtesWithAlignment < NumberOfPtes) { 03745 return STATUS_SECTION_TOO_BIG; 03746 } 03747 03748 SizeOfSegment = sizeof(SEGMENT) + sizeof(MMPTE) * 03749 (NumberOfPtesWithAlignment - 1); 03750 03751 NewSegment = ExAllocatePoolWithTag (PagedPool, 03752 SizeOfSegment, 03753 MMSECT); 03754 if (NewSegment == NULL) { 03755 03756 // 03757 // The requested pool could not be allocated. 03758 // Try to allocate the memory in smaller sizes. 03759 // 03760 03761 if (SizeOfSegment < MM_ALLOCATION_FRAGMENT) { 03762 return STATUS_INSUFFICIENT_RESOURCES; 03763 } 03764 03765 Size = MM_ALLOCATION_FRAGMENT; 03766 PartialSize = SizeOfSegment; 03767 03768 do { 03769 03770 if (PartialSize < MM_ALLOCATION_FRAGMENT) { 03771 PartialSize = (ULONG) ROUND_TO_PAGES (PartialSize); 03772 Size = PartialSize; 03773 } 03774 03775 NewSegment = ExAllocatePoolWithTag (PagedPool, 03776 Size, 03777 MMSECT); 03778 ExtendedSubsection = ExAllocatePoolWithTag (NonPagedPool, 03779 sizeof(SUBSECTION), 03780 'bSmM'); 03781 03782 if ((NewSegment == NULL) || (ExtendedSubsection == NULL)) { 03783 if (NewSegment) { 03784 ExFreePool (NewSegment); 03785 } 03786 if (ExtendedSubsection) { 03787 ExFreePool (ExtendedSubsection); 03788 } 03789 03790 // 03791 // Free all the previous allocations and return an error. 03792 // 03793 03794 while (FirstSubsection != NULL) { 03795 ExFreePool (FirstSubsection->SubsectionBase); 03796 Last = FirstSubsection->NextSubsection; 03797 ExFreePool (FirstSubsection); 03798 FirstSubsection = Last; 03799 } 03800 return STATUS_INSUFFICIENT_RESOURCES; 03801 } 03802 03803 NumberOfNewSubsections += 1; 03804 RtlZeroMemory (ExtendedSubsection, sizeof(SUBSECTION)); 03805 03806 if (FirstSubsection == NULL) { 03807 FirstSubsection = ExtendedSubsection; 03808 Last = ExtendedSubsection; 03809 NumberOfNewSubsections = 0; 03810 } else { 03811 Last->NextSubsection = ExtendedSubsection; 03812 } 03813 03814 ExtendedSubsection->PtesInSubsection = Size / sizeof(MMPTE); 03815 ExtendedSubsection->SubsectionBase = (PMMPTE)NewSegment; 03816 Last = ExtendedSubsection; 03817 PartialSize -= Size; 03818 } while (PartialSize != 0); 03819 03820 // 03821 // Reset new segment and free the first subsection, as 03822 // the subsection after the control area will become the 03823 // first subsection. 03824 // 03825 03826 NewSegment = (PSEGMENT)FirstSubsection->SubsectionBase; 03827 } 03828 03829 *Segment = NewSegment; 03830 RtlZeroMemory (NewSegment, sizeof(SEGMENT)); 03831 03832 ControlArea = 03833 (PCONTROL_AREA)File->SectionObjectPointer->DataSectionObject; 03834 03835 // 03836 // Control area and first subsection have been zeroed when allocated. 03837 // 03838 03839 ControlArea->Segment = NewSegment; 03840 ControlArea->NumberOfSectionReferences = 1; 03841 03842 if (IgnoreFileSizing == FALSE) { 03843 03844 // 03845 // This reference is not from the cache manager. 03846 // 03847 03848 ControlArea->NumberOfUserReferences = 1; 03849 } 03850 03851 ControlArea->u.Flags.BeingCreated = 1; 03852 ControlArea->u.Flags.File = 1; 03853 03854 if (FILE_REMOTE_DEVICE & File->DeviceObject->Characteristics) { 03855 03856 // 03857 // This file resides on a redirected drive. 03858 // 03859 03860 ControlArea->u.Flags.Networked = 1; 03861 } 03862 03863 if (AllocationAttributes & SEC_NOCACHE) { 03864 ControlArea->u.Flags.NoCache = 1; 03865 } 03866 03867 if (IgnoreFileSizing) { 03868 // Set the was purged flag to indicate that the 03869 // file size was not explicitly set. 03870 // 03871 03872 ControlArea->u.Flags.WasPurged = 1; 03873 } 03874 03875 ControlArea->NumberOfSubsections = (USHORT)(1 + NumberOfNewSubsections); 03876 ControlArea->FilePointer = File; 03877 03878 ASSERT (ControlArea->u.Flags.GlobalOnlyPerSession == 0); 03879 03880 Subsection = (PSUBSECTION)(ControlArea + 1); 03881 03882 if (FirstSubsection) { 03883 03884 Subsection->NextSubsection = FirstSubsection->NextSubsection; 03885 Subsection->PtesInSubsection = FirstSubsection->PtesInSubsection; 03886 ExFreePool (FirstSubsection); 03887 #if DBG 03888 FirstSubsection = NULL; 03889 #endif //DBG 03890 } else { 03891 ASSERT (Subsection->NextSubsection == NULL); 03892 } 03893 03894 First = TRUE; 03895 03896 FileOffset = 0; 03897 03898 do { 03899 03900 // 03901 // Loop through all the subsections and fill in the PTEs. 03902 // 03903 03904 03905 TempPte.u.Long = MiGetSubsectionAddressForPte (Subsection); 03906 TempPte.u.Soft.Prototype = 1; 03907 03908 // 03909 // Set all the PTEs to the execute-read-write protection. 03910 // The section will control access to these and the segment 03911 // must provide a method to allow other users to map the file 03912 // for various protections. 03913 // 03914 03915 TempPte.u.Soft.Protection = MM_EXECUTE_READWRITE; 03916 03917 // 03918 // Align the prototype PTEs on the proper boundary. 03919 // 03920 03921 if (First) { 03922 03923 PointerPte = &NewSegment->ThePtes[0]; 03924 j = (ULONG) (((ULONG_PTR)PointerPte >> PTE_SHIFT) & 03925 ((MM_PROTO_PTE_ALIGNMENT / PAGE_SIZE) - 1)); 03926 03927 if (j != 0) { 03928 j = (MM_PROTO_PTE_ALIGNMENT / PAGE_SIZE) - j; 03929 } 03930 03931 NewSegment->PrototypePte = &NewSegment->ThePtes[j]; 03932 NewSegment->ControlArea = ControlArea; 03933 NewSegment->SizeOfSegment = EndOfFile; 03934 NewSegment->TotalNumberOfPtes = NumberOfPtes; 03935 NewSegment->SegmentPteTemplate = TempPte; 03936 PointerPte = NewSegment->PrototypePte; 03937 Subsection->SubsectionBase = PointerPte; 03938 ControlArea->PagedPoolUsage = EX_REAL_POOL_USAGE((sizeof(SEGMENT) + (NumberOfPtes * sizeof(MMPTE)))); 03939 03940 if (Subsection->NextSubsection != NULL) { 03941 03942 // 03943 // Multiple segments and subsections. 03944 // Align first so it is a multiple of 64k sizes. 03945 // 03946 // 03947 03948 NewSegment->NonExtendedPtes = (ULONG) 03949 ((((Subsection->PtesInSubsection * sizeof(MMPTE)) - 03950 ((PCHAR)NewSegment->PrototypePte - (PCHAR)NewSegment)) 03951 / sizeof(MMPTE)) & ~((X64K >> PAGE_SHIFT) - 1)); 03952 } else { 03953 NewSegment->NonExtendedPtes = NumberOfPtesWithAlignment; 03954 } 03955 Subsection->PtesInSubsection = NewSegment->NonExtendedPtes; 03956 03957 First = FALSE; 03958 } else { 03959 PointerPte = (PMMPTE)Subsection->SubsectionBase; 03960 } 03961 03962 Subsection->ControlArea = ControlArea; 03963 03964 Mi4KStartForSubsection(&FileOffset, Subsection); 03965 03966 Subsection->u.SubsectionFlags.Protection = MM_EXECUTE_READWRITE; 03967 03968 if (Subsection->NextSubsection == NULL) { 03969 03970 LastFileChunk = (EndOfFile >> MM4K_SHIFT) - FileOffset; 03971 03972 // 03973 // Note this next line restricts the number of bytes mapped by 03974 // a single subsection to 16TB-4K. multiple subsections can always 03975 // be chained together to support an overall file of size 16K TB. 03976 // 03977 03978 Subsection->NumberOfFullSectors = (ULONG)LastFileChunk; 03979 03980 Subsection->u.SubsectionFlags.SectorEndOffset = 03981 (ULONG) EndOfFile & MM4K_MASK; 03982 03983 j = Subsection->PtesInSubsection; 03984 03985 Subsection->PtesInSubsection = (ULONG)( 03986 NumberOfPtesForEntireFile - 03987 (FileOffset >> (PAGE_SHIFT - MM4K_SHIFT))); 03988 03989 #if DBG 03990 MiSubsectionConsistent(Subsection); 03991 #endif 03992 03993 Subsection->UnusedPtes = j - Subsection->PtesInSubsection; 03994 } else { 03995 03996 Subsection->NumberOfFullSectors = 03997 Subsection->PtesInSubsection << (PAGE_SHIFT - MM4K_SHIFT); 03998 #if DBG 03999 MiSubsectionConsistent(Subsection); 04000 #endif 04001 04002 } 04003 04004 MiFillMemoryPte (PointerPte, 04005 (Subsection->PtesInSubsection + 04006 Subsection->UnusedPtes) * sizeof(MMPTE), 04007 TempPte.u.Long); 04008 04009 FileOffset += Subsection->PtesInSubsection << 04010 (PAGE_SHIFT - MM4K_SHIFT); 04011 Subsection = Subsection->NextSubsection; 04012 } while (Subsection != NULL); 04013 04014 return STATUS_SUCCESS; 04015 }

NTSTATUS MiCreateImageFileMap IN PFILE_OBJECT  File,
OUT PSEGMENT Segment
 

Definition at line 1424 of file creasect.c.

References ASSERT, BYTE_OFFSET, BYTES_TO_PAGES, CcZeroEndOfLastPage(), CONTROL_AREA, _SUBSECTION::ControlArea, EX_REAL_POOL_USAGE, ExAllocatePoolWithTag, ExFreePool(), FALSE, File, _CONTROL_AREA::FilePointer, FsRtlGetFileSize(), _SEGMENT::ImageInformation, INIT_IMAGE_INFORMATION, IoPageRead(), KeClearEvent, KeInitializeEvent, KernelMode, KeWaitForSingleObject(), LARGE_CONTROL_AREA, _MDL::MappedSystemVa, MDL_MAPPED_TO_SYSTEM_VA, MDL_PAGES_LOCKED, _MDL::MdlFlags, MI_GET_PROTECTION_FROM_SOFT_PTE, MI_ROUND_TO_SIZE, MI_WRITE_INVALID_PTE, MiChargeCommitment(), MiFlushDataSection(), MiGetImageProtection(), MiGetPageForHeader(), MiGetSubsectionAddress, MiGetSubsectionAddressForPte, MiHydra, MiMapImageHeaderInHyperSpace(), MiRemoveImageHeaderPage(), MiReturnCommitment(), MiUnmapImageHeaderInHyperSpace(), MiUpdateImageHeaderPage(), MiVerifyImageHeader(), MM_COPY_ON_WRITE_MASK, MM_DBG_COMMIT_IMAGE, MM_DBG_COMMIT_RETURN_IMAGE_NO_LARGE_CA, MM_EXECUTE_WRITECOPY, MM_MAXIMUM_IMAGE_HEADER, MM_PROTECTION_WRITE_MASK, MM_PROTO_PTE_ALIGNMENT, MM_READONLY, MM_TRACK_COMMIT, MmBuildMdlForNonPagedPool(), MMCONTROL, MmCreateMdl(), MMPTE, MMSECT, MmSectionCommitMutex, MMSECTOR_MASK, MMSECTOR_SHIFT, MmSharedCommit, MmSizeOfMdl(), MMTEMPORARY, MmUnmapLockedPages(), _SUBSECTION::NextSubsection, NonPagedPool, _LARGE_CONTROL_AREA::NonPagedPoolUsage, _CONTROL_AREA::NonPagedPoolUsage, NT_SUCCESS, NTSTATUS(), NULL, _SUBSECTION::NumberOfFullSectors, _CONTROL_AREA::NumberOfSectionReferences, _CONTROL_AREA::NumberOfSubsections, _CONTROL_AREA::NumberOfUserReferences, PAGE_ALIGN, PAGE_SHIFT, PAGE_SIZE, PAGED_CODE, PagedPool, _CONTROL_AREA::PagedPoolUsage, PLARGE_CONTROL_AREA, _SEGMENT::PrototypePte, PTE_SHIFT, _SUBSECTION::PtesInSubsection, SectorOffset, _CONTROL_AREA::Segment, SEGMENT, _LARGE_CONTROL_AREA::SessionId, _SUBSECTION::StartingSector, Status, SUBSECTION, _SUBSECTION::SubsectionBase, _SEGMENT::TotalNumberOfPtes, TRUE, _LARGE_CONTROL_AREA::u, _SUBSECTION::u, _MMPTE::u, _CONTROL_AREA::u, _SUBSECTION::UnusedPtes, _LARGE_CONTROL_AREA::UserGlobalList, USHORT, WrPageIn, X64K, ZERO_LARGE, and ZeroPte.

Referenced by MmCreateSection().

01431 : 01432 01433 This function creates the necessary structures to allow the mapping 01434 of an image file. 01435 01436 The image file is opened and verified for correctness, a segment 01437 object is created and initialized based on data in the image 01438 header. 01439 01440 Arguments: 01441 01442 File - Supplies the file object for the image file. 01443 01444 Segment - Returns the segment object. 01445 01446 Return Value: 01447 01448 Returns the status value. 01449 01450 TBS 01451 01452 01453 --*/ 01454 01455 { 01456 NTSTATUS Status; 01457 ULONG_PTR EndingAddress; 01458 ULONG NumberOfPtes; 01459 ULONG SizeOfSegment; 01460 ULONG SectionVirtualSize; 01461 ULONG i; 01462 ULONG j; 01463 PCONTROL_AREA ControlArea; 01464 PSUBSECTION Subsection; 01465 PMMPTE PointerPte; 01466 MMPTE TempPte; 01467 MMPTE TempPteDemandZero; 01468 PVOID Base; 01469 PIMAGE_DOS_HEADER DosHeader; 01470 PIMAGE_NT_HEADERS NtHeader; 01471 PIMAGE_FILE_HEADER FileHeader; 01472 ULONG SizeOfImage; 01473 ULONG SizeOfHeaders; 01474 #if defined(_WIN64) 01475 PIMAGE_NT_HEADERS32 NtHeader32; 01476 #endif 01477 PIMAGE_SECTION_HEADER SectionTableEntry; 01478 PSEGMENT NewSegment; 01479 ULONG SectorOffset; 01480 ULONG NumberOfSubsections; 01481 PFN_NUMBER PageFrameNumber; 01482 LARGE_INTEGER StartingOffset; 01483 PCHAR ExtendedHeader; 01484 PPFN_NUMBER Page; 01485 ULONG_PTR PreferredImageBase; 01486 ULONG_PTR NextVa; 01487 PKEVENT InPageEvent; 01488 PMDL Mdl; 01489 ULONG ImageFileSize; 01490 ULONG OffsetToSectionTable; 01491 ULONG ImageAlignment; 01492 ULONG RoundingAlignment; 01493 ULONG FileAlignment; 01494 BOOLEAN ImageCommit; 01495 BOOLEAN SectionCommit; 01496 IO_STATUS_BLOCK IoStatus; 01497 LARGE_INTEGER EndOfFile; 01498 ULONG NtHeaderSize; 01499 ULONG SubsectionsAllocated; 01500 PLARGE_CONTROL_AREA LargeControlArea; 01501 PSUBSECTION NewSubsection; 01502 ULONG OriginalProtection; 01503 ULONG LoaderFlags; 01504 01505 #if defined (_ALPHA_) || defined(_IA64_) 01506 //[barrybo] bugbug: The image alignment code should be switched back 01507 // out on IA64 when EMNT supports 4k pages for WOW64. 01508 BOOLEAN InvalidAlignmentAllowed = FALSE; 01509 01510 ULONG TempNumberOfSubsections; 01511 PIMAGE_SECTION_HEADER TempSectionTableEntry; 01512 ULONG AdditionalSubsections; 01513 ULONG AdditionalPtes; 01514 ULONG AdditionalBasePtes; 01515 ULONG NewSubsectionsAllocated; 01516 PSEGMENT OldSegment; 01517 PMMPTE NewPointerPte; 01518 PMMPTE OldPointerPte; 01519 ULONG OrigNumberOfPtes; 01520 PCONTROL_AREA NewControlArea; 01521 01522 #endif 01523 01524 ExtendedHeader = NULL; 01525 01526 // ************************************************************* 01527 // Create image file section. 01528 // ************************************************************* 01529 01530 PAGED_CODE(); 01531 01532 01533 Status = FsRtlGetFileSize (File, &EndOfFile); 01534 01535 if (Status == STATUS_FILE_IS_A_DIRECTORY) { 01536 01537 // 01538 // Can't map a directory as a section. Return error. 01539 // 01540 01541 return STATUS_INVALID_FILE_FOR_SECTION; 01542 } 01543 01544 if (!NT_SUCCESS (Status)) { 01545 return Status; 01546 } 01547 01548 if (EndOfFile.HighPart != 0) { 01549 01550 // 01551 // File too big. Return error. 01552 // 01553 01554 return STATUS_INVALID_FILE_FOR_SECTION; 01555 } 01556 01557 // 01558 // Create a segment which maps an image file. 01559 // For now map a COFF image file with the subsections 01560 // containing the based address of the file. 01561 // 01562 01563 // 01564 // Read in the file header. 01565 // 01566 01567 InPageEvent = ExAllocatePoolWithTag (NonPagedPool, 01568 sizeof(KEVENT) + MmSizeOfMdl ( 01569 NULL, 01570 MM_MAXIMUM_IMAGE_HEADER), 01571 MMTEMPORARY); 01572 if (InPageEvent == NULL) { 01573 return STATUS_INSUFFICIENT_RESOURCES; 01574 } 01575 01576 Mdl = (PMDL)(InPageEvent + 1); 01577 01578 // 01579 // Create an event for the read operation. 01580 // 01581 01582 KeInitializeEvent (InPageEvent, NotificationEvent, FALSE); 01583 01584 // 01585 // Build an MDL for the operation. 01586 // 01587 01588 MmCreateMdl( Mdl, NULL, PAGE_SIZE); 01589 Mdl->MdlFlags |= MDL_PAGES_LOCKED; 01590 01591 PageFrameNumber = MiGetPageForHeader(); 01592 01593 Page = (PPFN_NUMBER)(Mdl + 1); 01594 *Page = PageFrameNumber; 01595 01596 ZERO_LARGE (StartingOffset); 01597 01598 CcZeroEndOfLastPage (File); 01599 01600 // 01601 // Flush the data section if there is one. 01602 // 01603 01604 MiFlushDataSection (File); 01605 01606 Mdl->MdlFlags |= MDL_PAGES_LOCKED; 01607 Status = IoPageRead (File, 01608 Mdl, 01609 &StartingOffset, 01610 InPageEvent, 01611 &IoStatus 01612 ); 01613 01614 if (Status == STATUS_PENDING) { 01615 KeWaitForSingleObject( InPageEvent, 01616 WrPageIn, 01617 KernelMode, 01618 FALSE, 01619 (PLARGE_INTEGER)NULL); 01620 } 01621 01622 if (Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA) { 01623 MmUnmapLockedPages (Mdl->MappedSystemVa, Mdl); 01624 } 01625 01626 if ((!NT_SUCCESS(Status)) || (!NT_SUCCESS(IoStatus.Status))) { 01627 if (Status != STATUS_FILE_LOCK_CONFLICT) { 01628 Status = STATUS_INVALID_FILE_FOR_SECTION; 01629 } 01630 goto BadSection; 01631 } 01632 01633 Base = MiMapImageHeaderInHyperSpace (PageFrameNumber); 01634 DosHeader = (PIMAGE_DOS_HEADER)Base; 01635 01636 if (IoStatus.Information != PAGE_SIZE) { 01637 01638 // 01639 // A full page was not read from the file, zero any remaining 01640 // bytes. 01641 // 01642 01643 RtlZeroMemory ((PVOID)((PCHAR)Base + IoStatus.Information), 01644 PAGE_SIZE - IoStatus.Information); 01645 } 01646 01647 // 01648 // Check to determine if this is an NT image (PE format) or 01649 // a DOS image, Win-16 image, or OS/2 image. If the image is 01650 // not NT format, return an error indicating which image it 01651 // appears to be. 01652 // 01653 01654 if (DosHeader->e_magic != IMAGE_DOS_SIGNATURE) { 01655 01656 Status = STATUS_INVALID_IMAGE_NOT_MZ; 01657 goto NeImage; 01658 } 01659 01660 #ifndef i386 01661 if (((ULONG)DosHeader->e_lfanew & 3) != 0) { 01662 01663 // 01664 // The image header is not aligned on a longword boundary. 01665 // Report this as an invalid protect mode image. 01666 // 01667 01668 Status = STATUS_INVALID_IMAGE_PROTECT; 01669 goto NeImage; 01670 } 01671 #endif 01672 01673 if ((ULONG)DosHeader->e_lfanew > EndOfFile.LowPart) { 01674 Status = STATUS_INVALID_IMAGE_PROTECT; 01675 goto NeImage; 01676 } 01677 01678 if (((ULONG)DosHeader->e_lfanew + 01679 sizeof(IMAGE_NT_HEADERS) + 01680 (16 * sizeof(IMAGE_SECTION_HEADER))) <= (ULONG)DosHeader->e_lfanew) { 01681 Status = STATUS_INVALID_IMAGE_PROTECT; 01682 goto NeImage; 01683 } 01684 01685 if (((ULONG)DosHeader->e_lfanew + 01686 sizeof(IMAGE_NT_HEADERS) + 01687 (16 * sizeof(IMAGE_SECTION_HEADER))) > PAGE_SIZE) { 01688 01689 // 01690 // The PE header is not within the page already read or the 01691 // objects are in another page. 01692 // Build another MDL and read an additional 8k. 01693 // 01694 01695 ExtendedHeader = ExAllocatePoolWithTag (NonPagedPool, 01696 MM_MAXIMUM_IMAGE_HEADER, 01697 MMTEMPORARY); 01698 if (ExtendedHeader == NULL) { 01699 Status = STATUS_INSUFFICIENT_RESOURCES; 01700 goto NeImage; 01701 } 01702 01703 // 01704 // Build an MDL for the operation. 01705 // 01706 01707 MmCreateMdl( Mdl, ExtendedHeader, MM_MAXIMUM_IMAGE_HEADER); 01708 01709 MmBuildMdlForNonPagedPool (Mdl); 01710 01711 StartingOffset.LowPart = PtrToUlong(PAGE_ALIGN ((ULONG)DosHeader->e_lfanew)); 01712 01713 KeClearEvent (InPageEvent); 01714 Status = IoPageRead (File, 01715 Mdl, 01716 &StartingOffset, 01717 InPageEvent, 01718 &IoStatus 01719 ); 01720 01721 if (Status == STATUS_PENDING) { 01722 KeWaitForSingleObject( InPageEvent, 01723 WrPageIn, 01724 KernelMode, 01725 FALSE, 01726 (PLARGE_INTEGER)NULL); 01727 } 01728 01729 if (Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA) { 01730 MmUnmapLockedPages (Mdl->MappedSystemVa, Mdl); 01731 } 01732 01733 if ((!NT_SUCCESS(Status)) || (!NT_SUCCESS(IoStatus.Status))) { 01734 if (Status != STATUS_FILE_LOCK_CONFLICT) { 01735 Status = STATUS_INVALID_FILE_FOR_SECTION; 01736 } 01737 goto NeImage; 01738 } 01739 NtHeader = (PIMAGE_NT_HEADERS)((PCHAR)ExtendedHeader + 01740 BYTE_OFFSET((ULONG)DosHeader->e_lfanew)); 01741 NtHeaderSize = MM_MAXIMUM_IMAGE_HEADER - 01742 (ULONG)(BYTE_OFFSET((ULONG)DosHeader->e_lfanew)); 01743 01744 } else { 01745 NtHeader = (PIMAGE_NT_HEADERS)((PCHAR)DosHeader + 01746 (ULONG)DosHeader->e_lfanew); 01747 NtHeaderSize = PAGE_SIZE - (ULONG)DosHeader->e_lfanew; 01748 } 01749 FileHeader = &NtHeader->FileHeader; 01750 01751 // 01752 // Check to see if this is an NT image or a DOS or OS/2 image. 01753 // 01754 01755 Status = MiVerifyImageHeader (NtHeader, DosHeader, NtHeaderSize); 01756 if (Status != STATUS_SUCCESS) { 01757 goto NeImage; 01758 } 01759 01760 #if defined(_WIN64) 01761 if (NtHeader->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) { 01762 // 01763 // The image is 32-bit. All code below this point must check 01764 // if NtHeader is NULL. If it is, then the image is PE32 and 01765 // NtHeader32 must be used. 01766 // 01767 NtHeader32 = (PIMAGE_NT_HEADERS32)NtHeader; 01768 NtHeader = NULL; 01769 } else { 01770 NtHeader32 = NULL; 01771 } 01772 01773 if (NtHeader) { 01774 #endif 01775 ImageAlignment = NtHeader->OptionalHeader.SectionAlignment; 01776 FileAlignment = NtHeader->OptionalHeader.FileAlignment - 1; 01777 SizeOfImage = NtHeader->OptionalHeader.SizeOfImage; 01778 LoaderFlags = NtHeader->OptionalHeader.LoaderFlags; 01779 #if defined (_WIN64) 01780 } else { 01781 ImageAlignment = NtHeader32->OptionalHeader.SectionAlignment; 01782 FileAlignment = NtHeader32->OptionalHeader.FileAlignment - 1; 01783 SizeOfImage = NtHeader32->OptionalHeader.SizeOfImage; 01784 LoaderFlags = NtHeader32->OptionalHeader.LoaderFlags; 01785 } 01786 #endif 01787 01788 RoundingAlignment = ImageAlignment; 01789 NumberOfSubsections = FileHeader->NumberOfSections; 01790 01791 if (ImageAlignment < PAGE_SIZE) { 01792 01793 // 01794 // The image alignment is less than the page size, 01795 // map the image with a single subsection. 01796 // 01797 01798 ControlArea = ExAllocatePoolWithTag (NonPagedPool, 01799 (ULONG)(sizeof(CONTROL_AREA) + (sizeof(SUBSECTION))), 01800 MMCONTROL); 01801 SubsectionsAllocated = 1; 01802 } else { 01803 01804 // 01805 // Allocate a control area and a subsection for each section 01806 // header plus one for the image header which has no section. 01807 // 01808 01809 ControlArea = ExAllocatePoolWithTag(NonPagedPool, 01810 (ULONG)(sizeof(CONTROL_AREA) + 01811 (sizeof(SUBSECTION) * 01812 (NumberOfSubsections + 1))), 01813 'iCmM'); 01814 SubsectionsAllocated = NumberOfSubsections + 1; 01815 } 01816 01817 if (ControlArea == NULL) { 01818 01819 // 01820 // The requested pool could not be allocated. 01821 // 01822 01823 Status = STATUS_INSUFFICIENT_RESOURCES; 01824 goto NeImage; 01825 } 01826 01827 // 01828 // Zero the control area and the FIRST subsection. 01829 // 01830 01831 RtlZeroMemory (ControlArea, 01832 sizeof(CONTROL_AREA) + sizeof(SUBSECTION)); 01833 01834 ControlArea->NonPagedPoolUsage = EX_REAL_POOL_USAGE(sizeof(CONTROL_AREA) + 01835 sizeof(SUBSECTION) * 01836 SubsectionsAllocated); 01837 01838 ASSERT (ControlArea->u.Flags.GlobalOnlyPerSession == 0); 01839 01840 Subsection = (PSUBSECTION)(ControlArea + 1); 01841 01842 NumberOfPtes = BYTES_TO_PAGES (SizeOfImage); 01843 01844 if (NumberOfPtes == 0) { 01845 ExFreePool (ControlArea); 01846 Status = STATUS_INVALID_IMAGE_FORMAT; 01847 goto NeImage; 01848 } 01849 01850 #if defined (_ALPHA_) || defined(_IA64_) 01851 if (ImageAlignment < PAGE_SIZE && KeGetPreviousMode() != KernelMode && 01852 (FileHeader->Machine < USER_SHARED_DATA->ImageNumberLow || 01853 FileHeader->Machine > USER_SHARED_DATA->ImageNumberHigh)) { 01854 01855 InvalidAlignmentAllowed = TRUE; 01856 } 01857 OrigNumberOfPtes = NumberOfPtes; 01858 #endif 01859 01860 SizeOfSegment = sizeof(SEGMENT) + (sizeof(MMPTE) * (NumberOfPtes - 1)) + 01861 sizeof(SECTION_IMAGE_INFORMATION); 01862 01863 NewSegment = ExAllocatePoolWithTag (PagedPool, 01864 SizeOfSegment, 01865 MMSECT); 01866 01867 if (NewSegment == NULL) { 01868 01869 // 01870 // The requested pool could not be allocated. 01871 // 01872 01873 ExFreePool (ControlArea); 01874 Status = STATUS_INSUFFICIENT_RESOURCES; 01875 goto NeImage; 01876 } 01877 *Segment = NewSegment; 01878 RtlZeroMemory (NewSegment, sizeof(SEGMENT)); 01879 01880 // 01881 // Align the prototype PTEs on the proper boundary. 01882 // 01883 01884 PointerPte = &NewSegment->ThePtes[0]; 01885 i = (ULONG) (((ULONG_PTR)PointerPte >> PTE_SHIFT) & 01886 ((MM_PROTO_PTE_ALIGNMENT / PAGE_SIZE) - 1)); 01887 01888 if (i != 0) { 01889 i = (MM_PROTO_PTE_ALIGNMENT / PAGE_SIZE) - i; 01890 } 01891 01892 NewSegment->PrototypePte = &NewSegment->ThePtes[i]; 01893 01894 NewSegment->ControlArea = ControlArea; 01895 NewSegment->ImageInformation = 01896 (PSECTION_IMAGE_INFORMATION)((PCHAR)NewSegment + sizeof(SEGMENT) + 01897 (sizeof(MMPTE) * (NumberOfPtes - 1))); 01898 NewSegment->TotalNumberOfPtes = NumberOfPtes; 01899 NewSegment->NonExtendedPtes = NumberOfPtes; 01900 NewSegment->SizeOfSegment = (ULONG_PTR)NumberOfPtes * PAGE_SIZE; 01901 01902 RtlZeroMemory (NewSegment->ImageInformation, 01903 sizeof (SECTION_IMAGE_INFORMATION)); 01904 01905 01906 // 01907 // This code is built twice on the Win64 build - once for PE32+ and once for 01908 // PE32 images. 01909 // 01910 #define INIT_IMAGE_INFORMATION(OptHdr) { \ 01911 NewSegment->ImageInformation->TransferAddress = \ 01912 (PVOID)((ULONG_PTR)((OptHdr).ImageBase) + \ 01913 (OptHdr).AddressOfEntryPoint); \ 01914 NewSegment->ImageInformation->MaximumStackSize = \ 01915 (OptHdr).SizeOfStackReserve; \ 01916 NewSegment->ImageInformation->CommittedStackSize = \ 01917 (OptHdr).SizeOfStackCommit; \ 01918 NewSegment->ImageInformation->SubSystemType = \ 01919 (OptHdr).Subsystem; \ 01920 NewSegment->ImageInformation->SubSystemMajorVersion = (USHORT)((OptHdr).MajorSubsystemVersion); \ 01921 NewSegment->ImageInformation->SubSystemMinorVersion = (USHORT)((OptHdr).MinorSubsystemVersion); \ 01922 NewSegment->ImageInformation->DllCharacteristics = \ 01923 (OptHdr).DllCharacteristics; \ 01924 NewSegment->ImageInformation->ImageContainsCode = \ 01925 (BOOLEAN)(((OptHdr).SizeOfCode != 0) || \ 01926 ((OptHdr).AddressOfEntryPoint != 0)); \ 01927 } 01928 01929 #if defined (_WIN64) 01930 if (NtHeader) { 01931 #endif 01932 INIT_IMAGE_INFORMATION(NtHeader->OptionalHeader); 01933 #if defined (_WIN64) 01934 } else { 01935 // The image is 32-bit so use the 32-bit header 01936 INIT_IMAGE_INFORMATION(NtHeader32->OptionalHeader); 01937 } 01938 #endif 01939 #undef INIT_IMAGE_INFORMATION 01940 01941 NewSegment->ImageInformation->ImageCharacteristics = 01942 FileHeader->Characteristics; 01943 NewSegment->ImageInformation->Machine = 01944 FileHeader->Machine; 01945 01946 ControlArea->Segment = NewSegment; 01947 ControlArea->NumberOfSectionReferences = 1; 01948 ControlArea->NumberOfUserReferences = 1; 01949 ControlArea->u.Flags.BeingCreated = 1; 01950 ControlArea->PagedPoolUsage = EX_REAL_POOL_USAGE((sizeof(SEGMENT) + (NumberOfPtes * sizeof(MMPTE)))); 01951 01952 if (ImageAlignment < PAGE_SIZE) { 01953 01954 // 01955 // Image alignment is less than a page, the number 01956 // of subsections is 1. 01957 // 01958 01959 ControlArea->NumberOfSubsections = 1; 01960 } else { 01961 ControlArea->NumberOfSubsections = (USHORT)NumberOfSubsections; 01962 } 01963 01964 ControlArea->u.Flags.Image = 1; 01965 ControlArea->u.Flags.File = 1; 01966 01967 if ((FILE_FLOPPY_DISKETTE & File->DeviceObject->Characteristics) || 01968 ((FileHeader->Characteristics & 01969 IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP) && 01970 (FILE_REMOVABLE_MEDIA & File->DeviceObject->Characteristics)) || 01971 ((FileHeader->Characteristics & 01972 IMAGE_FILE_NET_RUN_FROM_SWAP) && 01973 (FILE_REMOTE_DEVICE & File->DeviceObject->Characteristics))) { 01974 01975 // 01976 // This file resides on a floppy disk or a removable media or 01977 // network with flags set indicating it should be copied 01978 // to the paging file. 01979 // 01980 01981 ControlArea->u.Flags.FloppyMedia = 1; 01982 } 01983 01984 if (FILE_REMOTE_DEVICE & File->DeviceObject->Characteristics) { 01985 01986 // 01987 // This file resides on a redirected drive. 01988 // 01989 01990 ControlArea->u.Flags.Networked = 1; 01991 } 01992 01993 ControlArea->FilePointer = File; 01994 01995 // 01996 // Build the subsection and prototype PTEs for the image header. 01997 // 01998 01999 Subsection->ControlArea = ControlArea; 02000 #if defined(_WIN64) 02001 if (NtHeader) { 02002 #endif 02003 NextVa = NtHeader->OptionalHeader.ImageBase; 02004 #if defined(_WIN64) 02005 } else { 02006 NextVa = NtHeader32->OptionalHeader.ImageBase; 02007 } 02008 #endif 02009 02010 02011 if ((NextVa & (X64K - 1)) != 0) { 02012 02013 // 02014 // Image header is not aligned on a 64k boundary. 02015 // 02016 02017 goto BadPeImageSegment; 02018 } 02019 02020 NewSegment->BasedAddress = (PVOID)NextVa; 02021 #if defined(_WIN64) 02022 if (NtHeader) { 02023 #endif 02024 SizeOfHeaders = NtHeader->OptionalHeader.SizeOfHeaders; 02025 #if defined(_WIN64) 02026 } else { 02027 SizeOfHeaders = NtHeader32->OptionalHeader.SizeOfHeaders; 02028 } 02029 #endif 02030 02031 if (SizeOfHeaders >= SizeOfImage) { 02032 goto BadPeImageSegment; 02033 } 02034 02035 Subsection->PtesInSubsection = MI_ROUND_TO_SIZE ( 02036 SizeOfHeaders, 02037 ImageAlignment 02038 ) >> PAGE_SHIFT; 02039 02040 PointerPte = NewSegment->PrototypePte; 02041 Subsection->SubsectionBase = PointerPte; 02042 02043 TempPte.u.Long = MiGetSubsectionAddressForPte (Subsection); 02044 TempPte.u.Soft.Prototype = 1; 02045 02046 NewSegment->SegmentPteTemplate = TempPte; 02047 SectorOffset = 0; 02048 02049 if (ImageAlignment < PAGE_SIZE) { 02050 02051 // 02052 // Aligned on less than a page size boundary. 02053 // Build a single subsection to refer to the image. 02054 // 02055 02056 PointerPte = NewSegment->PrototypePte; 02057 02058 Subsection->PtesInSubsection = NumberOfPtes; 02059 02060 Subsection->NumberOfFullSectors = 02061 (ULONG)(EndOfFile.QuadPart >> MMSECTOR_SHIFT); 02062 02063 ASSERT ((ULONG)(EndOfFile.HighPart & 0xFFFFF000) == 0); 02064 02065 Subsection->u.SubsectionFlags.SectorEndOffset = 02066 EndOfFile.LowPart & MMSECTOR_MASK; 02067 02068 Subsection->u.SubsectionFlags.Protection = MM_EXECUTE_WRITECOPY; 02069 02070 // 02071 // Set all the PTEs to the execute-read-write protection. 02072 // The section will control access to these and the segment 02073 // must provide a method to allow other users to map the file 02074 // for various protections. 02075 // 02076 02077 TempPte.u.Soft.Protection = MM_EXECUTE_WRITECOPY; 02078 02079 NewSegment->SegmentPteTemplate = TempPte; 02080 02081 02082 #if defined (_ALPHA_) || defined(_IA64_) 02083 // 02084 // Invalid image alignments are supported for cross platform 02085 // emulation. Only alpha and IA64 require extra handling because page 02086 // size is larger than x86. 02087 // 02088 02089 02090 if (InvalidAlignmentAllowed) { 02091 02092 TempPteDemandZero.u.Long = 0; 02093 TempPteDemandZero.u.Soft.Protection = MM_EXECUTE_WRITECOPY; 02094 SectorOffset = 0; 02095 02096 for (i = 0; i < NumberOfPtes; i += 1) { 02097 02098 // 02099 // Set prototype PTEs. 02100 // 02101 02102 if (SectorOffset < EndOfFile.LowPart) { 02103 02104 // 02105 // Data resides on the disk, refer to the control section. 02106 // 02107 02108 MI_WRITE_INVALID_PTE (PointerPte, TempPte); 02109 02110 } else { 02111 02112 // 02113 // Data does not reside on the disk, use Demand zero pages. 02114 // 02115 02116 MI_WRITE_INVALID_PTE (PointerPte, TempPteDemandZero); 02117 } 02118 02119 SectorOffset += PAGE_SIZE; 02120 PointerPte += 1; 02121 } 02122 02123 } else 02124 #endif 02125 { 02126 02127 for (i = 0; i < NumberOfPtes; i += 1) { 02128 02129 // 02130 // Set all the prototype PTEs to refer to the control section. 02131 // 02132 02133 MI_WRITE_INVALID_PTE (PointerPte, TempPte); 02134 PointerPte += 1; 02135 } 02136 } 02137 02138 NewSegment->ImageCommitment = NumberOfPtes; 02139 02140 02141 // 02142 // Indicate alignment is less than a page. 02143 // 02144 02145 TempPte.u.Long = 0; 02146 02147 } else { 02148 02149 // 02150 // Alignment is PAGE_SIZE or greater. 02151 // 02152 02153 if (Subsection->PtesInSubsection > NumberOfPtes) { 02154 02155 // 02156 // Inconsistent image, size does not agree with header. 02157 // 02158 02159 goto BadPeImageSegment; 02160 } 02161 NumberOfPtes -= Subsection->PtesInSubsection; 02162 02163 Subsection->NumberOfFullSectors = 02164 SizeOfHeaders >> MMSECTOR_SHIFT; 02165 02166 Subsection->u.SubsectionFlags.SectorEndOffset = 02167 SizeOfHeaders & MMSECTOR_MASK; 02168 02169 Subsection->u.SubsectionFlags.ReadOnly = 1; 02170 Subsection->u.SubsectionFlags.CopyOnWrite = 1; 02171 Subsection->u.SubsectionFlags.Protection = MM_READONLY; 02172 02173 TempPte.u.Soft.Protection = MM_READONLY; 02174 NewSegment->SegmentPteTemplate = TempPte; 02175 02176 for (i = 0; i < Subsection->PtesInSubsection; i += 1) { 02177 02178 // 02179 // Set all the prototype PTEs to refer to the control section. 02180 // 02181 02182 if (SectorOffset < SizeOfHeaders) { 02183 MI_WRITE_INVALID_PTE (PointerPte, TempPte); 02184 } else { 02185 MI_WRITE_INVALID_PTE (PointerPte, ZeroPte); 02186 } 02187 SectorOffset += PAGE_SIZE; 02188 PointerPte += 1; 02189 NextVa += PAGE_SIZE; 02190 } 02191 } 02192 02193 // 02194 // Build the next subsections. 02195 // 02196 02197 #if defined(_WIN64) 02198 if (NtHeader) { 02199 #endif 02200 PreferredImageBase = NtHeader->OptionalHeader.ImageBase; 02201 #if defined(_WIN64) 02202 } else { 02203 PreferredImageBase = NtHeader32->OptionalHeader.ImageBase; 02204 } 02205 #endif 02206 02207 // 02208 // At this point the object table is read in (if it was not 02209 // already read in) and may displace the image header. 02210 // 02211 02212 SectionTableEntry = NULL; 02213 OffsetToSectionTable = sizeof(ULONG) + 02214 sizeof(IMAGE_FILE_HEADER) + 02215 FileHeader->SizeOfOptionalHeader; 02216 02217 if ((BYTE_OFFSET(NtHeader) + OffsetToSectionTable + 02218 #if defined (_WIN64) 02219 BYTE_OFFSET(NtHeader32) + 02220 #endif 02221 ((NumberOfSubsections + 1) * 02222 sizeof (IMAGE_SECTION_HEADER))) <= PAGE_SIZE) { 02223 02224 // 02225 // Section tables are within the header which was read. 02226 // 02227 02228 #if defined(_WIN64) 02229 if (NtHeader32) { 02230 SectionTableEntry = (PIMAGE_SECTION_HEADER)((PCHAR)NtHeader32 + 02231 OffsetToSectionTable); 02232 } else 02233 #endif 02234 { 02235 SectionTableEntry = (PIMAGE_SECTION_HEADER)((PCHAR)NtHeader + 02236 OffsetToSectionTable); 02237 } 02238 02239 } else { 02240 02241 // 02242 // Has an extended header been read in and are the object 02243 // tables resident? 02244 // 02245 02246 if (ExtendedHeader != NULL) { 02247 02248 #if defined(_WIN64) 02249 if (NtHeader32) { 02250 SectionTableEntry = (PIMAGE_SECTION_HEADER)((PCHAR)NtHeader32 + 02251 OffsetToSectionTable); 02252 } else 02253 #endif 02254 { 02255 SectionTableEntry = (PIMAGE_SECTION_HEADER)((PCHAR)NtHeader + 02256 OffsetToSectionTable); 02257 } 02258 02259 // 02260 // Is the whole range of object tables mapped by the 02261 // extended header? 02262 // 02263 02264 if ((((PCHAR)SectionTableEntry + 02265 ((NumberOfSubsections + 1) * 02266 sizeof (IMAGE_SECTION_HEADER))) - 02267 (PCHAR)ExtendedHeader) > 02268 MM_MAXIMUM_IMAGE_HEADER) { 02269 SectionTableEntry = NULL; 02270 02271 } 02272 } 02273 } 02274 02275 if (SectionTableEntry == NULL) { 02276 02277 // 02278 // The section table entries are not in the same 02279 // pages as the other data already read in. Read in 02280 // the object table entries. 02281 // 02282 02283 if (ExtendedHeader == NULL) { 02284 ExtendedHeader = ExAllocatePoolWithTag (NonPagedPool, 02285 MM_MAXIMUM_IMAGE_HEADER, 02286 MMTEMPORARY); 02287 if (ExtendedHeader == NULL) { 02288 ExFreePool (NewSegment); 02289 ExFreePool (ControlArea); 02290 Status = STATUS_INSUFFICIENT_RESOURCES; 02291 goto NeImage; 02292 } 02293 02294 // 02295 // Build an MDL for the operation. 02296 // 02297 02298 MmCreateMdl( Mdl, ExtendedHeader, MM_MAXIMUM_IMAGE_HEADER); 02299 02300 MmBuildMdlForNonPagedPool (Mdl); 02301 } 02302 02303 StartingOffset.LowPart = PtrToUlong(PAGE_ALIGN ( 02304 (ULONG)DosHeader->e_lfanew + 02305 OffsetToSectionTable)); 02306 02307 SectionTableEntry = (PIMAGE_SECTION_HEADER)((PCHAR)ExtendedHeader + 02308 BYTE_OFFSET((ULONG)DosHeader->e_lfanew + 02309 OffsetToSectionTable)); 02310 02311 KeClearEvent (InPageEvent); 02312 Status = IoPageRead (File, 02313 Mdl, 02314 &StartingOffset, 02315 InPageEvent, 02316 &IoStatus 02317 ); 02318 02319 if (Status == STATUS_PENDING) { 02320 KeWaitForSingleObject( InPageEvent, 02321 WrPageIn, 02322 KernelMode, 02323 FALSE, 02324 (PLARGE_INTEGER)NULL); 02325 } 02326 02327 if (Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA) { 02328 MmUnmapLockedPages (Mdl->MappedSystemVa, Mdl); 02329 } 02330 02331 if ((!NT_SUCCESS(Status)) || (!NT_SUCCESS(IoStatus.Status))) { 02332 if (Status != STATUS_FILE_LOCK_CONFLICT) { 02333 Status = STATUS_INVALID_FILE_FOR_SECTION; 02334 } 02335 ExFreePool (NewSegment); 02336 ExFreePool (ControlArea); 02337 goto NeImage; 02338 } 02339 02340 // 02341 // From this point on NtHeader is only valid if it 02342 // was in the first 4k of the image, otherwise reading in 02343 // the object tables wiped it out. 02344 // 02345 02346 } 02347 02348 if (TempPte.u.Long == 0 02349 #if defined (_ALPHA_) || defined(_IA64_) 02350 && (!InvalidAlignmentAllowed) 02351 #endif 02352 ) { 02353 02354 // The image header is no longer valid, TempPte is 02355 // used to indicate that this image alignment is 02356 // less than a PAGE_SIZE. 02357 02358 // 02359 // Loop through all sections and make sure there is no 02360 // uninitialized data. 02361 // 02362 02363 Status = STATUS_SUCCESS; 02364 02365 while (NumberOfSubsections > 0) { 02366 if (SectionTableEntry->Misc.VirtualSize == 0) { 02367 SectionVirtualSize = SectionTableEntry->SizeOfRawData; 02368 } else { 02369 SectionVirtualSize = SectionTableEntry->Misc.VirtualSize; 02370 } 02371 02372 // 02373 // If the raw pointer + raw size overflows a long word, return an error. 02374 // 02375 02376 if (SectionTableEntry->PointerToRawData + 02377 SectionTableEntry->SizeOfRawData < 02378 SectionTableEntry->PointerToRawData) { 02379 02380 KdPrint(("MMCREASECT: invalid section/file size %Z\n", 02381 &File->FileName)); 02382 02383 Status = STATUS_INVALID_IMAGE_FORMAT; 02384 break; 02385 } 02386 02387 // 02388 // If the virtual size and address does not match the rawdata 02389 // and invalid alignments not allowed return an error. 02390 // 02391 02392 if (((SectionTableEntry->PointerToRawData != 02393 SectionTableEntry->VirtualAddress)) 02394 || 02395 (SectionVirtualSize > SectionTableEntry->SizeOfRawData)) { 02396 02397 KdPrint(("MMCREASECT: invalid BSS/Trailingzero %Z\n", 02398 &File->FileName)); 02399 02400 Status = STATUS_INVALID_IMAGE_FORMAT; 02401 break; 02402 } 02403 02404 02405 SectionTableEntry += 1; 02406 NumberOfSubsections -= 1; 02407 } 02408 02409 02410 if (!NT_SUCCESS(Status)) { 02411 ExFreePool (NewSegment); 02412 ExFreePool (ControlArea); 02413 goto NeImage; 02414 } 02415 02416 goto PeReturnSuccess; 02417 02418 } 02419 #if defined (_ALPHA_) || defined(_IA64_) 02420 02421 else if (TempPte.u.Long == 0 && InvalidAlignmentAllowed) { 02422 02423 TempNumberOfSubsections = NumberOfSubsections; 02424 TempSectionTableEntry = SectionTableEntry; 02425 02426 // 02427 // The image header is no longer valid, TempPte is 02428 // used to indicate that this image alignment is 02429 // less than a PAGE_SIZE. 02430 // 02431 02432 // 02433 // Loop through all sections and make sure there is no 02434 // uninitialized data. 02435 // 02436 // Also determine if there are shared data sections and 02437 // the number of extra ptes they require. 02438 // 02439 02440 AdditionalSubsections = 0; 02441 AdditionalPtes = 0; 02442 AdditionalBasePtes = 0; 02443 RoundingAlignment = PAGE_SIZE; 02444 02445 while (TempNumberOfSubsections > 0) { 02446 ULONG EndOfSection; 02447 ULONG ExtraPages; 02448 02449 if (TempSectionTableEntry->Misc.VirtualSize == 0) { 02450 SectionVirtualSize = TempSectionTableEntry->SizeOfRawData; 02451 } else { 02452 SectionVirtualSize = TempSectionTableEntry->Misc.VirtualSize; 02453 } 02454 02455 EndOfSection = TempSectionTableEntry->PointerToRawData + 02456 TempSectionTableEntry->SizeOfRawData; 02457 02458 // 02459 // If the raw pointer + raw size overflows a long word, return an error. 02460 // 02461 02462 if (EndOfSection < TempSectionTableEntry->PointerToRawData) { 02463 02464 KdPrint(("MMCREASECT: invalid section/file size %Z\n", 02465 &File->FileName)); 02466 02467 Status = STATUS_INVALID_IMAGE_FORMAT; 02468 02469 ExFreePool (NewSegment); 02470 ExFreePool (ControlArea); 02471 goto NeImage; 02472 } 02473 02474 // 02475 // If the section goes past SizeOfImage then allocate additional PTEs. 02476 // On x86 this is handled by the subsection mapping. On alpha this is handled 02477 // by the Wx86 loader extension after the image has been mapped in. But the 02478 // additional data must be in memory so it can be shuffled around later. 02479 // 02480 02481 if ((EndOfSection <= EndOfFile.LowPart) && 02482 (EndOfSection > SizeOfImage)) { 02483 02484 // 02485 // Allocate enough PTEs to cover the end of this section. 02486 // Maximize with any other sections that extend beyond SizeOfImage 02487 // 02488 02489 ExtraPages = MI_ROUND_TO_SIZE (EndOfSection - SizeOfImage, RoundingAlignment) >> PAGE_SHIFT; 02490 if (ExtraPages > AdditionalBasePtes) { 02491 AdditionalBasePtes = ExtraPages; 02492 } 02493 } 02494 02495 // Count number of shared data sections and additional ptes needed 02496 02497 if ((TempSectionTableEntry->Characteristics & IMAGE_SCN_MEM_SHARED) && 02498 (!(TempSectionTableEntry->Characteristics & IMAGE_SCN_MEM_EXECUTE) || 02499 (TempSectionTableEntry->Characteristics & IMAGE_SCN_MEM_WRITE))) { 02500 AdditionalPtes += 02501 MI_ROUND_TO_SIZE (SectionVirtualSize, RoundingAlignment) >> 02502 PAGE_SHIFT; 02503 AdditionalSubsections += 1; 02504 } 02505 02506 TempSectionTableEntry += 1; 02507 TempNumberOfSubsections -= 1; 02508 } 02509 02510 if (AdditionalBasePtes == 0 && (AdditionalSubsections == 0 || AdditionalPtes == 0)) { 02511 // no shared data sections 02512 goto PeReturnSuccess; 02513 } 02514 02515 // 02516 // There are additional Base PTEs or shared data sections. 02517 // For shared sections, allocate new PTEs for these sections 02518 // at the end of the image. The WX86 loader will change 02519 // fixups to point to the new pages. 02520 // 02521 // First reallocate the control area. 02522 // 02523 02524 NewSubsectionsAllocated = SubsectionsAllocated + 02525 AdditionalSubsections; 02526 02527 NewControlArea = ExAllocatePoolWithTag(NonPagedPool, 02528 (ULONG) (sizeof(CONTROL_AREA) + 02529 (sizeof(SUBSECTION) * 02530 NewSubsectionsAllocated)), 02531 'iCmM'); 02532 if (NewControlArea == NULL) { 02533 ExFreePool (NewSegment); 02534 ExFreePool (ControlArea); 02535 Status = STATUS_INSUFFICIENT_RESOURCES; 02536 goto NeImage; 02537 } 02538 02539 // 02540 // Copy the old control area to the new one, modify some fields. 02541 // 02542 02543 RtlMoveMemory (NewControlArea, ControlArea, 02544 sizeof(CONTROL_AREA) + 02545 sizeof(SUBSECTION) * SubsectionsAllocated); 02546 02547 NewControlArea->NonPagedPoolUsage = 02548 EX_REAL_POOL_USAGE(sizeof(CONTROL_AREA) + 02549 (sizeof(SUBSECTION) * 02550 NewSubsectionsAllocated)); 02551 02552 NewControlArea->NumberOfSubsections = (USHORT) NewSubsectionsAllocated; 02553 02554 // 02555 // Now allocate a new segment that has the newly calculated number 02556 // of PTEs, initialize it from the previously allocated new segment, 02557 // and overwrite the fields that should be changed. 02558 // 02559 02560 OldSegment = NewSegment; 02561 02562 02563 OrigNumberOfPtes += AdditionalBasePtes; 02564 02565 SizeOfSegment = sizeof(SEGMENT) + 02566 (sizeof(MMPTE) * (OrigNumberOfPtes + AdditionalPtes - 1)) + 02567 sizeof(SECTION_IMAGE_INFORMATION); 02568 02569 NewSegment = ExAllocatePoolWithTag (PagedPool, 02570 SizeOfSegment, 02571 MMSECT); 02572 02573 if (NewSegment == NULL) { 02574 02575 // 02576 // The requested pool could not be allocated. 02577 // 02578 02579 ExFreePool (ControlArea); 02580 ExFreePool (NewControlArea); 02581 ExFreePool (OldSegment); 02582 Status = STATUS_INSUFFICIENT_RESOURCES; 02583 goto NeImage; 02584 } 02585 02586 *Segment = NewSegment; 02587 RtlMoveMemory (NewSegment, OldSegment, sizeof(SEGMENT)); 02588 02589 // 02590 // Align the prototype PTEs on the proper boundary. 02591 // 02592 02593 NewPointerPte = &NewSegment->ThePtes[0]; 02594 i = (ULONG) (((ULONG_PTR)NewPointerPte >> PTE_SHIFT) & 02595 ((MM_PROTO_PTE_ALIGNMENT / PAGE_SIZE) - 1)); 02596 02597 if (i != 0) { 02598 i = (MM_PROTO_PTE_ALIGNMENT / PAGE_SIZE) - i; 02599 } 02600 02601 NewSegment->PrototypePte = &NewSegment->ThePtes[i]; 02602 if (i != 0) { 02603 RtlZeroMemory (&NewSegment->ThePtes[0], sizeof(MMPTE) * i); 02604 } 02605 PointerPte = NewSegment->PrototypePte + 02606 (PointerPte - OldSegment->PrototypePte); 02607 02608 NewSegment->ControlArea = NewControlArea; 02609 NewSegment->ImageInformation = 02610 (PSECTION_IMAGE_INFORMATION)((PCHAR)NewSegment + sizeof(SEGMENT) + 02611 (sizeof(MMPTE) * (OrigNumberOfPtes + AdditionalPtes - 1))); 02612 NewSegment->TotalNumberOfPtes = OrigNumberOfPtes + AdditionalPtes; 02613 NewSegment->NonExtendedPtes = OrigNumberOfPtes + AdditionalPtes; 02614 NewSegment->SizeOfSegment = (ULONG_PTR)(OrigNumberOfPtes + AdditionalPtes) * PAGE_SIZE; 02615 02616 RtlMoveMemory (NewSegment->ImageInformation, 02617 OldSegment->ImageInformation, 02618 sizeof (SECTION_IMAGE_INFORMATION)); 02619 02620 // 02621 // Now change the fields in the subsections to account for the new 02622 // control area and the new segment. Also change the PTEs in the 02623 // newly allocated segment to point to the new subsections. 02624 // 02625 02626 NewControlArea->Segment = NewSegment; 02627 NewControlArea->PagedPoolUsage = EX_REAL_POOL_USAGE((sizeof(SEGMENT) + 02628 ((OrigNumberOfPtes + AdditionalPtes) * sizeof(MMPTE)))); 02629 02630 Subsection = (PSUBSECTION)(ControlArea + 1); 02631 NewSubsection = (PSUBSECTION)(NewControlArea + 1); 02632 NewSubsection->PtesInSubsection += AdditionalBasePtes; 02633 02634 for (i = 0; i < SubsectionsAllocated; i += 1) { 02635 02636 // 02637 // Note: SubsectionsAllocated is always 1 (for wx86), so this loop 02638 // is executed only once. 02639 // 02640 02641 NewSubsection->ControlArea = (PCONTROL_AREA) NewControlArea; 02642 02643 NewSubsection->SubsectionBase = NewSegment->PrototypePte + 02644 (Subsection->SubsectionBase - OldSegment->PrototypePte); 02645 02646 NewPointerPte = NewSegment->PrototypePte; 02647 OldPointerPte = OldSegment->PrototypePte; 02648 02649 TempPte.u.Long = MiGetSubsectionAddressForPte (NewSubsection); 02650 TempPte.u.Soft.Prototype = 1; 02651 02652 for (j = 0; j < OldSegment->TotalNumberOfPtes+AdditionalBasePtes; j += 1) { 02653 02654 if ((OldPointerPte->u.Soft.Prototype == 1) && 02655 (MiGetSubsectionAddress (OldPointerPte) == Subsection)) { 02656 OriginalProtection = MI_GET_PROTECTION_FROM_SOFT_PTE (OldPointerPte); 02657 TempPte.u.Soft.Protection = OriginalProtection; 02658 MI_WRITE_INVALID_PTE (NewPointerPte, TempPte); 02659 } 02660 else if (i == 0) { 02661 02662 // 02663 // Since the outer for loop is executed only once, there 02664 // is no need for the i == 0 above, but it is safer to 02665 // have it. If the code changes later and other sections 02666 // are added, their PTEs will get initialized here as 02667 // DemandZero and if they are not DemandZero, they will be 02668 // overwritten in a later iteration of the outer loop. 02669 // For now, this else if clause will be executed only 02670 // for DemandZero PTEs. 02671 // 02672 02673 OriginalProtection = MI_GET_PROTECTION_FROM_SOFT_PTE (OldPointerPte); 02674 TempPteDemandZero.u.Long = 0; 02675 TempPteDemandZero.u.Soft.Protection = OriginalProtection; 02676 MI_WRITE_INVALID_PTE (NewPointerPte, TempPteDemandZero); 02677 } 02678 02679 NewPointerPte += 1; 02680 // Stop incrementing the OldPointerPte at the last entry and use it 02681 // for the additional Base PTEs 02682 if (j < OldSegment->TotalNumberOfPtes-1) { 02683 OldPointerPte += 1; 02684 } 02685 } 02686 02687 Subsection += 1; 02688 NewSubsection += 1; 02689 } 02690 02691 02692 RtlZeroMemory (NewSubsection, 02693 sizeof(SUBSECTION) * AdditionalSubsections); 02694 02695 ExFreePool (OldSegment); 02696 ExFreePool (ControlArea); 02697 ControlArea = (PCONTROL_AREA) NewControlArea; 02698 02699 // 02700 // Adjust some variables that are used below. 02701 // PointerPte has already been set above before OldSegment was freed. 02702 // 02703 02704 SubsectionsAllocated = NewSubsectionsAllocated; 02705 Subsection = NewSubsection - 1; // Points to last used subsection. 02706 NumberOfPtes = AdditionalPtes; // # PTEs that haven't yet been used in 02707 // previous subsections. 02708 02709 // Additional Base PTEs have been added. Only continue if there are 02710 // additional subsections to process 02711 if (AdditionalSubsections == 0 || AdditionalPtes == 0) { 02712 // no shared data sections 02713 goto PeReturnSuccess; 02714 } 02715 } 02716 #endif 02717 02718 while (NumberOfSubsections > 0) { 02719 02720 #if defined (_ALPHA_) || defined(_IA64_) 02721 if (!InvalidAlignmentAllowed || 02722 ((SectionTableEntry->Characteristics & IMAGE_SCN_MEM_SHARED) && 02723 (!(SectionTableEntry->Characteristics & IMAGE_SCN_MEM_EXECUTE) || 02724 (SectionTableEntry->Characteristics & IMAGE_SCN_MEM_WRITE)))) { 02725 #endif 02726 02727 // 02728 // Handle case where virtual size is 0. 02729 // 02730 02731 if (SectionTableEntry->Misc.VirtualSize == 0) { 02732 SectionVirtualSize = SectionTableEntry->SizeOfRawData; 02733 } else { 02734 SectionVirtualSize = SectionTableEntry->Misc.VirtualSize; 02735 } 02736 02737 // 02738 // Fix for Borland linker problem. The SizeOfRawData can 02739 // be a zero, but the PointerToRawData is not zero. 02740 // Set it to zero. 02741 // 02742 02743 if (SectionTableEntry->SizeOfRawData == 0) { 02744 SectionTableEntry->PointerToRawData = 0; 02745 } 02746 02747 // 02748 // If the section information wraps return an error. 02749 // 02750 02751 if (SectionTableEntry->PointerToRawData + 02752 SectionTableEntry->SizeOfRawData < 02753 SectionTableEntry->PointerToRawData) { 02754 02755 goto BadPeImageSegment; 02756 } 02757 02758 02759 Subsection += 1; 02760 Subsection->ControlArea = ControlArea; 02761 Subsection->NextSubsection = (PSUBSECTION)NULL; 02762 Subsection->UnusedPtes = 0; 02763 02764 if (((NextVa != 02765 (PreferredImageBase + SectionTableEntry->VirtualAddress)) 02766 02767 #if defined (_ALPHA_) || defined(_IA64_) 02768 && !InvalidAlignmentAllowed 02769 #endif 02770 02771 ) || 02772 (SectionVirtualSize == 0)) { 02773 02774 // 02775 // The specified virtual address does not align 02776 // with the next prototype PTE. 02777 // 02778 02779 goto BadPeImageSegment; 02780 } 02781 02782 Subsection->PtesInSubsection = 02783 MI_ROUND_TO_SIZE (SectionVirtualSize, RoundingAlignment) 02784 >> PAGE_SHIFT; 02785 02786 if (Subsection->PtesInSubsection > NumberOfPtes) { 02787 02788 // 02789 // Inconsistent image, size does not agree with object tables. 02790 // 02791 02792 goto BadPeImageSegment; 02793 } 02794 NumberOfPtes -= Subsection->PtesInSubsection; 02795 02796 Subsection->u.LongFlags = 0; 02797 Subsection->StartingSector = 02798 SectionTableEntry->PointerToRawData >> MMSECTOR_SHIFT; 02799 02800 // 02801 // Align ending sector on file align boundary. 02802 // 02803 02804 EndingAddress = (SectionTableEntry->PointerToRawData + 02805 SectionTableEntry->SizeOfRawData + 02806 FileAlignment) & ~FileAlignment; 02807 02808 Subsection->NumberOfFullSectors = (ULONG) 02809 ((EndingAddress >> MMSECTOR_SHIFT) - 02810 Subsection->StartingSector); 02811 02812 Subsection->u.SubsectionFlags.SectorEndOffset = 02813 (ULONG) EndingAddress & MMSECTOR_MASK; 02814 02815 Subsection->SubsectionBase = PointerPte; 02816 02817 // 02818 // Build both a demand zero PTE and a PTE pointing to the 02819 // subsection. 02820 // 02821 TempPte.u.Long = 0; 02822 TempPteDemandZero.u.Long = 0; 02823 02824 TempPte.u.Long = MiGetSubsectionAddressForPte (Subsection); 02825 TempPte.u.Soft.Prototype = 1; 02826 ImageFileSize = SectionTableEntry->PointerToRawData + 02827 SectionTableEntry->SizeOfRawData; 02828 TempPte.u.Soft.Protection = 02829 MiGetImageProtection (SectionTableEntry->Characteristics); 02830 TempPteDemandZero.u.Soft.Protection = TempPte.u.Soft.Protection; 02831 02832 if (SectionTableEntry->PointerToRawData == 0) { 02833 TempPte = TempPteDemandZero; 02834 } 02835 02836 Subsection->u.SubsectionFlags.ReadOnly = 1; 02837 Subsection->u.SubsectionFlags.CopyOnWrite = 1; 02838 Subsection->u.SubsectionFlags.Protection = MI_GET_PROTECTION_FROM_SOFT_PTE (&TempPte); 02839 02840 if (TempPte.u.Soft.Protection & MM_PROTECTION_WRITE_MASK) { 02841 if ((TempPte.u.Soft.Protection & MM_COPY_ON_WRITE_MASK) 02842 == MM_COPY_ON_WRITE_MASK) { 02843 02844 // 02845 // This page is copy on write, charge ImageCommitment 02846 // for all pages in this subsection. 02847 // 02848 02849 ImageCommit = TRUE; 02850 } else { 02851 02852 // 02853 // This page is write shared, charge commitment when 02854 // the mapping completes. 02855 // 02856 02857 SectionCommit = TRUE; 02858 Subsection->u.SubsectionFlags.GlobalMemory = 1; 02859 ControlArea->u.Flags.GlobalMemory = 1; 02860 } 02861 } else { 02862 02863 // 02864 // Not writable, don't charge commitment at all. 02865 // 02866 02867 ImageCommit = FALSE; 02868 SectionCommit = FALSE; 02869 } 02870 02871 NewSegment->SegmentPteTemplate = TempPte; 02872 SectorOffset = 0; 02873 02874 for (i = 0; i < Subsection->PtesInSubsection; i += 1) { 02875 02876 // 02877 // Set all the prototype PTEs to refer to the control section. 02878 // 02879 02880 if (SectorOffset < SectionVirtualSize) { 02881 02882 // 02883 // Make PTE accessible. 02884 // 02885 02886 if (SectionCommit) { 02887 NewSegment->NumberOfCommittedPages += 1; 02888 } 02889 if (ImageCommit) { 02890 NewSegment->ImageCommitment += 1; 02891 } 02892 02893 if (SectorOffset < SectionTableEntry->SizeOfRawData) { 02894 02895 // 02896 // Data resides on the disk, use the subsection format PTE. 02897 // 02898 MI_WRITE_INVALID_PTE (PointerPte, TempPte); 02899 } else { 02900 02901 // 02902 // Demand zero pages. 02903 // 02904 MI_WRITE_INVALID_PTE (PointerPte, TempPteDemandZero); 02905 } 02906 } else { 02907 02908 // 02909 // No access pages. 02910 // 02911 02912 MI_WRITE_INVALID_PTE (PointerPte, ZeroPte); 02913 } 02914 SectorOffset += PAGE_SIZE; 02915 PointerPte += 1; 02916 NextVa += PAGE_SIZE; 02917 } 02918 02919 #if defined (_ALPHA_) || defined(_IA64_) 02920 } 02921 #endif 02922 02923 SectionTableEntry += 1; 02924 NumberOfSubsections -= 1; 02925 } 02926 02927 #if defined (_ALPHA_) || defined(_IA64_) 02928 if (!InvalidAlignmentAllowed) { 02929 #endif 02930 02931 // 02932 // Account for the number of subsections that really are mapped. 02933 // 02934 02935 ASSERT (ImageAlignment >= PAGE_SIZE); 02936 ControlArea->NumberOfSubsections += 1; 02937 02938 // 02939 // If the file size is not as big as the image claimed to be, 02940 // return an error. 02941 // 02942 02943 if (ImageFileSize > EndOfFile.LowPart) { 02944 02945 // 02946 // Invalid image size. 02947 // 02948 02949 KdPrint(("MMCREASECT: invalid image size - file size %lx - image size %lx\n %Z\n", 02950 EndOfFile.LowPart, ImageFileSize, &File->FileName)); 02951 goto BadPeImageSegment; 02952 } 02953 02954 // 02955 // The total number of PTEs was decremented as sections were built, 02956 // make sure that there are less than 64k's worth at this point. 02957 // 02958 02959 if (NumberOfPtes >= (ImageAlignment >> PAGE_SHIFT)) { 02960 02961 // 02962 // Inconsistent image, size does not agree with object tables. 02963 // 02964 02965 KdPrint(("MMCREASECT: invalid image - PTE left %lx\n image name %Z\n", 02966 NumberOfPtes, &File->FileName)); 02967 02968 goto BadPeImageSegment; 02969 } 02970 02971 // 02972 // Set any remaining PTEs to no access. 02973 // 02974 02975 while (NumberOfPtes != 0) { 02976 MI_WRITE_INVALID_PTE (PointerPte, ZeroPte); 02977 PointerPte += 1; 02978 NumberOfPtes -= 1; 02979 } 02980 02981 // 02982 // Turn the image header page into a transition page within the 02983 // prototype PTEs. 02984 // 02985 02986 if ((ExtendedHeader == NULL) && (SizeOfHeaders < PAGE_SIZE)) { 02987 02988 // 02989 // Zero remaining portion of header. 02990 // 02991 02992 RtlZeroMemory ((PVOID)((PCHAR)Base + 02993 SizeOfHeaders), 02994 PAGE_SIZE - SizeOfHeaders); 02995 } 02996 02997 02998 #if defined (_ALPHA_) || defined(_IA64_) 02999 } 03000 #endif 03001 03002 if (NewSegment->NumberOfCommittedPages != 0) { 03003 03004 // 03005 // Commit the pages for the image section. 03006 // 03007 03008 if (MiChargeCommitment (NewSegment->NumberOfCommittedPages, NULL) == FALSE) { 03009 Status = STATUS_COMMITMENT_LIMIT; 03010 ExFreePool (NewSegment); 03011 ExFreePool (ControlArea); 03012 goto NeImage; 03013 } 03014 03015 MM_TRACK_COMMIT (MM_DBG_COMMIT_IMAGE, NewSegment->NumberOfCommittedPages); 03016 Status = STATUS_SUCCESS; 03017 03018 ExAcquireFastMutex (&MmSectionCommitMutex); 03019 MmSharedCommit += NewSegment->NumberOfCommittedPages; 03020 ExReleaseFastMutex (&MmSectionCommitMutex); 03021 } 03022 03023 PeReturnSuccess: 03024 03025 // 03026 // If this image is global per session, then allocate a large control 03027 // area. Note this doesn't need to be done for systemwide global control 03028 // areas or non-global control areas. 03029 // 03030 03031 if ((MiHydra == TRUE) && 03032 (ControlArea->u.Flags.GlobalMemory) && 03033 ((LoaderFlags & IMAGE_LOADER_FLAGS_SYSTEM_GLOBAL) == 0)) { 03034 03035 LargeControlArea = ExAllocatePoolWithTag(NonPagedPool, 03036 (ULONG)(sizeof(LARGE_CONTROL_AREA) + 03037 (sizeof(SUBSECTION) * 03038 SubsectionsAllocated)), 03039 'iCmM'); 03040 if (LargeControlArea == NULL) { 03041 03042 // 03043 // The requested pool could not be allocated. 03044 // 03045 03046 if (NewSegment->NumberOfCommittedPages != 0) { 03047 MiReturnCommitment (NewSegment->NumberOfCommittedPages); 03048 MM_TRACK_COMMIT (MM_DBG_COMMIT_RETURN_IMAGE_NO_LARGE_CA, NewSegment->NumberOfCommittedPages); 03049 ExAcquireFastMutex (&MmSectionCommitMutex); 03050 MmSharedCommit -= NewSegment->NumberOfCommittedPages; 03051 ExReleaseFastMutex (&MmSectionCommitMutex); 03052 } 03053 03054 ExFreePool (NewSegment); 03055 ExFreePool (ControlArea); 03056 03057 03058 Status = STATUS_INSUFFICIENT_RESOURCES; 03059 03060 goto NeImage; 03061 } 03062 03063 // 03064 // Copy the normal control area into our larger one, fix the linkages, 03065 // Fill in the additional fields in the new one and free the old one. 03066 // 03067 03068 RtlMoveMemory (LargeControlArea, ControlArea, sizeof(CONTROL_AREA)); 03069 LargeControlArea->NonPagedPoolUsage = EX_REAL_POOL_USAGE( 03070 sizeof(LARGE_CONTROL_AREA) + 03071 (sizeof(SUBSECTION) * 03072 SubsectionsAllocated)); 03073 03074 ASSERT (ControlArea->u.Flags.GlobalOnlyPerSession == 0); 03075 03076 Subsection = (PSUBSECTION)(ControlArea + 1); 03077 NewSubsection = (PSUBSECTION)(LargeControlArea + 1); 03078 03079 for (i = 0; i < SubsectionsAllocated; i += 1) { 03080 RtlMoveMemory (NewSubsection, Subsection, sizeof(SUBSECTION)); 03081 NewSubsection->ControlArea = (PCONTROL_AREA) LargeControlArea; 03082 03083 PointerPte = NewSegment->PrototypePte; 03084 03085 TempPte.u.Long = MiGetSubsectionAddressForPte (NewSubsection); 03086 TempPte.u.Soft.Prototype = 1; 03087 03088 for (j = 0; j < NewSegment->TotalNumberOfPtes; j += 1) { 03089 03090 if ((PointerPte->u.Soft.Prototype == 1) && 03091 (MiGetSubsectionAddress (PointerPte) == Subsection)) { 03092 OriginalProtection = MI_GET_PROTECTION_FROM_SOFT_PTE (PointerPte); 03093 TempPte.u.Soft.Protection = OriginalProtection; 03094 MI_WRITE_INVALID_PTE (PointerPte, TempPte); 03095 } 03096 PointerPte += 1; 03097 } 03098 03099 Subsection += 1; 03100 NewSubsection += 1; 03101 } 03102 03103 NewSegment->ControlArea = (PCONTROL_AREA) LargeControlArea; 03104 03105 LargeControlArea->u.Flags.GlobalOnlyPerSession = 1; 03106 03107 LargeControlArea->SessionId = 0; 03108 InitializeListHead (&LargeControlArea->UserGlobalList); 03109 03110 ExFreePool (ControlArea); 03111 03112 ControlArea = (PCONTROL_AREA) LargeControlArea; 03113 } 03114 03115 MiUnmapImageHeaderInHyperSpace (); 03116 03117 // 03118 // Set the PFN database entry for this page to look like a transition 03119 // page. 03120 // 03121 03122 PointerPte = NewSegment->PrototypePte; 03123 03124 MiUpdateImageHeaderPage (PointerPte, PageFrameNumber, ControlArea); 03125 if (ExtendedHeader != NULL) { 03126 ExFreePool (ExtendedHeader); 03127 } 03128 ExFreePool (InPageEvent); 03129 03130 return STATUS_SUCCESS; 03131 03132 03133 // 03134 // Error returns from image verification. 03135 // 03136 03137 BadPeImageSegment: 03138 03139 ExFreePool (NewSegment); 03140 ExFreePool (ControlArea); 03141 03142 //BadPeImage: 03143 Status = STATUS_INVALID_IMAGE_FORMAT; 03144 03145 NeImage: 03146 MiUnmapImageHeaderInHyperSpace (); 03147 03148 BadSection: 03149 MiRemoveImageHeaderPage(PageFrameNumber); 03150 if (ExtendedHeader != NULL) { 03151 ExFreePool (ExtendedHeader); 03152 } 03153 ExFreePool (InPageEvent); 03154 return Status; 03155 }

NTSTATUS MiCreatePagingFileMap OUT PSEGMENT Segment,
IN PUINT64  MaximumSize,
IN ULONG  ProtectionMask,
IN ULONG  AllocationAttributes
 

Definition at line 4018 of file creasect.c.

References BYTES_TO_PAGES, CONTROL_AREA, _SUBSECTION::ControlArea, EX_REAL_POOL_USAGE, ExAllocatePoolWithTag, ExFreePool(), FALSE, MI_WRITE_INVALID_PTE, MiChargeCommitment(), MiReturnCommitment(), MM_DBG_COMMIT_PAGEFILE_BACKED_SHMEM, MM_DBG_COMMIT_RETURN_PAGEFILE_BACKED_SHMEM, MM_PROTO_PTE_ALIGNMENT, MM_TRACK_COMMIT, MMCONTROL, MMSECT, MmSectionCommitMutex, MmSharedCommit, NonPagedPool, _CONTROL_AREA::NonPagedPoolUsage, NULL, _CONTROL_AREA::NumberOfSectionReferences, _CONTROL_AREA::NumberOfSubsections, _CONTROL_AREA::NumberOfUserReferences, PAGE_SHIFT, PAGE_SIZE, PAGED_CODE, PagedPool, _CONTROL_AREA::PagedPoolUsage, PTE_SHIFT, _SUBSECTION::PtesInSubsection, ROUND_TO_PAGES, SEGMENT, _CONTROL_AREA::Segment, SUBSECTION, _SUBSECTION::SubsectionBase, _MMPTE::u, _SUBSECTION::u, _CONTROL_AREA::u, and ZeroPte.

Referenced by MmCreateSection().

04027 : 04028 04029 This function creates the necessary structures to allow the mapping 04030 of a paging file. 04031 04032 Arguments: 04033 04034 Segment - Returns the segment object. 04035 04036 MaximumSize - Supplies the maximum size for the mapping. 04037 04038 ProtectionMask - Supplies the initial page protection. 04039 04040 AllocationAttributes - Supplies the allocation attributes for the 04041 mapping. 04042 04043 Return Value: 04044 04045 Returns the status value. 04046 04047 TBS 04048 04049 04050 --*/ 04051 04052 04053 { 04054 PFN_NUMBER NumberOfPtes; 04055 ULONG SizeOfSegment; 04056 ULONG i; 04057 PCONTROL_AREA ControlArea; 04058 PSEGMENT NewSegment; 04059 PMMPTE PointerPte; 04060 PSUBSECTION Subsection; 04061 MMPTE TempPte; 04062 LARGE_INTEGER SpecifiedSize; 04063 04064 PAGED_CODE(); 04065 04066 //******************************************************************* 04067 // Create a section backed by paging file. 04068 //******************************************************************* 04069 04070 if (*MaximumSize == 0) { 04071 return STATUS_INVALID_PARAMETER_4; 04072 } 04073 04074 // 04075 // Limit page file backed sections to the pagefile maximum size. 04076 // 04077 04078 #if defined (_WIN64) || defined (_X86PAE_) 04079 SpecifiedSize.QuadPart = (ROUND_TO_PAGES (*MaximumSize)) >> PAGE_SHIFT; 04080 04081 if (SpecifiedSize.HighPart != 0) 04082 #else 04083 if (*MaximumSize > (((ULONGLONG) 4 * 1024 * 1024 * 1024)) - (1024 * 1024)) 04084 #endif 04085 { 04086 return STATUS_SECTION_TOO_BIG; 04087 } 04088 04089 // 04090 // Create the segment object. 04091 // 04092 04093 // 04094 // Calculate the number of prototype PTEs to build for this segment. 04095 // 04096 04097 NumberOfPtes = BYTES_TO_PAGES (*MaximumSize); 04098 04099 if (AllocationAttributes & SEC_COMMIT) { 04100 04101 // 04102 // Commit the pages for the section. 04103 // 04104 04105 if (MiChargeCommitment (NumberOfPtes, NULL) == FALSE) { 04106 return STATUS_COMMITMENT_LIMIT; 04107 } 04108 MM_TRACK_COMMIT (MM_DBG_COMMIT_PAGEFILE_BACKED_SHMEM, NumberOfPtes); 04109 } 04110 04111 SizeOfSegment = sizeof(SEGMENT) + sizeof(MMPTE) * ((ULONG)NumberOfPtes - 1); 04112 04113 NewSegment = ExAllocatePoolWithTag (PagedPool, SizeOfSegment, MMSECT); 04114 04115 if (NewSegment == NULL) { 04116 04117 // 04118 // The requested pool could not be allocated. 04119 // 04120 04121 if (AllocationAttributes & SEC_COMMIT) { 04122 MiReturnCommitment (NumberOfPtes); 04123 MM_TRACK_COMMIT (MM_DBG_COMMIT_RETURN_PAGEFILE_BACKED_SHMEM, NumberOfPtes); 04124 } 04125 return STATUS_INSUFFICIENT_RESOURCES; 04126 } 04127 04128 *Segment = NewSegment; 04129 04130 ControlArea = ExAllocatePoolWithTag (NonPagedPool, 04131 (ULONG)sizeof(CONTROL_AREA) + 04132 (ULONG)sizeof(SUBSECTION), 04133 MMCONTROL); 04134 04135 if (ControlArea == NULL) { 04136 04137 // 04138 // The requested pool could not be allocated. 04139 // 04140 04141 ExFreePool (NewSegment); 04142 04143 if (AllocationAttributes & SEC_COMMIT) { 04144 MM_TRACK_COMMIT (MM_DBG_COMMIT_RETURN_PAGEFILE_BACKED_SHMEM, NumberOfPtes); 04145 MiReturnCommitment (NumberOfPtes); 04146 } 04147 return STATUS_INSUFFICIENT_RESOURCES; 04148 } 04149 04150 // 04151 // Zero control area and first subsection. 04152 // 04153 04154 RtlZeroMemory (ControlArea, 04155 sizeof(CONTROL_AREA) + sizeof(SUBSECTION)); 04156 04157 ControlArea->NonPagedPoolUsage = EX_REAL_POOL_USAGE(sizeof(CONTROL_AREA) + sizeof(SUBSECTION)); 04158 04159 ControlArea->Segment = NewSegment; 04160 ControlArea->NumberOfSectionReferences = 1; 04161 ControlArea->NumberOfUserReferences = 1; 04162 ControlArea->NumberOfSubsections = 1; 04163 04164 if (AllocationAttributes & SEC_BASED) { 04165 ControlArea->u.Flags.Based = 1; 04166 } 04167 04168 if (AllocationAttributes & SEC_RESERVE) { 04169 ControlArea->u.Flags.Reserve = 1; 04170 } 04171 04172 if (AllocationAttributes & SEC_COMMIT) { 04173 ControlArea->u.Flags.Commit = 1; 04174 } 04175 04176 Subsection = (PSUBSECTION)(ControlArea + 1); 04177 04178 Subsection->ControlArea = ControlArea; 04179 Subsection->PtesInSubsection = (ULONG)NumberOfPtes; 04180 Subsection->u.SubsectionFlags.Protection = ProtectionMask; 04181 04182 // 04183 // Align the prototype PTEs on the proper boundary. 04184 // 04185 04186 PointerPte = &NewSegment->ThePtes[0]; 04187 i = (ULONG) (((ULONG_PTR)PointerPte >> PTE_SHIFT) & 04188 ((MM_PROTO_PTE_ALIGNMENT / PAGE_SIZE) - 1)); 04189 04190 if (i != 0) { 04191 i = (MM_PROTO_PTE_ALIGNMENT / PAGE_SIZE) - i; 04192 } 04193 04194 // 04195 // Zero the segment header. 04196 // 04197 04198 RtlZeroMemory (NewSegment, sizeof(SEGMENT)); 04199 04200 NewSegment->PrototypePte = &NewSegment->ThePtes[i]; 04201 04202 NewSegment->ControlArea = ControlArea; 04203 04204 // 04205 // As size is limited to 2gb, ignore the high part. 04206 // 04207 04208 NewSegment->SizeOfSegment = (ULONG_PTR)NumberOfPtes * PAGE_SIZE; 04209 NewSegment->TotalNumberOfPtes = (ULONG)NumberOfPtes; 04210 NewSegment->NonExtendedPtes = (ULONG)NumberOfPtes; 04211 04212 ControlArea->PagedPoolUsage = EX_REAL_POOL_USAGE((sizeof(SEGMENT) + (NumberOfPtes * sizeof(MMPTE)))); 04213 04214 PointerPte = NewSegment->PrototypePte; 04215 Subsection->SubsectionBase = PointerPte; 04216 TempPte = ZeroPte; 04217 04218 if (AllocationAttributes & SEC_COMMIT) { 04219 TempPte.u.Soft.Protection = ProtectionMask; 04220 04221 // 04222 // Record commitment charging. 04223 // 04224 04225 NewSegment->NumberOfCommittedPages = NumberOfPtes; 04226 04227 ExAcquireFastMutex (&MmSectionCommitMutex); 04228 MmSharedCommit += NewSegment->NumberOfCommittedPages; 04229 ExReleaseFastMutex (&MmSectionCommitMutex); 04230 } 04231 04232 NewSegment->SegmentPteTemplate.u.Soft.Protection = ProtectionMask; 04233 04234 for (i = 0; i < NumberOfPtes; i += 1) { 04235 04236 // 04237 // Set all the prototype PTEs to either no access or demand zero 04238 // depending on the commit flag. 04239 // 04240 04241 MI_WRITE_INVALID_PTE (PointerPte, TempPte); 04242 PointerPte += 1; 04243 } 04244 04245 return STATUS_SUCCESS; 04246 }

ULONG MiDecrementCloneBlockReference IN PMMCLONE_DESCRIPTOR  CloneDescriptor,
IN PMMCLONE_BLOCK  CloneBlock,
IN PEPROCESS  CurrentProcess
 

Definition at line 1745 of file forksup.c.

References APC_LEVEL, ASSERT, _MMCLONE_BLOCK::CloneRefCount, DbgPrint, ExFreePool(), FALSE, FreePageList, IS_PTE_NOT_DEMAND_ZERO, KeBugCheckEx(), LOCK_PFN, LOCK_WS_REGARDLESS, MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE, MI_PFN_ELEMENT, MI_SET_PFN_DELETED, MiDecrementShareCount(), MiInsertPageInList(), MiMakeSystemAddressValidPfnWs(), MiReleasePageFileSpace(), MiRemoveClone, MiUnlinkPageFromList(), MiWaitForForkToComplete(), MM_DBG_FORK, MM_FORK_SUCCEEDED, MmPageLocationList, NonPagedPool, _MMPFN::OriginalPte, PagedPool, PsReturnPoolQuota(), _MMPFN::PteFrame, TRUE, _MMPTE::u, _MMPFN::u3, UNLOCK_PFN, UNLOCK_WS_REGARDLESS, and ZeroPte.

Referenced by MiCopyOnWrite(), MiDeletePte(), and MiDeleteValidAddress().

01753 : 01754 01755 This routine decrements the reference count field of a "fork prototype 01756 PTE" (clone-block). If the reference count becomes zero, the reference 01757 count for the clone-descriptor is decremented and if that becomes zero, 01758 it is deallocated and the number of process count for the clone header is 01759 decremented. If the number of process count becomes zero, the clone 01760 header is deallocated. 01761 01762 Arguments: 01763 01764 CloneDescriptor - Supplies the clone descriptor which describes the 01765 clone block. 01766 01767 CloneBlock - Supplies the clone block to decrement the reference count of. 01768 01769 CurrentProcess - Supplies the current process. 01770 01771 Return Value: 01772 01773 TRUE if the working set mutex was released, FALSE if it was not. 01774 01775 Environment: 01776 01777 Kernel mode, APCs disabled, working set mutex and PFN mutex held. 01778 01779 --*/ 01780 01781 { 01782 01783 ULONG MutexReleased; 01784 MMPTE CloneContents; 01785 PMMPFN Pfn3; 01786 KIRQL OldIrql; 01787 LONG NewCount; 01788 LOGICAL WsHeldSafe; 01789 01790 MutexReleased = FALSE; 01791 OldIrql = APC_LEVEL; 01792 01793 MutexReleased = MiMakeSystemAddressValidPfnWs (CloneBlock, CurrentProcess); 01794 01795 while (CurrentProcess->ForkInProgress) { 01796 MiWaitForForkToComplete (CurrentProcess); 01797 MiMakeSystemAddressValidPfnWs (CloneBlock, CurrentProcess); 01798 MutexReleased = TRUE; 01799 } 01800 01801 CloneBlock->CloneRefCount -= 1; 01802 NewCount = CloneBlock->CloneRefCount; 01803 01804 ASSERT (NewCount >= 0); 01805 01806 if (NewCount == 0) { 01807 CloneContents = CloneBlock->ProtoPte; 01808 } else { 01809 CloneContents = ZeroPte; 01810 } 01811 01812 if ((NewCount == 0) && (CloneContents.u.Long != 0)) { 01813 01814 // 01815 // The last reference to a fork prototype PTE 01816 // has been removed. Deallocate any page file 01817 // space and the transition page, if any. 01818 // 01819 01820 01821 // 01822 // Assert that the page is no longer valid. 01823 // 01824 01825 ASSERT (CloneContents.u.Hard.Valid == 0); 01826 01827 // 01828 // Assert that the PTE is not in subsection format (doesn't point 01829 // to a file). 01830 // 01831 01832 ASSERT (CloneContents.u.Soft.Prototype == 0); 01833 01834 if (CloneContents.u.Soft.Transition == 1) { 01835 01836 // 01837 // Prototype PTE in transition, put the page 01838 // on the free list. 01839 // 01840 01841 Pfn3 = MI_PFN_ELEMENT (CloneContents.u.Trans.PageFrameNumber); 01842 MI_SET_PFN_DELETED (Pfn3); 01843 01844 MiDecrementShareCount (Pfn3->PteFrame); 01845 01846 // 01847 // Check the reference count for the page, if the reference 01848 // count is zero and the page is not on the freelist, 01849 // move the page to the free list, if the reference 01850 // count is not zero, ignore this page. 01851 // When the reference count goes to zero, it will be placed on the 01852 // free list. 01853 // 01854 01855 if ((Pfn3->u3.e2.ReferenceCount == 0) && 01856 (Pfn3->u3.e1.PageLocation != FreePageList)) { 01857 01858 MiUnlinkPageFromList (Pfn3); 01859 MiReleasePageFileSpace (Pfn3->OriginalPte); 01860 MiInsertPageInList (MmPageLocationList[FreePageList], 01861 MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE(&CloneContents)); 01862 } 01863 } else { 01864 01865 if (IS_PTE_NOT_DEMAND_ZERO (CloneContents)) { 01866 MiReleasePageFileSpace (CloneContents); 01867 } 01868 } 01869 } 01870 01871 // 01872 // Decrement the number of references to the 01873 // clone descriptor. 01874 // 01875 01876 CloneDescriptor->NumberOfReferences -= 1; 01877 01878 if (CloneDescriptor->NumberOfReferences == 0) { 01879 01880 // 01881 // There are no longer any PTEs in this process which refer 01882 // to the fork prototype PTEs for this clone descriptor. 01883 // Remove the CloneDescriptor and decrement the CloneHeader 01884 // number of process's reference count. 01885 // 01886 01887 CloneDescriptor->CloneHeader->NumberOfProcessReferences -= 1; 01888 01889 MiRemoveClone (CloneDescriptor); 01890 01891 if (CloneDescriptor->CloneHeader->NumberOfProcessReferences == 0) { 01892 01893 // 01894 // There are no more processes pointing to this fork header 01895 // blow it away. 01896 // 01897 01898 UNLOCK_PFN (OldIrql); 01899 01900 // 01901 // The working set lock may have been acquired safely or unsafely 01902 // by our caller. Handle both cases here and below. 01903 // 01904 01905 UNLOCK_WS_REGARDLESS (CurrentProcess, WsHeldSafe); 01906 01907 MutexReleased = TRUE; 01908 01909 01910 #if DBG 01911 { 01912 01913 ULONG i; 01914 PMMCLONE_BLOCK OldCloneBlock; 01915 01916 OldCloneBlock = CloneDescriptor->CloneHeader->ClonePtes; 01917 for (i = 0; i < CloneDescriptor->CloneHeader->NumberOfPtes; i += 1) { 01918 if (OldCloneBlock->CloneRefCount != 0) { 01919 DbgPrint("fork block with non zero ref count %lx %lx %lx\n", 01920 OldCloneBlock, CloneDescriptor, 01921 CloneDescriptor->CloneHeader); 01922 KeBugCheckEx (MEMORY_MANAGEMENT, 1, 0, 0, 0); 01923 } 01924 } 01925 01926 if (MmDebug & MM_DBG_FORK) { 01927 DbgPrint("removing clone header at address %lx\n", 01928 CloneDescriptor->CloneHeader); 01929 } 01930 01931 } 01932 #endif //DBG 01933 01934 ExFreePool (CloneDescriptor->CloneHeader->ClonePtes); 01935 01936 ExFreePool (CloneDescriptor->CloneHeader); 01937 01938 // 01939 // The working set lock may have been acquired safely or unsafely 01940 // by our caller. Reacquire it in the same manner our caller did. 01941 // 01942 01943 LOCK_WS_REGARDLESS (CurrentProcess, WsHeldSafe); 01944 01945 LOCK_PFN (OldIrql); 01946 } 01947 01948 #if DBG 01949 if (MmDebug & MM_DBG_FORK) { 01950 DbgPrint("removing clone descriptor at address %lx\n",CloneDescriptor); 01951 } 01952 #endif //DBG 01953 01954 // 01955 // Return the pool for the global structures referenced by the 01956 // clone descriptor. 01957 // 01958 01959 UNLOCK_PFN (OldIrql); 01960 01961 if (CurrentProcess->ForkWasSuccessful == MM_FORK_SUCCEEDED) { 01962 01963 PsReturnPoolQuota (CurrentProcess, 01964 PagedPool, 01965 CloneDescriptor->PagedPoolQuotaCharge); 01966 01967 PsReturnPoolQuota (CurrentProcess, 01968 NonPagedPool, 01969 sizeof(MMCLONE_HEADER)); 01970 } 01971 01972 ExFreePool (CloneDescriptor); 01973 LOCK_PFN (OldIrql); 01974 } 01975 01976 return MutexReleased; 01977 }

VOID FASTCALL MiDecrementReferenceCount IN PFN_NUMBER  PageFrameIndex  ) 
 

Definition at line 167 of file pfndec.c.

References ActiveAndValid, ASSERT, BadPageList, FreePageList, KeBugCheckEx(), MI_IS_PFN_DELETED, MI_PFN_ELEMENT, MiInsertPageInList(), MiInsertStandbyListAtFront(), MiReleasePageFileSpace(), MiRestoreTransitionPte(), MM_PFN_LOCK_ASSERT, MmFrontOfList, MmHighestPhysicalPage, MmPageLocationList, ModifiedPageList, _MMPFN::OriginalPte, StandbyPageList, _MMPFN::u2, and _MMPFN::u3.

Referenced by MiCleanSection(), MiDecrementShareCount(), MiDispatchFault(), MiDownPfnReferenceCount(), MiFlushSectionInternal(), MiFreeNonPagedPool(), MiInitMachineDependent(), MiRemoveImageHeaderPage(), MiResolveTransitionFault(), MiSessionCreateInternal(), MiUnlockPagedAddress(), MiUpdateImageHeaderPage(), MiWriteComplete(), MmFreePagesFromMdl(), MmRemovePhysicalMemory(), MmReturnMemoryForHibernate(), MmShutdownSystem(), MmTrimAllSystemPagableMemory(), MmUnlockPagableImageSection(), MmUnlockPagedPool(), and MmUnlockPages().

00173 : 00174 00175 This routine decrements the reference count for the specified page. 00176 If the reference count becomes zero, the page is placed on the 00177 appropriate list (free, modified, standby or bad). If the page 00178 is placed on the free or standby list, the number of available 00179 pages is incremented and if it transitions from zero to one, the 00180 available page event is set. 00181 00182 00183 Arguments: 00184 00185 PageFrameIndex - Supplies the physical page number of which to 00186 decrement the reference count. 00187 00188 Return Value: 00189 00190 none. 00191 00192 Environment: 00193 00194 Must be holding the PFN database mutex with APCs disabled. 00195 00196 --*/ 00197 00198 { 00199 PMMPFN Pfn1; 00200 00201 MM_PFN_LOCK_ASSERT(); 00202 00203 ASSERT (PageFrameIndex <= MmHighestPhysicalPage); 00204 00205 Pfn1 = MI_PFN_ELEMENT (PageFrameIndex); 00206 ASSERT (Pfn1->u3.e2.ReferenceCount != 0); 00207 Pfn1->u3.e2.ReferenceCount -= 1; 00208 00209 00210 if (Pfn1->u3.e2.ReferenceCount != 0) { 00211 00212 // 00213 // The reference count is not zero, return. 00214 // 00215 00216 return; 00217 } 00218 00219 // 00220 // The reference count is now zero, put the page on some 00221 // list. 00222 // 00223 00224 00225 if (Pfn1->u2.ShareCount != 0) { 00226 00227 KeBugCheckEx (PFN_LIST_CORRUPT, 00228 7, 00229 PageFrameIndex, 00230 Pfn1->u2.ShareCount, 00231 0); 00232 return; 00233 } 00234 00235 ASSERT (Pfn1->u3.e1.PageLocation != ActiveAndValid); 00236 00237 if (MI_IS_PFN_DELETED (Pfn1)) { 00238 00239 // 00240 // There is no referenced PTE for this page, delete the page file 00241 // space (if any), and place the page on the free list. 00242 // 00243 00244 MiReleasePageFileSpace (Pfn1->OriginalPte); 00245 00246 if (Pfn1->u3.e1.RemovalRequested == 1) { 00247 MiInsertPageInList (MmPageLocationList[BadPageList], 00248 PageFrameIndex); 00249 } 00250 else { 00251 MiInsertPageInList (MmPageLocationList[FreePageList], 00252 PageFrameIndex); 00253 } 00254 00255 return; 00256 } 00257 00258 // 00259 // Place the page on the modified or standby list depending 00260 // on the state of the modify bit in the PFN element. 00261 // 00262 00263 if (Pfn1->u3.e1.Modified == 1) { 00264 MiInsertPageInList (MmPageLocationList[ModifiedPageList], PageFrameIndex); 00265 } else { 00266 00267 if (Pfn1->u3.e1.RemovalRequested == 1) { 00268 00269 // 00270 // The page may still be marked as on the modified list if the 00271 // current thread is the modified writer completing the write. 00272 // Mark it as standby so restoration of the transition PTE 00273 // doesn't flag this as illegal. 00274 // 00275 00276 Pfn1->u3.e1.PageLocation = StandbyPageList; 00277 00278 MiRestoreTransitionPte (PageFrameIndex); 00279 MiInsertPageInList (MmPageLocationList[BadPageList], 00280 PageFrameIndex); 00281 return; 00282 } 00283 00284 if (!MmFrontOfList) { 00285 MiInsertPageInList (MmPageLocationList[StandbyPageList], 00286 PageFrameIndex); 00287 } else { 00288 MiInsertStandbyListAtFront (PageFrameIndex); 00289 } 00290 } 00291 00292 return; 00293 } }

VOID FASTCALL MiDecrementShareCount IN PFN_NUMBER  PageFrameIndex  ) 
 

Definition at line 30 of file pfndec.c.

References ActiveAndValid, ASSERT, KeBugCheckEx(), MI_MAKE_VALID_PTE_TRANSITION, MI_PFN_ELEMENT, MI_WRITE_INVALID_PTE, MiDecrementReferenceCount(), MiGetByteOffset, MiMapPageInHyperSpace(), MiUnmapPageInHyperSpace, MmHighestPhysicalPage, MmIsAddressValid(), _MMPFN::OriginalPte, PERFINFO_DECREFCNT, _MMPFN::PteAddress, _MMPFN::PteFrame, StandbyPageList, TransitionPage, _MMPTE::u, _MMPFN::u2, and _MMPFN::u3.

Referenced by MiCleanSection(), MiCopyOnWrite(), MiDecommitPages(), MiDecrementCloneBlockReference(), MiDeletePte(), MiDeleteSystemPagableVm(), MiDeleteValidAddress(), MiEliminateWorkingSetEntry(), MiEnablePagingOfDriverAtInit(), MiHandleForkTransitionPte(), MiPurgeImageSection(), MiRemoveMappedPtes(), MiRestoreTransitionPte(), MiSegmentDelete(), MiSessionCopyOnWrite(), MiSetPagingOfDriver(), MmFreeSpecialPool(), MmOutPageKernelStack(), MmOutSwapProcess(), MmPurgeSection(), and MmUnmapViewInSystemCache().

00036 : 00037 00038 This routine decrements the share count within the PFN element 00039 for the specified physical page. If the share count becomes 00040 zero the corresponding PTE is converted to the transition state 00041 and the reference count is decremented and the ValidPte count 00042 of the PTEframe is decremented. 00043 00044 Arguments: 00045 00046 PageFrameIndex - Supplies the physical page number of which to decrement 00047 the share count. 00048 00049 Return Value: 00050 00051 None. 00052 00053 Environment: 00054 00055 Must be holding the PFN database mutex with APCs disabled. 00056 00057 --*/ 00058 00059 { 00060 MMPTE TempPte; 00061 PMMPTE PointerPte; 00062 PMMPFN Pfn1; 00063 KIRQL OldIrql; 00064 00065 ASSERT ((PageFrameIndex <= MmHighestPhysicalPage) && 00066 (PageFrameIndex > 0)); 00067 00068 Pfn1 = MI_PFN_ELEMENT (PageFrameIndex); 00069 00070 if (Pfn1->u3.e1.PageLocation != ActiveAndValid && 00071 Pfn1->u3.e1.PageLocation != StandbyPageList) { 00072 KeBugCheckEx (PFN_LIST_CORRUPT, 00073 0x99, 00074 PageFrameIndex, 00075 Pfn1->u3.e1.PageLocation, 00076 0); 00077 } 00078 00079 #if PFN_CONSISTENCY 00080 if (Pfn1->u3.e1.PageTablePage == 1) { 00081 00082 // Need to run the page and see if the number of transition & valid 00083 // pages + 1 matches up to the share count. 00084 // 00085 // For the page being freed (share == 1), need to snap the caller here 00086 00087 } 00088 #endif 00089 00090 Pfn1->u2.ShareCount -= 1; 00091 00092 PERFINFO_DECREFCNT(Pfn1, PERFINFO_LOG_WSCHANGE, PERFINFO_LOG_TYPE_DECSHARCNT) 00093 00094 ASSERT (Pfn1->u2.ShareCount < 0xF000000); 00095 00096 if (Pfn1->u2.ShareCount == 0) { 00097 00098 PERFINFO_DECREFCNT(Pfn1, PERFINFO_LOG_EMPTYQ, PERFINFO_LOG_TYPE_ZEROSHARECOUNT) 00099 00100 // 00101 // The share count is now zero, decrement the reference count 00102 // for the PFN element and turn the referenced PTE into 00103 // the transition state if it refers to a prototype PTE. 00104 // PTEs which are not prototype PTEs do not need to be placed 00105 // into transition as they are placed in transition when 00106 // they are removed from the working set (working set free routine). 00107 // 00108 00109 // 00110 // If the PTE referenced by this PFN element is actually 00111 // a prototype PTE, it must be mapped into hyperspace and 00112 // then operated on. 00113 // 00114 00115 if (Pfn1->u3.e1.PrototypePte == 1) { 00116 00117 OldIrql = 99; 00118 if (MmIsAddressValid (Pfn1->PteAddress)) { 00119 PointerPte = Pfn1->PteAddress; 00120 } else { 00121 00122 // 00123 // The address is not valid in this process, map it into 00124 // hyperspace so it can be operated upon. 00125 // 00126 00127 PointerPte = (PMMPTE)MiMapPageInHyperSpace(Pfn1->PteFrame, 00128 &OldIrql); 00129 PointerPte = (PMMPTE)((PCHAR)PointerPte + 00130 MiGetByteOffset(Pfn1->PteAddress)); 00131 } 00132 00133 TempPte = *PointerPte; 00134 MI_MAKE_VALID_PTE_TRANSITION (TempPte, 00135 Pfn1->OriginalPte.u.Soft.Protection); 00136 MI_WRITE_INVALID_PTE (PointerPte, TempPte); 00137 00138 if (OldIrql != 99) { 00139 MiUnmapPageInHyperSpace (OldIrql); 00140 } 00141 00142 // 00143 // There is no need to flush the translation buffer at this 00144 // time as we only invalidated a prototype PTE. 00145 // 00146 00147 } 00148 00149 // 00150 // Change the page location to inactive (from active and valid). 00151 // 00152 00153 Pfn1->u3.e1.PageLocation = TransitionPage; 00154 00155 // 00156 // Decrement the reference count as the share count is now zero. 00157 // 00158 00159 MiDecrementReferenceCount (PageFrameIndex); 00160 } 00161 00162 return; 00163 }

VOID MiDeletePageTablesForPhysicalRange IN PVOID  StartingAddress,
IN PVOID  EndingAddress
 

Definition at line 2361 of file allocvm.c.

References ADDRESS_AND_SIZE_TO_SPAN_PAGES, ASSERT, FALSE, LOCK_PFN, MI_DECREMENT_USED_PTES_BY_HANDLE, MI_GET_USED_PTES_FROM_HANDLE, MI_GET_USED_PTES_HANDLE, MI_PFN_ELEMENT, MiDeletePte(), MiGetPdeAddress, MiGetPteAddress, MiGetVirtualAddressMappedByPte, MiIsPteOnPdeBoundary, MiIsPteOnPpeBoundary, MM_BUMP_COUNTER, MMPTE, MmResidentAvailablePages, NULL, PAGE_SIZE, PsGetCurrentProcess, _MMPTE::u, _MMPFN::u2, and UNLOCK_PFN.

Referenced by MmCleanProcessAddressSpace(), and NtFreeVirtualMemory().

02368 : 02369 02370 This routine deletes page directory and page table pages for a 02371 user-controlled physical range of pages. 02372 02373 Even though PTEs may be zero in this range, UsedPageTable counts were 02374 incremented for these special ranges and must be decremented now. 02375 02376 Arguments: 02377 02378 StartingAddress - Supplies the starting address of the range. 02379 02380 EndingAddress - Supplies the ending address of the range. 02381 02382 Return Value: 02383 02384 None. 02385 02386 Environment: 02387 02388 Kernel mode, APCs disabled, WorkingSetMutex and AddressCreation mutexes 02389 held. 02390 02391 --*/ 02392 02393 { 02394 PVOID TempVa; 02395 MMPTE PteContents; 02396 PMMPTE LastPte; 02397 PMMPTE LastPde; 02398 PMMPTE PointerPte; 02399 PMMPTE PointerPde; 02400 PMMPTE PointerPpe; 02401 ULONG PagesNeeded; 02402 PEPROCESS CurrentProcess; 02403 PVOID UsedPageTableHandle; 02404 PVOID UsedPageDirectoryHandle; 02405 KIRQL OldIrql; 02406 PMMPFN Pfn1; 02407 02408 CurrentProcess = PsGetCurrentProcess(); 02409 02410 PointerPde = MiGetPdeAddress (StartingAddress); 02411 PointerPte = MiGetPteAddress (StartingAddress); 02412 LastPde = MiGetPdeAddress (EndingAddress); 02413 LastPte = MiGetPteAddress (EndingAddress); 02414 02415 UsedPageTableHandle = MI_GET_USED_PTES_HANDLE (StartingAddress); 02416 02417 // 02418 // Each PTE is already zeroed - just delete the containing pages. 02419 // 02420 02421 // 02422 // Restore resident available pages for all of the page directory and table 02423 // pages as they can now be paged again. 02424 // 02425 02426 if (LastPte != PointerPte) { 02427 PagesNeeded = ADDRESS_AND_SIZE_TO_SPAN_PAGES (PointerPte, 02428 (ULONG)(LastPte - PointerPte) * sizeof (MMPTE)); 02429 02430 #if defined (_WIN64) 02431 if (LastPde != PointerPde) { 02432 PagesNeeded += ADDRESS_AND_SIZE_TO_SPAN_PAGES (PointerPde, 02433 (ULONG)(LastPde - PointerPde) * sizeof (MMPTE)); 02434 } 02435 #endif 02436 } 02437 else { 02438 PagesNeeded = 1; 02439 #if defined (_WIN64) 02440 PagesNeeded += 1; 02441 #endif 02442 } 02443 02444 LOCK_PFN (OldIrql); 02445 02446 MmResidentAvailablePages += PagesNeeded; 02447 MM_BUMP_COUNTER(59, PagesNeeded); 02448 02449 while (StartingAddress <= EndingAddress) { 02450 02451 ASSERT (PointerPte->u.Long == 0); 02452 02453 PointerPte += 1; 02454 02455 MI_DECREMENT_USED_PTES_BY_HANDLE (UsedPageTableHandle); 02456 02457 if ((MiIsPteOnPdeBoundary(PointerPte)) || (PointerPte > LastPte)) { 02458 02459 // 02460 // The virtual address is on a page directory boundary or it is 02461 // the last address in the entire range. 02462 // 02463 // If all the entries have been eliminated from the previous 02464 // page table page, delete the page table page itself. 02465 // 02466 02467 PointerPde = MiGetPteAddress (PointerPte - 1); 02468 ASSERT (PointerPde->u.Hard.Valid == 1); 02469 02470 // 02471 // Down the sharecount on the finished page table page. 02472 // 02473 02474 PteContents = *PointerPde; 02475 Pfn1 = MI_PFN_ELEMENT (PteContents.u.Hard.PageFrameNumber); 02476 ASSERT (Pfn1->u2.ShareCount > 1); 02477 Pfn1->u2.ShareCount -= 1; 02478 02479 // 02480 // If all the entries have been eliminated from the previous 02481 // page table page, delete the page table page itself. 02482 // 02483 02484 if (MI_GET_USED_PTES_FROM_HANDLE (UsedPageTableHandle) == 0) { 02485 02486 TempVa = MiGetVirtualAddressMappedByPte(PointerPde); 02487 MiDeletePte (PointerPde, 02488 TempVa, 02489 FALSE, 02490 CurrentProcess, 02491 NULL, 02492 NULL); 02493 02494 #if defined (_WIN64) 02495 UsedPageDirectoryHandle = MI_GET_USED_PTES_HANDLE (PointerPte - 1); 02496 MI_DECREMENT_USED_PTES_BY_HANDLE (UsedPageDirectoryHandle); 02497 #endif 02498 } 02499 02500 #if defined (_WIN64) 02501 if ((MiIsPteOnPpeBoundary(PointerPte)) || (PointerPte > LastPte)) { 02502 02503 PointerPpe = MiGetPteAddress (PointerPde); 02504 ASSERT (PointerPpe->u.Hard.Valid == 1); 02505 02506 UsedPageDirectoryHandle = MI_GET_USED_PTES_HANDLE (PointerPte - 1); 02507 // 02508 // Down the sharecount on the finished page directory page. 02509 // 02510 02511 PteContents = *PointerPpe; 02512 Pfn1 = MI_PFN_ELEMENT (PteContents.u.Hard.PageFrameNumber); 02513 ASSERT (Pfn1->u2.ShareCount > 1); 02514 Pfn1->u2.ShareCount -= 1; 02515 02516 // 02517 // If all the entries have been eliminated from the previous 02518 // page directory page, delete the page directory page itself. 02519 // 02520 02521 if (MI_GET_USED_PTES_FROM_HANDLE (UsedPageDirectoryHandle) == 0) { 02522 TempVa = MiGetVirtualAddressMappedByPte(PointerPpe); 02523 MiDeletePte (PointerPpe, 02524 TempVa, 02525 FALSE, 02526 CurrentProcess, 02527 NULL, 02528 NULL); 02529 } 02530 } 02531 #endif 02532 02533 if (PointerPte > LastPte) { 02534 break; 02535 } 02536 02537 // 02538 // Release the PFN lock. This prevents a single thread 02539 // from forcing other high priority threads from being 02540 // blocked while a large address range is deleted. 02541 // 02542 02543 UNLOCK_PFN (OldIrql); 02544 UsedPageTableHandle = MI_GET_USED_PTES_HANDLE ((PVOID)((PUCHAR)StartingAddress + PAGE_SIZE)); 02545 LOCK_PFN (OldIrql); 02546 } 02547 02548 StartingAddress = (PVOID)((PUCHAR)StartingAddress + PAGE_SIZE); 02549 } 02550 02551 UNLOCK_PFN (OldIrql); 02552 02553 // 02554 // All done, return. 02555 // 02556 02557 return; 02558 }

VOID MiDeletePte IN PMMPTE  PointerPte,
IN PVOID  VirtualAddress,
IN ULONG  AddressSpaceDeletion,
IN PEPROCESS  CurrentProcess,
IN PMMPTE  PrototypePte,
IN PMMPTE_FLUSH_LIST PteFlushList  OPTIONAL
 

Definition at line 506 of file deleteva.c.

References ASSERT, DbgPrint, _MMWSLE::e1, FALSE, _MMWSL::FirstDynamic, FreePageList, KeBugCheckEx(), KeFlushSingleTb(), _MMWSLENTRY::LockedInMemory, _MMWSLENTRY::LockedInWs, MI_CAPTURE_DIRTY_BIT_TO_PFN, MI_GET_PAGE_FRAME_FROM_PTE, MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE, MI_PFN_ELEMENT, MI_PTE_LOOKUP_NEEDED, MI_SET_PFN_DELETED, MI_WRITE_INVALID_PTE, MiCheckPdeForPagedPool(), MiDecrementCloneBlockReference(), MiDecrementShareAndValidCount, MiDecrementShareCount(), MiDecrementShareCountOnly, MiDoesPdeExistAndMakeValid(), MiDoesPpeExistAndMakeValid, MiFlushPteList(), MiFormatPfn(), MiFormatPte(), MiGetPteAddress, MiGetVirtualAddressMappedByPte, MiHighestUserPte, MiInsertPageInList(), MiLocateCloneAddress, MiLocateWsle(), MiPteToProto, MiReleasePageFileSpace(), MiReleaseWsle(), MiRemoveWsle(), MiSwapWslEntries(), MiUnlinkPageFromList(), MM_DBG_PTE_UPDATE, MM_MAXIMUM_FLUSH_COUNT, MM_PFN_LOCK_ASSERT, MmPageLocationList, MmWorkingSetList, MmWsle, MMWSLENTRY, NT_SUCCESS, NULL, _MMPFN::OriginalPte, PAGE_ALIGN, PMMCLONE_BLOCK, PMMCLONE_DESCRIPTOR, PMMPTE_FLUSH_LIST, PrototypePte, _MMPFN::PteAddress, _MMPFN::PteFrame, TRUE, _MMPTE::u, _MMWSLE::u1, _MMPFN::u1, _MMPFN::u2, _MMPFN::u3, _MMWSLENTRY::Valid, WSLE_NULL_INDEX, and ZeroPte.

Referenced by MiDecommitPages(), MiDeletePageTablesForPhysicalRange(), MiDeleteVirtualAddresses(), MiGrowWsleHash(), MiRemoveMappedView(), MiRemoveWorkingSetPages(), MiUnmapLockedPagesInUserSpace(), and MmCleanProcessAddressSpace().

00517 : 00518 00519 This routine deletes the contents of the specified PTE. The PTE 00520 can be in one of the following states: 00521 00522 - active and valid 00523 - transition 00524 - in paging file 00525 - in prototype PTE format 00526 00527 Arguments: 00528 00529 PointerPte - Supplies a pointer to the PTE to delete. 00530 00531 VirtualAddress - Supplies the virtual address which corresponds to 00532 the PTE. This is used to locate the working set entry 00533 to eliminate it. 00534 00535 AddressSpaceDeletion - Supplies TRUE if the address space is being 00536 deleted, FALSE otherwise. If TRUE is specified 00537 the TB is not flushed and valid addresses are 00538 not removed from the working set. 00539 00540 00541 CurrentProcess - Supplies a pointer to the current process. 00542 00543 PrototypePte - Supplies a pointer to the prototype PTE which currently 00544 or originally mapped this page. This is used to determine 00545 if the PTE is a fork PTE and should have its reference block 00546 decremented. 00547 00548 Return Value: 00549 00550 None. 00551 00552 Environment: 00553 00554 Kernel mode, APCs disabled, PFN lock and working set mutex held. 00555 00556 --*/ 00557 00558 { 00559 PMMPTE PointerPde; 00560 PMMPTE PointerPpe; 00561 PMMPFN Pfn1; 00562 PMMPFN Pfn2; 00563 MMPTE PteContents; 00564 ULONG WorkingSetIndex; 00565 ULONG Entry; 00566 PVOID SwapVa; 00567 MMWSLENTRY Locked; 00568 ULONG WsPfnIndex; 00569 PMMCLONE_BLOCK CloneBlock; 00570 PMMCLONE_DESCRIPTOR CloneDescriptor; 00571 ULONG Waited; 00572 00573 MM_PFN_LOCK_ASSERT(); 00574 00575 #if DBG 00576 if (MmDebug & MM_DBG_PTE_UPDATE) { 00577 DbgPrint("deleting PTE\n"); 00578 MiFormatPte(PointerPte); 00579 } 00580 #endif //DBG 00581 00582 PteContents = *PointerPte; 00583 00584 if (PteContents.u.Hard.Valid == 1) { 00585 00586 #ifdef _X86_ 00587 #if DBG 00588 #if !defined(NT_UP) 00589 00590 if (PteContents.u.Hard.Writable == 1) { 00591 ASSERT (PteContents.u.Hard.Dirty == 1); 00592 } 00593 ASSERT (PteContents.u.Hard.Accessed == 1); 00594 #endif //NTUP 00595 #endif //DBG 00596 #endif //X86 00597 00598 // 00599 // PTE is valid. Check PFN database to see if this is a prototype PTE. 00600 // 00601 00602 Pfn1 = MI_PFN_ELEMENT (PteContents.u.Hard.PageFrameNumber); 00603 WsPfnIndex = Pfn1->u1.WsIndex; 00604 00605 #if DBG 00606 if (MmDebug & MM_DBG_PTE_UPDATE) { 00607 MiFormatPfn(Pfn1); 00608 } 00609 #endif //DBG 00610 00611 CloneDescriptor = NULL; 00612 00613 if (Pfn1->u3.e1.PrototypePte == 1) { 00614 00615 CloneBlock = (PMMCLONE_BLOCK)Pfn1->PteAddress; 00616 00617 // 00618 // Capture the state of the modified bit for this PTE. 00619 // 00620 00621 MI_CAPTURE_DIRTY_BIT_TO_PFN (PointerPte, Pfn1); 00622 00623 // 00624 // Decrement the share and valid counts of the page table 00625 // page which maps this PTE. 00626 // 00627 00628 PointerPde = MiGetPteAddress (PointerPte); 00629 if (PointerPde->u.Hard.Valid == 0) { 00630 #if !defined (_WIN64) 00631 if (!NT_SUCCESS(MiCheckPdeForPagedPool (PointerPte))) { 00632 #endif 00633 KeBugCheckEx (MEMORY_MANAGEMENT, 00634 0x61940, 00635 (ULONG_PTR)PointerPte, 00636 (ULONG_PTR)PointerPde->u.Long, 00637 (ULONG_PTR)MiGetVirtualAddressMappedByPte(PointerPte)); 00638 #if !defined (_WIN64) 00639 } 00640 #endif 00641 } 00642 MiDecrementShareAndValidCount (MI_GET_PAGE_FRAME_FROM_PTE (PointerPde)); 00643 00644 // 00645 // Decrement the share count for the physical page. 00646 // 00647 00648 MiDecrementShareCount (MI_GET_PAGE_FRAME_FROM_PTE (&PteContents)); 00649 00650 // 00651 // Check to see if this is a fork prototype PTE and if so 00652 // update the clone descriptor address. 00653 // 00654 00655 if (PointerPte <= MiHighestUserPte) { 00656 00657 if (PrototypePte != Pfn1->PteAddress) { 00658 00659 // 00660 // Locate the clone descriptor within the clone tree. 00661 // 00662 00663 CloneDescriptor = MiLocateCloneAddress ((PVOID)CloneBlock); 00664 00665 #if DBG 00666 if (CloneDescriptor == NULL) { 00667 DbgPrint("1PrototypePte %p Clone desc %p pfn pte addr %p\n", 00668 PrototypePte, CloneDescriptor, Pfn1->PteAddress); 00669 MiFormatPte(PointerPte); 00670 ASSERT (FALSE); 00671 } 00672 #endif // DBG 00673 00674 } 00675 } 00676 } else { 00677 00678 ASSERT (Pfn1->u2.ShareCount == 1); 00679 00680 // 00681 // This PTE is a NOT a prototype PTE, delete the physical page. 00682 // 00683 00684 // 00685 // Decrement the share and valid counts of the page table 00686 // page which maps this PTE. 00687 // 00688 00689 MiDecrementShareAndValidCount (Pfn1->PteFrame); 00690 00691 MI_SET_PFN_DELETED (Pfn1); 00692 00693 // 00694 // Decrement the share count for the physical page. As the page 00695 // is private it will be put on the free list. 00696 // 00697 00698 MiDecrementShareCountOnly (MI_GET_PAGE_FRAME_FROM_PTE (&PteContents)); 00699 00700 // 00701 // Decrement the count for the number of private pages. 00702 // 00703 00704 CurrentProcess->NumberOfPrivatePages -= 1; 00705 } 00706 00707 // 00708 // Find the WSLE for this page and eliminate it. 00709 // 00710 00711 // 00712 // If we are deleting the system portion of the address space, do 00713 // not remove WSLEs or flush translation buffers as there can be 00714 // no other usage of this address space. 00715 // 00716 00717 if (AddressSpaceDeletion == FALSE) { 00718 00719 WorkingSetIndex = MiLocateWsle (VirtualAddress, 00720 MmWorkingSetList, 00721 WsPfnIndex ); 00722 00723 ASSERT (WorkingSetIndex != WSLE_NULL_INDEX); 00724 00725 // 00726 // Check to see if this entry is locked in the working set 00727 // or locked in memory. 00728 // 00729 00730 Locked = MmWsle[WorkingSetIndex].u1.e1; 00731 00732 MiRemoveWsle (WorkingSetIndex, MmWorkingSetList); 00733 00734 // 00735 // Add this entry to the list of free working set entries 00736 // and adjust the working set count. 00737 // 00738 00739 MiReleaseWsle (WorkingSetIndex, &CurrentProcess->Vm); 00740 00741 if ((Locked.LockedInWs == 1) || (Locked.LockedInMemory == 1)) { 00742 00743 // 00744 // This entry is locked. 00745 // 00746 00747 ASSERT (WorkingSetIndex < MmWorkingSetList->FirstDynamic); 00748 MmWorkingSetList->FirstDynamic -= 1; 00749 00750 if (WorkingSetIndex != MmWorkingSetList->FirstDynamic) { 00751 00752 Entry = MmWorkingSetList->FirstDynamic; 00753 ASSERT (MmWsle[Entry].u1.e1.Valid); 00754 SwapVa = MmWsle[Entry].u1.VirtualAddress; 00755 SwapVa = PAGE_ALIGN (SwapVa); 00756 Pfn2 = MI_PFN_ELEMENT ( 00757 MiGetPteAddress (SwapVa)->u.Hard.PageFrameNumber); 00758 #if 0 00759 Entry = MiLocateWsleAndParent (SwapVa, 00760 &Parent, 00761 MmWorkingSetList, 00762 Pfn2->u1.WsIndex); 00763 00764 // 00765 // Swap the removed entry with the last locked entry 00766 // which is located at first dynamic. 00767 // 00768 00769 MiSwapWslEntries (Entry, 00770 Parent, 00771 WorkingSetIndex, 00772 MmWorkingSetList); 00773 #endif //0 00774 00775 MiSwapWslEntries (Entry, 00776 WorkingSetIndex, 00777 &CurrentProcess->Vm); 00778 } 00779 } else { 00780 ASSERT (WorkingSetIndex >= MmWorkingSetList->FirstDynamic); 00781 } 00782 00783 // 00784 // Flush the entry out of the TB. 00785 // 00786 00787 if (!ARGUMENT_PRESENT (PteFlushList)) { 00788 KeFlushSingleTb (VirtualAddress, 00789 TRUE, 00790 FALSE, 00791 (PHARDWARE_PTE)PointerPte, 00792 ZeroPte.u.Flush); 00793 } else { 00794 if (PteFlushList->Count != MM_MAXIMUM_FLUSH_COUNT) { 00795 PteFlushList->FlushPte[PteFlushList->Count] = PointerPte; 00796 PteFlushList->FlushVa[PteFlushList->Count] = VirtualAddress; 00797 PteFlushList->Count += 1; 00798 } 00799 MI_WRITE_INVALID_PTE (PointerPte, ZeroPte); 00800 } 00801 00802 if (CloneDescriptor != NULL) { 00803 00804 // 00805 // Flush PTEs as this could release the PFN_LOCK. 00806 // 00807 00808 if (ARGUMENT_PRESENT (PteFlushList)) { 00809 MiFlushPteList (PteFlushList, FALSE, ZeroPte); 00810 } 00811 00812 // 00813 // Decrement the reference count for the clone block, 00814 // note that this could release and reacquire 00815 // the mutexes hence cannot be done until after the 00816 // working set index has been removed. 00817 // 00818 00819 if (MiDecrementCloneBlockReference ( CloneDescriptor, 00820 CloneBlock, 00821 CurrentProcess )) { 00822 00823 // 00824 // The working set mutex was released. This may 00825 // have removed the current page directory & table page. 00826 // 00827 00828 PointerPpe = MiGetPteAddress (PointerPde); 00829 00830 do { 00831 00832 MiDoesPpeExistAndMakeValid (PointerPpe, 00833 CurrentProcess, 00834 TRUE, 00835 &Waited); 00836 00837 Waited = 0; 00838 00839 // 00840 // If the call below results in a PFN release and 00841 // reacquire, then we must redo them both. 00842 // 00843 00844 MiDoesPdeExistAndMakeValid (PointerPde, 00845 CurrentProcess, 00846 TRUE, 00847 &Waited); 00848 00849 } while (Waited != 0); 00850 } 00851 } 00852 } 00853 00854 } else if (PteContents.u.Soft.Prototype == 1) { 00855 00856 // 00857 // This is a prototype PTE, if it is a fork PTE clean up the 00858 // fork structures. 00859 // 00860 00861 if (PteContents.u.Soft.PageFileHigh != MI_PTE_LOOKUP_NEEDED) { 00862 00863 // 00864 // Check to see if the prototype PTE is a fork prototype PTE. 00865 // 00866 00867 if (PointerPte <= MiHighestUserPte) { 00868 00869 if (PrototypePte != MiPteToProto (PointerPte)) { 00870 00871 CloneBlock = (PMMCLONE_BLOCK)MiPteToProto (PointerPte); 00872 CloneDescriptor = MiLocateCloneAddress ((PVOID)CloneBlock); 00873 00874 00875 #if DBG 00876 if (CloneDescriptor == NULL) { 00877 DbgPrint("1PrototypePte %p Clone desc %p \n", 00878 PrototypePte, CloneDescriptor); 00879 MiFormatPte(PointerPte); 00880 ASSERT (FALSE); 00881 } 00882 #endif //DBG 00883 00884 // 00885 // Decrement the reference count for the clone block, 00886 // note that this could release and reacquire 00887 // the mutexes. 00888 // 00889 00890 MI_WRITE_INVALID_PTE (PointerPte, ZeroPte); 00891 00892 if (ARGUMENT_PRESENT (PteFlushList)) { 00893 MiFlushPteList (PteFlushList, FALSE, ZeroPte); 00894 } 00895 00896 if (MiDecrementCloneBlockReference ( CloneDescriptor, 00897 CloneBlock, 00898 CurrentProcess )) { 00899 00900 // 00901 // The working set mutex was released. This may 00902 // have removed the current page directory & table page. 00903 // 00904 00905 PointerPde = MiGetPteAddress (PointerPte); 00906 PointerPpe = MiGetPteAddress (PointerPde); 00907 00908 // 00909 // If either call below results in a PFN release and 00910 // reacquire, then we must redo them both. 00911 // 00912 00913 do { 00914 00915 if (MiDoesPpeExistAndMakeValid (PointerPpe, 00916 CurrentProcess, 00917 TRUE, 00918 &Waited) == FALSE) { 00919 00920 // 00921 // The PPE has been deleted when the PFN lock 00922 // was released. Just bail as the PDE/PTE are 00923 // gone now anyway. 00924 // 00925 00926 return; 00927 } 00928 00929 Waited = 0; 00930 00931 // 00932 // If the call below results in a PFN release and 00933 // reacquire, then we must redo them both. If the 00934 // PDE was deleted when the PFN lock was released 00935 // then we just bail as the PTE is gone anyway. 00936 // 00937 00938 if (MiDoesPdeExistAndMakeValid (PointerPde, 00939 CurrentProcess, 00940 TRUE, 00941 &Waited) == FALSE) { 00942 return; 00943 } 00944 00945 } while (Waited != 0); 00946 } 00947 } 00948 } 00949 } 00950 00951 } else if (PteContents.u.Soft.Transition == 1) { 00952 00953 // 00954 // This is a transition PTE. (Page is private) 00955 // 00956 00957 Pfn1 = MI_PFN_ELEMENT (PteContents.u.Trans.PageFrameNumber); 00958 00959 MI_SET_PFN_DELETED (Pfn1); 00960 00961 MiDecrementShareCount (Pfn1->PteFrame); 00962 00963 // 00964 // Check the reference count for the page, if the reference 00965 // count is zero, move the page to the free list, if the reference 00966 // count is not zero, ignore this page. When the reference count 00967 // goes to zero, it will be placed on the free list. 00968 // 00969 00970 if (Pfn1->u3.e2.ReferenceCount == 0) { 00971 MiUnlinkPageFromList (Pfn1); 00972 MiReleasePageFileSpace (Pfn1->OriginalPte); 00973 MiInsertPageInList (MmPageLocationList[FreePageList], 00974 MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE(&PteContents)); 00975 } 00976 00977 // 00978 // Decrement the count for the number of private pages. 00979 // 00980 00981 CurrentProcess->NumberOfPrivatePages -= 1; 00982 00983 } else { 00984 00985 // 00986 // Must be page file space. 00987 // 00988 00989 if (PteContents.u.Soft.PageFileHigh != MI_PTE_LOOKUP_NEEDED) { 00990 00991 if (MiReleasePageFileSpace (*PointerPte)) { 00992 00993 // 00994 // Decrement the count for the number of private pages. 00995 // 00996 00997 CurrentProcess->NumberOfPrivatePages -= 1; 00998 } 00999 } 01000 } 01001 01002 // 01003 // Zero the PTE contents. 01004 // 01005 01006 MI_WRITE_INVALID_PTE (PointerPte, ZeroPte); 01007 01008 return; 01009 }

NTSTATUS MiDeleteSessionVirtualAddresses IN PVOID  VirtualAddress,
IN SIZE_T  NumberOfBytes
 

PFN_NUMBER MiDeleteSystemPagableVm IN PMMPTE  PointerPte,
IN PFN_NUMBER  NumberOfPtes,
IN MMPTE  NewPteValue,
IN LOGICAL  SessionAllocation,
OUT PPFN_NUMBER ResidentPages  OPTIONAL
 

Definition at line 4950 of file sysload.c.

References APC_LEVEL, ASSERT, _MMPTE_FLUSH_LIST::Count, DbgPrint, FALSE, _MMWSL::FirstDynamic, _MMPTE_FLUSH_LIST::FlushPte, _MMPTE_FLUSH_LIST::FlushVa, FreePageList, KeBugCheckEx(), LOCK_PFN, LOCK_SESSION_SPACE_WS, LOCK_SYSTEM_WS, _MMWSLENTRY::LockedInMemory, _MMWSLENTRY::LockedInWs, MI_CAPTURE_DIRTY_BIT_TO_PFN, MI_FLUSH_ENTIRE_SESSION_TB, MI_GET_PAGE_FRAME_FROM_PTE, MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE, MI_PFN_ELEMENT, MI_SET_PFN_DELETED, MI_WRITE_INVALID_PTE, MiCheckPdeForPagedPool(), MiDecrementShareAndValidCount, MiDecrementShareCount(), MiDecrementShareCountOnly, MiFlushPteList(), MiGetPteAddress, MiGetVirtualAddressMappedByPte, MiHighestUserPte, MiInsertPageInList(), MiLocateWsle(), MiReleasePageFileSpace(), MiReleaseWsle(), MiRemoveWsle(), MiSwapWslEntries(), MiUnlinkPageFromList(), MM_MAXIMUM_FLUSH_COUNT, MmPageLocationList, MmSessionSpace, MmSystemCacheWorkingSetList, MmSystemCacheWs, NT_SUCCESS, _MMPFN::OriginalPte, PAGE_ALIGN, _MMPFN::PteFrame, TRUE, _MMPTE::u, _MMPFN::u1, _MMWSLE::u1, _MMPFN::u2, _MMPFN::u3, UNLOCK_PFN, UNLOCK_SESSION_SPACE_WS, UNLOCK_SYSTEM_WS, _MM_SESSION_SPACE::Vm, _MMSUPPORT::VmWorkingSetList, _MM_SESSION_SPACE::Wsle, WSLE_NULL_INDEX, WSLE_NUMBER, and ZeroKernelPte.

Referenced by MiFreeInitializationCode(), MiFreePoolPages(), MiLoadImageSection(), MmFreeDriverInitialization(), MmFreeSpecialPool(), and MmUnloadSystemImage().

04960 : 04961 04962 This function deletes pagable system address space (paged pool 04963 or driver pagable sections). 04964 04965 Arguments: 04966 04967 PointerPte - Supplies the start of the PTE range to delete. 04968 04969 NumberOfPtes - Supplies the number of PTEs in the range. 04970 04971 NewPteValue - Supplies the new value for the PTE. 04972 04973 SessionAllocation - Supplies TRUE if this is a range in session space. If 04974 TRUE is specified, it is assumed that the caller has 04975 already attached to the relevant session. 04976 04977 If FALSE is supplied, then it is assumed that the range 04978 is in the systemwide global space instead. 04979 04980 ResidentPages - If not NULL, the number of resident pages freed is 04981 returned here. 04982 04983 Return Value: 04984 04985 Returns the number of pages actually freed. 04986 04987 --*/ 04988 04989 { 04990 PFN_NUMBER PageFrameIndex; 04991 MMPTE PteContents; 04992 PMMPFN Pfn1; 04993 PFN_NUMBER ValidPages; 04994 PFN_NUMBER PagesRequired; 04995 MMPTE NewContents; 04996 WSLE_NUMBER WsIndex; 04997 KIRQL OldIrql; 04998 MMPTE_FLUSH_LIST PteFlushList; 04999 MMPTE JunkPte; 05000 MMWSLENTRY Locked; 05001 05002 ASSERT (KeGetCurrentIrql() <= APC_LEVEL); 05003 05004 ValidPages = 0; 05005 PagesRequired = 0; 05006 PteFlushList.Count = 0; 05007 NewContents = NewPteValue; 05008 while (NumberOfPtes != 0) { 05009 PteContents = *PointerPte; 05010 05011 if (PteContents.u.Long != ZeroKernelPte.u.Long) { 05012 05013 if (PteContents.u.Hard.Valid == 1) { 05014 05015 if (SessionAllocation == TRUE) { 05016 LOCK_SESSION_SPACE_WS (OldIrql); 05017 } 05018 else { 05019 LOCK_SYSTEM_WS (OldIrql); 05020 } 05021 05022 PteContents = *(volatile MMPTE *)PointerPte; 05023 if (PteContents.u.Hard.Valid == 0) { 05024 if (SessionAllocation == TRUE) { 05025 UNLOCK_SESSION_SPACE_WS (OldIrql); 05026 } 05027 else { 05028 UNLOCK_SYSTEM_WS (OldIrql); 05029 } 05030 05031 continue; 05032 } 05033 05034 // 05035 // Delete the page. 05036 // 05037 05038 PageFrameIndex = MI_GET_PAGE_FRAME_FROM_PTE (&PteContents); 05039 05040 Pfn1 = MI_PFN_ELEMENT (PageFrameIndex); 05041 05042 // 05043 // Check to see if this is a pagable page in which 05044 // case it needs to be removed from the working set list. 05045 // 05046 05047 WsIndex = Pfn1->u1.WsIndex; 05048 if (WsIndex == 0) { 05049 ValidPages += 1; 05050 } else { 05051 if (SessionAllocation == FALSE) { 05052 MiRemoveWsle (WsIndex, 05053 MmSystemCacheWorkingSetList ); 05054 MiReleaseWsle (WsIndex, &MmSystemCacheWs); 05055 } 05056 else { 05057 WsIndex = MiLocateWsle( 05058 MiGetVirtualAddressMappedByPte(PointerPte), 05059 MmSessionSpace->Vm.VmWorkingSetList, 05060 WsIndex 05061 ); 05062 05063 ASSERT (WsIndex != WSLE_NULL_INDEX); 05064 05065 // 05066 // Check to see if this entry is locked in 05067 // the working set or locked in memory. 05068 // 05069 05070 Locked = MmSessionSpace->Wsle[WsIndex].u1.e1; 05071 05072 MiRemoveWsle (WsIndex, MmSessionSpace->Vm.VmWorkingSetList); 05073 05074 MiReleaseWsle (WsIndex, &MmSessionSpace->Vm); 05075 05076 if (Locked.LockedInWs == 1 || Locked.LockedInMemory == 1) { 05077 05078 // 05079 // This entry is locked. 05080 // 05081 #if DBG 05082 DbgPrint("MiDeleteSystemPagableVm: Session PointerPte 0x%p, Pfn 0x%p Locked in memory\n", 05083 PointerPte, 05084 Pfn1); 05085 05086 DbgBreakPoint(); 05087 #endif 05088 ASSERT (WsIndex < MmSessionSpace->Vm.VmWorkingSetList->FirstDynamic); 05089 MmSessionSpace->Vm.VmWorkingSetList->FirstDynamic -= 1; 05090 05091 if (WsIndex != MmSessionSpace->Vm.VmWorkingSetList->FirstDynamic) { 05092 ULONG Entry; 05093 PVOID SwapVa; 05094 05095 Entry = MmSessionSpace->Vm.VmWorkingSetList->FirstDynamic; 05096 ASSERT (MmSessionSpace->Wsle[Entry].u1.e1.Valid); 05097 SwapVa = MmSessionSpace->Wsle[Entry].u1.VirtualAddress; 05098 SwapVa = PAGE_ALIGN (SwapVa); 05099 05100 MiSwapWslEntries (Entry, 05101 WsIndex, 05102 &MmSessionSpace->Vm); 05103 } 05104 } 05105 else { 05106 ASSERT (WsIndex >= MmSessionSpace->Vm.VmWorkingSetList->FirstDynamic); 05107 } 05108 } 05109 } 05110 05111 if (SessionAllocation == TRUE) { 05112 UNLOCK_SESSION_SPACE_WS (OldIrql); 05113 } 05114 else { 05115 UNLOCK_SYSTEM_WS (OldIrql); 05116 } 05117 05118 LOCK_PFN (OldIrql); 05119 #if DBG 05120 if ((Pfn1->u3.e2.ReferenceCount > 1) && 05121 (Pfn1->u3.e1.WriteInProgress == 0)) { 05122 DbgPrint ("MM:SYSLOAD - deleting pool locked for I/O pte %p, pfn %p, share=%x, refcount=%x, wsindex=%x\n", 05123 PointerPte, 05124 PageFrameIndex, 05125 Pfn1->u2.ShareCount, 05126 Pfn1->u3.e2.ReferenceCount, 05127 Pfn1->u1.WsIndex); 05128 // 05129 // This case is valid only if the page being deleted 05130 // contained a lookaside free list entry that wasn't mapped 05131 // and multiple threads faulted on it and waited together. 05132 // Some of the faulted threads are still on the ready 05133 // list but haven't run yet, and so still have references 05134 // to this page that they picked up during the fault. 05135 // But this current thread has already allocated the 05136 // lookaside entry and is now freeing the entire page. 05137 // 05138 // BUT - if it is NOT the above case, we really should 05139 // trap here. However, we don't have a good way to 05140 // distinguish between the two cases. Note 05141 // that this complication was inserted when we went to 05142 // cmpxchg8 because using locks would prevent anyone from 05143 // accessing the lookaside freelist flinks like this. 05144 // 05145 // So, the ASSERT below comes out, but we leave the print 05146 // above in (with more data added) for the case where it's 05147 // not a lookaside contender with the reference count, but 05148 // is instead a truly bad reference that needs to be 05149 // debugged. The system should crash shortly thereafter 05150 // and we'll at least have the above print to help us out. 05151 // 05152 // ASSERT (Pfn1->u3.e2.ReferenceCount == 1); 05153 } 05154 #endif //DBG 05155 // 05156 // Check if this is a prototype PTE 05157 // 05158 if (Pfn1->u3.e1.PrototypePte == 1) { 05159 05160 PMMPTE PointerPde; 05161 05162 ASSERT (SessionAllocation == TRUE); 05163 05164 // 05165 // Capture the state of the modified bit for this 05166 // PTE. 05167 // 05168 05169 MI_CAPTURE_DIRTY_BIT_TO_PFN (PointerPte, Pfn1); 05170 05171 // 05172 // Decrement the share and valid counts of the page table 05173 // page which maps this PTE. 05174 // 05175 05176 PointerPde = MiGetPteAddress (PointerPte); 05177 if (PointerPde->u.Hard.Valid == 0) { 05178 #if !defined (_WIN64) 05179 if (!NT_SUCCESS(MiCheckPdeForPagedPool (PointerPte))) { 05180 #endif 05181 KeBugCheckEx (MEMORY_MANAGEMENT, 05182 0x61940, 05183 (ULONG_PTR)PointerPte, 05184 (ULONG_PTR)PointerPde->u.Long, 05185 (ULONG_PTR)MiGetVirtualAddressMappedByPte(PointerPte)); 05186 #if !defined (_WIN64) 05187 } 05188 #endif 05189 } 05190 05191 MiDecrementShareAndValidCount (MI_GET_PAGE_FRAME_FROM_PTE (PointerPde)); 05192 05193 // 05194 // Decrement the share count for the physical page. 05195 // 05196 05197 MiDecrementShareCount (PageFrameIndex); 05198 05199 // 05200 // No need to worry about fork prototype PTEs 05201 // for kernel addresses. 05202 // 05203 05204 ASSERT (PointerPte > MiHighestUserPte); 05205 05206 } else { 05207 MiDecrementShareAndValidCount (Pfn1->PteFrame); 05208 MI_SET_PFN_DELETED (Pfn1); 05209 MiDecrementShareCountOnly (PageFrameIndex); 05210 } 05211 05212 MI_WRITE_INVALID_PTE (PointerPte, NewContents); 05213 UNLOCK_PFN (OldIrql); 05214 05215 // 05216 // Flush the TB for this page. 05217 // 05218 05219 if (PteFlushList.Count != MM_MAXIMUM_FLUSH_COUNT) { 05220 05221 // 05222 // We cannot rewrite the PTE without creating a race 05223 // condition. So don't let the TB flush do it anymore. 05224 // 05225 // PteFlushList.FlushPte[PteFlushList.Count] = PointerPte; 05226 // 05227 05228 PteFlushList.FlushPte[PteFlushList.Count] = 05229 (PMMPTE)&JunkPte; 05230 05231 PteFlushList.FlushVa[PteFlushList.Count] = 05232 MiGetVirtualAddressMappedByPte (PointerPte); 05233 PteFlushList.Count += 1; 05234 } 05235 05236 } else if (PteContents.u.Soft.Prototype) { 05237 05238 ASSERT (SessionAllocation == TRUE); 05239 05240 // 05241 // No need to worry about fork prototype PTEs 05242 // for kernel addresses. 05243 // 05244 05245 ASSERT (PointerPte >= MiHighestUserPte); 05246 05247 MI_WRITE_INVALID_PTE (PointerPte, NewContents); 05248 05249 // 05250 // We currently commit for all prototype kernel mappings since 05251 // we could copy-on-write. 05252 // 05253 05254 } else if (PteContents.u.Soft.Transition == 1) { 05255 05256 LOCK_PFN (OldIrql); 05257 05258 PteContents = *(volatile MMPTE *)PointerPte; 05259 05260 if (PteContents.u.Soft.Transition == 0) { 05261 UNLOCK_PFN (OldIrql); 05262 continue; 05263 } 05264 05265 // 05266 // Transition, release page. 05267 // 05268 05269 PageFrameIndex = MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE (&PteContents); 05270 05271 // 05272 // Set the pointer to PTE as empty so the page 05273 // is deleted when the reference count goes to zero. 05274 // 05275 05276 Pfn1 = MI_PFN_ELEMENT (PageFrameIndex); 05277 05278 MI_SET_PFN_DELETED (Pfn1); 05279 05280 MiDecrementShareCount (Pfn1->PteFrame); 05281 05282 // 05283 // Check the reference count for the page, if the reference 05284 // count is zero, move the page to the free list, if the 05285 // reference count is not zero, ignore this page. When the 05286 // reference count goes to zero, it will be placed on the 05287 // free list. 05288 // 05289 05290 if (Pfn1->u3.e2.ReferenceCount == 0) { 05291 MiUnlinkPageFromList (Pfn1); 05292 MiReleasePageFileSpace (Pfn1->OriginalPte); 05293 MiInsertPageInList (MmPageLocationList[FreePageList], 05294 PageFrameIndex); 05295 } 05296 #if DBG 05297 if ((Pfn1->u3.e2.ReferenceCount > 1) && 05298 (Pfn1->u3.e1.WriteInProgress == 0)) { 05299 DbgPrint ("MM:SYSLOAD - deleting pool locked for I/O %p\n", 05300 PageFrameIndex); 05301 DbgBreakPoint(); 05302 } 05303 #endif //DBG 05304 05305 MI_WRITE_INVALID_PTE (PointerPte, NewContents); 05306 UNLOCK_PFN (OldIrql); 05307 } else { 05308 05309 // 05310 // Demand zero, release page file space. 05311 // 05312 if (PteContents.u.Soft.PageFileHigh != 0) { 05313 LOCK_PFN (OldIrql); 05314 MiReleasePageFileSpace (PteContents); 05315 UNLOCK_PFN (OldIrql); 05316 } 05317 05318 MI_WRITE_INVALID_PTE (PointerPte, NewContents); 05319 } 05320 05321 PagesRequired += 1; 05322 } 05323 05324 NumberOfPtes -= 1; 05325 PointerPte += 1; 05326 } 05327 05328 // 05329 // There is the thorny case where one of the pages we just deleted could 05330 // get faulted back in when we released the PFN lock above within the loop. 05331 // The only time when this can happen is if a thread faulted during an 05332 // interlocked pool allocation for an address that we've just deleted. 05333 // 05334 // If this thread sees the NewContents in the PTE, it will treat it as 05335 // demand zero, and incorrectly allocate a page, PTE and WSL. It will 05336 // reference it once and realize it needs to reread the lookaside listhead 05337 // and restart the operation. But this page would live on in paged pool 05338 // as modified (but unused) until the paged pool allocator chose to give 05339 // out its virtual address again. 05340 // 05341 // The code below rewrites the PTEs which is really bad if another thread 05342 // gets a zero page between our first setting of the PTEs above and our 05343 // second setting below - because we'll reset the PTE to demand zero, but 05344 // we'll still have a WSL entry that's valid, and we spiral from there. 05345 // 05346 // We really should remove the writing of the PTE below since we've already 05347 // done it above. But for now, we're leaving it in - it's harmless because 05348 // we've chosen to fix this problem by checking for this case when we 05349 // materialize demand zero pages. Note that we have to fix this problem 05350 // by checking in the demand zero path because a thread could be coming into 05351 // that path any time before or after we flush the PTE list and any fixes 05352 // here could only address the before case, not the after. 05353 // 05354 05355 if (SessionAllocation == TRUE) { 05356 05357 // 05358 // Session space has no ASN - flush the entire TB. 05359 // 05360 05361 MI_FLUSH_ENTIRE_SESSION_TB (TRUE, TRUE); 05362 } 05363 05364 LOCK_PFN (OldIrql); 05365 MiFlushPteList (&PteFlushList, TRUE, NewContents); 05366 UNLOCK_PFN (OldIrql); 05367 05368 if (ARGUMENT_PRESENT(ResidentPages)) { 05369 *ResidentPages = ValidPages; 05370 } 05371 05372 return PagesRequired; 05373 }

VOID MiDeleteVirtualAddresses IN PUCHAR  StartingAddress,
IN PUCHAR  EndingAddress,
IN ULONG  AddressSpaceDeletion,
IN PMMVAD  Vad
 

Definition at line 26 of file deleteva.c.

References APC_LEVEL, _MMPTE_FLUSH_LIST::Count, DbgPrint, FALSE, IS_PTE_NOT_DEMAND_ZERO, LOCK_PFN, MI_DECREMENT_USED_PTES_BY_HANDLE, MI_GET_USED_PTES_FROM_HANDLE, MI_GET_USED_PTES_HANDLE, MI_VA_TO_VPN, MI_WRITE_INVALID_PTE, MiDeletePte(), MiDoesPdeExistAndMakeValid(), MiDoesPpeExistAndMakeValid, MiFlushPteList(), MiGetPdeAddress, MiGetPpeAddress, MiGetProtoPteAddress, MiGetPteAddress, MiGetVirtualAddressMappedByPte, MiIsPteOnPdeBoundary, MiIsVirtualAddressOnPdeBoundary, MiIsVirtualAddressOnPpeBoundary, MiLocateSubsection(), MM_PFN_LOCK_ASSERT, NULL, PAGE_SIZE, PsGetCurrentProcess, _SUBSECTION::PtesInSubsection, _SUBSECTION::SubsectionBase, TRUE, _MMPTE::u, UNLOCK_PFN, and ZeroPte.

Referenced by MiDeleteFreeVm(), MiRemoveMappedView(), and MmCleanProcessAddressSpace().

00035 : 00036 00037 This routine deletes the specified virtual address range within 00038 the current process. 00039 00040 Arguments: 00041 00042 StartingAddress - Supplies the first virtual address to delete. 00043 00044 EndingAddress - Supplies the last address to delete. 00045 00046 AddressSpaceDeletion - Supplies TRUE if the address space is being 00047 deleted, FALSE otherwise. If TRUE is specified 00048 the TB is not flushed and valid addresses are 00049 not removed from the working set. 00050 00051 Vad - Supplies the virtual address descriptor which maps this range 00052 or NULL if we are not concerned about views. From the Vad the 00053 range of prototype PTEs is determined and this information is 00054 used to uncover if the PTE refers to a prototype PTE or a 00055 fork PTE. 00056 00057 Return Value: 00058 00059 None. 00060 00061 00062 Environment: 00063 00064 Kernel mode, called with APCs disabled, working set mutex and PFN lock 00065 held. These mutexes may be released and reacquired to fault pages in. 00066 00067 --*/ 00068 00069 { 00070 PUCHAR Va; 00071 PUCHAR FirstValidVa; 00072 PVOID TempVa; 00073 PMMPTE PointerPte; 00074 PMMPTE PointerPde; 00075 PMMPTE PointerPpe; 00076 PMMPTE OriginalPointerPte; 00077 PMMPTE ProtoPte; 00078 PMMPTE ProtoPte2; 00079 PMMPTE LastProtoPte; 00080 PMMPTE LastProtoPte2; 00081 PEPROCESS CurrentProcess; 00082 PSUBSECTION Subsection; 00083 PVOID UsedPageTableHandle; 00084 PVOID UsedPageDirectoryHandle; 00085 KIRQL OldIrql; 00086 MMPTE_FLUSH_LIST FlushList; 00087 ULONG Waited; 00088 LOGICAL Skipped; 00089 00090 OldIrql = APC_LEVEL; 00091 FlushList.Count = 0; 00092 00093 MM_PFN_LOCK_ASSERT(); 00094 CurrentProcess = PsGetCurrentProcess(); 00095 00096 Va = StartingAddress; 00097 PointerPpe = MiGetPpeAddress (Va); 00098 PointerPde = MiGetPdeAddress (Va); 00099 PointerPte = MiGetPteAddress (Va); 00100 OriginalPointerPte = PointerPte; 00101 00102 do { 00103 00104 while (MiDoesPpeExistAndMakeValid (PointerPpe, 00105 CurrentProcess, 00106 TRUE, 00107 &Waited) == FALSE) { 00108 00109 // 00110 // This page directory parent entry is empty, go to the next one. 00111 // 00112 00113 PointerPpe += 1; 00114 PointerPde = MiGetVirtualAddressMappedByPte (PointerPpe); 00115 PointerPte = MiGetVirtualAddressMappedByPte (PointerPde); 00116 Va = MiGetVirtualAddressMappedByPte (PointerPte); 00117 00118 if (Va > EndingAddress) { 00119 00120 // 00121 // All done, return. 00122 // 00123 00124 return; 00125 } 00126 } 00127 00128 Waited = 0; 00129 00130 while (MiDoesPdeExistAndMakeValid (PointerPde, 00131 CurrentProcess, 00132 TRUE, 00133 &Waited) == FALSE) { 00134 00135 // 00136 // This page directory entry is empty, go to the next one. 00137 // 00138 00139 PointerPde += 1; 00140 PointerPte = MiGetVirtualAddressMappedByPte (PointerPde); 00141 Va = MiGetVirtualAddressMappedByPte (PointerPte); 00142 00143 if (Va > EndingAddress) { 00144 00145 // 00146 // All done, return. 00147 // 00148 00149 return; 00150 } 00151 #if defined (_WIN64) 00152 if (MiIsPteOnPdeBoundary (PointerPde)) { 00153 PointerPpe = MiGetPteAddress (PointerPde); 00154 Waited = 1; 00155 break; 00156 } 00157 #endif 00158 } 00159 00160 } while (Waited != 0); 00161 00162 FirstValidVa = Va; 00163 UsedPageTableHandle = MI_GET_USED_PTES_HANDLE (Va); 00164 00165 // 00166 // A valid PDE has been located, examine each PTE and delete them. 00167 // 00168 00169 if ((Vad == (PMMVAD)NULL) || 00170 (Vad->u.VadFlags.PrivateMemory) || 00171 (Vad->FirstPrototypePte == (PMMPTE)NULL)) { 00172 ProtoPte = (PMMPTE)NULL; 00173 LastProtoPte = (PMMPTE)NULL; 00174 } else { 00175 ProtoPte = Vad->FirstPrototypePte; 00176 LastProtoPte = (PMMPTE)4; 00177 } 00178 00179 // 00180 // Examine each PTE within the address range and delete it. 00181 // 00182 00183 while (Va <= EndingAddress) { 00184 00185 // 00186 // Note that the initial address could be aligned on a PPE or PDE 00187 // boundary so we must check for it here. 00188 // 00189 00190 if (MiIsVirtualAddressOnPdeBoundary(Va)) { 00191 00192 // 00193 // The virtual address is on a page directory boundary, 00194 // check the next PDE for validity and flush PTEs for the 00195 // previous page table page. 00196 // 00197 00198 MiFlushPteList (&FlushList, FALSE, ZeroPte); 00199 00200 // 00201 // If all the entries have been eliminated from the previous 00202 // page table page, delete the page table page itself. 00203 // 00204 00205 if ((MI_GET_USED_PTES_FROM_HANDLE (UsedPageTableHandle) == 0) && 00206 (PointerPde->u.Long != 0)) { 00207 00208 TempVa = MiGetVirtualAddressMappedByPte(PointerPde); 00209 MiDeletePte (PointerPde, 00210 TempVa, 00211 AddressSpaceDeletion, 00212 CurrentProcess, 00213 NULL, 00214 NULL); 00215 00216 #if defined (_WIN64) 00217 if (Va == FirstValidVa) { 00218 UsedPageDirectoryHandle = MI_GET_USED_PTES_HANDLE (PointerPte); 00219 } 00220 else { 00221 UsedPageDirectoryHandle = MI_GET_USED_PTES_HANDLE (PointerPte - 1); 00222 } 00223 00224 MI_DECREMENT_USED_PTES_BY_HANDLE (UsedPageDirectoryHandle); 00225 #endif 00226 00227 } 00228 00229 if (MiIsVirtualAddressOnPpeBoundary(Va)) { 00230 00231 if (Va == FirstValidVa) { 00232 UsedPageDirectoryHandle = MI_GET_USED_PTES_HANDLE (PointerPte); 00233 } 00234 else { 00235 UsedPageDirectoryHandle = MI_GET_USED_PTES_HANDLE (PointerPte - 1); 00236 } 00237 00238 if ((MI_GET_USED_PTES_FROM_HANDLE (UsedPageDirectoryHandle) == 0) && 00239 (PointerPpe->u.Long != 0)) { 00240 00241 TempVa = MiGetVirtualAddressMappedByPte(PointerPpe); 00242 MiDeletePte (PointerPpe, 00243 TempVa, 00244 AddressSpaceDeletion, 00245 CurrentProcess, 00246 NULL, 00247 NULL); 00248 } 00249 } 00250 00251 // 00252 // Release the PFN lock. This prevents a single thread 00253 // from forcing other high priority threads from being 00254 // blocked while a large address range is deleted. There 00255 // is nothing magic about the instructions within the 00256 // lock and unlock. 00257 // 00258 00259 UNLOCK_PFN (OldIrql); 00260 PointerPde = MiGetPdeAddress (Va); 00261 PointerPpe = MiGetPpeAddress (Va); 00262 Skipped = FALSE; 00263 LOCK_PFN (OldIrql); 00264 00265 do { 00266 while (MiDoesPpeExistAndMakeValid (PointerPpe, 00267 CurrentProcess, 00268 TRUE, 00269 &Waited) == FALSE) { 00270 00271 // 00272 // This page directory parent entry is empty, 00273 // go to the next one. 00274 // 00275 00276 Skipped = TRUE; 00277 PointerPpe += 1; 00278 PointerPde = MiGetVirtualAddressMappedByPte (PointerPpe); 00279 PointerPte = MiGetVirtualAddressMappedByPte (PointerPde); 00280 Va = MiGetVirtualAddressMappedByPte (PointerPte); 00281 00282 if (Va > EndingAddress) { 00283 00284 // 00285 // All done, return. 00286 // 00287 00288 return; 00289 } 00290 } 00291 00292 Waited = 0; 00293 00294 while (MiDoesPdeExistAndMakeValid (PointerPde, 00295 CurrentProcess, 00296 TRUE, 00297 &Waited) == FALSE) { 00298 00299 // 00300 // This page directory entry is empty, go to the next one. 00301 // 00302 00303 Skipped = TRUE; 00304 PointerPde += 1; 00305 PointerPte = MiGetVirtualAddressMappedByPte (PointerPde); 00306 Va = MiGetVirtualAddressMappedByPte (PointerPte); 00307 00308 if (Va > EndingAddress) { 00309 00310 // 00311 // All done, remove any straggling page directories and 00312 // return. 00313 // 00314 00315 #if defined (_WIN64) 00316 00317 PointerPde -= 1; 00318 PointerPte = MiGetVirtualAddressMappedByPte (PointerPde); 00319 UsedPageDirectoryHandle = MI_GET_USED_PTES_HANDLE (PointerPte); 00320 00321 if ((MI_GET_USED_PTES_FROM_HANDLE (UsedPageDirectoryHandle) == 0) && 00322 (PointerPpe->u.Long != 0)) { 00323 00324 TempVa = MiGetVirtualAddressMappedByPte(PointerPpe); 00325 MiDeletePte (PointerPpe, 00326 TempVa, 00327 AddressSpaceDeletion, 00328 CurrentProcess, 00329 NULL, 00330 NULL); 00331 } 00332 #endif 00333 00334 return; 00335 } 00336 00337 #if defined (_WIN64) 00338 if (MiIsPteOnPdeBoundary (PointerPde)) { 00339 PointerPpe = MiGetPteAddress (PointerPde); 00340 Waited = 1; 00341 break; 00342 } 00343 #endif 00344 00345 #if DBG 00346 if ((LastProtoPte != NULL) && 00347 (Vad->u2.VadFlags2.ExtendableFile == 0)) { 00348 ProtoPte2 = MiGetProtoPteAddress(Vad, MI_VA_TO_VPN (Va)); 00349 Subsection = MiLocateSubsection (Vad,MI_VA_TO_VPN (Va)); 00350 LastProtoPte2 = &Subsection->SubsectionBase[Subsection->PtesInSubsection]; 00351 if (Vad->u.VadFlags.ImageMap != 1) { 00352 if ((ProtoPte2 < Subsection->SubsectionBase) || 00353 (ProtoPte2 >= LastProtoPte2)) { 00354 DbgPrint ("bad proto pte %p va %p Vad %p sub %p\n", 00355 ProtoPte2,Va,Vad,Subsection); 00356 DbgBreakPoint(); 00357 } 00358 } 00359 } 00360 #endif //DBG 00361 } 00362 00363 } while (Waited != 0); 00364 00365 // 00366 // The PPE and PDE are now valid, get the page table use count. 00367 // 00368 00369 UsedPageTableHandle = MI_GET_USED_PTES_HANDLE (Va); 00370 00371 // 00372 // If we skipped chunks of address space, the prototype PTE pointer 00373 // must be updated now so VADs that span multiple subsections 00374 // are handled properly. 00375 // 00376 00377 if ((Skipped == TRUE) && (LastProtoPte != NULL)) { 00378 00379 ProtoPte = MiGetProtoPteAddress(Vad, MI_VA_TO_VPN(Va)); 00380 Subsection = MiLocateSubsection (Vad, MI_VA_TO_VPN(Va)); 00381 00382 if (Subsection != NULL) { 00383 LastProtoPte = &Subsection->SubsectionBase[Subsection->PtesInSubsection]; 00384 #if DBG 00385 if (Vad->u.VadFlags.ImageMap != 1) { 00386 if ((ProtoPte < Subsection->SubsectionBase) || 00387 (ProtoPte >= LastProtoPte)) { 00388 DbgPrint ("bad proto pte %p va %p Vad %p sub %p\n", 00389 ProtoPte,Va,Vad,Subsection); 00390 DbgBreakPoint(); 00391 } 00392 } 00393 #endif //DBG 00394 } 00395 else { 00396 00397 // 00398 // The Vad span is larger than the section being mapped. 00399 // Null the proto PTE local as no more proto PTEs will 00400 // need to be deleted at this point. 00401 // 00402 00403 LastProtoPte = (PMMPTE)NULL; 00404 } 00405 } 00406 } 00407 00408 // 00409 // The PPE and PDE are now valid, delete the PTEs. 00410 // 00411 00412 if (PointerPte->u.Long != 0) { 00413 00414 // 00415 // One less used page table entry in this page table page. 00416 // 00417 00418 MI_DECREMENT_USED_PTES_BY_HANDLE (UsedPageTableHandle); 00419 00420 if (IS_PTE_NOT_DEMAND_ZERO (*PointerPte)) { 00421 00422 if (LastProtoPte != NULL) { 00423 if (ProtoPte >= LastProtoPte) { 00424 ProtoPte = MiGetProtoPteAddress(Vad, MI_VA_TO_VPN(Va)); 00425 Subsection = MiLocateSubsection (Vad, MI_VA_TO_VPN(Va)); 00426 LastProtoPte = &Subsection->SubsectionBase[Subsection->PtesInSubsection]; 00427 } 00428 #if DBG 00429 if (Vad->u.VadFlags.ImageMap != 1) { 00430 if ((ProtoPte < Subsection->SubsectionBase) || 00431 (ProtoPte >= LastProtoPte)) { 00432 DbgPrint ("bad proto pte %p va %p Vad %p sub %p\n", 00433 ProtoPte,Va,Vad,Subsection); 00434 DbgBreakPoint(); 00435 } 00436 } 00437 #endif //DBG 00438 } 00439 00440 MiDeletePte (PointerPte, 00441 (PVOID)Va, 00442 AddressSpaceDeletion, 00443 CurrentProcess, 00444 ProtoPte, 00445 &FlushList); 00446 } else { 00447 MI_WRITE_INVALID_PTE (PointerPte, ZeroPte); 00448 } 00449 } 00450 00451 Va += PAGE_SIZE; 00452 PointerPte += 1; 00453 ProtoPte += 1; 00454 } 00455 00456 // 00457 // Flush out entries for the last page table page. 00458 // 00459 00460 MiFlushPteList (&FlushList, FALSE, ZeroPte); 00461 00462 // 00463 // If all the entries have been eliminated from the previous 00464 // page table page, delete the page table page itself. 00465 // 00466 00467 if ((MI_GET_USED_PTES_FROM_HANDLE (UsedPageTableHandle) == 0) && 00468 (PointerPde->u.Long != 0)) { 00469 00470 TempVa = MiGetVirtualAddressMappedByPte(PointerPde); 00471 MiDeletePte (PointerPde, 00472 TempVa, 00473 AddressSpaceDeletion, 00474 CurrentProcess, 00475 NULL, 00476 NULL); 00477 00478 #if defined (_WIN64) 00479 UsedPageDirectoryHandle = MI_GET_USED_PTES_HANDLE (PointerPte - 1); 00480 00481 MI_DECREMENT_USED_PTES_BY_HANDLE (UsedPageDirectoryHandle); 00482 00483 if ((MI_GET_USED_PTES_FROM_HANDLE (UsedPageDirectoryHandle) == 0) && 00484 (PointerPpe->u.Long != 0)) { 00485 00486 TempVa = MiGetVirtualAddressMappedByPte(PointerPpe); 00487 MiDeletePte (PointerPpe, 00488 TempVa, 00489 AddressSpaceDeletion, 00490 CurrentProcess, 00491 NULL, 00492 NULL); 00493 } 00494 #endif 00495 } 00496 00497 // 00498 // All done, return. 00499 // 00500 00501 return; 00502 }

VOID MiDereferenceSegmentThread IN PVOID  StartContext  ) 
 

Definition at line 603 of file sectsup.c.

References ASSERT, DbgPrint, _CONTROL_AREA::DereferenceList, DISPATCH_LEVEL, _MMPAGE_FILE_EXPANSION::Event, ExFreePool(), FALSE, KeClearEvent, KeSetEvent(), KeSetPriorityThread(), KeWaitForMultipleObjects(), _MMDEREFERENCE_SEGMENT_HEADER::ListHead, _MMDEREFERENCE_SEGMENT_HEADER::Lock, MiAttemptPageFileReduction(), MiExtendPagingFiles(), MiRemoveUnusedSegments(), MiSegmentDelete(), MM_DBG_SECTIONS, MmDereferenceSegmentHeader, MmUnusedSegmentCleanup, NTSTATUS(), NULL, PsGetCurrentThread, _MMPAGE_FILE_EXPANSION::RequestedExpansionSize, SegMaximumObject, _CONTROL_AREA::Segment, SegmentDereference, _MMDEREFERENCE_SEGMENT_HEADER::Semaphore, Status, _CONTROL_AREA::u, UsedSegmentCleanup, UserMode, VOID(), and WrVirtualMemory.

Referenced by MiSectionInitialization().

00609 : 00610 00611 This routine is the thread for dereferencing segments which have 00612 no references from any sections or mapped views AND there are 00613 no prototype PTEs within the segment which are in the transition 00614 state (i.e., no PFN database references to the segment). 00615 00616 It also does double duty and is used for expansion of paging files. 00617 00618 Arguments: 00619 00620 StartContext - Not used. 00621 00622 Return Value: 00623 00624 None. 00625 00626 --*/ 00627 00628 { 00629 PCONTROL_AREA ControlArea; 00630 PMMPAGE_FILE_EXPANSION PageExpand; 00631 PLIST_ENTRY NextEntry; 00632 KIRQL OldIrql; 00633 static KWAIT_BLOCK WaitBlockArray[SegMaximumObject]; 00634 PVOID WaitObjects[SegMaximumObject]; 00635 NTSTATUS Status; 00636 00637 UNREFERENCED_PARAMETER (StartContext); 00638 00639 // 00640 // Make this a real time thread. 00641 // 00642 00643 (VOID) KeSetPriorityThread (&PsGetCurrentThread()->Tcb, 00644 LOW_REALTIME_PRIORITY + 2); 00645 00646 WaitObjects[SegmentDereference] = (PVOID)&MmDereferenceSegmentHeader.Semaphore; 00647 WaitObjects[UsedSegmentCleanup] = (PVOID)&MmUnusedSegmentCleanup; 00648 00649 for (;;) { 00650 00651 Status = KeWaitForMultipleObjects(SegMaximumObject, 00652 &WaitObjects[0], 00653 WaitAny, 00654 WrVirtualMemory, 00655 UserMode, 00656 FALSE, 00657 NULL, 00658 &WaitBlockArray[0]); 00659 00660 // 00661 // Switch on the wait status. 00662 // 00663 00664 switch (Status) { 00665 00666 case SegmentDereference: 00667 00668 // 00669 // An entry is available to dereference, acquire the spinlock 00670 // and remove the entry. 00671 // 00672 00673 ExAcquireSpinLock (&MmDereferenceSegmentHeader.Lock, &OldIrql); 00674 00675 if (IsListEmpty(&MmDereferenceSegmentHeader.ListHead)) { 00676 00677 // 00678 // There is nothing in the list, rewait. 00679 // 00680 00681 ExReleaseSpinLock (&MmDereferenceSegmentHeader.Lock, OldIrql); 00682 break; 00683 } 00684 00685 NextEntry = RemoveHeadList(&MmDereferenceSegmentHeader.ListHead); 00686 00687 ExReleaseSpinLock (&MmDereferenceSegmentHeader.Lock, OldIrql); 00688 00689 ASSERT (KeGetCurrentIrql() < DISPATCH_LEVEL); 00690 00691 ControlArea = CONTAINING_RECORD( NextEntry, 00692 CONTROL_AREA, 00693 DereferenceList ); 00694 00695 if (ControlArea->Segment != NULL) { 00696 00697 // 00698 // This is a control area, delete it. 00699 // 00700 00701 #if DBG 00702 if (MmDebug & MM_DBG_SECTIONS) { 00703 DbgPrint("MM:dereferencing segment %lx control %lx\n", 00704 ControlArea->Segment, ControlArea); 00705 } 00706 #endif 00707 00708 // 00709 // Indicate this entry is not on any list. 00710 // 00711 00712 ControlArea->DereferenceList.Flink = NULL; 00713 00714 ASSERT (ControlArea->u.Flags.FilePointerNull == 1); 00715 MiSegmentDelete (ControlArea->Segment); 00716 00717 } else { 00718 00719 // 00720 // This is a request to expand or reduce the paging files. 00721 // 00722 00723 PageExpand = (PMMPAGE_FILE_EXPANSION)ControlArea; 00724 00725 if (PageExpand->RequestedExpansionSize == 0xFFFFFFFF) { 00726 00727 // 00728 // Attempt to reduce the size of the paging files. 00729 // 00730 00731 ExFreePool (PageExpand); 00732 00733 MiAttemptPageFileReduction (); 00734 } else { 00735 00736 // 00737 // Attempt to expand the size of the paging files. 00738 // 00739 00740 MiExtendPagingFiles (PageExpand); 00741 KeSetEvent (&PageExpand->Event, 0, FALSE); 00742 MiRemoveUnusedSegments(); 00743 } 00744 } 00745 break; 00746 00747 case UsedSegmentCleanup: 00748 00749 MiRemoveUnusedSegments(); 00750 00751 KeClearEvent (&MmUnusedSegmentCleanup); 00752 00753 break; 00754 00755 default: 00756 00757 KdPrint(("MMSegmentderef: Illegal wait status, %lx =\n", Status)); 00758 break; 00759 } // end switch 00760 00761 } //end for 00762 00763 return; 00764 }

VOID MiDetachSession VOID   ) 
 

Definition at line 1253 of file session.c.

References ASSERT, KeDetachSessionSpace(), MI_FLUSH_SESSION_TB, MI_SESSION_SPACE_END, MI_SESSION_SPACE_PAGE_TABLES, MiGetPdeAddress, MiGetPpeAddress, MiHydra, MmIsAddressValid(), MmSessionBase, MmSessionSpace, PsGetCurrentProcess, TRUE, _MMPTE::u, and ZeroKernelPte.

Referenced by MiEmptyAllWorkingSetsWorker(), and MmWorkingSetManager().

01259 : 01260 01261 Detaches from the specified session space. 01262 01263 Arguments: 01264 01265 None. 01266 01267 Return Value: 01268 01269 None. 01270 01271 Environment: 01272 01273 Kernel mode. No locks held. Current process must not have a session 01274 space to return to - ie: this should be the system process. 01275 01276 --*/ 01277 01278 { 01279 PMMPTE PointerPde; 01280 PMMPTE EndPde; 01281 KIRQL OldIrql; 01282 01283 ASSERT (MiHydra == TRUE); 01284 01285 ASSERT (PsGetCurrentProcess()->Vm.u.Flags.ProcessInSession == 0); 01286 ASSERT (MmIsAddressValid(MmSessionSpace) == TRUE); 01287 01288 #if defined (_WIN64) 01289 PointerPde = MiGetPpeAddress (MmSessionBase); 01290 PointerPde->u.Long = ZeroKernelPte.u.Long; 01291 #else 01292 PointerPde = MiGetPdeAddress (MmSessionBase); 01293 01294 EndPde = MiGetPdeAddress (MI_SESSION_SPACE_END); 01295 01296 RtlZeroMemory (PointerPde, MI_SESSION_SPACE_PAGE_TABLES * sizeof (MMPTE)); 01297 #endif 01298 01299 MI_FLUSH_SESSION_TB (OldIrql); 01300 01301 #if defined(_IA64_) 01302 KeDetachSessionSpace(); 01303 #endif 01304 }

NTSTATUS MiDispatchFault IN BOOLEAN  StoreInstrution,
IN PVOID  VirtualAdress,
IN PMMPTE  PointerPte,
IN PMMPTE  PointerProtoPte,
IN PEPROCESS  Process,
OUT PLOGICAL  ApcNeeded
 

Definition at line 68 of file pagfault.c.

References ActiveAndValid, APC_LEVEL, _ETHREAD::ApcNeeded, ASSERT, _MMINPAGE_SUPPORT::BasePte, _MDL::ByteCount, DbgPrint, _MMINPAGE_SUPPORT::Event, FALSE, _FILE_OBJECT::FileName, _MMINPAGE_SUPPORT::FilePointer, FreePageList, HYDRA_PROCESS, IoPageRead(), _MMINPAGE_SUPPORT::IoStatus, KeDelayExecutionThread(), KeEnterCriticalRegion, KeLeaveCriticalRegion, KernelMode, KeSetEvent(), LOCK_PFN, LOCK_SESSION_SPACE_WS, LOCK_SYSTEM_WS, _MMINPAGE_SUPPORT::Mdl, MI_IS_PHYSICAL_ADDRESS, MI_IS_SESSION_ADDRESS, MI_MAGIC_AWE_PTEFRAME, MI_MAKE_TRANSITION_PTE_VALID, MI_PFN_ELEMENT, MI_REMOVE_LOCKED_PAGE_CHARGE, MI_SET_PTE_DIRTY, MI_WRITE_VALID_PTE, MiAddValidPageToWorkingSet(), MiCompleteProtoPteFault(), MiDecrementReferenceCount(), MiFlushInPageSupportBlock(), MiGetPdeAddress, MiGetPteAddress, MiHydra, MiInsertPageInList(), MiResolveDemandZeroFault(), MiResolvePageFileFault(), MiResolveProtoPteFault(), MiResolveTransitionFault(), MiRestoreTransitionPte(), MiUnlinkPageFromList(), MiWaitForInPageComplete(), MM_DBG_PAGEFAULT, MmHardFaultNotifyRoutine, MmIsRetryIoStatus, MmPageLocationList, MmShortTime, _ETHREAD::NestedFaultCount, NT_SUCCESS, NTSTATUS(), NULL, _MMINPAGE_SUPPORT::Page, PAGE_SIZE, PERFINFO_DISPATCHFAULT_DECL, PERFINFO_HARDFAULT, PERFINFO_HARDFAULT_INFO, PERFINFO_HARDFAULT_IOTIME, _MMINPAGE_SUPPORT::Pfn, PHARD_FAULT_NOTIFY_ROUTINE, PsGetCurrentThread, _MMPFN::PteFrame, _MMINPAGE_SUPPORT::ReadOffset, StandbyPageList, STATUS_ISSUE_PAGING_IO, STATUS_PTE_CHANGED, STATUS_REFAULT, TRUE, _MMPTE::u, _MMPFN::u1, _MMPFN::u2, _MMPFN::u3, UNLOCK_PFN, UNLOCK_SESSION_SPACE_WS, UNLOCK_SYSTEM_WS, and UNLOCK_WS.

Referenced by MmAccessFault().

00079 : 00080 00081 This routine dispatches a page fault to the appropriate 00082 routine to complete the fault. 00083 00084 Arguments: 00085 00086 StoreInstruction - Supplies TRUE if the instruction is trying 00087 to modify the faulting address (i.e. write 00088 access required). 00089 00090 VirtualAddress - Supplies the faulting address. 00091 00092 PointerPte - Supplies the PTE for the faulting address. 00093 00094 PointerProtoPte - Supplies a pointer to the prototype PTE to fault in, 00095 NULL if no prototype PTE exists. 00096 00097 Process - Supplies a pointer to the process object. If this 00098 parameter is NULL, then the fault is for system 00099 space and the process's working set lock is not held. 00100 If this parameter is HYDRA_PROCESS, then the fault is for session 00101 space and the process's working set lock is not held - rather 00102 the session space's working set lock is held. 00103 00104 ApcNeeded - Supplies a pointer to a location set to TRUE if an I/O 00105 completion APC is needed to complete partial IRPs that 00106 collided. 00107 00108 It is the caller's responsibility to initialize this (usually 00109 to FALSE) on entry. However, since this routine may be called 00110 multiple times for a single fault (for the page directory, 00111 page table and the page itself), it is possible for it to 00112 occasionally be TRUE on entry. 00113 00114 If it is FALSE on exit, no completion APC is needed. 00115 00116 Return Value: 00117 00118 status. 00119 00120 Environment: 00121 00122 Kernel mode, working set lock held. 00123 00124 --*/ 00125 00126 { 00127 MMPTE TempPte; 00128 NTSTATUS status; 00129 PMMINPAGE_SUPPORT ReadBlock; 00130 MMPTE SavedPte; 00131 PMMINPAGE_SUPPORT CapturedEvent; 00132 KIRQL OldIrql; 00133 PPFN_NUMBER Page; 00134 PFN_NUMBER PageFrameIndex; 00135 LONG NumberOfBytes; 00136 PMMPTE CheckPte; 00137 PMMPTE ReadPte; 00138 PMMPFN PfnClusterPage; 00139 PMMPFN Pfn1; 00140 PHARD_FAULT_NOTIFY_ROUTINE NotifyRoutine; 00141 KIRQL PreviousIrql; 00142 LOGICAL WsLockChanged; 00143 PETHREAD CurrentThread; 00144 00145 PERFINFO_DISPATCHFAULT_DECL(); 00146 00147 WsLockChanged = FALSE; 00148 00149 ProtoPteNotResident: 00150 00151 if (PointerProtoPte != NULL) { 00152 00153 // 00154 // Acquire the PFN lock to synchronize access to prototype PTEs. 00155 // This is required as the working set lock will not prevent 00156 // multiple processes from operating on the same prototype PTE. 00157 // 00158 00159 LOCK_PFN (OldIrql); 00160 00161 // 00162 // Make sure the protoptes are in memory. For 00163 // user mode faults, this should already be the case. 00164 // 00165 00166 if (!MI_IS_PHYSICAL_ADDRESS(PointerProtoPte)) { 00167 CheckPte = MiGetPteAddress (PointerProtoPte); 00168 00169 if (CheckPte->u.Hard.Valid == 0) { 00170 00171 ASSERT (Process == NULL || (MiHydra == TRUE && Process == HYDRA_PROCESS)); 00172 00173 // 00174 // The page that contains the prototype PTE is not in memory. 00175 // 00176 00177 VirtualAddress = PointerProtoPte; 00178 PointerPte = CheckPte; 00179 PointerProtoPte = NULL; 00180 UNLOCK_PFN (OldIrql); 00181 00182 if (Process == HYDRA_PROCESS) { 00183 // 00184 // We were called while holding this session space's 00185 // working set lock. But we need to fault in a 00186 // prototype PTE which is in system paged pool. This 00187 // must be done under the system working set lock. 00188 // 00189 // So we release the session space WSL lock and get 00190 // the system working set lock. When done 00191 // we return STATUS_MORE_PROCESSING_REQUIRED 00192 // so our caller will call us again to handle the 00193 // actual prototype PTE fault. 00194 // 00195 00196 ASSERT (MiHydra == TRUE); 00197 UNLOCK_SESSION_SPACE_WS (APC_LEVEL); 00198 00199 // 00200 // Lock the system working set for paged pool 00201 // 00202 00203 LOCK_SYSTEM_WS (PreviousIrql); 00204 00205 // 00206 // System working set is locked so set Process to show it. 00207 // 00208 00209 Process = NULL; 00210 00211 WsLockChanged = TRUE; 00212 00213 ASSERT (MI_IS_SESSION_ADDRESS (VirtualAddress) == FALSE); 00214 } 00215 else { 00216 ASSERT (Process == NULL); 00217 } 00218 00219 goto ProtoPteNotResident; 00220 } 00221 } 00222 00223 if (PointerPte->u.Hard.Valid == 1) { 00224 00225 // 00226 // PTE was already made valid by the cache manager support 00227 // routines. 00228 // 00229 00230 UNLOCK_PFN (OldIrql); 00231 00232 if (WsLockChanged == TRUE) { 00233 UNLOCK_SYSTEM_WS (APC_LEVEL); 00234 LOCK_SESSION_SPACE_WS (PreviousIrql); 00235 } 00236 00237 return STATUS_SUCCESS; 00238 } 00239 00240 ReadPte = PointerProtoPte; 00241 00242 PERFINFO_HARDFAULT_INFO(PointerProtoPte); 00243 00244 status = MiResolveProtoPteFault (StoreInstruction, 00245 VirtualAddress, 00246 PointerPte, 00247 PointerProtoPte, 00248 &ReadBlock, 00249 Process, 00250 ApcNeeded); 00251 // 00252 // Returns with PFN lock released. 00253 // 00254 00255 ASSERT (KeGetCurrentIrql() == APC_LEVEL); 00256 00257 } else { 00258 00259 TempPte = *PointerPte; 00260 ASSERT (TempPte.u.Long != 0); 00261 00262 if (TempPte.u.Soft.Transition != 0) { 00263 00264 // 00265 // This is a transition page. 00266 // 00267 00268 status = MiResolveTransitionFault (VirtualAddress, 00269 PointerPte, 00270 Process, 00271 FALSE, 00272 ApcNeeded); 00273 00274 } else if (TempPte.u.Soft.PageFileHigh == 0) { 00275 00276 // 00277 // Demand zero fault. 00278 // 00279 00280 status = MiResolveDemandZeroFault (VirtualAddress, 00281 PointerPte, 00282 Process, 00283 FALSE); 00284 } else { 00285 00286 // 00287 // Page resides in paging file. 00288 // 00289 00290 ReadPte = PointerPte; 00291 LOCK_PFN (OldIrql); 00292 status = MiResolvePageFileFault (VirtualAddress, 00293 PointerPte, 00294 &ReadBlock, 00295 Process); 00296 } 00297 } 00298 00299 ASSERT (KeGetCurrentIrql() == APC_LEVEL); 00300 00301 if (NT_SUCCESS(status)) { 00302 00303 if (WsLockChanged == TRUE) { 00304 UNLOCK_SYSTEM_WS (APC_LEVEL); 00305 LOCK_SESSION_SPACE_WS (OldIrql); 00306 } 00307 00308 return status; 00309 } 00310 00311 if (status == STATUS_ISSUE_PAGING_IO) { 00312 00313 SavedPte = *ReadPte; 00314 00315 CapturedEvent = (PMMINPAGE_SUPPORT)ReadBlock->Pfn->u1.Event; 00316 00317 CurrentThread = NULL; 00318 00319 if (Process == HYDRA_PROCESS) { 00320 UNLOCK_SESSION_SPACE_WS(APC_LEVEL); 00321 } 00322 else if (Process != NULL) { 00323 00324 // 00325 // APCs must be explicitly disabled to prevent suspend APCs from 00326 // interrupting this thread before the I/O has been issued. 00327 // Otherwise a shared page I/O can stop any other thread that 00328 // references it indefinitely until the suspend is released. 00329 // 00330 00331 CurrentThread = PsGetCurrentThread(); 00332 00333 ASSERT (CurrentThread->NestedFaultCount <= 2); 00334 CurrentThread->NestedFaultCount += 1; 00335 00336 KeEnterCriticalRegion(); 00337 UNLOCK_WS (Process); 00338 } 00339 else { 00340 UNLOCK_SYSTEM_WS(APC_LEVEL); 00341 } 00342 00343 #if DBG 00344 if (MmDebug & MM_DBG_PAGEFAULT) { 00345 DbgPrint ("MMFAULT: va: %p size: %lx process: %s file: %Z\n", 00346 VirtualAddress, 00347 ReadBlock->Mdl.ByteCount, 00348 Process == HYDRA_PROCESS ? (PUCHAR)"Session Space" : (Process ? Process->ImageFileName : (PUCHAR)"SystemVa"), 00349 &ReadBlock->FilePointer->FileName 00350 ); 00351 } 00352 #endif //DBG 00353 00354 PERFINFO_HARDFAULT(VirtualAddress, ReadBlock); 00355 00356 #if defined(_PREFETCH_) 00357 00358 // 00359 // Assert no reads issued here are marked as prefetched. 00360 // 00361 00362 ASSERT (ReadBlock->PrefetchMdl == NULL); 00363 00364 #endif 00365 00366 // 00367 // Issue the read request. 00368 // 00369 00370 status = IoPageRead ( ReadBlock->FilePointer, 00371 &ReadBlock->Mdl, 00372 &ReadBlock->ReadOffset, 00373 &ReadBlock->Event, 00374 &ReadBlock->IoStatus); 00375 if (!NT_SUCCESS(status)) { 00376 00377 // 00378 // Set the event as the I/O system doesn't set it on errors. 00379 // 00380 00381 00382 ReadBlock->IoStatus.Status = status; 00383 ReadBlock->IoStatus.Information = 0; 00384 KeSetEvent (&ReadBlock->Event, 00385 0, 00386 FALSE); 00387 } 00388 00389 // 00390 // Wait for the I/O operation. 00391 // 00392 00393 status = MiWaitForInPageComplete (ReadBlock->Pfn, 00394 ReadPte, 00395 VirtualAddress, 00396 &SavedPte, 00397 CapturedEvent, 00398 Process); 00399 00400 if (CurrentThread != NULL) { 00401 KeLeaveCriticalRegion(); 00402 00403 ASSERT (CurrentThread->NestedFaultCount <= 3); 00404 ASSERT (CurrentThread->NestedFaultCount != 0); 00405 00406 CurrentThread->NestedFaultCount -= 1; 00407 00408 if ((CurrentThread->ApcNeeded == 1) && 00409 (CurrentThread->NestedFaultCount == 0)) { 00410 *ApcNeeded = TRUE; 00411 CurrentThread->ApcNeeded = 0; 00412 } 00413 } 00414 00415 PERFINFO_HARDFAULT_IOTIME(); 00416 00417 // 00418 // MiWaitForInPageComplete RETURNS WITH THE WORKING SET LOCK 00419 // AND PFN LOCK HELD!!! 00420 // 00421 00422 // 00423 // This is the thread which owns the event, clear the event field 00424 // in the PFN database. 00425 // 00426 00427 Pfn1 = ReadBlock->Pfn; 00428 Page = &ReadBlock->Page[0]; 00429 NumberOfBytes = (LONG)ReadBlock->Mdl.ByteCount; 00430 CheckPte = ReadBlock->BasePte; 00431 00432 while (NumberOfBytes > 0) { 00433 00434 // 00435 // Don't remove the page we just brought in to 00436 // satisfy this page fault. 00437 // 00438 00439 if (CheckPte != ReadPte) { 00440 PfnClusterPage = MI_PFN_ELEMENT (*Page); 00441 ASSERT (PfnClusterPage->PteFrame == Pfn1->PteFrame); 00442 #if DBG 00443 if (PfnClusterPage->u3.e1.InPageError) { 00444 ASSERT (status != STATUS_SUCCESS); 00445 } 00446 #endif //DBG 00447 if (PfnClusterPage->u3.e1.ReadInProgress != 0) { 00448 00449 ASSERT (PfnClusterPage->PteFrame != MI_MAGIC_AWE_PTEFRAME); 00450 PfnClusterPage->u3.e1.ReadInProgress = 0; 00451 00452 if (PfnClusterPage->u3.e1.InPageError == 0) { 00453 PfnClusterPage->u1.Event = (PKEVENT)NULL; 00454 } 00455 } 00456 MI_REMOVE_LOCKED_PAGE_CHARGE(PfnClusterPage, 9); 00457 MiDecrementReferenceCount (*Page); 00458 } else { 00459 PageFrameIndex = *Page; 00460 } 00461 00462 CheckPte += 1; 00463 Page += 1; 00464 NumberOfBytes -= PAGE_SIZE; 00465 } 00466 00467 if (status != STATUS_SUCCESS) { 00468 00469 MI_REMOVE_LOCKED_PAGE_CHARGE(MI_PFN_ELEMENT(PageFrameIndex), 9); 00470 MiDecrementReferenceCount (PageFrameIndex); 00471 00472 if (status == STATUS_PTE_CHANGED) { 00473 00474 // 00475 // State of PTE changed during I/O operation, just 00476 // return success and refault. 00477 // 00478 00479 UNLOCK_PFN (APC_LEVEL); 00480 00481 if (WsLockChanged == TRUE) { 00482 UNLOCK_SYSTEM_WS (APC_LEVEL); 00483 LOCK_SESSION_SPACE_WS (OldIrql); 00484 } 00485 00486 return STATUS_SUCCESS; 00487 00488 } 00489 00490 // 00491 // An I/O error occurred during the page read 00492 // operation. All the pages which were just 00493 // put into transition should be put onto the 00494 // free list if InPageError is set, and their 00495 // PTEs restored to the proper contents. 00496 // 00497 00498 Page = &ReadBlock->Page[0]; 00499 00500 NumberOfBytes = ReadBlock->Mdl.ByteCount; 00501 00502 while (NumberOfBytes > 0) { 00503 00504 PfnClusterPage = MI_PFN_ELEMENT (*Page); 00505 00506 if (PfnClusterPage->u3.e1.InPageError == 1) { 00507 00508 if (PfnClusterPage->u3.e2.ReferenceCount == 0) { 00509 00510 PfnClusterPage->u3.e1.InPageError = 0; 00511 00512 // 00513 // Only restore the transition PTE if the address 00514 // space still exists. Another thread may have 00515 // deleted the VAD while this thread waited for the 00516 // fault to complete - in this case, the frame 00517 // will be marked as free already. 00518 // 00519 00520 if (PfnClusterPage->u3.e1.PageLocation != FreePageList) { 00521 ASSERT (PfnClusterPage->u3.e1.PageLocation == 00522 StandbyPageList); 00523 MiUnlinkPageFromList (PfnClusterPage); 00524 MiRestoreTransitionPte (*Page); 00525 MiInsertPageInList (MmPageLocationList[FreePageList], 00526 *Page); 00527 } 00528 } 00529 } 00530 Page += 1; 00531 NumberOfBytes -= PAGE_SIZE; 00532 } 00533 UNLOCK_PFN (APC_LEVEL); 00534 00535 if (WsLockChanged == TRUE) { 00536 UNLOCK_SYSTEM_WS (APC_LEVEL); 00537 LOCK_SESSION_SPACE_WS (OldIrql); 00538 } 00539 00540 if (status == STATUS_REFAULT) { 00541 00542 // 00543 // The I/O operation to bring in a system page failed 00544 // due to insufficent resources. Delay a bit, then 00545 // return success and refault. 00546 // 00547 00548 KeDelayExecutionThread (KernelMode, FALSE, (PLARGE_INTEGER)&MmShortTime); 00549 return STATUS_SUCCESS; 00550 } 00551 00552 return status; 00553 } 00554 00555 // 00556 // PTE is still in transition state, same protection, etc. 00557 // 00558 00559 ASSERT (Pfn1->u3.e1.InPageError == 0); 00560 00561 if (Pfn1->u2.ShareCount == 0) { 00562 MI_REMOVE_LOCKED_PAGE_CHARGE (Pfn1, 9); 00563 } 00564 00565 Pfn1->u2.ShareCount += 1; 00566 Pfn1->u3.e1.PageLocation = ActiveAndValid; 00567 00568 MI_MAKE_TRANSITION_PTE_VALID (TempPte, ReadPte); 00569 if (StoreInstruction && TempPte.u.Hard.Write) { 00570 MI_SET_PTE_DIRTY (TempPte); 00571 } 00572 MI_WRITE_VALID_PTE (ReadPte, TempPte); 00573 00574 if (PointerProtoPte != NULL) { 00575 00576 // 00577 // The prototype PTE has been made valid, now make the 00578 // original PTE valid. 00579 // 00580 00581 if (PointerPte->u.Hard.Valid == 0) { 00582 #if DBG 00583 NTSTATUS oldstatus = status; 00584 #endif //DBG 00585 00586 // 00587 // PTE is not valid, continue with operation. 00588 // 00589 00590 status = MiCompleteProtoPteFault (StoreInstruction, 00591 VirtualAddress, 00592 PointerPte, 00593 PointerProtoPte); 00594 00595 // 00596 // Returns with PFN lock released! 00597 // 00598 00599 #if DBG 00600 if (PointerPte->u.Hard.Valid == 0) { 00601 DbgPrint ("MM:PAGFAULT - va %p %p %p status:%lx\n", 00602 VirtualAddress, PointerPte, PointerProtoPte, oldstatus); 00603 } 00604 #endif //DBG 00605 } 00606 } else { 00607 00608 #if PFN_CONSISTENCY 00609 if (MiGetPteAddress(ReadPte) == MiGetPdeAddress(PTE_BASE)) { 00610 Pfn1->u3.e1.PageTablePage = 1; 00611 } 00612 #endif 00613 00614 if (Pfn1->u1.Event == 0) { 00615 Pfn1->u1.Event = (PVOID)PsGetCurrentThread(); 00616 } 00617 00618 UNLOCK_PFN (APC_LEVEL); 00619 MiAddValidPageToWorkingSet (VirtualAddress, 00620 ReadPte, 00621 Pfn1, 00622 0); 00623 } 00624 00625 // 00626 // Note this routine could release and reacquire the PFN lock! 00627 // 00628 00629 LOCK_PFN (OldIrql); 00630 MiFlushInPageSupportBlock(); 00631 UNLOCK_PFN (APC_LEVEL); 00632 00633 if (status == STATUS_SUCCESS) { 00634 status = STATUS_PAGE_FAULT_PAGING_FILE; 00635 } 00636 NotifyRoutine = MmHardFaultNotifyRoutine; 00637 if (NotifyRoutine) { 00638 (*NotifyRoutine) ( 00639 ReadBlock->FilePointer, 00640 VirtualAddress 00641 ); 00642 } 00643 } 00644 00645 // 00646 // Stop high priority threads from consuming the CPU on collided 00647 // faults for pages that are still marked with inpage errors. All 00648 // the threads must let go of the page so it can be freed and the 00649 // inpage I/O reissued to the filesystem. 00650 // 00651 00652 if (MmIsRetryIoStatus(status)) { 00653 KeDelayExecutionThread (KernelMode, FALSE, (PLARGE_INTEGER)&MmShortTime); 00654 status = STATUS_SUCCESS; 00655 } 00656 00657 if ((status == STATUS_REFAULT) || 00658 (status == STATUS_PTE_CHANGED)) { 00659 status = STATUS_SUCCESS; 00660 } 00661 00662 ASSERT (KeGetCurrentIrql() == APC_LEVEL); 00663 00664 if (WsLockChanged == TRUE) { 00665 UNLOCK_SYSTEM_WS (APC_LEVEL); 00666 LOCK_SESSION_SPACE_WS (OldIrql); 00667 } 00668 00669 return status; 00670 }

ULONG MiDoesPdeExistAndMakeValid IN PMMPTE  PointerPde,
IN PEPROCESS  TargetProcess,
IN ULONG  PfnMutexHeld,
OUT PULONG  Waited
 

Definition at line 437 of file mmsup.c.

References APC_LEVEL, FALSE, LOCK_PFN, MiGetVirtualAddressMappedByPte, MiMakeSystemAddressValid(), TRUE, and UNLOCK_PFN.

Referenced by MiCalculatePageCommitment(), MiCloneProcessAddressSpace(), MiDeletePte(), MiDeleteVirtualAddresses(), MiFlushDirtyBitsToPfn(), MiIsEntireRangeCommitted(), MiProtectVirtualMemory(), MiQueryAddressState(), MiResetVirtualMemory(), MiSetProtectionOnSection(), MmFlushVirtualMemory(), MmSecureVirtualMemory(), and NtLockVirtualMemory().

00446 : 00447 00448 This routine examines the specified Page Directory Entry to determine 00449 if the page table page mapped by the PDE exists. 00450 00451 If the page table page exists and is not currently in memory, the 00452 working set mutex and, if held, the PFN mutex are released and the 00453 page table page is faulted into the working set. The mutexes are 00454 reacquired. 00455 00456 If the PDE exists, the function returns true. 00457 00458 Arguments: 00459 00460 PointerPde - Supplies a pointer to the PDE to examine and potentially 00461 bring into the working set. 00462 00463 TargetProcess - Supplies a pointer to the current process. 00464 00465 PfnMutexHeld - Supplies the value TRUE if the PFN mutex is held, FALSE 00466 otherwise. 00467 00468 Waited - Supplies a pointer to a ULONG to increment if the mutex is released 00469 and reacquired. Note this value may be incremented more than once. 00470 00471 Return Value: 00472 00473 TRUE if the PDE exists, FALSE if the PDE is zero. 00474 00475 Environment: 00476 00477 Kernel mode, APCs disabled, WorkingSetLock held. 00478 00479 --*/ 00480 00481 { 00482 PMMPTE PointerPte; 00483 KIRQL OldIrql; 00484 00485 OldIrql = APC_LEVEL; 00486 00487 if (PointerPde->u.Long == 0) { 00488 00489 // 00490 // This page directory entry doesn't exist, return FALSE. 00491 // 00492 00493 return FALSE; 00494 } 00495 00496 if (PointerPde->u.Hard.Valid == 1) { 00497 00498 // 00499 // Already valid. 00500 // 00501 00502 return TRUE; 00503 } 00504 00505 // 00506 // Page directory entry exists, it is either valid, in transition 00507 // or in the paging file. Fault it in. 00508 // 00509 00510 if (PfnMutexHeld) { 00511 UNLOCK_PFN (OldIrql); 00512 *Waited += 1; 00513 } 00514 00515 PointerPte = MiGetVirtualAddressMappedByPte (PointerPde); 00516 00517 *Waited += MiMakeSystemAddressValid (PointerPte, TargetProcess); 00518 00519 if (PfnMutexHeld) { 00520 LOCK_PFN (OldIrql); 00521 } 00522 return TRUE; 00523 }

VOID MiDumpPfn VOID   ) 
 

Referenced by MmInitSystem().

VOID MiDumpValidAddresses VOID   ) 
 

Referenced by MmInitSystem().

VOID MiDumpWsl VOID   ) 
 

Referenced by MiRemoveWsle().

VOID MiEmptyAllWorkingSets VOID   ) 
 

Definition at line 2715 of file wsmanage.c.

References ASSERT, ExPageLockHandle, FALSE, KeClearEvent, KernelMode, KeSetEvent(), KeWaitForSingleObject(), LOCK_EXPANSION, MiEmptyAllWorkingSetsWorker(), MiHydra, MiWaitForEmptyEvent, MiWaitingForWorkingSetEmpty, MmLockPagableSectionByHandle(), MmUnlockPagableImageSection(), MmWorkingSetManagerEvent, PAGED_CODE, PsGetCurrentThread, TRUE, UNLOCK_EXPANSION, and WrVirtualMemory.

Referenced by MiAllocateContiguousMemory(), MmGatherMemoryForHibernate(), and MmRemovePhysicalMemory().

02721 : 02722 02723 This routine attempts to empty all the working sets on the 02724 expansion list. 02725 02726 Arguments: 02727 02728 None. 02729 02730 Return Value: 02731 02732 None. 02733 02734 Environment: 02735 02736 Kernel mode. No locks held. APC level or below. 02737 02738 --*/ 02739 02740 { 02741 KIRQL OldIrql; 02742 02743 PAGED_CODE (); 02744 02745 MmLockPagableSectionByHandle (ExPageLockHandle); 02746 02747 if (MiHydra == FALSE) { 02748 MiEmptyAllWorkingSetsWorker (); 02749 } 02750 else { 02751 ASSERT (PsGetCurrentThread () != MmWorkingSetThread); 02752 02753 // 02754 // For Hydra, we cannot attach directly to the session space to be 02755 // trimmed because it would result in session space references by 02756 // other threads in this process to the attached session instead 02757 // of the (currently) correct one. In fact, we cannot even queue 02758 // this to a worker thread because the working set manager 02759 // (who shares the same page directory) may be attaching or 02760 // detaching from a session (any session). So this must be queued 02761 // to the working set manager. 02762 // 02763 02764 LOCK_EXPANSION (OldIrql); 02765 02766 if (MiWaitingForWorkingSetEmpty == FALSE) { 02767 MiWaitingForWorkingSetEmpty = TRUE; 02768 KeClearEvent (&MiWaitForEmptyEvent); 02769 } 02770 02771 UNLOCK_EXPANSION (OldIrql); 02772 02773 KeSetEvent (&MmWorkingSetManagerEvent, 0, FALSE); 02774 02775 KeWaitForSingleObject (&MiWaitForEmptyEvent, 02776 WrVirtualMemory, 02777 KernelMode, 02778 FALSE, 02779 (PLARGE_INTEGER)0); 02780 } 02781 02782 MmUnlockPagableImageSection (ExPageLockHandle); 02783 02784 return; 02785 }

NTSTATUS MiEmptyWorkingSet IN PMMSUPPORT  WsInfo,
IN LOGICAL  WaitOk
 

Definition at line 4726 of file wslist.c.

References _EPROCESS::AddressSpaceDeleted, APC_LEVEL, ASSERT, Count, ExTryToAcquireResourceExclusiveLite(), FALSE, _MMWSL::FirstDynamic, _MMWSL::FirstFree, KeDelayExecutionThread(), KeLowerIrql(), KeRaiseIrql(), KernelMode, _MMWSL::LastEntry, _MMWSL::LastInitializedWsle, LOCK_SESSION_SPACE_WS, LOCK_SYSTEM_WS, LOCK_WS, MI_GET_PAGE_FRAME_FROM_PTE, MI_PFN_ELEMENT, MiFreeWsle(), MiGetPteAddress, MiHydra, MiRemoveWorkingSetPages(), MiTrimRemovalPagesOnly, MM_FREE_WSLE_SHIFT, MM_SET_SESSION_RESOURCE_OWNER, MmShortTime, MmSystemCacheWs, MmSystemLockOwner, MmSystemWsLock, _MMWSL::NextSlot, NTSTATUS(), PERFINFO_GET_PAGE_INFO, PERFINFO_LOG_WS_REMOVAL, PERFINFO_PAGE_INFO_DECL, PsGetCurrentProcess, PsGetCurrentThread, _MMPFN::PteFrame, _MMWSL::Quota, Status, TRUE, _MMSUPPORT::u, _MMWSLE::u1, _MMPFN::u3, UNLOCK_SESSION_SPACE_WS, UNLOCK_SYSTEM_WS, UNLOCK_WS, _MMWSLE::VirtualAddress, _EPROCESS::WorkingSetLock, _MMWSL::Wsle, WSLE_NULL_INDEX, and _MM_SESSION_SPACE::WsLock.

Referenced by MiEmptyAllWorkingSetsWorker(), MmAdjustWorkingSetSize(), and MmTrimAllSystemPagableMemory().

04733 : 04734 04735 This routine frees all pages from the working set. 04736 04737 Arguments: 04738 04739 WsInfo - Supplies the working set information entry to trim. 04740 04741 WaitOk - Supplies TRUE if the caller can wait, FALSE if not. 04742 04743 Return Value: 04744 04745 Status of operation. 04746 04747 Environment: 04748 04749 Kernel mode. No locks. For session operations, the caller is responsible 04750 for attaching into the proper session. 04751 04752 --*/ 04753 04754 { 04755 PEPROCESS Process; 04756 KIRQL OldIrql; 04757 PMMPTE PointerPte; 04758 ULONG Entry; 04759 ULONG Count; 04760 ULONG LastFreed; 04761 PMMWSL WorkingSetList; 04762 PMMWSLE Wsle; 04763 PMMPFN Pfn1; 04764 PFN_NUMBER PageFrameIndex; 04765 ULONG Last; 04766 NTSTATUS Status; 04767 PMM_SESSION_SPACE SessionSpace; 04768 04769 if (WsInfo == &MmSystemCacheWs) { 04770 if (WaitOk == TRUE) { 04771 LOCK_SYSTEM_WS (OldIrql); 04772 } 04773 else { 04774 KeRaiseIrql (APC_LEVEL, &OldIrql); 04775 if (!ExTryToAcquireResourceExclusiveLite (&MmSystemWsLock)) { 04776 04777 // 04778 // System working set lock was not granted, don't trim 04779 // the system cache. 04780 // 04781 04782 KeLowerIrql (OldIrql); 04783 return STATUS_SUCCESS; 04784 } 04785 04786 MmSystemLockOwner = PsGetCurrentThread(); 04787 } 04788 } 04789 else if (WsInfo->u.Flags.SessionSpace == 0) { 04790 Process = PsGetCurrentProcess (); 04791 if (WaitOk == TRUE) { 04792 LOCK_WS (Process); 04793 } 04794 else { 04795 Count = 0; 04796 do { 04797 if (ExTryToAcquireFastMutex(&Process->WorkingSetLock) != FALSE) { 04798 break; 04799 } 04800 KeDelayExecutionThread (KernelMode, FALSE, &MmShortTime); 04801 Count += 1; 04802 if (Count == 5) { 04803 04804 // 04805 // Could not get the lock, don't trim this process. 04806 // 04807 04808 return STATUS_SUCCESS; 04809 } 04810 } while (TRUE); 04811 } 04812 if (Process->AddressSpaceDeleted != 0) { 04813 Status = STATUS_PROCESS_IS_TERMINATING; 04814 goto Deleted; 04815 } 04816 } 04817 else { 04818 if (WaitOk == TRUE) { 04819 LOCK_SESSION_SPACE_WS (OldIrql); 04820 } 04821 else { 04822 ASSERT (MiHydra == TRUE); 04823 SessionSpace = CONTAINING_RECORD(WsInfo, 04824 MM_SESSION_SPACE, 04825 Vm); 04826 04827 KeRaiseIrql (APC_LEVEL, &OldIrql); 04828 04829 if (!ExTryToAcquireResourceExclusiveLite (&SessionSpace->WsLock)) { 04830 04831 // 04832 // This session space's working set lock was not 04833 // granted, don't trim it. 04834 // 04835 04836 KeLowerIrql (OldIrql); 04837 return STATUS_SUCCESS; 04838 } 04839 04840 MM_SET_SESSION_RESOURCE_OWNER(); 04841 } 04842 } 04843 04844 WorkingSetList = WsInfo->VmWorkingSetList; 04845 Wsle = WorkingSetList->Wsle; 04846 04847 // 04848 // Attempt to remove the pages starting at the bottom. 04849 // 04850 04851 LastFreed = WorkingSetList->LastEntry; 04852 for (Entry = WorkingSetList->FirstDynamic; Entry <= LastFreed; Entry += 1) { 04853 04854 if (Wsle[Entry].u1.e1.Valid != 0) { 04855 PERFINFO_PAGE_INFO_DECL(); 04856 04857 PointerPte = MiGetPteAddress (Wsle[Entry].u1.VirtualAddress); 04858 04859 PERFINFO_GET_PAGE_INFO(PointerPte); 04860 04861 if (MiTrimRemovalPagesOnly == TRUE) { 04862 PageFrameIndex = MI_GET_PAGE_FRAME_FROM_PTE (PointerPte); 04863 Pfn1 = MI_PFN_ELEMENT (PageFrameIndex); 04864 if (Pfn1->u3.e1.RemovalRequested == 0) { 04865 Pfn1 = MI_PFN_ELEMENT (Pfn1->PteFrame); 04866 if (Pfn1->u3.e1.RemovalRequested == 0) { 04867 #if defined (_WIN64) 04868 Pfn1 = MI_PFN_ELEMENT (Pfn1->PteFrame); 04869 if (Pfn1->u3.e1.RemovalRequested == 0) { 04870 continue; 04871 } 04872 #else 04873 continue; 04874 #endif 04875 } 04876 } 04877 } 04878 04879 if (MiFreeWsle (Entry, WsInfo, PointerPte)) { 04880 PERFINFO_LOG_WS_REMOVAL(PERFINFO_LOG_TYPE_OUTWS_EMPTYQ, WsInfo); 04881 } 04882 } 04883 } 04884 04885 if (WsInfo != &MmSystemCacheWs && WsInfo->u.Flags.SessionSpace == 0) { 04886 MiRemoveWorkingSetPages (WorkingSetList,WsInfo); 04887 } 04888 WorkingSetList->Quota = WsInfo->WorkingSetSize; 04889 WorkingSetList->NextSlot = WorkingSetList->FirstDynamic; 04890 04891 // 04892 // Attempt to remove the pages from the front to the end. 04893 // 04894 04895 // 04896 // Reorder the free list. 04897 // 04898 04899 Last = 0; 04900 Entry = WorkingSetList->FirstDynamic; 04901 LastFreed = WorkingSetList->LastInitializedWsle; 04902 while (Entry <= LastFreed) { 04903 if (Wsle[Entry].u1.e1.Valid == 0) { 04904 if (Last == 0) { 04905 WorkingSetList->FirstFree = Entry; 04906 } else { 04907 Wsle[Last].u1.Long = Entry << MM_FREE_WSLE_SHIFT; 04908 } 04909 Last = Entry; 04910 } 04911 Entry += 1; 04912 } 04913 if (Last != 0) { 04914 Wsle[Last].u1.Long = WSLE_NULL_INDEX << MM_FREE_WSLE_SHIFT; // End of list. 04915 } 04916 Status = STATUS_SUCCESS; 04917 Deleted: 04918 04919 if (WsInfo == &MmSystemCacheWs) { 04920 UNLOCK_SYSTEM_WS (OldIrql); 04921 } 04922 else if (WsInfo->u.Flags.SessionSpace == 0) { 04923 UNLOCK_WS (Process); 04924 } 04925 else { 04926 UNLOCK_SESSION_SPACE_WS (OldIrql); 04927 } 04928 04929 return Status; 04930 }

VOID MiEnableKernelVerifier VOID   ) 
 

Referenced by MmInitSystem().

VOID MiEnableRandomSpecialPool IN LOGICAL  Enable  ) 
 

Definition at line 3398 of file allocpag.c.

References MiBadTags, and _MI_BAD_TAGS::RandomizerEnabled.

Referenced by MiApplyDriverVerifier(), and MiVerifyingDriverUnloading().

03401 { 03402 MiBadTags.RandomizerEnabled = Enable; 03403 }

LARGE_INTEGER MiEndingOffset IN PSUBSECTION  Subsection  ) 
 

Definition at line 965 of file flushsec.c.

References Mi4KStartFromSubsection, MM4K_SHIFT, and MMSECTOR_SHIFT.

Referenced by MiCanFileBeTruncatedInternal(), MiCleanSection(), MiFlushSectionInternal(), and MiResolveMappedFileFault().

00971 : 00972 00973 This function calculates the last valid file offset in a given subsection. 00974 offset. Note that images are stored in 512-byte units whereas data is 00975 stored in 4K units. 00976 00977 When this is all debugged, this should be made into a macro. 00978 00979 Arguments: 00980 00981 Subsection - Supplies a subsection to reference for the file address. 00982 00983 PteAddress - Supplies a PTE within the subsection 00984 00985 Return Value: 00986 00987 Returns the file offset to obtain the backing data from. 00988 00989 --*/ 00990 00991 { 00992 LARGE_INTEGER FileByteOffset; 00993 00994 if (Subsection->ControlArea->u.Flags.Image == 1) { 00995 FileByteOffset.QuadPart = 00996 (Subsection->StartingSector + Subsection->NumberOfFullSectors) << 00997 MMSECTOR_SHIFT; 00998 } 00999 else { 01000 Mi4KStartFromSubsection (&FileByteOffset, Subsection); 01001 01002 FileByteOffset.QuadPart += Subsection->NumberOfFullSectors; 01003 01004 FileByteOffset.QuadPart = FileByteOffset.QuadPart << MM4K_SHIFT; 01005 } 01006 01007 FileByteOffset.QuadPart += Subsection->u.SubsectionFlags.SectorEndOffset; 01008 01009 return FileByteOffset; 01010 }

ULONG FASTCALL MiEnsureAvailablePageOrWait IN PEPROCESS  Process,
IN PVOID  VirtualAddress
 

Definition at line 941 of file pfnlist.c.

References APC_LEVEL, _PHYSICAL_MEMORY_RUN::BasePage, DbgPrint, Event(), FALSE, FASTCALL, HYDRA_PROCESS, HYPER_SPACE, KdDebuggerNotPresent, KeBugCheckEx(), KeClearEvent, KernelMode, KeWaitForSingleObject(), LOCK_PFN, LOCK_SESSION_SPACE_WS, LOCK_SYSTEM_WS, LOCK_WS_REGARDLESS, MI_IS_HYPER_SPACE_ADDRESS, MI_IS_SYSTEM_ADDRESS, MI_PFN_ELEMENT, MiGetPteAddress, MM_HIGH_LIMIT, MM_LOW_LIMIT, MM_PFN_LOCK_ASSERT, MmAllocatedNonPagedPool, MmAvailablePages, MmAvailablePagesEvent, MmAvailablePagesEventHigh, MmMaximumNonPagedPoolInBytes, MmModifiedPageListHead, MmPhysicalMemoryBlock, MmSevenMinutes, MmSystemLockOwner, MmTotalPagesForPagingFile, NTSTATUS(), NULL, _PHYSICAL_MEMORY_DESCRIPTOR::NumberOfRuns, PAGE_SHIFT, _PHYSICAL_MEMORY_RUN::PageCount, PsGetCurrentThread, _PHYSICAL_MEMORY_DESCRIPTOR::Run, Status, _MMPFNLIST::Total, TransitionPage, TRUE, _MMPFN::u3, UNLOCK_PFN, UNLOCK_SESSION_SPACE_WS, UNLOCK_SYSTEM_WS, UNLOCK_WS_REGARDLESS, and WrFreePage.

Referenced by MiCopyOnWrite(), MiDoneWithThisPageGetAnother(), MiFillSystemPageDirectory(), MiGetPageForHeader(), MiInitializeSessionPool(), MiInitializeWorkingSetList(), MiLoadImageSection(), MiMakeOutswappedPageResident(), MiReloadBootLoadedDrivers(), MiResolveDemandZeroFault(), MiResolveMappedFileFault(), MiResolvePageFileFault(), MiSessionCommitImagePages(), MiSessionCommitPageTables(), MiSessionCopyOnWrite(), MiSessionCreateInternal(), MiSessionInitializeWorkingSetList(), MmAccessFault(), MmAllocateIndependentPages(), MmAllocateNonCachedMemory(), MmCopyToCachedPage(), MmCreateKernelStack(), MmCreateProcessAddressSpace(), and MmGrowKernelStack().

00948 : 00949 00950 This procedure ensures that a physical page is available on 00951 the zeroed, free or standby list such that the next call the remove a 00952 page absolutely will not block. This is necessary as blocking would 00953 require a wait which could cause a deadlock condition. 00954 00955 If a page is available the function returns immediately with a value 00956 of FALSE indicating no wait operation was performed. If no physical 00957 page is available, the thread enters a wait state and the function 00958 returns the value TRUE when the wait operation completes. 00959 00960 Arguments: 00961 00962 Process - Supplies a pointer to the current process if, and only if, 00963 the working set mutex is held currently held and should 00964 be released if a wait operation is issued. Supplies 00965 the value NULL otherwise. 00966 00967 VirtualAddress - Supplies the virtual address for the faulting page. 00968 If the value is NULL, the page is treated as a 00969 user mode address. 00970 00971 Return Value: 00972 00973 FALSE - if a page was immediately available. 00974 TRUE - if a wait operation occurred before a page became available. 00975 00976 00977 Environment: 00978 00979 Must be holding the PFN database mutex with APCs disabled. 00980 00981 --*/ 00982 00983 { 00984 PVOID Event; 00985 NTSTATUS Status; 00986 KIRQL OldIrql; 00987 KIRQL Ignore; 00988 ULONG Limit; 00989 ULONG Relock; 00990 PFN_NUMBER StrandedPages; 00991 LOGICAL WsHeldSafe; 00992 PMMPFN Pfn1; 00993 PMMPFN EndPfn; 00994 LARGE_INTEGER WaitBegin; 00995 LARGE_INTEGER WaitEnd; 00996 00997 MM_PFN_LOCK_ASSERT(); 00998 00999 if (MmAvailablePages >= MM_HIGH_LIMIT) { 01000 01001 // 01002 // Pages are available. 01003 // 01004 01005 return FALSE; 01006 } 01007 01008 // 01009 // If this fault is for paged pool (or pagable kernel space, 01010 // including page table pages), let it use the last page. 01011 // 01012 01013 #if defined(_IA64_) 01014 if (MI_IS_SYSTEM_ADDRESS(VirtualAddress) || 01015 (MI_IS_HYPER_SPACE_ADDRESS(VirtualAddress))) { 01016 #else 01017 if (((PMMPTE)VirtualAddress > MiGetPteAddress(HYPER_SPACE)) || 01018 ((VirtualAddress > MM_HIGHEST_USER_ADDRESS) && 01019 (VirtualAddress < (PVOID)PTE_BASE))) { 01020 #endif 01021 01022 // 01023 // This fault is in the system, use 1 page as the limit. 01024 // 01025 01026 if (MmAvailablePages >= MM_LOW_LIMIT) { 01027 01028 // 01029 // Pages are available. 01030 // 01031 01032 return FALSE; 01033 } 01034 01035 Limit = MM_LOW_LIMIT; 01036 Event = (PVOID)&MmAvailablePagesEvent; 01037 } else { 01038 Limit = MM_HIGH_LIMIT; 01039 Event = (PVOID)&MmAvailablePagesEventHigh; 01040 } 01041 01042 while (MmAvailablePages < Limit) { 01043 KeClearEvent ((PKEVENT)Event); 01044 01045 UNLOCK_PFN (APC_LEVEL); 01046 01047 if (Process == HYDRA_PROCESS) { 01048 UNLOCK_SESSION_SPACE_WS (APC_LEVEL); 01049 } 01050 else if (Process != NULL) { 01051 01052 // 01053 // The working set lock may have been acquired safely or unsafely 01054 // by our caller. Handle both cases here and below. 01055 // 01056 01057 UNLOCK_WS_REGARDLESS (Process, WsHeldSafe); 01058 } 01059 else { 01060 Relock = FALSE; 01061 if (MmSystemLockOwner == PsGetCurrentThread()) { 01062 UNLOCK_SYSTEM_WS (APC_LEVEL); 01063 Relock = TRUE; 01064 } 01065 } 01066 01067 KiQueryInterruptTime(&WaitBegin); 01068 01069 // 01070 // Wait 7 minutes for pages to become available. 01071 // 01072 01073 Status = KeWaitForSingleObject(Event, 01074 WrFreePage, 01075 KernelMode, 01076 FALSE, 01077 (PLARGE_INTEGER)&MmSevenMinutes); 01078 01079 if (Status == STATUS_TIMEOUT) { 01080 01081 KiQueryInterruptTime(&WaitEnd); 01082 01083 // 01084 // See how many transition pages have nonzero reference counts as 01085 // these indicate drivers that aren't unlocking the pages in their 01086 // MDLs. 01087 // 01088 01089 Limit = 0; 01090 StrandedPages = 0; 01091 01092 do { 01093 01094 Pfn1 = MI_PFN_ELEMENT (MmPhysicalMemoryBlock->Run[Limit].BasePage); 01095 EndPfn = Pfn1 + MmPhysicalMemoryBlock->Run[Limit].PageCount; 01096 01097 while (Pfn1 < EndPfn) { 01098 if ((Pfn1->u3.e1.PageLocation == TransitionPage) && 01099 (Pfn1->u3.e2.ReferenceCount != 0)) { 01100 StrandedPages += 1; 01101 } 01102 Pfn1 += 1; 01103 } 01104 Limit += 1; 01105 01106 } while (Limit != MmPhysicalMemoryBlock->NumberOfRuns); 01107 01108 // 01109 // This bugcheck can occur for the following reasons: 01110 // 01111 // A driver has blocked, deadlocking the modified or mapped 01112 // page writers. Examples of this include mutex deadlocks or 01113 // accesses to paged out memory in filesystem drivers, filter 01114 // drivers, etc. This indicates a driver bug. 01115 // 01116 // The storage driver(s) are not processing requests. Examples 01117 // of this are stranded queues, non-responding drives, etc. This 01118 // indicates a driver bug. 01119 // 01120 // Not enough pool is available for the storage stack to write out 01121 // modified pages. This indicates a driver bug. 01122 // 01123 // A high priority realtime thread has starved the balance set 01124 // manager from trimming pages and/or starved the modified writer 01125 // from writing them out. This indicates a bug in the component 01126 // that created this thread. 01127 // 01128 // All the processes have been trimmed to their minimums and all 01129 // modified pages written, but still no memory is available. The 01130 // freed memory must be stuck in transition pages with non-zero 01131 // reference counts - thus they cannot be put on the freelist. 01132 // A driver is neglecting to unlock the pages preventing the 01133 // reference counts from going to zero which would free the pages. 01134 // This may be due to transfers that never finish and the driver 01135 // never aborts or other driver bugs. 01136 // 01137 01138 KeBugCheckEx (NO_PAGES_AVAILABLE, 01139 MmModifiedPageListHead.Total, 01140 MmTotalPagesForPagingFile, 01141 (MmMaximumNonPagedPoolInBytes >> PAGE_SHIFT) - MmAllocatedNonPagedPool, 01142 StrandedPages); 01143 01144 if (!KdDebuggerNotPresent) { 01145 DbgPrint ("MmEnsureAvailablePageOrWait: 7 min timeout %x %x %x %x\n", WaitEnd.HighPart, WaitEnd.LowPart, WaitBegin.HighPart, WaitBegin.LowPart); 01146 DbgBreakPoint (); 01147 } 01148 } 01149 01150 if (Process == HYDRA_PROCESS) { 01151 LOCK_SESSION_SPACE_WS (Ignore); 01152 } 01153 else if (Process != NULL) { 01154 01155 // 01156 // The working set lock may have been acquired safely or unsafely 01157 // by our caller. Reacquire it in the same manner our caller did. 01158 // 01159 01160 LOCK_WS_REGARDLESS (Process, WsHeldSafe); 01161 } 01162 else { 01163 if (Relock) { 01164 LOCK_SYSTEM_WS (Ignore); 01165 } 01166 } 01167 01168 LOCK_PFN (OldIrql); 01169 } 01170 01171 return TRUE; 01172 }

SIZE_T MiExtendPagingFiles IN PMMPAGE_FILE_EXPANSION  PageExpand  ) 
 

Definition at line 1681 of file modwrite.c.

References ASSERT, FALSE, _MMPAGING_FILE::MaximumSize, MI_EXTEND_ANY_PAGEFILE, MiAttemptPageFileExtension(), MmChargeCommitmentLock, MmNumberOfPagingFiles, MmPageFileFullExtendPages, MmPagingFile, MmTotalCommitLimit, MmTotalCommittedPages, _MMPAGING_FILE::Size, and TRUE.

Referenced by MiDereferenceSegmentThread().

01687 : 01688 01689 This routine attempts to extend the paging files to provide 01690 ExtendSize bytes. 01691 01692 Note - Page file expansion and page file reduction are synchronized 01693 because a single thread is responsible for performing the 01694 operation. Hence, while expansion is occurring, a reduction 01695 request will be queued to the thread. 01696 01697 Arguments: 01698 01699 DesiredQuota - Supplies the quota in pages desired. 01700 01701 PageFileNumber - Supplies the page file number to extend. 01702 MI_EXTEND_ANY_PAGFILE indicates to extend any page file. 01703 01704 Return Value: 01705 01706 Returns the size of the extension. Zero if the page file(s) cannot 01707 be extended. 01708 01709 --*/ 01710 01711 { 01712 SIZE_T DesiredQuota; 01713 ULONG PageFileNumber; 01714 SIZE_T ExtendedSize; 01715 SIZE_T ExtendSize; 01716 ULONG i; 01717 KIRQL OldIrql; 01718 LOGICAL LockHeld; 01719 LOGICAL RealExpansion; 01720 01721 RealExpansion = TRUE; 01722 LockHeld = FALSE; 01723 ExtendedSize = 0; 01724 DesiredQuota = PageExpand->RequestedExpansionSize; 01725 PageFileNumber = PageExpand->PageFileNumber; 01726 01727 PageExpand->ActualExpansion = 0; 01728 01729 ASSERT (PageFileNumber < MmNumberOfPagingFiles || PageFileNumber == MI_EXTEND_ANY_PAGEFILE); 01730 01731 if (MmNumberOfPagingFiles == 0) { 01732 goto alldone; 01733 } 01734 01735 if (PageFileNumber < MmNumberOfPagingFiles) { 01736 i = PageFileNumber; 01737 ExtendedSize = MmPagingFile[i]->MaximumSize - MmPagingFile[i]->Size; 01738 if (ExtendedSize < DesiredQuota) { 01739 ExtendedSize = 0; 01740 } 01741 else { 01742 ExtendedSize = MiAttemptPageFileExtension (i, DesiredQuota, FALSE); 01743 } 01744 goto alldone; 01745 } 01746 01747 LockHeld = TRUE; 01748 ExAcquireSpinLock (&MmChargeCommitmentLock, &OldIrql); 01749 01750 // 01751 // Check to see if ample space already exists now that we have 01752 // the spinlock. 01753 // 01754 01755 ExtendSize = DesiredQuota + MmTotalCommittedPages; 01756 01757 if (MmTotalCommitLimit >= ExtendSize) { 01758 ExtendedSize = 1; 01759 RealExpansion = FALSE; 01760 goto alldone; 01761 } 01762 01763 // 01764 // Calculate the additional pages needed. 01765 // 01766 01767 ExtendSize -= MmTotalCommitLimit; 01768 01769 ExReleaseSpinLock (&MmChargeCommitmentLock, OldIrql); 01770 LockHeld = FALSE; 01771 01772 // 01773 // Make sure ample space exists within the paging files. 01774 // 01775 01776 i = 0; 01777 01778 do { 01779 ExtendedSize += MmPagingFile[i]->MaximumSize - MmPagingFile[i]->Size; 01780 i += 1; 01781 } while (i < MmNumberOfPagingFiles); 01782 01783 if (ExtendedSize < ExtendSize) { 01784 ExtendedSize = 0; 01785 goto alldone; 01786 } 01787 01788 // 01789 // Attempt to extend only one of the paging files. 01790 // 01791 01792 i = 0; 01793 do { 01794 ExtendedSize = MiAttemptPageFileExtension (i, ExtendSize, FALSE); 01795 if (ExtendedSize != 0) { 01796 goto alldone; 01797 } 01798 i += 1; 01799 } while (i < MmNumberOfPagingFiles); 01800 01801 ASSERT (ExtendedSize == 0); 01802 01803 if (MmNumberOfPagingFiles == 1) { 01804 01805 // 01806 // If the attempt didn't succeed for one (not enough disk space free) - 01807 // don't try to set it to the maximum size. 01808 // 01809 01810 goto alldone; 01811 } 01812 01813 // 01814 // Attempt to extend all paging files. 01815 // 01816 01817 i = 0; 01818 do { 01819 ASSERT (ExtendSize > ExtendedSize); 01820 ExtendedSize += MiAttemptPageFileExtension (i, 01821 ExtendSize - ExtendedSize, 01822 TRUE); 01823 if (ExtendedSize >= ExtendSize) { 01824 goto alldone; 01825 } 01826 i += 1; 01827 } while (i < MmNumberOfPagingFiles); 01828 01829 // 01830 // Not enough space is available. 01831 // 01832 01833 ExtendedSize = 0; 01834 01835 alldone: 01836 01837 if (LockHeld == FALSE) { 01838 ExAcquireSpinLock (&MmChargeCommitmentLock, &OldIrql); 01839 } 01840 01841 if ((ExtendedSize != 0) && (RealExpansion == TRUE)) { 01842 MmTotalCommitLimit += ExtendedSize; 01843 } 01844 01845 // 01846 // If commit allotments have been temporarily blocked then unblock now. 01847 // 01848 01849 if (MmPageFileFullExtendPages) { 01850 ASSERT (MmTotalCommittedPages >= MmPageFileFullExtendPages); 01851 MmTotalCommittedPages -= MmPageFileFullExtendPages; 01852 MmPageFileFullExtendPages = 0; 01853 } 01854 01855 PageExpand->InProgress = FALSE; 01856 PageExpand->ActualExpansion = ExtendedSize; 01857 01858 ExReleaseSpinLock (&MmChargeCommitmentLock, OldIrql); 01859 01860 return ExtendedSize; 01861 }

PMMPTE MiFindActualFaultingPte IN PVOID  FaultingAddress  ) 
 

Definition at line 2749 of file pagfault.c.

References MI_IS_PHYSICAL_ADDRESS, MI_PTE_LOOKUP_NEEDED, MiCheckVirtualAddress(), MiGetPdeAddress, MiGetPpeAddress, MiGetPteAddress, MiPteToProto, NULL, and _MMPTE::u.

Referenced by MiWaitForInPageComplete().

02755 : 02756 02757 This routine locates the actual PTE which must be made resident in order 02758 to complete this fault. Note that for certain cases multiple faults 02759 are required to make the final page resident. 02760 02761 Arguments: 02762 02763 FaultingAddress - Supplies the virtual address which caused the 02764 fault. 02765 02766 PointerPte - Supplies the pointer to the PTE which is in prototype 02767 PTE format. 02768 02769 02770 Return Value: 02771 02772 02773 Environment: 02774 02775 Kernel mode, APCs disabled, working set mutex held. 02776 02777 --*/ 02778 02779 { 02780 PMMPTE ProtoPteAddress; 02781 PMMPTE PointerPte; 02782 PMMPTE PointerFaultingPte; 02783 ULONG Protection; 02784 02785 if (MI_IS_PHYSICAL_ADDRESS(FaultingAddress)) { 02786 return NULL; 02787 } 02788 02789 #if defined (_WIN64) 02790 02791 PointerPte = MiGetPpeAddress (FaultingAddress); 02792 02793 if (PointerPte->u.Hard.Valid == 0) { 02794 02795 // 02796 // Page directory page is not valid. 02797 // 02798 02799 return PointerPte; 02800 } 02801 02802 #endif 02803 02804 PointerPte = MiGetPdeAddress (FaultingAddress); 02805 02806 if (PointerPte->u.Hard.Valid == 0) { 02807 02808 // 02809 // Page table page is not valid. 02810 // 02811 02812 return PointerPte; 02813 } 02814 02815 PointerPte = MiGetPteAddress (FaultingAddress); 02816 02817 if (PointerPte->u.Hard.Valid == 1) { 02818 02819 // 02820 // Page is already valid, no need to fault it in. 02821 // 02822 02823 return (PMMPTE)NULL; 02824 } 02825 02826 if (PointerPte->u.Soft.Prototype == 0) { 02827 02828 // 02829 // Page is not a prototype PTE, make this PTE valid. 02830 // 02831 02832 return PointerPte; 02833 } 02834 02835 // 02836 // Check to see if the PTE which maps the prototype PTE is valid. 02837 // 02838 02839 if (PointerPte->u.Soft.PageFileHigh == MI_PTE_LOOKUP_NEEDED) { 02840 02841 // 02842 // Protection is here, PTE must be located in VAD. 02843 // 02844 02845 ProtoPteAddress = MiCheckVirtualAddress (FaultingAddress, 02846 &Protection); 02847 02848 if (ProtoPteAddress == NULL) { 02849 02850 // 02851 // No prototype PTE means another thread has deleted the VAD while 02852 // this thread waited for the inpage to complete. Certainly NULL 02853 // must be returned so a stale PTE is not modified - the instruction 02854 // will then be reexecuted and an access violation delivered. 02855 // 02856 02857 return (PMMPTE)NULL; 02858 } 02859 02860 } else { 02861 02862 // 02863 // Protection is in ProtoPte. 02864 // 02865 02866 ProtoPteAddress = MiPteToProto (PointerPte); 02867 } 02868 02869 PointerFaultingPte = MiFindActualFaultingPte (ProtoPteAddress); 02870 02871 if (PointerFaultingPte == (PMMPTE)NULL) { 02872 return PointerPte; 02873 } else { 02874 return PointerFaultingPte; 02875 } 02876 02877 }

PVOID MiFindContiguousMemory IN PFN_NUMBER  LowestPfn,
IN PFN_NUMBER  HighestPfn,
IN PFN_NUMBER  BoundaryPfn,
IN PFN_NUMBER  SizeInPages,
IN PVOID  CallingAddress
 

Definition at line 4569 of file allocpag.c.

References ActiveAndValid, ASSERT, _PHYSICAL_MEMORY_RUN::BasePage, ExFreePool(), ExInsertPoolTag(), ExLockPool(), ExPageLockHandle, ExUnlockPool(), FALSE, FreePageList, Index, _MMFREE_POOL_ENTRY::List, List, LOCK_PFN2, MI_CHECK_PAGE_ALIGNMENT, MI_CONVERT_PHYSICAL_TO_PFN, MI_GET_PAGE_COLOR_FROM_VA, MI_GET_PAGE_FRAME_FROM_PTE, MI_IS_PHYSICAL_ADDRESS, MI_MAX_FREE_LIST_HEADS, MI_PFN_ELEMENT, MI_WRITE_VALID_PTE, MiChargeCommitmentCantExpand(), MiCheckForContiguousMemory(), MiGetPteAddress, MiGetVirtualAddressMappedByPte, MiInsertContiguousTag, MiProtectedPoolRemoveEntryList(), MiProtectFreeNonPagedPool(), MiReserveSystemPtes(), MiRestoreTransitionPte(), MiUnlinkFreeOrZeroedPage(), MiUnlinkPageFromList(), MiUnProtectFreeNonPagedPool(), MM_BUMP_COUNTER, MM_COLOR_MASK, MM_DBG_COMMIT_CONTIGUOUS_PAGES, MM_DEMAND_ZERO_WRITE_PTE, MM_FREE_POOL_SIGNATURE, MM_TRACK_COMMIT, MmAllocatedNonPagedPool, MmDynamicMemoryMutex, MmLockPagableSectionByHandle(), MmNonPagedPoolFreeListHead, MmNumberOfFreeNonPagedPool, MmPhysicalMemoryBlock, MmProtectFreedNonPagedPool, MmResidentAvailablePages, MmUnlockPagableImageSection(), NonPagedPool, NonPagedPoolDescriptor, NonPagedPoolExpansion, NULL, _PHYSICAL_MEMORY_DESCRIPTOR::NumberOfRuns, _MMPFN::OriginalPte, PAGE_ALIGN, PAGE_SHIFT, PAGE_SIZE, _PHYSICAL_MEMORY_RUN::PageCount, PAGED_CODE, _MMPFN::PteAddress, _MMPFN::PteFrame, _PHYSICAL_MEMORY_DESCRIPTOR::Run, _MMFREE_POOL_ENTRY::Signature, _MMFREE_POOL_ENTRY::Size, StandbyPageList, _POOL_DESCRIPTOR::TotalBigPages, TRUE, _MMPTE::u, _MMPFN::u1, _MMPFN::u2, _MMPFN::u3, UNLOCK_PFN2, ValidKernelPte, and ZeroedPageList.

Referenced by MiAllocateContiguousMemory().

04579 : 04580 04581 This function searches nonpaged pool and the free, zeroed, 04582 and standby lists for contiguous pages that satisfy the 04583 request. 04584 04585 Arguments: 04586 04587 LowestPfn - Supplies the lowest acceptable physical page number. 04588 04589 HighestPfn - Supplies the highest acceptable physical page number. 04590 04591 BoundaryPfn - Supplies the page frame number multiple the allocation must 04592 not cross. 0 indicates it can cross any boundary. 04593 04594 SizeInPages - Supplies the number of pages to allocate. 04595 04596 CallingAddress - Supplies the calling address of the allocator. 04597 04598 Return Value: 04599 04600 NULL - a contiguous range could not be found to satisfy the request. 04601 04602 NON-NULL - Returns a pointer (virtual address in the nonpaged portion 04603 of the system) to the allocated physically contiguous 04604 memory. 04605 04606 Environment: 04607 04608 Kernel mode, IRQL of APC_LEVEL or below. 04609 04610 --*/ 04611 { 04612 PMMPTE PointerPte; 04613 PMMPFN Pfn1; 04614 PVOID BaseAddress; 04615 PVOID BaseAddress2; 04616 KIRQL OldIrql; 04617 KIRQL OldIrql2; 04618 PMMFREE_POOL_ENTRY FreePageInfo; 04619 PLIST_ENTRY Entry; 04620 ULONG start; 04621 ULONG Index; 04622 PFN_NUMBER count; 04623 PFN_NUMBER Page; 04624 PFN_NUMBER LastPage; 04625 PFN_NUMBER found; 04626 PFN_NUMBER BoundaryMask; 04627 MMPTE TempPte; 04628 ULONG PageColor; 04629 ULONG AllocationPosition; 04630 PVOID Va; 04631 LOGICAL AddressIsPhysical; 04632 PFN_NUMBER SpanInPages; 04633 PFN_NUMBER SpanInPages2; 04634 04635 PAGED_CODE (); 04636 04637 BaseAddress = NULL; 04638 04639 BoundaryMask = ~(BoundaryPfn - 1); 04640 04641 // 04642 // A suitable pool page was not allocated via the pool allocator. 04643 // Grab the pool lock and manually search for a page which meets 04644 // the requirements. 04645 // 04646 04647 MmLockPagableSectionByHandle (ExPageLockHandle); 04648 04649 ExAcquireFastMutex (&MmDynamicMemoryMutex); 04650 04651 OldIrql = ExLockPool (NonPagedPool); 04652 04653 // 04654 // Trace through the page allocator's pool headers for a page which 04655 // meets the requirements. 04656 // 04657 04658 // 04659 // NonPaged pool is linked together through the pages themselves. 04660 // 04661 04662 Index = (ULONG)(SizeInPages - 1); 04663 04664 if (Index >= MI_MAX_FREE_LIST_HEADS) { 04665 Index = MI_MAX_FREE_LIST_HEADS - 1; 04666 } 04667 04668 while (Index < MI_MAX_FREE_LIST_HEADS) { 04669 04670 Entry = MmNonPagedPoolFreeListHead[Index].Flink; 04671 04672 while (Entry != &MmNonPagedPoolFreeListHead[Index]) { 04673 04674 if (MmProtectFreedNonPagedPool == TRUE) { 04675 MiUnProtectFreeNonPagedPool ((PVOID)Entry, 0); 04676 } 04677 04678 // 04679 // The list is not empty, see if this one meets the physical 04680 // requirements. 04681 // 04682 04683 FreePageInfo = CONTAINING_RECORD(Entry, 04684 MMFREE_POOL_ENTRY, 04685 List); 04686 04687 ASSERT (FreePageInfo->Signature == MM_FREE_POOL_SIGNATURE); 04688 if (FreePageInfo->Size >= SizeInPages) { 04689 04690 // 04691 // This entry has sufficient space, check to see if the 04692 // pages meet the physical requirements. 04693 // 04694 04695 Va = MiCheckForContiguousMemory (PAGE_ALIGN(Entry), 04696 FreePageInfo->Size, 04697 SizeInPages, 04698 LowestPfn, 04699 HighestPfn, 04700 BoundaryPfn); 04701 04702 if (Va != NULL) { 04703 04704 // 04705 // These pages meet the requirements. The returned 04706 // address may butt up on the end, the front or be 04707 // somewhere in the middle. Split the Entry based 04708 // on which case it is. 04709 // 04710 04711 Entry = PAGE_ALIGN(Entry); 04712 if (MmProtectFreedNonPagedPool == FALSE) { 04713 RemoveEntryList (&FreePageInfo->List); 04714 } 04715 else { 04716 MiProtectedPoolRemoveEntryList (&FreePageInfo->List); 04717 } 04718 04719 // 04720 // Adjust the number of free pages remaining in the pool. 04721 // The TotalBigPages calculation appears incorrect for the 04722 // case where we're splitting a block, but it's done this 04723 // way because ExFreePool corrects it when we free the 04724 // fragment block below. Likewise for 04725 // MmAllocatedNonPagedPool and MmNumberOfFreeNonPagedPool 04726 // which is corrected by MiFreePoolPages for the fragment. 04727 // 04728 04729 NonPagedPoolDescriptor.TotalBigPages += (ULONG)FreePageInfo->Size; 04730 MmAllocatedNonPagedPool += FreePageInfo->Size; 04731 MmNumberOfFreeNonPagedPool -= FreePageInfo->Size; 04732 04733 ASSERT ((LONG)MmNumberOfFreeNonPagedPool >= 0); 04734 04735 if (Va == Entry) { 04736 04737 // 04738 // Butted against the front. 04739 // 04740 04741 AllocationPosition = 0; 04742 } 04743 else if (((PCHAR)Va + (SizeInPages << PAGE_SHIFT)) == ((PCHAR)Entry + (FreePageInfo->Size << PAGE_SHIFT))) { 04744 04745 // 04746 // Butted against the end. 04747 // 04748 04749 AllocationPosition = 2; 04750 } 04751 else { 04752 04753 // 04754 // Somewhere in the middle. 04755 // 04756 04757 AllocationPosition = 1; 04758 } 04759 04760 // 04761 // Pages are being removed from the front of 04762 // the list entry and the whole list entry 04763 // will be removed and then the remainder inserted. 04764 // 04765 04766 // 04767 // Mark start and end for the block at the top of the 04768 // list. 04769 // 04770 04771 if (MI_IS_PHYSICAL_ADDRESS(Va)) { 04772 04773 // 04774 // On certain architectures, virtual addresses 04775 // may be physical and hence have no corresponding PTE. 04776 // 04777 04778 AddressIsPhysical = TRUE; 04779 Pfn1 = MI_PFN_ELEMENT (MI_CONVERT_PHYSICAL_TO_PFN (Va)); 04780 } else { 04781 AddressIsPhysical = FALSE; 04782 PointerPte = MiGetPteAddress(Va); 04783 ASSERT (PointerPte->u.Hard.Valid == 1); 04784 Pfn1 = MI_PFN_ELEMENT (PointerPte->u.Hard.PageFrameNumber); 04785 } 04786 04787 ASSERT (Pfn1->u3.e1.VerifierAllocation == 0); 04788 ASSERT (Pfn1->u3.e1.LargeSessionAllocation == 0); 04789 ASSERT (Pfn1->u3.e1.StartOfAllocation == 0); 04790 Pfn1->u3.e1.StartOfAllocation = 1; 04791 04792 // 04793 // Calculate the ending PFN address, note that since 04794 // these pages are contiguous, just add to the PFN. 04795 // 04796 04797 Pfn1 += SizeInPages - 1; 04798 ASSERT (Pfn1->u3.e1.VerifierAllocation == 0); 04799 ASSERT (Pfn1->u3.e1.LargeSessionAllocation == 0); 04800 ASSERT (Pfn1->u3.e1.EndOfAllocation == 0); 04801 Pfn1->u3.e1.EndOfAllocation = 1; 04802 04803 if (SizeInPages == FreePageInfo->Size) { 04804 04805 // 04806 // Unlock the pool and return. 04807 // 04808 BaseAddress = (PVOID)Va; 04809 goto Done; 04810 } 04811 04812 BaseAddress = NULL; 04813 04814 if (AllocationPosition != 2) { 04815 04816 // 04817 // The end piece needs to be freed as the removal 04818 // came from the front or the middle. 04819 // 04820 04821 BaseAddress = (PVOID)((PCHAR)Va + (SizeInPages << PAGE_SHIFT)); 04822 SpanInPages = FreePageInfo->Size - SizeInPages - 04823 (((ULONG_PTR)Va - (ULONG_PTR)Entry) >> PAGE_SHIFT); 04824 04825 // 04826 // Mark start and end of the allocation in the PFN database. 04827 // 04828 04829 if (AddressIsPhysical == TRUE) { 04830 04831 // 04832 // On certain architectures, virtual addresses 04833 // may be physical and hence have no corresponding PTE. 04834 // 04835 04836 Pfn1 = MI_PFN_ELEMENT (MI_CONVERT_PHYSICAL_TO_PFN (BaseAddress)); 04837 } else { 04838 PointerPte = MiGetPteAddress(BaseAddress); 04839 ASSERT (PointerPte->u.Hard.Valid == 1); 04840 Pfn1 = MI_PFN_ELEMENT (PointerPte->u.Hard.PageFrameNumber); 04841 } 04842 04843 ASSERT (Pfn1->u3.e1.VerifierAllocation == 0); 04844 ASSERT (Pfn1->u3.e1.LargeSessionAllocation == 0); 04845 ASSERT (Pfn1->u3.e1.StartOfAllocation == 0); 04846 Pfn1->u3.e1.StartOfAllocation = 1; 04847 04848 // 04849 // Calculate the ending PTE's address, can't depend on 04850 // these pages being physically contiguous. 04851 // 04852 04853 if (AddressIsPhysical == TRUE) { 04854 Pfn1 += (SpanInPages - 1); 04855 } else { 04856 PointerPte += (SpanInPages - 1); 04857 ASSERT (PointerPte->u.Hard.Valid == 1); 04858 Pfn1 = MI_PFN_ELEMENT (PointerPte->u.Hard.PageFrameNumber); 04859 } 04860 ASSERT (Pfn1->u3.e1.EndOfAllocation == 0); 04861 Pfn1->u3.e1.EndOfAllocation = 1; 04862 04863 ASSERT (((ULONG_PTR)BaseAddress & (PAGE_SIZE -1)) == 0); 04864 04865 SpanInPages2 = SpanInPages; 04866 } 04867 04868 BaseAddress2 = BaseAddress; 04869 BaseAddress = NULL; 04870 04871 if (AllocationPosition != 0) { 04872 04873 // 04874 // The front piece needs to be freed as the removal 04875 // came from the middle or the end. 04876 // 04877 04878 BaseAddress = (PVOID)Entry; 04879 04880 SpanInPages = ((ULONG_PTR)Va - (ULONG_PTR)Entry) >> PAGE_SHIFT; 04881 04882 // 04883 // Mark start and end of the allocation in the PFN database. 04884 // 04885 04886 if (AddressIsPhysical == TRUE) { 04887 04888 // 04889 // On certain architectures, virtual addresses 04890 // may be physical and hence have no corresponding PTE. 04891 // 04892 04893 Pfn1 = MI_PFN_ELEMENT (MI_CONVERT_PHYSICAL_TO_PFN (BaseAddress)); 04894 } else { 04895 PointerPte = MiGetPteAddress(BaseAddress); 04896 ASSERT (PointerPte->u.Hard.Valid == 1); 04897 Pfn1 = MI_PFN_ELEMENT (PointerPte->u.Hard.PageFrameNumber); 04898 } 04899 04900 ASSERT (Pfn1->u3.e1.VerifierAllocation == 0); 04901 ASSERT (Pfn1->u3.e1.LargeSessionAllocation == 0); 04902 ASSERT (Pfn1->u3.e1.StartOfAllocation == 0); 04903 Pfn1->u3.e1.StartOfAllocation = 1; 04904 04905 // 04906 // Calculate the ending PTE's address, can't depend on 04907 // these pages being physically contiguous. 04908 // 04909 04910 if (AddressIsPhysical == TRUE) { 04911 Pfn1 += (SpanInPages - 1); 04912 } else { 04913 PointerPte += (SpanInPages - 1); 04914 ASSERT (PointerPte->u.Hard.Valid == 1); 04915 Pfn1 = MI_PFN_ELEMENT (PointerPte->u.Hard.PageFrameNumber); 04916 } 04917 ASSERT (Pfn1->u3.e1.EndOfAllocation == 0); 04918 Pfn1->u3.e1.EndOfAllocation = 1; 04919 04920 ASSERT (((ULONG_PTR)BaseAddress & (PAGE_SIZE -1)) == 0); 04921 } 04922 04923 // 04924 // Unlock the pool. 04925 // 04926 04927 ExUnlockPool (NonPagedPool, OldIrql); 04928 04929 ExReleaseFastMutex (&MmDynamicMemoryMutex); 04930 04931 // 04932 // Free the split entry at BaseAddress back into the pool. 04933 // Note that we have overcharged the pool - the entire free 04934 // chunk has been billed. Here we return the piece we 04935 // didn't use and correct the momentary overbilling. 04936 // 04937 // The start and end allocation bits of this split entry 04938 // which we just set up enable ExFreePool and his callees 04939 // to correctly adjust the billing. 04940 // 04941 04942 if (BaseAddress) { 04943 ExInsertPoolTag ('tnoC', 04944 BaseAddress, 04945 SpanInPages << PAGE_SHIFT, 04946 NonPagedPool); 04947 ExFreePool (BaseAddress); 04948 } 04949 if (BaseAddress2) { 04950 ExInsertPoolTag ('tnoC', 04951 BaseAddress2, 04952 SpanInPages2 << PAGE_SHIFT, 04953 NonPagedPool); 04954 ExFreePool (BaseAddress2); 04955 } 04956 BaseAddress = Va; 04957 goto Done1; 04958 } 04959 } 04960 Entry = FreePageInfo->List.Flink; 04961 if (MmProtectFreedNonPagedPool == TRUE) { 04962 MiProtectFreeNonPagedPool ((PVOID)FreePageInfo, 04963 (ULONG)FreePageInfo->Size); 04964 } 04965 } 04966 Index += 1; 04967 } 04968 04969 // 04970 // No entry was found in free nonpaged pool that meets the requirements. 04971 // Search the PFN database for pages that meet the requirements. 04972 // 04973 04974 start = 0; 04975 do { 04976 04977 count = MmPhysicalMemoryBlock->Run[start].PageCount; 04978 Page = MmPhysicalMemoryBlock->Run[start].BasePage; 04979 04980 // 04981 // Close the gaps, then examine the range for a fit. 04982 // 04983 04984 LastPage = Page + count; 04985 04986 if (LastPage - 1 > HighestPfn) { 04987 LastPage = HighestPfn + 1; 04988 } 04989 04990 if (Page < LowestPfn) { 04991 Page = LowestPfn; 04992 } 04993 04994 if ((count != 0) && (Page + SizeInPages <= LastPage)) { 04995 04996 // 04997 // A fit may be possible in this run, check whether the pages 04998 // are on the right list. 04999 // 05000 05001 found = 0; 05002 05003 Pfn1 = MI_PFN_ELEMENT (Page); 05004 LOCK_PFN2 (OldIrql2); 05005 do { 05006 05007 if ((Pfn1->u3.e1.PageLocation == ZeroedPageList) || 05008 (Pfn1->u3.e1.PageLocation == FreePageList) || 05009 (Pfn1->u3.e1.PageLocation == StandbyPageList)) { 05010 05011 if ((Pfn1->u1.Flink != 0) && 05012 (Pfn1->u2.Blink != 0) && 05013 (Pfn1->u3.e2.ReferenceCount == 0)) { 05014 05015 // 05016 // Before starting a new run, ensure that it 05017 // can satisfy the boundary requirements (if any). 05018 // 05019 05020 if ((found == 0) && (BoundaryPfn != 0)) { 05021 if (((Page ^ (Page + SizeInPages - 1)) & BoundaryMask) != 0) { 05022 // 05023 // This run's physical address does not meet the 05024 // requirements. 05025 // 05026 05027 goto NextPage; 05028 } 05029 } 05030 05031 found += 1; 05032 if (found == SizeInPages) { 05033 05034 // 05035 // A match has been found, remove these 05036 // pages, add them to the free pool and 05037 // return. 05038 // 05039 05040 Page = 1 + Page - found; 05041 05042 // 05043 // Try to find system PTES to expand the pool into. 05044 // 05045 05046 PointerPte = MiReserveSystemPtes ((ULONG)SizeInPages, 05047 NonPagedPoolExpansion, 05048 0, 05049 0, 05050 FALSE); 05051 05052 if (PointerPte == NULL) { 05053 UNLOCK_PFN2 (OldIrql2); 05054 goto Done; 05055 } 05056 05057 MmResidentAvailablePages -= SizeInPages; 05058 MM_BUMP_COUNTER(3, SizeInPages); 05059 MiChargeCommitmentCantExpand (SizeInPages, TRUE); 05060 MM_TRACK_COMMIT (MM_DBG_COMMIT_CONTIGUOUS_PAGES, SizeInPages); 05061 BaseAddress = MiGetVirtualAddressMappedByPte (PointerPte); 05062 PageColor = MI_GET_PAGE_COLOR_FROM_VA(BaseAddress); 05063 TempPte = ValidKernelPte; 05064 MmAllocatedNonPagedPool += SizeInPages; 05065 NonPagedPoolDescriptor.TotalBigPages += (ULONG)SizeInPages; 05066 Pfn1 = MI_PFN_ELEMENT (Page - 1); 05067 05068 do { 05069 Pfn1 += 1; 05070 if (Pfn1->u3.e1.PageLocation == StandbyPageList) { 05071 MiUnlinkPageFromList (Pfn1); 05072 MiRestoreTransitionPte (Page); 05073 } else { 05074 MiUnlinkFreeOrZeroedPage (Page); 05075 } 05076 05077 MI_CHECK_PAGE_ALIGNMENT(Page, 05078 PageColor & MM_COLOR_MASK); 05079 Pfn1->u3.e1.PageColor = PageColor & MM_COLOR_MASK; 05080 PageColor += 1; 05081 TempPte.u.Hard.PageFrameNumber = Page; 05082 MI_WRITE_VALID_PTE (PointerPte, TempPte); 05083 05084 Pfn1->u3.e2.ReferenceCount = 1; 05085 Pfn1->u2.ShareCount = 1; 05086 Pfn1->PteAddress = PointerPte; 05087 Pfn1->OriginalPte.u.Long = MM_DEMAND_ZERO_WRITE_PTE; 05088 Pfn1->PteFrame = MI_GET_PAGE_FRAME_FROM_PTE (MiGetPteAddress(PointerPte)); 05089 Pfn1->u3.e1.PageLocation = ActiveAndValid; 05090 Pfn1->u3.e1.VerifierAllocation = 0; 05091 Pfn1->u3.e1.LargeSessionAllocation = 0; 05092 05093 if (found == SizeInPages) { 05094 Pfn1->u3.e1.StartOfAllocation = 1; 05095 } 05096 PointerPte += 1; 05097 Page += 1; 05098 found -= 1; 05099 } while (found); 05100 05101 Pfn1->u3.e1.EndOfAllocation = 1; 05102 UNLOCK_PFN2 (OldIrql2); 05103 goto Done; 05104 } 05105 } else { 05106 found = 0; 05107 } 05108 } else { 05109 found = 0; 05110 } 05111 NextPage: 05112 Page += 1; 05113 Pfn1 += 1; 05114 } while (Page < LastPage); 05115 UNLOCK_PFN2 (OldIrql2); 05116 } 05117 start += 1; 05118 } while (start != MmPhysicalMemoryBlock->NumberOfRuns); 05119 05120 Done: 05121 05122 ExUnlockPool (NonPagedPool, OldIrql); 05123 05124 ExReleaseFastMutex (&MmDynamicMemoryMutex); 05125 05126 Done1: 05127 05128 MmUnlockPagableImageSection (ExPageLockHandle); 05129 05130 if (BaseAddress) { 05131 05132 MiInsertContiguousTag (BaseAddress, 05133 SizeInPages << PAGE_SHIFT, 05134 CallingAddress); 05135 05136 ExInsertPoolTag ('tnoC', 05137 BaseAddress, 05138 SizeInPages << PAGE_SHIFT, 05139 NonPagedPool); 05140 } 05141 05142 return BaseAddress; 05143 }

PVOID MiFindEmptyAddressRange IN SIZE_T  SizeOfRange,
IN ULONG_PTR  Alignment,
IN ULONG  QuickCheck
 

Definition at line 431 of file vadtree.c.

References _MMVAD::EndingVpn, MI_ROUND_TO_SIZE, MI_VPN_TO_VA, MI_VPN_TO_VA_ENDING, MiFindEmptyAddressRangeInTree(), MiGetNextVad, NULL, PsGetCurrentProcess, _MMVAD::StartingVpn, _EPROCESS::VadFreeHint, and _EPROCESS::VadRoot.

Referenced by MiMapLockedPagesInUserSpace(), MiMapViewOfDataSection(), MiMapViewOfImageSection(), MiMapViewOfPhysicalSection(), and NtAllocateVirtualMemory().

00439 : 00440 00441 The function examines the virtual address descriptors to locate 00442 an unused range of the specified size and returns the starting 00443 address of the range. 00444 00445 Arguments: 00446 00447 SizeOfRange - Supplies the size in bytes of the range to locate. 00448 00449 Alignment - Supplies the alignment for the address. Must be 00450 a power of 2 and greater than the page_size. 00451 00452 QuickCheck - Supplies a zero if a quick check for free memory 00453 after the VadFreeHint exists, non-zero if checking 00454 should start at the lowest address. 00455 00456 Return Value: 00457 00458 Returns the starting address of a suitable range. 00459 00460 --*/ 00461 00462 { 00463 PMMVAD NextVad; 00464 PMMVAD FreeHint; 00465 PEPROCESS CurrentProcess; 00466 PVOID StartingVa; 00467 PVOID EndingVa; 00468 00469 CurrentProcess = PsGetCurrentProcess(); 00470 FreeHint = CurrentProcess->VadFreeHint; 00471 00472 if ((QuickCheck == 0) && (FreeHint != NULL)) { 00473 00474 EndingVa = MI_VPN_TO_VA_ENDING (FreeHint->EndingVpn); 00475 NextVad = MiGetNextVad (FreeHint); 00476 if (NextVad == NULL) { 00477 00478 if (SizeOfRange < 00479 (((ULONG_PTR)MM_HIGHEST_USER_ADDRESS + 1) - 00480 MI_ROUND_TO_SIZE((ULONG_PTR)EndingVa, Alignment))) { 00481 return (PMMADDRESS_NODE)MI_ROUND_TO_SIZE((ULONG_PTR)EndingVa, 00482 Alignment); 00483 } 00484 } else { 00485 StartingVa = MI_VPN_TO_VA (NextVad->StartingVpn); 00486 00487 if (SizeOfRange < 00488 ((ULONG_PTR)StartingVa - 00489 MI_ROUND_TO_SIZE((ULONG_PTR)EndingVa, Alignment))) { 00490 00491 // 00492 // Check to ensure that the ending address aligned upwards 00493 // is not greater than the starting address. 00494 // 00495 00496 if ((ULONG_PTR)StartingVa > 00497 MI_ROUND_TO_SIZE((ULONG_PTR)EndingVa,Alignment)) { 00498 return (PMMADDRESS_NODE)MI_ROUND_TO_SIZE((ULONG_PTR)EndingVa, 00499 Alignment); 00500 } 00501 } 00502 } 00503 } 00504 00505 return (PMMVAD)MiFindEmptyAddressRangeInTree ( 00506 SizeOfRange, 00507 Alignment, 00508 (PMMADDRESS_NODE)(CurrentProcess->VadRoot), 00509 (PMMADDRESS_NODE *)&CurrentProcess->VadFreeHint); 00510 00511 }

PVOID MiFindEmptyAddressRangeDownTree IN SIZE_T  SizeOfRange,
IN PVOID  HighestAddressToEndAt,
IN ULONG_PTR  Alignment,
IN PMMADDRESS_NODE  Root
 

Definition at line 1252 of file addrsup.c.

References ASSERT, _MMADDRESS_NODE::EndingVpn, ExRaiseStatus(), MI_ALIGN_TO_SIZE, MI_ROUND_TO_SIZE, MI_VA_TO_VPN, MI_VPN_TO_VA, MI_VPN_TO_VA_ENDING, MiGetPreviousNode(), MM_HIGHEST_VAD_ADDRESS, NULL, PAGE_SHIFT, PAGE_SIZE, _MMADDRESS_NODE::RightChild, and _MMADDRESS_NODE::StartingVpn.

Referenced by MiFindEmptySectionBaseDown().

01261 : 01262 01263 The function examines the virtual address descriptors to locate 01264 an unused range of the specified size and returns the starting 01265 address of the range. The function examines from the high 01266 addresses down and ensures that starting address is less than 01267 the specified address. 01268 01269 Arguments: 01270 01271 SizeOfRange - Supplies the size in bytes of the range to locate. 01272 01273 HighestAddressToEndAt - Supplies the virtual address that limits 01274 the value of the ending address. The ending 01275 address of the located range must be less 01276 than this address. 01277 01278 Alignment - Supplies the alignment for the address. Must be 01279 a power of 2 and greater than the page_size. 01280 01281 Root - Supplies the root of the tree to search through. 01282 01283 Return Value: 01284 01285 Returns the starting address of a suitable range. 01286 01287 --*/ 01288 01289 { 01290 PMMADDRESS_NODE Node; 01291 PMMADDRESS_NODE PreviousNode; 01292 ULONG_PTR AlignedEndingVa; 01293 PVOID OptimalStart; 01294 ULONG_PTR OptimalStartVpn; 01295 ULONG_PTR HighestVpn; 01296 ULONG_PTR AlignmentVpn; 01297 01298 SizeOfRange = MI_ROUND_TO_SIZE (SizeOfRange, PAGE_SIZE); 01299 01300 ASSERT (HighestAddressToEndAt != NULL); 01301 ASSERT (HighestAddressToEndAt <= (PVOID)((ULONG_PTR)MM_HIGHEST_VAD_ADDRESS + 1)); 01302 01303 HighestVpn = MI_VA_TO_VPN (HighestAddressToEndAt); 01304 01305 // 01306 // Locate the Node with the highest starting address. 01307 // 01308 01309 OptimalStart = (PVOID)(MI_ALIGN_TO_SIZE( 01310 (((ULONG_PTR)HighestAddressToEndAt + 1) - SizeOfRange), 01311 Alignment)); 01312 Node = Root; 01313 01314 if (Node == (PMMADDRESS_NODE)NULL) { 01315 01316 // 01317 // The tree is empty, any range is okay. 01318 // 01319 01320 return (PMMADDRESS_NODE)(OptimalStart); 01321 } 01322 01323 // 01324 // See if an empty slot exists to hold this range, locate the largest 01325 // element in the tree. 01326 // 01327 01328 while (Node->RightChild != (PMMADDRESS_NODE)NULL) { 01329 Node = Node->RightChild; 01330 } 01331 01332 // 01333 // Check to see if a range exists between the highest address VAD 01334 // and the highest address to end at. 01335 // 01336 01337 AlignedEndingVa = (ULONG_PTR)MI_ROUND_TO_SIZE ((ULONG_PTR)MI_VPN_TO_VA_ENDING (Node->EndingVpn), 01338 Alignment); 01339 01340 if (AlignedEndingVa < (ULONG_PTR)HighestAddressToEndAt) { 01341 01342 if ( SizeOfRange < ((ULONG_PTR)HighestAddressToEndAt - AlignedEndingVa)) { 01343 01344 return (PMMADDRESS_NODE)(MI_ALIGN_TO_SIZE( 01345 ((ULONG_PTR)HighestAddressToEndAt - SizeOfRange), 01346 Alignment)); 01347 } 01348 } 01349 01350 // 01351 // Walk the tree backwards looking for a fit. 01352 // 01353 01354 OptimalStartVpn = MI_VA_TO_VPN (OptimalStart); 01355 AlignmentVpn = MI_VA_TO_VPN (Alignment); 01356 01357 for (;;) { 01358 01359 PreviousNode = MiGetPreviousNode (Node); 01360 01361 if (PreviousNode != (PMMADDRESS_NODE)NULL) { 01362 01363 // 01364 // Is the ending Va below the top of the address to end at. 01365 // 01366 01367 if (PreviousNode->EndingVpn < OptimalStartVpn) { 01368 if ((SizeOfRange >> PAGE_SHIFT) <= 01369 ((ULONG_PTR)Node->StartingVpn - 01370 (ULONG_PTR)MI_ROUND_TO_SIZE(1 + PreviousNode->EndingVpn, 01371 AlignmentVpn))) { 01372 01373 // 01374 // See if the optimal start will fit between these 01375 // two VADs. 01376 // 01377 01378 if ((OptimalStartVpn > PreviousNode->EndingVpn) && 01379 (HighestVpn < Node->StartingVpn)) { 01380 return (PMMADDRESS_NODE)(OptimalStart); 01381 } 01382 01383 // 01384 // Check to ensure that the ending address aligned upwards 01385 // is not greater than the starting address. 01386 // 01387 01388 if ((ULONG_PTR)Node->StartingVpn > 01389 (ULONG_PTR)MI_ROUND_TO_SIZE(1 + PreviousNode->EndingVpn, 01390 AlignmentVpn)) { 01391 01392 return (PMMADDRESS_NODE)MI_ALIGN_TO_SIZE( 01393 (ULONG_PTR)MI_VPN_TO_VA (Node->StartingVpn) - SizeOfRange, 01394 Alignment); 01395 } 01396 } 01397 } 01398 } else { 01399 01400 // 01401 // No more descriptors, check to see if this fits into the remainder 01402 // of the address space. 01403 // 01404 01405 if (Node->StartingVpn > MI_VA_TO_VPN (MM_LOWEST_USER_ADDRESS)) { 01406 if ((SizeOfRange >> PAGE_SHIFT) <= 01407 ((ULONG_PTR)Node->StartingVpn - MI_VA_TO_VPN (MM_LOWEST_USER_ADDRESS))) { 01408 01409 // 01410 // See if the optimal start will fit between these 01411 // two VADs. 01412 // 01413 01414 if (HighestVpn < Node->StartingVpn) { 01415 return (PMMADDRESS_NODE)(OptimalStart); 01416 } 01417 01418 return (PMMADDRESS_NODE)MI_ALIGN_TO_SIZE( 01419 (ULONG_PTR)MI_VPN_TO_VA (Node->StartingVpn) - SizeOfRange, 01420 Alignment); 01421 } 01422 } else { 01423 ExRaiseStatus (STATUS_NO_MEMORY); 01424 } 01425 } 01426 Node = PreviousNode; 01427 } 01428 } #if DBG

PVOID MiFindEmptyAddressRangeInTree IN SIZE_T  SizeOfRange,
IN ULONG_PTR  Alignment,
IN PMMADDRESS_NODE  Root,
OUT PMMADDRESS_NODE PreviousVad
 

Definition at line 1127 of file addrsup.c.

References ASSERT, _MMADDRESS_NODE::EndingVpn, ExRaiseStatus(), _MMADDRESS_NODE::LeftChild, MI_ROUND_TO_SIZE, MI_VA_TO_VPN, MI_VPN_TO_VA, MI_VPN_TO_VA_ENDING, MiGetNextNode(), MM_HIGHEST_VAD_ADDRESS, NULL, PAGE_SHIFT, PAGE_SIZE, _MMADDRESS_NODE::StartingVpn, and X64K.

Referenced by MiFindEmptyAddressRange().

01136 : 01137 01138 The function examines the virtual address descriptors to locate 01139 an unused range of the specified size and returns the starting 01140 address of the range. 01141 01142 Arguments: 01143 01144 SizeOfRange - Supplies the size in bytes of the range to locate. 01145 01146 Alignment - Supplies the alignment for the address. Must be 01147 a power of 2 and greater than the page_size. 01148 01149 Root - Supplies the root of the tree to search through. 01150 01151 PreviousVad - Supplies the Vad which is before this the found 01152 address range. 01153 01154 Return Value: 01155 01156 Returns the starting address of a suitable range. 01157 01158 --*/ 01159 01160 { 01161 PMMADDRESS_NODE Node; 01162 PMMADDRESS_NODE NextNode; 01163 ULONG_PTR AlignmentVpn; 01164 01165 AlignmentVpn = Alignment >> PAGE_SHIFT; 01166 01167 // 01168 // Locate the Node with the lowest starting address. 01169 // 01170 01171 SizeOfRange = (SizeOfRange + (PAGE_SIZE - 1)) >> PAGE_SHIFT; 01172 ASSERT (SizeOfRange != 0); 01173 01174 Node = Root; 01175 01176 if (Node == (PMMADDRESS_NODE)NULL) { 01177 return MM_LOWEST_USER_ADDRESS; 01178 } 01179 while (Node->LeftChild != (PMMADDRESS_NODE)NULL) { 01180 Node = Node->LeftChild; 01181 } 01182 01183 // 01184 // Check to see if a range exists between the lowest address VAD 01185 // and lowest user address. 01186 // 01187 01188 if (Node->StartingVpn > MI_VA_TO_VPN (MM_LOWEST_USER_ADDRESS)) { 01189 if ( SizeOfRange < 01190 (Node->StartingVpn - MI_VA_TO_VPN (MM_LOWEST_USER_ADDRESS))) { 01191 01192 *PreviousVad = NULL; 01193 return MM_LOWEST_USER_ADDRESS; 01194 } 01195 } 01196 01197 for (;;) { 01198 01199 NextNode = MiGetNextNode (Node); 01200 01201 if (NextNode != (PMMADDRESS_NODE)NULL) { 01202 01203 if (SizeOfRange <= 01204 ((ULONG_PTR)NextNode->StartingVpn - 01205 MI_ROUND_TO_SIZE(1 + Node->EndingVpn, 01206 AlignmentVpn))) { 01207 01208 // 01209 // Check to ensure that the ending address aligned upwards 01210 // is not greater than the starting address. 01211 // 01212 01213 if ((ULONG_PTR)NextNode->StartingVpn > 01214 MI_ROUND_TO_SIZE(1 + Node->EndingVpn, 01215 AlignmentVpn)) { 01216 01217 *PreviousVad = Node; 01218 return (PMMADDRESS_NODE)MI_ROUND_TO_SIZE( 01219 (ULONG_PTR)MI_VPN_TO_VA_ENDING(Node->EndingVpn), 01220 Alignment); 01221 } 01222 } 01223 01224 } else { 01225 01226 // 01227 // No more descriptors, check to see if this fits into the remainder 01228 // of the address space. 01229 // 01230 01231 if ((((ULONG_PTR)Node->EndingVpn + MI_VA_TO_VPN(X64K)) < 01232 MI_VA_TO_VPN (MM_HIGHEST_VAD_ADDRESS)) 01233 && 01234 (SizeOfRange <= 01235 ((ULONG_PTR)MM_HIGHEST_VAD_ADDRESS - 01236 (ULONG_PTR)MI_ROUND_TO_SIZE( 01237 (ULONG_PTR)MI_VPN_TO_VA(Node->EndingVpn), Alignment)))) { 01238 01239 *PreviousVad = Node; 01240 return (PMMADDRESS_NODE)MI_ROUND_TO_SIZE( 01241 (ULONG_PTR)MI_VPN_TO_VA_ENDING(Node->EndingVpn), 01242 Alignment); 01243 } else { 01244 ExRaiseStatus (STATUS_NO_MEMORY); 01245 } 01246 } 01247 Node = NextNode; 01248 } 01249 }

PVOID MiFindEmptySectionBaseDown IN ULONG  SizeOfRange,
IN PVOID  HighestAddressToEndAt
 

Definition at line 154 of file sectsup.c.

References MiFindEmptyAddressRangeDownTree(), MmSectionBasedRoot, and X64K.

Referenced by MmCreateSection().

00161 : 00162 00163 The function examines the virtual address descriptors to locate 00164 an unused range of the specified size and returns the starting 00165 address of the range. This routine looks from the top down. 00166 00167 Arguments: 00168 00169 SectionBasedRoot - Supplies the root of the available address tree. 00170 00171 SizeOfRange - Supplies the size in bytes of the range to locate. 00172 00173 HighestAddressToEndAt - Supplies the virtual address to begin looking 00174 at. 00175 00176 Return Value: 00177 00178 Returns the starting address of a suitable range. 00179 00180 --*/ 00181 00182 { 00183 return MiFindEmptyAddressRangeDownTree (SizeOfRange, 00184 HighestAddressToEndAt, 00185 X64K, 00186 MmSectionBasedRoot); 00187 }

VOID MiFindInitializationCode OUT PVOID *  StartVa,
OUT PVOID *  EndVa
 

Definition at line 2474 of file mminit.c.

References DbgPrint, ExAcquireResourceExclusive, ExReleaseResource, KeEnterCriticalRegion, KeLeaveCriticalRegion, MiFindInitializationCode(), MiFreeInitializationCode(), NULL, PAGE_ALIGN, PAGE_SIZE, PsLoadedModuleList, PsLoadedModuleResource, ROUND_TO_PAGES, RtlImageNtHeader(), and TRUE.

Referenced by MiFindInitializationCode(), and MmZeroPageThread().

02481 : 02482 02483 This function locates the start and end of the kernel initialization 02484 code. This code resides in the "init" section of the kernel image. 02485 02486 Arguments: 02487 02488 StartVa - Returns the starting address of the init section. 02489 02490 EndVa - Returns the ending address of the init section. 02491 02492 Return Value: 02493 02494 None. 02495 02496 Environment: 02497 02498 Kernel Mode Only. End of system initialization. 02499 02500 --*/ 02501 02502 { 02503 PLDR_DATA_TABLE_ENTRY LdrDataTableEntry; 02504 PVOID CurrentBase; 02505 PVOID InitStart; 02506 PVOID InitEnd; 02507 PLIST_ENTRY Next; 02508 PIMAGE_NT_HEADERS NtHeader; 02509 PIMAGE_SECTION_HEADER SectionTableEntry; 02510 PIMAGE_SECTION_HEADER LastDiscard; 02511 LONG i; 02512 PVOID MiFindInitializationCodeAddress; 02513 02514 MiFindInitializationCodeAddress = MmGetProcedureAddress((PVOID)&MiFindInitializationCode); 02515 02516 *StartVa = NULL; 02517 02518 // 02519 // Walk through the loader blocks looking for the base which 02520 // contains this routine. 02521 // 02522 02523 KeEnterCriticalRegion(); 02524 ExAcquireResourceExclusive (&PsLoadedModuleResource, TRUE); 02525 Next = PsLoadedModuleList.Flink; 02526 02527 while ( Next != &PsLoadedModuleList ) { 02528 LdrDataTableEntry = CONTAINING_RECORD( Next, 02529 LDR_DATA_TABLE_ENTRY, 02530 InLoadOrderLinks 02531 ); 02532 if (LdrDataTableEntry->SectionPointer != NULL) { 02533 02534 // 02535 // This entry was loaded by MmLoadSystemImage so it's already 02536 // had its init section removed. 02537 // 02538 02539 Next = Next->Flink; 02540 continue; 02541 } 02542 02543 CurrentBase = (PVOID)LdrDataTableEntry->DllBase; 02544 NtHeader = RtlImageNtHeader(CurrentBase); 02545 02546 SectionTableEntry = (PIMAGE_SECTION_HEADER)((PCHAR)NtHeader + 02547 sizeof(ULONG) + 02548 sizeof(IMAGE_FILE_HEADER) + 02549 NtHeader->FileHeader.SizeOfOptionalHeader); 02550 02551 // 02552 // From the image header, locate the section named 'INIT'. 02553 // 02554 02555 i = NtHeader->FileHeader.NumberOfSections; 02556 02557 InitStart = NULL; 02558 while (i > 0) { 02559 02560 #if DBG 02561 if ((*(PULONG)SectionTableEntry->Name == 'tini') || 02562 (*(PULONG)SectionTableEntry->Name == 'egap')) { 02563 DbgPrint("driver %wZ has lower case sections (init or pagexxx)\n", 02564 &LdrDataTableEntry->FullDllName); 02565 } 02566 #endif //DBG 02567 02568 // 02569 // Free any INIT sections (or relocation sections that haven't 02570 // been already). Note a driver may have a relocation section 02571 // but not have any INIT code. 02572 // 02573 02574 if ((*(PULONG)SectionTableEntry->Name == 'TINI') || 02575 ((SectionTableEntry->Characteristics & IMAGE_SCN_MEM_DISCARDABLE) != 0)) { 02576 02577 02578 InitStart = (PVOID)((PCHAR)CurrentBase + SectionTableEntry->VirtualAddress); 02579 InitEnd = (PVOID)((PCHAR)InitStart + SectionTableEntry->SizeOfRawData - 1); 02580 InitEnd = (PVOID)((PCHAR)PAGE_ALIGN ((PCHAR)InitEnd + 02581 (NtHeader->OptionalHeader.SectionAlignment - 1)) - 1); 02582 InitStart = (PVOID)ROUND_TO_PAGES (InitStart); 02583 02584 // 02585 // Check if more sections are discardable after this one so 02586 // even small INIT sections can be discarded. 02587 // 02588 02589 if (i == 1) { 02590 LastDiscard = SectionTableEntry; 02591 } 02592 else { 02593 LastDiscard = NULL; 02594 do { 02595 i -= 1; 02596 SectionTableEntry += 1; 02597 02598 if ((SectionTableEntry->Characteristics & 02599 IMAGE_SCN_MEM_DISCARDABLE) != 0) { 02600 02601 // 02602 // Discard this too. 02603 // 02604 02605 LastDiscard = SectionTableEntry; 02606 } else { 02607 break; 02608 } 02609 } while (i > 1); 02610 } 02611 02612 if (LastDiscard) { 02613 InitEnd = (PVOID)(((PCHAR)CurrentBase + 02614 LastDiscard->VirtualAddress) + 02615 (LastDiscard->SizeOfRawData - 1)); 02616 02617 // 02618 // If this isn't the last section in the driver then the 02619 // the next section is not discardable. So the last 02620 // section is not rounded down, but all others must be. 02621 // 02622 02623 if (i != 1) { 02624 InitEnd = (PVOID)((PCHAR)PAGE_ALIGN ((PCHAR)InitEnd + 02625 (NtHeader->OptionalHeader.SectionAlignment - 1)) - 1); 02626 } 02627 } 02628 02629 if (InitEnd > (PVOID)((PCHAR)CurrentBase + 02630 LdrDataTableEntry->SizeOfImage)) { 02631 InitEnd = (PVOID)(((ULONG_PTR)CurrentBase + 02632 (LdrDataTableEntry->SizeOfImage - 1)) | 02633 (PAGE_SIZE - 1)); 02634 } 02635 02636 if (InitStart <= InitEnd) { 02637 if ((MiFindInitializationCodeAddress >= InitStart) && 02638 (MiFindInitializationCodeAddress <= InitEnd)) { 02639 02640 // 02641 // This init section is in the kernel, don't free it 02642 // now as it would free this code! 02643 // 02644 02645 *StartVa = InitStart; 02646 *EndVa = InitEnd; 02647 } 02648 else { 02649 MiFreeInitializationCode (InitStart, InitEnd); 02650 } 02651 } 02652 } 02653 i -= 1; 02654 SectionTableEntry += 1; 02655 } 02656 Next = Next->Flink; 02657 } 02658 ExReleaseResource (&PsLoadedModuleResource); 02659 KeLeaveCriticalRegion(); 02660 return; 02661 }

VOID MiFlushAllPages VOID   ) 
 

Definition at line 4870 of file modwrite.c.

References FALSE, KeDelayExecutionThread(), KernelMode, KeSetEvent(), Mm30Milliseconds, MmModifiedPageListHead, MmModifiedPageWriterEvent, MmWriteAllModifiedPages, _MMPFNLIST::Total, and TRUE.

Referenced by MiAllocateContiguousMemory(), MmGatherMemoryForHibernate(), and MmRemovePhysicalMemory().

04876 : 04877 04878 Forces a write of all modified pages. 04879 04880 Arguments: 04881 04882 None. 04883 04884 Return Value: 04885 04886 None. 04887 04888 Environment: 04889 04890 Kernel mode. No locks held. APC_LEVEL or less. 04891 04892 --*/ 04893 04894 { 04895 ULONG j = 0xff; 04896 04897 MmWriteAllModifiedPages = TRUE; 04898 KeSetEvent (&MmModifiedPageWriterEvent, 0, FALSE); 04899 04900 do { 04901 KeDelayExecutionThread (KernelMode, FALSE, &Mm30Milliseconds); 04902 j -= 1; 04903 } while ((MmModifiedPageListHead.Total > 50) && (j > 0)); 04904 04905 MmWriteAllModifiedPages = FALSE; 04906 return; 04907 }

VOID MiFlushEventCounter  ) 
 

Definition at line 2487 of file sectsup.c.

References APC_LEVEL, _MMEVENT_COUNT_LIST::Count, ExFreePool(), _EVENT_COUNTER::ListEntry, _MMEVENT_COUNT_LIST::ListHead, LOCK_PFN, MM_PFN_LOCK_ASSERT, MmEventCountList, NULL, and UNLOCK_PFN.

Referenced by MiFreeEventCounter().

02492 : 02493 02494 This routine examines the list of event counters and attempts 02495 to free up to 10 (if there are more than 4). 02496 02497 It will release and reacquire the PFN lock when it frees the 02498 event counters! 02499 02500 Arguments: 02501 02502 None. 02503 02504 Return Value: 02505 02506 None. 02507 02508 Environment: 02509 02510 Kernel mode, PFN lock held. 02511 02512 --*/ 02513 02514 02515 { 02516 KIRQL OldIrql; 02517 PEVENT_COUNTER Support[10]; 02518 ULONG i = 0; 02519 PLIST_ENTRY NextEntry; 02520 02521 MM_PFN_LOCK_ASSERT(); 02522 02523 while ((MmEventCountList.Count > 4) && (i < 10)) { 02524 NextEntry = RemoveHeadList (&MmEventCountList.ListHead); 02525 Support[i] = CONTAINING_RECORD (NextEntry, 02526 EVENT_COUNTER, 02527 ListEntry ); 02528 Support[i]->ListEntry.Flink = NULL; 02529 i += 1; 02530 MmEventCountList.Count -= 1; 02531 } 02532 02533 if (i == 0) { 02534 return; 02535 } 02536 02537 OldIrql = APC_LEVEL; 02538 UNLOCK_PFN (OldIrql); 02539 02540 do { 02541 i -= 1; 02542 ExFreePool(Support[i]); 02543 } while (i > 0); 02544 02545 LOCK_PFN (OldIrql); 02546 02547 return; 02548 }

VOID MiFlushInPageSupportBlock  ) 
 

Definition at line 4301 of file pagfault.c.

References APC_LEVEL, _MMINPAGE_SUPPORT_LIST::Count, ExFreePool(), _MMINPAGE_SUPPORT::ListEntry, _MMINPAGE_SUPPORT_LIST::ListHead, LOCK_PFN, _MMINPAGE_SUPPORT::Mdl, MM_PFN_LOCK_ASSERT, MmInPageSupportList, MMMAX_INPAGE_SUPPORT, NULL, and UNLOCK_PFN.

Referenced by MiDispatchFault().

04306 : 04307 04308 This routine examines the number of freed in page support blocks, 04309 and if more than 4, frees the blocks back to the NonPagedPool. 04310 04311 04312 ****** NB: The PFN LOCK is RELEASED and reacquired during this call ****** 04313 04314 04315 Arguments: 04316 04317 None. 04318 04319 Return Value: 04320 04321 None. 04322 04323 Environment: 04324 04325 Kernel mode, PFN lock held. 04326 04327 --*/ 04328 04329 #define MMMAX_INPAGE_SUPPORT 4 04330 04331 { 04332 KIRQL OldIrql; 04333 PMMINPAGE_SUPPORT Support[10]; 04334 ULONG i = 0; 04335 PLIST_ENTRY NextEntry; 04336 04337 MM_PFN_LOCK_ASSERT(); 04338 04339 while ((MmInPageSupportList.Count > MMMAX_INPAGE_SUPPORT) && (i < 10)) { 04340 NextEntry = RemoveHeadList (&MmInPageSupportList.ListHead); 04341 Support[i] = CONTAINING_RECORD (NextEntry, 04342 MMINPAGE_SUPPORT, 04343 ListEntry ); 04344 Support[i]->ListEntry.Flink = NULL; 04345 i += 1; 04346 MmInPageSupportList.Count -= 1; 04347 } 04348 04349 if (i == 0) { 04350 return; 04351 } 04352 04353 UNLOCK_PFN (APC_LEVEL); 04354 04355 do { 04356 i -= 1; 04357 04358 #if defined (_PREFETCH_) 04359 if ((Support[i]->PrefetchMdl != NULL) && 04360 (Support[i]->PrefetchMdl != &Support[i]->Mdl)) { 04361 ExFreePool (Support[i]->PrefetchMdl); 04362 } 04363 #endif 04364 04365 ExFreePool(Support[i]); 04366 } while (i > 0); 04367 04368 LOCK_PFN (OldIrql); 04369 04370 return; 04371 }

VOID MiFlushPteList IN PMMPTE_FLUSH_LIST  PteFlushList,
IN ULONG  AllProcessors,
IN MMPTE  FillPte
 

Definition at line 1160 of file deleteva.c.

References ASSERT, FALSE, KeFlushEntireTb(), KeFlushMultipleTb(), KeFlushSingleTb(), MiLockSystemSpaceAtDpcLevel, MiUnlockSystemSpaceFromDpcLevel, MM_FLUSH_COUNTER_MASK, MM_MAXIMUM_FLUSH_COUNT, MM_PFN_LOCK_ASSERT, MmFlushCounter, and TRUE.

Referenced by MiDeletePte(), MiDeleteSystemPagableVm(), MiDeleteVirtualAddresses(), MiProcessValidPteList(), MiReleaseSystemPtes(), MiRemoveMappedPtes(), MiRemoveWorkingSetPages(), MiReserveSystemPtes2(), and MmCleanProcessAddressSpace().

01168 : 01169 01170 This routine flushes all the PTEs in the PTE flush list. 01171 If the list has overflowed, the entire TB is flushed. 01172 01173 Arguments: 01174 01175 PteFlushList - Supplies an optional pointer to the list to be flushed. 01176 01177 AllProcessors - Supplies TRUE if the flush occurs on all processors. 01178 01179 FillPte - Supplies the PTE to fill with. 01180 01181 Return Value: 01182 01183 None. 01184 01185 Environment: 01186 01187 Kernel mode, PFN lock held. 01188 01189 --*/ 01190 01191 { 01192 ULONG count; 01193 01194 ASSERT (ARGUMENT_PRESENT (PteFlushList)); 01195 MM_PFN_LOCK_ASSERT (); 01196 01197 count = PteFlushList->Count; 01198 01199 if (count != 0) { 01200 if (count != 1) { 01201 if (count < MM_MAXIMUM_FLUSH_COUNT) { 01202 KeFlushMultipleTb (count, 01203 &PteFlushList->FlushVa[0], 01204 TRUE, 01205 (BOOLEAN)AllProcessors, 01206 &((PHARDWARE_PTE)PteFlushList->FlushPte[0]), 01207 FillPte.u.Flush); 01208 } else { 01209 01210 // 01211 // Array has overflowed, flush the entire TB. 01212 // 01213 01214 if (AllProcessors == TRUE) { 01215 MiLockSystemSpaceAtDpcLevel(); 01216 KeFlushEntireTb (TRUE, TRUE); 01217 MmFlushCounter = (MmFlushCounter + 1) & MM_FLUSH_COUNTER_MASK; 01218 MiUnlockSystemSpaceFromDpcLevel(); 01219 } else { 01220 KeFlushEntireTb (TRUE, FALSE); 01221 } 01222 } 01223 } else { 01224 KeFlushSingleTb (PteFlushList->FlushVa[0], 01225 TRUE, 01226 (BOOLEAN)AllProcessors, 01227 (PHARDWARE_PTE)PteFlushList->FlushPte[0], 01228 FillPte.u.Flush); 01229 } 01230 PteFlushList->Count = 0; 01231 } 01232 return; 01233 } }

NTSTATUS MiFlushSectionInternal IN PMMPTE  StartingPte,
IN PMMPTE  FinalPte,
IN PSUBSECTION  FirstSubsection,
IN PSUBSECTION  LastSubsection,
IN ULONG  Synchronize,
IN LOGICAL  WriteInProgressOk,
OUT PIO_STATUS_BLOCK  IoStatus
 

Definition at line 1014 of file flushsec.c.

References ASSERT, _MDL::ByteCount, DbgPrint, FALSE, _CONTROL_AREA::FilePointer, _CONTROL_AREA::FlushInProgressCount, IoSynchronousPageWrite(), KeClearEvent, KeDelayExecutionThread(), KeEnterCriticalRegion, KeInitializeEvent, KeLeaveCriticalRegion, KePulseEvent(), KernelMode, KeWaitForSingleObject(), LOCK_PFN, _MDL::MappedSystemVa, MDL_MAPPED_TO_SYSTEM_VA, MDL_PAGES_LOCKED, _MDL::MdlFlags, MI_ADD_LOCKED_PAGE_CHARGE, MI_ADD_LOCKED_PAGE_CHARGE_FOR_MODIFIED_PAGE, MI_GET_PAGE_FRAME_FROM_PTE, MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE, MI_INITIALIZE_ZERO_MDL, MI_PFN_ELEMENT, MI_REMOVE_LOCKED_PAGE_CHARGE, MiCheckProtoPtePageState(), MiDecrementReferenceCount(), MiEndingOffset(), MiIoRetryLevel, MiIsPteOnPdeBoundary, MiMakeSystemAddressValidPfn(), MiStartingOffset(), MiUnlinkPageFromList(), Mm30Milliseconds, MM_DBG_FLUSH_SECTION, MM_MAXIMUM_DISK_IO_SIZE, MmCollidedFlushEvent, MmIsRetryIoStatus, MmModifiedWriteClusterSize, MmOneSecond, MmUnmapLockedPages(), _SUBSECTION::NextSubsection, NT_SUCCESS, NTSTATUS(), NULL, _CONTROL_AREA::NumberOfPfnReferences, _MMPFN::OriginalPte, PAGE_SHIFT, PAGE_SIZE, _MMPFN::PteAddress, _SUBSECTION::PtesInSubsection, _MDL::Size, _MDL::StartVa, Status, STATUS_MAPPED_WRITER_COLLISION, _SUBSECTION::SubsectionBase, TRUE, _MMPTE::u, _CONTROL_AREA::u, _MMPFN::u3, UNLOCK_PFN, UNLOCK_PFN_AND_THEN_WAIT, and WrPageOut.

Referenced by MiRemoveUnusedSegments(), MmFlushSection(), and MmFlushVirtualMemory().

01026 : 01027 01028 This function flushes to the backing file any modified pages within 01029 the specified range of the section. The parameters describe the 01030 section's prototype PTEs (start and end) and the subsections 01031 which correspond to the starting and ending PTE. 01032 01033 Each PTE in the subsection between the specified start and end 01034 is examined and if the page is either valid or transition AND 01035 the page has been modified, the modify bit is cleared in the PFN 01036 database and the page is flushed to its backing file. 01037 01038 Arguments: 01039 01040 StartingPte - Supplies a pointer to the first prototype PTE to 01041 be examined for flushing. 01042 01043 FinalPte - Supplies a pointer to the last prototype PTE to be 01044 examined for flushing. 01045 01046 FirstSubsection - Supplies the subsection that contains the 01047 StartingPte. 01048 01049 LastSubsection - Supplies the subsection that contains the 01050 FinalPte. 01051 01052 Synchronize - Supplies TRUE if synchronization with all threads 01053 doing flush operations to this section should occur. 01054 01055 WriteInProgressOk - Supplies TRUE if the caller can tolerate a write 01056 already in progress for any dirty pages. 01057 01058 IoStatus - Returns the value of the IoStatus for the last attempted 01059 I/O operation. 01060 01061 Return Value: 01062 01063 Returns status of the operation. 01064 01065 --*/ 01066 01067 { 01068 PCONTROL_AREA ControlArea; 01069 PMMPTE PointerPte; 01070 PMMPTE LastPte; 01071 PMMPTE LastWritten; 01072 MMPTE PteContents; 01073 PMMPFN Pfn1; 01074 PMMPFN Pfn2; 01075 KIRQL OldIrql; 01076 PMDL Mdl; 01077 KEVENT IoEvent; 01078 PSUBSECTION Subsection; 01079 PPFN_NUMBER Page; 01080 PFN_NUMBER PageFrameIndex; 01081 PPFN_NUMBER LastPage; 01082 NTSTATUS Status; 01083 UINT64 StartingOffset; 01084 UINT64 TempOffset; 01085 BOOLEAN WriteNow; 01086 LOGICAL Bail; 01087 PFN_NUMBER MdlHack[(sizeof(MDL)/sizeof(PFN_NUMBER)) + (MM_MAXIMUM_DISK_IO_SIZE / PAGE_SIZE) + 1]; 01088 ULONG ReflushCount; 01089 01090 WriteNow = FALSE; 01091 Bail = FALSE; 01092 01093 IoStatus->Status = STATUS_SUCCESS; 01094 IoStatus->Information = 0; 01095 Mdl = (PMDL)&MdlHack[0]; 01096 01097 KeInitializeEvent (&IoEvent, NotificationEvent, FALSE); 01098 01099 FinalPte += 1; // Point to 1 past the last one. 01100 01101 LastWritten = NULL; 01102 LastPage = 0; 01103 Subsection = FirstSubsection; 01104 PointerPte = StartingPte; 01105 ControlArea = FirstSubsection->ControlArea; 01106 01107 LOCK_PFN (OldIrql); 01108 01109 ASSERT (ControlArea->u.Flags.Image == 0); 01110 01111 if (ControlArea->NumberOfPfnReferences == 0) { 01112 01113 // 01114 // No transition or valid prototype PTEs present, hence 01115 // no need to flush anything. 01116 // 01117 01118 UNLOCK_PFN (OldIrql); 01119 return STATUS_SUCCESS; 01120 } 01121 01122 while ((Synchronize) && (ControlArea->FlushInProgressCount != 0)) { 01123 01124 // 01125 // Another thread is currently performing a flush operation on 01126 // this file. Wait for that flush to complete. 01127 // 01128 01129 KeEnterCriticalRegion(); 01130 ControlArea->u.Flags.CollidedFlush = 1; 01131 UNLOCK_PFN_AND_THEN_WAIT(OldIrql); 01132 01133 KeWaitForSingleObject (&MmCollidedFlushEvent, 01134 WrPageOut, 01135 KernelMode, 01136 FALSE, 01137 &MmOneSecond); 01138 LOCK_PFN (OldIrql); 01139 KeLeaveCriticalRegion(); 01140 } 01141 01142 ControlArea->FlushInProgressCount += 1; 01143 01144 for (;;) { 01145 01146 if (LastSubsection != Subsection) { 01147 01148 // 01149 // Flush to the last PTE in this subsection. 01150 // 01151 01152 LastPte = &Subsection->SubsectionBase[Subsection->PtesInSubsection]; 01153 } else { 01154 01155 // 01156 // Flush to the end of the range. 01157 // 01158 01159 LastPte = FinalPte; 01160 } 01161 01162 // 01163 // If the prototype PTEs are paged out or have a share count 01164 // of 1, they cannot contain any transition or valid PTEs. 01165 // 01166 01167 if (!MiCheckProtoPtePageState(PointerPte, TRUE)) { 01168 PointerPte = (PMMPTE)(((ULONG_PTR)PointerPte | (PAGE_SIZE - 1)) + 1); 01169 } 01170 01171 while (PointerPte < LastPte) { 01172 01173 if (MiIsPteOnPdeBoundary(PointerPte)) { 01174 01175 // 01176 // We are on a page boundary, make sure this PTE is resident. 01177 // 01178 01179 if (!MiCheckProtoPtePageState(PointerPte, TRUE)) { 01180 PointerPte = (PMMPTE)((PCHAR)PointerPte + PAGE_SIZE); 01181 01182 // 01183 // If there are dirty pages to be written, write them 01184 // now as we are skipping over PTEs. 01185 // 01186 01187 if (LastWritten != NULL) { 01188 WriteNow = TRUE; 01189 goto CheckForWrite; 01190 } 01191 continue; 01192 } 01193 } 01194 01195 PteContents = *PointerPte; 01196 01197 if ((PteContents.u.Hard.Valid == 1) || 01198 ((PteContents.u.Soft.Prototype == 0) && 01199 (PteContents.u.Soft.Transition == 1))) { 01200 01201 // 01202 // Prototype PTE in transition, there are 3 possible cases: 01203 // 1. The page is part of an image which is sharable and 01204 // refers to the paging file - dereference page file 01205 // space and free the physical page. 01206 // 2. The page refers to the segment but is not modified - 01207 // free the physical page. 01208 // 3. The page refers to the segment and is modified - 01209 // write the page to the file and free the physical page. 01210 // 01211 01212 if (PteContents.u.Hard.Valid == 1) { 01213 PageFrameIndex = MI_GET_PAGE_FRAME_FROM_PTE (&PteContents); 01214 } else { 01215 PageFrameIndex = MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE (&PteContents); 01216 } 01217 01218 Pfn1 = MI_PFN_ELEMENT (PageFrameIndex); 01219 ASSERT (Pfn1->OriginalPte.u.Soft.Prototype == 1); 01220 ASSERT (Pfn1->OriginalPte.u.Hard.Valid == 0); 01221 01222 // 01223 // If the page is modified OR a write is in progress 01224 // flush it. The write in progress case catches problems 01225 // where the modified page write continually writes a 01226 // page and gets errors writing it, by writing pages 01227 // in this state, the error will be propagated back to 01228 // the caller. 01229 // 01230 01231 if ((Pfn1->u3.e1.Modified == 1) || 01232 (Pfn1->u3.e1.WriteInProgress)) { 01233 01234 if ((WriteInProgressOk == FALSE) && 01235 (Pfn1->u3.e1.WriteInProgress)) { 01236 01237 PointerPte = LastPte; 01238 Bail = TRUE; 01239 01240 if (LastWritten != NULL) { 01241 WriteNow = TRUE; 01242 } 01243 goto CheckForWrite; 01244 } 01245 01246 if (LastWritten == NULL) { 01247 01248 // 01249 // This is the first page of a cluster, initialize 01250 // the MDL, etc. 01251 // 01252 01253 LastPage = (PPFN_NUMBER)(Mdl + 1); 01254 01255 // 01256 // Calculate the offset to read into the file. 01257 // offset = base + ((thispte - basepte) << PAGE_SHIFT) 01258 // 01259 01260 StartingOffset = (UINT64) MiStartingOffset ( 01261 Subsection, 01262 Pfn1->PteAddress); 01263 01264 MI_INITIALIZE_ZERO_MDL (Mdl); 01265 01266 Mdl->MdlFlags |= MDL_PAGES_LOCKED; 01267 Mdl->StartVa = 01268 (PVOID)ULongToPtr(Pfn1->u3.e1.PageColor << PAGE_SHIFT); 01269 Mdl->Size = (CSHORT)(sizeof(MDL) + 01270 (sizeof(PFN_NUMBER) * MmModifiedWriteClusterSize)); 01271 } 01272 01273 LastWritten = PointerPte; 01274 Mdl->ByteCount += PAGE_SIZE; 01275 if (Mdl->ByteCount == (PAGE_SIZE * MmModifiedWriteClusterSize)) { 01276 WriteNow = TRUE; 01277 } 01278 01279 if (PteContents.u.Hard.Valid == 0) { 01280 01281 // 01282 // The page is in transition. 01283 // 01284 01285 MiUnlinkPageFromList (Pfn1); 01286 MI_ADD_LOCKED_PAGE_CHARGE_FOR_MODIFIED_PAGE(Pfn1, 18); 01287 } 01288 else { 01289 MI_ADD_LOCKED_PAGE_CHARGE(Pfn1, 20); 01290 } 01291 01292 // 01293 // Clear the modified bit for this page. 01294 // 01295 01296 Pfn1->u3.e1.Modified = 0; 01297 01298 // 01299 // Up the reference count for the physical page as there 01300 // is I/O in progress. 01301 // 01302 01303 Pfn1->u3.e2.ReferenceCount += 1; 01304 01305 *LastPage = PageFrameIndex; 01306 LastPage += 1; 01307 } else { 01308 01309 // 01310 // This page was not modified and therefore ends the 01311 // current write cluster if any. Set WriteNow to TRUE 01312 // if there is a cluster being built. 01313 // 01314 01315 if (LastWritten != NULL) { 01316 WriteNow = TRUE; 01317 } 01318 } 01319 } else { 01320 01321 // 01322 // This page was not modified and therefore ends the 01323 // current write cluster if any. Set WriteNow to TRUE 01324 // if there is a cluster being built. 01325 // 01326 01327 if (LastWritten != NULL) { 01328 WriteNow = TRUE; 01329 } 01330 } 01331 01332 PointerPte += 1; 01333 01334 CheckForWrite: 01335 01336 // 01337 // Write the current cluster if it is complete, 01338 // full, or the loop is now complete. 01339 // 01340 01341 if ((WriteNow) || 01342 ((PointerPte == LastPte) && (LastWritten != NULL))) { 01343 01344 LARGE_INTEGER EndOfFile; 01345 01346 // 01347 // Issue the write request. 01348 // 01349 01350 UNLOCK_PFN (OldIrql); 01351 01352 WriteNow = FALSE; 01353 01354 // 01355 // Make sure the write does not go past the 01356 // end of file. (segment size). 01357 // 01358 01359 EndOfFile = MiEndingOffset(Subsection); 01360 TempOffset = (UINT64) EndOfFile.QuadPart; 01361 01362 if (StartingOffset + Mdl->ByteCount > TempOffset) { 01363 01364 ASSERT ((ULONG_PTR)(TempOffset - StartingOffset) > 01365 (Mdl->ByteCount - PAGE_SIZE)); 01366 01367 Mdl->ByteCount = (ULONG)(TempOffset- 01368 StartingOffset); 01369 } 01370 01371 ReflushCount = MiIoRetryLevel; 01372 01373 while ( TRUE ) { 01374 01375 KeClearEvent (&IoEvent); 01376 01377 #if DBG 01378 if (MmDebug & MM_DBG_FLUSH_SECTION) { 01379 DbgPrint("flush page write begun %lx\n", 01380 Mdl->ByteCount); 01381 } 01382 #endif //DBG 01383 01384 Status = IoSynchronousPageWrite (ControlArea->FilePointer, 01385 Mdl, 01386 (PLARGE_INTEGER)&StartingOffset, 01387 &IoEvent, 01388 IoStatus ); 01389 01390 // 01391 // If success is returned, wait for the i/o event to be set. 01392 // 01393 01394 if (NT_SUCCESS(Status)) { 01395 KeWaitForSingleObject( &IoEvent, 01396 WrPageOut, 01397 KernelMode, 01398 FALSE, 01399 (PLARGE_INTEGER)NULL); 01400 // 01401 // Otherwise, copy the error to the IoStatus, for error 01402 // handling below. 01403 // 01404 01405 } else { 01406 IoStatus->Status = Status; 01407 } 01408 01409 if (Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA) { 01410 MmUnmapLockedPages (Mdl->MappedSystemVa, Mdl); 01411 } 01412 01413 Page = (PPFN_NUMBER)(Mdl + 1); 01414 01415 if (MmIsRetryIoStatus(IoStatus->Status)) { 01416 01417 ReflushCount -= 1; 01418 if (ReflushCount != 0) { 01419 KeDelayExecutionThread (KernelMode, FALSE, &Mm30Milliseconds); 01420 continue; 01421 } 01422 } 01423 01424 break; 01425 } 01426 01427 LOCK_PFN (OldIrql); 01428 01429 if (MiIsPteOnPdeBoundary(PointerPte) == 0) { 01430 01431 // 01432 // The next PTE is not in a different page, make 01433 // sure this page did not leave memory when the 01434 // I/O was in progress. 01435 // 01436 01437 MiMakeSystemAddressValidPfn (PointerPte); 01438 } 01439 01440 if (NT_SUCCESS(IoStatus->Status)) { 01441 01442 // 01443 // The I/O completed successfully, unlock the pages. 01444 // 01445 01446 while (Page < LastPage) { 01447 01448 Pfn2 = MI_PFN_ELEMENT (*Page); 01449 MI_REMOVE_LOCKED_PAGE_CHARGE(Pfn2, 19); 01450 MiDecrementReferenceCount (*Page); 01451 Page += 1; 01452 } 01453 } else { 01454 01455 // 01456 // Don't count on the file system to convey anything on errors 01457 // in the information field. 01458 // 01459 01460 IoStatus->Information = 0; 01461 01462 // 01463 // The I/O completed unsuccessfully, unlock the pages 01464 // and return an error status. 01465 // 01466 01467 while (Page < LastPage) { 01468 01469 Pfn2 = MI_PFN_ELEMENT (*Page); 01470 01471 // 01472 // Mark the page dirty again so it can be rewritten. 01473 // 01474 01475 Pfn2->u3.e1.Modified = 1; 01476 01477 MI_REMOVE_LOCKED_PAGE_CHARGE(Pfn2, 21); 01478 MiDecrementReferenceCount (*Page); 01479 Page += 1; 01480 } 01481 01482 // 01483 // Calculate how much was written thus far 01484 // and add that to the information field 01485 // of the IOSB. 01486 // 01487 01488 IoStatus->Information += 01489 (((LastWritten - StartingPte) << PAGE_SHIFT) - 01490 Mdl->ByteCount); 01491 01492 goto ErrorReturn; 01493 } 01494 01495 // 01496 // As the PFN lock has been released and 01497 // reacquired, do this loop again as the 01498 // PTE may have changed state. 01499 // 01500 01501 LastWritten = NULL; 01502 } 01503 01504 } //end while 01505 01506 if ((Bail == TRUE) || (Subsection == LastSubsection)) { 01507 01508 // 01509 // The last range has been flushed or we have collided with the 01510 // mapped page writer. Regardless, exit the top FOR loop 01511 // and return. 01512 // 01513 01514 break; 01515 } 01516 01517 Subsection = Subsection->NextSubsection; 01518 PointerPte = Subsection->SubsectionBase; 01519 01520 } //end for 01521 01522 ASSERT (LastWritten == NULL); 01523 01524 ErrorReturn: 01525 01526 ControlArea->FlushInProgressCount -= 1; 01527 if ((ControlArea->u.Flags.CollidedFlush == 1) && 01528 (ControlArea->FlushInProgressCount == 0)) { 01529 ControlArea->u.Flags.CollidedFlush = 0; 01530 KePulseEvent (&MmCollidedFlushEvent, 0, FALSE); 01531 } 01532 UNLOCK_PFN (OldIrql); 01533 01534 if (Bail == TRUE) { 01535 01536 // 01537 // This routine collided with the mapped page writer and the caller 01538 // expects an error for this. Give it to him. 01539 // 01540 01541 return STATUS_MAPPED_WRITER_COLLISION; 01542 } 01543 01544 return IoStatus->Status; 01545 }

VOID MiFlushTb VOID   ) 
 

VOID MiFormatPfn IN PMMPFN  PointerPfn  ) 
 

Referenced by MiCopyOnWrite(), MiDeletePte(), MiInitializePfn(), MiInitializePfnForOtherProcess(), MiResolveTransitionFault(), and MiUnlinkPageFromList().

VOID MiFormatPte IN PMMPTE  PointerPte  ) 
 

Referenced by MiCopyOnWrite(), MiDeletePte(), MiInitializePfn(), MiInitializePfnForOtherProcess(), MiResolveMappedFileFault(), MiResolveProtoPteFault(), MmAccessFault(), and MmInitSystem().

VOID MiFreeEventCounter IN PEVENT_COUNTER  Support,
IN ULONG  Flush
 

Definition at line 2438 of file sectsup.c.

References ASSERT, _MMEVENT_COUNT_LIST::Count, _MMEVENT_COUNT_LIST::ListHead, MiFlushEventCounter(), MM_PFN_LOCK_ASSERT, MmEventCountList, and NULL.

Referenced by MiCheckControlAreaStatus(), MiCheckPurgeAndUpMapCount(), and MmCreateSection().

02445 : 02446 02447 This routine frees an event counter back to the free list. 02448 02449 Arguments: 02450 02451 Support - Supplies a pointer to the event counter. 02452 02453 Flush - Supplies TRUE if the PFN lock can be released and the event 02454 counter pool block actually freed. The PFN lock will be 02455 reacquired before returning. 02456 02457 Return Value: 02458 02459 None. 02460 02461 Environment: 02462 02463 Kernel mode, PFN lock held. 02464 02465 --*/ 02466 02467 { 02468 02469 MM_PFN_LOCK_ASSERT(); 02470 02471 ASSERT (Support->RefCount != 0); 02472 ASSERT (Support->ListEntry.Flink == NULL); 02473 Support->RefCount -= 1; 02474 if (Support->RefCount == 0) { 02475 InsertTailList (&MmEventCountList.ListHead, 02476 &Support->ListEntry); 02477 MmEventCountList.Count += 1; 02478 } 02479 if ((Flush) && (MmEventCountList.Count > 4)) { 02480 MiFlushEventCounter(); 02481 } 02482 return; 02483 }

VOID MiFreeInitializationCode IN PVOID  StartVa,
IN PVOID  EndVa
 

Definition at line 2664 of file mminit.c.

References ASSERT, FALSE, FreePageList, LOCK_PFN, MI_CONVERT_PHYSICAL_TO_PFN, MI_IS_PHYSICAL_ADDRESS, MI_PFN_ELEMENT, MI_SET_PFN_DELETED, MiDeleteSystemPagableVm(), MiFreeInitializationCode(), MiGetPteAddress, MiInsertPageInList(), MmPageLocationList, MmUnlockPagableImageSection(), NULL, PAGE_SIZE, _MMPFN::u2, _MMPFN::u3, UNLOCK_PFN, and ZeroKernelPte.

Referenced by MiFindInitializationCode(), MiFreeInitializationCode(), and MmZeroPageThread().

02671 : 02672 02673 This function is called to delete the initialization code. 02674 02675 Arguments: 02676 02677 StartVa - Supplies the starting address of the range to delete. 02678 02679 EndVa - Supplies the ending address of the range to delete. 02680 02681 Return Value: 02682 02683 None. 02684 02685 Environment: 02686 02687 Kernel Mode Only. Runs after system initialization. 02688 02689 --*/ 02690 02691 { 02692 PMMPFN Pfn1; 02693 PMMPTE PointerPte; 02694 PFN_NUMBER PageFrameIndex; 02695 KIRQL OldIrql; 02696 PVOID UnlockHandle; 02697 02698 UnlockHandle = MmLockPagableCodeSection((PVOID)MiFreeInitializationCode); 02699 ASSERT(UnlockHandle); 02700 02701 if (MI_IS_PHYSICAL_ADDRESS(StartVa)) { 02702 LOCK_PFN (OldIrql); 02703 while (StartVa < EndVa) { 02704 02705 // 02706 // On certain architectures (e.g., MIPS) virtual addresses 02707 // may be physical and hence have no corresponding PTE. 02708 // 02709 02710 PageFrameIndex = MI_CONVERT_PHYSICAL_TO_PFN (StartVa); 02711 02712 Pfn1 = MI_PFN_ELEMENT (PageFrameIndex); 02713 Pfn1->u2.ShareCount = 0; 02714 Pfn1->u3.e2.ReferenceCount = 0; 02715 MI_SET_PFN_DELETED (Pfn1); 02716 MiInsertPageInList (MmPageLocationList[FreePageList], PageFrameIndex); 02717 StartVa = (PVOID)((PUCHAR)StartVa + PAGE_SIZE); 02718 } 02719 UNLOCK_PFN (OldIrql); 02720 } else { 02721 PointerPte = MiGetPteAddress (StartVa); 02722 MiDeleteSystemPagableVm (PointerPte, 02723 (PFN_NUMBER) (1 + MiGetPteAddress (EndVa) - 02724 PointerPte), 02725 ZeroKernelPte, 02726 FALSE, 02727 NULL); 02728 } 02729 MmUnlockPagableImageSection(UnlockHandle); 02730 return; 02731 }

VOID MiFreeInPageSupportBlock IN PMMINPAGE_SUPPORT  Support  ) 
 

Definition at line 4252 of file pagfault.c.

References ASSERT, _MMINPAGE_SUPPORT_LIST::Count, _MMINPAGE_SUPPORT_LIST::ListHead, MM_PFN_LOCK_ASSERT, MmInPageSupportList, and NULL.

Referenced by MiWaitForInPageComplete(), and MmCopyToCachedPage().

04258 : 04259 04260 This routine returns the in page support block to a list 04261 of freed blocks. 04262 04263 Arguments: 04264 04265 Support - Supplies the in page support block to put on the free list. 04266 04267 Return Value: 04268 04269 None. 04270 04271 Environment: 04272 04273 Kernel mode, PFN lock held. 04274 04275 --*/ 04276 04277 { 04278 04279 MM_PFN_LOCK_ASSERT(); 04280 04281 ASSERT (Support->u.Thread != NULL); 04282 ASSERT (Support->WaitCount != 0); 04283 #if defined (_PREFETCH_) 04284 ASSERT ((Support->ListEntry.Flink == NULL) || 04285 (Support->PrefetchMdl != NULL)); 04286 #else 04287 ASSERT (Support->ListEntry.Flink == NULL); 04288 #endif 04289 Support->WaitCount -= 1; 04290 if (Support->WaitCount == 0) { 04291 Support->u.Thread = NULL; 04292 InsertTailList (&MmInPageSupportList.ListHead, 04293 &Support->ListEntry); 04294 MmInPageSupportList.Count += 1; 04295 } 04296 return; 04297 }

VOID MiFreeSessionPoolBitMaps VOID   ) 
 

Definition at line 4478 of file allocpag.c.

References _MM_PAGED_POOL_INFO::EndOfPagedPoolBitmap, ExFreePool(), MmSessionSpace, NULL, PAGED_CODE, _MM_PAGED_POOL_INFO::PagedPoolAllocationMap, _MM_SESSION_SPACE::PagedPoolInfo, and _MM_PAGED_POOL_INFO::PagedPoolLargeSessionAllocationMap.

Referenced by MiDereferenceSession(), MiInitializeSessionPool(), and MiSessionCreateInternal().

04484 : 04485 04486 Free the current session's pool bitmap structures. 04487 04488 Arguments: 04489 04490 None. 04491 04492 Return Value: 04493 04494 None. 04495 04496 Environment: 04497 04498 Kernel mode. 04499 04500 --*/ 04501 04502 { 04503 PAGED_CODE(); 04504 04505 if (MmSessionSpace->PagedPoolInfo.PagedPoolAllocationMap ) { 04506 ExFreePool (MmSessionSpace->PagedPoolInfo.PagedPoolAllocationMap); 04507 MmSessionSpace->PagedPoolInfo.PagedPoolAllocationMap = NULL; 04508 } 04509 04510 if (MmSessionSpace->PagedPoolInfo.EndOfPagedPoolBitmap ) { 04511 ExFreePool (MmSessionSpace->PagedPoolInfo.EndOfPagedPoolBitmap); 04512 MmSessionSpace->PagedPoolInfo.EndOfPagedPoolBitmap = NULL; 04513 } 04514 04515 if (MmSessionSpace->PagedPoolInfo.PagedPoolLargeSessionAllocationMap) { 04516 ExFreePool (MmSessionSpace->PagedPoolInfo.PagedPoolLargeSessionAllocationMap); 04517 MmSessionSpace->PagedPoolInfo.PagedPoolLargeSessionAllocationMap = NULL; 04518 } 04519 }

VOID MiFreeSessionSpaceMap VOID   ) 
 

Definition at line 4071 of file mapview.c.

References _MMVIEW::ControlArea, DbgPrint, _MMVIEW::Entry, ExFreePool(), Index, KeBugCheckEx(), LOCK_SYSTEM_VIEW_SPACE, MiRemoveBitMap, MiUnmapViewInSystemSpace(), MmSessionSpace, NULL, PAGED_CODE, _MM_SESSION_SPACE::Session, _MM_SESSION_SPACE::SessionId, _MMSESSION::SystemSpaceBitMap, _MMSESSION::SystemSpaceHashEntries, _MMSESSION::SystemSpaceHashSize, _MMSESSION::SystemSpaceViewTable, and UNLOCK_SYSTEM_VIEW_SPACE.

Referenced by MiDereferenceSession(), and MiSessionCreateInternal().

04077 : 04078 04079 This routine frees the tables used for mapping session views. 04080 04081 Arguments: 04082 04083 None. 04084 04085 Return Value: 04086 04087 None. 04088 04089 Environment: 04090 04091 Kernel Mode. The caller must be in the correct session context. 04092 04093 --*/ 04094 04095 { 04096 PMMSESSION Session; 04097 04098 PAGED_CODE(); 04099 04100 Session = &MmSessionSpace->Session; 04101 04102 // 04103 // Check for leaks of objects in the view table. 04104 // 04105 04106 LOCK_SYSTEM_VIEW_SPACE (Session); 04107 04108 if (Session->SystemSpaceViewTable && Session->SystemSpaceHashEntries) { 04109 04110 KeBugCheckEx (SESSION_HAS_VALID_VIEWS_ON_EXIT, 04111 (ULONG_PTR)MmSessionSpace->SessionId, 04112 Session->SystemSpaceHashEntries, 04113 (ULONG_PTR)&Session->SystemSpaceViewTable[0], 04114 Session->SystemSpaceHashSize); 04115 04116 #if 0 04117 ULONG Index; 04118 04119 for (Index = 0; Index < Session->SystemSpaceHashSize; Index += 1) { 04120 04121 PMMVIEW Table; 04122 PVOID Base; 04123 04124 Table = &Session->SystemSpaceViewTable[Index]; 04125 04126 if (Table->Entry) { 04127 04128 #if DBG 04129 DbgPrint ("MM: MiFreeSessionSpaceMap: view entry %d leak: ControlArea %p, Addr %p, Size %d\n", 04130 Index, 04131 Table->ControlArea, 04132 Table->Entry & ~0xFFFF, 04133 Table->Entry & 0x0000FFFF 04134 ); 04135 #endif 04136 04137 Base = (PVOID)(Table->Entry & ~0xFFFF); 04138 04139 // 04140 // MiUnmapViewInSystemSpace locks the ViewLock. 04141 // 04142 04143 UNLOCK_SYSTEM_VIEW_SPACE(Session); 04144 04145 MiUnmapViewInSystemSpace (Session, Base); 04146 04147 LOCK_SYSTEM_VIEW_SPACE (Session); 04148 04149 // 04150 // The view table may have been deleted while we let go of 04151 // the lock. 04152 // 04153 04154 if (Session->SystemSpaceViewTable == NULL) { 04155 break; 04156 } 04157 } 04158 } 04159 #endif 04160 04161 } 04162 04163 UNLOCK_SYSTEM_VIEW_SPACE (Session); 04164 04165 if (Session->SystemSpaceViewTable) { 04166 ExFreePool (Session->SystemSpaceViewTable); 04167 Session->SystemSpaceViewTable = NULL; 04168 } 04169 04170 if (Session->SystemSpaceBitMap) { 04171 MiRemoveBitMap (&Session->SystemSpaceBitMap); 04172 } 04173 }

VOID MiFreeWorkingSetRange IN PVOID  StartVa,
IN PVOID  EndVa,
IN PMMSUPPORT  WsInfo
 

ULONG MiFreeWsle IN WSLE_NUMBER  WorkingSetIndex,
IN PMMSUPPORT  WsInfo,
IN PMMPTE  PointerPte
 

Definition at line 1326 of file wslist.c.

References ASSERT, _MMWSLE::e1, FALSE, _MMWSL::FirstDynamic, _MMWSL::FirstFree, _MMWSL::LastInitializedWsle, LOCK_PFN, MI_IS_SESSION_ADDRESS, MI_PFN_ELEMENT, MiDumpWsleInCacheBlock(), MiEliminateWorkingSetEntry(), MiRemoveWsle(), MM_FREE_WSLE_SHIFT, MM_SYSTEM_WS_LOCK_ASSERT, MmPagesAboveWsMinimum, MmSystemCacheWs, PDE_TOP, TRUE, _MMWSLE::u1, _MMPFN::u2, _MMPFN::u3, UNLOCK_PFN, _MMWSLENTRY::Valid, _MMWSLE::VirtualAddress, _MMWSL::Wsle, and WSLE_NULL_INDEX.

Referenced by MiEmptyWorkingSet(), MiInsertWsle(), MiReplaceWorkingSetEntryUsingFaultInfo(), MiTrimWorkingSet(), MmAdjustWorkingSetSize(), and NtUnlockVirtualMemory().

01334 : 01335 01336 This routine frees the specified WSLE and decrements the share 01337 count for the corresponding page, putting the PTE into a transition 01338 state if the share count goes to 0. 01339 01340 Arguments: 01341 01342 WorkingSetIndex - Supplies the index of the working set entry to free. 01343 01344 WsInfo - Supplies a pointer to the working set structure (process or 01345 system cache). 01346 01347 PointerPte - Supplies a pointer to the PTE for the working set entry. 01348 01349 Return Value: 01350 01351 Returns TRUE if the WSLE was removed, FALSE if it was not removed. 01352 Pages with valid PTEs are not removed (i.e. page table pages 01353 that contain valid or transition PTEs). 01354 01355 Environment: 01356 01357 Kernel mode, APCs disabled, working set lock. PFN lock NOT held. 01358 01359 --*/ 01360 01361 { 01362 PMMPFN Pfn1; 01363 PMMWSL WorkingSetList; 01364 PMMWSLE Wsle; 01365 KIRQL OldIrql; 01366 01367 WorkingSetList = WsInfo->VmWorkingSetList; 01368 Wsle = WorkingSetList->Wsle; 01369 01370 #if DBG 01371 if (WsInfo == &MmSystemCacheWs) { 01372 MM_SYSTEM_WS_LOCK_ASSERT(); 01373 } 01374 #endif //DBG 01375 01376 ASSERT (Wsle[WorkingSetIndex].u1.e1.Valid == 1); 01377 01378 // 01379 // Check to see if the located entry is eligible for removal. 01380 // 01381 01382 ASSERT (PointerPte->u.Hard.Valid == 1); 01383 01384 ASSERT (WorkingSetIndex >= WorkingSetList->FirstDynamic); 01385 01386 // 01387 // Check to see if this is a page table with valid PTEs. 01388 // 01389 // Note, don't clear the access bit for page table pages 01390 // with valid PTEs as this could cause an access trap fault which 01391 // would not be handled (it is only handled for PTEs not PDEs). 01392 // 01393 01394 Pfn1 = MI_PFN_ELEMENT (PointerPte->u.Hard.PageFrameNumber); 01395 01396 LOCK_PFN (OldIrql); 01397 01398 // 01399 // If the PTE is a page table page with non-zero share count or 01400 // within the system cache with its reference count greater 01401 // than 0, don't remove it. 01402 // 01403 01404 if (WsInfo == &MmSystemCacheWs) { 01405 if (Pfn1->u3.e2.ReferenceCount > 1) { 01406 UNLOCK_PFN (OldIrql); 01407 return FALSE; 01408 } 01409 } else { 01410 if ((Pfn1->u2.ShareCount > 1) && 01411 (Pfn1->u3.e1.PrototypePte == 0)) { 01412 01413 #if DBG 01414 if (WsInfo->u.Flags.SessionSpace == 1) { 01415 ASSERT (MI_IS_SESSION_ADDRESS (Wsle[WorkingSetIndex].u1.VirtualAddress)); 01416 } 01417 else { 01418 ASSERT ((Wsle[WorkingSetIndex].u1.VirtualAddress >= (PVOID)PTE_BASE) && 01419 (Wsle[WorkingSetIndex].u1.VirtualAddress<= (PVOID)PDE_TOP)); 01420 } 01421 #endif 01422 01423 // 01424 // Don't remove page table pages from the working set until 01425 // all transition pages have exited. 01426 // 01427 01428 UNLOCK_PFN (OldIrql); 01429 return FALSE; 01430 } 01431 } 01432 01433 // 01434 // Found a candidate, remove the page from the working set. 01435 // 01436 01437 MiEliminateWorkingSetEntry (WorkingSetIndex, 01438 PointerPte, 01439 Pfn1, 01440 Wsle); 01441 01442 UNLOCK_PFN (OldIrql); 01443 01444 // 01445 // Remove the working set entry from the working set. 01446 // 01447 01448 MiRemoveWsle (WorkingSetIndex, WorkingSetList); 01449 01450 ASSERT (WorkingSetList->FirstFree >= WorkingSetList->FirstDynamic); 01451 01452 ASSERT (WorkingSetIndex >= WorkingSetList->FirstDynamic); 01453 01454 // 01455 // Put the entry on the free list and decrement the current 01456 // size. 01457 // 01458 01459 ASSERT ((WorkingSetList->FirstFree <= WorkingSetList->LastInitializedWsle) || 01460 (WorkingSetList->FirstFree == WSLE_NULL_INDEX)); 01461 Wsle[WorkingSetIndex].u1.Long = WorkingSetList->FirstFree << MM_FREE_WSLE_SHIFT; 01462 WorkingSetList->FirstFree = WorkingSetIndex; 01463 ASSERT ((WorkingSetList->FirstFree <= WorkingSetList->LastInitializedWsle) || 01464 (WorkingSetList->FirstFree == WSLE_NULL_INDEX)); 01465 01466 if (WsInfo->WorkingSetSize > WsInfo->MinimumWorkingSetSize) { 01467 MmPagesAboveWsMinimum -= 1; 01468 } 01469 WsInfo->WorkingSetSize -= 1; 01470 01471 #if 0 01472 if ((WsInfo == &MmSystemCacheWs) && 01473 (Pfn1->u3.e1.Modified == 1)) { 01474 MiDumpWsleInCacheBlock (PointerPte); 01475 } 01476 #endif //0 01477 return TRUE; 01478 }

PEVENT_COUNTER MiGetEventCounter  ) 
 

Definition at line 2377 of file sectsup.c.

References APC_LEVEL, ASSERT, _MMEVENT_COUNT_LIST::Count, _EVENT_COUNTER::Event, ExAllocatePoolWithTag, FALSE, KeClearEvent, KeInitializeEvent, _EVENT_COUNTER::ListEntry, _MMEVENT_COUNT_LIST::ListHead, LOCK_PFN, MM_PFN_LOCK_ASSERT, MmEventCountList, NonPagedPool, NULL, _EVENT_COUNTER::RefCount, and UNLOCK_PFN.

Referenced by MiCheckControlAreaStatus(), MiCheckPurgeAndUpMapCount(), and MmCreateSection().

02382 : 02383 02384 This function maintains a list of "events" to allow waiting 02385 on segment operations (deletion, creation, purging). 02386 02387 Arguments: 02388 02389 None. 02390 02391 Return Value: 02392 02393 Event to be used for waiting (stored into the control area) or NULL if 02394 no event could be allocated. 02395 02396 Environment: 02397 02398 Kernel mode, PFN lock held. 02399 02400 --*/ 02401 02402 { 02403 KIRQL OldIrql; 02404 PEVENT_COUNTER Support; 02405 PLIST_ENTRY NextEntry; 02406 02407 MM_PFN_LOCK_ASSERT(); 02408 02409 if (MmEventCountList.Count == 0) { 02410 ASSERT (IsListEmpty(&MmEventCountList.ListHead)); 02411 OldIrql = APC_LEVEL; 02412 UNLOCK_PFN (OldIrql); 02413 Support = ExAllocatePoolWithTag (NonPagedPool, 02414 sizeof(EVENT_COUNTER), 02415 'xEmM'); 02416 if (Support == NULL) { 02417 LOCK_PFN (OldIrql); 02418 return NULL; 02419 } 02420 KeInitializeEvent (&Support->Event, NotificationEvent, FALSE); 02421 LOCK_PFN (OldIrql); 02422 } else { 02423 ASSERT (!IsListEmpty(&MmEventCountList.ListHead)); 02424 MmEventCountList.Count -= 1; 02425 NextEntry = RemoveHeadList (&MmEventCountList.ListHead); 02426 Support = CONTAINING_RECORD (NextEntry, 02427 EVENT_COUNTER, 02428 ListEntry ); 02429 //ASSERT (Support->RefCount == 0); 02430 KeClearEvent (&Support->Event); 02431 } 02432 Support->RefCount = 1; 02433 Support->ListEntry.Flink = NULL; 02434 return Support; 02435 }

PMMADDRESS_NODE FASTCALL MiGetFirstNode IN PMMADDRESS_NODE  Root  ) 
 

Definition at line 424 of file addrsup.c.

References _MMADDRESS_NODE::LeftChild, and NULL.

00430 : 00431 00432 This function locates the virtual address descriptor which contains 00433 the address range which logically is first within the address space. 00434 00435 Arguments: 00436 00437 None. 00438 00439 Return Value: 00440 00441 Returns a pointer to the virtual address descriptor containing the 00442 first address range, NULL if none. 00443 00444 --*/ 00445 00446 { 00447 PMMADDRESS_NODE First; 00448 00449 First = Root; 00450 00451 if (First == (PMMADDRESS_NODE)NULL) { 00452 return (PMMADDRESS_NODE)NULL; 00453 } 00454 00455 while (First->LeftChild != (PMMADDRESS_NODE)NULL) { 00456 First = First->LeftChild; 00457 } 00458 00459 return First; 00460 }

PMMADDRESS_NODE MiGetLastNode IN PMMADDRESS_NODE  Root  ) 
 

PMMADDRESS_NODE FASTCALL MiGetNextNode IN PMMADDRESS_NODE  Node  ) 
 

Definition at line 297 of file addrsup.c.

References _MMADDRESS_NODE::LeftChild, NULL, _MMADDRESS_NODE::Parent, and _MMADDRESS_NODE::RightChild.

Referenced by MiFindEmptyAddressRangeInTree().

00303 : 00304 00305 This function locates the virtual address descriptor which contains 00306 the address range which logically follows the specified address range. 00307 00308 Arguments: 00309 00310 Node - Supplies a pointer to a virtual address descriptor. 00311 00312 Return Value: 00313 00314 Returns a pointer to the virtual address descriptor containing the 00315 next address range, NULL if none. 00316 00317 --*/ 00318 00319 { 00320 PMMADDRESS_NODE Next; 00321 PMMADDRESS_NODE Parent; 00322 PMMADDRESS_NODE Left; 00323 00324 Next = Node; 00325 00326 if (Next->RightChild == (PMMADDRESS_NODE)NULL) { 00327 00328 while ((Parent = Next->Parent) != (PMMADDRESS_NODE)NULL) { 00329 00330 // 00331 // Locate the first ancestor of this node of which this 00332 // node is the left child of and return that node as the 00333 // next element. 00334 // 00335 00336 if (Parent->LeftChild == Next) { 00337 return Parent; 00338 } 00339 00340 Next = Parent; 00341 00342 } 00343 00344 return (PMMADDRESS_NODE)NULL; 00345 } 00346 00347 // 00348 // A right child exists, locate the left most child of that right child. 00349 // 00350 00351 Next = Next->RightChild; 00352 00353 while ((Left = Next->LeftChild) != (PMMADDRESS_NODE)NULL) { 00354 Next = Left; 00355 } 00356 return Next; 00357 00358 }

PFN_NUMBER MiGetPageForHeader VOID   ) 
 

Definition at line 4378 of file creasect.c.

References CONSISTENCY_UNLOCK_PFN, LOCK_PFN, MI_PAGE_COLOR_VA_PROCESS, MI_PFN_ELEMENT, MI_SET_PFN_DELETED, MiEnsureAvailablePageOrWait(), MiRemoveAnyPage(), _EPROCESS::NextPageColor, NULL, _MMPFN::OriginalPte, PsGetCurrentProcess, _MMPFN::PteAddress, _MMPFN::u3, UNLOCK_PFN, X64K, and ZeroPte.

Referenced by MiCheckForCrashDump(), and MiCreateImageFileMap().

04384 : 04385 04386 This non-pagable function acquires the PFN lock, removes 04387 a page and updates the PFN database as though the page was 04388 ready to be deleted if the reference count is decremented. 04389 04390 Arguments: 04391 04392 None. 04393 04394 Return Value: 04395 04396 Returns the physical page frame number. 04397 04398 --*/ 04399 04400 { 04401 KIRQL OldIrql; 04402 PFN_NUMBER PageFrameNumber; 04403 PMMPFN Pfn1; 04404 PEPROCESS Process; 04405 ULONG PageColor; 04406 04407 Process = PsGetCurrentProcess(); 04408 PageColor = MI_PAGE_COLOR_VA_PROCESS ((PVOID)X64K, 04409 &Process->NextPageColor); 04410 04411 // 04412 // Lock the PFN database and get a page. 04413 // 04414 04415 LOCK_PFN (OldIrql); 04416 04417 MiEnsureAvailablePageOrWait (NULL, NULL); 04418 04419 // 04420 // Remove page for 64k alignment. 04421 // 04422 04423 PageFrameNumber = MiRemoveAnyPage (PageColor); 04424 04425 // 04426 // Increment the reference count for the page so the 04427 // paging I/O will work, and so this page cannot be stolen from us. 04428 // 04429 04430 Pfn1 = MI_PFN_ELEMENT (PageFrameNumber); 04431 Pfn1->u3.e2.ReferenceCount += 1; 04432 04433 #ifndef PFN_CONSISTENCY 04434 // 04435 // Don't need the PFN lock for the fields below... 04436 // 04437 UNLOCK_PFN (OldIrql); 04438 #endif 04439 04440 Pfn1->OriginalPte = ZeroPte; 04441 Pfn1->PteAddress = (PVOID) (ULONG_PTR)X64K; 04442 MI_SET_PFN_DELETED (Pfn1); 04443 04444 CONSISTENCY_UNLOCK_PFN (OldIrql); 04445 04446 return PageFrameNumber; 04447 }

ULONG MiGetPageProtection IN PMMPTE  PointerPte,
IN PEPROCESS  Process
 

Definition at line 1874 of file protect.c.

References Index, KSTACK_POOL_START, MI_CONVERT_FROM_PTE_PROTECTION, MI_IS_PTE_PROTOTYPE, MI_PFN_ELEMENT, MI_PTE_LOOKUP_NEEDED, MiCaptureSystemPte(), MiGetVirtualAddressMappedByPte, MiLocateWsle(), MiNumberOfExtraSystemPdes, MiPteToProto, MM_VA_MAPPED_BY_PDE, MmWorkingSetList, MmWsle, _MMPFN::OriginalPte, PAGED_CODE, _MMPTE::u, _MMPFN::u1, and _MMPFN::u3.

Referenced by MiProtectVirtualMemory(), MiQueryAddressState(), MiSetProtectionOnSection(), and NtAllocateVirtualMemory().

01881 : 01882 01883 This routine returns the page protection of a non-zero PTE. 01884 It may release and reacquire the working set mutex. 01885 01886 Arguments: 01887 01888 PointerPte - Supplies a pointer to a non-zero PTE. 01889 01890 Return Value: 01891 01892 Returns the protection code. 01893 01894 Environment: 01895 01896 Kernel mode, working set and address creation mutex held. 01897 Note, that the address creation mutex does not need to be held 01898 if the working set mutex does not need to be released in the 01899 case of a prototype PTE. 01900 01901 --*/ 01902 01903 { 01904 01905 MMPTE PteContents; 01906 MMPTE ProtoPteContents; 01907 PMMPFN Pfn1; 01908 PMMPTE ProtoPteAddress; 01909 PVOID Va; 01910 ULONG Index; 01911 01912 PAGED_CODE(); 01913 01914 PteContents = *PointerPte; 01915 01916 if ((PteContents.u.Soft.Valid == 0) && (PteContents.u.Soft.Prototype == 1)) { 01917 01918 // 01919 // This pte is in prototype format, the protection is 01920 // stored in the prototype PTE. 01921 // 01922 01923 if (MI_IS_PTE_PROTOTYPE(PointerPte) || 01924 #ifdef _X86_ 01925 (MiNumberOfExtraSystemPdes && (PointerPte >= (PMMPTE)KSTACK_POOL_START && PointerPte < (PMMPTE)(KSTACK_POOL_START + MiNumberOfExtraSystemPdes * MM_VA_MAPPED_BY_PDE))) || 01926 #endif 01927 (PteContents.u.Soft.PageFileHigh == MI_PTE_LOOKUP_NEEDED)) { 01928 01929 // 01930 // The protection is within this PTE. 01931 // 01932 01933 return MI_CONVERT_FROM_PTE_PROTECTION ( 01934 PteContents.u.Soft.Protection); 01935 } 01936 01937 ProtoPteAddress = MiPteToProto (PointerPte); 01938 01939 // 01940 // Capture protopte PTE contents. 01941 // 01942 01943 ProtoPteContents = MiCaptureSystemPte (ProtoPteAddress, Process); 01944 01945 // 01946 // The working set mutex may have been released and the 01947 // page may no longer be in prototype format, get the 01948 // new contents of the PTE and obtain the protection mask. 01949 // 01950 01951 PteContents = MiCaptureSystemPte (PointerPte, Process); 01952 } 01953 01954 if ((PteContents.u.Soft.Valid == 0) && (PteContents.u.Soft.Prototype == 1)) { 01955 01956 // 01957 // Pte is still prototype, return the protection captured 01958 // from the prototype PTE. 01959 // 01960 01961 if (ProtoPteContents.u.Hard.Valid == 1) { 01962 01963 // 01964 // The prototype PTE is valid, get the protection from 01965 // the PFN database. 01966 // 01967 01968 Pfn1 = MI_PFN_ELEMENT (ProtoPteContents.u.Hard.PageFrameNumber); 01969 return MI_CONVERT_FROM_PTE_PROTECTION( 01970 Pfn1->OriginalPte.u.Soft.Protection); 01971 01972 } else { 01973 01974 // 01975 // The prototype PTE is not valid, return the protection from the 01976 // PTE. 01977 // 01978 01979 return MI_CONVERT_FROM_PTE_PROTECTION ( 01980 ProtoPteContents.u.Soft.Protection); 01981 } 01982 } 01983 01984 if (PteContents.u.Hard.Valid == 1) { 01985 01986 // 01987 // The page is valid, the protection field is either in the 01988 // PFN database original PTE element or the WSLE. If 01989 // the page is private, get it from the PFN original PTE 01990 // element, else use the WSLE. 01991 // 01992 01993 Pfn1 = MI_PFN_ELEMENT (PteContents.u.Hard.PageFrameNumber); 01994 01995 if ((Pfn1->u3.e1.PrototypePte == 0) || 01996 #ifdef _X86_ 01997 (MiNumberOfExtraSystemPdes && (PointerPte >= (PMMPTE)KSTACK_POOL_START && PointerPte < (PMMPTE)(KSTACK_POOL_START + MiNumberOfExtraSystemPdes * MM_VA_MAPPED_BY_PDE))) || 01998 #endif 01999 (MI_IS_PTE_PROTOTYPE(PointerPte))) { 02000 02001 // 02002 // This is a private PTE or the PTE address is that of a 02003 // prototype PTE, hence the protection is in 02004 // the original PTE. 02005 // 02006 02007 return MI_CONVERT_FROM_PTE_PROTECTION( 02008 Pfn1->OriginalPte.u.Soft.Protection); 02009 } 02010 02011 // 02012 // The PTE was a hardware PTE, get the protection 02013 // from the WSLE. 02014 02015 Va = (PULONG)MiGetVirtualAddressMappedByPte (PointerPte); 02016 Index = MiLocateWsle ((PVOID)Va, MmWorkingSetList, 02017 Pfn1->u1.WsIndex); 02018 02019 return MI_CONVERT_FROM_PTE_PROTECTION (MmWsle[Index].u1.e1.Protection); 02020 } 02021 02022 // 02023 // PTE is either demand zero or transition, in either 02024 // case protection is in PTE. 02025 // 02026 02027 return MI_CONVERT_FROM_PTE_PROTECTION (PteContents.u.Soft.Protection); 02028 02029 }

PMMADDRESS_NODE FASTCALL MiGetPreviousNode IN PMMADDRESS_NODE  Node  ) 
 

Definition at line 362 of file addrsup.c.

References _MMADDRESS_NODE::LeftChild, NULL, _MMADDRESS_NODE::Parent, and _MMADDRESS_NODE::RightChild.

Referenced by MiFindEmptyAddressRangeDownTree().

00368 : 00369 00370 This function locates the virtual address descriptor which contains 00371 the address range which logically precedes the specified virtual 00372 address descriptor. 00373 00374 Arguments: 00375 00376 Node - Supplies a pointer to a virtual address descriptor. 00377 00378 Return Value: 00379 00380 Returns a pointer to the virtual address descriptor containing the 00381 next address range, NULL if none. 00382 00383 --*/ 00384 00385 { 00386 PMMADDRESS_NODE Previous; 00387 00388 Previous = Node; 00389 00390 if (Previous->LeftChild == (PMMADDRESS_NODE)NULL) { 00391 00392 00393 while (Previous->Parent != (PMMADDRESS_NODE)NULL) { 00394 00395 // 00396 // Locate the first ancestor of this node of which this 00397 // node is the right child of and return that node as the 00398 // Previous element. 00399 // 00400 00401 if (Previous->Parent->RightChild == Previous) { 00402 return Previous->Parent; 00403 } 00404 00405 Previous = Previous->Parent; 00406 00407 } 00408 return (PMMADDRESS_NODE)NULL; 00409 } 00410 00411 // 00412 // A left child exists, locate the right most child of that left child. 00413 // 00414 00415 Previous = Previous->LeftChild; 00416 while (Previous->RightChild != (PMMADDRESS_NODE)NULL) { 00417 Previous = Previous->RightChild; 00418 } 00419 return Previous; 00420 }

PMMPTE FASTCALL MiGetProtoPteAddressExtended IN PMMVAD  Vad,
IN ULONG_PTR  Vpn
 

Definition at line 685 of file extsect.c.

References ASSERT, _SUBSECTION::NextSubsection, NULL, _SUBSECTION::PtesInSubsection, _SUBSECTION::SubsectionBase, and _CONTROL_AREA::u.

00692 : 00693 00694 This function calculates the address of the prototype PTE 00695 for the corresponding virtual address. 00696 00697 Arguments: 00698 00699 00700 Vad - Supplies a pointer to the virtual address desciptor which 00701 encompasses the virtual address. 00702 00703 Vpn - Supplies the virtual page number to locate a prototype PTE 00704 for. 00705 00706 Return Value: 00707 00708 The corresponding prototype PTE address. 00709 00710 --*/ 00711 00712 { 00713 PSUBSECTION Subsection; 00714 PCONTROL_AREA ControlArea; 00715 ULONG PteOffset; 00716 00717 ControlArea = Vad->ControlArea; 00718 00719 if (ControlArea->u.Flags.GlobalOnlyPerSession == 0) { 00720 Subsection = (PSUBSECTION)(ControlArea + 1); 00721 } 00722 else { 00723 Subsection = (PSUBSECTION)((PLARGE_CONTROL_AREA)ControlArea + 1); 00724 } 00725 00726 // 00727 // Locate the subsection which contains the First Prototype PTE 00728 // for this VAD. 00729 // 00730 00731 while ((Vad->FirstPrototypePte < Subsection->SubsectionBase) || 00732 (Vad->FirstPrototypePte >= 00733 &Subsection->SubsectionBase[Subsection->PtesInSubsection])) { 00734 00735 // 00736 // Get the next subsection. 00737 // 00738 00739 Subsection = Subsection->NextSubsection; 00740 if (Subsection == NULL) { 00741 return NULL; 00742 } 00743 } 00744 00745 // 00746 // How many PTEs beyond this subsection must we go? 00747 // 00748 00749 PteOffset = (ULONG) (((Vpn - Vad->StartingVpn) + 00750 (ULONG)(Vad->FirstPrototypePte - Subsection->SubsectionBase)) - 00751 Subsection->PtesInSubsection); 00752 00753 // DbgPrint("map extended subsection offset = %lx\n",PteOffset); 00754 00755 ASSERT (PteOffset < 0xF0000000); 00756 00757 PteOffset += Subsection->PtesInSubsection; 00758 00759 // 00760 // Locate the subsection which contains the prototype PTEs. 00761 // 00762 00763 while (PteOffset >= Subsection->PtesInSubsection) { 00764 PteOffset -= Subsection->PtesInSubsection; 00765 Subsection = Subsection->NextSubsection; 00766 if (Subsection == NULL) { 00767 return NULL; 00768 } 00769 } 00770 00771 // 00772 // The PTEs are in this subsection. 00773 // 00774 00775 ASSERT (PteOffset < Subsection->PtesInSubsection); 00776 00777 return &Subsection->SubsectionBase[PteOffset]; 00778 00779 }

PSUBSECTION MiGetSubsectionAndProtoFromPte IN PMMPTE  PointerPte,
IN PMMPTE ProtoPte,
IN PEPROCESS  Process
 

NTSTATUS MiGetWritablePagesInSection IN PSECTION  Section,
OUT PULONG  WritablePages
 

Definition at line 4868 of file creasect.c.

References ASSERT, MI_ROUND_TO_SIZE, MiGetImageProtection(), MM_PROTECTION_WRITE_MASK, MmMapViewOfSection(), MmUnmapViewOfSection(), NT_SUCCESS, NTSTATUS(), NULL, PAGE_SHIFT, PAGE_SIZE, PAGED_CODE, PsGetCurrentProcess, and Status.

Referenced by MiSessionWideReserveImageAddress().

04875 : 04876 04877 This routine calculates the number of writable pages in the image. 04878 04879 Arguments: 04880 04881 Section - Supplies the section for the image. 04882 04883 WritablePages - Supplies a pointer to fill with the 04884 number of writable pages. 04885 04886 Return Value: 04887 04888 STATUS_SUCCESS if all went well, otherwise various NTSTATUS error codes. 04889 04890 Environment: 04891 04892 Kernel mode, APC_LEVEL and below, MmSystemLoadLock held. 04893 04894 --*/ 04895 04896 { 04897 NTSTATUS Status; 04898 PVOID ViewBase; 04899 SIZE_T ViewSize; 04900 ULONG PagesInSubsection; 04901 ULONG Protection; 04902 ULONG NumberOfSubsections; 04903 ULONG OffsetToSectionTable; 04904 ULONG SectionVirtualSize; 04905 PEPROCESS Process; 04906 LARGE_INTEGER SectionOffset; 04907 PIMAGE_DOS_HEADER DosHeader; 04908 PIMAGE_NT_HEADERS NtHeader; 04909 PIMAGE_SECTION_HEADER SectionTableEntry; 04910 04911 PAGED_CODE(); 04912 04913 ViewBase = NULL; 04914 ViewSize = 0; 04915 SectionOffset.QuadPart = 0; 04916 04917 *WritablePages = 0; 04918 04919 Process = PsGetCurrentProcess(); 04920 04921 Status = MmMapViewOfSection (Section, 04922 Process, 04923 &ViewBase, 04924 0, 04925 0, 04926 &SectionOffset, 04927 &ViewSize, 04928 ViewUnmap, 04929 0, 04930 PAGE_EXECUTE); 04931 04932 if (!NT_SUCCESS(Status)) { 04933 return Status; 04934 } 04935 04936 // 04937 // The DLL is mapped as a data file not as an image. Pull apart the 04938 // executable header. The security checks have already been 04939 // done as part of creating the section in the first place. 04940 // 04941 04942 DosHeader = (PIMAGE_DOS_HEADER) ViewBase; 04943 04944 ASSERT (DosHeader->e_magic == IMAGE_DOS_SIGNATURE); 04945 04946 #ifndef i386 04947 ASSERT (((ULONG)DosHeader->e_lfanew & 3) == 0); 04948 #endif 04949 04950 ASSERT ((ULONG)DosHeader->e_lfanew <= ViewSize); 04951 04952 NtHeader = (PIMAGE_NT_HEADERS)((PCHAR)DosHeader + 04953 (ULONG)DosHeader->e_lfanew); 04954 04955 OffsetToSectionTable = sizeof(ULONG) + 04956 sizeof(IMAGE_FILE_HEADER) + 04957 NtHeader->FileHeader.SizeOfOptionalHeader; 04958 04959 SectionTableEntry = (PIMAGE_SECTION_HEADER)((PCHAR)NtHeader + 04960 OffsetToSectionTable); 04961 04962 NumberOfSubsections = NtHeader->FileHeader.NumberOfSections; 04963 04964 while (NumberOfSubsections > 0) { 04965 04966 Protection = MiGetImageProtection (SectionTableEntry->Characteristics); 04967 04968 if (Protection & MM_PROTECTION_WRITE_MASK) { 04969 04970 // 04971 // Handle the case where the virtual size is 0. 04972 // 04973 04974 if (SectionTableEntry->Misc.VirtualSize == 0) { 04975 SectionVirtualSize = SectionTableEntry->SizeOfRawData; 04976 } else { 04977 SectionVirtualSize = SectionTableEntry->Misc.VirtualSize; 04978 } 04979 04980 PagesInSubsection = 04981 MI_ROUND_TO_SIZE (SectionVirtualSize, PAGE_SIZE) >> PAGE_SHIFT; 04982 04983 *WritablePages += PagesInSubsection; 04984 } 04985 04986 SectionTableEntry += 1; 04987 NumberOfSubsections -= 1; 04988 } 04989 04990 Status = MmUnmapViewOfSection (Process, ViewBase); 04991 04992 ASSERT (NT_SUCCESS(Status)); 04993 04994 return Status; 04995 }

VOID MiGrowWsleHash IN PMMSUPPORT  WsInfo  ) 
 

Definition at line 3300 of file wslist.c.

References ASSERT, ASSERT32, ASSERT64, Count, FALSE, _MMWSL::HashTable, _MMWSL::HashTableSize, _MMWSL::HashTableStart, _MMWSL::HighestPermittedHashAddress, _MMWSL::LastInitializedWsle, LOCK_PFN, _MMWSLE::Long, MI_WSLE_HASH, MiAddWsleHash(), MiCheckWsleHash(), MiDeletePte(), MiGetPdeAddress, MiGetPpeAddress, MiGetPteAddress, MiGetVirtualAddressMappedByPte, MiIsPteOnPdeBoundary, MmSystemCacheWs, MMWSLE_HASH, _MMWSL::NonDirectCount, NULL, _EPROCESS::NumberOfPrivatePages, PAGE_ALIGN, PAGE_SHIFT, PAGE_SIZE, PsGetCurrentProcess, Size, TRUE, _MMPTE::u, _MMSUPPORT::u, _MMWSLE::u1, UNLOCK_PFN, _MMWSLE::VirtualAddress, and _MMWSL::Wsle.

Referenced by MiInitializeSystemCache(), MiInitializeWorkingSetList(), MiMakeSpecialPoolPagable(), MiSessionInitializeWorkingSetList(), MmAccessFault(), and MmAdjustWorkingSetSize().

03306 : 03307 03308 This function grows (or adds) a hash table to the working set list 03309 to allow direct indexing for WSLEs than cannot be located via the 03310 PFN database WSINDEX field. 03311 03312 The hash table is located AFTER the WSLE array and the pages are 03313 locked into the working set just like standard WSLEs. 03314 03315 Note that the hash table is expanded by setting the hash table 03316 field in the working set to NULL, but leaving the size as non-zero. 03317 This indicates that the hash should be expanded and the initial 03318 portion of the table zeroed. 03319 03320 Arguments: 03321 03322 WsInfo - Supplies a pointer to the working set info block for the 03323 process (or system cache). 03324 03325 Return Value: 03326 03327 None. 03328 03329 Environment: 03330 03331 Kernel mode, APCs disabled, working set lock held. 03332 03333 --*/ 03334 { 03335 LONG Size; 03336 PMMWSLE Wsle; 03337 PMMPTE StartPte; 03338 PMMPTE EndPte; 03339 PMMPTE PointerPte; 03340 PMMPTE PointerPde; 03341 PMMPTE PointerPpe; 03342 PMMPTE AllocatedPde; 03343 PMMPTE AllocatedPpe; 03344 ULONG First; 03345 ULONG Hash; 03346 ULONG NewSize; 03347 PMMWSLE_HASH Table; 03348 PMMWSLE_HASH OriginalTable; 03349 ULONG j; 03350 PMMWSL WorkingSetList; 03351 KIRQL OldIrql; 03352 ULONG Count; 03353 LOGICAL LoopStart; 03354 PVOID EntryHashTableEnd; 03355 PVOID TempVa; 03356 PEPROCESS CurrentProcess; 03357 03358 WorkingSetList = WsInfo->VmWorkingSetList; 03359 Wsle = WorkingSetList->Wsle; 03360 03361 Table = WorkingSetList->HashTable; 03362 OriginalTable = WorkingSetList->HashTable; 03363 03364 First = WorkingSetList->HashTableSize; 03365 03366 if (Table == NULL) { 03367 03368 NewSize = PtrToUlong(PAGE_ALIGN (((1 + WorkingSetList->NonDirectCount) * 03369 2 * sizeof(MMWSLE_HASH)) + PAGE_SIZE - 1)); 03370 03371 // 03372 // Note that the Table may be NULL and the HashTableSize/PTEs nonzero 03373 // in the case where the hash has been contracted. 03374 // 03375 03376 j = First * sizeof(MMWSLE_HASH); 03377 03378 // 03379 // Don't try for additional hash pages if we already have 03380 // the right amount (or too many). 03381 // 03382 03383 if ((j + PAGE_SIZE > NewSize) && (j != 0)) { 03384 return; 03385 } 03386 03387 Table = (PMMWSLE_HASH)(WorkingSetList->HashTableStart); 03388 EntryHashTableEnd = &Table[WorkingSetList->HashTableSize]; 03389 03390 WorkingSetList->HashTableSize = 0; 03391 03392 } else { 03393 03394 // 03395 // Attempt to add 4 pages, make sure the working set list has 03396 // 4 free entries. 03397 // 03398 03399 if ((WorkingSetList->LastInitializedWsle + 5) > WsInfo->WorkingSetSize) { 03400 NewSize = PAGE_SIZE * 4; 03401 } else { 03402 NewSize = PAGE_SIZE; 03403 } 03404 EntryHashTableEnd = &Table[WorkingSetList->HashTableSize]; 03405 } 03406 03407 if ((PCHAR)EntryHashTableEnd + NewSize > (PCHAR)WorkingSetList->HighestPermittedHashAddress) { 03408 NewSize = 03409 (ULONG)((PCHAR)(WorkingSetList->HighestPermittedHashAddress) - 03410 ((PCHAR)EntryHashTableEnd)); 03411 if (NewSize == 0) { 03412 if (OriginalTable == NULL) { 03413 WorkingSetList->HashTableSize = First; 03414 } 03415 return; 03416 } 03417 } 03418 03419 ASSERT64 ((MiGetPpeAddress(EntryHashTableEnd)->u.Hard.Valid == 0) || 03420 (MiGetPdeAddress(EntryHashTableEnd)->u.Hard.Valid == 0) || 03421 (MiGetPteAddress(EntryHashTableEnd)->u.Hard.Valid == 0)); 03422 03423 ASSERT32 (MiGetPteAddress(EntryHashTableEnd)->u.Hard.Valid == 0); 03424 03425 Size = NewSize; 03426 PointerPte = MiGetPteAddress (EntryHashTableEnd); 03427 StartPte = PointerPte; 03428 EndPte = PointerPte + (NewSize >> PAGE_SHIFT); 03429 03430 #if defined (_WIN64) 03431 LoopStart = TRUE; 03432 AllocatedPde = NULL; 03433 AllocatedPpe = NULL; 03434 #endif 03435 03436 do { 03437 03438 #if defined (_WIN64) 03439 if (LoopStart == TRUE || MiIsPteOnPdeBoundary(PointerPte)) { 03440 03441 PointerPpe = MiGetPdeAddress(PointerPte); 03442 PointerPde = MiGetPteAddress(PointerPte); 03443 03444 if (PointerPpe->u.Hard.Valid == 0) { 03445 if (MiAddWsleHash (WsInfo, PointerPpe) == FALSE) { 03446 break; 03447 } 03448 AllocatedPpe = PointerPpe; 03449 } 03450 03451 if (PointerPde->u.Hard.Valid == 0) { 03452 if (MiAddWsleHash (WsInfo, PointerPde) == FALSE) { 03453 break; 03454 } 03455 AllocatedPde = PointerPde; 03456 } 03457 03458 LoopStart = FALSE; 03459 } 03460 else { 03461 AllocatedPde = NULL; 03462 AllocatedPpe = NULL; 03463 } 03464 #endif 03465 03466 if (PointerPte->u.Hard.Valid == 0) { 03467 if (MiAddWsleHash (WsInfo, PointerPte) == FALSE) { 03468 break; 03469 } 03470 } 03471 03472 PointerPte += 1; 03473 Size -= PAGE_SIZE; 03474 } while (Size > 0); 03475 03476 // 03477 // If MiAddWsleHash was unable to allocate memory above, then roll back 03478 // any extra PPEs & PDEs that may have been created. Note NewSize must 03479 // be recalculated to handle the fact that memory may have run out. 03480 // 03481 03482 #if !defined (_WIN64) 03483 if (PointerPte == StartPte) { 03484 if (OriginalTable == NULL) { 03485 WorkingSetList->HashTableSize = First; 03486 } 03487 return; 03488 } 03489 #else 03490 if (PointerPte != EndPte) { 03491 03492 // 03493 // Clean up the last allocated PPE/PDE as they are not needed. 03494 // Note that the system cache and the session space working sets 03495 // have no current process (which MiDeletePte requires) which is 03496 // needed for WSLE and PrivatePages adjustments. 03497 // 03498 03499 if (WsInfo != &MmSystemCacheWs && WsInfo->u.Flags.SessionSpace == 0) { 03500 CurrentProcess = PsGetCurrentProcess(); 03501 03502 if (AllocatedPde != NULL) { 03503 ASSERT (AllocatedPde->u.Hard.Valid == 1); 03504 TempVa = MiGetVirtualAddressMappedByPte(AllocatedPde); 03505 LOCK_PFN (OldIrql); 03506 MiDeletePte (AllocatedPde, 03507 TempVa, 03508 FALSE, 03509 CurrentProcess, 03510 NULL, 03511 NULL); 03512 // 03513 // Add back in the private page MiDeletePte subtracted. 03514 // 03515 03516 CurrentProcess->NumberOfPrivatePages += 1; 03517 UNLOCK_PFN (OldIrql); 03518 } 03519 03520 if (AllocatedPpe != NULL) { 03521 ASSERT (AllocatedPpe->u.Hard.Valid == 1); 03522 TempVa = MiGetVirtualAddressMappedByPte(AllocatedPpe); 03523 LOCK_PFN (OldIrql); 03524 MiDeletePte (AllocatedPpe, 03525 TempVa, 03526 FALSE, 03527 CurrentProcess, 03528 NULL, 03529 NULL); 03530 // 03531 // Add back in the private page MiDeletePte subtracted. 03532 // 03533 03534 CurrentProcess->NumberOfPrivatePages += 1; 03535 UNLOCK_PFN (OldIrql); 03536 } 03537 } 03538 03539 if (PointerPte == StartPte) { 03540 if (OriginalTable == NULL) { 03541 WorkingSetList->HashTableSize = First; 03542 } 03543 } 03544 03545 return; 03546 } 03547 #endif 03548 03549 NewSize = (ULONG)((PointerPte - StartPte) << PAGE_SHIFT); 03550 03551 ASSERT ((MiGetVirtualAddressMappedByPte(PointerPte) == WorkingSetList->HighestPermittedHashAddress) || 03552 (PointerPte->u.Hard.Valid == 0)); 03553 03554 WorkingSetList->HashTableSize = First + NewSize / sizeof (MMWSLE_HASH); 03555 WorkingSetList->HashTable = Table; 03556 03557 ASSERT ((&Table[WorkingSetList->HashTableSize] == WorkingSetList->HighestPermittedHashAddress) || 03558 (MiGetPteAddress(&Table[WorkingSetList->HashTableSize])->u.Hard.Valid == 0)); 03559 03560 if (First != 0) { 03561 RtlZeroMemory (Table, First * sizeof(MMWSLE_HASH)); 03562 } 03563 03564 // 03565 // Fill hash table 03566 // 03567 03568 j = 0; 03569 Count = WorkingSetList->NonDirectCount; 03570 03571 Size = WorkingSetList->HashTableSize; 03572 03573 do { 03574 if ((Wsle[j].u1.e1.Valid == 1) && 03575 (Wsle[j].u1.e1.Direct == 0)) { 03576 03577 // 03578 // Hash this. 03579 // 03580 03581 Count -= 1; 03582 03583 Hash = MI_WSLE_HASH(Wsle[j].u1.Long, WorkingSetList); 03584 03585 while (Table[Hash].Key != 0) { 03586 Hash += 1; 03587 if (Hash >= (ULONG)Size) { 03588 Hash = 0; 03589 } 03590 } 03591 03592 Table[Hash].Key = Wsle[j].u1.Long & ~(PAGE_SIZE - 1); 03593 Table[Hash].Index = j; 03594 #if DBG 03595 PointerPte = MiGetPteAddress(Wsle[j].u1.VirtualAddress); 03596 ASSERT (PointerPte->u.Hard.Valid); 03597 #endif //DBG 03598 03599 } 03600 ASSERT (j <= WorkingSetList->LastEntry); 03601 j += 1; 03602 } while (Count); 03603 03604 #if DBG 03605 MiCheckWsleHash (WorkingSetList); 03606 #endif //DBG 03607 return; 03608 }

VOID MiInitializeCopyOnWritePfn IN PFN_NUMBER  PageFrameIndex,
IN PMMPTE  PointerPte,
IN WSLE_NUMBER  WorkingSetIndex,
IN PVOID  SessionSpace
 

Definition at line 3764 of file pagfault.c.

References ActiveAndValid, ASSERT, _MMWSLE::e1, KeBugCheckEx(), MI_GET_PAGE_FRAME_FROM_PTE, MI_MAKE_PROTECT_NOT_WRITE_COPY, MI_PFN_ELEMENT, MiCheckPdeForPagedPool(), MiGetPteAddress, MiGetVirtualAddressMappedByPte, MM_EXECUTE_READWRITE, MM_PFN_LOCK_ASSERT, MmWsle, NT_SUCCESS, _MMPFN::OriginalPte, _MMWSLENTRY::Protection, _MMPFN::PteAddress, _MMPFN::PteFrame, _MMPTE::u, _MMWSLE::u1, _MMPFN::u1, _MMPFN::u2, _MMPFN::u3, and _MM_SESSION_SPACE::Wsle.

Referenced by MiCopyOnWrite(), and MiSessionCopyOnWrite().

03773 : 03774 03775 This function initializes the specified PFN element to the 03776 active and valid state for a copy on write operation. 03777 03778 In this case the page table page which contains the PTE has 03779 the proper ShareCount. 03780 03781 Arguments: 03782 03783 PageFrameIndex - Supplies the page frame number to initialize. 03784 03785 PointerPte - Supplies the pointer to the PTE which caused the 03786 page fault. 03787 03788 WorkingSetIndex - Supplies the working set index for the corresponding 03789 virtual address. 03790 03791 SessionPointer - Supplies the session space pointer if this fault is for 03792 a session space page or NULL if this is for a user page. 03793 03794 03795 Return Value: 03796 03797 None. 03798 03799 Environment: 03800 03801 Kernel mode, APCs disabled, PFN mutex held. 03802 03803 --*/ 03804 03805 { 03806 PMMPFN Pfn1; 03807 PMMPTE PteFramePointer; 03808 PFN_NUMBER PteFramePage; 03809 PVOID VirtualAddress; 03810 PMM_SESSION_SPACE SessionSpace; 03811 03812 Pfn1 = MI_PFN_ELEMENT (PageFrameIndex); 03813 Pfn1->PteAddress = PointerPte; 03814 03815 // 03816 // Get the protection for the page. 03817 // 03818 03819 VirtualAddress = MiGetVirtualAddressMappedByPte (PointerPte); 03820 03821 Pfn1->OriginalPte.u.Long = 0; 03822 03823 if (SessionPointer) { 03824 Pfn1->OriginalPte.u.Soft.Protection = MM_EXECUTE_READWRITE; 03825 SessionSpace = (PMM_SESSION_SPACE) SessionPointer; 03826 SessionSpace->Wsle[WorkingSetIndex].u1.e1.Protection = 03827 MM_EXECUTE_READWRITE; 03828 } 03829 else { 03830 Pfn1->OriginalPte.u.Soft.Protection = 03831 MI_MAKE_PROTECT_NOT_WRITE_COPY ( 03832 MmWsle[WorkingSetIndex].u1.e1.Protection); 03833 } 03834 03835 ASSERT (Pfn1->u3.e2.ReferenceCount == 0); 03836 Pfn1->u3.e2.ReferenceCount += 1; 03837 Pfn1->u2.ShareCount += 1; 03838 Pfn1->u3.e1.PageLocation = ActiveAndValid; 03839 Pfn1->u1.WsIndex = WorkingSetIndex; 03840 03841 // 03842 // Determine the page frame number of the page table page which 03843 // contains this PTE. 03844 // 03845 03846 PteFramePointer = MiGetPteAddress(PointerPte); 03847 if (PteFramePointer->u.Hard.Valid == 0) { 03848 #if !defined (_WIN64) 03849 if (!NT_SUCCESS(MiCheckPdeForPagedPool (PointerPte))) { 03850 #endif 03851 KeBugCheckEx (MEMORY_MANAGEMENT, 03852 0x61940, 03853 (ULONG_PTR)PointerPte, 03854 (ULONG_PTR)PteFramePointer->u.Long, 03855 (ULONG_PTR)MiGetVirtualAddressMappedByPte(PointerPte)); 03856 #if !defined (_WIN64) 03857 } 03858 #endif 03859 } 03860 03861 PteFramePage = MI_GET_PAGE_FRAME_FROM_PTE (PteFramePointer); 03862 ASSERT (PteFramePage != 0); 03863 03864 Pfn1->PteFrame = PteFramePage; 03865 03866 #if PFN_CONSISTENCY 03867 MM_PFN_LOCK_ASSERT(); 03868 03869 Pfn1->u3.e1.PageTablePage = 0; 03870 #endif 03871 03872 // 03873 // Set the modified flag in the PFN database as we are writing 03874 // into this page and the dirty bit is already set in the PTE. 03875 // 03876 03877 Pfn1->u3.e1.Modified = 1; 03878 03879 return; 03880 }

LOGICAL MiInitializeDriverVerifierList IN PLOADER_PARAMETER_BLOCK  LoaderBlock  ) 
 

Definition at line 3121 of file verifier.c.

References _MI_VERIFIER_DRIVER_ENTRY::BaseName, End, ExAllocatePoolWithTag, ExInitializeFastMutex, FALSE, _MI_VERIFIER_DRIVER_ENTRY::Flags, IoVerifierInit(), IOVERIFIERINIT_EVERYTHING_TRACKED, IOVERIFIERINIT_PHASE0, IOVERIFIERINIT_VERIFIER_DRIVER_LIST, KeInitializeSpinLock(), KeQueryPerformanceCounter(), KernelVerifier, L, MI_VERIFIER_DRIVER_ENTRY, MiApplyDriverVerifier(), MiSuspectDriverList, MiTriageAddDrivers(), MiVerifierDriverAddedThunkListHead, MiVerifyAllDrivers, MiVerifyRandomDrivers, MmDontVerifyRandomDrivers, MmVerifierData, MmVerifyDriverBuffer, MmVerifyDriverBufferLength, MmVerifyDriverLevel, NonPagedPool, NULL, RtlEqualUnicodeString(), RtlInitUnicodeString(), Start, TRUE, UNICODE_WHITESPACE, USHORT, VerifierListLock, VerifierModifyableOptions, VerifierPoolLock, VerifierPoolMutex, VI_VERIFYING_DIRECTLY, ViBadMapperLock, ViInitializeEntry(), and ViInsertVerifierEntry().

Referenced by MmInitSystem().

03127 : 03128 03129 Parse the registry setting and set up the list of driver names that will 03130 be put through the validation process. 03131 03132 Walk the loaded module list and thunk any drivers that need/deserve it. 03133 03134 Arguments: 03135 03136 None. 03137 03138 Return Value: 03139 03140 TRUE if successful, FALSE if not. 03141 03142 Environment: 03143 03144 Kernel mode, Phase 0 Initialization. 03145 03146 Nonpaged (but not paged) pool exists. 03147 03148 The PsLoadedModuleList has not been set up yet although the boot drivers 03149 have been relocated to their final resting places. 03150 03151 --*/ 03152 03153 { 03154 ULONG i; 03155 PLIST_ENTRY NextEntry; 03156 PLDR_DATA_TABLE_ENTRY DataTableEntry; 03157 PWCHAR Start; 03158 PWCHAR End; 03159 PWCHAR Walk; 03160 ULONG NameLength; 03161 PMI_VERIFIER_DRIVER_ENTRY Verifier; 03162 LARGE_INTEGER CurrentTime; 03163 UNICODE_STRING KernelString; 03164 UNICODE_STRING HalString; 03165 PMI_VERIFIER_DRIVER_ENTRY KernelEntry; 03166 PMI_VERIFIER_DRIVER_ENTRY HalEntry; 03167 03168 InitializeListHead (&MiSuspectDriverList); 03169 03170 if (MmVerifyDriverLevel != (ULONG)-1) { 03171 if (MmVerifyDriverLevel & DRIVER_VERIFIER_IO_CHECKING) { 03172 if (MmVerifyDriverBufferLength == (ULONG)-1) { 03173 MmVerifyDriverBufferLength = 0; // Mm will not page out verifier pages. 03174 } 03175 } 03176 } 03177 03178 if (MmVerifyDriverBufferLength == (ULONG)-1) { 03179 03180 if (MmDontVerifyRandomDrivers == TRUE) { 03181 return FALSE; 03182 } 03183 03184 MmVerifyDriverBufferLength = 0; 03185 03186 CurrentTime = KeQueryPerformanceCounter (NULL); 03187 CurrentTime.LowPart = (CurrentTime.LowPart % 26); 03188 03189 MiVerifyRandomDrivers = (WCHAR)'A' + (WCHAR)CurrentTime.LowPart; 03190 03191 if ((MiVerifyRandomDrivers == (WCHAR)'H') || 03192 (MiVerifyRandomDrivers == (WCHAR)'J') || 03193 (MiVerifyRandomDrivers == (WCHAR)'X') || 03194 (MiVerifyRandomDrivers == (WCHAR)'Y') || 03195 (MiVerifyRandomDrivers == (WCHAR)'Z')) { 03196 MiVerifyRandomDrivers = (WCHAR)'X'; 03197 } 03198 } 03199 03200 KeInitializeSpinLock (&ViBadMapperLock); 03201 KeInitializeSpinLock (&VerifierListLock); 03202 03203 KeInitializeSpinLock (&VerifierPoolLock); 03204 ExInitializeFastMutex (&VerifierPoolMutex); 03205 03206 InitializeListHead (&MiVerifierDriverAddedThunkListHead); 03207 03208 // 03209 // If no default is specified, then special pool, pagable code/data 03210 // flushing and pool leak detection are enabled. 03211 // 03212 03213 if (MmVerifyDriverLevel == (ULONG)-1) { 03214 MmVerifierData.Level = DRIVER_VERIFIER_SPECIAL_POOLING | 03215 DRIVER_VERIFIER_FORCE_IRQL_CHECKING | 03216 DRIVER_VERIFIER_TRACK_POOL_ALLOCATIONS; 03217 } 03218 else { 03219 MmVerifierData.Level = MmVerifyDriverLevel; 03220 } 03221 03222 VerifierModifyableOptions = (DRIVER_VERIFIER_SPECIAL_POOLING | 03223 DRIVER_VERIFIER_FORCE_IRQL_CHECKING | 03224 DRIVER_VERIFIER_INJECT_ALLOCATION_FAILURES); 03225 03226 IoVerifierInit (MmVerifierData.Level, IOVERIFIERINIT_PHASE0 | 03227 IOVERIFIERINIT_EVERYTHING_TRACKED | 03228 IOVERIFIERINIT_VERIFIER_DRIVER_LIST); 03229 03230 KernelEntry = NULL; 03231 HalEntry = NULL; 03232 03233 if (MiVerifyRandomDrivers == (WCHAR)0) { 03234 03235 RtlInitUnicodeString (&KernelString, L"ntoskrnl.exe"); 03236 RtlInitUnicodeString (&HalString, L"hal.dll"); 03237 03238 Start = MmVerifyDriverBuffer; 03239 End = MmVerifyDriverBuffer + (MmVerifyDriverBufferLength - sizeof(WCHAR)) / sizeof(WCHAR); 03240 03241 while (Start < End) { 03242 if (UNICODE_WHITESPACE(*Start)) { 03243 Start += 1; 03244 continue; 03245 } 03246 03247 if (*Start == (WCHAR)'*') { 03248 MiVerifyAllDrivers = TRUE; 03249 break; 03250 } 03251 03252 for (Walk = Start; Walk < End; Walk += 1) { 03253 if (UNICODE_WHITESPACE(*Walk)) { 03254 break; 03255 } 03256 } 03257 03258 // 03259 // Got a string. Save it. 03260 // 03261 03262 NameLength = (ULONG)(Walk - Start + 1) * sizeof (WCHAR); 03263 03264 Verifier = (PMI_VERIFIER_DRIVER_ENTRY)ExAllocatePoolWithTag ( 03265 NonPagedPool, 03266 sizeof (MI_VERIFIER_DRIVER_ENTRY) + 03267 NameLength, 03268 'dLmM'); 03269 03270 if (Verifier == NULL) { 03271 break; 03272 } 03273 03274 Verifier->BaseName.Buffer = (PWSTR)((PCHAR)Verifier + 03275 sizeof (MI_VERIFIER_DRIVER_ENTRY)); 03276 Verifier->BaseName.Length = (USHORT)NameLength - sizeof (UNICODE_NULL); 03277 Verifier->BaseName.MaximumLength = (USHORT)NameLength; 03278 03279 RtlMoveMemory (Verifier->BaseName.Buffer, 03280 Start, 03281 NameLength - sizeof (UNICODE_NULL)); 03282 03283 ViInitializeEntry (Verifier, TRUE); 03284 03285 Verifier->Flags |= VI_VERIFYING_DIRECTLY; 03286 03287 ViInsertVerifierEntry (Verifier); 03288 03289 if (RtlEqualUnicodeString (&KernelString, 03290 &Verifier->BaseName, 03291 TRUE)) { 03292 03293 // 03294 // All driver pool allocation calls must be intercepted so 03295 // they are not mistaken for kernel pool allocations. 03296 // 03297 03298 MiVerifyAllDrivers = TRUE; 03299 03300 KernelVerifier = TRUE; 03301 KernelEntry = Verifier; 03302 03303 } 03304 else if (RtlEqualUnicodeString (&HalString, 03305 &Verifier->BaseName, 03306 TRUE)) { 03307 HalEntry = Verifier; 03308 } 03309 03310 Start = Walk + 1; 03311 } 03312 } 03313 03314 if (MiTriageAddDrivers (LoaderBlock) == TRUE) { 03315 03316 // 03317 // Disable random driver verification if triage has picked driver(s). 03318 // 03319 03320 MiVerifyRandomDrivers = (WCHAR)0; 03321 } 03322 03323 // 03324 // Process the boot-loaded drivers now. 03325 // 03326 03327 i = 0; 03328 NextEntry = LoaderBlock->LoadOrderListHead.Flink; 03329 03330 for ( ; NextEntry != &LoaderBlock->LoadOrderListHead; NextEntry = NextEntry->Flink) { 03331 03332 DataTableEntry = CONTAINING_RECORD(NextEntry, 03333 LDR_DATA_TABLE_ENTRY, 03334 InLoadOrderLinks); 03335 03336 // 03337 // Process the kernel and HAL specially. 03338 // 03339 03340 if (i == 0) { 03341 if (KernelEntry != NULL) { 03342 MiApplyDriverVerifier (DataTableEntry, KernelEntry); 03343 } 03344 } 03345 else if (i == 1) { 03346 if (HalEntry != NULL) { 03347 MiApplyDriverVerifier (DataTableEntry, HalEntry); 03348 } 03349 } 03350 else { 03351 MiApplyDriverVerifier (DataTableEntry, NULL); 03352 } 03353 i += 1; 03354 } 03355 03356 return TRUE; 03357 }

VOID MiInitializeIoTrackers VOID   ) 
 

Definition at line 1595 of file iosup.c.

References KeInitializeSpinLock(), _LOCK_HEADER::ListHead, _SYSPTES_HEADER::ListHead, MiDeadPteTrackerListHead, MiPteHeader, MiPteTrackerLock, MmLockedPagesHead, MmTrackLockedPages, MmTrackPtes, and TRUE.

Referenced by MmInitSystem().

01598 { 01599 if (MmTrackPtes != 0) { 01600 InitializeListHead (&MiDeadPteTrackerListHead); 01601 KeInitializeSpinLock (&MiPteTrackerLock); 01602 InitializeListHead (&MiPteHeader.ListHead); 01603 } 01604 01605 if (MmTrackLockedPages == TRUE) { 01606 InitializeListHead (&MmLockedPagesHead.ListHead); 01607 } 01608 }

LOGICAL MiInitializeLoadedModuleList IN PLOADER_PARAMETER_BLOCK  LoaderBlock  ) 
 

Definition at line 6591 of file sysload.c.

References ExAllocatePoolWithTag, ExFreePool(), ExInitializeResource, FALSE, KeInitializeSpinLock(), MiBuildImportsForBootDrivers(), MiLocateKernelSections(), NonPagedPool, NULL, PagedPool, PsLoadedModuleList, PsLoadedModuleResource, PsLoadedModuleSpinLock, PsNtosImageBase, and TRUE.

Referenced by MmInitSystem().

06597 : 06598 06599 This function initializes the loaded module list based on the LoaderBlock. 06600 06601 Arguments: 06602 06603 LoaderBlock - Supplies a pointer to the system loader block. 06604 06605 Return Value: 06606 06607 None. 06608 06609 Environment: 06610 06611 Kernel mode, Phase 0 Initialization. 06612 06613 --*/ 06614 06615 { 06616 PLIST_ENTRY NextEntry; 06617 PLDR_DATA_TABLE_ENTRY DataTableEntry1; 06618 PLDR_DATA_TABLE_ENTRY DataTableEntry2; 06619 06620 // 06621 // Initialize the loaded module list executive resource and spin lock. 06622 // 06623 06624 ExInitializeResource (&PsLoadedModuleResource); 06625 KeInitializeSpinLock (&PsLoadedModuleSpinLock); 06626 06627 InitializeListHead (&PsLoadedModuleList); 06628 06629 // 06630 // Scan the loaded module list and allocate and initialize a data table 06631 // entry for each module. The data table entry is inserted in the loaded 06632 // module list and the initialization order list in the order specified 06633 // in the loader parameter block. The data table entry is inserted in the 06634 // memory order list in memory order. 06635 // 06636 06637 NextEntry = LoaderBlock->LoadOrderListHead.Flink; 06638 DataTableEntry2 = CONTAINING_RECORD(NextEntry, 06639 LDR_DATA_TABLE_ENTRY, 06640 InLoadOrderLinks); 06641 PsNtosImageBase = DataTableEntry2->DllBase; 06642 06643 MiLocateKernelSections (DataTableEntry2); 06644 06645 while (NextEntry != &LoaderBlock->LoadOrderListHead) { 06646 06647 DataTableEntry2 = CONTAINING_RECORD(NextEntry, 06648 LDR_DATA_TABLE_ENTRY, 06649 InLoadOrderLinks); 06650 06651 // 06652 // Allocate a data table entry. 06653 // 06654 06655 DataTableEntry1 = ExAllocatePoolWithTag (NonPagedPool, 06656 sizeof(LDR_DATA_TABLE_ENTRY), 06657 'dLmM'); 06658 06659 if (DataTableEntry1 == NULL) { 06660 return FALSE; 06661 } 06662 06663 // 06664 // Copy the data table entry. 06665 // 06666 06667 *DataTableEntry1 = *DataTableEntry2; 06668 06669 DataTableEntry1->FullDllName.Buffer = ExAllocatePoolWithTag (PagedPool, 06670 DataTableEntry2->FullDllName.MaximumLength + sizeof(UNICODE_NULL), 06671 'TDmM'); 06672 06673 if (DataTableEntry1->FullDllName.Buffer == NULL) { 06674 ExFreePool (DataTableEntry1); 06675 return FALSE; 06676 } 06677 06678 DataTableEntry1->BaseDllName.Buffer = ExAllocatePoolWithTag (NonPagedPool, 06679 DataTableEntry2->BaseDllName.MaximumLength + sizeof(UNICODE_NULL), 06680 'dLmM'); 06681 06682 if (DataTableEntry1->BaseDllName.Buffer == NULL) { 06683 ExFreePool (DataTableEntry1->FullDllName.Buffer); 06684 ExFreePool (DataTableEntry1); 06685 return FALSE; 06686 } 06687 06688 // 06689 // Copy the strings. 06690 // 06691 06692 RtlMoveMemory (DataTableEntry1->FullDllName.Buffer, 06693 DataTableEntry2->FullDllName.Buffer, 06694 DataTableEntry1->FullDllName.MaximumLength); 06695 06696 RtlMoveMemory (DataTableEntry1->BaseDllName.Buffer, 06697 DataTableEntry2->BaseDllName.Buffer, 06698 DataTableEntry1->BaseDllName.MaximumLength); 06699 06700 // 06701 // Insert the data table entry in the load order list in the order 06702 // they are specified. 06703 // 06704 06705 InsertTailList(&PsLoadedModuleList, 06706 &DataTableEntry1->InLoadOrderLinks); 06707 06708 NextEntry = NextEntry->Flink; 06709 } 06710 06711 MiBuildImportsForBootDrivers (); 06712 06713 return TRUE; 06714 }

VOID MiInitializeMustSucceedPool VOID   ) 
 

VOID MiInitializeNonPagedPool VOID   ) 
 

Definition at line 2476 of file allocpag.c.

References ASSERT, BYTES_TO_PAGES, Index, MI_CONVERT_PHYSICAL_TO_PFN, MI_GET_PAGE_FRAME_FROM_PTE, MI_IS_PHYSICAL_ADDRESS, MI_MAX_FREE_LIST_HEADS, MiEndOfInitialPoolFrame, MiGetPteAddress, MiInitializeSystemPtes(), MM_FREE_POOL_SIGNATURE, MmExpandedPoolBitPosition, MmMaximumNonPagedPoolInBytes, MmMustSucceedPoolBitPosition, MmNonPagedMustSucceed, MmNonPagedPoolExpansionStart, MmNonPagedPoolFreeListHead, MmNonPagedPoolStart, MmNumberOfFreeNonPagedPool, MmSizeOfNonPagedMustSucceed, MmSizeOfNonPagedPoolInBytes, NonPagedPoolExpansion, PAGE_SIZE, PAGED_CODE, _MMFREE_POOL_ENTRY::Signature, Size, and _MMPTE::u.

Referenced by MiInitMachineDependent().

02482 : 02483 02484 This function initializes the NonPaged pool. 02485 02486 NonPaged Pool is linked together through the pages. 02487 02488 Arguments: 02489 02490 None. 02491 02492 Return Value: 02493 02494 None. 02495 02496 Environment: 02497 02498 Kernel mode, during initialization. 02499 02500 --*/ 02501 02502 { 02503 ULONG PagesInPool; 02504 ULONG Size; 02505 ULONG Index; 02506 PMMFREE_POOL_ENTRY FreeEntry; 02507 PMMFREE_POOL_ENTRY FirstEntry; 02508 PMMPTE PointerPte; 02509 PFN_NUMBER i; 02510 PULONG_PTR ThisPage; 02511 PULONG_PTR NextPage; 02512 PVOID EndOfInitialPool; 02513 PFN_NUMBER PageFrameIndex; 02514 02515 PAGED_CODE(); 02516 02517 // 02518 // Initialize the list heads for free pages. 02519 // 02520 02521 for (Index = 0; Index < MI_MAX_FREE_LIST_HEADS; Index += 1) { 02522 InitializeListHead (&MmNonPagedPoolFreeListHead[Index]); 02523 } 02524 02525 // 02526 // Initialize the must succeed pool (this occupies the first 02527 // pages of the pool area). 02528 // 02529 02530 // 02531 // Allocate NonPaged pool for the NonPagedPoolMustSucceed pool. 02532 // 02533 02534 MmNonPagedMustSucceed = (PCHAR)MmNonPagedPoolStart; 02535 02536 i = MmSizeOfNonPagedMustSucceed - PAGE_SIZE; 02537 02538 MmMustSucceedPoolBitPosition = BYTES_TO_PAGES(MmSizeOfNonPagedMustSucceed); 02539 02540 ThisPage = (PULONG_PTR)MmNonPagedMustSucceed; 02541 02542 while (i > 0) { 02543 NextPage = (PULONG_PTR)((PCHAR)ThisPage + PAGE_SIZE); 02544 *ThisPage = (ULONG_PTR)NextPage; 02545 ThisPage = NextPage; 02546 i -= PAGE_SIZE; 02547 } 02548 *ThisPage = 0; 02549 02550 // 02551 // Set up the remaining pages as non paged pool pages. 02552 // 02553 02554 ASSERT ((MmSizeOfNonPagedMustSucceed & (PAGE_SIZE - 1)) == 0); 02555 FreeEntry = (PMMFREE_POOL_ENTRY)((PCHAR)MmNonPagedPoolStart + 02556 MmSizeOfNonPagedMustSucceed); 02557 FirstEntry = FreeEntry; 02558 02559 PagesInPool = BYTES_TO_PAGES(MmSizeOfNonPagedPoolInBytes - 02560 MmSizeOfNonPagedMustSucceed); 02561 02562 // 02563 // Set the location of expanded pool. 02564 // 02565 02566 MmExpandedPoolBitPosition = BYTES_TO_PAGES (MmSizeOfNonPagedPoolInBytes); 02567 02568 MmNumberOfFreeNonPagedPool = PagesInPool; 02569 02570 Index = (ULONG)(MmNumberOfFreeNonPagedPool - 1); 02571 if (Index >= MI_MAX_FREE_LIST_HEADS) { 02572 Index = MI_MAX_FREE_LIST_HEADS - 1; 02573 } 02574 02575 InsertHeadList (&MmNonPagedPoolFreeListHead[Index], &FreeEntry->List); 02576 02577 FreeEntry->Size = PagesInPool; 02578 #if DBG 02579 FreeEntry->Signature = MM_FREE_POOL_SIGNATURE; 02580 #endif 02581 FreeEntry->Owner = FirstEntry; 02582 02583 while (PagesInPool > 1) { 02584 FreeEntry = (PMMFREE_POOL_ENTRY)((PCHAR)FreeEntry + PAGE_SIZE); 02585 #if DBG 02586 FreeEntry->Signature = MM_FREE_POOL_SIGNATURE; 02587 #endif 02588 FreeEntry->Owner = FirstEntry; 02589 PagesInPool -= 1; 02590 } 02591 02592 // 02593 // Set the last nonpaged pool PFN so coalescing on free doesn't go 02594 // past the end of the initial pool. 02595 // 02596 02597 EndOfInitialPool = (PVOID)((ULONG_PTR)MmNonPagedPoolStart + MmSizeOfNonPagedPoolInBytes - 1); 02598 02599 if (MI_IS_PHYSICAL_ADDRESS(EndOfInitialPool)) { 02600 PageFrameIndex = MI_CONVERT_PHYSICAL_TO_PFN (EndOfInitialPool); 02601 } else { 02602 PointerPte = MiGetPteAddress(EndOfInitialPool); 02603 ASSERT (PointerPte->u.Hard.Valid == 1); 02604 PageFrameIndex = MI_GET_PAGE_FRAME_FROM_PTE (PointerPte); 02605 } 02606 MiEndOfInitialPoolFrame = PageFrameIndex; 02607 02608 // 02609 // Set up the system PTEs for nonpaged pool expansion. 02610 // 02611 02612 PointerPte = MiGetPteAddress (MmNonPagedPoolExpansionStart); 02613 ASSERT (PointerPte->u.Hard.Valid == 0); 02614 02615 Size = BYTES_TO_PAGES(MmMaximumNonPagedPoolInBytes - 02616 MmSizeOfNonPagedPoolInBytes); 02617 02618 // 02619 // Insert a guard PTE at the bottom of expanded nonpaged pool. 02620 // 02621 02622 Size -= 1; 02623 PointerPte += 1; 02624 02625 MiInitializeSystemPtes (PointerPte, 02626 Size, 02627 NonPagedPoolExpansion 02628 ); 02629 02630 // 02631 // A guard PTE is built at the top by our caller. This allows us to 02632 // freely increment virtual addresses in MiFreePoolPages and just check 02633 // for a blank PTE. 02634 // 02635 }

VOID MiInitializePfn IN PFN_NUMBER  PageFrameIndex,
IN PMMPTE  PointerPte,
IN ULONG  ModifiedState
 

Definition at line 3398 of file pagfault.c.

References ActiveAndValid, ASSERT, DbgPrint, KeBugCheckEx(), MI_GET_PAGE_FRAME_FROM_PTE, MI_IS_CACHING_DISABLED, MI_PFN_ELEMENT, MiCheckPdeForPagedPool(), MiFormatPfn(), MiFormatPte(), MiGetPteAddress, MiGetVirtualAddressMappedByPte, MM_DEMAND_ZERO_WRITE_PTE, MM_EXECUTE_READWRITE, MM_NOCACHE, MM_PFN_LOCK_ASSERT, MM_READWRITE, NT_SUCCESS, _MMPFN::OriginalPte, _MMPFN::PteAddress, _MMPFN::PteFrame, _MMPTE::u, _MMPFN::u2, and _MMPFN::u3.

Referenced by ExAllocatePool(), MiAddWorkingSetPage(), MiAddWsleHash(), MiAllocatePoolPages(), MiAllocateSpecialPool(), MiFillSystemPageDirectory(), MiInitializeSystemCache(), MiInitializeWorkingSetList(), MiLoadImageSection(), MiReloadBootLoadedDrivers(), MiResolveDemandZeroFault(), MiSessionCommitImagePages(), MiSessionCreateInternal(), MiSessionInitializeWorkingSetList(), MmAccessFault(), MmAddPhysicalMemory(), MmAllocateIndependentPages(), MmAllocateNonCachedMemory(), MmCheckCachedPageState(), MmCreateKernelStack(), MmGrowKernelStack(), MmInitializeProcessAddressSpace(), and MmInitSystem().

03406 : 03407 03408 This function initializes the specified PFN element to the 03409 active and valid state. 03410 03411 Arguments: 03412 03413 PageFrameIndex - Supplies the page frame number to initialize. 03414 03415 PointerPte - Supplies the pointer to the PTE which caused the 03416 page fault. 03417 03418 ModifiedState - Supplies the state to set the modified field in the PFN 03419 element for this page, either 0 or 1. 03420 03421 Return Value: 03422 03423 None. 03424 03425 Environment: 03426 03427 Kernel mode, APCs disabled, PFN mutex held. 03428 03429 --*/ 03430 03431 { 03432 PMMPFN Pfn1; 03433 PMMPFN Pfn2; 03434 PMMPTE PteFramePointer; 03435 PFN_NUMBER PteFramePage; 03436 03437 MM_PFN_LOCK_ASSERT(); 03438 03439 Pfn1 = MI_PFN_ELEMENT (PageFrameIndex); 03440 Pfn1->PteAddress = PointerPte; 03441 03442 // 03443 // If the PTE is currently valid, an address space is being built, 03444 // just make the original PTE demand zero. 03445 // 03446 03447 if (PointerPte->u.Hard.Valid == 1) { 03448 Pfn1->OriginalPte.u.Long = MM_DEMAND_ZERO_WRITE_PTE; 03449 03450 #if defined(_IA64_) 03451 if (PointerPte->u.Hard.Execute == 1) { 03452 Pfn1->OriginalPte.u.Soft.Protection = MM_EXECUTE_READWRITE; 03453 } 03454 #endif 03455 03456 if (MI_IS_CACHING_DISABLED (PointerPte)) { 03457 Pfn1->OriginalPte.u.Soft.Protection = MM_READWRITE | MM_NOCACHE; 03458 } 03459 03460 } else { 03461 Pfn1->OriginalPte = *PointerPte; 03462 ASSERT (!((Pfn1->OriginalPte.u.Soft.Prototype == 0) && 03463 (Pfn1->OriginalPte.u.Soft.Transition == 1))); 03464 } 03465 03466 Pfn1->u3.e2.ReferenceCount += 1; 03467 03468 #if DBG 03469 if (Pfn1->u3.e2.ReferenceCount > 1) { 03470 DbgPrint("MM:incrementing ref count > 1 \n"); 03471 MiFormatPfn(Pfn1); 03472 MiFormatPte(PointerPte); 03473 } 03474 #endif 03475 03476 Pfn1->u2.ShareCount += 1; 03477 Pfn1->u3.e1.PageLocation = ActiveAndValid; 03478 Pfn1->u3.e1.Modified = ModifiedState; 03479 03480 #if defined (_WIN64) 03481 Pfn1->UsedPageTableEntries = 0; 03482 #endif 03483 03484 #if PFN_CONSISTENCY 03485 Pfn1->u3.e1.PageTablePage = 0; 03486 #endif 03487 // 03488 // Determine the page frame number of the page table page which 03489 // contains this PTE. 03490 // 03491 03492 PteFramePointer = MiGetPteAddress(PointerPte); 03493 if (PteFramePointer->u.Hard.Valid == 0) { 03494 #if !defined (_WIN64) 03495 if (!NT_SUCCESS(MiCheckPdeForPagedPool (PointerPte))) { 03496 #endif 03497 KeBugCheckEx (MEMORY_MANAGEMENT, 03498 0x61940, 03499 (ULONG_PTR)PointerPte, 03500 (ULONG_PTR)PteFramePointer->u.Long, 03501 (ULONG_PTR)MiGetVirtualAddressMappedByPte(PointerPte)); 03502 #if !defined (_WIN64) 03503 } 03504 #endif 03505 } 03506 PteFramePage = MI_GET_PAGE_FRAME_FROM_PTE (PteFramePointer); 03507 ASSERT (PteFramePage != 0); 03508 Pfn1->PteFrame = PteFramePage; 03509 03510 // 03511 // Increment the share count for the page table page containing 03512 // this PTE. 03513 // 03514 03515 Pfn2 = MI_PFN_ELEMENT (PteFramePage); 03516 03517 Pfn2->u2.ShareCount += 1; 03518 03519 return; 03520 }

VOID MiInitializePfnForOtherProcess IN PFN_NUMBER  PageFrameIndex,
IN PMMPTE  PointerPte,
IN PFN_NUMBER  ContainingPageFrame
 

Definition at line 3973 of file pagfault.c.

References ActiveAndValid, ASSERT, DbgPrint, MI_PFN_ELEMENT, MiFormatPfn(), MiFormatPte(), MM_DEMAND_ZERO_WRITE_PTE, MM_PFN_LOCK_ASSERT, _MMPFN::OriginalPte, _MMPFN::PteAddress, _MMPFN::PteFrame, _MMPTE::u, _MMPFN::u2, and _MMPFN::u3.

Referenced by MiAllocatePoolPages(), MiFillSystemPageDirectory(), MiInitializeSessionPool(), MiMakeOutswappedPageResident(), MiSessionCommitPageTables(), MiSessionCreateInternal(), and MiSessionInitializeWorkingSetList().

03981 : 03982 03983 This function initializes the specified PFN element to the 03984 active and valid state with the dirty bit on in the PTE and 03985 the PFN database marked as modified. 03986 03987 As this PTE is not visible from the current process, the containing 03988 page frame must be supplied at the PTE contents field for the 03989 PFN database element are set to demand zero. 03990 03991 Arguments: 03992 03993 PageFrameIndex - Supplies the page frame number of which to initialize. 03994 03995 PointerPte - Supplies the pointer to the PTE which caused the 03996 page fault. 03997 03998 ContainingPageFrame - Supplies the page frame number of the page 03999 table page which contains this PTE. 04000 If the ContainingPageFrame is 0, then 04001 the ShareCount for the 04002 containing page is not incremented. 04003 04004 Return Value: 04005 04006 None. 04007 04008 Environment: 04009 04010 Kernel mode, APCs disabled, PFN mutex held. 04011 04012 --*/ 04013 04014 { 04015 PMMPFN Pfn1; 04016 PMMPFN Pfn2; 04017 04018 Pfn1 = MI_PFN_ELEMENT (PageFrameIndex); 04019 Pfn1->PteAddress = PointerPte; 04020 Pfn1->OriginalPte.u.Long = MM_DEMAND_ZERO_WRITE_PTE; 04021 ASSERT (Pfn1->u3.e2.ReferenceCount == 0); 04022 Pfn1->u3.e2.ReferenceCount += 1; 04023 04024 #if DBG 04025 if (Pfn1->u3.e2.ReferenceCount > 1) { 04026 DbgPrint("MM:incrementing ref count > 1 \n"); 04027 MiFormatPfn(Pfn1); 04028 MiFormatPte(PointerPte); 04029 } 04030 #endif 04031 04032 Pfn1->u2.ShareCount += 1; 04033 Pfn1->u3.e1.PageLocation = ActiveAndValid; 04034 Pfn1->u3.e1.Modified = 1; 04035 04036 #if PFN_CONSISTENCY 04037 MM_PFN_LOCK_ASSERT(); 04038 04039 Pfn1->u3.e1.PageTablePage = 0; 04040 #endif 04041 04042 // 04043 // Increment the share count for the page table page containing 04044 // this PTE. 04045 // 04046 04047 if (ContainingPageFrame != 0) { 04048 Pfn1->PteFrame = ContainingPageFrame; 04049 Pfn2 = MI_PFN_ELEMENT (ContainingPageFrame); 04050 Pfn2->u2.ShareCount += 1; 04051 } 04052 return; 04053 }

VOID MiInitializeReadInProgressPfn IN PMDL  Mdl,
IN PMMPTE  BasePte,
IN PKEVENT  Event,
IN WSLE_NUMBER  WorkingSetIndex
 

Definition at line 3523 of file pagfault.c.

References ASSERT, Event(), KeBugCheckEx(), MI_ADD_LOCKED_PAGE_CHARGE_FOR_MODIFIED_PAGE, MI_GET_PAGE_FRAME_FROM_PTE, MI_MAKE_TRANSITION_PTE, MI_PFN_ELEMENT, MI_PROTOTYPE_WSINDEX, MI_WRITE_INVALID_PTE, MiCheckPdeForPagedPool(), MiGetPteAddress, MiGetVirtualAddressMappedByPte, MM_PFN_LOCK_ASSERT, NT_SUCCESS, _MMPFN::OriginalPte, PAGE_SIZE, _MMPFN::PteAddress, _MMPFN::PteFrame, _MMPTE::u, _MMPFN::u1, _MMPFN::u2, and _MMPFN::u3.

Referenced by MiResolveMappedFileFault(), and MiResolvePageFileFault().

03532 : 03533 03534 This function initializes the specified PFN element to the 03535 transition / read-in-progress state for an in-page operation. 03536 03537 03538 Arguments: 03539 03540 Mdl - Supplies a pointer to the MDL. 03541 03542 BasePte - Supplies the pointer to the PTE which the first page in 03543 the MDL maps. 03544 03545 Event - Supplies the event which is to be set when the I/O operation 03546 completes. 03547 03548 WorkingSetIndex - Supplies the working set index flag, a value of 03549 -1 indicates no WSLE is required because 03550 this is a prototype PTE. 03551 03552 Return Value: 03553 03554 None. 03555 03556 Environment: 03557 03558 Kernel mode, APCs disabled, PFN mutex held. 03559 03560 --*/ 03561 03562 { 03563 PMMPFN Pfn1; 03564 PMMPFN Pfn2; 03565 PMMPTE PteFramePointer; 03566 PFN_NUMBER PteFramePage; 03567 MMPTE TempPte; 03568 LONG NumberOfBytes; 03569 PPFN_NUMBER Page; 03570 03571 MM_PFN_LOCK_ASSERT(); 03572 03573 Page = (PPFN_NUMBER)(Mdl + 1); 03574 03575 NumberOfBytes = Mdl->ByteCount; 03576 03577 while (NumberOfBytes > 0) { 03578 03579 Pfn1 = MI_PFN_ELEMENT (*Page); 03580 Pfn1->u1.Event = Event; 03581 Pfn1->PteAddress = BasePte; 03582 Pfn1->OriginalPte = *BasePte; 03583 ASSERT (Pfn1->u3.e2.ReferenceCount == 0); 03584 MI_ADD_LOCKED_PAGE_CHARGE_FOR_MODIFIED_PAGE (Pfn1, 10); 03585 Pfn1->u3.e2.ReferenceCount += 1; 03586 03587 Pfn1->u2.ShareCount = 0; 03588 Pfn1->u3.e1.ReadInProgress = 1; 03589 Pfn1->u3.e1.InPageError = 0; 03590 03591 #if PFN_CONSISTENCY 03592 Pfn1->u3.e1.PageTablePage = 0; 03593 #endif 03594 if (WorkingSetIndex == MI_PROTOTYPE_WSINDEX) { 03595 Pfn1->u3.e1.PrototypePte = 1; 03596 } 03597 03598 // 03599 // Determine the page frame number of the page table page which 03600 // contains this PTE. 03601 // 03602 03603 PteFramePointer = MiGetPteAddress(BasePte); 03604 if (PteFramePointer->u.Hard.Valid == 0) { 03605 #if !defined (_WIN64) 03606 if (!NT_SUCCESS(MiCheckPdeForPagedPool (BasePte))) { 03607 #endif 03608 KeBugCheckEx (MEMORY_MANAGEMENT, 03609 0x61940, 03610 (ULONG_PTR)BasePte, 03611 (ULONG_PTR)PteFramePointer->u.Long, 03612 (ULONG_PTR)MiGetVirtualAddressMappedByPte(BasePte)); 03613 #if !defined (_WIN64) 03614 } 03615 #endif 03616 } 03617 03618 PteFramePage = MI_GET_PAGE_FRAME_FROM_PTE (PteFramePointer); 03619 Pfn1->PteFrame = PteFramePage; 03620 03621 // 03622 // Put the PTE into the transition state, no cache flush needed as 03623 // PTE is still not valid. 03624 // 03625 03626 MI_MAKE_TRANSITION_PTE (TempPte, 03627 *Page, 03628 BasePte->u.Soft.Protection, 03629 BasePte); 03630 MI_WRITE_INVALID_PTE (BasePte, TempPte); 03631 03632 // 03633 // Increment the share count for the page table page containing 03634 // this PTE as the PTE just went into the transition state. 03635 // 03636 03637 ASSERT (PteFramePage != 0); 03638 Pfn2 = MI_PFN_ELEMENT (PteFramePage); 03639 Pfn2->u2.ShareCount += 1; 03640 03641 NumberOfBytes -= PAGE_SIZE; 03642 Page += 1; 03643 BasePte += 1; 03644 } 03645 03646 return; 03647 }

VOID MiInitializeSessionIds VOID   ) 
 

Definition at line 350 of file session.c.

References ASSERT, ExInitializeFastMutex, MiCreateBitMap, MiSessionIdBitmap, MiSessionIdMutex, MM_MAXIMUM_CONCURRENT_SESSIONS, NonPagedPoolMustSucceed, NULL, PAGE_SIZE, PagedPool, and RtlClearAllBits().

00356 : 00357 00358 This routine creates and initializes session ID allocation/deallocation. 00359 00360 Arguments: 00361 00362 None. 00363 00364 Return Value: 00365 00366 None. 00367 00368 --*/ 00369 00370 { 00371 // 00372 // If this ever grows beyond the size of a page, both the allocation and 00373 // deletion code will need to be updated. 00374 // 00375 00376 ASSERT (sizeof(MM_SESSION_SPACE) <= PAGE_SIZE); 00377 00378 ExInitializeFastMutex (&MiSessionIdMutex); 00379 00380 MiCreateBitMap (&MiSessionIdBitmap, 00381 MM_MAXIMUM_CONCURRENT_SESSIONS, 00382 PagedPool); 00383 00384 if (MiSessionIdBitmap == NULL) { 00385 MiCreateBitMap (&MiSessionIdBitmap, 00386 MM_MAXIMUM_CONCURRENT_SESSIONS, 00387 NonPagedPoolMustSucceed); 00388 } 00389 00390 RtlClearAllBits (MiSessionIdBitmap); 00391 }

NTSTATUS MiInitializeSessionPool VOID   ) 
 

Definition at line 4222 of file allocpag.c.

References _MM_PAGED_POOL_INFO::AllocatedPagedPool, ASSERT, _MM_SESSION_SPACE::CommittedPages, _MM_PAGED_POOL_INFO::EndOfPagedPoolBitmap, ExInitializeFastMutex, ExpInitializePoolDescriptor(), FALSE, _MM_PAGED_POOL_INFO::FirstPteForPagedPool, Index, _MM_PAGED_POOL_INFO::LastPteForPagedPool, LOCK_PFN, MI_FLUSH_SINGLE_SESSION_TB, MI_GET_PAGE_COLOR_FROM_PTE, MI_PFN_ELEMENT, MI_SESSION_POOL, MI_SESSION_POOL_SIZE, MI_SET_PFN_DELETED, MI_WRITE_VALID_PTE, MiChargeCommitment(), MiCreateBitMap, MiDecrementShareAndValidCount, MiDecrementShareCountOnly, MiEnsureAvailablePageOrWait(), MiFillMemoryPte, MiFreeSessionPoolBitMaps(), MiGetPdeAddress, MiGetPdeSessionIndex, MiGetPteAddress, MiInitializePfnForOtherProcess(), MiRemoveAnyPage(), MiReturnCommitment(), MM_BUMP_COUNTER, MM_BUMP_SESS_COUNTER, MM_BUMP_SESSION_FAILURES, MM_DBG_COMMIT_RETURN_PAGED_POOL_PAGES, MM_DBG_COMMIT_RETURN_SESSION_POOL_PAGE_TABLES, MM_DBG_COMMIT_SESSION_POOL_PAGE_TABLES, MM_DBG_SESSION_PAGEDPOOL_PAGETABLE_ALLOC, MM_DBG_SESSION_PAGEDPOOL_PAGETABLE_FREE_FAIL1, MM_KERNEL_NOACCESS_PTE, MM_SESSION_FAILURE_NO_COMMIT, MM_SESSION_FAILURE_NO_NONPAGED_POOL, MM_SESSION_FAILURE_NO_RESIDENT, MM_TRACK_COMMIT, MmAvailablePages, MmResidentAvailablePages, MmSessionSpace, _MM_PAGED_POOL_INFO::NextPdeForPagedPoolExpansion, _MM_SESSION_SPACE::NonPagablePages, NonPagedPool, NULL, PAGE_SHIFT, PAGE_SIZE, _MM_SESSION_SPACE::PagedPool, _MM_PAGED_POOL_INFO::PagedPoolAllocationMap, _MM_SESSION_SPACE::PagedPoolBasePde, _MM_PAGED_POOL_INFO::PagedPoolCommit, _MM_SESSION_SPACE::PagedPoolEnd, _MM_PAGED_POOL_INFO::PagedPoolHint, _MM_SESSION_SPACE::PagedPoolInfo, _MM_PAGED_POOL_INFO::PagedPoolLargeSessionAllocationMap, _MM_SESSION_SPACE::PagedPoolMutex, PagedPoolSession, _MM_SESSION_SPACE::PagedPoolStart, _MM_SESSION_SPACE::PageTables, PPOOL_DESCRIPTOR, PTE_PER_PAGE, _MMPFN::PteFrame, RtlClearAllBits(), RtlClearBits(), RtlSetAllBits(), SESSION_GLOBAL, _MM_SESSION_SPACE::SessionPageDirectoryIndex, TRUE, _MMPTE::u, _MMPFN::u1, _MMPFN::u2, UNLOCK_PFN, ValidKernelPdeLocal, and ZeroKernelPte.

Referenced by MiSessionCreateInternal().

04228 : 04229 04230 Initialize the current session's pool structure. 04231 04232 Arguments: 04233 04234 None. 04235 04236 Return Value: 04237 04238 Status of the pool initialization. 04239 04240 Environment: 04241 04242 Kernel mode. 04243 04244 --*/ 04245 04246 { 04247 ULONG Index; 04248 MMPTE TempPte; 04249 PMMPTE PointerPde, PointerPte; 04250 PFN_NUMBER PageFrameIndex; 04251 PPOOL_DESCRIPTOR PoolDescriptor; 04252 PMM_SESSION_SPACE SessionGlobal; 04253 PMM_PAGED_POOL_INFO PagedPoolInfo; 04254 KIRQL OldIrql; 04255 PMMPFN Pfn1; 04256 MMPTE PreviousPte; 04257 #if DBG 04258 PMMPTE StartPde, EndPde; 04259 #endif 04260 04261 SessionGlobal = SESSION_GLOBAL(MmSessionSpace); 04262 04263 ExInitializeFastMutex (&SessionGlobal->PagedPoolMutex); 04264 04265 PoolDescriptor = &MmSessionSpace->PagedPool; 04266 04267 ExpInitializePoolDescriptor (PoolDescriptor, 04268 PagedPoolSession, 04269 0, 04270 0, 04271 &SessionGlobal->PagedPoolMutex); 04272 04273 MmSessionSpace->PagedPoolStart = (PVOID)MI_SESSION_POOL; 04274 04275 MmSessionSpace->PagedPoolEnd = (PVOID)((MI_SESSION_POOL + MI_SESSION_POOL_SIZE)-1); 04276 04277 PagedPoolInfo = &MmSessionSpace->PagedPoolInfo; 04278 PagedPoolInfo->PagedPoolCommit = 0; 04279 PagedPoolInfo->PagedPoolHint = 0; 04280 PagedPoolInfo->AllocatedPagedPool = 0; 04281 04282 // 04283 // Build the page table page for paged pool. 04284 // 04285 04286 PointerPde = MiGetPdeAddress (MmSessionSpace->PagedPoolStart); 04287 MmSessionSpace->PagedPoolBasePde = PointerPde; 04288 04289 PointerPte = MiGetPteAddress (MmSessionSpace->PagedPoolStart); 04290 04291 PagedPoolInfo->FirstPteForPagedPool = PointerPte; 04292 PagedPoolInfo->LastPteForPagedPool = MiGetPteAddress (MmSessionSpace->PagedPoolEnd); 04293 04294 #if DBG 04295 // 04296 // Session pool better be unused. 04297 // 04298 04299 StartPde = MiGetPdeAddress (MmSessionSpace->PagedPoolStart); 04300 EndPde = MiGetPdeAddress (MmSessionSpace->PagedPoolEnd); 04301 04302 while (StartPde <= EndPde) { 04303 ASSERT (StartPde->u.Long == 0); 04304 StartPde += 1; 04305 } 04306 #endif 04307 04308 // 04309 // Mark all PDEs as empty. 04310 // 04311 04312 MiFillMemoryPte (PointerPde, 04313 sizeof(MMPTE) * 04314 (1 + MiGetPdeAddress (MmSessionSpace->PagedPoolEnd) - PointerPde), 04315 ZeroKernelPte.u.Long); 04316 04317 if (MiChargeCommitment (1, NULL) == FALSE) { 04318 MM_BUMP_SESSION_FAILURES (MM_SESSION_FAILURE_NO_COMMIT); 04319 return STATUS_NO_MEMORY; 04320 } 04321 04322 MM_TRACK_COMMIT (MM_DBG_COMMIT_SESSION_POOL_PAGE_TABLES, 1); 04323 04324 TempPte = ValidKernelPdeLocal; 04325 04326 LOCK_PFN (OldIrql); 04327 04328 if (MmAvailablePages <= 1) { 04329 UNLOCK_PFN (OldIrql); 04330 MiReturnCommitment (1); 04331 MM_TRACK_COMMIT (MM_DBG_COMMIT_RETURN_SESSION_POOL_PAGE_TABLES, 1); 04332 MM_BUMP_SESSION_FAILURES (MM_SESSION_FAILURE_NO_RESIDENT); 04333 return STATUS_NO_MEMORY; 04334 } 04335 04336 MmResidentAvailablePages -= 1; 04337 MM_BUMP_COUNTER(42, 1); 04338 MM_BUMP_SESS_COUNTER(MM_DBG_SESSION_PAGEDPOOL_PAGETABLE_ALLOC, 1); 04339 04340 MiEnsureAvailablePageOrWait (NULL, NULL); 04341 04342 // 04343 // Allocate and map in the initial page table page for session pool. 04344 // 04345 04346 PageFrameIndex = MiRemoveAnyPage (MI_GET_PAGE_COLOR_FROM_PTE (PointerPde)); 04347 TempPte.u.Hard.PageFrameNumber = PageFrameIndex; 04348 MI_WRITE_VALID_PTE (PointerPde, TempPte); 04349 04350 MiInitializePfnForOtherProcess (PageFrameIndex, 04351 PointerPde, 04352 MmSessionSpace->SessionPageDirectoryIndex); 04353 04354 Pfn1 = MI_PFN_ELEMENT (PageFrameIndex); 04355 04356 // 04357 // This page will be locked into working set and assigned an index when 04358 // the working set is set up on return. 04359 // 04360 04361 ASSERT (Pfn1->u1.WsIndex == 0); 04362 04363 UNLOCK_PFN (OldIrql); 04364 04365 KeFillEntryTb ((PHARDWARE_PTE) PointerPde, PointerPte, FALSE); 04366 04367 #if !defined (_WIN64) 04368 04369 Index = MiGetPdeSessionIndex (MmSessionSpace->PagedPoolStart); 04370 04371 ASSERT (MmSessionSpace->PageTables[Index].u.Long == 0); 04372 MmSessionSpace->PageTables[Index] = TempPte; 04373 04374 #endif 04375 04376 MmSessionSpace->NonPagablePages += 1; 04377 MmSessionSpace->CommittedPages += 1; 04378 04379 MiFillMemoryPte (PointerPte, PAGE_SIZE, MM_KERNEL_NOACCESS_PTE); 04380 04381 PagedPoolInfo->NextPdeForPagedPoolExpansion = PointerPde + 1; 04382 04383 // 04384 // Initialize the bitmaps. 04385 // 04386 04387 MiCreateBitMap (&PagedPoolInfo->PagedPoolAllocationMap, 04388 MI_SESSION_POOL_SIZE >> PAGE_SHIFT, 04389 NonPagedPool); 04390 04391 if (PagedPoolInfo->PagedPoolAllocationMap == NULL) { 04392 MM_BUMP_SESSION_FAILURES (MM_SESSION_FAILURE_NO_NONPAGED_POOL); 04393 goto Failure; 04394 } 04395 04396 // 04397 // We start with all pages in the virtual address space as "busy", and 04398 // clear bits to make pages available as we dynamically expand the pool. 04399 // 04400 04401 RtlSetAllBits( PagedPoolInfo->PagedPoolAllocationMap ); 04402 04403 // 04404 // Indicate first page worth of PTEs are available. 04405 // 04406 04407 RtlClearBits (PagedPoolInfo->PagedPoolAllocationMap, 0, PTE_PER_PAGE); 04408 04409 // 04410 // Create the end of allocation range bitmap. 04411 // 04412 04413 MiCreateBitMap (&PagedPoolInfo->EndOfPagedPoolBitmap, 04414 MI_SESSION_POOL_SIZE >> PAGE_SHIFT, 04415 NonPagedPool); 04416 04417 if (PagedPoolInfo->EndOfPagedPoolBitmap == NULL) { 04418 MM_BUMP_SESSION_FAILURES (MM_SESSION_FAILURE_NO_NONPAGED_POOL); 04419 goto Failure; 04420 } 04421 04422 RtlClearAllBits (PagedPoolInfo->EndOfPagedPoolBitmap); 04423 04424 // 04425 // Create the large session allocation bitmap. 04426 // 04427 04428 MiCreateBitMap (&PagedPoolInfo->PagedPoolLargeSessionAllocationMap, 04429 MI_SESSION_POOL_SIZE >> PAGE_SHIFT, 04430 NonPagedPool); 04431 04432 if (PagedPoolInfo->PagedPoolLargeSessionAllocationMap == NULL) { 04433 MM_BUMP_SESSION_FAILURES (MM_SESSION_FAILURE_NO_NONPAGED_POOL); 04434 goto Failure; 04435 } 04436 04437 RtlClearAllBits (PagedPoolInfo->PagedPoolLargeSessionAllocationMap); 04438 04439 return STATUS_SUCCESS; 04440 04441 Failure: 04442 04443 MiFreeSessionPoolBitMaps (); 04444 04445 LOCK_PFN (OldIrql); 04446 04447 ASSERT (MmSessionSpace->SessionPageDirectoryIndex == Pfn1->PteFrame); 04448 ASSERT (Pfn1->u2.ShareCount == 1); 04449 MiDecrementShareAndValidCount (Pfn1->PteFrame); 04450 MI_SET_PFN_DELETED (Pfn1); 04451 MiDecrementShareCountOnly (PageFrameIndex); 04452 04453 MI_FLUSH_SINGLE_SESSION_TB (MiGetPteAddress(PointerPde), 04454 TRUE, 04455 TRUE, 04456 (PHARDWARE_PTE)PointerPde, 04457 ZeroKernelPte.u.Flush, 04458 PreviousPte); 04459 04460 MmSessionSpace->NonPagablePages -= 1; 04461 MmSessionSpace->CommittedPages -= 1; 04462 04463 MmResidentAvailablePages += 1; 04464 MM_BUMP_COUNTER(51, 1); 04465 MM_BUMP_SESS_COUNTER(MM_DBG_SESSION_PAGEDPOOL_PAGETABLE_FREE_FAIL1, 1); 04466 04467 UNLOCK_PFN (OldIrql); 04468 04469 MiReturnCommitment (1); 04470 04471 MM_TRACK_COMMIT (MM_DBG_COMMIT_RETURN_PAGED_POOL_PAGES, 1); 04472 04473 return STATUS_NO_MEMORY; 04474 }

VOID MiInitializeSessionWsSupport VOID   ) 
 

Definition at line 1847 of file wslist.c.

References MiSessionWsList.

Referenced by MmInitSystem().

01853 : 01854 01855 This routine initializes the session space working set support. 01856 01857 Arguments: 01858 01859 None. 01860 01861 Return Value: 01862 01863 None. 01864 01865 Environment: 01866 01867 Kernel mode, APC_LEVEL or below, no mutexes held. 01868 01869 --*/ 01870 01871 { 01872 // 01873 // This is the list of all session spaces ordered in a working set list. 01874 // 01875 01876 InitializeListHead (&MiSessionWsList); 01877 }

VOID MiInitializeSystemCache IN ULONG  MinimumWorkingSet,
IN ULONG  MaximumWorkingSet
 

Definition at line 814 of file mapcache.c.

References _MMSUPPORT::AllowWorkingSetAdjustment, COMPUTE_PAGES_SPANNED, _MMWSL::FirstDynamic, _MMWSL::FirstFree, _MMWSL::HashTable, _MMWSL::HashTableSize, _MMWSL::HashTableStart, _MMWSL::HighestPermittedHashAddress, L, _MMWSL::LastEntry, _MMWSL::LastInitializedWsle, _MMWORKING_SET_EXPANSION_HEAD::ListHead, LOCK_PFN, LOCK_SYSTEM_WS, _MMSUPPORT::MaximumWorkingSetSize, MI_GET_PAGE_COLOR_FROM_PTE, MI_PTE_BASE_FOR_LOWEST_KERNEL_ADDRESS, MI_WRITE_VALID_PTE, MiGetPteAddress, MiGrowWsleHash(), MiInitializePfn(), _MMSUPPORT::MinimumWorkingSetSize, MiRemoveZeroPage(), MiSystemCacheEndExtra, MiSystemCacheStartExtra, MM_EMPTY_PTE_LIST, MM_FREE_WSLE_SHIFT, MM_MAXIMUM_WORKING_SET, MM_SYSTEM_CACHE_START, MmFirstFreeSystemCache, MmLastFreeSystemCache, MmSystemCacheEnd, MmSystemCachePteBase, MmSystemCacheStart, MmSystemCacheWorkingSetList, MmSystemCacheWs, MmSystemCacheWsle, MmSystemCacheWsMaximum, MmSystemCacheWsMinimum, MmWorkingSetExpansionHead, MMWSLE, _MMWSL::NextSlot, NULL, PAGE_ALIGN, PAGE_SHIFT, PAGE_SIZE, _MMWSL::Quota, TRUE, _MMPTE::u, _MMWSLE::u1, UNLOCK_PFN, UNLOCK_SYSTEM_WS, _MMWSL::UsedPageTableEntries, ValidKernelPte, _MMSUPPORT::VmWorkingSetList, _MMSUPPORT::WorkingSetExpansionLinks, _MMSUPPORT::WorkingSetSize, _MMWSL::Wsle, WSLE_NULL_INDEX, and X256K.

Referenced by MmInitSystem().

00821 : 00822 00823 This routine initializes the system cache working set and 00824 data management structures. 00825 00826 Arguments: 00827 00828 MinimumWorkingSet - Supplies the minimum working set for the system 00829 cache. 00830 00831 MaximumWorkingSet - Supplies the maximum working set size for the 00832 system cache. 00833 00834 Return Value: 00835 00836 None. 00837 00838 Environment: 00839 00840 Kernel mode, called only at phase 0 initialization. 00841 00842 --*/ 00843 00844 { 00845 ULONG SizeOfSystemCacheInPages; 00846 ULONG HunksOf256KInCache; 00847 PMMWSLE WslEntry; 00848 ULONG NumberOfEntriesMapped; 00849 PFN_NUMBER i; 00850 MMPTE PteContents; 00851 PMMPTE PointerPte; 00852 KIRQL OldIrql; 00853 00854 PointerPte = MiGetPteAddress (MmSystemCacheWorkingSetList); 00855 00856 PteContents = ValidKernelPte; 00857 00858 LOCK_PFN (OldIrql); 00859 00860 i = MiRemoveZeroPage(MI_GET_PAGE_COLOR_FROM_PTE (PointerPte)); 00861 00862 PteContents.u.Hard.PageFrameNumber = i; 00863 00864 MI_WRITE_VALID_PTE (PointerPte, PteContents); 00865 00866 MiInitializePfn (i, PointerPte, 1L); 00867 00868 UNLOCK_PFN (OldIrql); 00869 00870 #if defined (_WIN64) 00871 MmSystemCacheWsle = (PMMWSLE)(MmSystemCacheWorkingSetList + 1); 00872 #else 00873 MmSystemCacheWsle = 00874 (PMMWSLE)(&MmSystemCacheWorkingSetList->UsedPageTableEntries[0]); 00875 #endif 00876 00877 MmSystemCacheWs.VmWorkingSetList = MmSystemCacheWorkingSetList; 00878 MmSystemCacheWs.WorkingSetSize = 0; 00879 MmSystemCacheWs.MinimumWorkingSetSize = MinimumWorkingSet; 00880 MmSystemCacheWs.MaximumWorkingSetSize = MaximumWorkingSet; 00881 InsertTailList (&MmWorkingSetExpansionHead.ListHead, 00882 &MmSystemCacheWs.WorkingSetExpansionLinks); 00883 00884 MmSystemCacheWs.AllowWorkingSetAdjustment = TRUE; 00885 00886 // 00887 // Don't use entry 0 as an index of zero in the PFN database 00888 // means that the page can be assigned to a slot. This is not 00889 // a problem for process working sets as page 0 is private. 00890 // 00891 00892 MmSystemCacheWorkingSetList->FirstFree = 1; 00893 MmSystemCacheWorkingSetList->FirstDynamic = 1; 00894 MmSystemCacheWorkingSetList->NextSlot = 1; 00895 MmSystemCacheWorkingSetList->LastEntry = (ULONG)MmSystemCacheWsMinimum; 00896 MmSystemCacheWorkingSetList->Quota = MmSystemCacheWorkingSetList->LastEntry; 00897 MmSystemCacheWorkingSetList->HashTable = NULL; 00898 MmSystemCacheWorkingSetList->HashTableSize = 0; 00899 MmSystemCacheWorkingSetList->Wsle = MmSystemCacheWsle; 00900 00901 MmSystemCacheWorkingSetList->HashTableStart = 00902 (PVOID)((PCHAR)PAGE_ALIGN (&MmSystemCacheWorkingSetList->Wsle[MM_MAXIMUM_WORKING_SET]) + PAGE_SIZE); 00903 00904 MmSystemCacheWorkingSetList->HighestPermittedHashAddress = (PVOID)(MM_SYSTEM_CACHE_START); 00905 00906 NumberOfEntriesMapped = (ULONG)(((PMMWSLE)((PCHAR)MmSystemCacheWorkingSetList + 00907 PAGE_SIZE)) - MmSystemCacheWsle); 00908 00909 LOCK_PFN (OldIrql); 00910 00911 while (NumberOfEntriesMapped < MmSystemCacheWsMaximum) { 00912 00913 PointerPte += 1; 00914 i = MiRemoveZeroPage(MI_GET_PAGE_COLOR_FROM_PTE (PointerPte)); 00915 PteContents.u.Hard.PageFrameNumber = i; 00916 MI_WRITE_VALID_PTE (PointerPte, PteContents); 00917 MiInitializePfn (i, PointerPte, 1L); 00918 NumberOfEntriesMapped += PAGE_SIZE / sizeof(MMWSLE); 00919 } 00920 00921 UNLOCK_PFN (OldIrql); 00922 00923 // 00924 // Initialize the following slots as free. 00925 // 00926 00927 WslEntry = MmSystemCacheWsle + 1; 00928 00929 for (i = 1; i < NumberOfEntriesMapped; i++) { 00930 00931 // 00932 // Build the free list, note that the first working 00933 // set entries (CurrentEntry) are not on the free list. 00934 // These entries are reserved for the pages which 00935 // map the working set and the page which contains the PDE. 00936 // 00937 00938 WslEntry->u1.Long = (i + 1) << MM_FREE_WSLE_SHIFT; 00939 WslEntry += 1; 00940 } 00941 00942 WslEntry -= 1; 00943 WslEntry->u1.Long = WSLE_NULL_INDEX << MM_FREE_WSLE_SHIFT; // End of list. 00944 00945 MmSystemCacheWorkingSetList->LastInitializedWsle = NumberOfEntriesMapped - 1; 00946 00947 // 00948 // Build a free list structure in the PTEs for the system cache. 00949 // 00950 00951 MmSystemCachePteBase = MI_PTE_BASE_FOR_LOWEST_KERNEL_ADDRESS; 00952 00953 SizeOfSystemCacheInPages = COMPUTE_PAGES_SPANNED (MmSystemCacheStart, 00954 (PCHAR)MmSystemCacheEnd - (PCHAR)MmSystemCacheStart + 1); 00955 00956 HunksOf256KInCache = SizeOfSystemCacheInPages / (X256K / PAGE_SIZE); 00957 00958 PointerPte = MiGetPteAddress (MmSystemCacheStart); 00959 00960 MmFirstFreeSystemCache = PointerPte; 00961 00962 for (i = 0; i < HunksOf256KInCache; i += 1) { 00963 PointerPte->u.List.NextEntry = (PointerPte + (X256K / PAGE_SIZE)) - MmSystemCachePteBase; 00964 PointerPte += X256K / PAGE_SIZE; 00965 } 00966 00967 PointerPte -= X256K / PAGE_SIZE; 00968 00969 #if defined(_X86_) 00970 00971 // 00972 // Add any extended ranges. 00973 // 00974 00975 if (MiSystemCacheEndExtra != MmSystemCacheEnd) { 00976 00977 SizeOfSystemCacheInPages = COMPUTE_PAGES_SPANNED (MiSystemCacheStartExtra, 00978 (PCHAR)MiSystemCacheEndExtra - (PCHAR)MiSystemCacheStartExtra + 1); 00979 00980 HunksOf256KInCache = SizeOfSystemCacheInPages / (X256K / PAGE_SIZE); 00981 00982 if (HunksOf256KInCache) { 00983 00984 PMMPTE PointerPteExtended; 00985 00986 PointerPteExtended = MiGetPteAddress (MiSystemCacheStartExtra); 00987 PointerPte->u.List.NextEntry = PointerPteExtended - MmSystemCachePteBase; 00988 PointerPte = PointerPteExtended; 00989 00990 for (i = 0; i < HunksOf256KInCache; i += 1) { 00991 PointerPte->u.List.NextEntry = (PointerPte + (X256K / PAGE_SIZE)) - MmSystemCachePteBase; 00992 PointerPte += X256K / PAGE_SIZE; 00993 } 00994 00995 PointerPte -= X256K / PAGE_SIZE; 00996 } 00997 } 00998 #endif 00999 01000 PointerPte->u.List.NextEntry = MM_EMPTY_PTE_LIST; 01001 MmLastFreeSystemCache = PointerPte; 01002 01003 if (MaximumWorkingSet > ((1536*1024) >> PAGE_SHIFT)) { 01004 01005 // 01006 // The working set list consists of more than a single page. 01007 // 01008 01009 LOCK_SYSTEM_WS (OldIrql); 01010 MiGrowWsleHash (&MmSystemCacheWs); 01011 UNLOCK_SYSTEM_WS (OldIrql); 01012 } 01013 }

VOID MiInitializeSystemPtes IN PMMPTE  StartingPte,
IN ULONG  NumberOfPtes,
IN MMSYSTEM_PTE_POOL_TYPE  SystemPteType
 

Definition at line 1740 of file sysptes.c.

References ASSERT, MI_PTE_BASE_FOR_LOWEST_KERNEL_ADDRESS, MI_WRITE_INVALID_PTE, MiAllocatePoolPages(), MiCountFreeSystemPtes(), MiFillMemoryPte, MiReleaseSystemPtes(), MiReserveSystemPtes(), MM_EMPTY_LIST, MM_EMPTY_PTE_LIST, MM_PTE_LIST_1, MM_PTE_LIST_16, MM_PTE_LIST_2, MM_PTE_LIST_4, MM_PTE_LIST_8, MM_SYS_PTE_TABLES_MAX, MmFirstFreeSystemPte, MmFlushCounter, MmFlushPte1, MmFreeSysPteListBySize, MmLastSysPteListBySize, MmSysPteIndex, MmSystemPteBase, MmSystemPtesEnd, MmSystemPtesStart, MmTotalFreeSystemPtes, NonPagedPool, NULL, SystemPteSpace, TRUE, _MMPTE::u, and ZeroKernelPte.

Referenced by MiInitializeNonPagedPool(), and MiInitMachineDependent().

01748 : 01749 01750 This routine initializes the system PTE pool. 01751 01752 Arguments: 01753 01754 StartingPte - Supplies the address of the first PTE to put in the pool. 01755 01756 NumberOfPtes - Supplies the number of PTEs to put in the pool. 01757 01758 SystemPtePoolType - Supplies the PTE type of the pool to initialize, one of 01759 SystemPteSpace or NonPagedPoolExpansion. 01760 01761 Return Value: 01762 01763 none. 01764 01765 Environment: 01766 01767 Kernel mode. 01768 01769 --*/ 01770 01771 { 01772 LONG i; 01773 LONG j; 01774 #ifdef _MI_SYSPTE_DEBUG_ 01775 PMMPTE_TRACKER Tracker; 01776 #endif 01777 01778 // 01779 // Set the base of the system PTE pool to this PTE. This takes into 01780 // account that systems may have additional PTE pools below the PTE_BASE. 01781 // 01782 01783 MmSystemPteBase = MI_PTE_BASE_FOR_LOWEST_KERNEL_ADDRESS; 01784 01785 MmSystemPtesStart[SystemPtePoolType] = StartingPte; 01786 MmSystemPtesEnd[SystemPtePoolType] = StartingPte + NumberOfPtes - 1; 01787 01788 // 01789 // If there are no PTEs specified, then make a valid chain by indicating 01790 // that the list is empty. 01791 // 01792 01793 if (NumberOfPtes == 0) { 01794 MmFirstFreeSystemPte[SystemPtePoolType] = ZeroKernelPte; 01795 MmFirstFreeSystemPte[SystemPtePoolType].u.List.NextEntry = 01796 MM_EMPTY_LIST; 01797 return; 01798 } 01799 01800 // 01801 // Initialize the specified system pte pool. 01802 // 01803 01804 MiFillMemoryPte (StartingPte, 01805 NumberOfPtes * sizeof (MMPTE), 01806 ZeroKernelPte.u.Long); 01807 01808 // 01809 // The page frame field points to the next cluster. As we only 01810 // have one cluster at initialization time, mark it as the last 01811 // cluster. 01812 // 01813 01814 StartingPte->u.List.NextEntry = MM_EMPTY_LIST; 01815 01816 MmFirstFreeSystemPte[SystemPtePoolType] = ZeroKernelPte; 01817 MmFirstFreeSystemPte[SystemPtePoolType].u.List.NextEntry = 01818 StartingPte - MmSystemPteBase; 01819 01820 // 01821 // If there is only one PTE in the pool, then mark it as a one entry 01822 // PTE. Otherwise, store the cluster size in the following PTE. 01823 // 01824 01825 if (NumberOfPtes == 1) { 01826 StartingPte->u.List.OneEntry = TRUE; 01827 01828 } else { 01829 StartingPte += 1; 01830 MI_WRITE_INVALID_PTE (StartingPte, ZeroKernelPte); 01831 StartingPte->u.List.NextEntry = NumberOfPtes; 01832 } 01833 01834 // 01835 // Set the total number of free PTEs for the specified type. 01836 // 01837 01838 MmTotalFreeSystemPtes[SystemPtePoolType] = NumberOfPtes; 01839 01840 ASSERT (MmTotalFreeSystemPtes[SystemPtePoolType] == 01841 MiCountFreeSystemPtes (SystemPtePoolType)); 01842 01843 if (SystemPtePoolType == SystemPteSpace) { 01844 01845 ULONG Lists[MM_SYS_PTE_TABLES_MAX] = {MM_PTE_LIST_1, MM_PTE_LIST_2, MM_PTE_LIST_4, MM_PTE_LIST_8, MM_PTE_LIST_16}; 01846 PMMPTE PointerPte; 01847 ULONG total; 01848 01849 #ifdef _MI_SYSPTE_DEBUG_ 01850 Tracker = (PMMPTE_TRACKER) MiAllocatePoolPages ( 01851 NonPagedPool, 01852 NumberOfPtes * sizeof (MMPTE_TRACKER), 01853 0); 01854 01855 if (Tracker) { 01856 RtlZeroMemory (Tracker, NumberOfPtes * sizeof (MMPTE_TRACKER)); 01857 } 01858 #endif 01859 01860 for (j = 0; j < MM_SYS_PTE_TABLES_MAX ; j++) { 01861 MmFreeSysPteListBySize [j].u.List.NextEntry = MM_EMPTY_PTE_LIST; 01862 MmLastSysPteListBySize [j] = &MmFreeSysPteListBySize [j]; 01863 } 01864 MmFlushCounter += 1; 01865 01866 #ifndef _MI_GUARD_PTE_ 01867 01868 // 01869 // Initialize the by size lists. 01870 // 01871 01872 total = MM_PTE_LIST_1 * MmSysPteIndex[0] + 01873 MM_PTE_LIST_2 * MmSysPteIndex[1] + 01874 MM_PTE_LIST_4 * MmSysPteIndex[2] + 01875 MM_PTE_LIST_8 * MmSysPteIndex[3] + 01876 MM_PTE_LIST_16 * MmSysPteIndex[4]; 01877 01878 PointerPte = MiReserveSystemPtes (total, 01879 SystemPteSpace, 01880 64*1024, 01881 0, 01882 TRUE); 01883 01884 for (i = (MM_SYS_PTE_TABLES_MAX - 1); i >= 0; i--) { 01885 do { 01886 Lists[i] -= 1; 01887 MiReleaseSystemPtes (PointerPte, 01888 MmSysPteIndex[i], 01889 SystemPteSpace); 01890 PointerPte += MmSysPteIndex[i]; 01891 } while (Lists[i] != 0 ); 01892 } 01893 #endif 01894 01895 MmFlushCounter += 1; 01896 MmFlushPte1 = NULL; 01897 01898 #ifdef _MI_SYSPTE_DEBUG_ 01899 MiPteTracker = Tracker; 01900 #endif 01901 } 01902 01903 return; 01904 }

BOOLEAN MiInitializeSystemSpaceMap PVOID Session  OPTIONAL  ) 
 

Referenced by MiBuildPagedPool(), and MiSessionCreateInternal().

VOID MiInitializeTransitionPfn IN PFN_NUMBER  PageFrameIndex,
IN PMMPTE  PointerPte,
IN WSLE_NUMBER  WorkingSetIndex
 

Definition at line 3650 of file pagfault.c.

References ASSERT, KeBugCheckEx(), MI_GET_PAGE_FRAME_FROM_PTE, MI_MAKE_TRANSITION_PTE, MI_PFN_ELEMENT, MI_PROTOTYPE_WSINDEX, MI_WRITE_INVALID_PTE, MiCheckPdeForPagedPool(), MiGetPteAddress, MiGetVirtualAddressMappedByPte, MM_PFN_LOCK_ASSERT, NT_SUCCESS, NULL, _MMPFN::OriginalPte, _MMPFN::PteAddress, _MMPFN::PteFrame, TransitionPage, _MMPTE::u, _MMPFN::u1, _MMPFN::u2, and _MMPFN::u3.

Referenced by MiUpdateImageHeaderPage(), and MmCopyToCachedPage().

03658 : 03659 03660 This function initializes the specified PFN element to the 03661 transition state. Main use is by MapImageFile to make the 03662 page which contains the image header transition in the 03663 prototype PTEs. 03664 03665 Arguments: 03666 03667 PageFrameIndex - Supplies the page frame index to be initialized. 03668 03669 PointerPte - Supplies an invalid, non-transition PTE to initialize. 03670 03671 WorkingSetIndex - Supplies the working set index flag, a value of 03672 MI_PROTOTYPE_WSINDEX indicates no WSLE is required 03673 because this is a prototype PTE. 03674 03675 Return Value: 03676 03677 None. 03678 03679 Environment: 03680 03681 Kernel mode, APCs disabled, PFN mutex held. 03682 03683 --*/ 03684 03685 { 03686 PMMPFN Pfn1; 03687 PMMPFN Pfn2; 03688 PMMPTE PteFramePointer; 03689 PFN_NUMBER PteFramePage; 03690 MMPTE TempPte; 03691 03692 MM_PFN_LOCK_ASSERT(); 03693 Pfn1 = MI_PFN_ELEMENT (PageFrameIndex); 03694 Pfn1->u1.Event = NULL; 03695 Pfn1->PteAddress = PointerPte; 03696 Pfn1->OriginalPte = *PointerPte; 03697 ASSERT (!((Pfn1->OriginalPte.u.Soft.Prototype == 0) && 03698 (Pfn1->OriginalPte.u.Soft.Transition == 1))); 03699 03700 // 03701 // Don't change the reference count (it should already be 1). 03702 // 03703 03704 Pfn1->u2.ShareCount = 0; 03705 03706 if (WorkingSetIndex == MI_PROTOTYPE_WSINDEX) { 03707 Pfn1->u3.e1.PrototypePte = 1; 03708 } 03709 03710 Pfn1->u3.e1.PageLocation = TransitionPage; 03711 03712 // 03713 // Determine the page frame number of the page table page which 03714 // contains this PTE. 03715 // 03716 03717 PteFramePointer = MiGetPteAddress(PointerPte); 03718 if (PteFramePointer->u.Hard.Valid == 0) { 03719 #if !defined (_WIN64) 03720 if (!NT_SUCCESS(MiCheckPdeForPagedPool (PointerPte))) { 03721 #endif 03722 KeBugCheckEx (MEMORY_MANAGEMENT, 03723 0x61940, 03724 (ULONG_PTR)PointerPte, 03725 (ULONG_PTR)PteFramePointer->u.Long, 03726 (ULONG_PTR)MiGetVirtualAddressMappedByPte(PointerPte)); 03727 #if !defined (_WIN64) 03728 } 03729 #endif 03730 } 03731 03732 PteFramePage = MI_GET_PAGE_FRAME_FROM_PTE (PteFramePointer); 03733 Pfn1->PteFrame = PteFramePage; 03734 03735 #if PFN_CONSISTENCY 03736 Pfn1->u3.e1.PageTablePage = 0; 03737 #endif 03738 03739 // 03740 // Put the PTE into the transition state, no cache flush needed as 03741 // PTE is still not valid. 03742 // 03743 03744 MI_MAKE_TRANSITION_PTE (TempPte, 03745 PageFrameIndex, 03746 PointerPte->u.Soft.Protection, 03747 PointerPte); 03748 03749 MI_WRITE_INVALID_PTE (PointerPte, TempPte); 03750 03751 // 03752 // Increment the share count for the page table page containing 03753 // this PTE as the PTE just went into the transition state. 03754 // 03755 03756 Pfn2 = MI_PFN_ELEMENT (PteFramePage); 03757 ASSERT (PteFramePage != 0); 03758 Pfn2->u2.ShareCount += 1; 03759 03760 return; 03761 }

VOID MiInitializeWorkingSetList IN PEPROCESS  CurrentProcess  ) 
 

Definition at line 1481 of file wslist.c.

References ASSERT, CONSISTENCY_LOCK_PFN, CONSISTENCY_UNLOCK_PFN, _MMWSL::FirstDynamic, _MMWSL::FirstFree, _MMWSL::HashTable, _MMWSL::HashTableSize, _MMWSL::HashTableStart, _MMWSL::HighestPermittedHashAddress, HYPER_SPACE, HYPER_SPACE_END, _MMWSL::LastEntry, _MMWSL::LastInitializedWsle, LOCK_PFN, MI_MAKE_VALID_PTE, MI_PAGE_COLOR_PTE_PROCESS, MI_PFN_ELEMENT, MI_SET_PTE_DIRTY, MI_SET_PTE_IN_WORKING_SET, MI_WRITE_VALID_PTE, MiEnsureAvailablePageOrWait(), MiGetPdeAddress, MiGetPpeAddress, MiGetPteAddress, MiGrowWsleHash(), MiInitializePfn(), MiRemoveZeroPage(), MM_DEMAND_ZERO_WRITE_PTE, MM_FREE_WSLE_SHIFT, MM_MAXIMUM_WORKING_SET, MM_READWRITE, MM_SESSION_SPACE_DEFAULT, MmWorkingSetList, MmWsle, _MMWSL::NextSlot, NULL, PAGE_ALIGN, PAGE_SHIFT, PAGE_SIZE, _MMWSL::Quota, _MMPTE::u, _MMWSLE::u1, _MMPFN::u1, UNLOCK_PFN, _MMWSL::WaitingForImageMapping, WORKING_SET_LIST, _MMWSL::Wsle, WSLE_NULL_INDEX, and WSLE_NUMBER.

Referenced by MmInitializeProcessAddressSpace().

01487 : 01488 01489 This routine initializes a process's working set to the empty 01490 state. 01491 01492 Arguments: 01493 01494 CurrentProcess - Supplies a pointer to the process to initialize. 01495 01496 Return Value: 01497 01498 None. 01499 01500 Environment: 01501 01502 Kernel mode, APCs disabled. 01503 01504 --*/ 01505 01506 { 01507 ULONG i; 01508 PMMWSLE WslEntry; 01509 ULONG CurrentEntry; 01510 PMMPTE PointerPte; 01511 PMMPFN Pfn1; 01512 WSLE_NUMBER NumberOfEntriesMapped; 01513 ULONG_PTR CurrentVa; 01514 PFN_NUMBER WorkingSetPage; 01515 MMPTE TempPte; 01516 KIRQL OldIrql; 01517 01518 WslEntry = MmWsle; 01519 01520 // 01521 // Initialize the temporary double mapping portion of hyperspace, if 01522 // it has not already been done. 01523 // 01524 // Initialize the working set list control cells. 01525 // 01526 01527 MmWorkingSetList->LastEntry = CurrentProcess->Vm.MinimumWorkingSetSize; 01528 MmWorkingSetList->Quota = MmWorkingSetList->LastEntry; 01529 MmWorkingSetList->WaitingForImageMapping = (PKEVENT)NULL; 01530 MmWorkingSetList->HashTable = NULL; 01531 MmWorkingSetList->HashTableSize = 0; 01532 MmWorkingSetList->Wsle = MmWsle; 01533 MmWorkingSetList->HashTableStart = 01534 (PVOID)((PCHAR)PAGE_ALIGN (&MmWsle[MM_MAXIMUM_WORKING_SET]) + PAGE_SIZE); 01535 01536 MmWorkingSetList->HighestPermittedHashAddress = (PVOID)(HYPER_SPACE_END + 1); 01537 01538 // 01539 // Fill in the reserved slots. Start with the page directory page. 01540 // 01541 01542 #if !defined (_X86PAE_) 01543 01544 WslEntry->u1.Long = PDE_BASE; 01545 WslEntry->u1.e1.Valid = 1; 01546 WslEntry->u1.e1.LockedInWs = 1; 01547 WslEntry->u1.e1.Direct = 1; 01548 01549 PointerPte = MiGetPteAddress (WslEntry->u1.VirtualAddress); 01550 Pfn1 = MI_PFN_ELEMENT (PointerPte->u.Hard.PageFrameNumber); 01551 01552 CONSISTENCY_LOCK_PFN (OldIrql); 01553 01554 #if !defined (_WIN64) 01555 Pfn1->u1.Event = (PVOID)CurrentProcess; 01556 #endif 01557 01558 CONSISTENCY_UNLOCK_PFN (OldIrql); 01559 01560 #else 01561 01562 // 01563 // Fill in all the page directory entries. 01564 // 01565 01566 for (i = 0; i < PD_PER_SYSTEM; i += 1) { 01567 01568 WslEntry->u1.VirtualAddress = (PVOID)(PDE_BASE + i * PAGE_SIZE); 01569 WslEntry->u1.e1.Valid = 1; 01570 WslEntry->u1.e1.LockedInWs = 1; 01571 WslEntry->u1.e1.Direct = 1; 01572 01573 PointerPte = MiGetPteAddress (WslEntry->u1.VirtualAddress); 01574 Pfn1 = MI_PFN_ELEMENT (PointerPte->u.Hard.PageFrameNumber); 01575 01576 ASSERT (Pfn1->u1.WsIndex == 0); 01577 01578 CONSISTENCY_LOCK_PFN (OldIrql); 01579 01580 Pfn1->u1.WsIndex = (WSLE_NUMBER)(WslEntry - MmWsle); 01581 01582 CONSISTENCY_UNLOCK_PFN (OldIrql); 01583 01584 WslEntry += 1; 01585 } 01586 WslEntry -= 1; 01587 01588 #endif 01589 01590 01591 #if defined (_WIN64) 01592 01593 // 01594 // Fill in the entry for the page directory parent page. 01595 // 01596 01597 WslEntry += 1; 01598 01599 WslEntry->u1.Long = PDE_TBASE; 01600 WslEntry->u1.e1.Valid = 1; 01601 WslEntry->u1.e1.LockedInWs = 1; 01602 WslEntry->u1.e1.Direct = 1; 01603 01604 PointerPte = MiGetPteAddress (WslEntry->u1.VirtualAddress); 01605 Pfn1 = MI_PFN_ELEMENT (PointerPte->u.Hard.PageFrameNumber); 01606 01607 ASSERT (Pfn1->u1.WsIndex == 0); 01608 01609 CONSISTENCY_LOCK_PFN (OldIrql); 01610 01611 Pfn1->u1.WsIndex = (WSLE_NUMBER)(WslEntry - MmWsle); 01612 01613 CONSISTENCY_UNLOCK_PFN (OldIrql); 01614 01615 // 01616 // Fill in the entry for the hyper space page directory page. 01617 // 01618 01619 WslEntry += 1; 01620 01621 WslEntry->u1.VirtualAddress = (PVOID)MiGetPdeAddress (HYPER_SPACE); 01622 WslEntry->u1.e1.Valid = 1; 01623 WslEntry->u1.e1.LockedInWs = 1; 01624 WslEntry->u1.e1.Direct = 1; 01625 01626 PointerPte = MiGetPteAddress (WslEntry->u1.VirtualAddress); 01627 Pfn1 = MI_PFN_ELEMENT (PointerPte->u.Hard.PageFrameNumber); 01628 01629 ASSERT (Pfn1->u1.WsIndex == 0); 01630 01631 CONSISTENCY_LOCK_PFN (OldIrql); 01632 01633 Pfn1->u1.WsIndex = (WSLE_NUMBER)(WslEntry - MmWsle); 01634 01635 CONSISTENCY_UNLOCK_PFN (OldIrql); 01636 01637 #if defined (_IA64_) 01638 01639 // 01640 // Fill in the entry for the session space page directory parent page. 01641 // 01642 01643 WslEntry += 1; 01644 01645 WslEntry->u1.VirtualAddress = (PVOID)MiGetPpeAddress (MM_SESSION_SPACE_DEFAULT); 01646 WslEntry->u1.e1.Valid = 1; 01647 WslEntry->u1.e1.LockedInWs = 1; 01648 WslEntry->u1.e1.Direct = 1; 01649 01650 PointerPte = MiGetPteAddress (WslEntry->u1.VirtualAddress); 01651 Pfn1 = MI_PFN_ELEMENT (PointerPte->u.Hard.PageFrameNumber); 01652 01653 ASSERT (Pfn1->u1.WsIndex == 0); 01654 01655 CONSISTENCY_LOCK_PFN (OldIrql); 01656 01657 Pfn1->u1.WsIndex = (WSLE_NUMBER)(WslEntry - MmWsle); 01658 01659 CONSISTENCY_UNLOCK_PFN (OldIrql); 01660 01661 #endif 01662 01663 #endif 01664 01665 // 01666 // Fill in the entry for the page table page which maps hyper space. 01667 // 01668 01669 WslEntry += 1; 01670 01671 WslEntry->u1.VirtualAddress = (PVOID)MiGetPteAddress (HYPER_SPACE); 01672 WslEntry->u1.e1.Valid = 1; 01673 WslEntry->u1.e1.LockedInWs = 1; 01674 WslEntry->u1.e1.Direct = 1; 01675 01676 PointerPte = MiGetPteAddress (WslEntry->u1.VirtualAddress); 01677 Pfn1 = MI_PFN_ELEMENT (PointerPte->u.Hard.PageFrameNumber); 01678 01679 ASSERT (Pfn1->u1.WsIndex == 0); 01680 01681 CONSISTENCY_LOCK_PFN (OldIrql); 01682 01683 Pfn1->u1.WsIndex = (WSLE_NUMBER)(WslEntry - MmWsle); 01684 01685 CONSISTENCY_UNLOCK_PFN (OldIrql); 01686 01687 #if defined (_X86PAE_) 01688 01689 // 01690 // Fill in the entry for the second page table page which maps hyper space. 01691 // 01692 01693 WslEntry += 1; 01694 01695 WslEntry->u1.VirtualAddress = (PVOID)MiGetPteAddress (HYPER_SPACE2); 01696 WslEntry->u1.e1.Valid = 1; 01697 WslEntry->u1.e1.LockedInWs = 1; 01698 WslEntry->u1.e1.Direct = 1; 01699 01700 PointerPte = MiGetPteAddress (WslEntry->u1.VirtualAddress); 01701 Pfn1 = MI_PFN_ELEMENT (PointerPte->u.Hard.PageFrameNumber); 01702 01703 ASSERT (Pfn1->u1.WsIndex == 0); 01704 01705 CONSISTENCY_LOCK_PFN (OldIrql); 01706 01707 Pfn1->u1.WsIndex = (WSLE_NUMBER)(WslEntry - MmWsle); 01708 01709 CONSISTENCY_UNLOCK_PFN (OldIrql); 01710 01711 #endif 01712 01713 // 01714 // Fill in the entry for the page which contains the working set list. 01715 // 01716 01717 WslEntry += 1; 01718 01719 WslEntry->u1.VirtualAddress = (PVOID)MmWorkingSetList; 01720 WslEntry->u1.e1.Valid = 1; 01721 WslEntry->u1.e1.LockedInWs = 1; 01722 WslEntry->u1.e1.Direct = 1; 01723 01724 PointerPte = MiGetPteAddress (WslEntry->u1.VirtualAddress); 01725 Pfn1 = MI_PFN_ELEMENT (PointerPte->u.Hard.PageFrameNumber); 01726 01727 ASSERT (Pfn1->u1.WsIndex == 0); 01728 01729 CONSISTENCY_LOCK_PFN (OldIrql); 01730 01731 Pfn1->u1.WsIndex = (WSLE_NUMBER)(WslEntry - MmWsle); 01732 01733 CONSISTENCY_UNLOCK_PFN (OldIrql); 01734 01735 CurrentEntry = (WSLE_NUMBER)((WslEntry - MmWsle) + 1); 01736 01737 // 01738 // Check to see if more pages are required in the working set list 01739 // to map the current maximum working set size. 01740 // 01741 01742 NumberOfEntriesMapped = (WSLE_NUMBER)(((PMMWSLE)((PCHAR)WORKING_SET_LIST + PAGE_SIZE)) - 01743 MmWsle); 01744 01745 if (CurrentProcess->Vm.MaximumWorkingSetSize >= NumberOfEntriesMapped) { 01746 01747 PointerPte = MiGetPteAddress (&MmWsle[0]); 01748 01749 CurrentVa = (ULONG_PTR)MmWorkingSetList + PAGE_SIZE; 01750 01751 // 01752 // The working set requires more than a single page. 01753 // 01754 01755 LOCK_PFN (OldIrql); 01756 01757 do { 01758 01759 MiEnsureAvailablePageOrWait (NULL, NULL); 01760 01761 PointerPte += 1; 01762 WorkingSetPage = MiRemoveZeroPage ( 01763 MI_PAGE_COLOR_PTE_PROCESS (PointerPte, 01764 &CurrentProcess->NextPageColor)); 01765 PointerPte->u.Long = MM_DEMAND_ZERO_WRITE_PTE; 01766 01767 MiInitializePfn (WorkingSetPage, PointerPte, 1); 01768 01769 MI_MAKE_VALID_PTE (TempPte, 01770 WorkingSetPage, 01771 MM_READWRITE, 01772 PointerPte ); 01773 01774 MI_SET_PTE_DIRTY (TempPte); 01775 01776 MI_SET_PTE_IN_WORKING_SET (&TempPte, CurrentEntry); 01777 01778 MI_WRITE_VALID_PTE (PointerPte, TempPte); 01779 01780 WslEntry += 1; 01781 01782 WslEntry->u1.Long = CurrentVa; 01783 WslEntry->u1.e1.Valid = 1; 01784 WslEntry->u1.e1.LockedInWs = 1; 01785 WslEntry->u1.e1.Direct = 1; 01786 01787 Pfn1 = MI_PFN_ELEMENT (PointerPte->u.Hard.PageFrameNumber); 01788 01789 ASSERT (Pfn1->u1.WsIndex == 0); 01790 Pfn1->u1.WsIndex = CurrentEntry; 01791 01792 // MiInsertWsle(CurrentEntry, MmWorkingSetList); 01793 01794 CurrentEntry += 1; 01795 CurrentVa += PAGE_SIZE; 01796 01797 NumberOfEntriesMapped += PAGE_SIZE / sizeof(MMWSLE); 01798 01799 } while (CurrentProcess->Vm.MaximumWorkingSetSize >= NumberOfEntriesMapped); 01800 01801 UNLOCK_PFN (OldIrql); 01802 } 01803 01804 CurrentProcess->Vm.WorkingSetSize = CurrentEntry; 01805 MmWorkingSetList->FirstFree = CurrentEntry; 01806 MmWorkingSetList->FirstDynamic = CurrentEntry; 01807 MmWorkingSetList->NextSlot = CurrentEntry; 01808 01809 // 01810 // Initialize the following slots as free. 01811 // 01812 01813 i = CurrentEntry + 1; 01814 do { 01815 01816 // 01817 // Build the free list, note that the first working 01818 // set entries (CurrentEntry) are not on the free list. 01819 // These entries are reserved for the pages which 01820 // map the working set and the page which contains the PDE. 01821 // 01822 01823 WslEntry += 1; 01824 WslEntry->u1.Long = i << MM_FREE_WSLE_SHIFT; 01825 i += 1; 01826 } while (i <= NumberOfEntriesMapped); 01827 01828 WslEntry->u1.Long = WSLE_NULL_INDEX << MM_FREE_WSLE_SHIFT; // End of list. 01829 01830 MmWorkingSetList->LastInitializedWsle = 01831 NumberOfEntriesMapped - 1; 01832 01833 if (CurrentProcess->Vm.MaximumWorkingSetSize > ((1536*1024) >> PAGE_SHIFT)) { 01834 01835 // 01836 // The working set list consists of more than a single page. 01837 // 01838 01839 MiGrowWsleHash (&CurrentProcess->Vm); 01840 } 01841 01842 return; 01843 }

VOID MiInitMachineDependent IN PLOADER_PARAMETER_BLOCK  LoaderBlock  ) 
 

Definition at line 41 of file inialpha.c.

References _16MB, _1MB, ActiveAndValid, ASSERT, BadPageList, _MEMORY_ALLOCATION_DESCRIPTOR::BasePage, _MMPFNLIST::Blink, Buffer, c, CHAR, DISPATCH_LEVEL, ExAllocatePoolWithTag, FALSE, FIRST_MAPPING_PTE, _MMPFNLIST::Flink, _MMCOLOR_TABLES::Flink, FreePageList, HYPER_SPACE, InbvDisplayString(), InitializePool(), KeBugCheck(), KeBugCheckEx(), KeFlushSingleTb(), KeInitializeSpinLock(), KeLowerIrql(), KeRaiseIrql(), KeSweepDcache(), KSEG0_BASE, LAST_MAPPING_PTE, _MEMORY_ALLOCATION_DESCRIPTOR::ListEntry, _MMPFNLIST::ListName, LoaderBad, LoaderFirmwareTemporary, LoaderFree, LoaderLoadedProgram, LoaderOsloaderHeap, LoaderOsloaderStack, LOCK_PFN, _MMSUPPORT::MaximumWorkingSetSize, _MEMORY_ALLOCATION_DESCRIPTOR::MemoryType, MI_CONVERT_PHYSICAL_TO_PFN, MI_GET_COLOR_FROM_SECONDARY, MI_GET_PAGE_COLOR_FROM_PTE, MI_IS_PHYSICAL_ADDRESS, MI_PFN_ELEMENT, MI_SESSION_SPACE_END, MI_SET_PFN_DELETED, MiGetPdeAddress, MiGetPteAddress, MiGetVirtualAddressMappedByPte, MiHydra, MiInitializeNonPagedPool(), MiInitializeSystemPtes(), MiInsertPageInList(), _MMSUPPORT::MinimumWorkingSetSize, MiRemoveAnyPage(), MiRequestedSystemPtes, MiReserveSystemPtes(), MM_COLOR_MASK, MM_EMPTY_LIST, MM_LOWEST_NONPAGED_SYSTEM_START, MM_MAX_ADDITIONAL_NONPAGED_POOL, MM_MAX_INITIAL_NONPAGED_POOL, MM_MAXIMUM_NUMBER_OF_COLORS, MM_PAGES_IN_KSEG0, MM_SECONDARY_COLORS_DEFAULT, MM_SECONDARY_COLORS_MAX, MM_SECONDARY_COLORS_MIN, MM_SUBSECTION_MAP, MM_SYSTEM_SPACE_END, MM_SYSTEM_SPACE_START, MMCOLOR_TABLES, MmDefaultMaximumNonPagedPool, MmDynamicPfn, MmExpandedNonPagedPoolInBytes, MmFirstReservedMappingPte, MmFreePagesByColor, MmFreePagesByPrimaryColor, MmHiberPages, MmHighestPhysicalPage, MmHighestPossiblePhysicalPage, MmInitializeProcessAddressSpace(), MmIsAddressValid(), MmLastReservedMappingPte, MmLowestPhysicalPage, MmMaxAdditionNonPagedPoolPerMb, MmMaximumNonPagedPoolInBytes, MmMinAdditionNonPagedPoolPerMb, MmMinimumNonPagedPoolSize, MmNonPagedMustSucceed, MmNonPagedPoolEnd, MmNonPagedPoolExpansionStart, MmNonPagedPoolStart, MmNonPagedSystemStart, MmNumberOfPhysicalPages, MmNumberOfSystemPtes, MmPageAlignedPoolBase, MmPageLocationList, MMPFN, MmPfnDatabase, MmPfnLock, MmSecondaryColorMask, MmSecondaryColors, MmSessionBase, MmSizeOfNonPagedMustSucceed, MmSizeOfNonPagedPoolInBytes, MmSubsectionBase, MmSubsectionTopPage, MmSystemProcessWorkingSetMax, MmSystemProcessWorkingSetMin, MmSystemSpaceLock, MmWorkingSetList, MMWSL, MmWsle, NON_PAGED_SYSTEM_END, NonPagedPool, NonPagedPoolExpansion, NonPagedPoolMustSucceed, NULL, NUMBER_OF_MAPPING_PTES, PAGE_ALIGN, PAGE_DIRECTORY_MASK, PAGE_SHIFT, PAGE_SIZE, _MEMORY_ALLOCATION_DESCRIPTOR::PageCount, PDE_PER_PAGE, PsGetCurrentProcess, PTE_PER_PAGE, PTE_SHIFT, _MMPFN::PteAddress, _MMPFN::PteFrame, RtlCompareMemoryUlong(), sprintf(), StandbyPageList, SystemPteSpace, TRUE, _MMPTE::u, _MMPFN::u2, _MMPFN::u3, UNLOCK_PFN, ValidKernelPte, _EPROCESS::Vm, WORKING_SET_LIST, _EPROCESS::WorkingSetPage, ZeroedPageList, and ZeroKernelPte.

Referenced by MmInitSystem().

00047 : 00048 00049 This routine performs the necessary operations to enable virtual 00050 memory. This includes building the page directory page, building 00051 page table pages to map the code section, the data section, the' 00052 stack section and the trap handler. 00053 00054 It also initializes the PFN database and populates the free list. 00055 00056 00057 Arguments: 00058 00059 None. 00060 00061 Return Value: 00062 00063 None. 00064 00065 Environment: 00066 00067 Kernel mode. 00068 00069 --*/ 00070 00071 { 00072 PMMPFN BasePfn; 00073 PMMPFN BottomPfn; 00074 PMMPFN TopPfn; 00075 BOOLEAN PfnInKseg0; 00076 ULONG LowMemoryReserved; 00077 ULONG i, j; 00078 ULONG HighPage; 00079 ULONG PagesLeft; 00080 ULONG PageNumber; 00081 ULONG PdePageNumber; 00082 ULONG PdePage; 00083 ULONG PageFrameIndex; 00084 ULONG NextPhysicalPage; 00085 ULONG PfnAllocation; 00086 ULONG NumberOfPages; 00087 PEPROCESS CurrentProcess; 00088 PVOID SpinLockPage; 00089 ULONG MostFreePage; 00090 ULONG MostFreeLowMem; 00091 PLIST_ENTRY NextMd; 00092 ULONG MaxPool; 00093 KIRQL OldIrql; 00094 PMEMORY_ALLOCATION_DESCRIPTOR FreeDescriptor; 00095 PMEMORY_ALLOCATION_DESCRIPTOR FreeDescriptorLowMem; 00096 PMEMORY_ALLOCATION_DESCRIPTOR MemoryDescriptor; 00097 MMPTE TempPte; 00098 PMMPTE PointerPde; 00099 PMMPTE PointerPte; 00100 PMMPTE LastPte; 00101 PMMPTE CacheStackPage; 00102 PMMPTE Pde; 00103 PMMPTE StartPde; 00104 PMMPTE EndPde; 00105 PMMPFN Pfn1; 00106 PMMPFN Pfn2; 00107 PULONG PointerLong; 00108 CHAR Buffer[256]; 00109 PMMFREE_POOL_ENTRY Entry; 00110 PVOID NonPagedPoolStartVirtual; 00111 ULONG Range; 00112 ULONG RemovedLowPage; 00113 ULONG RemovedLowCount; 00114 00115 RemovedLowPage = 0; 00116 RemovedLowCount = 0; 00117 LowMemoryReserved = 0; 00118 MostFreePage = 0; 00119 MostFreeLowMem = 0; 00120 FreeDescriptor = NULL; 00121 FreeDescriptorLowMem = NULL; 00122 00123 PointerPte = MiGetPdeAddress (PDE_BASE); 00124 00125 PdePageNumber = PointerPte->u.Hard.PageFrameNumber; 00126 00127 PsGetCurrentProcess()->Pcb.DirectoryTableBase[0] = PointerPte->u.Long; 00128 00129 KeSweepDcache (FALSE); 00130 00131 // 00132 // Get the lower bound of the free physical memory and the 00133 // number of physical pages by walking the memory descriptor lists. 00134 // In addition, find the memory descriptor with the most free pages 00135 // that begins at a physical address less than 16MB. The 16 MB 00136 // boundary is necessary for allocating common buffers for use by 00137 // ISA devices that cannot address more than 24 bits. 00138 // 00139 00140 NextMd = LoaderBlock->MemoryDescriptorListHead.Flink; 00141 00142 // 00143 // When restoring a hibernation image, OS Loader needs to use "a few" extra 00144 // pages of LoaderFree memory. 00145 // This is not accounted for when reserving memory for hibernation below. 00146 // Start with a safety margin to allow for this plus modest future increase. 00147 // 00148 00149 MmHiberPages = 96; 00150 00151 while (NextMd != &LoaderBlock->MemoryDescriptorListHead) { 00152 00153 MemoryDescriptor = CONTAINING_RECORD(NextMd, 00154 MEMORY_ALLOCATION_DESCRIPTOR, 00155 ListEntry); 00156 00157 HighPage = MemoryDescriptor->BasePage + MemoryDescriptor->PageCount-1; 00158 00159 // 00160 // This check results in /BURNMEMORY chunks not being counted. 00161 // 00162 00163 if (MemoryDescriptor->MemoryType != LoaderBad) { 00164 MmNumberOfPhysicalPages += MemoryDescriptor->PageCount; 00165 } 00166 00167 if (MemoryDescriptor->BasePage < MmLowestPhysicalPage) { 00168 MmLowestPhysicalPage = MemoryDescriptor->BasePage; 00169 } 00170 00171 if (HighPage > MmHighestPhysicalPage) { 00172 MmHighestPhysicalPage = HighPage; 00173 } 00174 00175 // 00176 // Locate the largest free block starting below 16 megs 00177 // and the largest free block. 00178 // 00179 00180 if ((MemoryDescriptor->MemoryType == LoaderFree) || 00181 (MemoryDescriptor->MemoryType == LoaderLoadedProgram) || 00182 (MemoryDescriptor->MemoryType == LoaderFirmwareTemporary) || 00183 (MemoryDescriptor->MemoryType == LoaderOsloaderStack)) { 00184 00185 // 00186 // Every page that will be used as free memory that is not already 00187 // marked as LoaderFree must be counted so a hibernate can reserve 00188 // the proper amount. 00189 // 00190 00191 if (MemoryDescriptor->MemoryType != LoaderFree) { 00192 MmHiberPages += MemoryDescriptor->PageCount; 00193 } 00194 00195 if ((MemoryDescriptor->PageCount > MostFreeLowMem) && 00196 (MemoryDescriptor->BasePage < (_16MB >> PAGE_SHIFT)) && 00197 (HighPage < MM_PAGES_IN_KSEG0)) { 00198 00199 MostFreeLowMem = MemoryDescriptor->PageCount; 00200 FreeDescriptorLowMem = MemoryDescriptor; 00201 00202 } else if (MemoryDescriptor->PageCount > MostFreePage) { 00203 00204 MostFreePage = MemoryDescriptor->PageCount; 00205 FreeDescriptor = MemoryDescriptor; 00206 } 00207 } else if (MemoryDescriptor->MemoryType == LoaderOsloaderHeap) { 00208 // 00209 // We do not want to use this memory yet as it still has important 00210 // data structures in it. But we still want to account for this in 00211 // the hibernation pages 00212 // 00213 MmHiberPages += MemoryDescriptor->PageCount; 00214 } 00215 00216 NextMd = MemoryDescriptor->ListEntry.Flink; 00217 } 00218 00219 // 00220 // Perform sanity checks on the results of walking the memory 00221 // descriptors. 00222 // 00223 00224 if (MmNumberOfPhysicalPages < 1024) { 00225 KeBugCheckEx (INSTALL_MORE_MEMORY, 00226 MmNumberOfPhysicalPages, 00227 MmLowestPhysicalPage, 00228 MmHighestPhysicalPage, 00229 0); 00230 } 00231 00232 if (FreeDescriptorLowMem == NULL){ 00233 InbvDisplayString("MmInit *** FATAL ERROR *** no free descriptors that begin below physical address 16MB\n"); 00234 KeBugCheck (MEMORY_MANAGEMENT); 00235 } 00236 00237 if (MmDynamicPfn == TRUE) { 00238 00239 // 00240 // Since a ~128mb PFN database is required to span the 32GB supported 00241 // by Alpha, require 256mb of memory to be present to support 00242 // this option. 00243 // 00244 00245 if (MmNumberOfPhysicalPages >= (256 * 1024 * 1024) / PAGE_SIZE) { 00246 MmHighestPossiblePhysicalPage = 0x400000 - 1; 00247 } 00248 else { 00249 MmDynamicPfn = FALSE; 00250 } 00251 } 00252 else { 00253 MmHighestPossiblePhysicalPage = MmHighestPhysicalPage; 00254 } 00255 00256 // 00257 // Used later to build nonpaged pool. 00258 // 00259 00260 NextPhysicalPage = FreeDescriptorLowMem->BasePage; 00261 NumberOfPages = FreeDescriptorLowMem->PageCount; 00262 00263 // 00264 // Build non-paged pool using the physical pages following the 00265 // data page in which to build the pool from. Non-paged pool grows 00266 // from the high range of the virtual address space and expands 00267 // downward. 00268 // 00269 // At this time non-paged pool is constructed so virtual addresses 00270 // are also physically contiguous. 00271 // 00272 00273 if ((MmSizeOfNonPagedPoolInBytes >> PAGE_SHIFT) > 00274 (7 * (MmNumberOfPhysicalPages >> 3))) { 00275 00276 // 00277 // More than 7/8 of memory allocated to nonpagedpool, reset to 0. 00278 // 00279 00280 MmSizeOfNonPagedPoolInBytes = 0; 00281 } 00282 00283 if (MmSizeOfNonPagedPoolInBytes < MmMinimumNonPagedPoolSize) { 00284 00285 // 00286 // Calculate the size of nonpaged pool. Use the minimum size, 00287 // then for every MB above 8mb add extra pages. 00288 // 00289 00290 MmSizeOfNonPagedPoolInBytes = MmMinimumNonPagedPoolSize; 00291 00292 MmSizeOfNonPagedPoolInBytes += 00293 ((MmNumberOfPhysicalPages - 1024) / 00294 (_1MB >> PAGE_SHIFT) ) * 00295 MmMinAdditionNonPagedPoolPerMb; 00296 } 00297 00298 // 00299 // Align to page size boundary. 00300 // 00301 00302 MmSizeOfNonPagedPoolInBytes &= ~(PAGE_SIZE - 1); 00303 00304 // 00305 // Limit initial nonpaged pool size to MM_MAX_INITIAL_NONPAGED_POOL 00306 // 00307 00308 if (MmSizeOfNonPagedPoolInBytes > MM_MAX_INITIAL_NONPAGED_POOL) { 00309 MmSizeOfNonPagedPoolInBytes = MM_MAX_INITIAL_NONPAGED_POOL; 00310 } 00311 00312 // 00313 // If the non-paged pool that we want to allocate will not fit in 00314 // the free memory descriptor that we have available then recompute 00315 // the size of non-paged pool to be the size of the free memory 00316 // descriptor. If the free memory descriptor cannot fit the 00317 // minimum non-paged pool size (MmMinimumNonPagedPoolSize) then we 00318 // cannot boot the operating system. 00319 // 00320 00321 if ((MmSizeOfNonPagedPoolInBytes >> PAGE_SHIFT) > NumberOfPages) { 00322 00323 // 00324 // Reserve all of low memory for nonpaged pool. 00325 // 00326 00327 MmSizeOfNonPagedPoolInBytes = NumberOfPages << PAGE_SHIFT; 00328 LowMemoryReserved = NextPhysicalPage; 00329 00330 // 00331 // Switch to backup descriptor for all other allocations. 00332 // 00333 00334 NextPhysicalPage = FreeDescriptor->BasePage; 00335 NumberOfPages = FreeDescriptor->PageCount; 00336 00337 if (MmSizeOfNonPagedPoolInBytes < MmMinimumNonPagedPoolSize) { 00338 InbvDisplayString("MmInit *** FATAL ERROR *** cannot allocate non-paged pool\n"); 00339 sprintf(Buffer, 00340 "Largest description = %d pages, require %d pages\n", 00341 NumberOfPages, 00342 MmMinimumNonPagedPoolSize >> PAGE_SHIFT); 00343 InbvDisplayString (Buffer ); 00344 KeBugCheck (MEMORY_MANAGEMENT); 00345 00346 } 00347 } 00348 00349 // 00350 // Calculate the maximum size of pool. 00351 // 00352 00353 if (MmMaximumNonPagedPoolInBytes == 0) { 00354 00355 // 00356 // Calculate the size of nonpaged pool. 00357 // For every MB above 8mb add extra pages. 00358 // 00359 00360 MmMaximumNonPagedPoolInBytes = MmDefaultMaximumNonPagedPool; 00361 00362 // 00363 // Make sure enough expansion for the PFN database exists. 00364 // 00365 00366 MmMaximumNonPagedPoolInBytes += (ULONG)PAGE_ALIGN ( 00367 MmHighestPhysicalPage * sizeof(MMPFN)); 00368 00369 MmMaximumNonPagedPoolInBytes += 00370 ((MmNumberOfPhysicalPages - 1024) / 00371 (_1MB >> PAGE_SHIFT) ) * 00372 MmMaxAdditionNonPagedPoolPerMb; 00373 } 00374 00375 MaxPool = MmSizeOfNonPagedPoolInBytes + PAGE_SIZE * 16 + 00376 (ULONG)PAGE_ALIGN ( 00377 MmHighestPhysicalPage * sizeof(MMPFN)); 00378 00379 if (MmMaximumNonPagedPoolInBytes < MaxPool) { 00380 MmMaximumNonPagedPoolInBytes = MaxPool; 00381 } 00382 00383 // 00384 // If the system is configured for maximum system PTEs then limit maximum 00385 // nonpaged pool to 128mb so the rest of the virtual address space can 00386 // be used for the PTEs. Also push as much nonpaged pool as possible 00387 // into kseg0 to free up more PTEs. 00388 // 00389 00390 if (MmMaximumNonPagedPoolInBytes > MM_MAX_ADDITIONAL_NONPAGED_POOL) { 00391 00392 ULONG InitialNonPagedPages; 00393 ULONG ExpansionPagesToMove; 00394 ULONG LowAvailPages; 00395 00396 if ((MiRequestedSystemPtes == (ULONG)-1) || (MiHydra == TRUE)) { 00397 MmMaximumNonPagedPoolInBytes = MM_MAX_ADDITIONAL_NONPAGED_POOL; 00398 00399 if (LowMemoryReserved == 0) { 00400 00401 InitialNonPagedPages = (MmSizeOfNonPagedPoolInBytes >> PAGE_SHIFT); 00402 00403 if (InitialNonPagedPages + 1024 < NumberOfPages) { 00404 LowAvailPages = NumberOfPages - 1024 - InitialNonPagedPages; 00405 00406 ExpansionPagesToMove = (MmMaximumNonPagedPoolInBytes >> PAGE_SHIFT) - InitialNonPagedPages; 00407 00408 if (ExpansionPagesToMove > 32) { 00409 ExpansionPagesToMove -= 32; 00410 if (LowAvailPages > ExpansionPagesToMove) { 00411 LowAvailPages = ExpansionPagesToMove; 00412 } 00413 00414 MmSizeOfNonPagedPoolInBytes += (LowAvailPages << PAGE_SHIFT); 00415 } 00416 } 00417 } 00418 00419 if (MmSizeOfNonPagedPoolInBytes == MmMaximumNonPagedPoolInBytes) { 00420 ASSERT (MmSizeOfNonPagedPoolInBytes > (32 << PAGE_SHIFT)); 00421 MmSizeOfNonPagedPoolInBytes -= (32 << PAGE_SHIFT); 00422 } 00423 } 00424 } 00425 00426 // 00427 // Limit maximum nonpaged pool to MM_MAX_ADDITIONAL_NONPAGED_POOL. 00428 // 00429 00430 if (MmMaximumNonPagedPoolInBytes > MM_MAX_ADDITIONAL_NONPAGED_POOL) { 00431 00432 if (MmMaximumNonPagedPoolInBytes > MM_MAX_INITIAL_NONPAGED_POOL + MM_MAX_ADDITIONAL_NONPAGED_POOL) { 00433 MmMaximumNonPagedPoolInBytes = MM_MAX_INITIAL_NONPAGED_POOL + MM_MAX_ADDITIONAL_NONPAGED_POOL; 00434 } 00435 00436 if (LowMemoryReserved != 0) { 00437 if (MmMaximumNonPagedPoolInBytes > MmSizeOfNonPagedPoolInBytes + MM_MAX_ADDITIONAL_NONPAGED_POOL) { 00438 MmMaximumNonPagedPoolInBytes = MmSizeOfNonPagedPoolInBytes + MM_MAX_ADDITIONAL_NONPAGED_POOL; 00439 } 00440 MmExpandedNonPagedPoolInBytes = MmMaximumNonPagedPoolInBytes - MmSizeOfNonPagedPoolInBytes; 00441 } 00442 else { 00443 00444 if ((MM_MAX_INITIAL_NONPAGED_POOL >> PAGE_SHIFT) >= NumberOfPages) { 00445 00446 // 00447 // Reserve all of low memory for nonpaged pool. 00448 // 00449 00450 SIZE_T Diff; 00451 00452 Diff = MmMaximumNonPagedPoolInBytes - MmSizeOfNonPagedPoolInBytes; 00453 if (Diff > MM_MAX_ADDITIONAL_NONPAGED_POOL) { 00454 Diff = MM_MAX_ADDITIONAL_NONPAGED_POOL; 00455 } 00456 00457 MmSizeOfNonPagedPoolInBytes = NumberOfPages << PAGE_SHIFT; 00458 MmMaximumNonPagedPoolInBytes = MmSizeOfNonPagedPoolInBytes + Diff; 00459 LowMemoryReserved = NextPhysicalPage; 00460 00461 // 00462 // Switch to backup descriptor for all other allocations. 00463 // 00464 00465 NextPhysicalPage = FreeDescriptor->BasePage; 00466 NumberOfPages = FreeDescriptor->PageCount; 00467 } 00468 else { 00469 00470 MmSizeOfNonPagedPoolInBytes = MM_MAX_INITIAL_NONPAGED_POOL; 00471 00472 // 00473 // The pages must be subtracted from the low descriptor so 00474 // they are not used for anything else or put on the freelist. 00475 // But they must be added back in later when initializing PFNs 00476 // for all the descriptor ranges. 00477 // 00478 00479 RemovedLowCount = (MmSizeOfNonPagedPoolInBytes >> PAGE_SHIFT); 00480 FreeDescriptorLowMem->PageCount -= RemovedLowCount; 00481 RemovedLowPage = FreeDescriptorLowMem->BasePage + FreeDescriptorLowMem->PageCount; 00482 00483 NumberOfPages = FreeDescriptorLowMem->PageCount; 00484 } 00485 00486 MmExpandedNonPagedPoolInBytes = MmMaximumNonPagedPoolInBytes - MmSizeOfNonPagedPoolInBytes; 00487 00488 if (MmExpandedNonPagedPoolInBytes > MM_MAX_ADDITIONAL_NONPAGED_POOL) { 00489 MmExpandedNonPagedPoolInBytes = MM_MAX_ADDITIONAL_NONPAGED_POOL; 00490 } 00491 } 00492 } 00493 00494 if (MmExpandedNonPagedPoolInBytes) { 00495 MmNonPagedPoolStart = (PVOID)((ULONG)MmNonPagedPoolEnd 00496 - MmExpandedNonPagedPoolInBytes); 00497 } 00498 else { 00499 MmNonPagedPoolStart = (PVOID)((ULONG)MmNonPagedPoolEnd 00500 - (MmMaximumNonPagedPoolInBytes - 1)); 00501 } 00502 00503 MmNonPagedPoolStart = (PVOID)PAGE_ALIGN(MmNonPagedPoolStart); 00504 NonPagedPoolStartVirtual = MmNonPagedPoolStart; 00505 00506 // 00507 // Calculate the starting PDE for the system PTE pool which is 00508 // right below the nonpaged pool. 00509 // 00510 00511 MmNonPagedSystemStart = (PVOID)(((ULONG)MmNonPagedPoolStart - 00512 ((MmNumberOfSystemPtes + 1) * PAGE_SIZE)) & 00513 (~PAGE_DIRECTORY_MASK)); 00514 00515 if (MmNonPagedSystemStart < MM_LOWEST_NONPAGED_SYSTEM_START) { 00516 MmNonPagedSystemStart = MM_LOWEST_NONPAGED_SYSTEM_START; 00517 } 00518 00519 MmNumberOfSystemPtes = (((ULONG)MmNonPagedPoolStart - 00520 (ULONG)MmNonPagedSystemStart) >> PAGE_SHIFT)-1; 00521 ASSERT (MmNumberOfSystemPtes > 1000); 00522 00523 // 00524 // Set the global bit for all PDEs in system space. 00525 // 00526 00527 StartPde = MiGetPdeAddress (MM_SYSTEM_SPACE_START); 00528 EndPde = MiGetPdeAddress (MM_SYSTEM_SPACE_END); 00529 00530 while (StartPde <= EndPde) { 00531 00532 if (StartPde->u.Hard.Global == 0) { 00533 TempPte = *StartPde; 00534 TempPte.u.Hard.Global = 1; 00535 *StartPde = TempPte; 00536 } 00537 00538 StartPde += 1; 00539 } 00540 00541 if (MiHydra == TRUE) { 00542 00543 // 00544 // Clear the global bit for all session space addresses. 00545 // 00546 00547 StartPde = MiGetPdeAddress (MmSessionBase); 00548 EndPde = MiGetPdeAddress (MI_SESSION_SPACE_END); 00549 00550 while (StartPde < EndPde) { 00551 00552 if (StartPde->u.Hard.Global == 1) { 00553 TempPte = *StartPde; 00554 TempPte.u.Hard.Global = 0; 00555 *StartPde = TempPte; 00556 } 00557 00558 ASSERT (StartPde->u.Long == 0); 00559 StartPde += 1; 00560 } 00561 } 00562 00563 StartPde = MiGetPdeAddress (MmNonPagedSystemStart); 00564 00565 EndPde = MiGetPdeAddress (MmNonPagedPoolEnd); 00566 00567 ASSERT ((EndPde - StartPde) < (LONG)NumberOfPages); 00568 00569 TempPte = ValidKernelPte; 00570 00571 while (StartPde <= EndPde) { 00572 if (StartPde->u.Hard.Valid == 0) { 00573 00574 // 00575 // Map in a page directory page. 00576 // 00577 00578 TempPte.u.Hard.PageFrameNumber = NextPhysicalPage; 00579 NumberOfPages -= 1; 00580 NextPhysicalPage += 1; 00581 00582 if (NumberOfPages == 0) { 00583 ASSERT (NextPhysicalPage != (FreeDescriptor->BasePage + 00584 FreeDescriptor->PageCount)); 00585 NextPhysicalPage = FreeDescriptor->BasePage; 00586 NumberOfPages = FreeDescriptor->PageCount; 00587 } 00588 *StartPde = TempPte; 00589 } 00590 StartPde += 1; 00591 } 00592 00593 // 00594 // Zero the PTEs before non-paged pool. 00595 // 00596 00597 StartPde = MiGetPteAddress (MmNonPagedSystemStart); 00598 PointerPte = MiGetPteAddress (MmNonPagedPoolStart); 00599 00600 RtlZeroMemory (StartPde, (ULONG)PointerPte - (ULONG)StartPde); 00601 00602 // 00603 // Fill in the PTEs for non-paged pool. 00604 // 00605 00606 PointerPte = MiGetPteAddress(MmNonPagedPoolStart); 00607 LastPte = MiGetPteAddress((ULONG)MmNonPagedPoolStart + 00608 MmSizeOfNonPagedPoolInBytes - 1); 00609 00610 if (MmExpandedNonPagedPoolInBytes == 0) { 00611 if (!LowMemoryReserved) { 00612 00613 if (NumberOfPages < (ULONG)(LastPte - PointerPte + 1)) { 00614 00615 // 00616 // Can't just switch descriptors here - the initial nonpaged 00617 // pool is always mapped via KSEG0 and is thus required to be 00618 // virtually and physically contiguous. 00619 // 00620 00621 KeBugCheckEx (INSTALL_MORE_MEMORY, 00622 MmNumberOfPhysicalPages, 00623 NumberOfPages, 00624 LastPte - PointerPte + 1, 00625 1); 00626 } 00627 00628 while (PointerPte <= LastPte) { 00629 TempPte.u.Hard.PageFrameNumber = NextPhysicalPage; 00630 NextPhysicalPage += 1; 00631 NumberOfPages -= 1; 00632 ASSERT (NumberOfPages != 0); 00633 *PointerPte = TempPte; 00634 PointerPte += 1; 00635 } 00636 00637 } else { 00638 00639 ULONG ReservedPage = FreeDescriptorLowMem->BasePage; 00640 00641 while (PointerPte <= LastPte) { 00642 TempPte.u.Hard.PageFrameNumber = ReservedPage; 00643 ReservedPage += 1; 00644 *PointerPte = TempPte; 00645 PointerPte += 1; 00646 } 00647 } 00648 LastPte = MiGetPteAddress ((ULONG)MmNonPagedPoolStart + 00649 MmMaximumNonPagedPoolInBytes - 1); 00650 } 00651 else { 00652 LastPte = MiGetPteAddress ((ULONG)MmNonPagedPoolStart + 00653 MmExpandedNonPagedPoolInBytes - 1); 00654 } 00655 00656 // 00657 // Zero the remaining PTEs for non-paged pool maximum. 00658 // 00659 00660 while (PointerPte <= LastPte) { 00661 *PointerPte = ZeroKernelPte; 00662 PointerPte += 1; 00663 } 00664 00665 // 00666 // Zero the remaining PTEs (if any). 00667 // 00668 00669 while (((ULONG)PointerPte & (PAGE_SIZE - 1)) != 0) { 00670 *PointerPte = ZeroKernelPte; 00671 PointerPte += 1; 00672 } 00673 00674 if (MmExpandedNonPagedPoolInBytes) { 00675 00676 if (LowMemoryReserved) { 00677 MmNonPagedPoolStart = (PVOID)((LowMemoryReserved << PAGE_SHIFT) | 00678 KSEG0_BASE); 00679 } 00680 else if (RemovedLowPage) { 00681 MmNonPagedPoolStart = (PVOID)((RemovedLowPage << PAGE_SHIFT) | 00682 KSEG0_BASE); 00683 } 00684 else { 00685 ASSERT (FALSE); 00686 } 00687 } 00688 else { 00689 PointerPte = MiGetPteAddress (MmNonPagedPoolStart); 00690 MmNonPagedPoolStart = (PVOID)((PointerPte->u.Hard.PageFrameNumber << PAGE_SHIFT) | 00691 KSEG0_BASE); 00692 } 00693 00694 MmPageAlignedPoolBase[NonPagedPool] = MmNonPagedPoolStart; 00695 00696 MmSubsectionBase = (ULONG)MmNonPagedPoolStart; 00697 00698 if (MmExpandedNonPagedPoolInBytes == 0) { 00699 if (NextPhysicalPage < (MM_SUBSECTION_MAP >> PAGE_SHIFT)) { 00700 MmSubsectionBase = KSEG0_BASE; 00701 } 00702 } 00703 00704 MmSubsectionTopPage = (((MmSubsectionBase & ~KSEG0_BASE) + MM_SUBSECTION_MAP) >> PAGE_SHIFT); 00705 00706 // 00707 // Non-paged pages now exist, build the pool structures. 00708 // 00709 00710 if (MmExpandedNonPagedPoolInBytes) { 00711 MmNonPagedPoolExpansionStart = (PVOID)NonPagedPoolStartVirtual; 00712 } 00713 else { 00714 MmNonPagedPoolExpansionStart = (PVOID)((PCHAR)NonPagedPoolStartVirtual + 00715 MmSizeOfNonPagedPoolInBytes); 00716 } 00717 00718 MiInitializeNonPagedPool (); 00719 00720 // 00721 // Before Non-paged pool can be used, the PFN database must 00722 // be built. This is due to the fact that the start and end of 00723 // allocation bits for nonpaged pool are maintained in the 00724 // PFN elements for the corresponding pages. 00725 // 00726 00727 // 00728 // Calculate the number of pages required from page zero to 00729 // the highest page. 00730 // 00731 // Get the number of secondary colors and add the array for tracking 00732 // secondary colors to the end of the PFN database. 00733 // 00734 00735 if (MmSecondaryColors == 0) { 00736 MmSecondaryColors = PCR->SecondLevelCacheSize; 00737 } 00738 00739 MmSecondaryColors = MmSecondaryColors >> PAGE_SHIFT; 00740 00741 // 00742 // Make sure value is power of two and within limits. 00743 // 00744 00745 if (((MmSecondaryColors & (MmSecondaryColors -1)) != 0) || 00746 (MmSecondaryColors < MM_SECONDARY_COLORS_MIN) || 00747 (MmSecondaryColors > MM_SECONDARY_COLORS_MAX)) { 00748 00749 MmSecondaryColors = MM_SECONDARY_COLORS_DEFAULT; 00750 } 00751 00752 MmSecondaryColorMask = MmSecondaryColors - 1; 00753 00754 PfnAllocation = 1 + ((((MmHighestPossiblePhysicalPage + 1) * sizeof(MMPFN)) + 00755 (MmSecondaryColors * sizeof(MMCOLOR_TABLES)*2)) 00756 >> PAGE_SHIFT); 00757 00758 // 00759 // If the number of pages remaining in the current descriptor is 00760 // greater than the number of pages needed for the PFN database, 00761 // and the descriptor is for memory below 1 gig, then allocate the 00762 // PFN database from the current free descriptor. 00763 // Note: FW creates a new memory descriptor for any memory above 1GB. 00764 // Thus we don't need to worry if the highest page will go beyond 1GB for 00765 // this memory descriptor. 00766 // 00767 00768 #ifndef PFN_CONSISTENCY 00769 if ((NumberOfPages >= PfnAllocation) && 00770 (NextPhysicalPage + NumberOfPages <= MM_PAGES_IN_KSEG0)) { 00771 00772 // 00773 // Allocate the PFN database in kseg0. 00774 // 00775 // Compute the address of the PFN by allocating the appropriate 00776 // number of pages from the end of the free descriptor. 00777 // 00778 00779 PfnInKseg0 = TRUE; 00780 HighPage = NextPhysicalPage + NumberOfPages; 00781 MmPfnDatabase = (PMMPFN)(KSEG0_BASE | 00782 ((HighPage - PfnAllocation) << PAGE_SHIFT)); 00783 RtlZeroMemory(MmPfnDatabase, PfnAllocation * PAGE_SIZE); 00784 00785 // 00786 // Mark off the chunk of memory used for the PFN database. 00787 // 00788 00789 NumberOfPages -= PfnAllocation; 00790 00791 if (NextPhysicalPage >= FreeDescriptorLowMem->BasePage && 00792 NextPhysicalPage < (FreeDescriptorLowMem->BasePage + 00793 FreeDescriptorLowMem->PageCount)) { 00794 00795 // 00796 // We haven't used the other descriptor. 00797 // 00798 00799 FreeDescriptorLowMem->PageCount -= PfnAllocation; 00800 00801 } else { 00802 00803 FreeDescriptor->PageCount -= PfnAllocation; 00804 } 00805 00806 // 00807 // Allocate one PTE at the very top of the Mm virtual address space. 00808 // This provides protection against the caller of the first real 00809 // nonpaged expansion allocation in case he accidentally overruns his 00810 // pool block. (We'll trap instead of corrupting the crashdump PTEs). 00811 // This also allows us to freely increment in MiFreePoolPages 00812 // without having to worry about a valid PTE just after the end of 00813 // the highest nonpaged pool allocation. 00814 // 00815 00816 MiReserveSystemPtes (1, 00817 NonPagedPoolExpansion, 00818 0, 00819 0, 00820 TRUE); 00821 00822 } else { 00823 00824 #endif // PFN_CONSISTENCY 00825 00826 // 00827 // Calculate the start of the Pfn database (it starts at physical 00828 // page zero, even if the lowest physical page is not zero). 00829 // 00830 00831 PfnInKseg0 = FALSE; 00832 PointerPte = MiReserveSystemPtes (PfnAllocation, 00833 NonPagedPoolExpansion, 00834 0, 00835 0, 00836 TRUE); 00837 00838 #if PFN_CONSISTENCY 00839 MiPfnStartPte = PointerPte; 00840 MiPfnPtes = PfnAllocation; 00841 #endif 00842 00843 MmPfnDatabase = (PMMPFN)(MiGetVirtualAddressMappedByPte (PointerPte)); 00844 00845 // 00846 // Allocate one more PTE just below the PFN database. This provides 00847 // protection against the caller of the first real nonpaged 00848 // expansion allocation in case he accidentally overruns his pool 00849 // block. (We'll trap instead of corrupting the PFN database). 00850 // This also allows us to freely increment in MiFreePoolPages 00851 // without having to worry about a valid PTE just after the end of 00852 // the highest nonpaged pool allocation. 00853 // 00854 00855 MiReserveSystemPtes (1, 00856 NonPagedPoolExpansion, 00857 0, 00858 0, 00859 TRUE); 00860 00861 // 00862 // Go through the memory descriptors and for each physical page 00863 // make sure the PFN database has a valid PTE to map it. This allows 00864 // machines with sparse physical memory to have a minimal PFN 00865 // database. 00866 // 00867 00868 NextMd = LoaderBlock->MemoryDescriptorListHead.Flink; 00869 00870 while (NextMd != &LoaderBlock->MemoryDescriptorListHead) { 00871 00872 MemoryDescriptor = CONTAINING_RECORD(NextMd, 00873 MEMORY_ALLOCATION_DESCRIPTOR, 00874 ListEntry); 00875 00876 PointerPte = MiGetPteAddress (MI_PFN_ELEMENT( 00877 MemoryDescriptor->BasePage)); 00878 00879 LastPte = MiGetPteAddress (((PCHAR)(MI_PFN_ELEMENT( 00880 MemoryDescriptor->BasePage + 00881 MemoryDescriptor->PageCount))) - 1); 00882 00883 // 00884 // If memory was temporarily removed to create the initial non 00885 // paged pool, account for it now so PFN entries are created for it. 00886 // 00887 00888 if (MemoryDescriptor == FreeDescriptorLowMem) { 00889 if (RemovedLowPage) { 00890 ASSERT (MemoryDescriptor->BasePage + MemoryDescriptor->PageCount == RemovedLowPage); 00891 LastPte = MiGetPteAddress (((PCHAR)(MI_PFN_ELEMENT( 00892 MemoryDescriptor->BasePage + 00893 RemovedLowCount + 00894 MemoryDescriptor->PageCount))) - 1); 00895 } 00896 } 00897 00898 while (PointerPte <= LastPte) { 00899 00900 if (PointerPte->u.Hard.Valid == 0) { 00901 TempPte.u.Hard.PageFrameNumber = NextPhysicalPage; 00902 NextPhysicalPage += 1; 00903 NumberOfPages -= 1; 00904 if (NumberOfPages == 0) { 00905 ASSERT (NextPhysicalPage != (FreeDescriptor->BasePage + 00906 FreeDescriptor->PageCount)); 00907 NextPhysicalPage = FreeDescriptor->BasePage; 00908 NumberOfPages = FreeDescriptor->PageCount; 00909 } 00910 *PointerPte = TempPte; 00911 RtlZeroMemory (MiGetVirtualAddressMappedByPte (PointerPte), 00912 PAGE_SIZE); 00913 } 00914 PointerPte += 1; 00915 } 00916 NextMd = MemoryDescriptor->ListEntry.Flink; 00917 } 00918 #ifndef PFN_CONSISTENCY 00919 } 00920 #endif // PFN_CONSISTENCY 00921 00922 // 00923 // Initialize support for colored pages. 00924 // 00925 00926 MmFreePagesByColor[0] = (PMMCOLOR_TABLES) 00927 &MmPfnDatabase[MmHighestPossiblePhysicalPage + 1]; 00928 00929 MmFreePagesByColor[1] = &MmFreePagesByColor[0][MmSecondaryColors]; 00930 00931 // 00932 // Make sure the PTEs are mapped. 00933 // 00934 00935 if (!MI_IS_PHYSICAL_ADDRESS(MmFreePagesByColor[0])) { 00936 00937 PointerPte = MiGetPteAddress (&MmFreePagesByColor[0][0]); 00938 00939 LastPte = MiGetPteAddress ( 00940 (PVOID)((PCHAR)&MmFreePagesByColor[1][MmSecondaryColors]-1)); 00941 00942 while (PointerPte <= LastPte) { 00943 if (PointerPte->u.Hard.Valid == 0) { 00944 TempPte.u.Hard.PageFrameNumber = NextPhysicalPage; 00945 NextPhysicalPage += 1; 00946 NumberOfPages -= 1; 00947 if (NumberOfPages == 0) { 00948 ASSERT (NextPhysicalPage != (FreeDescriptor->BasePage + 00949 FreeDescriptor->PageCount)); 00950 NextPhysicalPage = FreeDescriptor->BasePage; 00951 NumberOfPages = FreeDescriptor->PageCount; 00952 } 00953 *PointerPte = TempPte; 00954 RtlZeroMemory (MiGetVirtualAddressMappedByPte (PointerPte), 00955 PAGE_SIZE); 00956 } 00957 PointerPte += 1; 00958 } 00959 } 00960 00961 for (i = 0; i < MmSecondaryColors; i += 1) { 00962 MmFreePagesByColor[ZeroedPageList][i].Flink = MM_EMPTY_LIST; 00963 MmFreePagesByColor[FreePageList][i].Flink = MM_EMPTY_LIST; 00964 } 00965 00966 #if MM_MAXIMUM_NUMBER_OF_COLORS > 1 00967 for (i = 0; i < MM_MAXIMUM_NUMBER_OF_COLORS; i += 1) { 00968 MmFreePagesByPrimaryColor[ZeroedPageList][i].ListName = ZeroedPageList; 00969 MmFreePagesByPrimaryColor[FreePageList][i].ListName = FreePageList; 00970 MmFreePagesByPrimaryColor[ZeroedPageList][i].Flink = MM_EMPTY_LIST; 00971 MmFreePagesByPrimaryColor[FreePageList][i].Flink = MM_EMPTY_LIST; 00972 MmFreePagesByPrimaryColor[ZeroedPageList][i].Blink = MM_EMPTY_LIST; 00973 MmFreePagesByPrimaryColor[FreePageList][i].Blink = MM_EMPTY_LIST; 00974 } 00975 #endif 00976 00977 // 00978 // Go through the page table entries and for any page which is 00979 // valid, update the corresponding PFN database element. 00980 // 00981 00982 PointerPde = MiGetPdeAddress (PTE_BASE); 00983 00984 PdePage = PointerPde->u.Hard.PageFrameNumber; 00985 Pfn1 = MI_PFN_ELEMENT(PdePage); 00986 Pfn1->PteFrame = PdePage; 00987 Pfn1->PteAddress = PointerPde; 00988 Pfn1->u2.ShareCount += 1; 00989 Pfn1->u3.e2.ReferenceCount = 1; 00990 Pfn1->u3.e1.PageLocation = ActiveAndValid; 00991 Pfn1->u3.e1.PageColor = 00992 MI_GET_COLOR_FROM_SECONDARY(GET_PAGE_COLOR_FROM_PTE (PointerPde)); 00993 00994 // 00995 // Add the pages which were used to construct nonpaged pool to 00996 // the PFN database. 00997 // 00998 00999 Pde = MiGetPdeAddress (MmNonPagedSystemStart); 01000 01001 EndPde = MiGetPdeAddress(NON_PAGED_SYSTEM_END); 01002 01003 while (Pde <= EndPde) { 01004 if (Pde->u.Hard.Valid == 1) { 01005 PdePage = Pde->u.Hard.PageFrameNumber; 01006 Pfn1 = MI_PFN_ELEMENT(PdePage); 01007 Pfn1->PteFrame = PointerPde->u.Hard.PageFrameNumber; 01008 Pfn1->PteAddress = Pde; 01009 Pfn1->u2.ShareCount += 1; 01010 Pfn1->u3.e2.ReferenceCount = 1; 01011 Pfn1->u3.e1.PageLocation = ActiveAndValid; 01012 Pfn1->u3.e1.PageColor = 01013 MI_GET_COLOR_FROM_SECONDARY(GET_PAGE_COLOR_FROM_PTE (Pde)); 01014 01015 PointerPte = MiGetVirtualAddressMappedByPte (Pde); 01016 for (j = 0 ; j < PTE_PER_PAGE; j += 1) { 01017 if (PointerPte->u.Hard.Valid == 1) { 01018 01019 PageFrameIndex = PointerPte->u.Hard.PageFrameNumber; 01020 Pfn2 = MI_PFN_ELEMENT(PageFrameIndex); 01021 Pfn2->PteFrame = PdePage; 01022 Pfn2->u2.ShareCount += 1; 01023 Pfn2->u3.e2.ReferenceCount = 1; 01024 Pfn2->u3.e1.PageLocation = ActiveAndValid; 01025 01026 Pfn2->PteAddress = 01027 (PMMPTE)(KSEG0_BASE | (PageFrameIndex << PTE_SHIFT)); 01028 01029 Pfn2->u3.e1.PageColor = 01030 MI_GET_COLOR_FROM_SECONDARY(GET_PAGE_COLOR_FROM_PTE (Pfn2->PteAddress)); 01031 } 01032 PointerPte += 1; 01033 } 01034 } 01035 Pde += 1; 01036 } 01037 01038 // 01039 // Handle the initial nonpaged pool on expanded systems. 01040 // 01041 01042 if (MmExpandedNonPagedPoolInBytes) { 01043 PageFrameIndex = (((ULONG_PTR)MmNonPagedPoolStart & ~KSEG0_BASE) >> PAGE_SHIFT); 01044 Pfn1 = MI_PFN_ELEMENT(PageFrameIndex); 01045 j = PageFrameIndex + (MmSizeOfNonPagedPoolInBytes >> PAGE_SHIFT); 01046 while (PageFrameIndex < j) { 01047 Pfn1->PteFrame = PdePage; 01048 Pfn1->u2.ShareCount += 1; 01049 Pfn1->u3.e2.ReferenceCount = 1; 01050 Pfn1->u3.e1.PageLocation = ActiveAndValid; 01051 01052 Pfn1->PteAddress = 01053 (PMMPTE)(KSEG0_BASE | (PageFrameIndex << PTE_SHIFT)); 01054 01055 Pfn1->u3.e1.PageColor = 01056 MI_GET_COLOR_FROM_SECONDARY(GET_PAGE_COLOR_FROM_PTE (Pfn1->PteAddress)); 01057 PageFrameIndex += 1; 01058 Pfn1 += 1; 01059 } 01060 } 01061 01062 // 01063 // If page zero is still unused, mark it as in use. This is 01064 // temporary as we want to find bugs where a physical page 01065 // is specified as zero. 01066 // 01067 01068 Pfn1 = &MmPfnDatabase[MmLowestPhysicalPage]; 01069 if (Pfn1->u3.e2.ReferenceCount == 0) { 01070 01071 // 01072 // Make the reference count non-zero and point it into a 01073 // page directory. 01074 // 01075 01076 Pde = MiGetPdeAddress (0xb0000000); 01077 PdePage = Pde->u.Hard.PageFrameNumber; 01078 Pfn1->PteFrame = PdePageNumber; 01079 Pfn1->PteAddress = Pde; 01080 Pfn1->u2.ShareCount += 1; 01081 Pfn1->u3.e2.ReferenceCount = 1; 01082 Pfn1->u3.e1.PageLocation = ActiveAndValid; 01083 Pfn1->u3.e1.PageColor = 01084 MI_GET_COLOR_FROM_SECONDARY(GET_PAGE_COLOR_FROM_PTE (Pde)); 01085 } 01086 01087 // end of temporary set to physical page zero. 01088 01089 // 01090 // Walk through the memory descriptors and add pages to the 01091 // free list in the PFN database. 01092 // 01093 01094 NextMd = LoaderBlock->MemoryDescriptorListHead.Flink; 01095 01096 while (NextMd != &LoaderBlock->MemoryDescriptorListHead) { 01097 01098 MemoryDescriptor = CONTAINING_RECORD(NextMd, 01099 MEMORY_ALLOCATION_DESCRIPTOR, 01100 ListEntry); 01101 01102 i = MemoryDescriptor->PageCount; 01103 NextPhysicalPage = MemoryDescriptor->BasePage; 01104 01105 switch (MemoryDescriptor->MemoryType) { 01106 case LoaderBad: 01107 while (i != 0) { 01108 MiInsertPageInList (MmPageLocationList[BadPageList], 01109 NextPhysicalPage); 01110 i -= 1; 01111 NextPhysicalPage += 1; 01112 } 01113 break; 01114 01115 case LoaderFree: 01116 case LoaderLoadedProgram: 01117 case LoaderFirmwareTemporary: 01118 case LoaderOsloaderStack: 01119 01120 Pfn1 = MI_PFN_ELEMENT (NextPhysicalPage); 01121 while (i != 0) { 01122 if (Pfn1->u3.e2.ReferenceCount == 0) { 01123 01124 // 01125 // Set the PTE address to the physical page for 01126 // virtual address alignment checking. 01127 // 01128 01129 Pfn1->PteAddress = 01130 (PMMPTE)(NextPhysicalPage << PTE_SHIFT); 01131 01132 Pfn1->u3.e1.PageColor = 01133 MI_GET_COLOR_FROM_SECONDARY(GET_PAGE_COLOR_FROM_PTE (Pfn1->PteAddress)); 01134 MiInsertPageInList (MmPageLocationList[FreePageList], 01135 NextPhysicalPage); 01136 } 01137 Pfn1 += 1; 01138 i -= 1; 01139 NextPhysicalPage += 1; 01140 } 01141 break; 01142 01143 default: 01144 01145 PointerPte = MiGetPteAddress (KSEG0_BASE | 01146 (NextPhysicalPage << PAGE_SHIFT)); 01147 Pfn1 = MI_PFN_ELEMENT (NextPhysicalPage); 01148 while (i != 0) { 01149 01150 // 01151 // Set page as in use. 01152 // 01153 01154 Pfn1->PteFrame = PdePageNumber; 01155 Pfn1->PteAddress = PointerPte; 01156 Pfn1->u2.ShareCount += 1; 01157 Pfn1->u3.e2.ReferenceCount = 1; 01158 Pfn1->u3.e1.PageLocation = ActiveAndValid; 01159 Pfn1->u3.e1.PageColor = 01160 MI_GET_COLOR_FROM_SECONDARY(GET_PAGE_COLOR_FROM_PTE (PointerPte)); 01161 01162 Pfn1 += 1; 01163 i -= 1; 01164 NextPhysicalPage += 1; 01165 PointerPte += 1; 01166 } 01167 01168 break; 01169 } 01170 01171 NextMd = MemoryDescriptor->ListEntry.Flink; 01172 } 01173 01174 // 01175 // Indicate that the PFN database is allocated in NonPaged pool. 01176 // 01177 if (PfnInKseg0 == FALSE) { 01178 01179 // 01180 // The PFN database is allocated in virtual memory 01181 // 01182 // Set the start and end of allocation. 01183 // 01184 01185 Pfn1 = MI_PFN_ELEMENT(MiGetPteAddress(&MmPfnDatabase[MmLowestPhysicalPage])->u.Hard.PageFrameNumber); 01186 Pfn1->u3.e1.StartOfAllocation = 1; 01187 Pfn1 = MI_PFN_ELEMENT(MiGetPteAddress(&MmPfnDatabase[MmHighestPossiblePhysicalPage])->u.Hard.PageFrameNumber); 01188 Pfn1->u3.e1.EndOfAllocation = 1; 01189 01190 } else { 01191 01192 // 01193 // The PFN database is allocated in KSEG0. 01194 // 01195 // Mark all PFN entries for the PFN pages in use. 01196 // 01197 01198 PageNumber = ((ULONG)MmPfnDatabase - KSEG0_BASE) >> PAGE_SHIFT; 01199 Pfn1 = MI_PFN_ELEMENT(PageNumber); 01200 do { 01201 Pfn1->PteAddress = (PMMPTE)(PageNumber << PTE_SHIFT); 01202 Pfn1->u3.e1.PageColor = 01203 MI_GET_COLOR_FROM_SECONDARY(GET_PAGE_COLOR_FROM_PTE (Pfn1->PteAddress)); 01204 Pfn1 += 1; 01205 PfnAllocation -= 1; 01206 } while (PfnAllocation != 0); 01207 01208 // 01209 // Scan the PFN database backward for pages that are completely zero. 01210 // These pages are unused and can be added to the free list 01211 // 01212 01213 if (MmDynamicPfn == FALSE) { 01214 BottomPfn = MI_PFN_ELEMENT(MmHighestPhysicalPage); 01215 do { 01216 01217 // 01218 // Compute the address of the start of the page that is next 01219 // lower in memory and scan backwards until that page address 01220 // is reached or just crossed. 01221 // 01222 01223 if (((ULONG)BottomPfn & (PAGE_SIZE - 1)) != 0) { 01224 BasePfn = (PMMPFN)((ULONG)BottomPfn & ~(PAGE_SIZE - 1)); 01225 TopPfn = BottomPfn + 1; 01226 01227 } else { 01228 BasePfn = (PMMPFN)((ULONG)BottomPfn - PAGE_SIZE); 01229 TopPfn = BottomPfn; 01230 } 01231 01232 while (BottomPfn > BasePfn) { 01233 BottomPfn -= 1; 01234 } 01235 01236 // 01237 // If the entire range over which the PFN entries span is 01238 // completely zero and the PFN entry that maps the page is 01239 // not in the range, then add the page to the appropriate 01240 // free list. 01241 // 01242 01243 Range = (ULONG)TopPfn - (ULONG)BottomPfn; 01244 if (RtlCompareMemoryUlong((PVOID)BottomPfn, Range, 0) == Range) { 01245 01246 // 01247 // Set the PTE address to the physical page for 01248 // virtual address alignment checking. 01249 // 01250 01251 PageNumber = ((ULONG)BasePfn - KSEG0_BASE) >> PAGE_SHIFT; 01252 Pfn1 = MI_PFN_ELEMENT(PageNumber); 01253 01254 ASSERT(Pfn1->u3.e2.ReferenceCount == 0); 01255 01256 PfnAllocation += 1; 01257 01258 Pfn1->PteAddress = (PMMPTE)(PageNumber << PTE_SHIFT); 01259 Pfn1->u3.e1.PageColor = 01260 MI_GET_COLOR_FROM_SECONDARY(GET_PAGE_COLOR_FROM_PTE (Pfn1->PteAddress)); 01261 01262 MiInsertPageInList(MmPageLocationList[FreePageList], 01263 PageNumber); 01264 } 01265 01266 } while (BottomPfn > MmPfnDatabase); 01267 } 01268 } 01269 01270 // 01271 // Indicate that nonpaged pool must succeed is allocated in 01272 // nonpaged pool. 01273 // 01274 01275 i = MmSizeOfNonPagedMustSucceed; 01276 Pfn1 = MI_PFN_ELEMENT(MI_CONVERT_PHYSICAL_TO_PFN (MmNonPagedMustSucceed)); 01277 01278 while ((LONG)i > 0) { 01279 Pfn1->u3.e1.StartOfAllocation = 1; 01280 Pfn1->u3.e1.EndOfAllocation = 1; 01281 i -= PAGE_SIZE; 01282 Pfn1 += 1; 01283 } 01284 01285 KeInitializeSpinLock (&MmSystemSpaceLock); 01286 KeInitializeSpinLock (&MmPfnLock); 01287 01288 // 01289 // Initialize the nonpaged available PTEs for mapping I/O space 01290 // and kernel stacks. 01291 // 01292 01293 PointerPte = MiGetPteAddress (MmNonPagedSystemStart); 01294 01295 // 01296 // Since the initial nonpaged pool must always reside in KSEG0 (many changes 01297 // would be needed in this routine otherwise), reallocate the PTEs for it 01298 // to the pagable system PTE pool now. 01299 // 01300 01301 MmNumberOfSystemPtes = MiGetPteAddress(MmNonPagedPoolExpansionStart) - PointerPte - 1; 01302 01303 MiInitializeSystemPtes (PointerPte, MmNumberOfSystemPtes, SystemPteSpace); 01304 01305 // 01306 // Initialize the nonpaged pool. 01307 // 01308 01309 InitializePool (NonPagedPool, 0); 01310 01311 // 01312 // Initialize memory management structures for this process. 01313 // 01314 01315 // 01316 // Build working set list. System initialization has created 01317 // a PTE for hyperspace. 01318 // 01319 // Note, we can't remove a zeroed page as hyper space does not 01320 // exist and we map non-zeroed pages into hyper space to zero. 01321 // 01322 01323 PointerPte = MiGetPdeAddress(HYPER_SPACE); 01324 01325 ASSERT (PointerPte->u.Hard.Valid == 1); 01326 PointerPte->u.Hard.Global = 0; 01327 PointerPte->u.Hard.Write = 1; 01328 PageFrameIndex = PointerPte->u.Hard.PageFrameNumber; 01329 01330 // 01331 // Point to the page table page we just created and zero it. 01332 // 01333 01334 PointerPte = MiGetPteAddress(HYPER_SPACE); 01335 RtlZeroMemory ((PVOID)PointerPte, PAGE_SIZE); 01336 01337 // 01338 // Hyper space now exists, set the necessary variables. 01339 // 01340 01341 MmFirstReservedMappingPte = MiGetPteAddress (FIRST_MAPPING_PTE); 01342 MmLastReservedMappingPte = MiGetPteAddress (LAST_MAPPING_PTE); 01343 01344 MmWorkingSetList = WORKING_SET_LIST; 01345 MmWsle = (PMMWSLE)((PUCHAR)WORKING_SET_LIST + sizeof(MMWSL)); 01346 01347 // 01348 // Initialize this process's memory management structures including 01349 // the working set list. 01350 // 01351 01352 // 01353 // The PFN element for the page directory has already been initialized, 01354 // zero the reference count and the share count so they won't be 01355 // wrong. 01356 // 01357 01358 Pfn1 = MI_PFN_ELEMENT (PdePageNumber); 01359 01360 LOCK_PFN (OldIrql); 01361 01362 Pfn1->u2.ShareCount = 0; 01363 Pfn1->u3.e2.ReferenceCount = 0; 01364 01365 // 01366 // The PFN element for the PDE which maps hyperspace has already 01367 // been initialized, zero the reference count and the share count 01368 // so they won't be wrong. 01369 // 01370 01371 Pfn1 = MI_PFN_ELEMENT (PageFrameIndex); 01372 Pfn1->u2.ShareCount = 0; 01373 Pfn1->u3.e2.ReferenceCount = 0; 01374 01375 CurrentProcess = PsGetCurrentProcess (); 01376 01377 // 01378 // Get a page for the working set list and map it into the Page 01379 // directory at the page after hyperspace. 01380 // 01381 01382 PointerPte = MiGetPteAddress (HYPER_SPACE); 01383 PageFrameIndex = MiRemoveAnyPage (MI_GET_PAGE_COLOR_FROM_PTE(PointerPte)); 01384 01385 CurrentProcess->WorkingSetPage = PageFrameIndex; 01386 01387 TempPte.u.Hard.PageFrameNumber = PageFrameIndex; 01388 PointerPde = MiGetPdeAddress (HYPER_SPACE) + 1; 01389 01390 // 01391 // Assert that the double mapped pages have the same alignment. 01392 // 01393 01394 ASSERT ((PointerPte->u.Long & (0xF << PTE_SHIFT)) == 01395 (PointerPde->u.Long & (0xF << PTE_SHIFT))); 01396 01397 *PointerPde = TempPte; 01398 PointerPde->u.Hard.Global = 0; 01399 01400 PointerPte = MiGetVirtualAddressMappedByPte (PointerPde); 01401 01402 KeFillEntryTb ((PHARDWARE_PTE)PointerPde, 01403 PointerPte, 01404 TRUE); 01405 01406 RtlZeroMemory ((PVOID)PointerPte, PAGE_SIZE); 01407 01408 TempPte = *PointerPde; 01409 TempPte.u.Hard.Valid = 0; 01410 TempPte.u.Hard.Global = 0; 01411 01412 KeFlushSingleTb (PointerPte, 01413 TRUE, 01414 FALSE, 01415 (PHARDWARE_PTE)PointerPde, 01416 TempPte.u.Hard); 01417 01418 UNLOCK_PFN (OldIrql); 01419 01420 // 01421 // Initialize hyperspace for this process. 01422 // 01423 01424 PointerPte = MmFirstReservedMappingPte; 01425 PointerPte->u.Hard.PageFrameNumber = NUMBER_OF_MAPPING_PTES; 01426 01427 CurrentProcess->Vm.MaximumWorkingSetSize = MmSystemProcessWorkingSetMax; 01428 CurrentProcess->Vm.MinimumWorkingSetSize = MmSystemProcessWorkingSetMin; 01429 01430 MmInitializeProcessAddressSpace (CurrentProcess, 01431 (PEPROCESS)NULL, 01432 (PVOID)NULL, 01433 (PVOID)NULL); 01434 01435 *PointerPde = ZeroKernelPte; 01436 01437 // 01438 // Check to see if moving the secondary page structures to the end 01439 // of the PFN database is a waste of memory. And if so, copy it 01440 // to paged pool. 01441 // 01442 // If the PFN database ends on a page aligned boundary and the 01443 // size of the two arrays is less than a page, free the page 01444 // and allocate nonpagedpool for this. 01445 // 01446 01447 if ((((ULONG)MmFreePagesByColor[0] & (PAGE_SIZE - 1)) == 0) && 01448 ((MmSecondaryColors * 2 * sizeof(MMCOLOR_TABLES)) < PAGE_SIZE)) { 01449 01450 PMMCOLOR_TABLES c; 01451 01452 c = MmFreePagesByColor[0]; 01453 01454 MmFreePagesByColor[0] = ExAllocatePoolWithTag (NonPagedPoolMustSucceed, 01455 MmSecondaryColors * 2 * sizeof(MMCOLOR_TABLES), 01456 ' mM'); 01457 01458 MmFreePagesByColor[1] = &MmFreePagesByColor[0][MmSecondaryColors]; 01459 01460 RtlMoveMemory (MmFreePagesByColor[0], 01461 c, 01462 MmSecondaryColors * 2 * sizeof(MMCOLOR_TABLES)); 01463 01464 // 01465 // Free the page. 01466 // 01467 01468 if (!MI_IS_PHYSICAL_ADDRESS(c)) { 01469 PointerPte = MiGetPteAddress(c); 01470 PageFrameIndex = PointerPte->u.Hard.PageFrameNumber; 01471 *PointerPte = ZeroKernelPte; 01472 } else { 01473 PageFrameIndex = MI_CONVERT_PHYSICAL_TO_PFN (c); 01474 } 01475 01476 LOCK_PFN (OldIrql); 01477 01478 Pfn1 = MI_PFN_ELEMENT (PageFrameIndex); 01479 ASSERT ((Pfn1->u3.e2.ReferenceCount <= 1) && (Pfn1->u2.ShareCount <= 1)); 01480 Pfn1->u2.ShareCount = 0; 01481 Pfn1->u3.e2.ReferenceCount = 0; 01482 MI_SET_PFN_DELETED (Pfn1); 01483 #if DBG 01484 Pfn1->u3.e1.PageLocation = StandbyPageList; 01485 #endif //DBG 01486 MiInsertPageInList (MmPageLocationList[FreePageList], PageFrameIndex); 01487 UNLOCK_PFN (OldIrql); 01488 } 01489 01490 return; 01491 } }

VOID FASTCALL MiInsertBasedSection IN PSECTION  Section  ) 
 

Definition at line 79 of file sectsup.c.

References ASSERT, MiInsertNode(), and MmSectionBasedRoot.

Referenced by MmCreateSection().

00085 : 00086 00087 This function inserts a virtual address descriptor into the tree and 00088 reorders the splay tree as appropriate. 00089 00090 Arguments: 00091 00092 Section - Supplies a pointer to a based section. 00093 00094 Return Value: 00095 00096 None. 00097 00098 Environment: 00099 00100 Must be holding the section based mutex. 00101 00102 --*/ 00103 00104 { 00105 PMMADDRESS_NODE *Root; 00106 00107 ASSERT (Section->Address.EndingVpn > Section->Address.StartingVpn); 00108 00109 Root = &MmSectionBasedRoot; 00110 00111 MiInsertNode (&Section->Address, Root); 00112 return; 00113 }

VOID MiInsertConflictInList IN PMMLOCK_CONFLICT  Conflict  ) 
 

Referenced by MmSecureVirtualMemory(), and NtLockVirtualMemory().

VOID FASTCALL MiInsertFrontModifiedNoWrite IN PFN_NUMBER  PageFrameIndex  ) 
 

Definition at line 1683 of file pfnlist.c.

References ASSERT, _MMPFNLIST::Blink, _MMPFNLIST::Flink, MI_PFN_ELEMENT, MI_TALLY_TRANSITION_PAGE_ADDITION, MM_EMPTY_LIST, MM_PFN_LOCK_ASSERT, MmHighestPhysicalPage, MmLowestPhysicalPage, MmModifiedNoWritePageListHead, ModifiedNoWritePageList, _MMPFNLIST::Total, _MMPFN::u1, _MMPFN::u2, and _MMPFN::u3.

Referenced by MiGatherMappedPages().

01689 : 01690 01691 This procedure inserts a page at the FRONT of the modified no 01692 write list. 01693 01694 Arguments: 01695 01696 PageFrameIndex - Supplies the physical page number to insert in the 01697 list. 01698 01699 Return Value: 01700 01701 none. 01702 01703 Environment: 01704 01705 Must be holding the PFN database mutex with APCs disabled. 01706 01707 --*/ 01708 01709 { 01710 PFN_NUMBER first; 01711 PMMPFN Pfn1; 01712 PMMPFN Pfn2; 01713 01714 MM_PFN_LOCK_ASSERT(); 01715 ASSERT ((PageFrameIndex != 0) && (PageFrameIndex <= MmHighestPhysicalPage) && 01716 (PageFrameIndex >= MmLowestPhysicalPage)); 01717 01718 // 01719 // Check to ensure the reference count for the page 01720 // is zero. 01721 // 01722 01723 Pfn1 = MI_PFN_ELEMENT(PageFrameIndex); 01724 01725 ASSERT (Pfn1->u3.e2.ReferenceCount == 0); 01726 01727 MmModifiedNoWritePageListHead.Total += 1; // One more page on the list. 01728 01729 MI_TALLY_TRANSITION_PAGE_ADDITION (Pfn1); 01730 01731 first = MmModifiedNoWritePageListHead.Flink; 01732 if (first == MM_EMPTY_LIST) { 01733 01734 // 01735 // List is empty add the page to the ListHead. 01736 // 01737 01738 MmModifiedNoWritePageListHead.Blink = PageFrameIndex; 01739 } else { 01740 Pfn2 = MI_PFN_ELEMENT (first); 01741 Pfn2->u2.Blink = PageFrameIndex; 01742 } 01743 01744 MmModifiedNoWritePageListHead.Flink = PageFrameIndex; 01745 Pfn1->u1.Flink = first; 01746 Pfn1->u2.Blink = MM_EMPTY_LIST; 01747 Pfn1->u3.e1.PageLocation = ModifiedNoWritePageList; 01748 return; 01749 } }

VOID FASTCALL MiInsertNode IN PMMADDRESS_NODE  Node,
IN OUT PMMADDRESS_NODE Root
 

Definition at line 464 of file addrsup.c.

References _MMADDRESS_NODE::LeftChild, MiReorderTree(), NULL, _MMADDRESS_NODE::Parent, _MMADDRESS_NODE::RightChild, and _MMADDRESS_NODE::StartingVpn.

Referenced by MiInsertBasedSection(), and MiInsertVad().

00471 : 00472 00473 This function inserts a virtual address descriptor into the tree and 00474 reorders the splay tree as appropriate. 00475 00476 Arguments: 00477 00478 Node - Supplies a pointer to a virtual address descriptor 00479 00480 00481 Return Value: 00482 00483 None. 00484 00485 --*/ 00486 00487 { 00488 ULONG Level = 0; 00489 PMMADDRESS_NODE Parent; 00490 00491 // 00492 // Initialize virtual address descriptor child links. 00493 // 00494 00495 Node->LeftChild = (PMMADDRESS_NODE)NULL; 00496 Node->RightChild = (PMMADDRESS_NODE)NULL; 00497 00498 // 00499 // If the tree is empty, then establish this virtual address descriptor 00500 // as the root of the tree. 00501 // Otherwise descend the tree to find the correct place to 00502 // insert the descriptor. 00503 // 00504 00505 Parent = *Root; 00506 if (!Parent) { 00507 *Root = Node; 00508 Node->Parent = (PMMADDRESS_NODE)NULL; 00509 } else { 00510 00511 for (;;) { 00512 00513 Level += 1; 00514 if (Level == 15) { 00515 MiReorderTree(Parent, Root); 00516 } 00517 00518 // 00519 // If the starting address for this virtual address descriptor 00520 // is less than the parent starting address, then 00521 // follow the left child link. Else follow the right child link. 00522 // 00523 00524 if (Node->StartingVpn < Parent->StartingVpn) { 00525 00526 // 00527 // Starting address of the virtual address descriptor is less 00528 // than the parent starting virtual address. 00529 // Follow left child link if not null. Otherwise 00530 // insert the descriptor as the left child of the parent and 00531 // reorder the tree. 00532 // 00533 00534 if (Parent->LeftChild) { 00535 Parent = Parent->LeftChild; 00536 } else { 00537 Parent->LeftChild = Node; 00538 Node->Parent = Parent; 00539 // MiReorderTree(Node, Root); 00540 break; 00541 } 00542 } else { 00543 00544 // 00545 // Starting address of the virtual address descriptor is greater 00546 // than the parent starting virtual address. 00547 // Follow right child link if not null. Otherwise 00548 // insert the descriptor as the right child of the parent and 00549 // reorder the tree. 00550 // 00551 00552 if (Parent->RightChild) { 00553 Parent = Parent->RightChild; 00554 } else { 00555 Parent->RightChild = Node; 00556 Node->Parent = Parent; 00557 // MiReorderTree(Node, Root); 00558 break; 00559 } 00560 } 00561 } 00562 } 00563 return; 00564 }

VOID FASTCALL MiInsertPageInList IN PMMPFNLIST  ListHead,
IN PFN_NUMBER  PageFrameIndex
 

Definition at line 59 of file pfnlist.c.

References ASSERT, BadPageList, _MMCOLOR_TABLES::Blink, FALSE, _MMCOLOR_TABLES::Flink, FreePageList, KeBugCheckEx(), KeSetEvent(), KeSetTimerEx(), MI_BARRIER_STAMP_ZEROED_PAGE, MI_GET_COLOR_FROM_SECONDARY, MI_GET_PAGE_FRAME_FROM_PTE, MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE, MI_GET_SECONDARY_COLOR, MI_PFN_ELEMENT, MI_TALLY_TRANSITION_PAGE_ADDITION, MiGetByteOffset, MiMapPageInHyperSpace(), MiModifiedPageLife, MiModifiedPageWriterTimer, MiModifiedPageWriterTimerDpc, MiRestoreTransitionPte(), MiTimerPending, MiUnmapPageInHyperSpace, MM_DBG_PAGE_REF_COUNT, MM_EMPTY_LIST, MM_HIGH_LIMIT, MM_LOW_LIMIT, MM_PFN_LOCK_ASSERT, MmAvailablePages, MmAvailablePagesEvent, MmAvailablePagesEventHigh, MmFreePageListHead, MmFreePagesByColor, MmHighestPhysicalPage, MmIsAddressValid(), MmLowestPhysicalPage, MmMinimumFreePagesToZero, MmModifiedPageListByColor, MmModifiedPageListHead, MmModifiedPageMaximum, MmModifiedPageWriterEvent, MmPageLocationList, MmTotalPagesForPagingFile, MmZeroedPageListHead, MmZeroingPageEvent, MmZeroingPageThreadActive, ModifiedNoWritePageList, ModifiedPageList, _MMPFN::OriginalPte, PERFINFO_INSERTINLIST, PsGetCurrentProcess, _MMPFN::PteAddress, _MMPFN::PteFrame, StandbyPageList, _MMPFNLIST::Total, TRUE, _MMPTE::u, _MMPFN::u1, _MMPFN::u2, _MMPFN::u3, VOID(), and ZeroedPageList.

Referenced by MiCleanSection(), MiDecommitPages(), MiDecrementCloneBlockReference(), MiDecrementReferenceCount(), MiDeletePte(), MiDeleteSystemPagableVm(), MiDispatchFault(), MiFreeInitializationCode(), MiGatherMappedPages(), MiInitMachineDependent(), MiModifiedPageWriterWorker(), MiPurgeImageSection(), MiRemovePhysicalPages(), MiResetVirtualMemory(), MiResolveTransitionFault(), MiSegmentDelete(), MmAddPhysicalMemory(), MmDeleteProcessAddressSpace(), MmFreeLoaderBlock(), MmPurgeSection(), MmRemovePhysicalMemory(), and MmZeroPageThread().

00066 : 00067 00068 This procedure inserts a page at the end of the specified list (free, 00069 standby, bad, zeroed, modified). 00070 00071 00072 Arguments: 00073 00074 ListHead - Supplies the list of the list in which to insert the 00075 specified physical page. 00076 00077 PageFrameIndex - Supplies the physical page number to insert in the 00078 list. 00079 00080 Return Value: 00081 00082 none. 00083 00084 Environment: 00085 00086 Must be holding the PFN database mutex with APCs disabled. 00087 00088 --*/ 00089 00090 { 00091 PFN_NUMBER last; 00092 PMMPFN Pfn1; 00093 PMMPFN Pfn2; 00094 ULONG Color; 00095 00096 MM_PFN_LOCK_ASSERT(); 00097 ASSERT ((PageFrameIndex != 0) && 00098 (PageFrameIndex <= MmHighestPhysicalPage) && 00099 (PageFrameIndex >= MmLowestPhysicalPage)); 00100 00101 // 00102 // Check to ensure the reference count for the page is zero. 00103 // 00104 00105 Pfn1 = MI_PFN_ELEMENT(PageFrameIndex); 00106 00107 ASSERT (Pfn1->u3.e1.LockCharged == 0); 00108 00109 PERFINFO_INSERTINLIST(PageFrameIndex, ListHead); 00110 00111 #if DBG 00112 if (MmDebug & MM_DBG_PAGE_REF_COUNT) { 00113 00114 PMMPTE PointerPte; 00115 KIRQL OldIrql = 99; 00116 00117 if ((ListHead->ListName == StandbyPageList) || 00118 (ListHead->ListName == ModifiedPageList)) { 00119 00120 if ((Pfn1->u3.e1.PrototypePte == 1) && 00121 (MmIsAddressValid (Pfn1->PteAddress))) { 00122 PointerPte = Pfn1->PteAddress; 00123 } else { 00124 00125 // 00126 // The page containing the prototype PTE is not valid, 00127 // map the page into hyperspace and reference it that way. 00128 // 00129 00130 PointerPte = MiMapPageInHyperSpace (Pfn1->PteFrame, &OldIrql); 00131 PointerPte = (PMMPTE)((PCHAR)PointerPte + 00132 MiGetByteOffset(Pfn1->PteAddress)); 00133 } 00134 00135 ASSERT ((MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE (PointerPte) == PageFrameIndex) || 00136 (MI_GET_PAGE_FRAME_FROM_PTE (PointerPte) == PageFrameIndex)); 00137 ASSERT (PointerPte->u.Soft.Transition == 1); 00138 ASSERT (PointerPte->u.Soft.Prototype == 0); 00139 if (OldIrql != 99) { 00140 MiUnmapPageInHyperSpace (OldIrql) 00141 } 00142 } 00143 } 00144 #endif 00145 00146 #if PFN_CONSISTENCY 00147 if (ListHead == &MmFreePageListHead) { 00148 if (Pfn1->u2.ShareCount != 0) { 00149 KeBugCheckEx (PFN_LIST_CORRUPT, 00150 0x91, 00151 PageFrameIndex, 00152 Pfn1->u2.ShareCount, 00153 Pfn1->u3.e2.ReferenceCount); 00154 } 00155 } 00156 else if (ListHead == &MmZeroedPageListHead) { 00157 if (Pfn1->u2.ShareCount != 0) { 00158 KeBugCheckEx (PFN_LIST_CORRUPT, 00159 0x92, 00160 PageFrameIndex, 00161 Pfn1->u2.ShareCount, 00162 Pfn1->u3.e2.ReferenceCount); 00163 } 00164 } 00165 #endif 00166 00167 #if DBG 00168 if ((ListHead->ListName == StandbyPageList) || 00169 (ListHead->ListName == ModifiedPageList)) { 00170 if ((Pfn1->OriginalPte.u.Soft.Prototype == 0) && 00171 (Pfn1->OriginalPte.u.Soft.Transition == 1)) { 00172 KeBugCheckEx (MEMORY_MANAGEMENT, 0x8888, 0,0,0); 00173 } 00174 } 00175 #endif 00176 00177 ASSERT (Pfn1->u3.e2.ReferenceCount == 0); 00178 00179 ListHead->Total += 1; // One more page on the list. 00180 00181 // 00182 // On MIPS R4000 modified pages destined for the paging file are 00183 // kept on separate lists which group pages of the same color 00184 // together 00185 // 00186 00187 if (ListHead == &MmModifiedPageListHead) { 00188 00189 #if PFN_CONSISTENCY 00190 if (Pfn1->u2.ShareCount != 0) { 00191 KeBugCheckEx (PFN_LIST_CORRUPT, 00192 0x90, 00193 PageFrameIndex, 00194 Pfn1->u2.ShareCount, 00195 Pfn1->u3.e2.ReferenceCount); 00196 } 00197 #endif 00198 00199 if (Pfn1->OriginalPte.u.Soft.Prototype == 0) { 00200 00201 // 00202 // This page is destined for the paging file (not 00203 // a mapped file). Change the list head to the 00204 // appropriate colored list head. 00205 // 00206 00207 ListHead = &MmModifiedPageListByColor [Pfn1->u3.e1.PageColor]; 00208 ListHead->Total += 1; 00209 MmTotalPagesForPagingFile += 1; 00210 } 00211 else { 00212 00213 // 00214 // This page is destined for a mapped file (not 00215 // the paging file). If there are no other pages currently 00216 // destined for the mapped file, start our timer so that we can 00217 // ensure that these pages make it to disk even if we don't pile 00218 // up enough of them to trigger the modified page writer or need 00219 // the memory. If we don't do this here, then for this scenario, 00220 // only an orderly system shutdown will write them out (days, 00221 // weeks, months or years later) and any power out in between 00222 // means we'll have lost the data. 00223 // 00224 00225 if (ListHead->Total - MmTotalPagesForPagingFile == 1) { 00226 00227 // 00228 // Start the DPC timer because we're the first on the list. 00229 // 00230 00231 if (MiTimerPending == FALSE) { 00232 MiTimerPending = TRUE; 00233 00234 (VOID) KeSetTimerEx( &MiModifiedPageWriterTimer, MiModifiedPageLife, 0, &MiModifiedPageWriterTimerDpc ); 00235 } 00236 } 00237 } 00238 } 00239 else if ((Pfn1->u3.e1.RemovalRequested == 1) && 00240 (ListHead->ListName <= StandbyPageList)) { 00241 00242 ListHead->Total -= 1; // Undo previous increment 00243 00244 if (ListHead->ListName == StandbyPageList) { 00245 Pfn1->u3.e1.PageLocation = StandbyPageList; 00246 MiRestoreTransitionPte (PageFrameIndex); 00247 } 00248 00249 ListHead = MmPageLocationList[BadPageList]; 00250 ListHead->Total += 1; // One more page on the list. 00251 } 00252 00253 00254 last = ListHead->Blink; 00255 if (last == MM_EMPTY_LIST) { 00256 00257 // 00258 // List is empty add the page to the ListHead. 00259 // 00260 00261 ListHead->Flink = PageFrameIndex; 00262 } else { 00263 Pfn2 = MI_PFN_ELEMENT (last); 00264 Pfn2->u1.Flink = PageFrameIndex; 00265 } 00266 00267 ListHead->Blink = PageFrameIndex; 00268 Pfn1->u1.Flink = MM_EMPTY_LIST; 00269 Pfn1->u2.Blink = last; 00270 Pfn1->u3.e1.PageLocation = ListHead->ListName; 00271 00272 // 00273 // If the page was placed on the free, standby or zeroed list, 00274 // update the count of usable pages in the system. If the count 00275 // transitions from 0 to 1, the event associated with available 00276 // pages should become true. 00277 // 00278 00279 if (ListHead->ListName <= StandbyPageList) { 00280 MmAvailablePages += 1; 00281 00282 // 00283 // A page has just become available, check to see if the 00284 // page wait events should be signalled. 00285 // 00286 00287 if (MmAvailablePages == MM_LOW_LIMIT) { 00288 KeSetEvent (&MmAvailablePagesEvent, 0, FALSE); 00289 } else if (MmAvailablePages == MM_HIGH_LIMIT) { 00290 KeSetEvent (&MmAvailablePagesEventHigh, 0, FALSE); 00291 } 00292 00293 if (ListHead->ListName <= FreePageList) { 00294 00295 ASSERT (Pfn1->u3.e1.InPageError == 0); 00296 00297 // 00298 // We are adding a page to the free or zeroed page list. 00299 // Add the page to the end of the correct colored page list. 00300 // 00301 00302 Color = MI_GET_SECONDARY_COLOR (PageFrameIndex, Pfn1); 00303 ASSERT (Pfn1->u3.e1.PageColor == MI_GET_COLOR_FROM_SECONDARY(Color)); 00304 00305 if (MmFreePagesByColor[ListHead->ListName][Color].Flink == 00306 MM_EMPTY_LIST) { 00307 00308 // 00309 // This list is empty, add this as the first and last 00310 // entry. 00311 // 00312 00313 MmFreePagesByColor[ListHead->ListName][Color].Flink = 00314 PageFrameIndex; 00315 MmFreePagesByColor[ListHead->ListName][Color].Blink = 00316 (PVOID)Pfn1; 00317 } else { 00318 Pfn2 = (PMMPFN)MmFreePagesByColor[ListHead->ListName][Color].Blink; 00319 Pfn2->OriginalPte.u.Long = PageFrameIndex; 00320 MmFreePagesByColor[ListHead->ListName][Color].Blink = (PVOID)Pfn1; 00321 } 00322 Pfn1->OriginalPte.u.Long = MM_EMPTY_LIST; 00323 00324 if (ListHead->ListName == ZeroedPageList) { 00325 MI_BARRIER_STAMP_ZEROED_PAGE (&Pfn1->PteFrame); 00326 } 00327 } 00328 else { 00329 00330 // 00331 // Transition page list so tally it appropriately. 00332 // 00333 00334 MI_TALLY_TRANSITION_PAGE_ADDITION (Pfn1); 00335 } 00336 00337 if ((ListHead->ListName == FreePageList) && 00338 (MmFreePageListHead.Total >= MmMinimumFreePagesToZero) && 00339 (MmZeroingPageThreadActive == FALSE)) { 00340 00341 // 00342 // There are enough pages on the free list, start 00343 // the zeroing page thread. 00344 // 00345 00346 MmZeroingPageThreadActive = TRUE; 00347 KeSetEvent (&MmZeroingPageEvent, 0, FALSE); 00348 } 00349 return; 00350 } 00351 00352 // 00353 // Check to see if there are too many modified pages. 00354 // 00355 00356 if (ListHead->ListName == ModifiedPageList) { 00357 00358 // 00359 // Transition page list so tally it appropriately. 00360 // 00361 00362 MI_TALLY_TRANSITION_PAGE_ADDITION (Pfn1); 00363 00364 if (Pfn1->OriginalPte.u.Soft.Prototype == 0) { 00365 ASSERT (Pfn1->OriginalPte.u.Soft.PageFileHigh == 0); 00366 } 00367 00368 PsGetCurrentProcess()->ModifiedPageCount += 1; 00369 if (MmModifiedPageListHead.Total >= MmModifiedPageMaximum ) { 00370 00371 // 00372 // Start the modified page writer. 00373 // 00374 00375 KeSetEvent (&MmModifiedPageWriterEvent, 0, FALSE); 00376 } 00377 } 00378 else if (ListHead->ListName == ModifiedNoWritePageList) { 00379 MI_TALLY_TRANSITION_PAGE_ADDITION (Pfn1); 00380 } 00381 00382 return; 00383 }

VOID FASTCALL MiInsertStandbyListAtFront IN PFN_NUMBER  PageFrameIndex  ) 
 

Definition at line 388 of file pfnlist.c.

References ASSERT, FALSE, _MMPFNLIST::Flink, KeBugCheckEx(), KeSetEvent(), MI_GET_PAGE_FRAME_FROM_PTE, MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE, MI_PFN_ELEMENT, MiGetByteOffset, MiMapPageInHyperSpace(), MiUnmapPageInHyperSpace, MM_DBG_PAGE_REF_COUNT, MM_EMPTY_LIST, MM_HIGH_LIMIT, MM_LOW_LIMIT, MM_PFN_LOCK_ASSERT, MmAvailablePages, MmAvailablePagesEvent, MmAvailablePagesEventHigh, MmHighestPhysicalPage, MmIsAddressValid(), MmLowestPhysicalPage, MmModifiedNoWritePageListHead, MmModifiedPageListHead, MmStandbyPageListHead, MmTransitionPrivatePages, MmTransitionSharedPages, _MMPFN::OriginalPte, PERFINFO_INSERT_FRONT_STANDBY, _MMPFN::PteAddress, _MMPFN::PteFrame, StandbyPageList, _MMPFNLIST::Total, _MMPTE::u, _MMPFN::u1, _MMPFN::u2, and _MMPFN::u3.

Referenced by MiDecrementReferenceCount().

00394 : 00395 00396 This procedure inserts a page at the front of the standby list. 00397 00398 Arguments: 00399 00400 PageFrameIndex - Supplies the physical page number to insert in the 00401 list. 00402 00403 Return Value: 00404 00405 none. 00406 00407 Environment: 00408 00409 Must be holding the PFN database mutex with APCs disabled. 00410 00411 --*/ 00412 00413 { 00414 PFN_NUMBER first; 00415 IN PMMPFNLIST ListHead; 00416 PMMPFN Pfn1; 00417 PMMPFN Pfn2; 00418 00419 MM_PFN_LOCK_ASSERT(); 00420 ASSERT ((PageFrameIndex != 0) && (PageFrameIndex <= MmHighestPhysicalPage) && 00421 (PageFrameIndex >= MmLowestPhysicalPage)); 00422 00423 // 00424 // Check to ensure the reference count for the page 00425 // is zero. 00426 // 00427 00428 Pfn1 = MI_PFN_ELEMENT(PageFrameIndex); 00429 00430 PERFINFO_INSERT_FRONT_STANDBY(PageFrameIndex); 00431 00432 #if DBG 00433 if (MmDebug & MM_DBG_PAGE_REF_COUNT) { 00434 00435 PMMPTE PointerPte; 00436 KIRQL OldIrql = 99; 00437 00438 if ((Pfn1->u3.e1.PrototypePte == 1) && 00439 (MmIsAddressValid (Pfn1->PteAddress))) { 00440 PointerPte = Pfn1->PteAddress; 00441 } else { 00442 00443 // 00444 // The page containing the prototype PTE is not valid, 00445 // map the page into hyperspace and reference it that way. 00446 // 00447 00448 PointerPte = MiMapPageInHyperSpace (Pfn1->PteFrame, &OldIrql); 00449 PointerPte = (PMMPTE)((PCHAR)PointerPte + 00450 MiGetByteOffset(Pfn1->PteAddress)); 00451 } 00452 00453 ASSERT ((MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE (PointerPte) == PageFrameIndex) || 00454 (MI_GET_PAGE_FRAME_FROM_PTE (PointerPte) == PageFrameIndex)); 00455 ASSERT (PointerPte->u.Soft.Transition == 1); 00456 ASSERT (PointerPte->u.Soft.Prototype == 0); 00457 if (OldIrql != 99) { 00458 MiUnmapPageInHyperSpace (OldIrql) 00459 } 00460 } 00461 00462 if ((Pfn1->OriginalPte.u.Soft.Prototype == 0) && 00463 (Pfn1->OriginalPte.u.Soft.Transition == 1)) { 00464 KeBugCheckEx (MEMORY_MANAGEMENT, 0x8889, 0,0,0); 00465 } 00466 #endif 00467 00468 ASSERT (Pfn1->u3.e2.ReferenceCount == 0); 00469 ASSERT (Pfn1->u3.e1.PrototypePte == 1); 00470 MmTransitionSharedPages += 1; 00471 00472 MmStandbyPageListHead.Total += 1; // One more page on the list. 00473 00474 ASSERT (MmTransitionPrivatePages + MmTransitionSharedPages == MmStandbyPageListHead.Total + MmModifiedPageListHead.Total + MmModifiedNoWritePageListHead.Total); 00475 00476 ListHead = &MmStandbyPageListHead; 00477 00478 first = ListHead->Flink; 00479 if (first == MM_EMPTY_LIST) { 00480 00481 // 00482 // List is empty add the page to the ListHead. 00483 // 00484 00485 ListHead->Blink = PageFrameIndex; 00486 } else { 00487 Pfn2 = MI_PFN_ELEMENT (first); 00488 Pfn2->u2.Blink = PageFrameIndex; 00489 } 00490 00491 ListHead->Flink = PageFrameIndex; 00492 Pfn1->u2.Blink = MM_EMPTY_LIST; 00493 Pfn1->u1.Flink = first; 00494 Pfn1->u3.e1.PageLocation = StandbyPageList; 00495 00496 // 00497 // If the page was placed on the free, standby or zeroed list, 00498 // update the count of usable pages in the system. If the count 00499 // transitions from 0 to 1, the event associated with available 00500 // pages should become true. 00501 // 00502 00503 MmAvailablePages += 1; 00504 00505 // 00506 // A page has just become available, check to see if the 00507 // page wait events should be signalled. 00508 // 00509 00510 if (MmAvailablePages == MM_LOW_LIMIT) { 00511 KeSetEvent (&MmAvailablePagesEvent, 0, FALSE); 00512 } else if (MmAvailablePages == MM_HIGH_LIMIT) { 00513 KeSetEvent (&MmAvailablePagesEventHigh, 0, FALSE); 00514 } 00515 00516 return; 00517 }

VOID MiInsertVad IN PMMVAD  Vad  ) 
 

Definition at line 30 of file vadtree.c.

References ASSERT, _EPROCESS::CommitCharge, _EPROCESS::CommitChargeLimit, _EPROCESS::CommitChargePeak, _MMWSL::CommittedPageTables, EXCEPTION_EXECUTE_HANDLER, ExRaiseStatus(), FALSE, _EPROCESS::Job, _EPROCESS::JobStatus, MI_CHECK_BIT, MI_SET_BIT, MI_VA_TO_VPN, MI_VPN_TO_VA, MiChargeCommitment(), MiChargePageFileQuota(), MiGetPpePdeOffset, MiInsertNode(), MiReturnPageFileQuota(), MM_DBG_COMMIT_INSERT_VAD, MM_MAX_COMMIT, MM_TRACK_COMMIT, MMVAD, MmWorkingSetList, NonPagedPool, NULL, _MMWSL::NumberOfCommittedPageTables, PagedPool, PDE_PER_PAGE, PS_JOB_STATUS_REPORT_COMMIT_CHANGES, PsChangeJobMemoryUsage(), PsChargePoolQuota(), PsGetCurrentProcess, PsReportProcessMemoryLimitViolation(), PsReturnPoolQuota(), PTE_SHIFT, TRUE, _EPROCESS::VadFreeHint, _EPROCESS::VadHint, _EPROCESS::VadRoot, and X64K.

Referenced by MiCloneProcessAddressSpace(), MiCreatePebOrTeb(), MiMapLockedPagesInUserSpace(), MiMapViewOfDataSection(), MiMapViewOfImageSection(), MiMapViewOfPhysicalSection(), MmInitializeProcessAddressSpace(), NtAllocateVirtualMemory(), and NtFreeVirtualMemory().

00036 : 00037 00038 This function inserts a virtual address descriptor into the tree and 00039 reorders the splay tree as appropriate. 00040 00041 Arguments: 00042 00043 Vad - Supplies a pointer to a virtual address descriptor 00044 00045 00046 Return Value: 00047 00048 None - An exception is raised if quota is exceeded. 00049 00050 --*/ 00051 00052 { 00053 PMMADDRESS_NODE *Root; 00054 PEPROCESS CurrentProcess; 00055 SIZE_T RealCharge; 00056 SIZE_T PageCharge; 00057 SIZE_T PagedQuotaCharged; 00058 ULONG FirstPage; 00059 ULONG LastPage; 00060 SIZE_T PagedPoolCharge; 00061 LOGICAL ChargedPageFileQuota; 00062 LOGICAL ChargedJobCommit; 00063 00064 ASSERT (Vad->EndingVpn >= Vad->StartingVpn); 00065 00066 CurrentProcess = PsGetCurrentProcess(); 00067 00068 // 00069 // Commit charge of MAX_COMMIT means don't charge quota. 00070 // 00071 00072 if (Vad->u.VadFlags.CommitCharge != MM_MAX_COMMIT) { 00073 00074 PageCharge = 0; 00075 PagedQuotaCharged = 0; 00076 ChargedPageFileQuota = FALSE; 00077 ChargedJobCommit = FALSE; 00078 00079 // 00080 // Charge quota for the nonpaged pool for the VAD. This is 00081 // done here rather than by using ExAllocatePoolWithQuota 00082 // so the process object is not referenced by the quota charge. 00083 // 00084 00085 PsChargePoolQuota (CurrentProcess, NonPagedPool, sizeof(MMVAD)); 00086 00087 try { 00088 00089 // 00090 // Charge quota for the prototype PTEs if this is a mapped view. 00091 // 00092 00093 if ((Vad->u.VadFlags.PrivateMemory == 0) && 00094 (Vad->ControlArea != NULL)) { 00095 PagedPoolCharge = 00096 (Vad->EndingVpn - Vad->StartingVpn) << PTE_SHIFT; 00097 PsChargePoolQuota (CurrentProcess, PagedPool, PagedPoolCharge); 00098 PagedQuotaCharged = PagedPoolCharge; 00099 } 00100 00101 #if !defined (_WIN64) 00102 // 00103 // Add in the charge for page table pages. 00104 // 00105 00106 FirstPage = MiGetPpePdeOffset (MI_VPN_TO_VA (Vad->StartingVpn)); 00107 LastPage = MiGetPpePdeOffset (MI_VPN_TO_VA (Vad->EndingVpn)); 00108 00109 while (FirstPage <= LastPage) { 00110 00111 if (!MI_CHECK_BIT (MmWorkingSetList->CommittedPageTables, 00112 FirstPage)) { 00113 PageCharge += 1; 00114 } 00115 FirstPage += 1; 00116 } 00117 #endif 00118 00119 RealCharge = Vad->u.VadFlags.CommitCharge + PageCharge; 00120 00121 if (RealCharge != 0) { 00122 00123 MiChargePageFileQuota (RealCharge, CurrentProcess); 00124 ChargedPageFileQuota = TRUE; 00125 00126 #if 0 //commented out so page file quota is meaningful. 00127 if (Vad->u.VadFlags.PrivateMemory == 0) { 00128 00129 if ((Vad->ControlArea->FilePointer == NULL) && 00130 (Vad->u.VadFlags.PhysicalMapping == 0)) { 00131 00132 // 00133 // Don't charge commitment for the page file space 00134 // occupied by a page file section. This will be 00135 // charged as the shared memory is committed. 00136 // 00137 00138 RealCharge -= 1 + (Vad->EndingVpn - 00139 Vad->StartingVpn); 00140 } 00141 } 00142 #endif //0 00143 if (CurrentProcess->CommitChargeLimit) { 00144 if (CurrentProcess->CommitCharge + RealCharge > CurrentProcess->CommitChargeLimit) { 00145 if (CurrentProcess->Job) { 00146 PsReportProcessMemoryLimitViolation (); 00147 } 00148 ExRaiseStatus (STATUS_COMMITMENT_LIMIT); 00149 } 00150 } 00151 if (CurrentProcess->JobStatus & PS_JOB_STATUS_REPORT_COMMIT_CHANGES) { 00152 if (PsChangeJobMemoryUsage(RealCharge) == FALSE) { 00153 ExRaiseStatus (STATUS_COMMITMENT_LIMIT); 00154 } 00155 ChargedJobCommit = TRUE; 00156 } 00157 00158 if (MiChargeCommitment (RealCharge, CurrentProcess) == FALSE) { 00159 ExRaiseStatus (STATUS_COMMITMENT_LIMIT); 00160 } 00161 00162 CurrentProcess->CommitCharge += RealCharge; 00163 if (CurrentProcess->CommitCharge > CurrentProcess->CommitChargePeak) { 00164 CurrentProcess->CommitChargePeak = CurrentProcess->CommitCharge; 00165 } 00166 } 00167 } except (EXCEPTION_EXECUTE_HANDLER) { 00168 00169 // 00170 // Return any quotas charged thus far. 00171 // 00172 00173 PsReturnPoolQuota (CurrentProcess, NonPagedPool, sizeof(MMVAD)); 00174 00175 if (PagedQuotaCharged != 0) { 00176 PsReturnPoolQuota (CurrentProcess, PagedPool, PagedPoolCharge); 00177 } 00178 00179 if (ChargedPageFileQuota == TRUE) { 00180 00181 MiReturnPageFileQuota (RealCharge, 00182 CurrentProcess); 00183 } 00184 00185 if (ChargedJobCommit == TRUE) { 00186 00187 // 00188 // Temporarily up the process commit charge as the 00189 // job code will be referencing it as though everything 00190 // has succeeded. 00191 // 00192 00193 CurrentProcess->CommitCharge += RealCharge; 00194 PsChangeJobMemoryUsage(-(SSIZE_T)RealCharge); 00195 CurrentProcess->CommitCharge -= RealCharge; 00196 } 00197 00198 ExRaiseStatus (GetExceptionCode()); 00199 } 00200 00201 MM_TRACK_COMMIT (MM_DBG_COMMIT_INSERT_VAD, RealCharge); 00202 00203 #if !defined (_WIN64) 00204 if (PageCharge != 0) { 00205 00206 // 00207 // Since the commitment was successful, charge the page 00208 // table pages. 00209 // 00210 00211 FirstPage = MiGetPpePdeOffset (MI_VPN_TO_VA (Vad->StartingVpn)); 00212 00213 while (FirstPage <= LastPage) { 00214 00215 if (!MI_CHECK_BIT (MmWorkingSetList->CommittedPageTables, 00216 FirstPage)) { 00217 MI_SET_BIT (MmWorkingSetList->CommittedPageTables, 00218 FirstPage); 00219 MmWorkingSetList->NumberOfCommittedPageTables += 1; 00220 #if defined (_X86PAE_) 00221 ASSERT (MmWorkingSetList->NumberOfCommittedPageTables < 00222 PD_PER_SYSTEM * PDE_PER_PAGE); 00223 #else 00224 ASSERT (MmWorkingSetList->NumberOfCommittedPageTables < 00225 PDE_PER_PAGE); 00226 #endif 00227 } 00228 FirstPage += 1; 00229 } 00230 } 00231 #endif 00232 } 00233 00234 Root = (PMMADDRESS_NODE *)&CurrentProcess->VadRoot; 00235 00236 // 00237 // Set the hint field in the process to this Vad. 00238 // 00239 00240 CurrentProcess->VadHint = Vad; 00241 00242 if (CurrentProcess->VadFreeHint != NULL) { 00243 if (((ULONG)((PMMVAD)CurrentProcess->VadFreeHint)->EndingVpn + 00244 MI_VA_TO_VPN (X64K)) >= 00245 Vad->StartingVpn) { 00246 CurrentProcess->VadFreeHint = Vad; 00247 } 00248 } 00249 00250 MiInsertNode ( (PMMADDRESS_NODE)Vad, Root); 00251 return; 00252 }

VOID FASTCALL MiInsertWsle IN WSLE_NUMBER  Entry,
IN PMMWSL  WorkingSetList
 

Definition at line 51 of file wstree.c.

References _MMSUPPORT::AllowWorkingSetAdjustment, ASSERT, DbgPrint, _MMWSLENTRY::Direct, _MMWSLE::e1, Index, _MMWSLE_HASH::Index, KeQueryTickCount(), _MMWSLE_HASH::Key, Key, LOCK_EXPANSION_IF_ALPHA, _MMWSLE::Long, MI_WSLE_HASH, MiCheckWsleHash(), MiFreeWsle(), MiGetPteAddress, MM_DBG_PTE_UPDATE, MM_GROW_WSLE_HASH, MmSessionSpace, MmSystemCacheWorkingSetList, MmSystemCacheWs, MmWorkingSetList, NULL, PAGE_ALIGN, PAGE_SIZE, PERFINFO_GET_PAGE_INFO, PERFINFO_LOG_WS_REMOVAL, PERFINFO_PAGE_INFO_DECL, PsGetCurrentProcess, Size, TickCount(), TRUE, _MMSUPPORT::u, _MMWSLE::u1, UNLOCK_EXPANSION_IF_ALPHA, _MMWSLENTRY::Valid, _MMWSLE::VirtualAddress, _MM_SESSION_SPACE::Vm, and WSLE_NUMBER.

Referenced by MiRemoveWorkingSetPages(), and MiUpdateWsle().

00058 : 00059 00060 This routine inserts a Working Set List Entry (WSLE) into the 00061 working set. 00062 00063 Arguments: 00064 00065 Entry - The index number of the WSLE to insert. 00066 00067 WorkingSetList - Supplies the working set list to insert into. 00068 00069 Return Value: 00070 00071 None. 00072 00073 Environment: 00074 00075 Kernel mode, APCs disabled, Working Set Mutex held. 00076 00077 --*/ 00078 00079 { 00080 PVOID VirtualAddress; 00081 PMMWSLE Wsle; 00082 PMMSUPPORT WsInfo; 00083 WSLE_NUMBER Hash; 00084 PMMWSLE_HASH Table; 00085 WSLE_NUMBER j; 00086 PMMPTE PointerPte; 00087 WSLE_NUMBER Index; 00088 LARGE_INTEGER TickCount; 00089 ULONG Size; 00090 #if defined(_ALPHA_) && !defined(_AXP64_) 00091 KIRQL OldIrql; 00092 #endif 00093 00094 Wsle = WorkingSetList->Wsle; 00095 00096 VirtualAddress = PAGE_ALIGN(Wsle[Entry].u1.VirtualAddress); 00097 00098 #if DBG 00099 if (MmDebug & MM_DBG_PTE_UPDATE) { 00100 DbgPrint("inserting element %lx %lx\n", Entry, Wsle[Entry].u1.Long); 00101 } 00102 00103 ASSERT (Wsle[Entry].u1.e1.Valid == 1); 00104 ASSERT (Wsle[Entry].u1.e1.Direct != 1); 00105 #endif //DBG 00106 00107 WorkingSetList->NonDirectCount += 1; 00108 00109 if ((Table = WorkingSetList->HashTable) == NULL) { 00110 return; 00111 } 00112 00113 #if DBG 00114 MmNumberOfInserts += 1; 00115 #endif //DBG 00116 00117 Hash = MI_WSLE_HASH(Wsle[Entry].u1.Long, WorkingSetList); 00118 00119 // 00120 // Check hash table size and see if there is enough room to 00121 // hash or if the table should be grown. 00122 // 00123 00124 if ((WorkingSetList->NonDirectCount + 10 + 00125 (WorkingSetList->HashTableSize >> 4)) > 00126 WorkingSetList->HashTableSize) { 00127 00128 if (WorkingSetList == MmWorkingSetList) { 00129 WsInfo = &PsGetCurrentProcess()->Vm; 00130 ASSERT (WsInfo->u.Flags.SessionSpace == 0); 00131 } 00132 else if (WorkingSetList == MmSystemCacheWorkingSetList) { 00133 WsInfo = &MmSystemCacheWs; 00134 ASSERT (WsInfo->u.Flags.SessionSpace == 0); 00135 } 00136 else { 00137 WsInfo = &MmSessionSpace->Vm; 00138 ASSERT (WsInfo->u.Flags.SessionSpace == 1); 00139 } 00140 00141 if ((Table + WorkingSetList->HashTableSize + ((2*PAGE_SIZE) / sizeof (MMWSLE_HASH)) <= (PMMWSLE_HASH)WorkingSetList->HighestPermittedHashAddress) && 00142 (WsInfo->AllowWorkingSetAdjustment)) { 00143 00144 #if defined(_ALPHA_) && !defined(_AXP64_) 00145 LOCK_EXPANSION_IF_ALPHA (OldIrql); 00146 #endif 00147 WsInfo->AllowWorkingSetAdjustment = MM_GROW_WSLE_HASH; 00148 #if defined(_ALPHA_) && !defined(_AXP64_) 00149 UNLOCK_EXPANSION_IF_ALPHA (OldIrql); 00150 #endif 00151 } 00152 00153 if ((WorkingSetList->NonDirectCount + 00154 (WorkingSetList->HashTableSize >> 4)) > 00155 WorkingSetList->HashTableSize) { 00156 00157 // 00158 // No more room in the hash table, remove one and add there. 00159 // Pick a victim within 16 of where this would hash to. 00160 // 00161 00162 KeQueryTickCount(&TickCount); 00163 j = Hash + (TickCount.LowPart & 0xF); 00164 00165 Size = WorkingSetList->HashTableSize; 00166 00167 if (j >= Size) { 00168 j = TickCount.LowPart & 0xF; 00169 } 00170 00171 do { 00172 if (Table[j].Key != 0) { 00173 PERFINFO_PAGE_INFO_DECL(); 00174 00175 PointerPte = MiGetPteAddress (Table[j].Key); 00176 Index = WorkingSetList->HashTable[j].Index; 00177 ASSERT (Wsle[Index].u1.e1.Valid == 1); 00178 PointerPte = MiGetPteAddress (Wsle[Index].u1.VirtualAddress); 00179 00180 PERFINFO_GET_PAGE_INFO(PointerPte); 00181 if (MiFreeWsle (Index, WsInfo, PointerPte)) { 00182 PERFINFO_LOG_WS_REMOVAL(PERFINFO_LOG_TYPE_OUTWS_HASHFULL, WsInfo); 00183 break; 00184 } 00185 } 00186 j += 1; 00187 if (j >= Size) { 00188 j = 0; 00189 } 00190 } while (TRUE); 00191 } 00192 } 00193 00194 // 00195 // Add to the hash table. 00196 // 00197 00198 while (Table[Hash].Key != 0) { 00199 Hash += 1; 00200 if (Hash >= WorkingSetList->HashTableSize) { 00201 Hash = 0; 00202 } 00203 } 00204 00205 Table[Hash].Key = Wsle[Entry].u1.Long & ~(PAGE_SIZE - 1); 00206 Table[Hash].Index = Entry; 00207 00208 #if DBG 00209 if ((MmNumberOfInserts % 1000) == 0) { 00210 MiCheckWsleHash (WorkingSetList); 00211 } 00212 #endif //DBG 00213 return; 00214 }

ULONG MiIsEntireRangeCommitted IN PVOID  StartingAddress,
IN PVOID  EndingAddress,
IN PMMVAD  Vad,
IN PEPROCESS  Process
 

Definition at line 937 of file freevm.c.

References FALSE, MiDoesPdeExistAndMakeValid(), MiDoesPpeExistAndMakeValid, MiGetPdeAddress, MiGetPteAddress, MiGetVirtualAddressMappedByPte, MiIsPteDecommittedPage(), MiIsPteOnPdeBoundary, PAGE_SIZE, PAGED_CODE, TRUE, and _MMPTE::u.

Referenced by MiProtectVirtualMemory(), and NtFreeVirtualMemory().

00946 : 00947 00948 This routine examines the range of pages from the starting address 00949 up to and including the ending address and returns TRUE if every 00950 page in the range is committed, FALSE otherwise. 00951 00952 Arguments: 00953 00954 StartingAddress - Supplies the starting address of the range. 00955 00956 EndingAddress - Supplies the ending address of the range. 00957 00958 Vad - Supplies the virtual address descriptor which describes the range. 00959 00960 Process - Supplies the current process. 00961 00962 Return Value: 00963 00964 TRUE if the entire range is committed. 00965 FALSE if any page within the range is not committed. 00966 00967 Environment: 00968 00969 Kernel mode, APCs disable, WorkingSetMutex and AddressCreation mutexes 00970 held. 00971 00972 --*/ 00973 00974 { 00975 PMMPTE PointerPte; 00976 PMMPTE LastPte; 00977 PMMPTE PointerPde; 00978 PMMPTE PointerPpe; 00979 ULONG FirstTime; 00980 ULONG Waited; 00981 PVOID Va; 00982 00983 PAGED_CODE(); 00984 00985 FirstTime = TRUE; 00986 00987 PointerPde = MiGetPdeAddress (StartingAddress); 00988 PointerPte = MiGetPteAddress (StartingAddress); 00989 LastPte = MiGetPteAddress (EndingAddress); 00990 00991 // 00992 // Set the Va to the starting address + 8, this solves problems 00993 // associated with address 0 (NULL) being used as a valid virtual 00994 // address and NULL in the VAD commitment field indicating no pages 00995 // are committed. 00996 // 00997 00998 Va = (PVOID)((PCHAR)StartingAddress + 8); 00999 01000 while (PointerPte <= LastPte) { 01001 01002 if (MiIsPteOnPdeBoundary(PointerPte) || (FirstTime)) { 01003 01004 // 01005 // This may be a PPE/PDE boundary, check to see if both 01006 // PPE/PDE pages exist. 01007 // 01008 01009 FirstTime = FALSE; 01010 PointerPde = MiGetPteAddress (PointerPte); 01011 PointerPpe = MiGetPteAddress (PointerPde); 01012 01013 do { 01014 01015 while (!MiDoesPpeExistAndMakeValid(PointerPpe, Process, FALSE, &Waited)) { 01016 01017 // 01018 // No PDE exists for the starting address, check the VAD 01019 // to see if the pages are committed. 01020 // 01021 01022 PointerPpe += 1; 01023 01024 PointerPde = MiGetVirtualAddressMappedByPte (PointerPpe); 01025 PointerPte = MiGetVirtualAddressMappedByPte (PointerPde); 01026 Va = MiGetVirtualAddressMappedByPte (PointerPte); 01027 01028 if (PointerPte > LastPte) { 01029 01030 // 01031 // Make sure the entire range is committed. 01032 // 01033 01034 if (Vad->u.VadFlags.MemCommit == 0) { 01035 01036 // 01037 // The entire range to be decommitted is not committed, 01038 // return an error. 01039 // 01040 01041 return FALSE; 01042 } else { 01043 return TRUE; 01044 } 01045 } 01046 01047 // 01048 // Make sure the range thus far is committed. 01049 // 01050 01051 if (Vad->u.VadFlags.MemCommit == 0) { 01052 01053 // 01054 // The entire range to be decommitted is not committed, 01055 // return an error. 01056 // 01057 01058 return FALSE; 01059 } 01060 } 01061 01062 Waited = 0; 01063 01064 while (!MiDoesPdeExistAndMakeValid(PointerPde, Process, FALSE, &Waited)) { 01065 01066 // 01067 // No PDE exists for the starting address, check the VAD 01068 // to see if the pages are committed. 01069 // 01070 01071 PointerPde += 1; 01072 01073 PointerPpe = MiGetPteAddress (PointerPde); 01074 PointerPte = MiGetVirtualAddressMappedByPte (PointerPde); 01075 Va = MiGetVirtualAddressMappedByPte (PointerPte); 01076 01077 if (PointerPte > LastPte) { 01078 01079 // 01080 // Make sure the entire range is committed. 01081 // 01082 01083 if (Vad->u.VadFlags.MemCommit == 0) { 01084 01085 // 01086 // The entire range to be decommitted is not committed, 01087 // return an error. 01088 // 01089 01090 return FALSE; 01091 } else { 01092 return TRUE; 01093 } 01094 } 01095 01096 // 01097 // Make sure the range thus far is committed. 01098 // 01099 01100 if (Vad->u.VadFlags.MemCommit == 0) { 01101 01102 // 01103 // The entire range to be decommitted is not committed, 01104 // return an error. 01105 // 01106 01107 return FALSE; 01108 } 01109 #if defined (_WIN64) 01110 if (MiIsPteOnPdeBoundary (PointerPde)) { 01111 PointerPpe = MiGetPteAddress (PointerPde); 01112 Waited = 1; 01113 break; 01114 } 01115 #endif 01116 } 01117 } while (Waited != 0); 01118 } 01119 01120 // 01121 // The page table page exists, check each PTE for commitment. 01122 // 01123 01124 if (PointerPte->u.Long == 0) { 01125 01126 // 01127 // This page has not been committed, check the VAD. 01128 // 01129 01130 if (Vad->u.VadFlags.MemCommit == 0) { 01131 01132 // 01133 // The entire range to be decommitted is not committed, 01134 // return an error. 01135 // 01136 01137 return FALSE; 01138 } 01139 } else { 01140 01141 // 01142 // Has this page been explicitly decommitted? 01143 // 01144 01145 if (MiIsPteDecommittedPage (PointerPte)) { 01146 01147 // 01148 // This page has been explicitly decommitted, return an error. 01149 // 01150 01151 return FALSE; 01152 } 01153 } 01154 PointerPte += 1; 01155 Va = (PVOID)((PCHAR)(Va) + PAGE_SIZE); 01156 } 01157 return TRUE; 01158 }

ULONG MiIsEntireRangeDecommitted IN PVOID  StartingAddress,
IN PVOID  EndingAddress,
IN PMMVAD  Vad,
IN PEPROCESS  Process
 

Referenced by NtAllocateVirtualMemory().

ULONG FASTCALL MiIsProtectionCompatible IN ULONG  OldProtect,
IN ULONG  NewProtect
 

Definition at line 139 of file mmsup.c.

References EXCEPTION_EXECUTE_HANDLER, FALSE, MiMakeProtectionMask(), MmCompatibleProtectionMask, and TRUE.

Referenced by NtMapViewOfSection().

00146 : 00147 00148 This function takes two user supplied page protections and checks 00149 to see if the new protection is compatible with the old protection. 00150 00151 protection compatible protections 00152 NoAccess NoAccess 00153 ReadOnly NoAccess, ReadOnly, ReadWriteCopy 00154 ReadWriteCopy NoAccess, ReadOnly, ReadWriteCopy 00155 ReadWrite NoAccess, ReadOnly, ReadWriteCopy, ReadWrite 00156 Execute NoAccess, Execute 00157 ExecuteRead NoAccess, ReadOnly, ReadWriteCopy, Execute, ExecuteRead, 00158 ExecuteWriteCopy 00159 ExecuteWrite NoAccess, ReadOnly, ReadWriteCopy, Execute, ExecuteRead, 00160 ExecuteWriteCopy, ReadWrite, ExecuteWrite 00161 ExecuteWriteCopy NoAccess, ReadOnly, ReadWriteCopy, Execute, ExecuteRead, 00162 ExecuteWriteCopy 00163 00164 Arguments: 00165 00166 OldProtect - Supplies the protection to be compatible with. 00167 00168 NewProtect - Supplies the protection to check out. 00169 00170 00171 Return Value: 00172 00173 Returns TRUE if the protection is compatible, FALSE if not. 00174 00175 Environment: 00176 00177 Kernel Mode. 00178 00179 --*/ 00180 00181 { 00182 ULONG Mask; 00183 ULONG ProtectMask; 00184 00185 try { 00186 Mask = MiMakeProtectionMask (OldProtect) & 0x7; 00187 } except (EXCEPTION_EXECUTE_HANDLER) { 00188 return FALSE; 00189 } 00190 00191 ProtectMask = MmCompatibleProtectionMask[Mask] | PAGE_GUARD | PAGE_NOCACHE; 00192 00193 if ((ProtectMask | NewProtect) != ProtectMask) { 00194 return FALSE; 00195 } 00196 return TRUE; 00197 }

ULONG FASTCALL MiIsPteDecommittedPage IN PMMPTE  PointerPte  ) 
 

Definition at line 42 of file mmsup.c.

References FALSE, MI_PTE_LOOKUP_NEEDED, MM_DECOMMIT, TRUE, and _MMPTE::u.

Referenced by MiCalculatePageCommitment(), MiIsEntireRangeCommitted(), and MiQueryAddressState().

00048 : 00049 00050 This function checks the contents of a PTE to determine if the 00051 PTE is explicitly decommitted. 00052 00053 If the PTE is a prototype PTE and the protection is not in the 00054 prototype PTE, the value FALSE is returned. 00055 00056 Arguments: 00057 00058 PointerPte - Supplies a pointer to the PTE to examine. 00059 00060 Return Value: 00061 00062 TRUE if the PTE is in the explicit decommitted state. 00063 FALSE if the PTE is not in the explicit decommitted state. 00064 00065 Environment: 00066 00067 Kernel mode, APCs disabled, WorkingSetLock held. 00068 00069 --*/ 00070 00071 { 00072 MMPTE PteContents; 00073 00074 PteContents = *PointerPte; 00075 00076 // 00077 // If the protection in the PTE is not decommitted, return false. 00078 // 00079 00080 if (PteContents.u.Soft.Protection != MM_DECOMMIT) { 00081 return FALSE; 00082 } 00083 00084 // 00085 // Check to make sure the protection field is really being interpreted 00086 // correctly. 00087 // 00088 00089 if (PteContents.u.Hard.Valid == 1) { 00090 00091 // 00092 // The PTE is valid and therefore cannot be decommitted. 00093 // 00094 00095 return FALSE; 00096 } 00097 00098 if ((PteContents.u.Soft.Prototype == 1) && 00099 (PteContents.u.Soft.PageFileHigh != MI_PTE_LOOKUP_NEEDED)) { 00100 00101 // 00102 // The PTE's protection is not known as it is in 00103 // prototype PTE format. Return FALSE. 00104 // 00105 00106 return FALSE; 00107 } 00108 00109 // 00110 // It is a decommitted PTE. 00111 // 00112 00113 return TRUE; 00114 }

LOGICAL MiIssuePageExtendRequest IN PMMPAGE_FILE_EXPANSION  PageExtend  ) 
 

Definition at line 4911 of file modwrite.c.

References Executive, FALSE, KeReleaseSemaphore(), KernelMode, KeWaitForSingleObject(), L, _MMDEREFERENCE_SEGMENT_HEADER::ListHead, _MMDEREFERENCE_SEGMENT_HEADER::Lock, MmDereferenceSegmentHeader, MmOneSecond, MmTwentySeconds, NTSTATUS(), NULL, _MMDEREFERENCE_SEGMENT_HEADER::Semaphore, and TRUE.

Referenced by MiChargeCommitment(), and NtCreatePagingFile().

04917 : 04918 04919 Queue a message to the segment dereferencing / pagefile extending 04920 thread to see if the page file can be extended. Extension is done 04921 in the context of a system thread due to mutexes which the current 04922 thread may be holding. 04923 04924 Arguments: 04925 04926 PageExtend - Supplies a pointer to the page file extension request. 04927 04928 Return Value: 04929 04930 TRUE indicates the request completed. FALSE indicates the request timed 04931 out and was removed. 04932 04933 Environment: 04934 04935 Kernel mode. No locks held. APC level or less. 04936 04937 --*/ 04938 04939 { 04940 KIRQL OldIrql; 04941 NTSTATUS status; 04942 PLIST_ENTRY NextEntry; 04943 04944 ExAcquireFastLock (&MmDereferenceSegmentHeader.Lock, &OldIrql); 04945 InsertTailList ( &MmDereferenceSegmentHeader.ListHead, 04946 &PageExtend->DereferenceList); 04947 ExReleaseFastLock (&MmDereferenceSegmentHeader.Lock, OldIrql); 04948 04949 KeReleaseSemaphore (&MmDereferenceSegmentHeader.Semaphore, 04950 0L, 04951 1L, 04952 TRUE); 04953 04954 // 04955 // Wait for the thread to extend the paging file. 04956 // 04957 04958 status = KeWaitForSingleObject (&PageExtend->Event, 04959 Executive, 04960 KernelMode, 04961 FALSE, 04962 (PageExtend->RequestedExpansionSize < 10) ? 04963 &MmOneSecond : &MmTwentySeconds); 04964 04965 if (status == STATUS_TIMEOUT) { 04966 04967 // 04968 // The wait has timed out, if this request has not 04969 // been processed, remove it from the list and check 04970 // to see if we should allow this request to succeed. 04971 // This prevents a deadlock between the file system 04972 // trying to allocate memory in the FSP and the 04973 // segment dereferencing thread trying to close a 04974 // file object, and waiting in the file system. 04975 // 04976 04977 KdPrint(("MiIssuePageExtendRequest: wait timed out, page-extend= %lx, quota = %lx\n", 04978 PageExtend, PageExtend->RequestedExpansionSize)); 04979 04980 ExAcquireFastLock (&MmDereferenceSegmentHeader.Lock, &OldIrql); 04981 04982 NextEntry = MmDereferenceSegmentHeader.ListHead.Flink; 04983 04984 while (NextEntry != &MmDereferenceSegmentHeader.ListHead) { 04985 04986 // 04987 // Check to see if this is the entry we are waiting for. 04988 // 04989 04990 if (NextEntry == &PageExtend->DereferenceList) { 04991 04992 // 04993 // Remove this entry. 04994 // 04995 04996 RemoveEntryList (&PageExtend->DereferenceList); 04997 ExReleaseFastLock (&MmDereferenceSegmentHeader.Lock, OldIrql); 04998 return FALSE; 04999 } 05000 NextEntry = NextEntry->Flink; 05001 } 05002 05003 ExReleaseFastLock (&MmDereferenceSegmentHeader.Lock, OldIrql); 05004 05005 // 05006 // Entry is being processed, wait for completion. 05007 // 05008 05009 KdPrint (("MiIssuePageExtendRequest: rewaiting...\n")); 05010 05011 KeWaitForSingleObject (&PageExtend->Event, 05012 Executive, 05013 KernelMode, 05014 FALSE, 05015 NULL); 05016 } 05017 05018 return TRUE; 05019 }

VOID MiIssuePageExtendRequestNoWait IN PFN_NUMBER  SizeInPages  ) 
 

Definition at line 5023 of file modwrite.c.

References ASSERT, _MMPAGE_FILE_EXPANSION::DereferenceList, DISPATCH_LEVEL, FALSE, _MMPAGE_FILE_EXPANSION::InProgress, KeReleaseSemaphore(), L, _MMDEREFERENCE_SEGMENT_HEADER::ListHead, _MMDEREFERENCE_SEGMENT_HEADER::Lock, MmAttemptForCantExtend, MmChargeCommitmentLock, MmDereferenceSegmentHeader, NTSTATUS(), ONEMB_IN_PAGES, _MMPAGE_FILE_EXPANSION::RequestedExpansionSize, _MMDEREFERENCE_SEGMENT_HEADER::Semaphore, and TRUE.

Referenced by MiAllocatePoolPages(), and MmResourcesAvailable().

05029 : 05030 05031 Queue a message to the segment dereferencing / pagefile extending 05032 thread to see if the page file can be extended. Extension is done 05033 in the context of a system thread due to mutexes which the current 05034 thread may be holding. 05035 05036 Arguments: 05037 05038 SizeInPages - Supplies the size in pages to increase the page file(s) by. 05039 This is rounded up to a 1MB multiple by this routine. 05040 05041 Return Value: 05042 05043 TRUE indicates the request completed. FALSE indicates the request timed 05044 out and was removed. 05045 05046 Environment: 05047 05048 Kernel mode. No locks held. APC level or less. 05049 05050 Note this routine must be very careful to not use any paged 05051 pool as the only reason it is being called is because pool is depleted. 05052 05053 --*/ 05054 05055 { 05056 KIRQL OldIrql; 05057 NTSTATUS status; 05058 PLIST_ENTRY NextEntry; 05059 05060 ASSERT (KeGetCurrentIrql() < DISPATCH_LEVEL); 05061 05062 ExAcquireFastLock (&MmChargeCommitmentLock, &OldIrql); 05063 05064 if (MmAttemptForCantExtend.InProgress != FALSE) { 05065 05066 // 05067 // An expansion request is already in progress, assume 05068 // it will help enough (another can always be issued later) and 05069 // that it will succeed. 05070 // 05071 05072 ExReleaseFastLock (&MmChargeCommitmentLock, OldIrql); 05073 return; 05074 } 05075 05076 MmAttemptForCantExtend.InProgress = TRUE; 05077 ExReleaseFastLock (&MmChargeCommitmentLock, OldIrql); 05078 05079 SizeInPages = (SizeInPages + ONEMB_IN_PAGES - 1) & ~(ONEMB_IN_PAGES - 1); 05080 05081 MmAttemptForCantExtend.RequestedExpansionSize = SizeInPages; 05082 05083 ExAcquireFastLock (&MmDereferenceSegmentHeader.Lock, &OldIrql); 05084 05085 InsertTailList ( &MmDereferenceSegmentHeader.ListHead, 05086 &MmAttemptForCantExtend.DereferenceList); 05087 05088 ExReleaseFastLock (&MmDereferenceSegmentHeader.Lock, OldIrql); 05089 05090 KeReleaseSemaphore (&MmDereferenceSegmentHeader.Semaphore, 05091 0L, 05092 1L, 05093 FALSE); 05094 05095 return; 05096 } }

PMMVAD FASTCALL MiLocateAddress IN PVOID  Vad  ) 
 

Definition at line 380 of file vadtree.c.

References MI_VA_TO_VPN, MiLocateAddressInTree(), NULL, PsGetCurrentProcess, _EPROCESS::VadHint, and _EPROCESS::VadRoot.

Referenced by MiCheckVirtualAddress(), MiUnmapLockedPagesInUserSpace(), MmDeleteTeb(), MmFlushVirtualMemory(), MmMapUserAddressesToPage(), MmSecureVirtualMemory(), MmSetBankedSection(), MmUnmapViewOfSection(), MmUnsecureVirtualMemory(), NtAreMappedFilesTheSame(), NtFreeVirtualMemory(), NtLockVirtualMemory(), and NtUnlockVirtualMemory().

00386 : 00387 00388 The function locates the virtual address descriptor which describes 00389 a given address. 00390 00391 Arguments: 00392 00393 VirtualAddress - Supplies the virtual address to locate a descriptor 00394 for. 00395 00396 Return Value: 00397 00398 Returns a pointer to the virtual address descriptor which contains 00399 the supplied virtual address or NULL if none was located. 00400 00401 --*/ 00402 00403 { 00404 PMMVAD FoundVad; 00405 PEPROCESS CurrentProcess; 00406 ULONG_PTR Vpn; 00407 00408 CurrentProcess = PsGetCurrentProcess(); 00409 00410 if (CurrentProcess->VadHint == NULL) { 00411 return NULL; 00412 } 00413 00414 Vpn = MI_VA_TO_VPN (VirtualAddress); 00415 if ((Vpn >= ((PMMADDRESS_NODE)CurrentProcess->VadHint)->StartingVpn) && 00416 (Vpn <= ((PMMADDRESS_NODE)CurrentProcess->VadHint)->EndingVpn)) { 00417 00418 return (PMMVAD)CurrentProcess->VadHint; 00419 } 00420 00421 FoundVad = (PMMVAD)MiLocateAddressInTree ( Vpn, 00422 (PMMADDRESS_NODE *)&(CurrentProcess->VadRoot)); 00423 00424 if (FoundVad != NULL) { 00425 CurrentProcess->VadHint = (PVOID)FoundVad; 00426 } 00427 return FoundVad; 00428 }

PMMADDRESS_NODE FASTCALL MiLocateAddressInTree IN ULONG_PTR  Vpn,
IN PMMADDRESS_NODE Root
 

Definition at line 1001 of file addrsup.c.

References _MMADDRESS_NODE::EndingVpn, _MMADDRESS_NODE::LeftChild, MiReorderTree(), NULL, _MMADDRESS_NODE::RightChild, and _MMADDRESS_NODE::StartingVpn.

Referenced by MiLocateAddress().

01008 : 01009 01010 The function locates the virtual address descriptor which describes 01011 a given address. 01012 01013 Arguments: 01014 01015 Vpn - Supplies the virtual page number to locate a descriptor 01016 for. 01017 01018 Return Value: 01019 01020 Returns a pointer to the virtual address descriptor which contains 01021 the supplied virtual address or NULL if none was located. 01022 01023 --*/ 01024 01025 { 01026 01027 PMMADDRESS_NODE Parent; 01028 ULONG Level = 0; 01029 01030 Parent = *Root; 01031 01032 for (;;) { 01033 01034 if (Parent == (PMMADDRESS_NODE)NULL) { 01035 return (PMMADDRESS_NODE)NULL; 01036 } 01037 01038 if (Level == 20) { 01039 01040 // 01041 // There are 20 nodes above this point, reorder the 01042 // tree with this node as the root. 01043 // 01044 01045 MiReorderTree(Parent, Root); 01046 } 01047 01048 if (Vpn < Parent->StartingVpn) { 01049 Parent = Parent->LeftChild; 01050 Level += 1; 01051 01052 } else if (Vpn > Parent->EndingVpn) { 01053 Parent = Parent->RightChild; 01054 Level += 1; 01055 01056 } else { 01057 01058 // 01059 // The address is within the start and end range. 01060 // 01061 01062 return Parent; 01063 } 01064 } 01065 }

WSLE_NUMBER MiLocateAndReserveWsle IN PMMSUPPORT  WsInfo  ) 
 

Definition at line 117 of file wslist.c.

References ASSERT, _MMWSLE::e1, FALSE, _MMWSL::FirstDynamic, _MMWSL::FirstFree, _MMWSL::LastEntry, _MMWSL::LastInitializedWsle, MiAddWorkingSetPage(), MiDoReplacement(), MM_FREE_WSLE_SHIFT, MmInfoCounters, MmPagesAboveWsMinimum, MmSystemCacheWs, MmTransitionSharedPages, MmTransitionSharedPagesPeak, _MMINFO_COUNTERS::PageFaultCount, _MMWSL::Quota, TRUE, _MMWSLE::u1, _MMWSLENTRY::Valid, _MMWSL::Wsle, WSLE_NULL_INDEX, and WSLE_NUMBER.

Referenced by MiAddValidPageToWorkingSet(), MiAddWsleHash(), MiLockCode(), MmAccessFault(), MmCheckCachedPageState(), and MmCopyToCachedPage().

00123 : 00124 00125 This function examines the Working Set List for the current 00126 process and locates an entry to contain a new page. If the 00127 working set is not currently at its quota, the new page is 00128 added without removing a page, if the working set is at its 00129 quota a page is removed from the working set and the new 00130 page added in its place. 00131 00132 Arguments: 00133 00134 None. 00135 00136 Return Value: 00137 00138 Returns the working set index which is now reserved for the 00139 next page to be added. 00140 00141 Environment: 00142 00143 Kernel mode, APCs disabled, working set lock. PFN lock NOT held. 00144 00145 --*/ 00146 00147 { 00148 WSLE_NUMBER WorkingSetIndex; 00149 PMMWSL WorkingSetList; 00150 PMMWSLE Wsle; 00151 ULONG QuotaIncrement; 00152 BOOLEAN MustReplace; 00153 00154 MustReplace = FALSE; 00155 WorkingSetList = WsInfo->VmWorkingSetList; 00156 Wsle = WorkingSetList->Wsle; 00157 00158 // 00159 // Update page fault counts. 00160 // 00161 00162 WsInfo->PageFaultCount += 1; 00163 MmInfoCounters.PageFaultCount += 1; 00164 00165 // 00166 // Determine if a page should be removed from the working set to make 00167 // room for the new page. If so, remove it. In addition, determine 00168 // the size of the QuotaIncrement if the size needs to be boosted. 00169 // 00170 00171 retry_replacement: 00172 00173 QuotaIncrement = MiDoReplacement(WsInfo, MustReplace); 00174 00175 ASSERT (WsInfo->WorkingSetSize <= WorkingSetList->Quota); 00176 WsInfo->WorkingSetSize += 1; 00177 00178 if (WsInfo->WorkingSetSize > WorkingSetList->Quota) { 00179 00180 // 00181 // Increment the quota and check boundary conditions. 00182 // 00183 00184 WorkingSetList->Quota += QuotaIncrement; 00185 00186 WsInfo->LastTrimFaultCount = WsInfo->PageFaultCount; 00187 00188 if (WorkingSetList->Quota > WorkingSetList->LastInitializedWsle) { 00189 00190 // 00191 // Add more pages to the working set list structure. 00192 // 00193 00194 if (MiAddWorkingSetPage (WsInfo) == TRUE) { 00195 ASSERT (WsInfo->WorkingSetSize <= WorkingSetList->Quota); 00196 } 00197 else { 00198 00199 // 00200 // No page was added to the working set list structure. 00201 // We must replace a page within this working set. 00202 // 00203 00204 WsInfo->WorkingSetSize -= 1; 00205 MustReplace = TRUE; 00206 goto retry_replacement; 00207 } 00208 } 00209 } 00210 00211 // 00212 // Get the working set entry from the free list. 00213 // 00214 00215 ASSERT (WorkingSetList->FirstFree <= WorkingSetList->LastInitializedWsle); 00216 00217 ASSERT (WorkingSetList->FirstFree >= WorkingSetList->FirstDynamic); 00218 00219 WorkingSetIndex = WorkingSetList->FirstFree; 00220 WorkingSetList->FirstFree = (WSLE_NUMBER)(Wsle[WorkingSetIndex].u1.Long >> MM_FREE_WSLE_SHIFT); 00221 00222 ASSERT ((WorkingSetList->FirstFree <= WorkingSetList->LastInitializedWsle) || 00223 (WorkingSetList->FirstFree == WSLE_NULL_INDEX)); 00224 00225 if (WsInfo->WorkingSetSize > WsInfo->MinimumWorkingSetSize) { 00226 MmPagesAboveWsMinimum += 1; 00227 } 00228 00229 if (WsInfo->WorkingSetSize > WsInfo->PeakWorkingSetSize) { 00230 WsInfo->PeakWorkingSetSize = WsInfo->WorkingSetSize; 00231 } 00232 00233 if (WsInfo == &MmSystemCacheWs) { 00234 if (WsInfo->WorkingSetSize + MmTransitionSharedPages > MmTransitionSharedPagesPeak) { 00235 MmTransitionSharedPagesPeak = WsInfo->WorkingSetSize + MmTransitionSharedPages; 00236 } 00237 } 00238 00239 if (WorkingSetIndex > WorkingSetList->LastEntry) { 00240 WorkingSetList->LastEntry = WorkingSetIndex; 00241 } 00242 00243 // 00244 // The returned entry is guaranteed to be available at this point. 00245 // 00246 00247 ASSERT (Wsle[WorkingSetIndex].u1.e1.Valid == 0); 00248 00249 return WorkingSetIndex; 00250 }

PSUBSECTION FASTCALL MiLocateSubsection IN PMMVAD  Vad,
IN ULONG_PTR  Vpn
 

Definition at line 783 of file extsect.c.

References ASSERT, _SUBSECTION::NextSubsection, NULL, _SUBSECTION::PtesInSubsection, _SUBSECTION::SubsectionBase, and _CONTROL_AREA::u.

Referenced by MiDeleteVirtualAddresses(), and MmFlushVirtualMemory().

00790 : 00791 00792 This function calculates the address of the subsection 00793 for the corresponding virtual address. 00794 00795 This function only works for mapped files NOT mapped images. 00796 00797 Arguments: 00798 00799 00800 Vad - Supplies a pointer to the virtual address desciptor which 00801 encompasses the virtual address. 00802 00803 Vpn - Supplies the virtual page number to locate a prototype PTE 00804 for. 00805 00806 Return Value: 00807 00808 The corresponding prototype subsection. 00809 00810 --*/ 00811 00812 { 00813 PSUBSECTION Subsection; 00814 PCONTROL_AREA ControlArea; 00815 ULONG PteOffset; 00816 00817 ControlArea = Vad->ControlArea; 00818 00819 if (ControlArea->u.Flags.GlobalOnlyPerSession == 0) { 00820 Subsection = (PSUBSECTION)(ControlArea + 1); 00821 } 00822 else { 00823 Subsection = (PSUBSECTION)((PLARGE_CONTROL_AREA)ControlArea + 1); 00824 } 00825 00826 Subsection = (PSUBSECTION)(ControlArea + 1); 00827 00828 #if 0 00829 if (Subsection->NextSubsection == NULL) { 00830 00831 // 00832 // There is only one subsection, don't look any further. 00833 // 00834 00835 return Subsection; 00836 } 00837 #endif //0 00838 00839 if (ControlArea->u.Flags.Image) { 00840 00841 // 00842 // There is only one subsection, don't look any further. 00843 // 00844 00845 return Subsection; 00846 } 00847 00848 // 00849 // Locate the subsection which contains the First Prototype PTE 00850 // for this VAD. 00851 // 00852 00853 while ((Vad->FirstPrototypePte < Subsection->SubsectionBase) || 00854 (Vad->FirstPrototypePte >= 00855 &Subsection->SubsectionBase[Subsection->PtesInSubsection])) { 00856 00857 // 00858 // Get the next subsection. 00859 // 00860 00861 Subsection = Subsection->NextSubsection; 00862 if (Subsection == NULL) { 00863 return NULL; 00864 } 00865 } 00866 00867 // 00868 // How many PTEs beyond this subsection must we go? 00869 // 00870 00871 PteOffset = (ULONG)((Vpn - Vad->StartingVpn) + 00872 (ULONG)(Vad->FirstPrototypePte - Subsection->SubsectionBase)); 00873 00874 ASSERT (PteOffset < 0xF0000000); 00875 00876 // 00877 // Locate the subsection which contains the prototype PTEs. 00878 // 00879 00880 while (PteOffset >= Subsection->PtesInSubsection) { 00881 PteOffset -= Subsection->PtesInSubsection; 00882 Subsection = Subsection->NextSubsection; 00883 if (Subsection == NULL) { 00884 return NULL; 00885 } 00886 } 00887 00888 // 00889 // The PTEs are in this subsection. 00890 // 00891 00892 return Subsection; 00893 } }

WSLE_NUMBER FASTCALL MiLocateWsle IN PVOID  VirtualAddress,
IN PMMWSL  WorkingSetList,
IN WSLE_NUMBER  WsPfnIndex
 

Definition at line 248 of file wstree.c.

References ASSERT, _MMWSLE_HASH::Index, KeBugCheckEx(), _MMWSLE_HASH::Key, MI_GET_WORKING_SET_FROM_PTE, MI_MAXIMUM_PTE_WORKING_SET_INDEX, MI_WSLE_HASH, MiGetPteAddress, PAGE_ALIGN, _MMPTE::u, _MMWSLE::u1, _MMWSLE::VirtualAddress, and WSLE_NUMBER.

Referenced by MiAllocatePoolPages(), MiCloneProcessAddressSpace(), MiCopyOnWrite(), MiDecommitPages(), MiDeleteAddressesInWorkingSet(), MiDeletePte(), MiDeleteSystemPagableVm(), MiGetPageProtection(), MiLockCode(), MiRemoveMappedPtes(), MiRemovePageFromWorkingSet(), MiSessionCommitPageTables(), MiSessionCopyOnWrite(), MiSetProtectionOnSection(), MmUnmapViewInSystemCache(), NtLockVirtualMemory(), and NtUnlockVirtualMemory().

00256 : 00257 00258 This function locates the specified virtual address within the 00259 working set list. 00260 00261 Arguments: 00262 00263 VirtualAddress - Supplies the virtual to locate within the working 00264 set list. 00265 00266 WorkingSetList - Supplies the working set list to search. 00267 00268 WsPfnIndex - Supplies a hint to try before hashing or walking linearly. 00269 00270 Return Value: 00271 00272 Returns the index into the working set list which contains the entry. 00273 00274 Environment: 00275 00276 Kernel mode, APCs disabled, Working Set Mutex held. 00277 00278 --*/ 00279 00280 { 00281 WSLE_NUMBER i; 00282 PMMWSLE Wsle; 00283 ULONG Hash; 00284 PMMWSLE_HASH Table; 00285 ULONG Tries; 00286 WSLE_NUMBER WsPteIndex; 00287 PMMPTE PointerPte; 00288 00289 Wsle = WorkingSetList->Wsle; 00290 00291 VirtualAddress = PAGE_ALIGN(VirtualAddress); 00292 00293 #if defined (_WIN64) 00294 PointerPte = MiGetPteAddress (VirtualAddress); 00295 WsPteIndex = MI_GET_WORKING_SET_FROM_PTE (PointerPte); 00296 if (WsPteIndex != 0) { 00297 while (WsPteIndex <= WorkingSetList->LastInitializedWsle) { 00298 if ((VirtualAddress == PAGE_ALIGN(Wsle[WsPteIndex].u1.VirtualAddress)) && 00299 (Wsle[WsPteIndex].u1.e1.Valid == 1)) { 00300 return WsPteIndex; 00301 } 00302 WsPteIndex += MI_MAXIMUM_PTE_WORKING_SET_INDEX; 00303 } 00304 00305 // 00306 // No working set index for this PTE ! 00307 // 00308 00309 KeBugCheckEx (MEMORY_MANAGEMENT, 00310 0x41283, 00311 (ULONG_PTR)VirtualAddress, 00312 PointerPte->u.Long, 00313 (ULONG_PTR)WorkingSetList); 00314 } 00315 #endif 00316 00317 if (WsPfnIndex <= WorkingSetList->LastInitializedWsle) { 00318 if ((VirtualAddress == PAGE_ALIGN(Wsle[WsPfnIndex].u1.VirtualAddress)) && 00319 (Wsle[WsPfnIndex].u1.e1.Valid == 1)) { 00320 return WsPfnIndex; 00321 } 00322 } 00323 00324 if (WorkingSetList->HashTable) { 00325 Tries = 0; 00326 Table = WorkingSetList->HashTable; 00327 00328 Hash = MI_WSLE_HASH(VirtualAddress, WorkingSetList); 00329 00330 while (Table[Hash].Key != (ULONG_PTR)VirtualAddress) { 00331 Hash += 1; 00332 if (Hash >= WorkingSetList->HashTableSize) { 00333 Hash = 0; 00334 if (Tries != 0) { 00335 KeBugCheckEx (MEMORY_MANAGEMENT, 00336 0x41284, 00337 (ULONG_PTR)VirtualAddress, 00338 WsPfnIndex, 00339 (ULONG_PTR)WorkingSetList); 00340 } 00341 Tries = 1; 00342 } 00343 } 00344 ASSERT (WorkingSetList->Wsle[Table[Hash].Index].u1.e1.Direct == 0); 00345 return Table[Hash].Index; 00346 } 00347 00348 i = 0; 00349 00350 for (; ; ) { 00351 if ((VirtualAddress == PAGE_ALIGN(Wsle[i].u1.VirtualAddress)) && 00352 (Wsle[i].u1.e1.Valid == 1)) { 00353 ASSERT (WorkingSetList->Wsle[i].u1.e1.Direct == 0); 00354 return i; 00355 } 00356 i += 1; 00357 } 00358 }

VOID MiLockCode IN PMMPTE  FirstPte,
IN PMMPTE  LastPte,
IN ULONG  LockType
 

Definition at line 6461 of file iosup.c.

References ActiveAndValid, APC_LEVEL, ASSERT, FALSE, _MMWSL::FirstDynamic, LOCK_PFN, MI_ADD_LOCKED_PAGE_CHARGE, MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE, MI_IS_PHYSICAL_ADDRESS, MI_IS_SESSION_IMAGE_ADDRESS, MI_MAKE_VALID_PTE, MI_PFN_ELEMENT, MI_REMOVE_LOCKED_PAGE_CHARGE, MI_SET_PTE_IN_WORKING_SET, MI_WRITE_VALID_PTE, MI_ZERO_WSINDEX, MiGetPteAddress, MiGetVirtualAddressMappedByPte, MiLocateAndReserveWsle(), MiLocateWsle(), MiMakeSystemAddressValidPfnSystemWs(), MiReleaseWsle(), MiRemoveWsle(), MiSwapWslEntries(), MiUnlinkPageFromList(), MiUpdateWsle(), MM_BUMP_COUNTER, MM_LOCK_BY_REFCOUNT, MM_PFN_LOCK_ASSERT, MmLockedCode, MmPagedPoolEnd, MmPagedPoolStart, MmResidentAvailablePages, MmSessionSpace, MmSpecialPoolEnd, MmSpecialPoolStart, MmSystemCacheWorkingSetList, MmSystemCacheWs, MmTotalSystemDriverPages, _MMPFN::OriginalPte, PMMSUPPORT, PsGetCurrentThread, _MMPFN::PteAddress, TRUE, _MMPTE::u, _MMWSLE::u1, _MMPFN::u1, _MMPFN::u2, _MMPFN::u3, UNLOCK_PFN, _MM_SESSION_SPACE::Vm, _MMSUPPORT::VmWorkingSetList, _MM_SESSION_SPACE::Wsle, WSLE_NUMBER, and ZeroKernelPte.

Referenced by MmLockPagableSectionByHandle(), MmLockPagedPool(), and MmResetDriverPaging().

06469 : 06470 06471 This routine checks to see if the specified pages are resident in 06472 the process's working set and if so the reference count for the 06473 page is incremented. This allows the virtual address to be accessed 06474 without getting a hard page fault (have to go to the disk...) except 06475 for the extremely rare case when the page table page is removed from the 06476 working set and migrates to the disk. 06477 06478 If the virtual address is that of the system wide global "cache", the 06479 virtual address of the "locked" pages is always guaranteed to 06480 be valid. 06481 06482 NOTE: This routine is not to be used for general locking of user 06483 addresses - use MmProbeAndLockPages. This routine is intended for 06484 well behaved system code like the file system caches which allocates 06485 virtual addresses for mapping files AND guarantees that the mapping 06486 will not be modified (deleted or changed) while the pages are locked. 06487 06488 Arguments: 06489 06490 FirstPte - Supplies the base address to begin locking. 06491 06492 LastPte - The last PTE to lock. 06493 06494 LockType - Supplies either MM_LOCK_BY_REFCOUNT or MM_LOCK_NONPAGE. 06495 LOCK_BY_REFCOUNT increments the reference count to keep 06496 the page in memory, LOCK_NONPAGE removes the page from 06497 the working set so it's locked just like nonpaged pool. 06498 06499 Return Value: 06500 06501 None. 06502 06503 Environment: 06504 06505 Kernel mode, System working set mutex and PFN LOCK held. 06506 06507 --*/ 06508 06509 { 06510 PMMPFN Pfn1; 06511 PMMPTE PointerPte; 06512 MMPTE TempPte; 06513 MMPTE PteContents; 06514 WSLE_NUMBER WorkingSetIndex; 06515 WSLE_NUMBER SwapEntry; 06516 PFN_NUMBER PageFrameIndex; 06517 KIRQL OldIrql; 06518 LOGICAL SessionSpace; 06519 PMMWSL WorkingSetList; 06520 PMMSUPPORT Vm; 06521 #if PFN_CONSISTENCY 06522 KIRQL PfnIrql; 06523 #endif 06524 06525 MM_PFN_LOCK_ASSERT(); 06526 06527 SessionSpace = MI_IS_SESSION_IMAGE_ADDRESS (MiGetVirtualAddressMappedByPte(FirstPte)); 06528 06529 if (SessionSpace == TRUE) { 06530 Vm = &MmSessionSpace->Vm; 06531 WorkingSetList = MmSessionSpace->Vm.VmWorkingSetList; 06532 } 06533 06534 // 06535 // Session space is never locked by refcount. 06536 // 06537 06538 ASSERT ((SessionSpace == FALSE) || (LockType != MM_LOCK_BY_REFCOUNT)); 06539 06540 ASSERT (!MI_IS_PHYSICAL_ADDRESS(MiGetVirtualAddressMappedByPte(FirstPte))); 06541 PointerPte = FirstPte; 06542 06543 MmLockedCode += 1 + LastPte - FirstPte; 06544 06545 do { 06546 06547 PteContents = *PointerPte; 06548 ASSERT (PteContents.u.Long != ZeroKernelPte.u.Long); 06549 if (PteContents.u.Hard.Valid == 0) { 06550 06551 if (PteContents.u.Soft.Prototype == 1) { 06552 06553 // 06554 // Page is not in memory and it is a prototype. 06555 // 06556 06557 MiMakeSystemAddressValidPfnSystemWs ( 06558 MiGetVirtualAddressMappedByPte(PointerPte)); 06559 06560 continue; 06561 } 06562 else if (PteContents.u.Soft.Transition == 1) { 06563 06564 PageFrameIndex = MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE (&PteContents); 06565 06566 Pfn1 = MI_PFN_ELEMENT (PageFrameIndex); 06567 if ((Pfn1->u3.e1.ReadInProgress) || 06568 (Pfn1->u3.e1.InPageError)) { 06569 06570 // 06571 // Page read is ongoing, force a collided fault. 06572 // 06573 06574 MiMakeSystemAddressValidPfnSystemWs ( 06575 MiGetVirtualAddressMappedByPte(PointerPte)); 06576 06577 continue; 06578 } 06579 06580 // 06581 // Paged pool is trimmed without regard to sharecounts. 06582 // This means a paged pool PTE can be in transition while 06583 // the page is still marked active. 06584 // 06585 06586 if (Pfn1->u3.e1.PageLocation == ActiveAndValid) { 06587 06588 ASSERT (((Pfn1->PteAddress >= MiGetPteAddress(MmPagedPoolStart)) && 06589 (Pfn1->PteAddress <= MiGetPteAddress(MmPagedPoolEnd))) || 06590 ((Pfn1->PteAddress >= MiGetPteAddress(MmSpecialPoolStart)) && 06591 (Pfn1->PteAddress <= MiGetPteAddress(MmSpecialPoolEnd)))); 06592 06593 // 06594 // Don't increment the valid PTE count for the 06595 // paged pool page. 06596 // 06597 06598 ASSERT (Pfn1->u2.ShareCount != 0); 06599 ASSERT (Pfn1->u3.e2.ReferenceCount != 0); 06600 Pfn1->u2.ShareCount += 1; 06601 } 06602 else { 06603 06604 MiUnlinkPageFromList (Pfn1); 06605 06606 // 06607 // Set the reference count and share counts to 1. Note the 06608 // reference count may be 1 already if a modified page 06609 // write is underway. The systemwide locked page charges 06610 // are correct in either case and nothing needs to be done 06611 // just yet. 06612 // 06613 06614 Pfn1->u3.e2.ReferenceCount += 1; 06615 Pfn1->u2.ShareCount = 1; 06616 } 06617 06618 Pfn1->u3.e1.PageLocation = ActiveAndValid; 06619 06620 MI_MAKE_VALID_PTE (TempPte, 06621 PageFrameIndex, 06622 Pfn1->OriginalPte.u.Soft.Protection, 06623 PointerPte); 06624 06625 MI_WRITE_VALID_PTE (PointerPte, TempPte); 06626 06627 // 06628 // Increment the reference count one for putting it the 06629 // working set list and one for locking it for I/O. 06630 // 06631 06632 if (LockType == MM_LOCK_BY_REFCOUNT) { 06633 06634 // 06635 // Lock the page in the working set by upping the 06636 // reference count. 06637 // 06638 06639 MI_ADD_LOCKED_PAGE_CHARGE (Pfn1, 34); 06640 Pfn1->u3.e2.ReferenceCount += 1; 06641 Pfn1->u1.Event = (PVOID)PsGetCurrentThread(); 06642 06643 UNLOCK_PFN (APC_LEVEL); 06644 WorkingSetIndex = MiLocateAndReserveWsle (&MmSystemCacheWs); 06645 06646 MiUpdateWsle (&WorkingSetIndex, 06647 MiGetVirtualAddressMappedByPte (PointerPte), 06648 MmSystemCacheWorkingSetList, 06649 Pfn1); 06650 06651 MI_SET_PTE_IN_WORKING_SET (PointerPte, WorkingSetIndex); 06652 06653 LOCK_PFN (OldIrql); 06654 06655 } else { 06656 06657 // 06658 // The wsindex field must be zero because the 06659 // page is not in the system (or session) working set. 06660 // 06661 06662 ASSERT (Pfn1->u1.WsIndex == 0); 06663 06664 // 06665 // Adjust available pages as this page is now not in any 06666 // working set, just like a non-paged pool page. On entry 06667 // this page was in transition so it was part of the 06668 // available pages by definition. 06669 // 06670 06671 MmResidentAvailablePages -= 1; 06672 if (Pfn1->u3.e1.PrototypePte == 0) { 06673 MmTotalSystemDriverPages -= 1; 06674 } 06675 MM_BUMP_COUNTER(29, 1); 06676 } 06677 } else { 06678 06679 // 06680 // Page is not in memory. 06681 // 06682 06683 MiMakeSystemAddressValidPfnSystemWs ( 06684 MiGetVirtualAddressMappedByPte(PointerPte)); 06685 06686 continue; 06687 } 06688 06689 } 06690 else { 06691 06692 // 06693 // This address is already in the system (or session) working set. 06694 // 06695 06696 Pfn1 = MI_PFN_ELEMENT (PteContents.u.Hard.PageFrameNumber); 06697 06698 // 06699 // Up the reference count so the page cannot be released. 06700 // 06701 06702 MI_ADD_LOCKED_PAGE_CHARGE (Pfn1, 36); 06703 Pfn1->u3.e2.ReferenceCount += 1; 06704 06705 if (LockType != MM_LOCK_BY_REFCOUNT) { 06706 06707 // 06708 // If the page is in the system working set, remove it. 06709 // The system working set lock MUST be owned to check to 06710 // see if this page is in the working set or not. This 06711 // is because the pager may have just released the PFN lock, 06712 // acquired the system lock and is now trying to add the 06713 // page to the system working set. 06714 // 06715 // If the page is in the SESSION working set, it cannot be 06716 // removed as all these pages are carefully accounted for. 06717 // Instead move it to the locked portion of the working set 06718 // if it is not there already. 06719 // 06720 06721 if (Pfn1->u1.WsIndex != 0) { 06722 06723 UNLOCK_PFN (APC_LEVEL); 06724 06725 if (SessionSpace == TRUE) { 06726 06727 WorkingSetIndex = MiLocateWsle ( 06728 MiGetVirtualAddressMappedByPte(PointerPte), 06729 WorkingSetList, 06730 Pfn1->u1.WsIndex); 06731 06732 if (WorkingSetIndex >= WorkingSetList->FirstDynamic) { 06733 06734 SwapEntry = WorkingSetList->FirstDynamic; 06735 06736 if (WorkingSetIndex != WorkingSetList->FirstDynamic) { 06737 06738 // 06739 // Swap this entry with the one at first 06740 // dynamic. Note that the working set index 06741 // in the PTE is updated here as well. 06742 // 06743 06744 MiSwapWslEntries (WorkingSetIndex, 06745 SwapEntry, 06746 Vm); 06747 } 06748 06749 WorkingSetList->FirstDynamic += 1; 06750 } 06751 else { 06752 SwapEntry = WorkingSetIndex; 06753 } 06754 06755 // 06756 // Indicate that the page is locked. 06757 // 06758 06759 MmSessionSpace->Wsle[SwapEntry].u1.e1.LockedInWs = 1; 06760 } 06761 else { 06762 MiRemoveWsle (Pfn1->u1.WsIndex, MmSystemCacheWorkingSetList); 06763 MiReleaseWsle (Pfn1->u1.WsIndex, &MmSystemCacheWs); 06764 06765 MI_SET_PTE_IN_WORKING_SET (PointerPte, 0); 06766 } 06767 06768 LOCK_PFN (OldIrql); 06769 06770 MI_ZERO_WSINDEX (Pfn1); 06771 06772 // 06773 // Adjust available pages as this page is now not in any 06774 // working set, just like a non-paged pool page. 06775 // 06776 06777 MmResidentAvailablePages -= 1; 06778 MM_BUMP_COUNTER(29, 1); 06779 if (Pfn1->u3.e1.PrototypePte == 0) { 06780 MmTotalSystemDriverPages -= 1; 06781 } 06782 } 06783 ASSERT (Pfn1->u3.e2.ReferenceCount > 1); 06784 MI_REMOVE_LOCKED_PAGE_CHARGE (Pfn1, 37); 06785 Pfn1->u3.e2.ReferenceCount -= 1; 06786 } 06787 } 06788 06789 PointerPte += 1; 06790 } while (PointerPte <= LastPte); 06791 06792 return; 06793 }

ULONG FASTCALL MiLockPagedAddress IN PVOID  VirtualAddress,
IN ULONG  PfnLockHeld
 

Definition at line 1058 of file mmsup.c.

References FALSE, LOCK_PFN2, MI_ADD_LOCKED_PAGE_CHARGE, MI_PFN_ELEMENT, MiGetPteAddress, MiGetVirtualAddressMappedByPte, MiMakeSystemAddressValidPfn(), _MMPTE::u, _MMPFN::u3, and UNLOCK_PFN2.

Referenced by MiCloneProcessAddressSpace().

01065 : 01066 01067 This routine checks to see if the virtual address is valid, and if 01068 not makes it valid. 01069 01070 Arguments: 01071 01072 VirtualAddress - Supplies the virtual address to make valid. 01073 01074 CurrentProcess - Supplies a pointer to the current process. 01075 01076 Return Value: 01077 01078 Returns TRUE if lock released and wait performed, FALSE otherwise. 01079 01080 Environment: 01081 01082 Kernel mode. 01083 01084 --*/ 01085 01086 { 01087 01088 PMMPTE PointerPte; 01089 PMMPFN Pfn1; 01090 KIRQL OldIrql; 01091 ULONG Waited = FALSE; 01092 01093 PointerPte = MiGetPteAddress(VirtualAddress); 01094 01095 // 01096 // The address must be within paged pool. 01097 // 01098 01099 if (PfnLockHeld == FALSE) { 01100 LOCK_PFN2 (OldIrql); 01101 } 01102 01103 if (PointerPte->u.Hard.Valid == 0) { 01104 01105 Waited = MiMakeSystemAddressValidPfn ( 01106 MiGetVirtualAddressMappedByPte(PointerPte)); 01107 01108 } 01109 01110 Pfn1 = MI_PFN_ELEMENT (PointerPte->u.Hard.PageFrameNumber); 01111 MI_ADD_LOCKED_PAGE_CHARGE(Pfn1, 6); 01112 Pfn1->u3.e2.ReferenceCount += 1; 01113 01114 if (PfnLockHeld == FALSE) { 01115 UNLOCK_PFN2 (OldIrql); 01116 } 01117 return Waited; 01118 }

PLDR_DATA_TABLE_ENTRY MiLookupDataTableEntry IN PVOID  AddressWithinSection,
IN ULONG  ResourceHeld
 

Definition at line 6991 of file iosup.c.

References ExAcquireResourceShared, ExReleaseResource, KeEnterCriticalRegion, KeLeaveCriticalRegion, NULL, PAGED_CODE, PsLoadedModuleList, PsLoadedModuleResource, and TRUE.

Referenced by MmAddVerifierThunks(), MmGetSectionRange(), MmLockPagableDataSection(), MmPageEntireDriver(), and MmResetDriverPaging().

06998 : 06999 07000 This functions locates the data table entry that maps the specified address. 07001 07002 Arguments: 07003 07004 AddressWithinSection - Supplies the address of a function contained 07005 within the desired module. 07006 07007 ResourceHeld - Supplies TRUE if the loaded module resource is already held, 07008 FALSE if not. 07009 07010 Return Value: 07011 07012 The address of the loaded module list data table entry that maps the 07013 argument address. 07014 07015 --*/ 07016 07017 { 07018 PLDR_DATA_TABLE_ENTRY DataTableEntry; 07019 PLDR_DATA_TABLE_ENTRY FoundEntry = NULL; 07020 PLIST_ENTRY NextEntry; 07021 07022 PAGED_CODE(); 07023 07024 // 07025 // Search the loaded module list for the data table entry that describes 07026 // the DLL that was just unloaded. It is possible that an entry is not in 07027 // the list if a failure occurred at a point in loading the DLL just before 07028 // the data table entry was generated. 07029 // 07030 07031 if (!ResourceHeld) { 07032 KeEnterCriticalRegion(); 07033 ExAcquireResourceShared (&PsLoadedModuleResource, TRUE); 07034 } 07035 07036 NextEntry = PsLoadedModuleList.Flink; 07037 do { 07038 07039 DataTableEntry = CONTAINING_RECORD(NextEntry, 07040 LDR_DATA_TABLE_ENTRY, 07041 InLoadOrderLinks); 07042 07043 // 07044 // Locate the loaded module that contains this address. 07045 // 07046 07047 if ( AddressWithinSection >= DataTableEntry->DllBase && 07048 AddressWithinSection < (PVOID)((PUCHAR)DataTableEntry->DllBase+DataTableEntry->SizeOfImage) ) { 07049 07050 FoundEntry = DataTableEntry; 07051 break; 07052 } 07053 07054 NextEntry = NextEntry->Flink; 07055 } while (NextEntry != &PsLoadedModuleList); 07056 07057 if (!ResourceHeld) { 07058 ExReleaseResource (&PsLoadedModuleResource); 07059 KeLeaveCriticalRegion(); 07060 } 07061 return FoundEntry; 07062 }

ULONG MiMakePdeExistAndMakeValid IN PMMPTE  PointerPde,
IN PEPROCESS  TargetProcess,
IN ULONG  PfnMutexHeld
 

Definition at line 624 of file mmsup.c.

References APC_LEVEL, ASSERT, FALSE, LOCK_PFN, MiGetPteAddress, MiGetVirtualAddressMappedByPte, MiMakeSystemAddressValid(), TRUE, _MMPTE::u, and UNLOCK_PFN.

Referenced by MiCreatePageTablesForPhysicalRange(), MiDecommitPages(), MiMapLockedPagesInUserSpace(), MiMapViewOfPhysicalSection(), MiProtectVirtualMemory(), MiSetProtectionOnSection(), and NtAllocateVirtualMemory().

00632 : 00633 00634 This routine examines the specified Page Directory Parent Entry to 00635 determine if the page directory page mapped by the PPE exists. If it does, 00636 then it examines the specified Page Directory Entry to determine if 00637 the page table page mapped by the PDE exists. 00638 00639 If the page table page exists and is not currently in memory, the 00640 working set mutex and, if held, the PFN mutex are released and the 00641 page table page is faulted into the working set. The mutexes are 00642 reacquired. 00643 00644 If the PDE exists, the function returns true. 00645 00646 If the PDE does not exist, a zero filled PTE is created and it 00647 too is brought into the working set. In this case the return 00648 value is FALSE. 00649 00650 Arguments: 00651 00652 PointerPde - Supplies a pointer to the PDE to examine and bring 00653 into the working set. 00654 00655 TargetProcess - Supplies a pointer to the current process. 00656 00657 PfnMutexHeld - Supplies the value TRUE if the PFN mutex is held, FALSE 00658 otherwise. 00659 00660 Return Value: 00661 00662 TRUE if the PDE exists, FALSE if the PDE was created. 00663 00664 Environment: 00665 00666 Kernel mode, APCs disabled, WorkingSetLock held. 00667 00668 --*/ 00669 00670 { 00671 PMMPTE PointerPte; 00672 PMMPTE PointerPpe; 00673 KIRQL OldIrql; 00674 ULONG ReturnValue; 00675 00676 PointerPpe = MiGetPteAddress (PointerPde); 00677 00678 if (PointerPpe->u.Hard.Valid == 1 && PointerPde->u.Hard.Valid == 1) { 00679 00680 // 00681 // Already valid. 00682 // 00683 00684 return TRUE; 00685 } 00686 00687 // 00688 // Deal with the page directory page first. 00689 // 00690 00691 if (PointerPpe->u.Long == 0) { 00692 ReturnValue = FALSE; 00693 } else { 00694 ReturnValue = TRUE; 00695 } 00696 00697 // 00698 // Page directory parent entry not valid, make it valid. 00699 // 00700 00701 OldIrql = APC_LEVEL; 00702 00703 do { 00704 00705 if (PfnMutexHeld) { 00706 UNLOCK_PFN (OldIrql); 00707 } 00708 00709 // 00710 // Fault it in. 00711 // 00712 00713 MiMakeSystemAddressValid (PointerPde, TargetProcess); 00714 00715 ASSERT (PointerPpe->u.Hard.Valid == 1); 00716 00717 if (PfnMutexHeld) { 00718 LOCK_PFN (OldIrql); 00719 } 00720 00721 // 00722 // Now deal with the page table page. 00723 // 00724 00725 if (ReturnValue == TRUE) { 00726 if (PointerPde->u.Long == 0) { 00727 ReturnValue = FALSE; 00728 } else { 00729 ReturnValue = TRUE; 00730 } 00731 } 00732 00733 // 00734 // Page directory entry not valid, make it valid. 00735 // 00736 00737 OldIrql = APC_LEVEL; 00738 00739 if (PfnMutexHeld) { 00740 UNLOCK_PFN (OldIrql); 00741 } 00742 00743 PointerPte = MiGetVirtualAddressMappedByPte (PointerPde); 00744 00745 // 00746 // Fault it in. 00747 // 00748 00749 MiMakeSystemAddressValid (PointerPte, TargetProcess); 00750 00751 ASSERT (PointerPde->u.Hard.Valid == 1); 00752 00753 if (PfnMutexHeld) { 00754 LOCK_PFN (OldIrql); 00755 } 00756 00757 } while (PointerPpe->u.Hard.Valid == 0 || PointerPde->u.Hard.Valid == 0); 00758 00759 return ReturnValue; 00760 }

ULONG FASTCALL MiMakeProtectionMask IN ULONG  Protect  ) 
 

Definition at line 243 of file mmsup.c.

References ExRaiseStatus(), MM_GUARD_PAGE, MM_NOACCESS, MM_NOCACHE, MmUserProtectionToMask1, and MmUserProtectionToMask2.

Referenced by MiIsProtectionCompatible(), MiProtectSpecialPool(), MiProtectVirtualMemory(), MiSetProtectionOnSection(), MmCreateSection(), MmMapViewOfSection(), MmSetPageProtection(), NtAllocateVirtualMemory(), NtMapViewOfSection(), and NtProtectVirtualMemory().

00249 : 00250 00251 This function takes a user supplied protection and converts it 00252 into a 5-bit protection code for the PTE. 00253 00254 Arguments: 00255 00256 Protect - Supplies the protection. 00257 00258 00259 Return Value: 00260 00261 Returns the protection code for use in the PTE. 00262 An exception is raised if the user supplied protection is invalid. 00263 00264 Environment: 00265 00266 Kernel Mode. 00267 00268 --*/ 00269 00270 { 00271 ULONG Field1; 00272 ULONG Field2; 00273 ULONG ProtectCode; 00274 00275 if (Protect >= (PAGE_NOCACHE * 2)) { 00276 ExRaiseStatus (STATUS_INVALID_PAGE_PROTECTION); 00277 } 00278 00279 Field1 = Protect & 0xF; 00280 Field2 = (Protect >> 4) & 0xF; 00281 00282 // 00283 // Make sure at least one field is set. 00284 // 00285 00286 if (Field1 == 0) { 00287 if (Field2 == 0) { 00288 00289 // 00290 // Both fields are zero, raise exception. 00291 // 00292 00293 ExRaiseStatus (STATUS_INVALID_PAGE_PROTECTION); 00294 return 0; 00295 } 00296 ProtectCode = MmUserProtectionToMask2[Field2]; 00297 } else { 00298 if (Field2 != 0) { 00299 // 00300 // Both fields are non-zero, raise exception. 00301 // 00302 00303 ExRaiseStatus (STATUS_INVALID_PAGE_PROTECTION); 00304 return 0; 00305 } 00306 ProtectCode = MmUserProtectionToMask1[Field1]; 00307 } 00308 00309 if (ProtectCode == -1) { 00310 ExRaiseStatus (STATUS_INVALID_PAGE_PROTECTION); 00311 } 00312 00313 if (Protect & PAGE_GUARD) { 00314 if (ProtectCode == MM_NOACCESS) { 00315 00316 // 00317 // Invalid protection, no access and no_cache. 00318 // 00319 00320 ExRaiseStatus (STATUS_INVALID_PAGE_PROTECTION); 00321 } 00322 00323 ProtectCode |= MM_GUARD_PAGE; 00324 } 00325 00326 if (Protect & PAGE_NOCACHE) { 00327 00328 if (ProtectCode == MM_NOACCESS) { 00329 00330 // 00331 // Invalid protection, no access and no cache. 00332 // 00333 00334 ExRaiseStatus (STATUS_INVALID_PAGE_PROTECTION); 00335 } 00336 00337 ProtectCode |= MM_NOCACHE; 00338 } 00339 00340 return ProtectCode; 00341 }

ULONG FASTCALL MiMakeSystemAddressValid IN PVOID  VirtualAddress,
IN PEPROCESS  CurrentProcess
 

Definition at line 764 of file mmsup.c.

References ASSERT, FALSE, KeBugCheckEx(), KernelMode, LOCK_WS_REGARDLESS, MM_PAGED_POOL_START, MmAccessFault(), MmIsAddressValid(), MmPagedPoolEnd, NT_SUCCESS, NTSTATUS(), TRUE, and UNLOCK_WS_REGARDLESS.

Referenced by MiCloneProcessAddressSpace(), MiDoesPdeExistAndMakeValid(), and MiMakePdeExistAndMakeValid().

00771 : 00772 00773 This routine checks to see if the virtual address is valid, and if 00774 not makes it valid. 00775 00776 Arguments: 00777 00778 VirtualAddress - Supplies the virtual address to make valid. 00779 00780 CurrentProcess - Supplies a pointer to the current process. 00781 00782 Return Value: 00783 00784 Returns TRUE if lock released and wait performed, FALSE otherwise. 00785 00786 Environment: 00787 00788 Kernel mode, APCs disabled, WorkingSetLock held. 00789 00790 --*/ 00791 00792 { 00793 NTSTATUS status; 00794 LOGICAL WsHeldSafe; 00795 ULONG Waited; 00796 00797 Waited = FALSE; 00798 00799 ASSERT (VirtualAddress > MM_HIGHEST_USER_ADDRESS); 00800 00801 ASSERT ((VirtualAddress < MM_PAGED_POOL_START) || 00802 (VirtualAddress > MmPagedPoolEnd)); 00803 00804 while (!MmIsAddressValid(VirtualAddress)) { 00805 00806 // 00807 // The virtual address is not present. Release 00808 // the working set mutex and fault it in. 00809 // 00810 // The working set lock may have been acquired safely or unsafely 00811 // by our caller. Handle both cases here and below. 00812 // 00813 00814 UNLOCK_WS_REGARDLESS(CurrentProcess, WsHeldSafe); 00815 00816 status = MmAccessFault (FALSE, VirtualAddress, KernelMode, (PVOID)0); 00817 if (!NT_SUCCESS(status)) { 00818 KdPrint (("MM:page fault status %lx\n",status)); 00819 KeBugCheckEx (KERNEL_DATA_INPAGE_ERROR, 00820 1, 00821 (ULONG)status, 00822 (ULONG_PTR)CurrentProcess, 00823 (ULONG_PTR)VirtualAddress); 00824 } 00825 00826 LOCK_WS_REGARDLESS(CurrentProcess, WsHeldSafe); 00827 00828 Waited = TRUE; 00829 } 00830 00831 return Waited; 00832 }

ULONG FASTCALL MiMakeSystemAddressValidPfn IN PVOID  VirtualAddress  ) 
 

Definition at line 996 of file mmsup.c.

References APC_LEVEL, ASSERT, FALSE, KeBugCheckEx(), KernelMode, LOCK_PFN, MmAccessFault(), MmIsAddressValid(), NT_SUCCESS, NTSTATUS(), TRUE, and UNLOCK_PFN.

Referenced by MiCheckProtoPtePageState(), MiCleanSection(), MiFlushSectionInternal(), MiLockPagedAddress(), MiSegmentDelete(), MiSetSystemCodeProtection(), MiUpdateImageHeaderPage(), MmAccessFault(), MmCheckCachedPageState(), MmCopyToCachedPage(), and MmPurgeSection().

01002 : 01003 01004 This routine checks to see if the virtual address is valid, and if 01005 not makes it valid. 01006 01007 Arguments: 01008 01009 VirtualAddress - Supplies the virtual address to make valid. 01010 01011 Return Value: 01012 01013 Returns TRUE if lock released and wait performed, FALSE otherwise. 01014 01015 Environment: 01016 01017 Kernel mode, APCs disabled, only the PFN Lock held. 01018 01019 --*/ 01020 01021 { 01022 NTSTATUS status; 01023 KIRQL OldIrql = APC_LEVEL; 01024 01025 ULONG Waited = FALSE; 01026 01027 ASSERT (VirtualAddress > MM_HIGHEST_USER_ADDRESS); 01028 01029 while (!MmIsAddressValid(VirtualAddress)) { 01030 01031 // 01032 // The virtual address is not present. Release 01033 // the working set mutex and fault it in. 01034 // 01035 01036 UNLOCK_PFN (OldIrql); 01037 01038 status = MmAccessFault (FALSE, VirtualAddress, KernelMode, (PVOID)0); 01039 if (!NT_SUCCESS(status)) { 01040 KdPrint (("MM:page fault status %lx\n",status)); 01041 KeBugCheckEx (KERNEL_DATA_INPAGE_ERROR, 01042 3, 01043 (ULONG)status, 01044 (ULONG_PTR)VirtualAddress, 01045 0); 01046 } 01047 01048 LOCK_PFN (OldIrql); 01049 01050 Waited = TRUE; 01051 } 01052 01053 return Waited; 01054 }

ULONG FASTCALL MiMakeSystemAddressValidPfnSystemWs IN PVOID  VirtualAddress  ) 
 

Definition at line 916 of file mmsup.c.

References APC_LEVEL, ASSERT, FALSE, KeBugCheckEx(), KernelMode, LOCK_PFN, LOCK_SESSION_SPACE_WS, LOCK_SYSTEM_WS, MI_IS_SESSION_IMAGE_ADDRESS, MmAccessFault(), MmIsAddressValid(), NT_SUCCESS, NTSTATUS(), TRUE, UNLOCK_PFN, UNLOCK_SESSION_SPACE_WS, and UNLOCK_SYSTEM_WS.

Referenced by MiLockCode(), and MmLockPagableSectionByHandle().

00922 : 00923 00924 This routine checks to see if the virtual address is valid, and if 00925 not makes it valid. 00926 00927 Arguments: 00928 00929 VirtualAddress - Supplies the virtual address to make valid. 00930 00931 Return Value: 00932 00933 Returns TRUE if lock released and wait performed, FALSE otherwise. 00934 00935 Environment: 00936 00937 Kernel mode, APCs disabled, PFN lock held, system working set lock held. 00938 00939 --*/ 00940 00941 { 00942 NTSTATUS status; 00943 ULONG Waited; 00944 KIRQL OldIrql; 00945 KIRQL OldIrqlWs; 00946 LOGICAL SessionSpace; 00947 00948 Waited = FALSE; 00949 OldIrql = APC_LEVEL; 00950 OldIrqlWs = APC_LEVEL; 00951 00952 ASSERT (VirtualAddress > MM_HIGHEST_USER_ADDRESS); 00953 00954 SessionSpace = MI_IS_SESSION_IMAGE_ADDRESS (VirtualAddress); 00955 00956 while (!MmIsAddressValid(VirtualAddress)) { 00957 00958 // 00959 // The virtual address is not present. Release 00960 // the working set mutex and fault it in. 00961 // 00962 00963 UNLOCK_PFN (OldIrql); 00964 00965 if (SessionSpace == TRUE) { 00966 UNLOCK_SESSION_SPACE_WS (OldIrqlWs); 00967 } 00968 else { 00969 UNLOCK_SYSTEM_WS (OldIrqlWs); 00970 } 00971 00972 status = MmAccessFault (FALSE, VirtualAddress, KernelMode, (PVOID)0); 00973 if (!NT_SUCCESS(status)) { 00974 KdPrint (("MM:page fault status %lx\n",status)); 00975 KeBugCheckEx (KERNEL_DATA_INPAGE_ERROR, 00976 2, 00977 (ULONG)status, 00978 (ULONG_PTR)0, 00979 (ULONG_PTR)VirtualAddress); 00980 } 00981 if (SessionSpace == TRUE) { 00982 LOCK_SESSION_SPACE_WS (OldIrqlWs); 00983 } 00984 else { 00985 LOCK_SYSTEM_WS (OldIrqlWs); 00986 } 00987 LOCK_PFN (OldIrql); 00988 00989 Waited = TRUE; 00990 } 00991 return Waited; 00992 }

ULONG FASTCALL MiMakeSystemAddressValidPfnWs IN PVOID  VirtualAddress,
IN PEPROCESS CurrentProcess  OPTIONAL
 

Definition at line 837 of file mmsup.c.

References APC_LEVEL, ASSERT, FALSE, KeBugCheckEx(), KernelMode, LOCK_PFN, LOCK_WS_REGARDLESS, MmAccessFault(), MmIsAddressValid(), NT_SUCCESS, NTSTATUS(), NULL, TRUE, UNLOCK_PFN, and UNLOCK_WS_REGARDLESS.

Referenced by MiCaptureSystemPte(), MiDecrementCloneBlockReference(), MiGetSubsectionAndProtoFromPte(), MiPurgeImageSection(), MiResetVirtualMemory(), and MiUpCloneProtoRefCount().

00844 : 00845 00846 This routine checks to see if the virtual address is valid, and if 00847 not makes it valid. 00848 00849 Arguments: 00850 00851 VirtualAddress - Supplies the virtual address to make valid. 00852 00853 CurrentProcess - Supplies a pointer to the current process, if the 00854 working set lock is not held, this value is NULL. 00855 00856 Return Value: 00857 00858 Returns TRUE if lock released and wait performed, FALSE otherwise. 00859 00860 Environment: 00861 00862 Kernel mode, APCs disabled, PFN lock held, working set lock held 00863 if CurrentProcess != NULL. 00864 00865 --*/ 00866 00867 { 00868 NTSTATUS status; 00869 ULONG Waited; 00870 KIRQL OldIrql; 00871 LOGICAL WsHeldSafe; 00872 00873 Waited = FALSE; 00874 OldIrql = APC_LEVEL; 00875 00876 ASSERT (VirtualAddress > MM_HIGHEST_USER_ADDRESS); 00877 00878 while (!MmIsAddressValid(VirtualAddress)) { 00879 00880 // 00881 // The virtual address is not present. Release 00882 // the working set mutex and fault it in. 00883 // 00884 00885 UNLOCK_PFN (OldIrql); 00886 if (CurrentProcess != NULL) { 00887 00888 // 00889 // The working set lock may have been acquired safely or unsafely 00890 // by our caller. Handle both cases here and below. 00891 // 00892 00893 UNLOCK_WS_REGARDLESS(CurrentProcess, WsHeldSafe); 00894 } 00895 status = MmAccessFault (FALSE, VirtualAddress, KernelMode, (PVOID)0); 00896 if (!NT_SUCCESS(status)) { 00897 KdPrint (("MM:page fault status %lx\n",status)); 00898 KeBugCheckEx (KERNEL_DATA_INPAGE_ERROR, 00899 2, 00900 (ULONG)status, 00901 (ULONG_PTR)CurrentProcess, 00902 (ULONG_PTR)VirtualAddress); 00903 } 00904 if (CurrentProcess != NULL) { 00905 LOCK_WS_REGARDLESS(CurrentProcess, WsHeldSafe); 00906 } 00907 LOCK_PFN (OldIrql); 00908 00909 Waited = TRUE; 00910 } 00911 return Waited; 00912 }

PVOID MiMapImageHeaderInHyperSpace IN PFN_NUMBER  PageFrameIndex  ) 
 

Definition at line 80 of file axp64/hypermap.c.

References ASSERT, DbgPrint, Executive, FALSE, IMAGE_MAPPING_PTE, KeBugCheck(), KeEnterCriticalRegion, KeLeaveCriticalRegion, KernelMode, KeWaitForSingleObject(), LOCK_PFN, MiGetPteAddress, MiGetVirtualAddressMappedByPte, MmImageMappingPteEvent, MmWorkingSetList, NULL, _MMPTE::u, UNLOCK_PFN, UNLOCK_PFN_AND_THEN_WAIT, ValidPtePte, and _MMWSL::WaitingForImageMapping.

00086 : 00087 00088 The physical address of the specified page is returned. 00089 00090 Arguments: 00091 00092 PageFrameIndex - Supplies the physical page number to map. 00093 00094 Return Value: 00095 00096 Returns the virtual address where the specified physical page was 00097 mapped. 00098 00099 Environment: 00100 00101 Kernel mode. 00102 00103 --*/ 00104 00105 { 00106 MMPTE TempPte; 00107 PMMPTE PointerPte; 00108 KIRQL OldIrql; 00109 00110 #if DBG 00111 00112 if (PageFrameIndex == 0) { 00113 DbgPrint("attempt to map physical page 0 in hyper space\n"); 00114 KeBugCheck (MEMORY_MANAGEMENT); 00115 } 00116 00117 #endif //DBG 00118 00119 PointerPte = MiGetPteAddress (IMAGE_MAPPING_PTE); 00120 00121 LOCK_PFN(OldIrql); 00122 00123 while (PointerPte->u.Long != 0) { 00124 00125 // 00126 // If there is no event specified, set one up. 00127 // 00128 00129 if (MmWorkingSetList->WaitingForImageMapping == (PKEVENT)NULL) { 00130 00131 // 00132 // Set the global event into the field and wait for it. 00133 // 00134 00135 MmWorkingSetList->WaitingForImageMapping = &MmImageMappingPteEvent; 00136 } 00137 00138 // 00139 // Release the PFN lock and wait on the event in an 00140 // atomic operation. 00141 // 00142 00143 KeEnterCriticalRegion(); 00144 00145 UNLOCK_PFN_AND_THEN_WAIT(OldIrql); 00146 00147 KeWaitForSingleObject(MmWorkingSetList->WaitingForImageMapping, 00148 Executive, 00149 KernelMode, 00150 FALSE, 00151 (PLARGE_INTEGER)NULL); 00152 00153 KeLeaveCriticalRegion(); 00154 00155 LOCK_PFN (OldIrql); 00156 } 00157 00158 ASSERT (PointerPte->u.Long == 0); 00159 00160 TempPte = ValidPtePte; 00161 TempPte.u.Hard.PageFrameNumber = PageFrameIndex; 00162 00163 *PointerPte = TempPte; 00164 00165 UNLOCK_PFN (OldIrql); 00166 00167 return (PVOID)MiGetVirtualAddressMappedByPte (PointerPte); 00168 }

PVOID MiMapPageInHyperSpace IN PFN_NUMBER  PageFrameIndex,
OUT PKIRQL  OldIrql
 

PVOID MiMapPageToZeroInHyperSpace IN PFN_NUMBER  PageFrameIndex  ) 
 

Definition at line 241 of file axp64/hypermap.c.

References ASSERT, and MM_PFN_LOCK_ASSERT.

00247 : 00248 00249 This procedure maps the specified page frame into the 43-bit super 00250 page address range. 00251 00252 Arguments: 00253 00254 PageFrameIndex - Supplies the page frame to map. 00255 00256 Return Value: 00257 00258 The 43-bit super address of the respective page is returned as the 00259 function value. 00260 00261 --*/ 00262 00263 { 00264 00265 // 00266 // On AXP64 systems all pages can be mapped physically using the 43-bit 00267 // super page address range. 00268 // 00269 00270 ASSERT(PageFrameIndex != 0); 00271 00272 MM_PFN_LOCK_ASSERT(); 00273 00274 return KSEG_ADDRESS(PageFrameIndex); 00275 } }

VOID MiMappedPageWriter IN PVOID  StartContext  ) 
 

Definition at line 4239 of file modwrite.c.

References APC_LEVEL, _MMMOD_WRITER_MDL_ENTRY::ControlArea, FALSE, _MMMOD_WRITER_MDL_ENTRY::File, _MMMOD_WRITER_MDL_ENTRY::FileResource, FsRtlAcquireFileForModWrite(), FsRtlSetTopLevelIrpForModWriter, IoAsynchronousPageWrite(), _MMMOD_WRITER_MDL_ENTRY::IoStatus, IoSynchronousPageWrite(), KeClearEvent, KeInitializeEvent, KeLowerIrql(), KeRaiseIrql(), KernelMode, KeSetPriorityThread(), KeWaitForSingleObject(), LOCK_PFN, _MMMOD_WRITER_MDL_ENTRY::Mdl, MiWriteComplete(), MmMappedPageWriterEvent, MmMappedPageWriterList, NT_ERROR, NTSTATUS(), NULL, PsGetCurrentThread, Status, TRUE, _CONTROL_AREA::u, _MMMOD_WRITER_MDL_ENTRY::u, UNLOCK_PFN, VOID(), _MMMOD_WRITER_MDL_ENTRY::WriteOffset, and WrVirtualMemory.

Referenced by MiModifiedPageWriter().

04245 : 04246 04247 Implements the NT secondary modified page writer thread. 04248 Requests for writes to mapped files are sent to this thread. 04249 This is required as the writing of mapped file pages could cause 04250 page faults resulting in requests for free pages. But there 04251 could be no free pages - hence a dead lock. Rather than deadlock 04252 the whole system waiting on the modified page writer, creating 04253 a secondary thread allows that thread to block without affecting 04254 on going page file writes. 04255 04256 Arguments: 04257 04258 StartContext - not used. 04259 04260 Return Value: 04261 04262 None. 04263 04264 Environment: 04265 04266 Kernel mode. 04267 04268 --*/ 04269 04270 { 04271 PMMMOD_WRITER_MDL_ENTRY ModWriterEntry; 04272 KIRQL OldIrql = 0; 04273 NTSTATUS Status; 04274 KEVENT TempEvent; 04275 04276 UNREFERENCED_PARAMETER (StartContext); 04277 04278 // 04279 // Make this a real time thread. 04280 // 04281 04282 (VOID) KeSetPriorityThread (&PsGetCurrentThread()->Tcb, 04283 LOW_REALTIME_PRIORITY + 1); 04284 04285 // 04286 // Let the file system know that we are getting resources. 04287 // 04288 04289 FsRtlSetTopLevelIrpForModWriter(); 04290 04291 KeInitializeEvent (&TempEvent, NotificationEvent, FALSE); 04292 04293 while (TRUE) { 04294 KeWaitForSingleObject (&MmMappedPageWriterEvent, 04295 WrVirtualMemory, 04296 KernelMode, 04297 FALSE, 04298 (PLARGE_INTEGER)NULL); 04299 04300 LOCK_PFN (OldIrql); 04301 if (IsListEmpty (&MmMappedPageWriterList)) { 04302 KeClearEvent (&MmMappedPageWriterEvent); 04303 UNLOCK_PFN (OldIrql); 04304 } else { 04305 04306 ModWriterEntry = (PMMMOD_WRITER_MDL_ENTRY)RemoveHeadList ( 04307 &MmMappedPageWriterList); 04308 04309 UNLOCK_PFN (OldIrql); 04310 04311 04312 if (ModWriterEntry->ControlArea->u.Flags.FailAllIo == 1) { 04313 Status = STATUS_UNSUCCESSFUL; 04314 04315 } else if (FsRtlAcquireFileForModWrite (ModWriterEntry->File, 04316 &ModWriterEntry->u.LastByte, 04317 &ModWriterEntry->FileResource)) { 04318 04319 // 04320 // Issue the write request. 04321 // 04322 04323 Status = IoAsynchronousPageWrite ( 04324 ModWriterEntry->File, 04325 &ModWriterEntry->Mdl, 04326 &ModWriterEntry->WriteOffset, 04327 MiWriteComplete, 04328 (PVOID)ModWriterEntry, 04329 &ModWriterEntry->u.IoStatus, 04330 &ModWriterEntry->Irp ); 04331 } else { 04332 04333 // 04334 // Unable to get the file system resources, set error status 04335 // to lock conflict (ignored by MiWriteComplete) so the APC 04336 // routine is explicitly called. 04337 // 04338 04339 Status = STATUS_FILE_LOCK_CONFLICT; 04340 } 04341 04342 if (NT_ERROR(Status)) { 04343 04344 // 04345 // An error has occurred, disable APC's and 04346 // call the write completion routine. 04347 // 04348 04349 ModWriterEntry->u.IoStatus.Status = Status; 04350 ModWriterEntry->u.IoStatus.Information = 0; 04351 KeRaiseIrql (APC_LEVEL, &OldIrql); 04352 MiWriteComplete ((PVOID)ModWriterEntry, 04353 &ModWriterEntry->u.IoStatus, 04354 0 ); 04355 KeLowerIrql (OldIrql); 04356 } 04357 #if 0 04358 //TEMPORARY code to use synchronous I/O here. 04359 04360 // 04361 // Issue the write request. 04362 // 04363 04364 Status = IoSynchronousPageWrite ( 04365 ModWriterEntry->File, 04366 &ModWriterEntry->Mdl, 04367 &ModWriterEntry->WriteOffset, 04368 &TempEvent, 04369 &ModWriterEntry->u.IoStatus ); 04370 04371 if (NT_ERROR(Status)) { 04372 ModWriterEntry->u.IoStatus.Status = Status; 04373 ModWriterEntry->u.IoStatus.Information = 0; 04374 } 04375 04376 if (NT_ERROR(ModWriterEntry->u.IoStatus.Status)) { 04377 KdPrint(("MM MODWRITE: modified page write failed %lx\n", Status)); 04378 } 04379 04380 // 04381 // Call the write completion routine. 04382 // 04383 04384 KeRaiseIrql (APC_LEVEL, &OldIrql); 04385 MiWriteComplete ((PVOID)ModWriterEntry, 04386 &ModWriterEntry->IoStatus, 04387 0 ); 04388 KeLowerIrql (OldIrql); 04389 #endif //0 04390 04391 } 04392 04393 } 04394 }

PVOID MiMapSinglePage IN PVOID VirtualAddress  OPTIONAL,
IN PFN_NUMBER  PageFrameIndex,
IN MEMORY_CACHING_TYPE  CacheType,
IN MM_PAGE_PRIORITY  Priority
 

Definition at line 2395 of file iosup.c.

References ASSERT, FALSE, HighPagePriority, KeFlushEntireTb(), KeFlushSingleTb(), KeInvalidateAllCaches(), MI_DISABLE_CACHING, MI_IS_PHYSICAL_ADDRESS, MI_SET_PTE_WRITE_COMBINE, MI_WRITE_INVALID_PTE, MI_WRITE_VALID_PTE, MiGetPteAddress, MiGetSystemPteAvailability(), MiGetVirtualAddressMappedByPte, MiReserveSystemPtes(), MiSweepCacheMachineDependent(), MiWriteCombiningPtes, MM_COLOR_ALIGNMENT, MmCached, MmHardwareCoherentCached, MmNonCached, MmNonCachedUnordered, MmWriteCombined, NULL, PAGE_SIZE, PAGED_CODE, SystemPteSpace, TRUE, _MMPTE::u, ValidKernelPte, and ZeroPte.

Referenced by MiCloneProcessAddressSpace().

02404 : 02405 02406 This function (re)maps a single system PTE to the specified physical page. 02407 02408 Arguments: 02409 02410 VirtualAddress - Supplies the virtual address to map the page frame at. 02411 NULL indicates a system PTE is needed. Non-NULL supplies 02412 the virtual address returned by an earlier 02413 MiMapSinglePage call. 02414 02415 PageFrameIndex - Supplies the page frame index to map. 02416 02417 CacheType - Supplies the type of cache mapping to use for the MDL. 02418 MmCached indicates "normal" kernel or user mappings. 02419 02420 Priority - Supplies an indication as to how important it is that this 02421 request succeed under low available PTE conditions. 02422 02423 Return Value: 02424 02425 Returns the base address where the page is mapped, or NULL if it the 02426 mapping failed. 02427 02428 Environment: 02429 02430 Kernel mode. APC_LEVEL or below. 02431 02432 --*/ 02433 02434 { 02435 PMMPTE PointerPte; 02436 MMPTE TempPte; 02437 02438 PAGED_CODE (); 02439 02440 if (VirtualAddress == NULL) { 02441 02442 // 02443 // Make sure there are enough PTEs of the requested size. 02444 // 02445 02446 if ((Priority != HighPagePriority) && 02447 (MiGetSystemPteAvailability (1, Priority) == FALSE)) { 02448 return NULL; 02449 } 02450 02451 PointerPte = MiReserveSystemPtes (1, 02452 SystemPteSpace, 02453 MM_COLOR_ALIGNMENT, 02454 0, 02455 0); 02456 02457 if (PointerPte == NULL) { 02458 02459 // 02460 // Not enough system PTES are available. 02461 // 02462 02463 return NULL; 02464 } 02465 02466 ASSERT (PointerPte->u.Hard.Valid == 0); 02467 VirtualAddress = MiGetVirtualAddressMappedByPte (PointerPte); 02468 } 02469 else { 02470 ASSERT (MI_IS_PHYSICAL_ADDRESS (VirtualAddress) == 0); 02471 ASSERT (VirtualAddress >= MM_SYSTEM_RANGE_START); 02472 02473 PointerPte = MiGetPteAddress (VirtualAddress); 02474 ASSERT (PointerPte->u.Hard.Valid == 1); 02475 02476 MI_WRITE_INVALID_PTE (PointerPte, ZeroPte); 02477 02478 KeFlushSingleTb (VirtualAddress, 02479 TRUE, 02480 TRUE, 02481 (PHARDWARE_PTE)PointerPte, 02482 ZeroPte.u.Flush); 02483 } 02484 02485 TempPte = ValidKernelPte; 02486 02487 switch (CacheType) { 02488 02489 case MmNonCached: 02490 MI_DISABLE_CACHING (TempPte); 02491 break; 02492 02493 case MmCached: 02494 break; 02495 02496 case MmWriteCombined: 02497 MI_SET_PTE_WRITE_COMBINE (TempPte); 02498 break; 02499 02500 case MmHardwareCoherentCached: 02501 break; 02502 02503 #if 0 02504 case MmNonCachedUnordered: 02505 break; 02506 #endif 02507 02508 default: 02509 break; 02510 } 02511 02512 #if defined(_IA64_) 02513 if (CacheType != MmCached) { 02514 KeFlushEntireTb(FALSE, TRUE); 02515 } 02516 #endif 02517 02518 TempPte.u.Hard.PageFrameNumber = PageFrameIndex; 02519 02520 MI_WRITE_VALID_PTE (PointerPte, TempPte); 02521 02522 #if defined(i386) 02523 // 02524 // If write combined was specified then flush all caches and TBs. 02525 // 02526 02527 if (CacheType == MmWriteCombined && MiWriteCombiningPtes == TRUE) { 02528 KeFlushEntireTb (FALSE, TRUE); 02529 KeInvalidateAllCaches (TRUE); 02530 } 02531 #endif 02532 02533 #if defined(_IA64_) 02534 if (CacheType != MmCached) { 02535 MiSweepCacheMachineDependent(VirtualAddress, PAGE_SIZE, CacheType); 02536 } 02537 #endif 02538 02539 return VirtualAddress; 02540 }

NTSTATUS MiMapViewOfPhysicalSection IN PCONTROL_AREA  ControlArea,
IN PEPROCESS  Process,
IN PVOID *  CapturedBase,
IN PLARGE_INTEGER  SectionOffset,
IN PSIZE_T  CapturedViewSize,
IN ULONG  ProtectionMask,
IN ULONG_PTR  ZeroBits,
IN ULONG  AllocationType,
IN BOOLEAN  WriteCombined,
OUT PBOOLEAN  ReleasedWsMutex
 

Definition at line 43 of file alpha/physsect.c.

References AggregatePages(), ASSERT, CONSISTENCY_LOCK_PFN, CONSISTENCY_UNLOCK_PFN, _MMVAD::ControlArea, DbgPrint, _MMVAD::EndingVpn, _MI_PHYSICAL_VIEW::EndVa, ExAllocatePoolWithTag, EXCEPTION_EXECUTE_HANDLER, ExFreePool(), ExRaiseStatus(), FALSE, _MMVAD::FirstPrototypePte, KeFlushEntireTb(), KeInvalidateAllCaches(), L, _MMVAD::LastContiguousPte, _MI_PHYSICAL_VIEW::ListEntry, LOCK_AWE, LOCK_PFN, LOCK_PFN2, LOCK_WS_UNSAFE, MaximumAlignment(), MI_64K_ALIGN, MI_CONVERT_PHYSICAL_BUS_TO_PFN, MI_GET_USED_PTES_FROM_HANDLE, MI_GET_USED_PTES_HANDLE, MI_INCREMENT_USED_PTES_BY_HANDLE, MI_IS_CACHING_DISABLED, MI_MAKE_VALID_PTE, MI_PFN_ELEMENT, MI_PHYSICAL_VIEW_KEY, MI_SET_PTE_DIRTY, MI_SET_PTE_WRITE_COMBINE, MI_VA_TO_VPN, MI_WRITE_VALID_PTE, MiCheckForConflictingVad, MiFindEmptyAddressRange(), MiGetPdeAddress, MiGetPpeAddress, MiGetPteAddress, MiGetSubsectionAddressForPte, MiGetVirtualAddressMappedByPte, MiInsertVad(), MiIsPteOnPdeBoundary, MiIsPteOnPpeBoundary, MiMakePdeExistAndMakeValid(), MiMakePpeExistAndMakeValid, MiProtoAddressForPte, MiSweepCacheMachineDependent(), MiWriteCombiningPtes, MM_USER_ADDRESS_RANGE_LIMIT, MM_VA_MAPPED_BY_PDE, MM_VIEW_UNMAP, MmPageSizeInfo, MMPPTE_NAME, MMVAD, MMVADKEY, MmWriteCombined, NonPagedPool, NULL, PAGE_SHIFT, PAGE_SIZE, _SUBSECTION::StartingSector, _MMVAD::StartingVpn, _MI_PHYSICAL_VIEW::StartVa, TRUE, _SUBSECTION::u, _MMPTE::u, _MMVAD::u, _MMPFN::u2, _MMVAD::u2, _MMVAD::u4, UNLOCK_AWE, UNLOCK_PFN, UNLOCK_PFN2, UNLOCK_WS_UNSAFE, _MI_PHYSICAL_VIEW::Vad, X64K, and ZeroPte.

Referenced by MmMapViewOfSection().

00058 : 00059 00060 This routine maps the specified physical section into the 00061 specified process's address space. 00062 00063 Arguments: 00064 00065 see MmMapViewOfSection above... 00066 00067 ControlArea - Supplies the control area for the section. 00068 00069 Process - Supplies the process pointer which is receiving the section. 00070 00071 ProtectionMask - Supplies the initial page protection-mask. 00072 00073 ReleasedWsMutex - Supplies FALSE, receives TRUE if the working set 00074 mutex is released. 00075 00076 Return Value: 00077 00078 Status of the map view operation. 00079 00080 Environment: 00081 00082 Kernel Mode, working set mutex and address creation mutex held. 00083 00084 --*/ 00085 00086 { 00087 PMMVAD Vad; 00088 PVOID StartingAddress; 00089 PVOID EndingAddress; 00090 KIRQL OldIrql; 00091 KIRQL OldIrql2; 00092 PMMPTE PointerPpe; 00093 PMMPTE PointerPde; 00094 PMMPTE PointerPte; 00095 PMMPTE LastPte; 00096 MMPTE TempPte; 00097 PMMPFN Pfn2; 00098 ULONG PhysicalViewSize; 00099 ULONG Alignment; 00100 ULONG PagesToMap; 00101 ULONG NextPfn; 00102 PVOID UsedPageTableHandle; 00103 PVOID UsedPageDirectoryHandle; 00104 PMI_PHYSICAL_VIEW PhysicalView; 00105 00106 // 00107 // Physical memory section. 00108 // 00109 00110 #ifdef FIRSTDBG 00111 00112 DbgPrint( "MM: Physsect CaptureBase = %x SectionOffset = %x\n", 00113 CapturedBase, SectionOffset->LowPart ); 00114 DbgPrint( "MM: Physsect Allocation Type = %x, MEM_LARGE_PAGES = %x\n", 00115 AllocationType, MEM_LARGE_PAGES ); 00116 00117 #endif //FIRSTDBG 00118 00119 // 00120 // Compute the alignment we require for the virtual mapping. 00121 // The default is 64K to match protection boundaries. 00122 // Larger page sizes are used if MEM_LARGE_PAGES is requested. 00123 // The Alpha AXP architecture supports granularity hints so that 00124 // larger pages can be defined in the following multiples of 00125 // PAGE_SIZE: 00126 // 8**(GH) * PAGE_SIZE, where GH element of {0,1,2,3} 00127 // 00128 00129 Alignment = X64K; 00130 00131 if( AllocationType & MEM_LARGE_PAGES ){ 00132 00133 // 00134 // MaxAlignment is the maximum boundary alignment of the 00135 // SectionOffset (where the maximum boundary is one of the possible 00136 // granularity hints boundaries) 00137 // 00138 00139 ULONG MaxAlignment = MaximumAlignment( SectionOffset->LowPart ); 00140 00141 Alignment = (MaxAlignment > Alignment) ? MaxAlignment : Alignment; 00142 00143 #ifdef FIRSTDBG 00144 00145 DbgPrint( "MM: Alignment = %x, SectionOffset = %x\n", 00146 Alignment, SectionOffset->LowPart ); 00147 00148 #endif //FIRSTDBG 00149 00150 } 00151 00152 00153 LOCK_WS_UNSAFE (Process); 00154 00155 if (*CapturedBase == NULL) { 00156 00157 // 00158 // Attempt to locate address space. This could raise an 00159 // exception. 00160 // 00161 00162 try { 00163 00164 // 00165 // Find a starting address on an alignment boundary. 00166 // 00167 00168 00169 PhysicalViewSize = (SectionOffset->LowPart + *CapturedViewSize) - 00170 (ULONG)MI_64K_ALIGN(SectionOffset->LowPart); 00171 StartingAddress = MiFindEmptyAddressRange (PhysicalViewSize, 00172 Alignment, 00173 (ULONG)ZeroBits); 00174 00175 } except (EXCEPTION_EXECUTE_HANDLER) { 00176 00177 return GetExceptionCode(); 00178 } 00179 00180 EndingAddress = (PVOID)(((ULONG)StartingAddress + 00181 PhysicalViewSize - 1L) | (PAGE_SIZE - 1L)); 00182 StartingAddress = (PVOID)((ULONG)StartingAddress + 00183 (SectionOffset->LowPart & (X64K - 1))); 00184 00185 if (ZeroBits > 0) { 00186 if (EndingAddress > (PVOID)((ULONG)0xFFFFFFFF >> ZeroBits)) { 00187 return STATUS_NO_MEMORY; 00188 } 00189 } 00190 00191 } else { 00192 00193 // 00194 // Check to make sure the specified base address to ending address 00195 // is currently unused. 00196 // 00197 00198 PhysicalViewSize = (SectionOffset->LowPart + *CapturedViewSize) - 00199 (ULONG)MI_64K_ALIGN(SectionOffset->LowPart); 00200 StartingAddress = (PVOID)((ULONG)MI_64K_ALIGN(*CapturedBase) + 00201 (SectionOffset->LowPart & (X64K - 1))); 00202 EndingAddress = (PVOID)(((ULONG)StartingAddress + 00203 *CapturedViewSize - 1L) | (PAGE_SIZE - 1L)); 00204 00205 Vad = MiCheckForConflictingVad (StartingAddress, EndingAddress); 00206 if (Vad != (PMMVAD)NULL) { 00207 #if 0 00208 MiDumpConflictingVad (StartingAddress, EndingAddress, Vad); 00209 #endif 00210 00211 return STATUS_CONFLICTING_ADDRESSES; 00212 } 00213 } 00214 00215 // 00216 // An unoccuppied address range has been found, build the virtual 00217 // address descriptor to describe this range. 00218 // 00219 00220 // 00221 // Establish an exception handler and attempt to allocate 00222 // the pool and charge quota. Note that the InsertVad routine 00223 // will also charge quota which could raise an exception. 00224 // 00225 00226 try { 00227 00228 PhysicalView = (PMI_PHYSICAL_VIEW)ExAllocatePoolWithTag (NonPagedPool, 00229 sizeof(MI_PHYSICAL_VIEW), 00230 MI_PHYSICAL_VIEW_KEY); 00231 if (PhysicalView == NULL) { 00232 ExRaiseStatus (STATUS_INSUFFICIENT_RESOURCES); 00233 } 00234 00235 Vad = (PMMVAD)ExAllocatePoolWithTag (NonPagedPool, sizeof(MMVAD), ' daV'); 00236 if (Vad == NULL) { 00237 ExRaiseStatus (STATUS_INSUFFICIENT_RESOURCES); 00238 } 00239 00240 PhysicalView->Vad = Vad; 00241 PhysicalView->StartVa = StartingAddress; 00242 PhysicalView->EndVa = EndingAddress; 00243 00244 Vad->StartingVpn = MI_VA_TO_VPN (StartingAddress); 00245 Vad->EndingVpn = MI_VA_TO_VPN (EndingAddress); 00246 Vad->ControlArea = ControlArea; 00247 Vad->u.LongFlags = 0; 00248 Vad->u2.VadFlags2.Inherit = ViewUnmap; 00249 Vad->u.VadFlags.PhysicalMapping = 1; 00250 Vad->u4.Banked = NULL; 00251 // Vad->u.VadFlags.ImageMap = 0; 00252 Vad->u.VadFlags.Protection = ProtectionMask; 00253 Vad->u2.VadFlags2.CopyOnWrite = 0; 00254 // Vad->u.VadFlags.LargePages = 0; 00255 Vad->FirstPrototypePte = 00256 (PMMPTE)(MI_CONVERT_PHYSICAL_BUS_TO_PFN(*SectionOffset)); 00257 00258 // 00259 // Set the first prototype PTE field in the Vad. 00260 // 00261 00262 Vad->LastContiguousPte = 00263 (PMMPTE)(MI_CONVERT_PHYSICAL_BUS_TO_PFN(*SectionOffset)); 00264 00265 // 00266 // Insert the VAD. This could get an exception. 00267 // 00268 00269 MiInsertVad (Vad); 00270 00271 } except (EXCEPTION_EXECUTE_HANDLER) { 00272 00273 if (PhysicalView != NULL) { 00274 ExFreePool (PhysicalView); 00275 } 00276 00277 if (Vad != (PMMVAD)NULL) { 00278 00279 // 00280 // The pool allocation suceeded, but the quota charge 00281 // in InsertVad failed, deallocate the pool and return 00282 // an error. 00283 // 00284 00285 ExFreePool (Vad); 00286 return GetExceptionCode(); 00287 } 00288 return STATUS_INSUFFICIENT_RESOURCES; 00289 } 00290 00291 // Increment the count of the number of views for the 00292 // section object. This requires the PFN mutex to be held. 00293 // 00294 00295 LOCK_AWE (Process, OldIrql); 00296 LOCK_PFN2 (OldIrql2); 00297 00298 InsertHeadList (&Process->PhysicalVadList, &PhysicalView->ListEntry); 00299 00300 ControlArea->NumberOfMappedViews += 1; 00301 ControlArea->NumberOfUserReferences += 1; 00302 ASSERT (ControlArea->NumberOfSectionReferences != 0); 00303 00304 UNLOCK_PFN2 (OldIrql2); 00305 UNLOCK_AWE (Process, OldIrql); 00306 00307 // 00308 // Build the PTEs in the address space. 00309 // 00310 00311 PointerPpe = MiGetPpeAddress (StartingAddress); 00312 PointerPde = MiGetPdeAddress (StartingAddress); 00313 PointerPte = MiGetPteAddress (StartingAddress); 00314 LastPte = MiGetPteAddress (EndingAddress); 00315 00316 #if defined (_WIN64) 00317 MiMakePpeExistAndMakeValid (PointerPpe, Process, FALSE); 00318 if (PointerPde->u.Long == 0) { 00319 UsedPageDirectoryHandle = MI_GET_USED_PTES_HANDLE (PointerPte); 00320 ASSERT (MI_GET_USED_PTES_FROM_HANDLE (UsedPageDirectoryHandle) == 0); 00321 MI_INCREMENT_USED_PTES_BY_HANDLE (UsedPageDirectoryHandle); 00322 } 00323 #endif 00324 00325 MiMakePdeExistAndMakeValid(PointerPde, Process, FALSE); 00326 00327 Pfn2 = MI_PFN_ELEMENT(PointerPde->u.Hard.PageFrameNumber); 00328 00329 PagesToMap = ( ((ULONG)EndingAddress - (ULONG)StartingAddress) 00330 + (PAGE_SIZE-1) ) >> PAGE_SHIFT; 00331 00332 NextPfn = MI_CONVERT_PHYSICAL_BUS_TO_PFN(*SectionOffset); 00333 00334 #ifdef FIRSTDBG 00335 00336 DbgPrint( "MM: Physsect, PagesToMap = %x NextPfn = %x\n", 00337 PagesToMap, NextPfn ); 00338 00339 #endif //FIRSTDBG 00340 00341 MI_MAKE_VALID_PTE (TempPte, 00342 NextPfn, 00343 ProtectionMask, 00344 PointerPte); 00345 00346 if (WriteCombined == TRUE) { 00347 MI_SET_PTE_WRITE_COMBINE (TempPte); 00348 } 00349 00350 if (TempPte.u.Hard.Write) { 00351 TempPte.u.Hard.Dirty = 1; 00352 } 00353 00354 while (PointerPte <= LastPte) { 00355 00356 ULONG PagesTogether; 00357 ULONG GranularityHint; 00358 00359 // 00360 // Compute the number of pages that can be mapped together 00361 // 00362 00363 if (AllocationType & MEM_LARGE_PAGES) { 00364 PagesTogether = AggregatePages (PointerPte, 00365 NextPfn, 00366 PagesToMap, 00367 &GranularityHint); 00368 } else { 00369 PagesTogether = 1; 00370 GranularityHint = 0; 00371 } 00372 00373 #ifdef FIRSTDBG 00374 00375 DbgPrint( "MM: Physsect PointerPte = %x, NextPfn = %x\n", 00376 PointerPte, NextPfn ); 00377 DbgPrint( "MM: Va = %x TempPte.Pfn = %x\n", 00378 MiGetVirtualAddressMappedByPte( PointerPte ), 00379 TempPte.u.Hard.PageFrameNumber ); 00380 DbgPrint( "MM: PagesToMap = %x\n", PagesToMap ); 00381 DbgPrint( "MM: PagesTogether = %x, GH = %x\n", 00382 PagesTogether, GranularityHint ); 00383 00384 #endif //FIRSTDBG 00385 00386 TempPte.u.Hard.GranularityHint = GranularityHint; 00387 00388 NextPfn += PagesTogether; 00389 PagesToMap -= PagesTogether; 00390 00391 UsedPageTableHandle = MI_GET_USED_PTES_HANDLE (MiGetVirtualAddressMappedByPte (PointerPte)); 00392 00393 while (PagesTogether--) { 00394 00395 if (MiIsPteOnPdeBoundary (PointerPte)) { 00396 00397 PointerPde = MiGetPteAddress (PointerPte); 00398 00399 if (MiIsPteOnPpeBoundary (PointerPte)) { 00400 PointerPpe = MiGetPteAddress (PointerPde); 00401 MiMakePpeExistAndMakeValid (PointerPpe, Process, FALSE); 00402 if (PointerPde->u.Long == 0) { 00403 UsedPageDirectoryHandle = MI_GET_USED_PTES_HANDLE (PointerPte); 00404 ASSERT (MI_GET_USED_PTES_FROM_HANDLE (UsedPageDirectoryHandle) == 0); 00405 00406 MI_INCREMENT_USED_PTES_BY_HANDLE (UsedPageDirectoryHandle); 00407 } 00408 } 00409 00410 MiMakePdeExistAndMakeValid (PointerPde, Process, FALSE); 00411 Pfn2 = MI_PFN_ELEMENT (PointerPde->u.Hard.PageFrameNumber); 00412 UsedPageTableHandle = MI_GET_USED_PTES_HANDLE (MiGetVirtualAddressMappedByPte (PointerPte)); 00413 } 00414 00415 ASSERT( PointerPte->u.Long == 0 ); 00416 00417 *PointerPte = TempPte; 00418 #if PFN_CONSISTENCY 00419 LOCK_PFN (OldIrql); 00420 #endif 00421 Pfn2->u2.ShareCount += 1; 00422 #if PFN_CONSISTENCY 00423 UNLOCK_PFN (OldIrql); 00424 #endif 00425 00426 // 00427 // Increment the count of non-zero page table entries for this 00428 // page table and the number of private pages for the process. 00429 // 00430 00431 MI_INCREMENT_USED_PTES_BY_HANDLE (UsedPageTableHandle); 00432 00433 PointerPte += 1; 00434 00435 TempPte.u.Hard.PageFrameNumber += 1; 00436 00437 } // while (PagesTogether-- ) 00438 00439 } // while (PointerPte <= LastPte) 00440 00441 UNLOCK_WS_UNSAFE (Process); 00442 *ReleasedWsMutex = TRUE; 00443 00444 // 00445 // Update the current virtual size in the process header. 00446 // 00447 00448 *CapturedViewSize = (ULONG)EndingAddress - (ULONG)StartingAddress + 1L; 00449 Process->VirtualSize += *CapturedViewSize; 00450 00451 if (Process->VirtualSize > Process->PeakVirtualSize) { 00452 Process->PeakVirtualSize = Process->VirtualSize; 00453 } 00454 00455 // 00456 // Translate the virtual address to a quasi-virtual address for 00457 // use by drivers that touch mapped devices. Note: the routine 00458 // HalCreateQva will not translate the StartingAddress if the 00459 // StartingAddress is within system memory address space. 00460 // 00461 // N.B. - It will not work to attempt map addresses that begin in 00462 // system memory and extend through i/o space. 00463 // 00464 00465 *CapturedBase = HalCreateQva( *SectionOffset, StartingAddress ); 00466 00467 return STATUS_SUCCESS; 00468 }

VOID MiMarkProcessAsWriteWatch IN PEPROCESS  Process  ) 
 

Referenced by MiPhysicalViewInserter().

VOID MiModifiedPageWriter IN PVOID  StartContext  ) 
 

Definition at line 2669 of file modwrite.c.

References _MMMOD_WRITER_LISTHEAD::Event, ExAllocatePoolWithTag, FALSE, KeDelayExecutionThread(), KeInitializeEvent, KernelMode, KeSetPriorityThread(), L, _MMMOD_WRITER_MDL_ENTRY::Links, _MMMOD_WRITER_LISTHEAD::ListHead, MiMappedPageWriter(), MiModifiedPageWriterWorker(), MM_MAPPED_FILE_MDLS, MmFreePagingSpaceLow, MmMappedFileHeader, MmMappedFileMdl, MmMappedPageWriterEvent, MmMappedPageWriterList, MmModifiedWriteClusterSize, MmPagingFileHeader, MmSystemShutdown, NonPagedPoolMustSucceed, NULL, ObjectAttributes, PAGED_CODE, _MMMOD_WRITER_MDL_ENTRY::PagingFile, _MMMOD_WRITER_MDL_ENTRY::PagingListHead, PsCreateSystemThread(), PsGetCurrentThread, ThreadHandle, and VOID().

Referenced by MmInitSystem().

02675 : 02676 02677 Implements the NT modified page writer thread. When the modified 02678 page threshold is reached, or memory becomes overcommitted the 02679 modified page writer event is set, and this thread becomes active. 02680 02681 Arguments: 02682 02683 StartContext - not used. 02684 02685 Return Value: 02686 02687 None. 02688 02689 Environment: 02690 02691 Kernel mode. 02692 02693 --*/ 02694 02695 { 02696 HANDLE ThreadHandle; 02697 OBJECT_ATTRIBUTES ObjectAttributes; 02698 ULONG i; 02699 02700 PAGED_CODE(); 02701 02702 StartContext; //avoid compiler warning. 02703 02704 // 02705 // Initialize listheads as empty. 02706 // 02707 02708 MmSystemShutdown = 0; 02709 KeInitializeEvent (&MmPagingFileHeader.Event, NotificationEvent, FALSE); 02710 KeInitializeEvent (&MmMappedFileHeader.Event, NotificationEvent, FALSE); 02711 02712 InitializeListHead(&MmPagingFileHeader.ListHead); 02713 InitializeListHead(&MmMappedFileHeader.ListHead); 02714 InitializeListHead(&MmFreePagingSpaceLow); 02715 02716 for (i = 0; i < MM_MAPPED_FILE_MDLS; i += 1) { 02717 MmMappedFileMdl[i] = ExAllocatePoolWithTag (NonPagedPoolMustSucceed, 02718 sizeof(MMMOD_WRITER_MDL_ENTRY) + 02719 MmModifiedWriteClusterSize * 02720 sizeof(PFN_NUMBER), 02721 ' mM'); 02722 02723 MmMappedFileMdl[i]->PagingFile = NULL; 02724 MmMappedFileMdl[i]->PagingListHead = &MmMappedFileHeader; 02725 02726 InsertTailList (&MmMappedFileHeader.ListHead, 02727 &MmMappedFileMdl[i]->Links); 02728 } 02729 02730 // 02731 // Make this a real time thread. 02732 // 02733 02734 (VOID) KeSetPriorityThread (&PsGetCurrentThread()->Tcb, 02735 LOW_REALTIME_PRIORITY + 1); 02736 02737 // 02738 // Start a secondary thread for writing mapped file pages. This 02739 // is required as the writing of mapped file pages could cause 02740 // page faults resulting in requests for free pages. But there 02741 // could be no free pages - hence a dead lock. Rather than deadlock 02742 // the whole system waiting on the modified page writer, creating 02743 // a secondary thread allows that thread to block without affecting 02744 // on going page file writes. 02745 // 02746 02747 KeInitializeEvent (&MmMappedPageWriterEvent, NotificationEvent, FALSE); 02748 InitializeListHead(&MmMappedPageWriterList); 02749 InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, NULL ); 02750 02751 PsCreateSystemThread (&ThreadHandle, 02752 THREAD_ALL_ACCESS, 02753 &ObjectAttributes, 02754 0L, 02755 NULL, 02756 MiMappedPageWriter, 02757 NULL ); 02758 ZwClose (ThreadHandle); 02759 MiModifiedPageWriterWorker(); 02760 02761 // 02762 // Shutdown in progress, wait forever. 02763 // 02764 02765 { 02766 LARGE_INTEGER Forever; 02767 02768 // 02769 // System has shutdown, go into LONG wait. 02770 // 02771 02772 Forever.LowPart = 0; 02773 Forever.HighPart = 0xF000000; 02774 KeDelayExecutionThread (KernelMode, FALSE, &Forever); 02775 } 02776 02777 return; 02778 }

VOID MiModifiedPageWriterTimerDispatch IN PKDPC  Dpc,
IN PVOID  DeferredContext,
IN PVOID  SystemArgument1,
IN PVOID  SystemArgument2
 

Definition at line 2782 of file modwrite.c.

References FALSE, KeSetEvent(), LOCK_PFN2, MiMappedPagesTooOldEvent, MiTimerPending, TRUE, and UNLOCK_PFN2.

Referenced by MmInitSystem().

02791 : 02792 02793 This routine is executed whenever modified mapped pages are waiting to 02794 be written. Its job is to signal the Modified Page Writer to write 02795 these out. 02796 02797 Arguments: 02798 02799 Dpc - Supplies a pointer to a control object of type DPC. 02800 02801 DeferredContext - Optional deferred context; not used. 02802 02803 SystemArgument1 - Optional argument 1; not used. 02804 02805 SystemArgument2 - Optional argument 2; not used. 02806 02807 Return Value: 02808 02809 None. 02810 02811 --*/ 02812 02813 { 02814 KIRQL OldIrql; 02815 02816 UNREFERENCED_PARAMETER (Dpc); 02817 UNREFERENCED_PARAMETER (DeferredContext); 02818 UNREFERENCED_PARAMETER (SystemArgument1); 02819 UNREFERENCED_PARAMETER (SystemArgument2); 02820 02821 LOCK_PFN2 (OldIrql); 02822 02823 MiTimerPending = TRUE; 02824 KeSetEvent (&MiMappedPagesTooOldEvent, 0, FALSE); 02825 02826 UNLOCK_PFN2 (OldIrql); 02827 }

VOID MiObtainFreePages VOID   ) 
 

Definition at line 336 of file wsmanage.c.

References FALSE, KeSetEvent(), MmAvailablePages, MmModifiedPageListHead, MmModifiedPageWriterEvent, MmModifiedWriteClusterSize, MmModNoWriteInsert, MmPagesAboveWsMinimum, MmPagesAboveWsThreshold, MmWorkingSetManagerEvent, and _MMPFNLIST::Total.

Referenced by MiRemovePageByColor(), MiRemovePageFromList(), MiUnlinkFreeOrZeroedPage(), and MiUnlinkPageFromList().

00342 : 00343 00344 This function examines the size of the modified list and the 00345 total number of pages in use because of working set increments 00346 and obtains pages by writing modified pages and/or reducing 00347 working sets. 00348 00349 Arguments: 00350 00351 None. 00352 00353 Return Value: 00354 00355 None. 00356 00357 Environment: 00358 00359 Kernel mode, APCs disabled, working set and PFN mutexes held. 00360 00361 --*/ 00362 00363 { 00364 00365 // 00366 // Check to see if there are enough modified pages to institute a 00367 // write. 00368 // 00369 00370 if ((MmModifiedPageListHead.Total >= MmModifiedWriteClusterSize) || 00371 (MmModNoWriteInsert)) { 00372 00373 // 00374 // Start the modified page writer. 00375 // 00376 00377 KeSetEvent (&MmModifiedPageWriterEvent, 0, FALSE); 00378 } 00379 00380 // 00381 // See if there are enough working sets above the minimum 00382 // threshold to make working set trimming worthwhile. 00383 // 00384 00385 if ((MmPagesAboveWsMinimum > MmPagesAboveWsThreshold) || 00386 (MmAvailablePages < 5)) { 00387 00388 // 00389 // Start the working set manager to reduce working sets. 00390 // 00391 00392 KeSetEvent (&MmWorkingSetManagerEvent, 0, FALSE); 00393 } 00394 }

VOID MiPhysicalViewAdjuster IN PEPROCESS  Process,
IN PMMVAD  OldVad,
IN PMMVAD  NewVad
 

Definition at line 2721 of file iosup.c.

References ASSERT, FALSE, LOCK_AWE, LOCK_PFN2, UNLOCK_AWE, UNLOCK_PFN2, and _MI_PHYSICAL_VIEW::Vad.

Referenced by MmSecureVirtualMemory().

02729 : 02730 02731 This function is a nonpaged wrapper which acquires the PFN lock to repoint 02732 a physical VAD in the process chain. 02733 02734 Arguments: 02735 02736 Process - Supplies the process in which to adjust the physical VAD. 02737 02738 Vad - Supplies the old Vad to replace. 02739 02740 NewVad - Supplies the newVad to substitute. 02741 02742 Return Value: 02743 02744 None. 02745 02746 Environment: 02747 02748 Kernel mode, called with APCs disabled, working set mutex held. 02749 02750 --*/ 02751 { 02752 KIRQL OldIrql; 02753 KIRQL OldIrql2; 02754 PLIST_ENTRY NextEntry; 02755 PMI_PHYSICAL_VIEW PhysicalView; 02756 02757 LOCK_AWE (Process, OldIrql); 02758 02759 LOCK_PFN2 (OldIrql2); 02760 02761 NextEntry = Process->PhysicalVadList.Flink; 02762 while (NextEntry != &Process->PhysicalVadList) { 02763 02764 PhysicalView = CONTAINING_RECORD(NextEntry, 02765 MI_PHYSICAL_VIEW, 02766 ListEntry); 02767 02768 if (PhysicalView->Vad == OldVad) { 02769 PhysicalView->Vad = NewVad; 02770 UNLOCK_PFN2 (OldIrql2); 02771 UNLOCK_AWE (Process, OldIrql); 02772 return; 02773 } 02774 02775 NextEntry = NextEntry->Flink; 02776 } 02777 02778 ASSERT (FALSE); 02779 02780 UNLOCK_PFN2 (OldIrql2); 02781 UNLOCK_AWE (Process, OldIrql); 02782 }

VOID MiPhysicalViewRemover IN PEPROCESS  Process,
IN PMMVAD  Vad
 

Definition at line 2641 of file iosup.c.

References ASSERT, _MI_PHYSICAL_VIEW::BitMap, BitMap, ExFreePool(), FALSE, LOCK_AWE, LOCK_PFN2, MiActiveWriteWatch, NonPagedPool, NULL, PsReturnPoolQuota(), UNLOCK_AWE, UNLOCK_PFN2, and _MI_PHYSICAL_VIEW::Vad.

Referenced by MiUnmapLockedPagesInUserSpace(), MmCleanProcessAddressSpace(), and NtFreeVirtualMemory().

02648 : 02649 02650 This function is a nonpaged wrapper which acquires the PFN lock to remove 02651 a physical VAD from the process chain. 02652 02653 Arguments: 02654 02655 Process - Supplies the process to remove the physical VAD from. 02656 02657 Vad - Supplies the Vad to remove. 02658 02659 Return Value: 02660 02661 None. 02662 02663 Environment: 02664 02665 Kernel mode, APC_LEVEL, working set and address space mutexes held. 02666 02667 --*/ 02668 { 02669 KIRQL OldIrql; 02670 KIRQL OldIrql2; 02671 PRTL_BITMAP BitMap; 02672 PLIST_ENTRY NextEntry; 02673 PMI_PHYSICAL_VIEW PhysicalView; 02674 ULONG BitMapSize; 02675 02676 BitMap = NULL; 02677 02678 LOCK_AWE (Process, OldIrql); 02679 02680 LOCK_PFN2 (OldIrql2); 02681 02682 NextEntry = Process->PhysicalVadList.Flink; 02683 while (NextEntry != &Process->PhysicalVadList) { 02684 02685 PhysicalView = CONTAINING_RECORD(NextEntry, 02686 MI_PHYSICAL_VIEW, 02687 ListEntry); 02688 02689 if (PhysicalView->Vad == Vad) { 02690 RemoveEntryList (NextEntry); 02691 02692 if (Vad->u.VadFlags.WriteWatch == 1) { 02693 MiActiveWriteWatch -= 1; 02694 BitMap = PhysicalView->BitMap; 02695 ASSERT (BitMap != NULL); 02696 } 02697 02698 UNLOCK_PFN2 (OldIrql2); 02699 UNLOCK_AWE (Process, OldIrql); 02700 ExFreePool (PhysicalView); 02701 02702 if (BitMap != NULL) { 02703 BitMapSize = sizeof(RTL_BITMAP) + (ULONG)(((BitMap->SizeOfBitMap + 31) / 32) * 4); 02704 PsReturnPoolQuota (Process, NonPagedPool, BitMapSize); 02705 ExFreePool (BitMap); 02706 } 02707 02708 return; 02709 } 02710 02711 NextEntry = NextEntry->Flink; 02712 } 02713 02714 ASSERT (FALSE); 02715 02716 UNLOCK_PFN2 (OldIrql2); 02717 UNLOCK_AWE (Process, OldIrql); 02718 }

NTSTATUS MiProtectVirtualMemory IN PEPROCESS  Process,
IN PVOID *  CapturedBase,
IN PSIZE_T  CapturedRegionSize,
IN ULONG  Protect,
IN PULONG  LastProtect
 

Definition at line 344 of file protect.c.

References ALT_CHANGE, ASSERT, _MMVAD::ControlArea, _MMVAD::EndingVpn, ExAcquireFastMutexUnsafe(), EXCEPTION_EXECUTE_HANDLER, ExReleaseFastMutexUnsafe(), FALSE, L, LOCK_WS_AND_ADDRESS_SPACE, LOCK_WS_UNSAFE, MI_CONVERT_FROM_PTE_PROTECTION, MI_GET_USED_PTES_HANDLE, MI_GET_WORKING_SET_FROM_PTE, MI_INCREMENT_USED_PTES_BY_HANDLE, MI_MAKE_VALID_PTE, MI_PFN_ELEMENT, MI_SET_PTE_IN_WORKING_SET, MI_VA_TO_VPN, MiChangeNoAccessForkPte(), MiCheckForConflictingVad, MiCheckSecuredVad(), MiCopyOnWrite(), MiDoesPdeExistAndMakeValid(), MiDoesPpeExistAndMakeValid, MiFlushTbAndCapture(), MiGetPageProtection(), MiGetPdeAddress, MiGetPpeAddress, MiGetProtoPteAddress, MiGetPteAddress, MiGetVirtualAddressMappedByPte, MiIsEntireRangeCommitted(), MiIsPteOnPdeBoundary, MiMakePdeExistAndMakeValid(), MiMakePpeExistAndMakeValid, MiMakeProtectForNativePage(), MiMakeProtectionMask(), MiProtectFor4kPage(), MiQueryProtectionFor4kPage(), MiRemovePageFromWorkingSet(), MiSetProtectionOnSection(), MiSetProtectionOnTransitionPte(), MM_PROTECTION_COPY_MASK, MmSectionCommitMutex, NT_SUCCESS, NTSTATUS(), NULL, _MMPFN::OriginalPte, PAGE_4K, PAGE_4K_ALIGN, PAGE_ALIGN, PAGE_SIZE, _MMVAD::StartingVpn, Status, TRUE, _MMVAD::u, _CONTROL_AREA::u, _MMPTE::u, _MMVAD::u2, _MMPFN::u3, UNLOCK_ADDRESS_SPACE, UNLOCK_WS_AND_ADDRESS_SPACE, UNLOCK_WS_UNSAFE, and VOID().

Referenced by NtAllocateVirtualMemory(), and NtProtectVirtualMemory().

00354 : 00355 00356 This routine changes the protection on a region of committed pages 00357 within the virtual address space of the subject process. Setting 00358 the protection on a range of pages causes the old protection to be 00359 replaced by the specified protection value. 00360 00361 Arguments: 00362 00363 Process - Supplies a pointer to the current process. 00364 00365 BaseAddress - Supplies the starting address to protect. 00366 00367 RegionsSize - Supplies the size of the region to protect. 00368 00369 NewProtect - Supplies the new protection to set. 00370 00371 LastProtect - Supplies the address of a kernel owned pointer to 00372 store (without probing) the old protection into. 00373 00374 00375 Return Value: 00376 00377 the status of the protect operation. 00378 00379 Environment: 00380 00381 Kernel mode 00382 00383 --*/ 00384 00385 { 00386 PMMVAD FoundVad; 00387 PVOID StartingAddress; 00388 PVOID EndingAddress; 00389 PVOID CapturedBase; 00390 SIZE_T CapturedRegionSize; 00391 NTSTATUS Status; 00392 ULONG Attached; 00393 PMMPTE PointerPte; 00394 PMMPTE LastPte; 00395 PMMPTE PointerPde; 00396 PMMPTE PointerPpe; 00397 PMMPTE PointerProtoPte; 00398 PMMPTE LastProtoPte; 00399 PMMPFN Pfn1; 00400 ULONG CapturedOldProtect; 00401 ULONG ProtectionMask; 00402 MMPTE TempPte; 00403 MMPTE PteContents; 00404 MMPTE PreviousPte; 00405 ULONG Locked; 00406 PVOID Va; 00407 ULONG DoAgain; 00408 ULONG Waited; 00409 PVOID UsedPageTableHandle; 00410 PVOID UsedPageDirectoryHandle; 00411 ULONG WorkingSetIndex; 00412 #if defined(_MIALT4K_) 00413 PVOID OriginalBase; 00414 SIZE_T OriginalRegionSize; 00415 ULONG OriginalProtectionMask; 00416 PVOID StartingAddressFor4k; 00417 PVOID EndingAddressFor4k; 00418 SIZE_T CapturedRegionSizeFor4k; 00419 ULONG CapturedOldProtectFor4k; 00420 BOOLEAN EmulationFor4kPage = FALSE; 00421 #endif 00422 00423 Attached = FALSE; 00424 Locked = FALSE; 00425 00426 // 00427 // Get the address creation mutex to block multiple threads from 00428 // creating or deleting address space at the same time. 00429 // Get the working set mutex so PTEs can be modified. 00430 // Block APCs so an APC which takes a page 00431 // fault does not corrupt various structures. 00432 // 00433 00434 CapturedBase = *BaseAddress; 00435 CapturedRegionSize = *RegionSize; 00436 00437 #if defined(_MIALT4K_) 00438 OriginalBase = CapturedBase; 00439 OriginalRegionSize = CapturedRegionSize; 00440 00441 if (Process->Wow64Process != NULL) { 00442 00443 StartingAddressFor4k = (PVOID)PAGE_4K_ALIGN(OriginalBase); 00444 00445 EndingAddressFor4k = (PVOID)(((ULONG_PTR)OriginalBase + 00446 OriginalRegionSize - 1) | (PAGE_4K - 1)); 00447 00448 CapturedRegionSizeFor4k = (ULONG_PTR)EndingAddressFor4k - 00449 (ULONG_PTR)StartingAddressFor4k + 1L; 00450 00451 OriginalProtectionMask = MiMakeProtectionMask(NewProtect); 00452 00453 EmulationFor4kPage = TRUE; 00454 00455 } 00456 #endif 00457 00458 try { 00459 ProtectionMask = MiMakeProtectionMask (NewProtect); 00460 } except (EXCEPTION_EXECUTE_HANDLER) { 00461 return GetExceptionCode(); 00462 } 00463 00464 LOCK_WS_AND_ADDRESS_SPACE (Process); 00465 00466 // 00467 // Make sure the address space was not deleted, if so, return an error. 00468 // 00469 00470 if (Process->AddressSpaceDeleted != 0) { 00471 Status = STATUS_PROCESS_IS_TERMINATING; 00472 goto ErrorFound; 00473 } 00474 00475 EndingAddress = (PVOID)(((ULONG_PTR)CapturedBase + 00476 CapturedRegionSize - 1L) | (PAGE_SIZE - 1L)); 00477 StartingAddress = (PVOID)PAGE_ALIGN(CapturedBase); 00478 FoundVad = MiCheckForConflictingVad (StartingAddress, EndingAddress); 00479 00480 if (FoundVad == (PMMVAD)NULL) { 00481 00482 // 00483 // No virtual address is reserved at the specified base address, 00484 // return an error. 00485 // 00486 00487 Status = STATUS_CONFLICTING_ADDRESSES; 00488 goto ErrorFound; 00489 } 00490 00491 // 00492 // Ensure that the starting and ending addresses are all within 00493 // the same virtual address descriptor. 00494 // 00495 00496 if ((MI_VA_TO_VPN (StartingAddress) < FoundVad->StartingVpn) || 00497 (MI_VA_TO_VPN (EndingAddress) > FoundVad->EndingVpn)) { 00498 00499 // 00500 // Not within the section virtual address descriptor, 00501 // return an error. 00502 // 00503 00504 Status = STATUS_CONFLICTING_ADDRESSES; 00505 goto ErrorFound; 00506 } 00507 00508 if (FoundVad->u.VadFlags.UserPhysicalPages == 1) { 00509 00510 // 00511 // These must always be readwrite. 00512 // 00513 00514 Status = STATUS_CONFLICTING_ADDRESSES; 00515 goto ErrorFound; 00516 } 00517 00518 if (FoundVad->u.VadFlags.PhysicalMapping == 1) { 00519 00520 // 00521 // Setting the protection of a physically mapped section is 00522 // not allowed as there is no corresponding PFN database element. 00523 // 00524 00525 Status = STATUS_CONFLICTING_ADDRESSES; 00526 goto ErrorFound; 00527 } 00528 00529 if (FoundVad->u.VadFlags.NoChange == 1) { 00530 00531 // 00532 // An attempt is made at changing the protection 00533 // of a secured VAD, check to see if the address range 00534 // to change allows the change. 00535 // 00536 00537 Status = MiCheckSecuredVad (FoundVad, 00538 CapturedBase, 00539 CapturedRegionSize, 00540 ProtectionMask); 00541 00542 if (!NT_SUCCESS (Status)) { 00543 goto ErrorFound; 00544 } 00545 } 00546 #if defined(_MIALT4K_) 00547 else if (EmulationFor4kPage == TRUE) { 00548 // 00549 // if not secured, relax the protection 00550 // 00551 00552 NewProtect = MiMakeProtectForNativePage(StartingAddressFor4k, 00553 NewProtect, 00554 Process); 00555 00556 ProtectionMask = MiMakeProtectionMask (NewProtect); 00557 } 00558 #endif 00559 00560 if (FoundVad->u.VadFlags.PrivateMemory == 0) { 00561 00562 00563 // 00564 // For mapped sections, the NO_CACHE attribute is not allowed. 00565 // 00566 00567 if (NewProtect & PAGE_NOCACHE) { 00568 00569 // 00570 // Not allowed. 00571 // 00572 00573 Status = STATUS_INVALID_PARAMETER_4; 00574 goto ErrorFound; 00575 } 00576 00577 // 00578 // If this is a file mapping, then all pages must be 00579 // committed as there can be no sparse file maps. Images 00580 // can have non-committed pages if the alignment is greater 00581 // than the page size. 00582 // 00583 00584 if ((FoundVad->ControlArea->u.Flags.File == 0) || 00585 (FoundVad->ControlArea->u.Flags.Image == 1)) { 00586 00587 PointerProtoPte = MiGetProtoPteAddress (FoundVad, 00588 MI_VA_TO_VPN (StartingAddress)); 00589 LastProtoPte = MiGetProtoPteAddress (FoundVad, 00590 MI_VA_TO_VPN (EndingAddress)); 00591 00592 // 00593 // Release the working set mutex and acquire the section 00594 // commit mutex. Check all the prototype PTEs described by 00595 // the virtual address range to ensure they are committed. 00596 // 00597 00598 UNLOCK_WS_UNSAFE (Process); 00599 ExAcquireFastMutexUnsafe (&MmSectionCommitMutex); 00600 00601 while (PointerProtoPte <= LastProtoPte) { 00602 00603 // 00604 // Check to see if the prototype PTE is committed, if 00605 // not return an error. 00606 // 00607 00608 if (PointerProtoPte->u.Long == 0) { 00609 00610 // 00611 // Error, this prototype PTE is not committed. 00612 // 00613 00614 ExReleaseFastMutexUnsafe (&MmSectionCommitMutex); 00615 Status = STATUS_NOT_COMMITTED; 00616 UNLOCK_ADDRESS_SPACE (Process); 00617 goto ErrorFoundNoWs; 00618 } 00619 PointerProtoPte += 1; 00620 } 00621 00622 // 00623 // The range is committed, release the section commitment 00624 // mutex, acquire the working set mutex and update the local PTEs. 00625 // 00626 00627 ExReleaseFastMutexUnsafe (&MmSectionCommitMutex); 00628 00629 // 00630 // Set the protection on the section pages. This could 00631 // get a quota exceeded exception. 00632 // 00633 00634 LOCK_WS_UNSAFE (Process); 00635 } 00636 00637 #if defined(_MIALT4K_) 00638 00639 // 00640 // We need to change the alternate table before PTEs are created for the protection 00641 // change. 00642 // 00643 00644 if (EmulationFor4kPage == TRUE) { 00645 00646 // 00647 // Before accessing Alternate Table, unlock the working set mutex 00648 // 00649 00650 UNLOCK_WS_UNSAFE (Process); 00651 00652 // 00653 // Get the old protection 00654 // 00655 00656 CapturedOldProtectFor4k = 00657 MiQueryProtectionFor4kPage(StartingAddressFor4k, Process); 00658 00659 if (CapturedOldProtectFor4k != 0) { 00660 00661 CapturedOldProtectFor4k = 00662 MI_CONVERT_FROM_PTE_PROTECTION(CapturedOldProtectFor4k); 00663 00664 } 00665 00666 // 00667 // Set the alternate permission table 00668 // 00669 00670 if ((FoundVad->u.VadFlags.ImageMap == 1) || 00671 (FoundVad->u2.VadFlags2.CopyOnWrite == 1)) { 00672 00673 OriginalProtectionMask |= MM_PROTECTION_COPY_MASK; 00674 00675 } 00676 00677 MiProtectFor4kPage (StartingAddressFor4k, 00678 CapturedRegionSizeFor4k, 00679 OriginalProtectionMask, 00680 ALT_CHANGE, 00681 Process); 00682 00683 LOCK_WS_UNSAFE (Process); 00684 } 00685 #endif 00686 00687 try { 00688 Locked = MiSetProtectionOnSection ( Process, 00689 FoundVad, 00690 StartingAddress, 00691 EndingAddress, 00692 NewProtect, 00693 &CapturedOldProtect, 00694 FALSE ); 00695 00696 } except (EXCEPTION_EXECUTE_HANDLER) { 00697 00698 Status = GetExceptionCode(); 00699 goto ErrorFound; 00700 } 00701 } else { 00702 00703 // 00704 // Not a section, private. 00705 // For private pages, the WRITECOPY attribute is not allowed. 00706 // 00707 00708 if ((NewProtect & PAGE_WRITECOPY) || 00709 (NewProtect & PAGE_EXECUTE_WRITECOPY)) { 00710 00711 // 00712 // Not allowed. 00713 // 00714 00715 Status = STATUS_INVALID_PARAMETER_4; 00716 goto ErrorFound; 00717 } 00718 00719 // 00720 // Ensure all of the pages are already committed as described 00721 // in the virtual address descriptor. 00722 // 00723 00724 if ( !MiIsEntireRangeCommitted(StartingAddress, 00725 EndingAddress, 00726 FoundVad, 00727 Process)) { 00728 00729 // 00730 // Previously reserved pages have been decommitted, or an error 00731 // occurred, release mutex and return status. 00732 // 00733 00734 Status = STATUS_NOT_COMMITTED; 00735 goto ErrorFound; 00736 } 00737 00738 #if defined(_MIALT4K_) 00739 00740 // 00741 // We need to change the alternate table before PTEs are created for the protection 00742 // change. 00743 // 00744 00745 if (EmulationFor4kPage == TRUE) { 00746 00747 // 00748 // Before accessing Alternate Table, unlock the working set mutex 00749 // 00750 00751 UNLOCK_WS_UNSAFE (Process); 00752 00753 // 00754 // Get the old protection 00755 // 00756 00757 CapturedOldProtectFor4k = 00758 MiQueryProtectionFor4kPage(StartingAddressFor4k, Process); 00759 00760 if (CapturedOldProtectFor4k != 0) { 00761 00762 CapturedOldProtectFor4k = 00763 MI_CONVERT_FROM_PTE_PROTECTION(CapturedOldProtectFor4k); 00764 00765 } 00766 00767 // 00768 // Set the alternate permission table 00769 // 00770 00771 MiProtectFor4kPage (StartingAddressFor4k, 00772 CapturedRegionSizeFor4k, 00773 OriginalProtectionMask, 00774 ALT_CHANGE, 00775 Process); 00776 00777 LOCK_WS_UNSAFE (Process); 00778 } 00779 #endif 00780 00781 // 00782 // The address range is committed, change the protection. 00783 // 00784 00785 PointerPpe = MiGetPpeAddress (StartingAddress); 00786 PointerPde = MiGetPdeAddress (StartingAddress); 00787 PointerPte = MiGetPteAddress (StartingAddress); 00788 LastPte = MiGetPteAddress (EndingAddress); 00789 00790 #if defined (_WIN64) 00791 MiMakePpeExistAndMakeValid (PointerPpe, Process, FALSE); 00792 if (PointerPde->u.Long == 0) { 00793 UsedPageDirectoryHandle = MI_GET_USED_PTES_HANDLE (PointerPte); 00794 MI_INCREMENT_USED_PTES_BY_HANDLE (UsedPageDirectoryHandle); 00795 } 00796 #endif 00797 00798 MiMakePdeExistAndMakeValid(PointerPde, Process, FALSE); 00799 00800 // 00801 // Capture the protection for the first page. 00802 // 00803 00804 if (PointerPte->u.Long != 0) { 00805 00806 CapturedOldProtect = MiGetPageProtection (PointerPte, Process); 00807 00808 // 00809 // Make sure the page directory & table pages are still resident. 00810 // 00811 00812 #if defined (_WIN64) 00813 MiMakePpeExistAndMakeValid (PointerPpe, Process, FALSE); 00814 if (PointerPde->u.Long == 0) { 00815 UsedPageDirectoryHandle = MI_GET_USED_PTES_HANDLE (PointerPte); 00816 MI_INCREMENT_USED_PTES_BY_HANDLE (UsedPageDirectoryHandle); 00817 } 00818 #endif 00819 00820 (VOID) MiMakePdeExistAndMakeValid(PointerPde, Process, FALSE); 00821 00822 } else { 00823 00824 // 00825 // Get the protection from the VAD. 00826 // 00827 00828 CapturedOldProtect = 00829 MI_CONVERT_FROM_PTE_PROTECTION(FoundVad->u.VadFlags.Protection); 00830 } 00831 00832 // 00833 // For all the PTEs in the specified address range, set the 00834 // protection depending on the state of the PTE. 00835 // 00836 00837 while (PointerPte <= LastPte) { 00838 00839 if (MiIsPteOnPdeBoundary (PointerPte)) { 00840 00841 PointerPde = MiGetPteAddress (PointerPte); 00842 PointerPpe = MiGetPdeAddress (PointerPte); 00843 00844 #if defined (_WIN64) 00845 MiMakePpeExistAndMakeValid (PointerPpe, Process, FALSE); 00846 if (PointerPde->u.Long == 0) { 00847 UsedPageDirectoryHandle = MI_GET_USED_PTES_HANDLE (PointerPte); 00848 MI_INCREMENT_USED_PTES_BY_HANDLE (UsedPageDirectoryHandle); 00849 } 00850 #endif 00851 00852 MiMakePdeExistAndMakeValid(PointerPde, Process, FALSE); 00853 } 00854 00855 PteContents = *PointerPte; 00856 00857 if (PteContents.u.Long == 0) { 00858 00859 // 00860 // Increment the count of non-zero page table entries 00861 // for this page table and the number of private pages 00862 // for the process. The protection will be set as 00863 // if the PTE was demand zero. 00864 // 00865 00866 UsedPageTableHandle = MI_GET_USED_PTES_HANDLE (MiGetVirtualAddressMappedByPte (PointerPte)); 00867 00868 MI_INCREMENT_USED_PTES_BY_HANDLE (UsedPageTableHandle); 00869 } 00870 00871 if (PteContents.u.Hard.Valid == 1) { 00872 00873 // 00874 // Set the protection into both the PTE and the original PTE 00875 // in the PFN database. 00876 // 00877 00878 Pfn1 = MI_PFN_ELEMENT (PteContents.u.Hard.PageFrameNumber); 00879 00880 if (Pfn1->u3.e1.PrototypePte == 1) { 00881 00882 // 00883 // This PTE refers to a fork prototype PTE, make it 00884 // private. 00885 // 00886 00887 MiCopyOnWrite (MiGetVirtualAddressMappedByPte (PointerPte), 00888 PointerPte); 00889 00890 // 00891 // This may have released the working set mutex and 00892 // the page directory and table pages may no longer be 00893 // in memory. 00894 // 00895 00896 do { 00897 00898 (VOID)MiDoesPpeExistAndMakeValid (MiGetPteAddress (PointerPde), 00899 Process, 00900 FALSE, 00901 &Waited); 00902 00903 Waited = 0; 00904 00905 (VOID)MiDoesPdeExistAndMakeValid (PointerPde, 00906 Process, 00907 FALSE, 00908 &Waited); 00909 00910 } while (Waited != 0); 00911 00912 // 00913 // Do the loop again for the same PTE. 00914 // 00915 00916 continue; 00917 } else { 00918 00919 // 00920 // The PTE is a private page which is valid, if the 00921 // specified protection is no-access or guard page 00922 // remove the PTE from the working set. 00923 // 00924 00925 if ((NewProtect & PAGE_NOACCESS) || 00926 (NewProtect & PAGE_GUARD)) { 00927 00928 // 00929 // Remove the page from the working set. 00930 // 00931 00932 Locked = MiRemovePageFromWorkingSet (PointerPte, 00933 Pfn1, 00934 &Process->Vm); 00935 00936 00937 continue; 00938 } else { 00939 00940 #if PFN_CONSISTENCY 00941 MiSetOriginalPteProtection (Pfn1, ProtectionMask); 00942 #else 00943 Pfn1->OriginalPte.u.Soft.Protection = ProtectionMask; 00944 #endif 00945 MI_MAKE_VALID_PTE (TempPte, 00946 PointerPte->u.Hard.PageFrameNumber, 00947 ProtectionMask, 00948 PointerPte); 00949 00950 WorkingSetIndex = MI_GET_WORKING_SET_FROM_PTE (&PteContents); 00951 MI_SET_PTE_IN_WORKING_SET (&TempPte, WorkingSetIndex); 00952 00953 // 00954 // Flush the TB as we have changed the protection 00955 // of a valid PTE. 00956 // 00957 00958 PreviousPte.u.Flush = MiFlushTbAndCapture (PointerPte, 00959 TempPte.u.Flush, 00960 Pfn1); 00961 } 00962 } 00963 } else { 00964 00965 if (PteContents.u.Soft.Prototype == 1) { 00966 00967 // 00968 // This PTE refers to a fork prototype PTE, make the 00969 // page private. This is accomplished by releasing 00970 // the working set mutex, reading the page thereby 00971 // causing a fault, and re-executing the loop, hopefully, 00972 // this time, we'll find the page present and will 00973 // turn it into a private page. 00974 // 00975 // Note, that a TRY is used to catch guard 00976 // page exceptions and no-access exceptions. 00977 // 00978 00979 Va = MiGetVirtualAddressMappedByPte (PointerPte); 00980 00981 DoAgain = TRUE; 00982 00983 while (PteContents.u.Hard.Valid == 0) { 00984 00985 UNLOCK_WS_UNSAFE (Process); 00986 00987 try { 00988 00989 *(volatile ULONG *)Va; 00990 } except (EXCEPTION_EXECUTE_HANDLER) { 00991 00992 if (GetExceptionCode() == 00993 STATUS_ACCESS_VIOLATION) { 00994 00995 // 00996 // The prototype PTE must be noaccess. 00997 // 00998 00999 DoAgain = MiChangeNoAccessForkPte (PointerPte, 01000 ProtectionMask); 01001 } else if (GetExceptionCode() == 01002 STATUS_IN_PAGE_ERROR) { 01003 // 01004 // Ignore this page and go onto the next one. 01005 // 01006 01007 PointerPte += 1; 01008 DoAgain = TRUE; 01009 01010 if (PointerPte > LastPte) { 01011 LOCK_WS_UNSAFE (Process); 01012 break; 01013 } 01014 } 01015 } 01016 01017 LOCK_WS_UNSAFE (Process); 01018 01019 do { 01020 01021 (VOID)MiDoesPpeExistAndMakeValid (MiGetPteAddress (PointerPde), 01022 Process, 01023 FALSE, 01024 &Waited); 01025 01026 Waited = 0; 01027 01028 (VOID)MiDoesPdeExistAndMakeValid (PointerPde, 01029 Process, 01030 FALSE, 01031 &Waited); 01032 01033 } while (Waited != 0); 01034 01035 PteContents = *(volatile MMPTE *)PointerPte; 01036 } 01037 01038 if (DoAgain) { 01039 continue; 01040 } 01041 01042 } else { 01043 01044 if (PteContents.u.Soft.Transition == 1) { 01045 01046 if (MiSetProtectionOnTransitionPte ( 01047 PointerPte, 01048 ProtectionMask)) { 01049 continue; 01050 } 01051 } else { 01052 01053 // 01054 // Must be page file space or demand zero. 01055 // 01056 01057 PointerPte->u.Soft.Protection = ProtectionMask; 01058 ASSERT (PointerPte->u.Long != 0); 01059 } 01060 } 01061 } 01062 PointerPte += 1; 01063 } //end while 01064 } 01065 01066 // 01067 // Common completion code. 01068 // 01069 01070 #if defined(_MIALT4K_) 01071 01072 if (EmulationFor4kPage == TRUE) { 01073 01074 StartingAddress = StartingAddressFor4k; 01075 01076 EndingAddress = EndingAddressFor4k; 01077 01078 if (CapturedOldProtectFor4k != 0) { 01079 01080 // 01081 // change CapturedOldProtect when CapturedOldProtectFor4k 01082 // contains the true protection for the 4k page 01083 // 01084 01085 CapturedOldProtect = CapturedOldProtectFor4k; 01086 01087 } 01088 } 01089 #endif 01090 01091 *RegionSize = (PCHAR)EndingAddress - (PCHAR)StartingAddress + 1L; 01092 *BaseAddress = StartingAddress; 01093 *LastProtect = CapturedOldProtect; 01094 01095 if (Locked) { 01096 Status = STATUS_WAS_UNLOCKED; 01097 } else { 01098 Status = STATUS_SUCCESS; 01099 } 01100 01101 ErrorFound: 01102 UNLOCK_WS_AND_ADDRESS_SPACE (Process); 01103 01104 ErrorFoundNoWs: 01105 return Status; 01106 }

VOID MiPurgeImageSection IN PCONTROL_AREA  ControlArea,
IN PEPROCESS  Process
 

Definition at line 541 of file umapview.c.

References APC_LEVEL, ASSERT, _SUBSECTION::ControlArea, DbgPrint, FALSE, FreePageList, KeDelayExecutionThread(), KernelMode, LOCK_PFN, MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE, MI_PFN_ELEMENT, MI_SET_PFN_DELETED, MI_WRITE_INVALID_PTE, MiDecrementShareCount(), MiGetSubsectionAddressForPte, MiInsertPageInList(), MiIsPteOnPdeBoundary, MiMakeSystemAddressValidPfnWs(), MiReleasePageFileSpace(), MiUnlinkPageFromList(), MmPageLocationList, MMSECTOR_SHIFT, MmShortTime, NoAccessPte, _SUBSECTION::NumberOfFullSectors, _MMPFN::OriginalPte, PAGE_SIZE, _MMPFN::PteFrame, _SUBSECTION::PtesInSubsection, _SUBSECTION::StartingSector, _SUBSECTION::SubsectionBase, _SUBSECTION::u, _MMPTE::u, _MMPFN::u3, and UNLOCK_PFN.

Referenced by MiCheckControlArea().

00548 : 00549 00550 This function locates subsections within an image section that 00551 contain global memory and resets the global memory back to 00552 the initial subsection contents. 00553 00554 Note, that for this routine to be called the section is not 00555 referenced nor is it mapped in any process. 00556 00557 Arguments: 00558 00559 ControlArea - Supplies a pointer to the control area for the section. 00560 00561 Process - Supplies a pointer to the process IFF the working set mutex 00562 is held, else NULL is supplied. Note that IFF the working set 00563 mutex is held, it must always be acquired unsafe. 00564 00565 Return Value: 00566 00567 None. 00568 00569 Environment: 00570 00571 PFN LOCK held. 00572 00573 --*/ 00574 00575 { 00576 PMMPTE PointerPte; 00577 PMMPTE LastPte; 00578 PMMPFN Pfn1; 00579 MMPTE PteContents; 00580 MMPTE NewContents; 00581 MMPTE NewContentsDemandZero; 00582 KIRQL OldIrql = APC_LEVEL; 00583 ULONG i; 00584 ULONG SizeOfRawData; 00585 ULONG OffsetIntoSubsection; 00586 PSUBSECTION Subsection; 00587 #if DBG 00588 ULONG DelayCount = 0; 00589 #endif //DBG 00590 00591 ASSERT (ControlArea->u.Flags.Image != 0); 00592 00593 i = ControlArea->NumberOfSubsections; 00594 00595 if (ControlArea->u.Flags.GlobalOnlyPerSession == 0) { 00596 Subsection = (PSUBSECTION)(ControlArea + 1); 00597 } 00598 else { 00599 Subsection = (PSUBSECTION)((PLARGE_CONTROL_AREA)ControlArea + 1); 00600 } 00601 00602 // 00603 // Loop through all the subsections 00604 00605 while (i > 0) { 00606 00607 if (Subsection->u.SubsectionFlags.GlobalMemory == 1) { 00608 00609 NewContents.u.Long = 0; 00610 NewContentsDemandZero.u.Long = 0; 00611 SizeOfRawData = 0; 00612 OffsetIntoSubsection = 0; 00613 00614 // 00615 // Purge this section. 00616 // 00617 00618 if (Subsection->StartingSector != 0) { 00619 00620 // 00621 // This is not a demand zero section. 00622 // 00623 00624 NewContents.u.Long = MiGetSubsectionAddressForPte(Subsection); 00625 NewContents.u.Soft.Prototype = 1; 00626 00627 SizeOfRawData = (Subsection->NumberOfFullSectors << MMSECTOR_SHIFT) | 00628 Subsection->u.SubsectionFlags.SectorEndOffset; 00629 } 00630 00631 NewContents.u.Soft.Protection = 00632 Subsection->u.SubsectionFlags.Protection; 00633 NewContentsDemandZero.u.Soft.Protection = 00634 NewContents.u.Soft.Protection; 00635 00636 PointerPte = Subsection->SubsectionBase; 00637 LastPte = &Subsection->SubsectionBase[Subsection->PtesInSubsection]; 00638 ControlArea = Subsection->ControlArea; 00639 00640 // 00641 // The WS lock may be released and reacquired and our callers 00642 // always acquire it unsafe. 00643 // 00644 00645 MiMakeSystemAddressValidPfnWs (PointerPte, Process); 00646 00647 while (PointerPte < LastPte) { 00648 00649 if (MiIsPteOnPdeBoundary(PointerPte)) { 00650 00651 // 00652 // We are on a page boundary, make sure this PTE is resident. 00653 // 00654 00655 MiMakeSystemAddressValidPfnWs (PointerPte, Process); 00656 } 00657 00658 PteContents = *PointerPte; 00659 if (PteContents.u.Long == 0) { 00660 00661 // 00662 // No more valid PTEs to deal with. 00663 // 00664 00665 break; 00666 } 00667 00668 ASSERT (PteContents.u.Hard.Valid == 0); 00669 00670 if ((PteContents.u.Soft.Prototype == 0) && 00671 (PteContents.u.Soft.Transition == 1)) { 00672 00673 // 00674 // The prototype PTE is in transition format. 00675 // 00676 00677 Pfn1 = MI_PFN_ELEMENT (PteContents.u.Trans.PageFrameNumber); 00678 00679 // 00680 // If the prototype PTE is no longer pointing to 00681 // the original image page (not in protopte format), 00682 // or has been modified, remove it from memory. 00683 // 00684 00685 if ((Pfn1->u3.e1.Modified == 1) || 00686 (Pfn1->OriginalPte.u.Soft.Prototype == 0)) { 00687 ASSERT (Pfn1->OriginalPte.u.Hard.Valid == 0); 00688 00689 // 00690 // This is a transition PTE which has been 00691 // modified or is no longer in protopte format. 00692 // 00693 00694 if (Pfn1->u3.e2.ReferenceCount != 0) { 00695 00696 // 00697 // There must be an I/O in progress on this 00698 // page. Wait for the I/O operation to complete. 00699 // 00700 00701 UNLOCK_PFN (OldIrql); 00702 00703 KeDelayExecutionThread (KernelMode, FALSE, &MmShortTime); 00704 00705 // 00706 // Redo the loop. 00707 // 00708 #if DBG 00709 if ((DelayCount % 1024) == 0) { 00710 DbgPrint("MMFLUSHSEC: waiting for i/o to complete PFN %lx\n", 00711 Pfn1); 00712 } 00713 DelayCount += 1; 00714 #endif //DBG 00715 00716 LOCK_PFN (OldIrql); 00717 00718 MiMakeSystemAddressValidPfnWs (PointerPte, Process); 00719 continue; 00720 } 00721 00722 ASSERT (!((Pfn1->OriginalPte.u.Soft.Prototype == 0) && 00723 (Pfn1->OriginalPte.u.Soft.Transition == 1))); 00724 00725 MI_WRITE_INVALID_PTE (PointerPte, Pfn1->OriginalPte); 00726 ASSERT (Pfn1->OriginalPte.u.Hard.Valid == 0); 00727 00728 // 00729 // Only reduce the number of PFN references if 00730 // the original PTE is still in prototype PTE 00731 // format. 00732 // 00733 00734 if (Pfn1->OriginalPte.u.Soft.Prototype == 1) { 00735 ControlArea->NumberOfPfnReferences -= 1; 00736 ASSERT ((LONG)ControlArea->NumberOfPfnReferences >= 0); 00737 } 00738 MiUnlinkPageFromList (Pfn1); 00739 00740 MI_SET_PFN_DELETED (Pfn1); 00741 00742 MiDecrementShareCount (Pfn1->PteFrame); 00743 00744 // 00745 // If the reference count for the page is zero, insert 00746 // it into the free page list, otherwise leave it alone 00747 // and when the reference count is decremented to zero 00748 // the page will go to the free list. 00749 // 00750 00751 if (Pfn1->u3.e2.ReferenceCount == 0) { 00752 MiReleasePageFileSpace (Pfn1->OriginalPte); 00753 MiInsertPageInList (MmPageLocationList[FreePageList], 00754 MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE (&PteContents)); 00755 } 00756 00757 MI_WRITE_INVALID_PTE (PointerPte, NewContents); 00758 } 00759 } else { 00760 00761 // 00762 // Prototype PTE is not in transition format. 00763 // 00764 00765 if (PteContents.u.Soft.Prototype == 0) { 00766 00767 // 00768 // This refers to a page in the paging file, 00769 // as it no longer references the image, 00770 // restore the PTE contents to what they were 00771 // at the initial image creation. 00772 // 00773 00774 if (PteContents.u.Long != NoAccessPte.u.Long) { 00775 MiReleasePageFileSpace (PteContents); 00776 MI_WRITE_INVALID_PTE (PointerPte, NewContents); 00777 } 00778 } 00779 } 00780 PointerPte += 1; 00781 OffsetIntoSubsection += PAGE_SIZE; 00782 00783 if (OffsetIntoSubsection >= SizeOfRawData) { 00784 00785 // 00786 // There are trailing demand zero pages in this 00787 // subsection, set the PTE contents to be demand 00788 // zero for the remainder of the PTEs in this 00789 // subsection. 00790 // 00791 00792 NewContents = NewContentsDemandZero; 00793 } 00794 00795 #if DBG 00796 DelayCount = 0; 00797 #endif //DBG 00798 00799 } //end while 00800 } 00801 00802 i -=1; 00803 Subsection += 1; 00804 } 00805 00806 return; 00807 } }

VOID MiPurgeSubsectionInternal IN PSUBSECTION  Subsection,
IN ULONG  PteOffset
 

ULONG FASTCALL MiReleasePageFileSpace IN MMPTE  PteContents  ) 
 

Definition at line 1014 of file deleteva.c.

References ASSERT, _MMPAGING_FILE::CurrentUsage, FALSE, _MMPAGING_FILE::FreeSpace, GET_PAGING_FILE_NUMBER, GET_PAGING_FILE_OFFSET, MiUpdateModifiedWriterMdls(), MM_PFN_LOCK_ASSERT, MM_USABLE_PAGES_FREE, MmNumberOfActiveMdlEntries, MmPagingFile, MmPagingFileDebug, RtlClearBits(), and TRUE.

Referenced by MiCleanSection(), MiCompleteProtoPteFault(), MiCopyOnWrite(), MiDecommitPages(), MiDecrementCloneBlockReference(), MiDecrementReferenceCount(), MiDeletePte(), MiDeleteSystemPagableVm(), MiMakeOutswappedPageResident(), MiPurgeImageSection(), MiResetVirtualMemory(), MiSegmentDelete(), MiSetDirtyBit(), MiSetModifyBit(), MiSetPageModified(), MiWriteComplete(), MmPurgeSection(), MmSetAddressRangeModified(), and MmUnlockPages().

01020 : 01021 01022 This routine frees the paging file allocated to the specified PTE 01023 and adjusts the necessary quotas. 01024 01025 Arguments: 01026 01027 PteContents - Supplies the PTE which is in page file format. 01028 01029 Return Value: 01030 01031 Returns TRUE if any paging file space was deallocated. 01032 01033 Environment: 01034 01035 Kernel mode, APCs disabled, PFN lock held. 01036 01037 --*/ 01038 01039 { 01040 ULONG FreeBit; 01041 ULONG PageFileNumber; 01042 01043 MM_PFN_LOCK_ASSERT(); 01044 01045 if (PteContents.u.Soft.Prototype == 1) { 01046 01047 // 01048 // Not in page file format. 01049 // 01050 01051 return FALSE; 01052 } 01053 01054 FreeBit = GET_PAGING_FILE_OFFSET (PteContents); 01055 01056 if ((FreeBit == 0) || (FreeBit == 0xFFFFF)) { 01057 01058 // 01059 // Page is not in a paging file, just return. 01060 // 01061 01062 return FALSE; 01063 } 01064 01065 PageFileNumber = GET_PAGING_FILE_NUMBER (PteContents); 01066 01067 ASSERT (RtlCheckBit( MmPagingFile[PageFileNumber]->Bitmap, FreeBit) == 1); 01068 01069 #if DBG 01070 if ((FreeBit < 8192) && (PageFileNumber == 0)) { 01071 ASSERT ((MmPagingFileDebug[FreeBit] & 1) != 0); 01072 MmPagingFileDebug[FreeBit] ^= 1; 01073 } 01074 #endif //DBG 01075 01076 RtlClearBits ( MmPagingFile[PageFileNumber]->Bitmap, FreeBit, 1); 01077 01078 MmPagingFile[PageFileNumber]->FreeSpace += 1; 01079 MmPagingFile[PageFileNumber]->CurrentUsage -= 1; 01080 01081 // 01082 // Check to see if we should move some MDL entries for the 01083 // modified page writer now that more free space is available. 01084 // 01085 01086 if ((MmNumberOfActiveMdlEntries == 0) || 01087 (MmPagingFile[PageFileNumber]->FreeSpace == MM_USABLE_PAGES_FREE)) { 01088 01089 MiUpdateModifiedWriterMdls (PageFileNumber); 01090 } 01091 01092 return TRUE; 01093 }

VOID MiReleaseSystemPtes IN PMMPTE  StartingPte,
IN ULONG  NumberOfPtes,
IN MMSYSTEM_PTE_POOL_TYPE  SystemPteType
 

Definition at line 1354 of file sysptes.c.

References ASSERT, _MMPTE_FLUSH_LIST::Count, DbgPrint, DISPATCH_LEVEL, _MMPTE_FLUSH_LIST::FlushPte, _MMPTE_FLUSH_LIST::FlushVa, Index, KeBugCheckEx(), KeFlushEntireTb(), KeLowerIrql(), KeRaiseIrql(), MiCountFreeSystemPtes(), MiDumpSystemPtes(), MiFillMemoryPte, MiFlushPteList(), MiGetVirtualAddressMappedByPte, MiLockSystemSpace, MiUnlockSystemSpace, MM_DBG_SYS_PTES, MM_EMPTY_PTE_LIST, MM_KERNEL_NOACCESS_PTE, MM_MAX_SYSPTE_FREE, MM_MAXIMUM_FLUSH_COUNT, MM_MIN_SYSPTE_FREE, MM_PTE_TABLE_LIMIT, MmFirstFreeSystemPte, MmFlushCounter, MmFlushPte1, MmFreeSysPteListBySize, MmLastSysPteListBySize, MmSysPteIndex, MmSysPteListBySizeCount, MmSysPteMinimumFree, MmSysPteTables, MmSystemPteBase, MmSystemPtesEnd, MmSystemPtesStart, MmTotalFreeSystemPtes, NULL, PAGE_SIZE, Size, SystemPteSpace, TRUE, _MMPTE::u, and ZeroKernelPte.

Referenced by ExFreePool(), MiAddSystemPtes(), MiDereferenceSession(), MiFeedSysPtePool(), MiFreeNonPagedPool(), MiInitializeSystemPtes(), MiLoadImageSection(), MiReloadBootLoadedDrivers(), MiSessionCreateInternal(), MiUnmapSinglePage(), MmAllocateIndependentPages(), MmAllocateNonCachedMemory(), MmDeleteKernelStack(), MmFreeNonCachedMemory(), MmMapIoSpace(), MmMapLockedPagesSpecifyCache(), MmMapVideoDisplay(), MmUnloadSystemImage(), MmUnmapIoSpace(), MmUnmapLockedPages(), and MmUnmapVideoDisplay().

01362 : 01363 01364 This function releases the specified number of PTEs 01365 within the non paged portion of system space. 01366 01367 Note that the PTEs must be invalid and the page frame number 01368 must have been set to zero. 01369 01370 Arguments: 01371 01372 StartingPte - Supplies the address of the first PTE to release. 01373 01374 NumberOfPtes - Supplies the number of PTEs to release. 01375 01376 SystemPtePoolType - Supplies the PTE type of the pool to release PTEs to, 01377 one of SystemPteSpace or NonPagedPoolExpansion. 01378 01379 Return Value: 01380 01381 none. 01382 01383 Environment: 01384 01385 Kernel mode. 01386 01387 --*/ 01388 01389 { 01390 ULONG_PTR Size; 01391 ULONG i; 01392 ULONG_PTR PteOffset; 01393 PMMPTE PointerPte; 01394 PMMPTE PointerFollowingPte; 01395 PMMPTE NextPte; 01396 KIRQL OldIrql; 01397 ULONG Index; 01398 #if defined(_IA64_) 01399 MMPTE_FLUSH_LIST PteFlushList; 01400 PMMPTE Previous; 01401 PVOID BaseAddress; 01402 #endif 01403 01404 // 01405 // Check to make sure the PTEs don't map anything. 01406 // 01407 01408 ASSERT (NumberOfPtes != 0); 01409 01410 #ifdef _MI_GUARD_PTE_ 01411 if (NumberOfPtes == 0) { 01412 KeBugCheckEx (SYSTEM_PTE_MISUSE, 01413 0xD, 01414 (ULONG_PTR)StartingPte, 01415 NumberOfPtes, 01416 SystemPtePoolType); 01417 } 01418 01419 if (SystemPtePoolType == SystemPteSpace) { 01420 if ((StartingPte + NumberOfPtes)->u.Long != MM_KERNEL_NOACCESS_PTE) { 01421 KeBugCheckEx (SYSTEM_PTE_MISUSE, 01422 0xE, 01423 (ULONG_PTR)StartingPte, 01424 NumberOfPtes, 01425 SystemPtePoolType); 01426 } 01427 NumberOfPtes += 1; 01428 } 01429 #endif 01430 01431 #if DBG 01432 if (StartingPte < MmSystemPtesStart[SystemPtePoolType]) { 01433 KeBugCheckEx (SYSTEM_PTE_MISUSE, 01434 0xF, 01435 (ULONG_PTR)StartingPte, 01436 NumberOfPtes, 01437 SystemPtePoolType); 01438 } 01439 01440 if (StartingPte > MmSystemPtesEnd[SystemPtePoolType]) { 01441 KeBugCheckEx (SYSTEM_PTE_MISUSE, 01442 0x10, 01443 (ULONG_PTR)StartingPte, 01444 NumberOfPtes, 01445 SystemPtePoolType); 01446 } 01447 #endif //DBG 01448 01449 #if 0 01450 if (MmDebug & MM_DBG_SYS_PTES) { 01451 DbgPrint("releasing 0x%lx system PTEs at location %lx\n",NumberOfPtes,StartingPte); 01452 } 01453 #endif //0 01454 01455 #if defined(_IA64_) 01456 01457 PteFlushList.Count = 0; 01458 Previous = StartingPte; 01459 BaseAddress = MiGetVirtualAddressMappedByPte (Previous); 01460 for (i = 0; i < NumberOfPtes ; i++) { 01461 if (PteFlushList.Count != MM_MAXIMUM_FLUSH_COUNT) { 01462 PteFlushList.FlushPte[PteFlushList.Count] = Previous; 01463 PteFlushList.FlushVa[PteFlushList.Count] = BaseAddress; 01464 PteFlushList.Count += 1; 01465 } 01466 *Previous = ZeroKernelPte; 01467 BaseAddress = (PVOID)((PCHAR)BaseAddress + PAGE_SIZE); 01468 Previous++; 01469 } 01470 01471 KeRaiseIrql (DISPATCH_LEVEL, &OldIrql); 01472 MiFlushPteList (&PteFlushList, TRUE, ZeroKernelPte); 01473 KeLowerIrql (OldIrql); 01474 01475 #else 01476 01477 // 01478 // Zero PTEs. 01479 // 01480 01481 #ifdef _MI_SYSPTE_DEBUG_ 01482 MiValidateSystemPtes (StartingPte, NumberOfPtes); 01483 #endif 01484 01485 MiFillMemoryPte (StartingPte, 01486 NumberOfPtes * sizeof (MMPTE), 01487 ZeroKernelPte.u.Long); 01488 01489 #ifdef _MI_SYSPTE_DEBUG_ 01490 01491 // 01492 // Invalidate any TB entries that might have been mapped to 01493 // immediately prevent bad callers from corrupting the system. 01494 // 01495 01496 KeFlushEntireTb (TRUE, TRUE); 01497 #endif 01498 01499 #endif 01500 01501 // 01502 // Acquire system space spin lock to synchronize access. 01503 // 01504 01505 PteOffset = (ULONG_PTR)(StartingPte - MmSystemPteBase); 01506 01507 #ifdef _MI_SYSPTE_DEBUG_ 01508 if (PteOffset == 0) { 01509 KeBugCheckEx (SYSTEM_PTE_MISUSE, 01510 0x11, 01511 (ULONG_PTR)StartingPte, 01512 NumberOfPtes, 01513 SystemPtePoolType); 01514 } 01515 #endif 01516 01517 MiLockSystemSpace(OldIrql); 01518 01519 #ifdef _MI_SYSPTE_DEBUG_ 01520 MiCheckPteRelease (StartingPte, NumberOfPtes); 01521 #endif 01522 01523 #ifndef _MI_GUARD_PTE_ 01524 if ((SystemPtePoolType == SystemPteSpace) && 01525 (NumberOfPtes <= MM_PTE_TABLE_LIMIT)) { 01526 01527 Index = MmSysPteTables [NumberOfPtes]; 01528 NumberOfPtes = MmSysPteIndex [Index]; 01529 01530 if (MmTotalFreeSystemPtes[SystemPteSpace] >= MM_MIN_SYSPTE_FREE) { 01531 01532 // 01533 // Don't add to the pool if the size is greater than 15 + the minimum. 01534 // 01535 01536 i = MmSysPteMinimumFree[Index]; 01537 if (MmTotalFreeSystemPtes[SystemPteSpace] >= MM_MAX_SYSPTE_FREE) { 01538 01539 // 01540 // Lots of free PTEs, quadruple the limit. 01541 // 01542 01543 i = i * 4; 01544 } 01545 i += 15; 01546 if (MmSysPteListBySizeCount[Index] <= i) { 01547 01548 #if DBG 01549 if (MmDebug & MM_DBG_SYS_PTES) { 01550 PMMPTE PointerPte1; 01551 01552 PointerPte1 = &MmFreeSysPteListBySize[Index]; 01553 while (PointerPte1->u.List.NextEntry != MM_EMPTY_PTE_LIST) { 01554 PMMPTE PointerFreedPte; 01555 ULONG j; 01556 01557 PointerPte1 = MmSystemPteBase + PointerPte1->u.List.NextEntry; 01558 PointerFreedPte = PointerPte1; 01559 for (j = 0; j < MmSysPteIndex[Index]; j++) { 01560 ASSERT (PointerFreedPte->u.Hard.Valid == 0); 01561 PointerFreedPte++; 01562 } 01563 } 01564 } 01565 #endif //DBG 01566 MmSysPteListBySizeCount [Index] += 1; 01567 PointerPte = MmLastSysPteListBySize[Index]; 01568 ASSERT (PointerPte->u.List.NextEntry == MM_EMPTY_PTE_LIST); 01569 PointerPte->u.List.NextEntry = PteOffset; 01570 MmLastSysPteListBySize[Index] = StartingPte; 01571 StartingPte->u.List.NextEntry = MM_EMPTY_PTE_LIST; 01572 01573 #if DBG 01574 if (MmDebug & MM_DBG_SYS_PTES) { 01575 PMMPTE PointerPte1; 01576 PointerPte1 = &MmFreeSysPteListBySize[Index]; 01577 while (PointerPte1->u.List.NextEntry != MM_EMPTY_PTE_LIST) { 01578 PMMPTE PointerFreedPte; 01579 ULONG j; 01580 01581 PointerPte1 = MmSystemPteBase + PointerPte1->u.List.NextEntry; 01582 PointerFreedPte = PointerPte1; 01583 for (j = 0; j < MmSysPteIndex[Index]; j++) { 01584 ASSERT (PointerFreedPte->u.Hard.Valid == 0); 01585 PointerFreedPte++; 01586 } 01587 } 01588 } 01589 #endif //DBG 01590 if (NumberOfPtes == 1) { 01591 if (MmFlushPte1 == NULL) { 01592 MmFlushPte1 = StartingPte; 01593 } 01594 } else { 01595 (StartingPte + 1)->u.List.NextEntry = MmFlushCounter; 01596 } 01597 01598 MiUnlockSystemSpace(OldIrql); 01599 return; 01600 } 01601 } 01602 } 01603 #endif 01604 01605 MmTotalFreeSystemPtes[SystemPtePoolType] += NumberOfPtes; 01606 01607 PteOffset = (ULONG_PTR)(StartingPte - MmSystemPteBase); 01608 PointerPte = &MmFirstFreeSystemPte[SystemPtePoolType]; 01609 01610 while (TRUE) { 01611 NextPte = MmSystemPteBase + PointerPte->u.List.NextEntry; 01612 if (PteOffset < PointerPte->u.List.NextEntry) { 01613 01614 // 01615 // Insert in the list at this point. The 01616 // previous one should point to the new freed set and 01617 // the new freed set should point to the place 01618 // the previous set points to. 01619 // 01620 // Attempt to combine the clusters before we 01621 // insert. 01622 // 01623 // Locate the end of the current structure. 01624 // 01625 01626 ASSERT (((StartingPte + NumberOfPtes) <= NextPte) || 01627 (PointerPte->u.List.NextEntry == MM_EMPTY_PTE_LIST)); 01628 01629 PointerFollowingPte = PointerPte + 1; 01630 if (PointerPte->u.List.OneEntry) { 01631 Size = 1; 01632 } else { 01633 Size = (ULONG_PTR) PointerFollowingPte->u.List.NextEntry; 01634 } 01635 if ((PointerPte + Size) == StartingPte) { 01636 01637 // 01638 // We can combine the clusters. 01639 // 01640 01641 NumberOfPtes += (ULONG)Size; 01642 PointerFollowingPte->u.List.NextEntry = NumberOfPtes; 01643 PointerPte->u.List.OneEntry = 0; 01644 01645 // 01646 // Point the starting PTE to the beginning of 01647 // the new free set and try to combine with the 01648 // following free cluster. 01649 // 01650 01651 StartingPte = PointerPte; 01652 01653 } else { 01654 01655 // 01656 // Can't combine with previous. Make this Pte the 01657 // start of a cluster. 01658 // 01659 01660 // 01661 // Point this cluster to the next cluster. 01662 // 01663 01664 StartingPte->u.List.NextEntry = PointerPte->u.List.NextEntry; 01665 01666 // 01667 // Point the current cluster to this cluster. 01668 // 01669 01670 PointerPte->u.List.NextEntry = PteOffset; 01671 01672 // 01673 // Set the size of this cluster. 01674 // 01675 01676 if (NumberOfPtes == 1) { 01677 StartingPte->u.List.OneEntry = 1; 01678 01679 } else { 01680 StartingPte->u.List.OneEntry = 0; 01681 PointerFollowingPte = StartingPte + 1; 01682 PointerFollowingPte->u.List.NextEntry = NumberOfPtes; 01683 } 01684 } 01685 01686 // 01687 // Attempt to combine the newly created cluster with 01688 // the following cluster. 01689 // 01690 01691 if ((StartingPte + NumberOfPtes) == NextPte) { 01692 01693 // 01694 // Combine with following cluster. 01695 // 01696 01697 // 01698 // Set the next cluster to the value contained in the 01699 // cluster we are merging into this one. 01700 // 01701 01702 StartingPte->u.List.NextEntry = NextPte->u.List.NextEntry; 01703 StartingPte->u.List.OneEntry = 0; 01704 PointerFollowingPte = StartingPte + 1; 01705 01706 if (NextPte->u.List.OneEntry) { 01707 Size = 1; 01708 01709 } else { 01710 NextPte++; 01711 Size = (ULONG_PTR) NextPte->u.List.NextEntry; 01712 } 01713 PointerFollowingPte->u.List.NextEntry = NumberOfPtes + Size; 01714 } 01715 #if 0 01716 if (MmDebug & MM_DBG_SYS_PTES) { 01717 MiDumpSystemPtes(SystemPtePoolType); 01718 } 01719 #endif //0 01720 01721 #if DBG 01722 if (MmDebug & MM_DBG_SYS_PTES) { 01723 ASSERT (MmTotalFreeSystemPtes[SystemPtePoolType] == 01724 MiCountFreeSystemPtes (SystemPtePoolType)); 01725 } 01726 #endif //DBG 01727 MiUnlockSystemSpace(OldIrql); 01728 return; 01729 } 01730 01731 // 01732 // Point to next freed cluster. 01733 // 01734 01735 PointerPte = NextPte; 01736 } 01737 }

VOID MiReleaseWsle IN WSLE_NUMBER  WorkingSetIndex,
IN PMMSUPPORT  WsInfo
 

Definition at line 1016 of file wslist.c.

References ASSERT, _MMWSL::FirstFree, _MMWSL::LastInitializedWsle, MM_FREE_WSLE_SHIFT, MM_SYSTEM_WS_LOCK_ASSERT, MmPagesAboveWsMinimum, MmSystemCacheWs, _MMWSLE::u1, _MMWSL::Wsle, and WSLE_NULL_INDEX.

Referenced by MiDecommitPages(), MiDeleteAddressesInWorkingSet(), MiDeletePte(), MiDeleteSystemPagableVm(), MiLockCode(), MiRemoveMappedPtes(), MiRemovePageFromWorkingSet(), and MmUnmapViewInSystemCache().

01023 : 01024 01025 This function releases a previously reserved working set entry to 01026 be reused. A release occurs when a page fault is retried due to 01027 changes in PTEs and working sets during an I/O operation. 01028 01029 Arguments: 01030 01031 WorkingSetIndex - Supplies the index of the working set entry to 01032 release. 01033 01034 Return Value: 01035 01036 None. 01037 01038 Environment: 01039 01040 Kernel mode, APCs disabled, working set lock held and PFN lock held. 01041 01042 --*/ 01043 01044 { 01045 PMMWSL WorkingSetList; 01046 PMMWSLE Wsle; 01047 01048 WorkingSetList = WsInfo->VmWorkingSetList; 01049 Wsle = WorkingSetList->Wsle; 01050 #if DBG 01051 if (WsInfo == &MmSystemCacheWs) { 01052 MM_SYSTEM_WS_LOCK_ASSERT(); 01053 } 01054 #endif //DBG 01055 01056 ASSERT (WorkingSetIndex <= WorkingSetList->LastInitializedWsle); 01057 01058 // 01059 // Put the entry on the free list and decrement the current 01060 // size. 01061 // 01062 01063 ASSERT ((WorkingSetList->FirstFree <= WorkingSetList->LastInitializedWsle) || 01064 (WorkingSetList->FirstFree == WSLE_NULL_INDEX)); 01065 Wsle[WorkingSetIndex].u1.Long = WorkingSetList->FirstFree << MM_FREE_WSLE_SHIFT; 01066 WorkingSetList->FirstFree = WorkingSetIndex; 01067 ASSERT ((WorkingSetList->FirstFree <= WorkingSetList->LastInitializedWsle) || 01068 (WorkingSetList->FirstFree == WSLE_NULL_INDEX)); 01069 if (WsInfo->WorkingSetSize > WsInfo->MinimumWorkingSetSize) { 01070 MmPagesAboveWsMinimum -= 1; 01071 } 01072 WsInfo->WorkingSetSize -= 1; 01073 return; 01074 01075 }

VOID MiReloadBootLoadedDrivers IN PLOADER_PARAMETER_BLOCK  LoaderBlock  ) 
 

Definition at line 5956 of file sysload.c.

References ASSERT, DbgPrint, FALSE, InitializationPhase, LdrDoubleRelocateImage(), LdrRelocateImage(), LOCK_PFN, MI_GET_PAGE_COLOR_FROM_PTE, MI_GET_PAGE_FRAME_FROM_PTE, MI_MAKE_VALID_PTE, MI_PFN_ELEMENT, MI_SET_ACCESSED_IN_PTE, MI_SET_PFN_DELETED, MI_SET_PTE_DIRTY, MI_WRITE_VALID_PTE, MiDecrementShareAndValidCount, MiDecrementShareCountOnly, MiEnsureAvailablePageOrWait(), MiGetPteAddress, MiGetVirtualAddressMappedByPte, MiInitializePfn(), MiNoLowMemory, MiReleaseSystemPtes(), MiRemoveAnyPage(), MiRemoveLowPages(), MiReserveSystemPtes(), MiUpdateThunks(), MM_EXECUTE_READWRITE, MmMakeLowMemory, NT_SUCCESS, NTSTATUS(), NULL, PAGE_SHIFT, PAGE_SIZE, _MMPFN::PteAddress, _MMPFN::PteFrame, ROUND_TO_PAGES, RtlImageNtHeader(), Status, SystemPteSpace, TRUE, _MMPTE::u, _MMPFN::u1, _MMPFN::u2, _MMPFN::u3, UNLOCK_PFN, and ZeroPte.

Referenced by MmInitSystem().

05962 : 05963 05964 The kernel, HAL and boot drivers are relocated by the loader. 05965 All the boot drivers are then relocated again here. 05966 05967 This function relocates osloader-loaded images into system PTEs. This 05968 gives these images the benefits that all other drivers already enjoy, 05969 including : 05970 05971 1. Paging of the drivers (this is more than 500K today). 05972 2. Write-protection of their text sections. 05973 3. Automatic unload of drivers on last dereference. 05974 05975 Note care must be taken when processing HIGHADJ relocations more than once. 05976 05977 Arguments: 05978 05979 LoaderBlock - Supplies a pointer to the system loader block. 05980 05981 Return Value: 05982 05983 None. 05984 05985 Environment: 05986 05987 Kernel mode, Phase 0 Initialization. 05988 05989 --*/ 05990 05991 { 05992 PLDR_DATA_TABLE_ENTRY DataTableEntry; 05993 PLIST_ENTRY NextEntry; 05994 PIMAGE_NT_HEADERS NtHeader; 05995 PIMAGE_DATA_DIRECTORY DataDirectory; 05996 ULONG_PTR i; 05997 ULONG NumberOfPtes; 05998 ULONG NumberOfLoaderPtes; 05999 PMMPTE PointerPte; 06000 PMMPTE LastPte; 06001 PMMPTE LoaderPte; 06002 MMPTE PteContents; 06003 MMPTE TempPte; 06004 PVOID LoaderImageAddress; 06005 PVOID NewImageAddress; 06006 NTSTATUS Status; 06007 PFN_NUMBER PageFrameIndex; 06008 PFN_NUMBER PteFramePage; 06009 PMMPTE PteFramePointer; 06010 PMMPFN Pfn1; 06011 PMMPFN Pfn2; 06012 KIRQL OldIrql; 06013 PCHAR RelocatedVa; 06014 PCHAR NonRelocatedVa; 06015 LOGICAL StopMoving; 06016 06017 #if !defined (_X86_) 06018 06019 // 06020 // Non-x86 platforms have map registers so no memory shuffling is needed. 06021 // 06022 06023 MmMakeLowMemory = FALSE; 06024 #endif 06025 StopMoving = FALSE; 06026 06027 i = 0; 06028 NextEntry = LoaderBlock->LoadOrderListHead.Flink; 06029 06030 for ( ; NextEntry != &LoaderBlock->LoadOrderListHead; NextEntry = NextEntry->Flink) { 06031 06032 // 06033 // Skip the kernel and the HAL. Note their relocation sections will 06034 // be automatically reclaimed. 06035 // 06036 06037 i += 1; 06038 if (i <= 2) { 06039 continue; 06040 } 06041 06042 DataTableEntry = CONTAINING_RECORD(NextEntry, 06043 LDR_DATA_TABLE_ENTRY, 06044 InLoadOrderLinks); 06045 06046 // 06047 // Ensure that the relocation section exists and that the loader 06048 // hasn't freed it already. 06049 // 06050 06051 NtHeader = RtlImageNtHeader(DataTableEntry->DllBase); 06052 06053 if (NtHeader == NULL) { 06054 continue; 06055 } 06056 06057 if (IMAGE_DIRECTORY_ENTRY_BASERELOC >= NtHeader->OptionalHeader.NumberOfRvaAndSizes) { 06058 continue; 06059 } 06060 06061 DataDirectory = &NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC]; 06062 06063 if (DataDirectory->VirtualAddress == 0) { 06064 continue; 06065 } 06066 06067 if (DataDirectory->VirtualAddress + DataDirectory->Size > DataTableEntry->SizeOfImage) { 06068 06069 // 06070 // The relocation section has already been freed, the user must 06071 // be using an old loader that didn't save the relocations. 06072 // 06073 06074 continue; 06075 } 06076 06077 LoaderImageAddress = DataTableEntry->DllBase; 06078 LoaderPte = MiGetPteAddress(DataTableEntry->DllBase); 06079 NumberOfLoaderPtes = (ULONG)((ROUND_TO_PAGES(DataTableEntry->SizeOfImage)) >> PAGE_SHIFT); 06080 06081 LOCK_PFN (OldIrql); 06082 06083 PointerPte = LoaderPte; 06084 LastPte = PointerPte + NumberOfLoaderPtes; 06085 06086 while (PointerPte < LastPte) { 06087 ASSERT (PointerPte->u.Hard.Valid == 1); 06088 PageFrameIndex = MI_GET_PAGE_FRAME_FROM_PTE (PointerPte); 06089 Pfn1 = MI_PFN_ELEMENT (PageFrameIndex); 06090 06091 // 06092 // Mark the page as modified so boot drivers that call 06093 // MmPageEntireDriver don't lose their unmodified data ! 06094 // 06095 06096 Pfn1->u3.e1.Modified = 1; 06097 PointerPte += 1; 06098 } 06099 06100 UNLOCK_PFN (OldIrql); 06101 06102 // 06103 // Extra PTEs are allocated here to map the relocation section at the 06104 // new address so the image can be relocated. 06105 // 06106 06107 NumberOfPtes = NumberOfLoaderPtes; 06108 06109 PointerPte = MiReserveSystemPtes (NumberOfPtes, 06110 SystemPteSpace, 06111 0, 06112 0, 06113 FALSE); 06114 06115 if (PointerPte == NULL) { 06116 continue; 06117 } 06118 06119 LastPte = PointerPte + NumberOfPtes; 06120 06121 NewImageAddress = MiGetVirtualAddressMappedByPte (PointerPte); 06122 06123 #if DBG_SYSLOAD 06124 DbgPrint ("Relocating %wZ from %p to %p, %x bytes\n", 06125 &DataTableEntry->FullDllName, 06126 DataTableEntry->DllBase, 06127 NewImageAddress, 06128 DataTableEntry->SizeOfImage 06129 ); 06130 #endif 06131 06132 // 06133 // This assert is important because the assumption is made that PTEs 06134 // (not superpages) are mapping these drivers. 06135 // 06136 06137 ASSERT (InitializationPhase == 0); 06138 06139 // 06140 // If the system is configured to make low memory available for ISA 06141 // type drivers, then copy the boot loaded drivers now. Otherwise 06142 // only PTE adjustment is done. Presumably some day when ISA goes 06143 // away this code can be removed. 06144 // 06145 06146 RelocatedVa = NewImageAddress; 06147 NonRelocatedVa = (PCHAR) DataTableEntry->DllBase; 06148 06149 while (PointerPte < LastPte) { 06150 06151 PteContents = *LoaderPte; 06152 ASSERT (PteContents.u.Hard.Valid == 1); 06153 06154 if (MmMakeLowMemory == TRUE) { 06155 #if DBG 06156 PageFrameIndex = MI_GET_PAGE_FRAME_FROM_PTE (LoaderPte); 06157 Pfn1 = MI_PFN_ELEMENT (PageFrameIndex); 06158 ASSERT (Pfn1->u1.WsIndex == 0); 06159 #endif 06160 LOCK_PFN (OldIrql); 06161 MiEnsureAvailablePageOrWait (NULL, NULL); 06162 PageFrameIndex = MiRemoveAnyPage( 06163 MI_GET_PAGE_COLOR_FROM_PTE (PointerPte)); 06164 06165 if (PageFrameIndex < (16*1024*1024)/PAGE_SIZE) { 06166 06167 // 06168 // If the frames cannot be replaced with high pages 06169 // then stop copying. 06170 // 06171 06172 #if defined (_X86PAE_) 06173 if (MiNoLowMemory == FALSE) 06174 #endif 06175 StopMoving = TRUE; 06176 } 06177 06178 MI_MAKE_VALID_PTE (TempPte, 06179 PageFrameIndex, 06180 MM_EXECUTE_READWRITE, 06181 PointerPte); 06182 06183 MI_SET_PTE_DIRTY (TempPte); 06184 MI_SET_ACCESSED_IN_PTE (&TempPte, 1); 06185 MI_WRITE_VALID_PTE (PointerPte, TempPte); 06186 06187 MiInitializePfn (PageFrameIndex, PointerPte, 1); 06188 Pfn1 = MI_PFN_ELEMENT (PageFrameIndex); 06189 Pfn1->u3.e1.Modified = 1; 06190 06191 // 06192 // Initialize the WsIndex just like the original page had it. 06193 // 06194 06195 Pfn1->u1.WsIndex = 0; 06196 06197 UNLOCK_PFN (OldIrql); 06198 RtlMoveMemory (RelocatedVa, NonRelocatedVa, PAGE_SIZE); 06199 RelocatedVa += PAGE_SIZE; 06200 NonRelocatedVa += PAGE_SIZE; 06201 } 06202 else { 06203 MI_MAKE_VALID_PTE (TempPte, 06204 PteContents.u.Hard.PageFrameNumber, 06205 MM_EXECUTE_READWRITE, 06206 PointerPte); 06207 06208 MI_WRITE_VALID_PTE (PointerPte, TempPte); 06209 } 06210 06211 PointerPte += 1; 06212 LoaderPte += 1; 06213 } 06214 PointerPte -= NumberOfPtes; 06215 06216 ASSERT (*(PULONG)NewImageAddress == *(PULONG)LoaderImageAddress); 06217 06218 // 06219 // Image is now mapped at the new address. Relocate it (again). 06220 // 06221 06222 #if defined(_ALPHA_) 06223 06224 // 06225 // HIGHADJ relocations need special re-processing. This needs to be 06226 // done before resetting ImageBase. 06227 // 06228 06229 Status = (NTSTATUS)LdrDoubleRelocateImage(NewImageAddress, 06230 LoaderImageAddress, 06231 "SYSLDR", 06232 (ULONG)STATUS_SUCCESS, 06233 (ULONG)STATUS_CONFLICTING_ADDRESSES, 06234 (ULONG)STATUS_INVALID_IMAGE_FORMAT 06235 ); 06236 #endif 06237 06238 NtHeader->OptionalHeader.ImageBase = (ULONG_PTR)LoaderImageAddress; 06239 if (MmMakeLowMemory == TRUE) { 06240 PIMAGE_NT_HEADERS NtHeader2; 06241 06242 NtHeader2 = (PIMAGE_NT_HEADERS)((PCHAR)NtHeader + (RelocatedVa - NonRelocatedVa)); 06243 NtHeader2->OptionalHeader.ImageBase = (ULONG_PTR)LoaderImageAddress; 06244 } 06245 06246 Status = (NTSTATUS)LdrRelocateImage(NewImageAddress, 06247 "SYSLDR", 06248 (ULONG)STATUS_SUCCESS, 06249 (ULONG)STATUS_CONFLICTING_ADDRESSES, 06250 (ULONG)STATUS_INVALID_IMAGE_FORMAT 06251 ); 06252 06253 if (!NT_SUCCESS(Status)) { 06254 06255 if (MmMakeLowMemory == TRUE) { 06256 while (PointerPte < LastPte) { 06257 PageFrameIndex = MI_GET_PAGE_FRAME_FROM_PTE (PointerPte); 06258 Pfn1 = MI_PFN_ELEMENT (PageFrameIndex); 06259 MiDecrementShareAndValidCount (Pfn1->PteFrame); 06260 MI_SET_PFN_DELETED (Pfn1); 06261 MiDecrementShareCountOnly (PageFrameIndex); 06262 PointerPte += 1; 06263 } 06264 } 06265 06266 MiReleaseSystemPtes (PointerPte, 06267 NumberOfPtes, 06268 SystemPteSpace); 06269 06270 if (StopMoving == TRUE) { 06271 MmMakeLowMemory = FALSE; 06272 } 06273 06274 continue; 06275 } 06276 06277 // 06278 // Update the IATs for all other loaded modules that reference this one. 06279 // 06280 06281 NonRelocatedVa = (PCHAR) DataTableEntry->DllBase; 06282 DataTableEntry->DllBase = NewImageAddress; 06283 06284 MiUpdateThunks (LoaderBlock, 06285 LoaderImageAddress, 06286 NewImageAddress, 06287 DataTableEntry->SizeOfImage); 06288 06289 06290 // 06291 // Update the loaded module list entry. 06292 // 06293 06294 DataTableEntry->Flags |= LDRP_SYSTEM_MAPPED; 06295 DataTableEntry->DllBase = NewImageAddress; 06296 DataTableEntry->EntryPoint = 06297 (PVOID)((PCHAR)NewImageAddress + NtHeader->OptionalHeader.AddressOfEntryPoint); 06298 DataTableEntry->SizeOfImage = NumberOfPtes << PAGE_SHIFT; 06299 06300 // 06301 // Update the PFNs of the image to support trimming. 06302 // Note that the loader addresses are freed now so no references 06303 // to it are permitted after this point. 06304 // 06305 06306 LoaderPte = MiGetPteAddress (NonRelocatedVa); 06307 06308 LOCK_PFN (OldIrql); 06309 06310 while (PointerPte < LastPte) { 06311 ASSERT (PointerPte->u.Hard.Valid == 1); 06312 06313 if (MmMakeLowMemory == TRUE) { 06314 ASSERT (LoaderPte->u.Hard.Valid == 1); 06315 PageFrameIndex = MI_GET_PAGE_FRAME_FROM_PTE (LoaderPte); 06316 Pfn1 = MI_PFN_ELEMENT (PageFrameIndex); 06317 06318 #if defined (_X86_) || defined (_IA64_) 06319 06320 // 06321 // Decrement the share count on the original page table 06322 // page so it can be freed. 06323 // 06324 06325 MiDecrementShareAndValidCount (Pfn1->PteFrame); 06326 #endif 06327 06328 MI_SET_PFN_DELETED (Pfn1); 06329 MiDecrementShareCountOnly (PageFrameIndex); 06330 LoaderPte += 1; 06331 } 06332 else { 06333 06334 PageFrameIndex = MI_GET_PAGE_FRAME_FROM_PTE (PointerPte); 06335 Pfn1 = MI_PFN_ELEMENT (PageFrameIndex); 06336 06337 #if defined (_X86_) || defined (_IA64_) 06338 06339 // 06340 // Decrement the share count on the original page table 06341 // page so it can be freed. 06342 // 06343 06344 MiDecrementShareAndValidCount (Pfn1->PteFrame); 06345 *Pfn1->PteAddress = ZeroPte; 06346 #endif 06347 06348 // 06349 // Chain the PFN entry to its new page table. 06350 // 06351 06352 PteFramePointer = MiGetPteAddress(PointerPte); 06353 PteFramePage = MI_GET_PAGE_FRAME_FROM_PTE (PteFramePointer); 06354 06355 Pfn1->PteFrame = PteFramePage; 06356 Pfn1->PteAddress = PointerPte; 06357 06358 // 06359 // Increment the share count for the page table page that now 06360 // contains the PTE that was copied. 06361 // 06362 06363 Pfn2 = MI_PFN_ELEMENT (PteFramePage); 06364 Pfn2->u2.ShareCount += 1; 06365 } 06366 06367 PointerPte += 1; 06368 } 06369 06370 UNLOCK_PFN (OldIrql); 06371 06372 // 06373 // The physical pages mapping the relocation section are freed 06374 // later with the rest of the initialization code spanned by the 06375 // DataTableEntry->SizeOfImage. 06376 // 06377 06378 if (StopMoving == TRUE) { 06379 MmMakeLowMemory = FALSE; 06380 } 06381 } 06382 #if defined (_X86PAE_) 06383 if (MiNoLowMemory == TRUE) { 06384 MiRemoveLowPages (); 06385 } 06386 #endif 06387 }

PFN_NUMBER FASTCALL MiRemoveAnyPage IN ULONG  PageColor  ) 
 

Definition at line 1395 of file pfnlist.c.

References ASSERT, _MMCOLOR_TABLES::Flink, _MMPFNLIST::Flink, FreePageList, MI_CHECK_PAGE_ALIGNMENT, MI_GET_SECONDARY_COLOR, MI_MAGIC_AWE_PTEFRAME, MI_PFN_ELEMENT, MiRemovePageByColor(), MiRemovePageFromList(), MM_COLOR_MASK, MM_EMPTY_LIST, MM_PFN_LOCK_ASSERT, MmAvailablePages, MmFreePageListHead, MmFreePagesByColor, MmStandbyPageListHead, MmZeroedPageListHead, _MMPFN::PteFrame, _MMPFNLIST::Total, _MMPFN::u2, _MMPFN::u3, and ZeroedPageList.

Referenced by ExAllocatePool(), MiAllocatePoolPages(), MiAllocateSpecialPool(), MiBuildPagedPool(), MiCopyOnWrite(), MiFillSystemPageDirectory(), MiGetPageForHeader(), MiInitializeSessionPool(), MiInitMachineDependent(), MiLoadImageSection(), MiMakeOutswappedPageResident(), MiReloadBootLoadedDrivers(), MiResolveDemandZeroFault(), MiResolveMappedFileFault(), MiResolvePageFileFault(), MiSessionCommitImagePages(), MiSessionCommitPageTables(), MiSessionCopyOnWrite(), MiSessionCreateInternal(), MiSessionInitializeWorkingSetList(), MmAccessFault(), MmAllocateIndependentPages(), MmAllocateNonCachedMemory(), MmCopyToCachedPage(), MmCreateKernelStack(), MmCreateProcessAddressSpace(), MmGatherMemoryForHibernate(), MmGrowKernelStack(), MmInitSystem(), and MmZeroPageThread().

01401 : 01402 01403 This procedure removes a page from either the free, zeroed, 01404 or standby lists (in that order). If no pages exist on the zeroed 01405 or free list a transition page is removed from the standby list 01406 and the PTE (may be a prototype PTE) which refers to this page is 01407 changed from transition back to its original contents. 01408 01409 Note pages MUST exist to satisfy this request. The caller ensures this 01410 by first calling MiEnsureAvailablePageOrWait. 01411 01412 Arguments: 01413 01414 PageColor - Supplies the page color for which this page is destined. 01415 This is used for checking virtual address alignments to 01416 determine if the D cache needs flushing before the page 01417 can be reused. 01418 01419 Return Value: 01420 01421 The physical page number removed from the specified list. 01422 01423 Environment: 01424 01425 Must be holding the PFN database mutex with APCs disabled. 01426 01427 --*/ 01428 01429 { 01430 PFN_NUMBER Page; 01431 PMMPFN Pfn1; 01432 ULONG Color; 01433 01434 MM_PFN_LOCK_ASSERT(); 01435 ASSERT(MmAvailablePages != 0); 01436 01437 // 01438 // Check the free page list, and if a page is available 01439 // remove it and return its value. 01440 // 01441 01442 if (MmFreePagesByColor[FreePageList][PageColor].Flink != MM_EMPTY_LIST) { 01443 01444 // 01445 // Remove the first entry on the free by color list. 01446 // 01447 01448 Page = MmFreePagesByColor[FreePageList][PageColor].Flink; 01449 #if DBG 01450 Pfn1 = MI_PFN_ELEMENT(Page); 01451 ASSERT (Pfn1->u3.e1.PageLocation == FreePageList); 01452 ASSERT (Pfn1->u3.e1.PageColor == (PageColor & MM_COLOR_MASK)); 01453 ASSERT (Pfn1->PteFrame != MI_MAGIC_AWE_PTEFRAME); 01454 #endif 01455 MiRemovePageByColor (Page, PageColor); 01456 #if DBG 01457 ASSERT (Pfn1->u3.e1.PageColor == (PageColor & MM_COLOR_MASK)); 01458 ASSERT (Pfn1->u3.e2.ReferenceCount == 0); 01459 ASSERT (Pfn1->u2.ShareCount == 0); 01460 ASSERT (Pfn1->PteFrame != MI_MAGIC_AWE_PTEFRAME); 01461 #endif 01462 return Page; 01463 01464 } 01465 01466 if (MmFreePagesByColor[ZeroedPageList][PageColor].Flink 01467 != MM_EMPTY_LIST) { 01468 01469 // 01470 // Remove the first entry on the zeroed by color list. 01471 // 01472 01473 Page = MmFreePagesByColor[ZeroedPageList][PageColor].Flink; 01474 #if DBG 01475 Pfn1 = MI_PFN_ELEMENT(Page); 01476 ASSERT (Pfn1->u3.e1.PageColor == (PageColor & MM_COLOR_MASK)); 01477 ASSERT (Pfn1->u3.e1.PageLocation == ZeroedPageList); 01478 ASSERT (Pfn1->PteFrame != MI_MAGIC_AWE_PTEFRAME); 01479 #endif 01480 01481 MiRemovePageByColor (Page, PageColor); 01482 ASSERT (Pfn1->PteFrame != MI_MAGIC_AWE_PTEFRAME); 01483 return Page; 01484 } 01485 01486 // 01487 // Try the free page list by primary color. 01488 // 01489 01490 if (MmFreePageListHead.Flink != MM_EMPTY_LIST) { 01491 Page = MmFreePageListHead.Flink; 01492 Color = MI_GET_SECONDARY_COLOR (Page, MI_PFN_ELEMENT(Page)); 01493 01494 #if DBG 01495 Pfn1 = MI_PFN_ELEMENT(Page); 01496 ASSERT (Pfn1->u3.e1.PageColor == (PageColor & MM_COLOR_MASK)); 01497 ASSERT (Pfn1->u3.e1.PageLocation == FreePageList); 01498 ASSERT (Pfn1->PteFrame != MI_MAGIC_AWE_PTEFRAME); 01499 #endif 01500 MiRemovePageByColor (Page, Color); 01501 #if DBG 01502 ASSERT (Pfn1->u3.e1.PageColor == (PageColor & MM_COLOR_MASK)); 01503 ASSERT (Pfn1->u3.e2.ReferenceCount == 0); 01504 ASSERT (Pfn1->u2.ShareCount == 0); 01505 ASSERT (Pfn1->PteFrame != MI_MAGIC_AWE_PTEFRAME); 01506 #endif 01507 return Page; 01508 01509 } 01510 01511 if (MmZeroedPageListHead.Flink != MM_EMPTY_LIST) { 01512 Page = MmZeroedPageListHead.Flink; 01513 Color = MI_GET_SECONDARY_COLOR (Page, MI_PFN_ELEMENT(Page)); 01514 MiRemovePageByColor (Page, Color); 01515 #if DBG 01516 Pfn1 = MI_PFN_ELEMENT(Page); 01517 ASSERT (Pfn1->u3.e1.PageColor == (PageColor & MM_COLOR_MASK)); 01518 ASSERT (Pfn1->u3.e2.ReferenceCount == 0); 01519 ASSERT (Pfn1->u2.ShareCount == 0); 01520 ASSERT (Pfn1->PteFrame != MI_MAGIC_AWE_PTEFRAME); 01521 #endif 01522 return Page; 01523 } 01524 01525 if (MmFreePageListHead.Total != 0) { 01526 01527 Page = MiRemovePageFromList(&MmFreePageListHead); 01528 ASSERT ((MI_PFN_ELEMENT(Page))->PteFrame != MI_MAGIC_AWE_PTEFRAME); 01529 01530 } else { 01531 01532 // 01533 // Check the zeroed page list, and if a page is available 01534 // remove it and return its value. 01535 // 01536 01537 if (MmZeroedPageListHead.Total != 0) { 01538 01539 Page = MiRemovePageFromList(&MmZeroedPageListHead); 01540 ASSERT ((MI_PFN_ELEMENT(Page))->PteFrame != MI_MAGIC_AWE_PTEFRAME); 01541 01542 } else { 01543 01544 // 01545 // No pages exist on the free or zeroed list, use the 01546 // standby list. 01547 // 01548 01549 ASSERT(MmStandbyPageListHead.Total != 0); 01550 01551 Page = MiRemovePageFromList(&MmStandbyPageListHead); 01552 ASSERT ((MI_PFN_ELEMENT(Page))->PteFrame != MI_MAGIC_AWE_PTEFRAME); 01553 } 01554 } 01555 01556 MI_CHECK_PAGE_ALIGNMENT(Page, PageColor & MM_COLOR_MASK); 01557 #if DBG 01558 Pfn1 = MI_PFN_ELEMENT (Page); 01559 ASSERT (Pfn1->u3.e2.ReferenceCount == 0); 01560 ASSERT (Pfn1->u2.ShareCount == 0); 01561 #endif 01562 return Page; 01563 }

VOID MiRemoveConflictFromList IN PMMLOCK_CONFLICT  Conflict  ) 
 

Referenced by MmSecureVirtualMemory(), and NtLockVirtualMemory().

VOID MiRemoveImageHeaderPage IN PFN_NUMBER  PageFrameNumber  ) 
 

Definition at line 4501 of file creasect.c.

References LOCK_PFN, MiDecrementReferenceCount(), and UNLOCK_PFN.

Referenced by MiCheckForCrashDump(), and MiCreateImageFileMap().

04507 : 04508 04509 This non-pagable function acquires the PFN lock, and decrements 04510 the reference count thereby causing the physical page to 04511 be deleted. 04512 04513 Arguments: 04514 04515 PageFrameNumber - Supplies the PFN to decrement. 04516 04517 Return Value: 04518 04519 None. 04520 04521 --*/ 04522 { 04523 KIRQL OldIrql; 04524 04525 LOCK_PFN (OldIrql); 04526 MiDecrementReferenceCount (PageFrameNumber); 04527 UNLOCK_PFN (OldIrql); 04528 return; 04529 }

VOID MiRemoveImageSectionObject IN PFILE_OBJECT  File,
IN PCONTROL_AREA  ControlArea
 

Definition at line 4753 of file creasect.c.

References ASSERT, File, MM_PFN_LOCK_ASSERT, NULL, _LARGE_CONTROL_AREA::u, and _LARGE_CONTROL_AREA::UserGlobalList.

Referenced by MiCheckControlArea(), MiCheckForControlAreaDeletion(), MiCleanSection(), and MmCreateSection().

04760 : 04761 04762 This function searches the control area chains (if any) for an existing 04763 cache of the specified image file. For non-global control areas, there is 04764 no chain and the control area is shared for all callers and sessions. 04765 Likewise for systemwide global control areas. 04766 04767 However, for global PER-SESSION control areas, we must do the walk. 04768 04769 Upon finding the specified control area, we unlink it. 04770 04771 Arguments: 04772 04773 File - Supplies the file object for the image file. 04774 04775 InputControlArea - Supplies the control area to remove. 04776 04777 Return Value: 04778 04779 None. 04780 04781 Environment: 04782 04783 Must be holding the PFN lock. 04784 04785 --*/ 04786 04787 { 04788 PLIST_ENTRY Head, Next; 04789 PLARGE_CONTROL_AREA ControlArea; 04790 PLARGE_CONTROL_AREA FirstControlArea; 04791 PLARGE_CONTROL_AREA NextControlArea; 04792 04793 MM_PFN_LOCK_ASSERT(); 04794 04795 ControlArea = (PLARGE_CONTROL_AREA) InputControlArea; 04796 04797 FirstControlArea = (PLARGE_CONTROL_AREA)(File->SectionObjectPointer->ImageSectionObject); 04798 04799 // 04800 // Get a pointer to the first control area. If this is not a 04801 // global-per-session control area, then there is no list, so we're done. 04802 // 04803 04804 if (FirstControlArea->u.Flags.GlobalOnlyPerSession == 0) { 04805 ASSERT (ControlArea->u.Flags.GlobalOnlyPerSession == 0); 04806 04807 (PCONTROL_AREA)(File->SectionObjectPointer->ImageSectionObject) = NULL; 04808 return; 04809 } 04810 04811 // 04812 // A list may exist. Walk it as necessary and delete the requested entry. 04813 // 04814 04815 if (FirstControlArea == ControlArea) { 04816 04817 // 04818 // The first entry is the one to remove. If it is the only entry 04819 // in the list, then the new first entry pointer will be NULL. 04820 // Otherwise, get a pointer to the next entry and unlink the current. 04821 // 04822 04823 if (IsListEmpty (&FirstControlArea->UserGlobalList)) { 04824 NextControlArea = NULL; 04825 } else { 04826 Next = FirstControlArea->UserGlobalList.Flink; 04827 RemoveEntryList (&FirstControlArea->UserGlobalList); 04828 NextControlArea = CONTAINING_RECORD (Next, 04829 LARGE_CONTROL_AREA, 04830 UserGlobalList); 04831 04832 ASSERT (NextControlArea->u.Flags.GlobalOnlyPerSession == 1); 04833 } 04834 04835 (PCONTROL_AREA)(File->SectionObjectPointer->ImageSectionObject) = 04836 (PCONTROL_AREA) NextControlArea; 04837 return; 04838 } 04839 04840 // 04841 // Remove the entry, note that the ImageSectionObject need not be updated 04842 // as the entry is not at the head. 04843 // 04844 04845 #if DBG 04846 Head = &FirstControlArea->UserGlobalList; 04847 04848 for (Next = Head->Flink; Next != Head; Next = Next->Flink) { 04849 04850 NextControlArea = CONTAINING_RECORD (Next, 04851 LARGE_CONTROL_AREA, 04852 UserGlobalList); 04853 04854 ASSERT (NextControlArea->u.Flags.GlobalOnlyPerSession == 1); 04855 04856 if (NextControlArea == ControlArea) { 04857 break; 04858 } 04859 } 04860 ASSERT (Next != Head); 04861 #endif 04862 04863 RemoveEntryList (&ControlArea->UserGlobalList); 04864 }

NTSTATUS MiRemoveImageSessionWide IN PVOID  BaseAddr  ) 
 

Definition at line 1223 of file sessload.c.

References ASSERT, MiSessionRemoveImage(), MiSessionWideDereferenceImage(), MmIsAddressValid(), MmSessionSpace, NT_SUCCESS, NTSTATUS(), PAGED_CODE, Status, SYSLOAD_LOCK_OWNED_BY_ME, and TRUE.

Referenced by MiLoadImageSection(), and MmUnloadSystemImage().

01229 : 01230 01231 Delete the image space region from the current session space. 01232 This dereferences the globally allocated SessionWide region. 01233 01234 The SessionWide region will be deleted if the reference count goes to zero. 01235 01236 Arguments: 01237 01238 BaseAddress - Supplies the address the driver is loaded at. 01239 01240 Return Value: 01241 01242 Returns STATUS_SUCCESS on success, STATUS_NOT_FOUND on failure. 01243 01244 Environment: 01245 01246 Kernel mode, APC_LEVEL and below, MmSystemLoadLock held. 01247 01248 --*/ 01249 01250 { 01251 NTSTATUS Status; 01252 01253 PAGED_CODE(); 01254 01255 SYSLOAD_LOCK_OWNED_BY_ME (); 01256 01257 ASSERT (MmIsAddressValid(MmSessionSpace) == TRUE); 01258 01259 Status = MiSessionWideDereferenceImage (BaseAddress); 01260 01261 ASSERT (NT_SUCCESS(Status)); 01262 01263 // 01264 // Remove the image reference from the current session space. 01265 // 01266 01267 MiSessionRemoveImage (BaseAddress); 01268 01269 return Status; 01270 }

VOID MiRemoveMappedView IN PEPROCESS  CurrentProcess,
IN PMMVAD  Vad
 

Definition at line 265 of file umapview.c.

References ASSERT, _MMPTE_FLUSH_LIST::Count, ExAcquireFastMutexUnsafe(), ExFreePool(), ExReleaseFastMutexUnsafe(), FALSE, KeFlushEntireTb(), LOCK_AWE, LOCK_PFN, MI_DECREMENT_USED_PTES_BY_HANDLE, MI_GET_PAGE_FRAME_FROM_PTE, MI_GET_USED_PTES_FROM_HANDLE, MI_GET_USED_PTES_HANDLE, MI_VPN_TO_VA, MI_VPN_TO_VA_ENDING, MI_WRITE_INVALID_PTE, MiCheckControlArea(), MiDecrementShareAndValidCount, MiDeletePte(), MiDeleteVirtualAddresses(), MiGetPdeAddress, MiGetPteAddress, MiGetVirtualAddressMappedByPte, MiIsPteOnPdeBoundary, MM_MAXIMUM_FLUSH_COUNT, MmSectionBasedMutex, NULL, _CONTROL_AREA::NumberOfMappedViews, _CONTROL_AREA::NumberOfUserReferences, PMMEXTEND_INFO, TRUE, UNLOCK_AWE, UNLOCK_PFN, _MI_PHYSICAL_VIEW::Vad, and ZeroPte.

Referenced by MmCleanProcessAddressSpace(), and MmUnmapViewOfSection().

00272 : 00273 00274 This function removes the mapping from the current process's 00275 address space. The physical VAD may be a normal mapping (backed by 00276 a control area) or it may have no control area (it was mapped by a driver). 00277 00278 Arguments: 00279 00280 Process - Supplies a referenced pointer to the current process object. 00281 00282 Vad - Supplies the VAD which maps the view. 00283 00284 Return Value: 00285 00286 None. 00287 00288 Environment: 00289 00290 APC level, working set mutex and address creation mutex held. 00291 00292 NOTE: THE WORKING SET MUTEXES MAY BE RELEASED THEN REACQUIRED!!!! 00293 00294 SINCE MiCheckControlArea releases unsafe, the WS mutex must be 00295 acquired UNSAFE. 00296 00297 --*/ 00298 00299 { 00300 KIRQL OldIrql; 00301 BOOLEAN DereferenceSegment; 00302 PCONTROL_AREA ControlArea; 00303 PMMPTE PointerPte; 00304 PMMPTE PointerPde; 00305 PMMPTE LastPte; 00306 PFN_NUMBER PdePage; 00307 PKEVENT PurgeEvent; 00308 PVOID TempVa; 00309 BOOLEAN DeleteOnClose; 00310 MMPTE_FLUSH_LIST PteFlushList; 00311 PVOID UsedPageTableHandle; 00312 PLIST_ENTRY NextEntry; 00313 PMI_PHYSICAL_VIEW PhysicalView; 00314 PVOID PhysicalPool; 00315 #if defined (_WIN64) 00316 PMMPTE PointerPpe; 00317 PVOID UsedPageDirectoryHandle; 00318 #endif 00319 00320 DereferenceSegment = FALSE; 00321 PurgeEvent = NULL; 00322 DeleteOnClose = FALSE; 00323 PhysicalPool = NULL; 00324 00325 ControlArea = Vad->ControlArea; 00326 00327 if (Vad->u.VadFlags.PhysicalMapping == 1) { 00328 00329 if (Vad->u4.Banked) { 00330 ExFreePool (Vad->u4.Banked); 00331 } 00332 00333 #ifdef LARGE_PAGES 00334 if (Vad->u.VadFlags.LargePages == 1) { 00335 00336 // 00337 // Delete the subsection allocated to hold the large pages. 00338 // 00339 00340 ExFreePool (Vad->FirstPrototypePte); 00341 Vad->FirstPrototypePte = NULL; 00342 KeFlushEntireTb (TRUE, FALSE); 00343 LOCK_PFN (OldIrql); 00344 } else { 00345 00346 #endif //LARGE_PAGES 00347 00348 // 00349 // This is a physical memory view. The pages map physical memory 00350 // and are not accounted for in the working set list or in the PFN 00351 // database. 00352 // 00353 00354 LOCK_AWE (CurrentProcess, OldIrql); 00355 00356 NextEntry = CurrentProcess->PhysicalVadList.Flink; 00357 while (NextEntry != &CurrentProcess->PhysicalVadList) { 00358 00359 PhysicalView = CONTAINING_RECORD(NextEntry, 00360 MI_PHYSICAL_VIEW, 00361 ListEntry); 00362 00363 if (Vad == PhysicalView->Vad) { 00364 RemoveEntryList (NextEntry); 00365 PhysicalPool = (PVOID)PhysicalView; 00366 break; 00367 } 00368 NextEntry = NextEntry->Flink; 00369 } 00370 00371 UNLOCK_AWE (CurrentProcess, OldIrql); 00372 00373 // 00374 // Set count so only flush entire TB operations are performed. 00375 // 00376 00377 PteFlushList.Count = MM_MAXIMUM_FLUSH_COUNT; 00378 00379 LOCK_PFN (OldIrql); 00380 00381 // 00382 // Remove the PTES from the address space. 00383 // 00384 00385 PointerPde = MiGetPdeAddress (MI_VPN_TO_VA (Vad->StartingVpn)); 00386 PdePage = MI_GET_PAGE_FRAME_FROM_PTE (PointerPde); 00387 PointerPte = MiGetPteAddress (MI_VPN_TO_VA (Vad->StartingVpn)); 00388 LastPte = MiGetPteAddress (MI_VPN_TO_VA (Vad->EndingVpn)); 00389 00390 UsedPageTableHandle = MI_GET_USED_PTES_HANDLE (MI_VPN_TO_VA (Vad->StartingVpn)); 00391 00392 while (PointerPte <= LastPte) { 00393 00394 if (MiIsPteOnPdeBoundary (PointerPte)) { 00395 00396 PointerPde = MiGetPteAddress (PointerPte); 00397 PdePage = MI_GET_PAGE_FRAME_FROM_PTE (PointerPde); 00398 00399 UsedPageTableHandle = MI_GET_USED_PTES_HANDLE (MiGetVirtualAddressMappedByPte (PointerPte)); 00400 } 00401 00402 MI_WRITE_INVALID_PTE (PointerPte, ZeroPte); 00403 MiDecrementShareAndValidCount (PdePage); 00404 00405 // 00406 // Decrement the count of non-zero page table entries for this 00407 // page table. 00408 // 00409 00410 MI_DECREMENT_USED_PTES_BY_HANDLE (UsedPageTableHandle); 00411 00412 // 00413 // If all the entries have been eliminated from the previous 00414 // page table page, delete the page table page itself. And if 00415 // this results in an empty page directory page, then delete 00416 // that too. 00417 // 00418 00419 if (MI_GET_USED_PTES_FROM_HANDLE(UsedPageTableHandle) == 0) { 00420 00421 TempVa = MiGetVirtualAddressMappedByPte(PointerPde); 00422 00423 PteFlushList.Count = MM_MAXIMUM_FLUSH_COUNT; 00424 00425 MiDeletePte (PointerPde, 00426 TempVa, 00427 FALSE, 00428 CurrentProcess, 00429 (PMMPTE)NULL, 00430 &PteFlushList); 00431 00432 // 00433 // Add back in the private page MiDeletePte subtracted. 00434 // 00435 00436 CurrentProcess->NumberOfPrivatePages += 1; 00437 00438 #if defined (_WIN64) 00439 UsedPageDirectoryHandle = MI_GET_USED_PTES_HANDLE (PointerPte); 00440 00441 MI_DECREMENT_USED_PTES_BY_HANDLE (UsedPageDirectoryHandle); 00442 00443 if (MI_GET_USED_PTES_FROM_HANDLE(UsedPageDirectoryHandle) == 0) { 00444 00445 PointerPpe = MiGetPdeAddress(PointerPte); 00446 TempVa = MiGetVirtualAddressMappedByPte(PointerPpe); 00447 00448 PteFlushList.Count = MM_MAXIMUM_FLUSH_COUNT; 00449 00450 MiDeletePte (PointerPpe, 00451 TempVa, 00452 FALSE, 00453 CurrentProcess, 00454 (PMMPTE)NULL, 00455 &PteFlushList); 00456 00457 // 00458 // Add back in the private page MiDeletePte subtracted. 00459 // 00460 00461 CurrentProcess->NumberOfPrivatePages += 1; 00462 } 00463 #endif 00464 } 00465 PointerPte += 1; 00466 } 00467 KeFlushEntireTb (TRUE, FALSE); 00468 00469 #ifdef LARGE_PAGES 00470 } 00471 #endif //LARGE_PAGES 00472 } else { 00473 00474 if (Vad->u2.VadFlags2.ExtendableFile) { 00475 PMMEXTEND_INFO exinfo = NULL; 00476 ExAcquireFastMutexUnsafe (&MmSectionBasedMutex); 00477 ASSERT (Vad->ControlArea->Segment->ExtendInfo == Vad->u4.ExtendedInfo); 00478 Vad->u4.ExtendedInfo->ReferenceCount -= 1; 00479 if (Vad->u4.ExtendedInfo->ReferenceCount == 0) { 00480 exinfo = Vad->u4.ExtendedInfo; 00481 Vad->ControlArea->Segment->ExtendInfo = NULL; 00482 } 00483 ExReleaseFastMutexUnsafe (&MmSectionBasedMutex); 00484 if (exinfo) { 00485 ExFreePool (exinfo); 00486 } 00487 } 00488 00489 LOCK_PFN (OldIrql); 00490 MiDeleteVirtualAddresses (MI_VPN_TO_VA (Vad->StartingVpn), 00491 MI_VPN_TO_VA_ENDING (Vad->EndingVpn), 00492 FALSE, 00493 Vad); 00494 } 00495 00496 // 00497 // Only physical VADs mapped by drivers don't have control areas. 00498 // If this view has a control area, the view count must be decremented now. 00499 // 00500 00501 if (ControlArea) { 00502 00503 // 00504 // Decrement the count of the number of views for the 00505 // Segment object. This requires the PFN mutex to be held (it is 00506 // already). 00507 // 00508 00509 ControlArea->NumberOfMappedViews -= 1; 00510 ControlArea->NumberOfUserReferences -= 1; 00511 00512 // 00513 // Check to see if the control area (segment) should be deleted. 00514 // This routine releases the PFN lock. 00515 // 00516 00517 MiCheckControlArea (ControlArea, CurrentProcess, OldIrql); 00518 } 00519 else { 00520 00521 UNLOCK_PFN (OldIrql); 00522 00523 // 00524 // Even though it says short VAD in VadFlags, it better be a long VAD. 00525 // 00526 00527 ASSERT (Vad->u.VadFlags.PhysicalMapping == 1); 00528 ASSERT (Vad->u4.Banked == NULL); 00529 ASSERT (Vad->ControlArea == NULL); 00530 ASSERT (Vad->FirstPrototypePte == NULL); 00531 } 00532 00533 if (PhysicalPool != NULL) { 00534 ExFreePool (PhysicalPool); 00535 } 00536 00537 return; 00538 }

VOID FASTCALL MiRemoveNode IN PMMADDRESS_NODE  Node,
IN OUT PMMADDRESS_NODE Root
 

Definition at line 568 of file addrsup.c.

References _MMADDRESS_NODE::LeftChild, NULL, _MMADDRESS_NODE::Parent, and _MMADDRESS_NODE::RightChild.

Referenced by MiRemoveBasedSection(), and MiRemoveVad().

00575 : 00576 00577 This function removes a virtual address descriptor from the tree and 00578 reorders the splay tree as appropriate. 00579 00580 Arguments: 00581 00582 Node - Supplies a pointer to a virtual address descriptor. 00583 00584 Return Value: 00585 00586 None. 00587 00588 --*/ 00589 00590 { 00591 00592 PMMADDRESS_NODE LeftChild; 00593 PMMADDRESS_NODE RightChild; 00594 PMMADDRESS_NODE SplayNode; 00595 00596 00597 LeftChild = Node->LeftChild; 00598 RightChild = Node->RightChild; 00599 00600 00601 // 00602 // If the Node is the root of the tree, then establish new root. Else 00603 // isolate splay case and perform splay tree transformation. 00604 // 00605 00606 if (Node == *Root) { 00607 00608 // 00609 // This Node is the root of the tree. There are four cases to 00610 // handle: 00611 // 00612 // 1. the descriptor has no children 00613 // 2. the descriptor has a left child but no right child 00614 // 3. the descriptor has a right child but no left child 00615 // 4. the descriptor has both a right child and a left child 00616 // 00617 00618 if (LeftChild) { 00619 if (RightChild) { 00620 00621 // 00622 // The descriptor has both a left child and a right child. 00623 // 00624 00625 if (LeftChild->RightChild) { 00626 00627 // 00628 // The left child has a right child. Make the right most 00629 // descendent of the right child of the left child the 00630 // new root of the tree. 00631 // 00632 // Pictorially: 00633 // 00634 // R R 00635 // | | 00636 // X Z 00637 // / \ / \ 00638 // A B -> A B 00639 // \ \ 00640 // . . 00641 // \ 00642 // Z 00643 // 00644 00645 SplayNode = LeftChild->RightChild; 00646 while (SplayNode->RightChild) { 00647 SplayNode = SplayNode->RightChild; 00648 } 00649 *Root = SplayNode; 00650 SplayNode->Parent->RightChild = SplayNode->LeftChild; 00651 if (SplayNode->LeftChild) { 00652 SplayNode->LeftChild->Parent = SplayNode->Parent; 00653 } 00654 SplayNode->Parent = (PMMADDRESS_NODE)NULL; 00655 LeftChild->Parent = SplayNode; 00656 RightChild->Parent = SplayNode; 00657 SplayNode->LeftChild = LeftChild; 00658 SplayNode->RightChild = RightChild; 00659 } else if (RightChild->LeftChild) { 00660 00661 // 00662 // The right child has a left child. Make the left most 00663 // descendent of the left child of the right child the 00664 // new root of the tree. 00665 // 00666 // Pictorially: 00667 // 00668 // R R 00669 // | | 00670 // X Z 00671 // / \ / \ 00672 // A B -> A B 00673 // / / 00674 // . . 00675 // / 00676 // Z 00677 // 00678 00679 SplayNode = RightChild->LeftChild; 00680 while (SplayNode->LeftChild) { 00681 SplayNode = SplayNode->LeftChild; 00682 } 00683 *Root = SplayNode; 00684 SplayNode->Parent->LeftChild = SplayNode->RightChild; 00685 if (SplayNode->RightChild) { 00686 SplayNode->RightChild->Parent = SplayNode->Parent; 00687 } 00688 SplayNode->Parent = (PMMADDRESS_NODE)NULL; 00689 LeftChild->Parent = SplayNode; 00690 RightChild->Parent = SplayNode; 00691 SplayNode->LeftChild = LeftChild; 00692 SplayNode->RightChild = RightChild; 00693 } else { 00694 00695 // 00696 // The left child of the descriptor does not have a right child, 00697 // and the right child of the descriptor does not have a left 00698 // child. Make the left child of the descriptor the new root of 00699 // the tree. 00700 // 00701 // Pictorially: 00702 // 00703 // R R 00704 // | | 00705 // X A 00706 // / \ / \ 00707 // A B -> . B 00708 // / / 00709 // . 00710 // 00711 00712 *Root = LeftChild; 00713 LeftChild->Parent = (PMMADDRESS_NODE)NULL; 00714 LeftChild->RightChild = RightChild; 00715 LeftChild->RightChild->Parent = LeftChild; 00716 } 00717 } else { 00718 00719 // 00720 // The descriptor has a left child, but does not have a right child. 00721 // Make the left child the new root of the tree. 00722 // 00723 // Pictorially: 00724 // 00725 // R R 00726 // | | 00727 // X -> A 00728 // / 00729 // A 00730 // 00731 00732 *Root = LeftChild; 00733 LeftChild->Parent = (PMMADDRESS_NODE)NULL; 00734 } 00735 } else if (RightChild) { 00736 00737 // 00738 // The descriptor has a right child, but does not have a left child. 00739 // Make the right child the new root of the tree. 00740 // 00741 // Pictorially: 00742 // 00743 // R R 00744 // | | 00745 // X -> A 00746 // \ 00747 // A 00748 // 00749 00750 *Root = RightChild; 00751 RightChild->Parent = (PMMADDRESS_NODE)NULL; 00752 while (RightChild->LeftChild) { 00753 RightChild = RightChild->LeftChild; 00754 } 00755 } else { 00756 00757 // 00758 // The descriptor has neither a left child nor a right child. The 00759 // tree will be empty after removing the descriptor. 00760 // 00761 // Pictorially: 00762 // 00763 // R R 00764 // | -> 00765 // X 00766 // 00767 00768 *Root = NULL; 00769 } 00770 } else if (LeftChild) { 00771 if (RightChild) { 00772 00773 // 00774 // The descriptor has both a left child and a right child. 00775 // 00776 00777 if (LeftChild->RightChild) { 00778 00779 // 00780 // The left child has a right child. Make the right most 00781 // descendent of the right child of the left child the new 00782 // root of the subtree. 00783 // 00784 // Pictorially: 00785 // 00786 // P P 00787 // / \ 00788 // X X 00789 // / \ / \ 00790 // A B or A B 00791 // \ \ 00792 // . . 00793 // \ \ 00794 // Z Z 00795 // 00796 // | 00797 // v 00798 // 00799 // P P 00800 // / \ 00801 // Z Z 00802 // / \ / \ 00803 // A B or A B 00804 // \ \ 00805 // . . 00806 // 00807 00808 SplayNode = LeftChild->RightChild; 00809 while (SplayNode->RightChild) { 00810 SplayNode = SplayNode->RightChild; 00811 } 00812 SplayNode->Parent->RightChild = SplayNode->LeftChild; 00813 if (SplayNode->LeftChild) { 00814 SplayNode->LeftChild->Parent = SplayNode->Parent; 00815 } 00816 SplayNode->Parent = Node->Parent; 00817 if (Node == Node->Parent->LeftChild) { 00818 Node->Parent->LeftChild = SplayNode; 00819 } else { 00820 Node->Parent->RightChild = SplayNode; 00821 } 00822 LeftChild->Parent = SplayNode; 00823 RightChild->Parent = SplayNode; 00824 SplayNode->LeftChild = LeftChild; 00825 SplayNode->RightChild = RightChild; 00826 } else if (RightChild->LeftChild) { 00827 00828 // 00829 // The right child has a left child. Make the left most 00830 // descendent of the left child of the right child the 00831 // new root of the subtree. 00832 // 00833 // Pictorially: 00834 // 00835 // P P 00836 // / \ 00837 // X X 00838 // / \ / \ 00839 // A B or A B 00840 // / / 00841 // . . 00842 // / / 00843 // Z Z 00844 // 00845 // | 00846 // v 00847 // 00848 // P P 00849 // / \ 00850 // Z Z 00851 // / \ / \ 00852 // A B or A B 00853 // / / 00854 // . . 00855 // 00856 00857 SplayNode = RightChild->LeftChild; 00858 while (SplayNode->LeftChild) { 00859 SplayNode = SplayNode->LeftChild; 00860 } 00861 SplayNode->Parent->LeftChild = SplayNode->RightChild; 00862 if (SplayNode->RightChild) { 00863 SplayNode->RightChild->Parent = SplayNode->Parent; 00864 } 00865 SplayNode->Parent = Node->Parent; 00866 if (Node == Node->Parent->LeftChild) { 00867 Node->Parent->LeftChild = SplayNode; 00868 } else { 00869 Node->Parent->RightChild = SplayNode; 00870 } 00871 LeftChild->Parent = SplayNode; 00872 RightChild->Parent = SplayNode; 00873 SplayNode->LeftChild = LeftChild; 00874 SplayNode->RightChild = RightChild; 00875 } else { 00876 00877 // 00878 // The left child of the descriptor does not have a right child, 00879 // and the right child of the descriptor does node have a left 00880 // child. Make the left child of the descriptor the new root of 00881 // the subtree. 00882 // 00883 // Pictorially: 00884 // 00885 // P P 00886 // / \ 00887 // X X 00888 // / \ / \ 00889 // A B or A B 00890 // / / 00891 // . . 00892 // 00893 // | 00894 // v 00895 // 00896 // P P 00897 // / \ 00898 // A A 00899 // / \ / \ 00900 // . B or . B 00901 // / / 00902 // 00903 00904 SplayNode = LeftChild; 00905 SplayNode->Parent = Node->Parent; 00906 if (Node == Node->Parent->LeftChild) { 00907 Node->Parent->LeftChild = SplayNode; 00908 } else { 00909 Node->Parent->RightChild = SplayNode; 00910 } 00911 SplayNode->RightChild = RightChild; 00912 RightChild->Parent = SplayNode; 00913 } 00914 } else { 00915 00916 // 00917 // The descriptor has a left child, but does not have a right child. 00918 // Make the left child the new root of the subtree. 00919 // 00920 // Pictorially: 00921 // 00922 // P P 00923 // / \ 00924 // X or X 00925 // / / 00926 // A A 00927 // 00928 // | 00929 // v 00930 // 00931 // P P 00932 // / \ 00933 // A A 00934 // 00935 00936 LeftChild->Parent = Node->Parent; 00937 if (Node == Node->Parent->LeftChild) { 00938 Node->Parent->LeftChild = LeftChild; 00939 } else { 00940 Node->Parent->RightChild = LeftChild; 00941 } 00942 } 00943 } else if (RightChild) { 00944 00945 // 00946 // descriptor has a right child, but does not have a left child. Make 00947 // the right child the new root of the subtree. 00948 // 00949 // Pictorially: 00950 // 00951 // P P 00952 // / \ 00953 // X or X 00954 // \ \ 00955 // A A 00956 // 00957 // | 00958 // v 00959 // 00960 // P P 00961 // / \ 00962 // A A 00963 // 00964 00965 RightChild->Parent = Node->Parent; 00966 if (Node == Node->Parent->LeftChild) { 00967 Node->Parent->LeftChild = RightChild; 00968 } else { 00969 Node->Parent->RightChild = RightChild; 00970 } 00971 } else { 00972 00973 // 00974 // The descriptor has neither a left child nor a right child. Delete 00975 // the descriptor from the tree and adjust its parent right or left 00976 // link. 00977 // 00978 // Pictorially: 00979 // 00980 // P P 00981 // / \ 00982 // X or X 00983 // 00984 // | 00985 // v 00986 // 00987 // P P 00988 // 00989 00990 if (Node == Node->Parent->LeftChild) { 00991 Node->Parent->LeftChild = (PMMADDRESS_NODE)NULL; 00992 } else { 00993 Node->Parent->RightChild = (PMMADDRESS_NODE)NULL; 00994 } 00995 } 00996 return; 00997 }

PFN_NUMBER FASTCALL MiRemovePageFromList IN PMMPFNLIST  ListHead  ) 
 

Definition at line 521 of file pfnlist.c.

References ASSERT, _MMCOLOR_TABLES::Flink, FreePageList, KeBugCheckEx(), MI_GET_SECONDARY_COLOR, MI_PFN_ELEMENT, MI_TALLY_TRANSITION_PAGE_REMOVAL, MiObtainFreePages(), MiRestoreTransitionPte(), MM_EMPTY_LIST, MM_PFN_LOCK_ASSERT, MmAvailablePages, MmFreePagesByColor, MmHighestPhysicalPage, MmLowestPhysicalPage, MmMinimumFreePages, ModifiedPageList, _MMPFN::OriginalPte, PERFINFO_REMOVEPAGE, StandbyPageList, _MMPTE::u, _MMPFN::u1, _MMPFN::u2, and _MMPFN::u3.

Referenced by MiRemoveAnyPage(), MiRemoveZeroPage(), and MmTrimAllSystemPagableMemory().

00527 : 00528 00529 This procedure removes a page from the head of the specified list (free, 00530 standby, zeroed, modified). 00531 00532 This routine clears the flags word in the PFN database, hence the 00533 PFN information for this page must be initialized. 00534 00535 Arguments: 00536 00537 ListHead - Supplies the list of the list in which to remove the 00538 specified physical page. 00539 00540 Return Value: 00541 00542 The physical page number removed from the specified list. 00543 00544 Environment: 00545 00546 Must be holding the PFN database mutex with APCs disabled. 00547 00548 --*/ 00549 00550 { 00551 PFN_NUMBER PageFrameIndex; 00552 PMMPFN Pfn1; 00553 PMMPFN Pfn2; 00554 ULONG Color; 00555 00556 MM_PFN_LOCK_ASSERT(); 00557 00558 // 00559 // If the specified list is empty return MM_EMPTY_LIST. 00560 // 00561 00562 if (ListHead->Total == 0) { 00563 00564 KdPrint(("MM:Attempting to remove page from empty list\n")); 00565 KeBugCheckEx (PFN_LIST_CORRUPT, 1, (ULONG_PTR)ListHead, MmAvailablePages, 0); 00566 return 0; 00567 } 00568 00569 ASSERT (ListHead->ListName != ModifiedPageList); 00570 00571 // 00572 // Decrement the count of pages on the list and remove the first 00573 // page from the list. 00574 // 00575 00576 ListHead->Total -= 1; 00577 PageFrameIndex = ListHead->Flink; 00578 Pfn1 = MI_PFN_ELEMENT (PageFrameIndex); 00579 00580 PERFINFO_REMOVEPAGE(PageFrameIndex, PERFINFO_LOG_TYPE_REMOVEPAGEFROMLIST); 00581 00582 ListHead->Flink = Pfn1->u1.Flink; 00583 00584 // 00585 // Zero the flink and blink in the pfn database element. 00586 // 00587 00588 Pfn1->u1.Flink = 0; // Assumes Flink width is >= WsIndex width 00589 Pfn1->u2.Blink = 0; 00590 00591 // 00592 // If the last page was removed (the ListHead->Flink is now 00593 // MM_EMPTY_LIST) make the listhead->Blink MM_EMPTY_LIST as well. 00594 // 00595 00596 if (ListHead->Flink == MM_EMPTY_LIST) { 00597 ListHead->Blink = MM_EMPTY_LIST; 00598 } else { 00599 00600 // 00601 // Make the PFN element point to MM_EMPTY_LIST signifying this 00602 // is the last page in the list. 00603 // 00604 00605 Pfn2 = MI_PFN_ELEMENT (ListHead->Flink); 00606 Pfn2->u2.Blink = MM_EMPTY_LIST; 00607 } 00608 00609 // 00610 // Check to see if we now have one less page available. 00611 // 00612 00613 if (ListHead->ListName <= StandbyPageList) { 00614 MmAvailablePages -= 1; 00615 00616 if (ListHead->ListName == StandbyPageList) { 00617 00618 // 00619 // This page is currently in transition, restore the PTE to 00620 // its original contents so this page can be reused. 00621 // 00622 00623 MI_TALLY_TRANSITION_PAGE_REMOVAL (Pfn1); 00624 MiRestoreTransitionPte (PageFrameIndex); 00625 } 00626 00627 if (MmAvailablePages < MmMinimumFreePages) { 00628 00629 // 00630 // Obtain free pages. 00631 // 00632 00633 MiObtainFreePages(); 00634 } 00635 } 00636 00637 ASSERT ((PageFrameIndex != 0) && 00638 (PageFrameIndex <= MmHighestPhysicalPage) && 00639 (PageFrameIndex >= MmLowestPhysicalPage)); 00640 00641 // 00642 // Zero the PFN flags longword. 00643 // 00644 00645 Color = Pfn1->u3.e1.PageColor; 00646 ASSERT (Pfn1->u3.e1.RemovalRequested == 0); 00647 Pfn1->u3.e2.ShortFlags = 0; 00648 Pfn1->u3.e1.PageColor = Color; 00649 Color = MI_GET_SECONDARY_COLOR (PageFrameIndex, Pfn1); 00650 00651 if (ListHead->ListName <= FreePageList) { 00652 00653 // 00654 // Update the color lists. 00655 // 00656 00657 ASSERT (MmFreePagesByColor[ListHead->ListName][Color].Flink == PageFrameIndex); 00658 MmFreePagesByColor[ListHead->ListName][Color].Flink = 00659 (PFN_NUMBER) Pfn1->OriginalPte.u.Long; 00660 } 00661 00662 return PageFrameIndex; 00663 }

ULONG MiRemovePageFromWorkingSet IN PMMPTE  PointerPte,
IN PMMPFN  Pfn1,
IN PMMSUPPORT  WsInfo
 

Definition at line 899 of file wslist.c.

References ASSERT, FALSE, _MMWSL::FirstDynamic, LOCK_PFN, _MMWSLENTRY::LockedInMemory, _MMWSLENTRY::LockedInWs, MI_PFN_ELEMENT, MiEliminateWorkingSetEntry(), MiGetPteAddress, MiGetVirtualAddressMappedByPte, MiLocateWsle(), MiReleaseWsle(), MiRemoveWsle(), MiSwapWslEntries(), PAGE_ALIGN, TRUE, _MMWSLE::u1, UNLOCK_PFN, _MMWSL::Wsle, WSLE_NULL_INDEX, and WSLE_NUMBER.

Referenced by MiProtectSpecialPool(), MiProtectVirtualMemory(), and MiSetProtectionOnSection().

00907 : 00908 00909 This function removes the page mapped by the specified PTE from 00910 the process's working set list. 00911 00912 Arguments: 00913 00914 PointerPte - Supplies a pointer to the PTE mapping the page to 00915 be removed from the working set list. 00916 00917 Pfn1 - Supplies a pointer to the PFN database element referred to 00918 by the PointerPte. 00919 00920 Return Value: 00921 00922 Returns TRUE if the specified page was locked in the working set, 00923 FALSE otherwise. 00924 00925 Environment: 00926 00927 Kernel mode, APCs disabled, working set mutex held. 00928 00929 --*/ 00930 00931 { 00932 WSLE_NUMBER WorkingSetIndex; 00933 PVOID VirtualAddress; 00934 WSLE_NUMBER Entry; 00935 PVOID SwapVa; 00936 MMWSLENTRY Locked; 00937 PMMWSL WorkingSetList; 00938 PMMWSLE Wsle; 00939 KIRQL OldIrql; 00940 00941 WorkingSetList = WsInfo->VmWorkingSetList; 00942 Wsle = WorkingSetList->Wsle; 00943 00944 VirtualAddress = MiGetVirtualAddressMappedByPte (PointerPte); 00945 WorkingSetIndex = MiLocateWsle (VirtualAddress, 00946 WorkingSetList, 00947 Pfn1->u1.WsIndex); 00948 00949 ASSERT (WorkingSetIndex != WSLE_NULL_INDEX); 00950 LOCK_PFN (OldIrql); 00951 MiEliminateWorkingSetEntry (WorkingSetIndex, 00952 PointerPte, 00953 Pfn1, 00954 Wsle); 00955 00956 UNLOCK_PFN (OldIrql); 00957 00958 // 00959 // Check to see if this entry is locked in the working set 00960 // or locked in memory. 00961 // 00962 00963 Locked = Wsle[WorkingSetIndex].u1.e1; 00964 MiRemoveWsle (WorkingSetIndex, WorkingSetList); 00965 00966 // 00967 // Add this entry to the list of free working set entries 00968 // and adjust the working set count. 00969 // 00970 00971 MiReleaseWsle ((WSLE_NUMBER)WorkingSetIndex, WsInfo); 00972 00973 if ((Locked.LockedInWs == 1) || (Locked.LockedInMemory == 1)) { 00974 00975 // 00976 // This entry is locked. 00977 // 00978 00979 WorkingSetList->FirstDynamic -= 1; 00980 00981 if (WorkingSetIndex != WorkingSetList->FirstDynamic) { 00982 00983 SwapVa = Wsle[WorkingSetList->FirstDynamic].u1.VirtualAddress; 00984 SwapVa = PAGE_ALIGN (SwapVa); 00985 00986 PointerPte = MiGetPteAddress (SwapVa); 00987 Pfn1 = MI_PFN_ELEMENT (PointerPte->u.Hard.PageFrameNumber); 00988 #if 0 00989 Entry = MiLocateWsleAndParent (SwapVa, 00990 &Parent, 00991 WorkingSetList, 00992 Pfn1->u1.WsIndex); 00993 00994 // 00995 // Swap the removed entry with the last locked entry 00996 // which is located at first dynamic. 00997 // 00998 00999 MiSwapWslEntries (Entry, Parent, WorkingSetIndex, WorkingSetList); 01000 #endif //0 01001 01002 Entry = MiLocateWsle (SwapVa, WorkingSetList, Pfn1->u1.WsIndex); 01003 01004 MiSwapWslEntries (Entry, WorkingSetIndex, WsInfo); 01005 01006 } 01007 return TRUE; 01008 } else { 01009 ASSERT (WorkingSetIndex >= WorkingSetList->FirstDynamic); 01010 } 01011 return FALSE; 01012 }

NTSTATUS MiRemovePsLoadedModule PLDR_DATA_TABLE_ENTRY  DataTableEntry  ) 
 

VOID MiRemoveUserPhysicalPagesVad IN PMMVAD_SHORT  FoundVad  ) 
 

Definition at line 2110 of file physical.c.

References APC_LEVEL, ASSERT, _MMPTE_FLUSH_LIST::Count, DbgPrint, _MMPTE_FLUSH_LIST::FlushPte, _MMPTE_FLUSH_LIST::FlushVa, LOCK_AWE, LOCK_PFN2, LOWEST_USABLE_PHYSICAL_PAGE, MI_GET_PAGE_FRAME_FROM_PTE, MI_PFN_ELEMENT, MI_PFN_IS_AWE, MI_VPN_TO_VA, MI_VPN_TO_VA_ENDING, MI_WRITE_INVALID_PTE, MiFlushUserPhysicalPteList(), MiGetPteAddress, MiGetVirtualAddressMappedByPte, MM_MAXIMUM_FLUSH_COUNT, NULL, _EPROCESS::PhysicalVadList, PsGetCurrentProcess, _MMPTE::u, UNLOCK_AWE, UNLOCK_PFN2, _MI_PHYSICAL_VIEW::Vad, _EPROCESS::VadPhysicalPages, _EPROCESS::VadPhysicalPagesBitMap, and ZeroPte.

Referenced by MmCleanProcessAddressSpace(), and NtFreeVirtualMemory().

02116 : 02117 02118 This function removes the user-physical-pages mapped region from the 02119 current process's address space. This mapped region is private memory. 02120 02121 The physical pages of this Vad are unmapped here, but not freed. 02122 02123 Pagetable pages are freed and their use/commitment counts/quotas are 02124 managed by our caller. 02125 02126 Arguments: 02127 02128 Vad - Supplies the VAD which manages the address space. 02129 02130 Return Value: 02131 02132 None. 02133 02134 Environment: 02135 02136 APC level, working set mutex and address creation mutex held. 02137 02138 --*/ 02139 02140 { 02141 PMMPFN Pfn1; 02142 PEPROCESS Process; 02143 PFN_NUMBER PageFrameIndex; 02144 MMPTE_FLUSH_LIST PteFlushList; 02145 PMMPTE PointerPte; 02146 MMPTE PteContents; 02147 PMMPTE EndingPte; 02148 #if DBG 02149 KIRQL OldIrql; 02150 KIRQL OldIrql2; 02151 ULONG_PTR ActualPages; 02152 ULONG_PTR ExpectedPages; 02153 PLIST_ENTRY NextEntry; 02154 PMI_PHYSICAL_VIEW PhysicalView; 02155 #endif 02156 02157 ASSERT (KeGetCurrentIrql() == APC_LEVEL); 02158 02159 ASSERT (Vad->u.VadFlags.UserPhysicalPages == 1); 02160 02161 Process = PsGetCurrentProcess(); 02162 02163 // 02164 // If the physical pages count is zero, nothing needs to be done. 02165 // On checked systems, verify the list anyway. 02166 // 02167 02168 #if DBG 02169 ActualPages = 0; 02170 ExpectedPages = Process->VadPhysicalPages; 02171 #else 02172 if (Process->VadPhysicalPages == 0) { 02173 return; 02174 } 02175 #endif 02176 02177 // 02178 // The caller must have removed this Vad from the physical view list, 02179 // otherwise another thread could immediately remap pages back into the Vad. 02180 // 02181 // This allows us to proceed without acquiring the AWE or PFN locks - 02182 // everything can be done under the WS lock which is already held. 02183 // 02184 02185 #if DBG 02186 LOCK_AWE (Process, OldIrql); 02187 02188 LOCK_PFN2 (OldIrql2); 02189 02190 NextEntry = Process->PhysicalVadList.Flink; 02191 while (NextEntry != &Process->PhysicalVadList) { 02192 02193 PhysicalView = CONTAINING_RECORD(NextEntry, 02194 MI_PHYSICAL_VIEW, 02195 ListEntry); 02196 02197 if (PhysicalView->Vad == (PMMVAD)Vad) { 02198 DbgPrint ("MiRemoveUserPhysicalPagesVad : Vad %p still in list!\n", 02199 Vad); 02200 DbgBreakPoint (); 02201 } 02202 02203 NextEntry = NextEntry->Flink; 02204 } 02205 02206 UNLOCK_PFN2 (OldIrql2); 02207 UNLOCK_AWE (Process, OldIrql); 02208 #endif 02209 02210 // 02211 // If the physical pages bitmap doesn't exist, nothing needs to be done. 02212 // 02213 02214 if (Process->VadPhysicalPagesBitMap == NULL) { 02215 ASSERT (ExpectedPages == 0); 02216 return; 02217 } 02218 02219 PointerPte = MiGetPteAddress (MI_VPN_TO_VA (Vad->StartingVpn)); 02220 EndingPte = MiGetPteAddress (MI_VPN_TO_VA_ENDING (Vad->EndingVpn)); 02221 02222 PteFlushList.Count = 0; 02223 02224 while (PointerPte <= EndingPte) { 02225 PteContents = *PointerPte; 02226 if (PteContents.u.Hard.Valid == 0) { 02227 PointerPte += 1; 02228 continue; 02229 } 02230 02231 PageFrameIndex = MI_GET_PAGE_FRAME_FROM_PTE (PointerPte); 02232 02233 ASSERT (PageFrameIndex >= LOWEST_USABLE_PHYSICAL_PAGE); 02234 ASSERT (ExpectedPages != 0); 02235 02236 Pfn1 = MI_PFN_ELEMENT(PageFrameIndex); 02237 02238 ASSERT (MI_PFN_IS_AWE (Pfn1)); 02239 ASSERT (Pfn1->u2.ShareCount == 2); 02240 ASSERT (Pfn1->PteAddress == PointerPte); 02241 02242 // 02243 // The frame is currently mapped in this Vad so the PTE must 02244 // be cleared and the TB entry flushed. 02245 // 02246 02247 Pfn1->u2.ShareCount -= 1; 02248 Pfn1->PteAddress = (PMMPTE)0; 02249 02250 if (PteFlushList.Count != MM_MAXIMUM_FLUSH_COUNT) { 02251 PteFlushList.FlushVa[PteFlushList.Count] = 02252 MiGetVirtualAddressMappedByPte (PointerPte); 02253 PteFlushList.FlushPte[PteFlushList.Count] = PointerPte; 02254 PteFlushList.Count += 1; 02255 } 02256 02257 MI_WRITE_INVALID_PTE (PointerPte, ZeroPte); 02258 02259 PointerPte += 1; 02260 #if DBG 02261 ActualPages += 1; 02262 #endif 02263 ASSERT (ActualPages <= ExpectedPages); 02264 } 02265 02266 // 02267 // Flush the TB entries for these pages. Note ZeroPte is only used 02268 // when the FlushPte[0] field is nonzero or if only a single PTE is 02269 // being flushed. 02270 // 02271 02272 MiFlushUserPhysicalPteList (&PteFlushList); 02273 02274 return; 02275 }

VOID MiRemoveVad IN PMMVAD  Vad  ) 
 

Definition at line 256 of file vadtree.c.

References BYTES_TO_PAGES, _EPROCESS::CommitCharge, ExFreePool(), _EPROCESS::JobStatus, List, _MMSECURE_ENTRY::List, MiGetPreviousVad, MiRemoveNode(), MiReturnCommitment(), MiReturnPageFileQuota(), MM_DBG_COMMIT_RETURN_VAD, MM_MAX_COMMIT, MM_TRACK_COMMIT, NonPagedPool, NULL, PagedPool, PS_JOB_STATUS_REPORT_COMMIT_CHANGES, PsChangeJobMemoryUsage(), PsGetCurrentProcess, PsReturnPoolQuota(), PTE_SHIFT, _EPROCESS::VadFreeHint, _EPROCESS::VadHint, and _EPROCESS::VadRoot.

Referenced by MiUnmapLockedPagesInUserSpace(), MmCleanProcessAddressSpace(), MmDeleteTeb(), MmUnmapViewOfSection(), NtAllocateVirtualMemory(), and NtFreeVirtualMemory().

00262 : 00263 00264 This function removes a virtual address descriptor from the tree and 00265 reorders the splay tree as appropriate. If any quota or commitment 00266 was charged by the VAD (as indicated by the CommitCharge field) it 00267 is released. 00268 00269 Arguments: 00270 00271 Vad - Supplies a pointer to a virtual address descriptor. 00272 00273 Return Value: 00274 00275 None. 00276 00277 --*/ 00278 00279 { 00280 PMMADDRESS_NODE *Root; 00281 PEPROCESS CurrentProcess; 00282 SIZE_T RealCharge; 00283 PLIST_ENTRY Next; 00284 PMMSECURE_ENTRY Entry; 00285 00286 CurrentProcess = PsGetCurrentProcess(); 00287 00288 00289 // 00290 // Commit charge of MAX_COMMIT means don't charge quota. 00291 // 00292 00293 if (Vad->u.VadFlags.CommitCharge != MM_MAX_COMMIT) { 00294 00295 // 00296 // Return the quota charge to the process. 00297 // 00298 00299 PsReturnPoolQuota (CurrentProcess, NonPagedPool, sizeof(MMVAD)); 00300 00301 if ((Vad->u.VadFlags.PrivateMemory == 0) && 00302 (Vad->ControlArea != NULL)) { 00303 PsReturnPoolQuota (CurrentProcess, 00304 PagedPool, 00305 (Vad->EndingVpn - Vad->StartingVpn) << PTE_SHIFT); 00306 } 00307 00308 RealCharge = Vad->u.VadFlags.CommitCharge; 00309 00310 if (RealCharge != 0) { 00311 00312 MiReturnPageFileQuota (RealCharge, CurrentProcess); 00313 00314 if ((Vad->u.VadFlags.PrivateMemory == 0) && 00315 (Vad->ControlArea != NULL)) { 00316 00317 #if 0 //commented out so page file quota is meaningful. 00318 if (Vad->ControlArea->FilePointer == NULL) { 00319 00320 // 00321 // Don't release commitment for the page file space 00322 // occupied by a page file section. This will be charged 00323 // as the shared memory is committed. 00324 // 00325 00326 RealCharge -= BYTES_TO_PAGES ((ULONG)Vad->EndingVa - 00327 (ULONG)Vad->StartingVa); 00328 } 00329 #endif 00330 } 00331 00332 MiReturnCommitment (RealCharge); 00333 MM_TRACK_COMMIT (MM_DBG_COMMIT_RETURN_VAD, RealCharge); 00334 if (CurrentProcess->JobStatus & PS_JOB_STATUS_REPORT_COMMIT_CHANGES) { 00335 PsChangeJobMemoryUsage(-(SSIZE_T)RealCharge); 00336 } 00337 CurrentProcess->CommitCharge -= RealCharge; 00338 } 00339 } 00340 00341 if (Vad == CurrentProcess->VadFreeHint) { 00342 CurrentProcess->VadFreeHint = MiGetPreviousVad (Vad); 00343 } 00344 00345 Root = (PMMADDRESS_NODE *)&CurrentProcess->VadRoot; 00346 00347 MiRemoveNode ( (PMMADDRESS_NODE)Vad, Root); 00348 00349 if (Vad->u.VadFlags.NoChange) { 00350 if (Vad->u2.VadFlags2.MultipleSecured) { 00351 00352 // 00353 // Free the oustanding pool allocations. 00354 // 00355 00356 Next = Vad->u3.List.Flink; 00357 do { 00358 Entry = CONTAINING_RECORD( Next, 00359 MMSECURE_ENTRY, 00360 List); 00361 00362 Next = Entry->List.Flink; 00363 ExFreePool (Entry); 00364 } while (Next != &Vad->u3.List); 00365 } 00366 } 00367 00368 // 00369 // If the VadHint was the removed Vad, change the Hint. 00370 00371 if (CurrentProcess->VadHint == Vad) { 00372 CurrentProcess->VadHint = CurrentProcess->VadRoot; 00373 } 00374 00375 return; 00376 }

VOID MiRemoveWorkingSetPages IN PMMWSL  WorkingSetList,
IN PMMSUPPORT  WsInfo
 

Definition at line 4228 of file wslist.c.

References ASSERT, CONSISTENCY_LOCK_PFN, CONSISTENCY_UNLOCK_PFN, _MMPTE_FLUSH_LIST::Count, DbgPrint, FALSE, LOCK_EXPANSION_IF_ALPHA, LOCK_PFN, MI_FLUSH_ENTIRE_SESSION_TB, MI_GET_PAGE_FRAME_FROM_PTE, MI_PFN_ELEMENT, MI_SET_PTE_IN_WORKING_SET, MiCheckNullIndex(), MiDeletePte(), MiFlushPteList(), MiGetPdeAddress, MiGetPpeAddress, MiGetPteAddress, MiGetVirtualAddressMappedByPte, MiInsertWsle(), MiIsPteOnPdeBoundary, MiIsPteOnPpeBoundary, MiRemoveWsle(), MM_FREE_WSLE_SHIFT, MM_GROW_WSLE_HASH, MmSystemCacheWs, MMWSLE_HASH, NULL, _EPROCESS::NumberOfPrivatePages, PAGE_ALIGN, PAGE_SIZE, PsGetCurrentProcess, TRUE, _MMPTE::u, _MMSUPPORT::u, _MMPFN::u1, _MMWSLE::u1, _MMPFN::u2, _MMPFN::u3, UNLOCK_EXPANSION_IF_ALPHA, UNLOCK_PFN, WSLE_NULL_INDEX, WSLE_NUMBER, and ZeroPte.

04235 : 04236 04237 This routine compresses the WSLEs into the front of the working set 04238 and frees the pages for unneeded working set entries. 04239 04240 Arguments: 04241 04242 WorkingSetList - Supplies a pointer to the working set list to compress. 04243 04244 Return Value: 04245 04246 None. 04247 04248 Environment: 04249 04250 Kernel mode, Working set lock held, APCs disabled. 04251 04252 --*/ 04253 04254 { 04255 PMMWSLE FreeEntry; 04256 PMMWSLE LastEntry; 04257 PMMWSLE Wsle; 04258 ULONG FreeIndex; 04259 ULONG LastIndex; 04260 ULONG LastInvalid; 04261 PMMPTE LastPte; 04262 PMMPTE PointerPte; 04263 PMMPTE PointerPde; 04264 PMMPTE PointerPpe; 04265 PMMPTE WsPte; 04266 PMMPFN Pfn1; 04267 PEPROCESS CurrentProcess; 04268 MMPTE_FLUSH_LIST PteFlushList; 04269 ULONG NewSize; 04270 PMMWSLE_HASH Table; 04271 KIRQL OldIrql; 04272 04273 ASSERT (WsInfo != &MmSystemCacheWs && WsInfo->u.Flags.SessionSpace == 0); 04274 04275 PteFlushList.Count = 0; 04276 CurrentProcess = PsGetCurrentProcess(); 04277 04278 #if DBG 04279 MiCheckNullIndex (WorkingSetList); 04280 #endif //DBG 04281 04282 // 04283 // Check to see if the wsle hash table should be contracted. 04284 // 04285 04286 if (WorkingSetList->HashTable) { 04287 04288 Table = WorkingSetList->HashTable; 04289 04290 #if DBG 04291 if ((PVOID)(&Table[WorkingSetList->HashTableSize]) < WorkingSetList->HighestPermittedHashAddress) { 04292 ASSERT (MiGetPteAddress(&Table[WorkingSetList->HashTableSize])->u.Hard.Valid == 0); 04293 } 04294 #endif 04295 04296 if (WsInfo->WorkingSetSize < 200) { 04297 NewSize = 0; 04298 } 04299 else { 04300 NewSize = PtrToUlong(PAGE_ALIGN ((WorkingSetList->NonDirectCount * 2 * 04301 sizeof(MMWSLE_HASH)) + PAGE_SIZE - 1)); 04302 04303 NewSize = NewSize / sizeof(MMWSLE_HASH); 04304 } 04305 04306 if (NewSize < WorkingSetList->HashTableSize) { 04307 04308 #if defined(_ALPHA_) && !defined(_AXP64_) 04309 LOCK_EXPANSION_IF_ALPHA (OldIrql); 04310 #endif 04311 if (NewSize && WsInfo->AllowWorkingSetAdjustment) { 04312 WsInfo->AllowWorkingSetAdjustment = MM_GROW_WSLE_HASH; 04313 } 04314 #if defined(_ALPHA_) && !defined(_AXP64_) 04315 UNLOCK_EXPANSION_IF_ALPHA (OldIrql); 04316 #endif 04317 04318 // 04319 // Remove pages from hash table. 04320 // 04321 04322 ASSERT (((ULONG_PTR)&WorkingSetList->HashTable[NewSize] & 04323 (PAGE_SIZE - 1)) == 0); 04324 04325 PointerPte = MiGetPteAddress (&WorkingSetList->HashTable[NewSize]); 04326 04327 LastPte = MiGetPteAddress (WorkingSetList->HighestPermittedHashAddress); 04328 // 04329 // Set the hash table to null indicating that no hashing 04330 // is going on. 04331 // 04332 04333 WorkingSetList->HashTable = NULL; 04334 WorkingSetList->HashTableSize = NewSize; 04335 04336 LOCK_PFN (OldIrql); 04337 while ((PointerPte < LastPte) && (PointerPte->u.Hard.Valid == 1)) { 04338 04339 MiDeletePte (PointerPte, 04340 MiGetVirtualAddressMappedByPte (PointerPte), 04341 FALSE, 04342 CurrentProcess, 04343 NULL, 04344 &PteFlushList); 04345 04346 // 04347 // Add back in the private page MiDeletePte subtracted. 04348 // 04349 04350 CurrentProcess->NumberOfPrivatePages += 1; 04351 04352 PointerPte += 1; 04353 04354 #if defined (_WIN64) 04355 // 04356 // If all the entries have been removed from the previous page 04357 // table page, delete the page table page itself. Likewise with 04358 // the page directory page. 04359 // 04360 04361 if ((MiIsPteOnPdeBoundary(PointerPte)) || 04362 ((MiGetPdeAddress(PointerPte))->u.Hard.Valid == 0) || 04363 ((MiGetPteAddress(PointerPte))->u.Hard.Valid == 0) || 04364 (PointerPte->u.Hard.Valid == 0)) { 04365 04366 MiFlushPteList (&PteFlushList, FALSE, ZeroPte); 04367 04368 PointerPde = MiGetPteAddress (PointerPte - 1); 04369 04370 ASSERT (PointerPde->u.Hard.Valid == 1); 04371 04372 Pfn1 = MI_PFN_ELEMENT (MI_GET_PAGE_FRAME_FROM_PTE (PointerPde)); 04373 04374 if (Pfn1->u2.ShareCount == 1 && Pfn1->u3.e2.ReferenceCount == 1) 04375 { 04376 MiDeletePte (PointerPde, 04377 PointerPte - 1, 04378 FALSE, 04379 CurrentProcess, 04380 NULL, 04381 NULL); 04382 04383 // 04384 // Add back in the private page MiDeletePte subtracted. 04385 // 04386 04387 CurrentProcess->NumberOfPrivatePages += 1; 04388 } 04389 04390 if (MiIsPteOnPpeBoundary(PointerPte)) { 04391 04392 PointerPpe = MiGetPteAddress (PointerPde); 04393 04394 ASSERT (PointerPpe->u.Hard.Valid == 1); 04395 04396 Pfn1 = MI_PFN_ELEMENT (MI_GET_PAGE_FRAME_FROM_PTE (PointerPpe)); 04397 04398 if (Pfn1->u2.ShareCount == 1 && Pfn1->u3.e2.ReferenceCount == 1) 04399 { 04400 MiDeletePte (PointerPpe, 04401 PointerPde, 04402 FALSE, 04403 CurrentProcess, 04404 NULL, 04405 NULL); 04406 04407 // 04408 // Add back in the private page MiDeletePte subtracted. 04409 // 04410 04411 CurrentProcess->NumberOfPrivatePages += 1; 04412 } 04413 } 04414 PointerPde = MiGetPteAddress (PointerPte); 04415 PointerPpe = MiGetPdeAddress (PointerPte); 04416 if ((PointerPpe->u.Hard.Valid == 0) || 04417 (PointerPde->u.Hard.Valid == 0)) { 04418 break; 04419 } 04420 } 04421 #endif 04422 } 04423 MiFlushPteList (&PteFlushList, FALSE, ZeroPte); 04424 04425 if (WsInfo->u.Flags.SessionSpace == 1) { 04426 04427 // 04428 // Session space has no ASN - flush the entire TB. 04429 // 04430 04431 MI_FLUSH_ENTIRE_SESSION_TB (TRUE, TRUE); 04432 } 04433 04434 UNLOCK_PFN (OldIrql); 04435 } 04436 #if defined (_WIN64) 04437 04438 // 04439 // For 64-bit NT, the page tables and page directories are also 04440 // deleted during contraction. 04441 // 04442 04443 ASSERT ((MiGetPpeAddress(&Table[WorkingSetList->HashTableSize])->u.Hard.Valid == 0) || 04444 (MiGetPdeAddress(&Table[WorkingSetList->HashTableSize])->u.Hard.Valid == 0) || 04445 (MiGetPteAddress(&Table[WorkingSetList->HashTableSize])->u.Hard.Valid == 0)); 04446 04447 #else 04448 04449 ASSERT (MiGetPteAddress(&Table[WorkingSetList->HashTableSize])->u.Hard.Valid == 0); 04450 04451 #endif 04452 } 04453 04454 // 04455 // If the only pages in the working set are locked pages (that 04456 // is all pages are BEFORE first dynamic, just reorganize the 04457 // free list). 04458 // 04459 04460 Wsle = WorkingSetList->Wsle; 04461 if (WorkingSetList->FirstDynamic == WsInfo->WorkingSetSize) { 04462 04463 LastIndex = WorkingSetList->FirstDynamic; 04464 LastEntry = &Wsle[LastIndex]; 04465 04466 } else { 04467 04468 // 04469 // Start from the first dynamic and move towards the end looking 04470 // for free entries. At the same time start from the end and 04471 // move towards first dynamic looking for valid entries. 04472 // 04473 04474 LastInvalid = 0; 04475 FreeIndex = WorkingSetList->FirstDynamic; 04476 FreeEntry = &Wsle[FreeIndex]; 04477 LastIndex = WorkingSetList->LastEntry; 04478 LastEntry = &Wsle[LastIndex]; 04479 04480 while (FreeEntry < LastEntry) { 04481 if (FreeEntry->u1.e1.Valid == 1) { 04482 FreeEntry += 1; 04483 FreeIndex += 1; 04484 } else if (LastEntry->u1.e1.Valid == 0) { 04485 LastEntry -= 1; 04486 LastIndex -= 1; 04487 } else { 04488 04489 // 04490 // Move the WSLE at LastEntry to the free slot at FreeEntry. 04491 // 04492 04493 LastInvalid = 1; 04494 *FreeEntry = *LastEntry; 04495 PointerPte = MiGetPteAddress (LastEntry->u1.VirtualAddress); 04496 04497 if (LastEntry->u1.e1.Direct) { 04498 04499 Pfn1 = MI_PFN_ELEMENT (PointerPte->u.Hard.PageFrameNumber); 04500 04501 CONSISTENCY_LOCK_PFN (OldIrql); 04502 04503 Pfn1->u1.WsIndex = FreeIndex; 04504 04505 CONSISTENCY_UNLOCK_PFN (OldIrql); 04506 04507 } else { 04508 04509 // 04510 // This entry is in the working set. Remove it 04511 // and then add the entry add the free slot. 04512 // 04513 04514 MiRemoveWsle (LastIndex, WorkingSetList); 04515 MiInsertWsle (FreeIndex, WorkingSetList); 04516 } 04517 04518 MI_SET_PTE_IN_WORKING_SET (PointerPte, FreeIndex); 04519 LastEntry->u1.Long = 0; 04520 LastEntry -= 1; 04521 LastIndex -= 1; 04522 FreeEntry += 1; 04523 FreeIndex += 1; 04524 } 04525 } 04526 04527 // 04528 // If no entries were freed, just return. 04529 // 04530 04531 if (LastInvalid == 0) { 04532 #if DBG 04533 MiCheckNullIndex (WorkingSetList); 04534 #endif //DBG 04535 return; 04536 } 04537 } 04538 04539 // 04540 // Reorganize the free list. Make last entry the first free. 04541 // 04542 04543 ASSERT ((LastEntry - 1)->u1.e1.Valid == 1); 04544 04545 if (LastEntry->u1.e1.Valid == 1) { 04546 LastEntry += 1; 04547 LastIndex += 1; 04548 } 04549 04550 WorkingSetList->LastEntry = LastIndex - 1; 04551 WorkingSetList->FirstFree = LastIndex; 04552 04553 ASSERT ((LastEntry - 1)->u1.e1.Valid == 1); 04554 ASSERT ((LastEntry)->u1.e1.Valid == 0); 04555 04556 // 04557 // Point free entry to the first invalid page. 04558 // 04559 04560 FreeEntry = LastEntry; 04561 04562 while (LastIndex < WorkingSetList->LastInitializedWsle) { 04563 04564 // 04565 // Put the remainder of the WSLEs on the free list. 04566 // 04567 04568 ASSERT (LastEntry->u1.e1.Valid == 0); 04569 LastIndex += 1; 04570 LastEntry->u1.Long = LastIndex << MM_FREE_WSLE_SHIFT; 04571 LastEntry += 1; 04572 } 04573 04574 //LastEntry->u1.Long = WSLE_NULL_INDEX << MM_FREE_WSLE_SHIFT; // End of list. 04575 04576 // 04577 // Delete the working set pages at the end. 04578 // 04579 04580 PointerPte = MiGetPteAddress (&Wsle[WorkingSetList->LastInitializedWsle]); 04581 if (&Wsle[WsInfo->MinimumWorkingSetSize] > FreeEntry) { 04582 FreeEntry = &Wsle[WsInfo->MinimumWorkingSetSize]; 04583 } 04584 04585 WsPte = MiGetPteAddress (FreeEntry); 04586 04587 #if 0 04588 if (MiGetPteAddress (FreeEntry) != MiGetPteAddress (FreeEntry + 1)) { 04589 DbgPrint ("MiRemoveWorkingSetPages caught boundary case %x\n", FreeEntry); 04590 DbgBreakPoint(); 04591 04592 WsPte = MiGetPteAddress (FreeEntry + 1); 04593 } 04594 #endif 04595 04596 ASSERT (WorkingSetList->FirstFree >= WorkingSetList->FirstDynamic); 04597 04598 LOCK_PFN (OldIrql); 04599 while (PointerPte > WsPte) { 04600 ASSERT (PointerPte->u.Hard.Valid == 1); 04601 04602 MiDeletePte (PointerPte, 04603 MiGetVirtualAddressMappedByPte (PointerPte), 04604 FALSE, 04605 CurrentProcess, 04606 NULL, 04607 &PteFlushList); 04608 04609 // 04610 // Add back in the private page MiDeletePte subtracted. 04611 // 04612 04613 CurrentProcess->NumberOfPrivatePages += 1; 04614 04615 #if defined (_WIN64) 04616 // 04617 // If all the entries have been removed from the previous page 04618 // table page, delete the page table page itself. Likewise with 04619 // the page directory page. 04620 // 04621 04622 if (MiIsPteOnPdeBoundary(PointerPte)) { 04623 04624 PointerPde = MiGetPteAddress (PointerPte); 04625 04626 ASSERT (PointerPde->u.Hard.Valid == 1); 04627 04628 Pfn1 = MI_PFN_ELEMENT (MI_GET_PAGE_FRAME_FROM_PTE (PointerPde)); 04629 04630 if (Pfn1->u2.ShareCount == 1 && Pfn1->u3.e2.ReferenceCount == 1) { 04631 04632 MiFlushPteList (&PteFlushList, FALSE, ZeroPte); 04633 04634 MiDeletePte (PointerPde, 04635 PointerPte, 04636 FALSE, 04637 CurrentProcess, 04638 NULL, 04639 NULL); 04640 04641 // 04642 // Add back in the private page MiDeletePte subtracted. 04643 // 04644 04645 CurrentProcess->NumberOfPrivatePages += 1; 04646 } 04647 04648 if (MiIsPteOnPpeBoundary(PointerPte)) { 04649 04650 PointerPpe = MiGetPteAddress (PointerPde); 04651 04652 ASSERT (PointerPpe->u.Hard.Valid == 1); 04653 04654 Pfn1 = MI_PFN_ELEMENT (MI_GET_PAGE_FRAME_FROM_PTE (PointerPpe)); 04655 04656 if (Pfn1->u2.ShareCount == 1 && Pfn1->u3.e2.ReferenceCount == 1) 04657 { 04658 04659 MiFlushPteList (&PteFlushList, FALSE, ZeroPte); 04660 04661 MiDeletePte (PointerPpe, 04662 PointerPde, 04663 FALSE, 04664 CurrentProcess, 04665 NULL, 04666 NULL); 04667 04668 // 04669 // Add back in the private page MiDeletePte subtracted. 04670 // 04671 04672 CurrentProcess->NumberOfPrivatePages += 1; 04673 } 04674 } 04675 } 04676 #endif 04677 04678 PointerPte -= 1; 04679 } 04680 04681 MiFlushPteList (&PteFlushList, FALSE, ZeroPte); 04682 04683 if (WsInfo->u.Flags.SessionSpace == 1) { 04684 04685 // 04686 // Session space has no ASN - flush the entire TB. 04687 // 04688 04689 MI_FLUSH_ENTIRE_SESSION_TB (TRUE, TRUE); 04690 } 04691 04692 UNLOCK_PFN (OldIrql); 04693 04694 ASSERT (WorkingSetList->FirstFree >= WorkingSetList->FirstDynamic); 04695 04696 // 04697 // Mark the last PTE in the list as free. 04698 // 04699 04700 LastEntry = (PMMWSLE)((PCHAR)(PAGE_ALIGN(FreeEntry)) + PAGE_SIZE); 04701 LastEntry -= 1; 04702 04703 ASSERT (LastEntry->u1.e1.Valid == 0); 04704 LastEntry->u1.Long = WSLE_NULL_INDEX << MM_FREE_WSLE_SHIFT; //End of List. 04705 ASSERT (LastEntry > &Wsle[0]); 04706 WorkingSetList->LastInitializedWsle = (WSLE_NUMBER)(LastEntry - &Wsle[0]); 04707 WorkingSetList->NextSlot = WorkingSetList->FirstDynamic; 04708 04709 ASSERT (WorkingSetList->LastEntry <= WorkingSetList->LastInitializedWsle); 04710 04711 if (WorkingSetList->Quota < WorkingSetList->LastInitializedWsle) { 04712 WorkingSetList->Quota = WorkingSetList->LastInitializedWsle; 04713 } 04714 04715 ASSERT ((MiGetPteAddress(&Wsle[WorkingSetList->LastInitializedWsle]))->u.Hard.Valid == 1); 04716 ASSERT ((WorkingSetList->FirstFree <= WorkingSetList->LastInitializedWsle) || 04717 (WorkingSetList->FirstFree == WSLE_NULL_INDEX)); 04718 #if DBG 04719 MiCheckNullIndex (WorkingSetList); 04720 #endif //DBG 04721 return; 04722 }

VOID FASTCALL MiRemoveWsle IN WSLE_NUMBER  Entry,
IN PMMWSL  WorkingSetList
 

Definition at line 464 of file wstree.c.

References ASSERT, DbgPrint, _MMWSLE::e1, KeBugCheckEx(), _MMWSLE_HASH::Key, _MMWSLE::Long, MI_IS_SYSTEM_CACHE_ADDRESS, MI_WSLE_HASH, MiDumpWsl(), MM_DBG_DUMP_WSL, MM_DBG_PTE_UPDATE, MM_PAGED_POOL_START, MmNonPagedSystemStart, MmPagedPoolPage, MmSystemCachePage, MmSystemCacheStart, MmSystemCacheWorkingSetList, MmSystemCodePage, MmSystemDriverPage, PAGE_ALIGN, _MMWSLE::u1, _MMWSLENTRY::Valid, and _MMWSLE::VirtualAddress.

Referenced by MiDecommitPages(), MiDeletePte(), MiDeleteSystemPagableVm(), MiFreeWsle(), MiLockCode(), MiRemoveMappedPtes(), MiRemovePageFromWorkingSet(), MiRemoveWorkingSetPages(), and MmUnmapViewInSystemCache().

00471 : 00472 00473 This routine removes a Working Set List Entry (WSLE) from the 00474 working set. 00475 00476 Arguments: 00477 00478 Entry - The index number of the WSLE to remove. 00479 00480 00481 Return Value: 00482 00483 None. 00484 00485 Environment: 00486 00487 Kernel mode, APCs disabled, Working Set Mutex held. 00488 00489 --*/ 00490 { 00491 PMMWSLE Wsle; 00492 PVOID VirtualAddress; 00493 PMMWSLE_HASH Table; 00494 ULONG Hash; 00495 ULONG Tries; 00496 00497 Wsle = WorkingSetList->Wsle; 00498 00499 // 00500 // Locate the entry in the tree. 00501 // 00502 00503 #if DBG 00504 if (MmDebug & MM_DBG_PTE_UPDATE) { 00505 DbgPrint("removing wsle %lx %lx\n", 00506 Entry, Wsle[Entry].u1.Long); 00507 } 00508 if (MmDebug & MM_DBG_DUMP_WSL) { 00509 MiDumpWsl(); 00510 DbgPrint(" \n"); 00511 } 00512 00513 #endif //DBG 00514 00515 ASSERT (Wsle[Entry].u1.e1.Valid == 1); 00516 00517 VirtualAddress = PAGE_ALIGN (Wsle[Entry].u1.VirtualAddress); 00518 00519 if (WorkingSetList == MmSystemCacheWorkingSetList) { 00520 00521 // 00522 // count system space inserts and removals. 00523 // 00524 00525 #if defined(_X86_) 00526 if (MI_IS_SYSTEM_CACHE_ADDRESS(VirtualAddress)) { 00527 MmSystemCachePage -= 1; 00528 } else 00529 #endif 00530 if (VirtualAddress < MmSystemCacheStart) { 00531 MmSystemCodePage -= 1; 00532 } else if (VirtualAddress < MM_PAGED_POOL_START) { 00533 MmSystemCachePage -= 1; 00534 } else if (VirtualAddress < MmNonPagedSystemStart) { 00535 MmPagedPoolPage -= 1; 00536 } else { 00537 MmSystemDriverPage -= 1; 00538 } 00539 } 00540 00541 Wsle[Entry].u1.e1.Valid = 0; 00542 00543 if (Wsle[Entry].u1.e1.Direct == 0) { 00544 00545 WorkingSetList->NonDirectCount -= 1; 00546 00547 if (WorkingSetList->HashTable) { 00548 Hash = MI_WSLE_HASH(Wsle[Entry].u1.Long, WorkingSetList); 00549 Table = WorkingSetList->HashTable; 00550 Tries = 0; 00551 00552 while (Table[Hash].Key != (ULONG_PTR)VirtualAddress) { 00553 Hash += 1; 00554 if (Hash >= WorkingSetList->HashTableSize) { 00555 Hash = 0; 00556 if (Tries != 0) { 00557 KeBugCheckEx (MEMORY_MANAGEMENT, 00558 0x41784, 00559 (ULONG_PTR)VirtualAddress, 00560 Entry, 00561 (ULONG_PTR)WorkingSetList); 00562 } 00563 Tries = 1; 00564 } 00565 } 00566 Table[Hash].Key = 0; 00567 00568 } 00569 } 00570 00571 return; 00572 }

VOID MiRemoveWsleFromFreeList IN ULONG  Entry,
IN PMMWSLE  Wsle,
IN PMMWSL  WorkingSetList
 

Definition at line 799 of file wstree.c.

References ASSERT, MM_FREE_WSLE_SHIFT, WSLE_NULL_INDEX, and WSLE_NUMBER.

Referenced by MiSwapWslEntries().

00807 : 00808 00809 This routine removes a working set list entry from the free list. 00810 It is used when the entry required is not the first element 00811 in the free list. 00812 00813 Arguments: 00814 00815 Entry - Supplies the index of the entry to remove. 00816 00817 Wsle - Supplies a pointer to the array of WSLEs. 00818 00819 WorkingSetList - Supplies a pointer to the working set list. 00820 00821 Return Value: 00822 00823 None. 00824 00825 Environment: 00826 00827 Kernel mode, Working set lock and PFN lock held, APCs disabled. 00828 00829 --*/ 00830 00831 { 00832 WSLE_NUMBER Free; 00833 WSLE_NUMBER ParentFree; 00834 00835 Free = WorkingSetList->FirstFree; 00836 00837 if (Entry == Free) { 00838 ASSERT ((Wsle[Entry].u1.Long >> MM_FREE_WSLE_SHIFT) <= WorkingSetList->LastInitializedWsle); 00839 WorkingSetList->FirstFree = (WSLE_NUMBER)(Wsle[Entry].u1.Long >> MM_FREE_WSLE_SHIFT); 00840 00841 } else { 00842 do { 00843 ParentFree = Free; 00844 ASSERT (Wsle[Free].u1.e1.Valid == 0); 00845 Free = (WSLE_NUMBER)(Wsle[Free].u1.Long >> MM_FREE_WSLE_SHIFT); 00846 } while (Free != Entry); 00847 00848 Wsle[ParentFree].u1.Long = Wsle[Entry].u1.Long; 00849 } 00850 ASSERT ((WorkingSetList->FirstFree <= WorkingSetList->LastInitializedWsle) || 00851 (WorkingSetList->FirstFree == WSLE_NULL_INDEX)); 00852 return; 00853 }

PFN_NUMBER FASTCALL MiRemoveZeroPage IN ULONG  PageColor  ) 
 

Definition at line 1177 of file pfnlist.c.

References ASSERT, _MMCOLOR_TABLES::Flink, _MMPFNLIST::Flink, FreePageList, MI_BARRIER_STAMP_ZEROED_PAGE, MI_CHECK_PAGE_ALIGNMENT, MI_GET_SECONDARY_COLOR, MI_MAGIC_AWE_PTEFRAME, MI_PFN_ELEMENT, MiRemovePageByColor(), MiRemovePageFromList(), MiZeroPhysicalPage(), MM_COLOR_MASK, MM_EMPTY_LIST, MM_PFN_LOCK_ASSERT, MmAvailablePages, MmFreePageListHead, MmFreePagesByColor, MmStandbyPageListHead, MmZeroedPageListHead, PAGE_SHIFT, _MMPFN::PteFrame, _MMPFNLIST::Total, _MMPFN::u2, _MMPFN::u3, and ZeroedPageList.

Referenced by MiAddWorkingSetPage(), MiAddWsleHash(), MiDoneWithThisPageGetAnother(), MiInitializeSystemCache(), MiInitializeWorkingSetList(), MiResolveDemandZeroFault(), MiResolveMappedFileFault(), MiSessionInitializeWorkingSetList(), MmAddPhysicalMemory(), MmCheckCachedPageState(), MmInitSystem(), and MmShutdownSystem().

01183 : 01184 01185 This procedure removes a zero page from either the zeroed, free 01186 or standby lists (in that order). If no pages exist on the zeroed 01187 or free list a transition page is removed from the standby list 01188 and the PTE (may be a prototype PTE) which refers to this page is 01189 changed from transition back to its original contents. 01190 01191 If the page is not obtained from the zeroed list, it is zeroed. 01192 01193 Arguments: 01194 01195 PageColor - Supplies the page color for which this page is destined. 01196 This is used for checking virtual address alignments to 01197 determine if the D cache needs flushing before the page 01198 can be reused. 01199 01200 Return Value: 01201 01202 The physical page number removed from the specified list. 01203 01204 Environment: 01205 01206 Must be holding the PFN database mutex with APCs disabled. 01207 01208 --*/ 01209 01210 { 01211 PFN_NUMBER Page; 01212 PMMPFN Pfn1; 01213 ULONG Color; 01214 01215 MM_PFN_LOCK_ASSERT(); 01216 ASSERT(MmAvailablePages != 0); 01217 01218 // 01219 // Attempt to remove a page from the zeroed page list. If a page 01220 // is available, then remove it and return its page frame index. 01221 // Otherwise, attempt to remove a page from the free page list or 01222 // the standby list. 01223 // 01224 // N.B. It is not necessary to change page colors even if the old 01225 // color is not equal to the new color. The zero page thread 01226 // ensures that all zeroed pages are removed from all caches. 01227 // 01228 01229 if (MmFreePagesByColor[ZeroedPageList][PageColor].Flink != MM_EMPTY_LIST) { 01230 01231 // 01232 // Remove the first entry on the zeroed by color list. 01233 // 01234 01235 Page = MmFreePagesByColor[ZeroedPageList][PageColor].Flink; 01236 01237 #if DBG 01238 Pfn1 = MI_PFN_ELEMENT(Page); 01239 ASSERT (Pfn1->u3.e1.PageLocation == ZeroedPageList); 01240 ASSERT (Pfn1->PteFrame != MI_MAGIC_AWE_PTEFRAME); 01241 #endif 01242 01243 MiRemovePageByColor (Page, PageColor); 01244 01245 #if DBG 01246 ASSERT (Pfn1->u3.e1.PageColor == (PageColor & MM_COLOR_MASK)); 01247 ASSERT (Pfn1->u3.e2.ReferenceCount == 0); 01248 ASSERT (Pfn1->u2.ShareCount == 0); 01249 ASSERT (Pfn1->PteFrame != MI_MAGIC_AWE_PTEFRAME); 01250 #endif 01251 return Page; 01252 01253 } 01254 01255 // 01256 // No previously zeroed page with the specified secondary color exists. 01257 // Try a zeroed page of the primary color. 01258 // 01259 01260 if (MmZeroedPageListHead.Flink != MM_EMPTY_LIST) { 01261 Page = MmZeroedPageListHead.Flink; 01262 #if DBG 01263 Pfn1 = MI_PFN_ELEMENT(Page); 01264 ASSERT (Pfn1->u3.e1.PageLocation == ZeroedPageList); 01265 ASSERT (Pfn1->PteFrame != MI_MAGIC_AWE_PTEFRAME); 01266 #endif 01267 Color = MI_GET_SECONDARY_COLOR (Page, MI_PFN_ELEMENT(Page)); 01268 MiRemovePageByColor (Page, Color); 01269 #if DBG 01270 Pfn1 = MI_PFN_ELEMENT(Page); 01271 ASSERT (Pfn1->u3.e1.PageColor == (PageColor & MM_COLOR_MASK)); 01272 ASSERT (Pfn1->u3.e2.ReferenceCount == 0); 01273 ASSERT (Pfn1->u2.ShareCount == 0); 01274 ASSERT (Pfn1->PteFrame != MI_MAGIC_AWE_PTEFRAME); 01275 #endif 01276 return Page; 01277 } 01278 01279 // 01280 // No zeroed page of the primary color exists, try a free page of the 01281 // secondary color. 01282 // 01283 01284 if (MmFreePagesByColor[FreePageList][PageColor].Flink != MM_EMPTY_LIST) { 01285 01286 // 01287 // Remove the first entry on the free list by color. 01288 // 01289 01290 Page = MmFreePagesByColor[FreePageList][PageColor].Flink; 01291 01292 #if DBG 01293 Pfn1 = MI_PFN_ELEMENT(Page); 01294 ASSERT (Pfn1->u3.e1.PageLocation == FreePageList); 01295 ASSERT (Pfn1->PteFrame != MI_MAGIC_AWE_PTEFRAME); 01296 #endif 01297 01298 MiRemovePageByColor (Page, PageColor); 01299 #if DBG 01300 Pfn1 = MI_PFN_ELEMENT(Page); 01301 ASSERT (Pfn1->u3.e1.PageColor == (PageColor & MM_COLOR_MASK)); 01302 ASSERT (Pfn1->u3.e2.ReferenceCount == 0); 01303 ASSERT (Pfn1->u2.ShareCount == 0); 01304 ASSERT (Pfn1->PteFrame != MI_MAGIC_AWE_PTEFRAME); 01305 #endif 01306 goto ZeroPage; 01307 } 01308 01309 if (MmFreePageListHead.Flink != MM_EMPTY_LIST) { 01310 Page = MmFreePageListHead.Flink; 01311 01312 Color = MI_GET_SECONDARY_COLOR (Page, MI_PFN_ELEMENT(Page)); 01313 MiRemovePageByColor (Page, Color); 01314 #if DBG 01315 Pfn1 = MI_PFN_ELEMENT(Page); 01316 ASSERT (Pfn1->u3.e1.PageColor == (PageColor & MM_COLOR_MASK)); 01317 ASSERT (Pfn1->u3.e2.ReferenceCount == 0); 01318 ASSERT (Pfn1->u2.ShareCount == 0); 01319 ASSERT (Pfn1->PteFrame != MI_MAGIC_AWE_PTEFRAME); 01320 #endif 01321 goto ZeroPage; 01322 } 01323 01324 ASSERT (MmZeroedPageListHead.Total == 0); 01325 ASSERT (MmFreePageListHead.Total == 0); 01326 01327 if (MmZeroedPageListHead.Total != 0) { 01328 01329 Page = MiRemovePageFromList(&MmZeroedPageListHead); 01330 MI_CHECK_PAGE_ALIGNMENT(Page, PageColor & MM_COLOR_MASK); 01331 01332 } else { 01333 01334 // 01335 // Attempt to remove a page from the free list. If a page is 01336 // available, then remove it. Otherwise, attempt to remove a 01337 // page from the standby list. 01338 // 01339 01340 if (MmFreePageListHead.Total != 0) { 01341 Page = MiRemovePageFromList(&MmFreePageListHead); 01342 ASSERT ((MI_PFN_ELEMENT(Page))->PteFrame != MI_MAGIC_AWE_PTEFRAME); 01343 } else { 01344 01345 // 01346 // Remove a page from the standby list and restore the original 01347 // contents of the PTE to free the last reference to the physical 01348 // page. 01349 // 01350 01351 ASSERT (MmStandbyPageListHead.Total != 0); 01352 01353 Page = MiRemovePageFromList(&MmStandbyPageListHead); 01354 ASSERT ((MI_PFN_ELEMENT(Page))->PteFrame != MI_MAGIC_AWE_PTEFRAME); 01355 } 01356 01357 // 01358 // Zero the page removed from the free or standby list. 01359 // 01360 01361 ZeroPage: 01362 01363 Pfn1 = MI_PFN_ELEMENT(Page); 01364 01365 #if defined(_ALPHA_) 01366 HalZeroPage((PVOID)ULongToPtr((PageColor & MM_COLOR_MASK) << PAGE_SHIFT), 01367 (PVOID)ULongToPtr((Pfn1->u3.e1.PageColor) << PAGE_SHIFT), 01368 Page); 01369 #else 01370 MiZeroPhysicalPage (Page, 0); 01371 #endif 01372 01373 // 01374 // Note the stamping must occur after the page is zeroed. 01375 // 01376 01377 MI_BARRIER_STAMP_ZEROED_PAGE (&Pfn1->PteFrame); 01378 01379 Pfn1->u3.e1.PageColor = PageColor & MM_COLOR_MASK; 01380 01381 } 01382 01383 #if DBG 01384 Pfn1 = MI_PFN_ELEMENT (Page); 01385 ASSERT (Pfn1->u3.e2.ReferenceCount == 0); 01386 ASSERT (Pfn1->u2.ShareCount == 0); 01387 ASSERT (Pfn1->PteFrame != MI_MAGIC_AWE_PTEFRAME); 01388 #endif 01389 01390 return Page; 01391 }

PMMPTE MiReserveSystemPtes IN ULONG  NumberOfPtes,
IN MMSYSTEM_PTE_POOL_TYPE  SystemPteType,
IN ULONG  Alignment,
IN ULONG  Offset,
IN ULONG  BugCheckOnFailure
 

Definition at line 524 of file sysptes.c.

References ASSERT, Index, KeBugCheckEx(), KeFlushEntireTb(), MiFeedSysPtePool(), MiLockSystemSpace, MiReserveSystemPtes2(), MiUnlockSystemSpace, MM_DBG_SYS_PTES, MM_EMPTY_PTE_LIST, MM_FLUSH_COUNTER_MASK, MM_KERNEL_NOACCESS_PTE, MM_PTE_TABLE_LIMIT, MmFlushCounter, MmFlushPte1, MmFreeSysPteListBySize, MmLastSysPteListBySize, MmSysPteIndex, MmSysPteListBySizeCount, MmSysPteMinimumFree, MmSysPteTables, MmSystemPteBase, MmSystemPtesEnd, MmSystemPtesStart, NULL, Offset, PAGE_SHIFT, PTE_SHIFT, SystemPteSpace, TRUE, and _MMPTE::u.

Referenced by ExAllocatePool(), MiAllocatePoolPages(), MiBuildPagedPool(), MiFindContiguousMemory(), MiInitializeSpecialPool(), MiInitializeSystemPtes(), MiInitMachineDependent(), MiLoadImageSection(), MiMapBBTMemory(), MiMapSinglePage(), MiReloadBootLoadedDrivers(), MiSessionCreateInternal(), MmAllocateIndependentPages(), MmAllocateNonCachedMemory(), MmCreateKernelStack(), MmMapIoSpace(), MmMapLockedPagesSpecifyCache(), and MmMapVideoDisplay().

00534 : 00535 00536 This function locates the specified number of unused PTEs to locate 00537 within the non paged portion of system space. 00538 00539 Arguments: 00540 00541 NumberOfPtes - Supplies the number of PTEs to locate. 00542 00543 SystemPtePoolType - Supplies the PTE type of the pool to expand, one of 00544 SystemPteSpace or NonPagedPoolExpansion. 00545 00546 Alignment - Supplies the virtual address alignment for the address 00547 the returned PTE maps. For example, if the value is 64K, 00548 the returned PTE will map an address on a 64K boundary. 00549 An alignment of zero means to align on a page boundary. 00550 00551 Offset - Supplies the offset into the alignment for the virtual address. 00552 For example, if the Alignment is 64k and the Offset is 4k, 00553 the returned address will be 4k above a 64k boundary. 00554 00555 BugCheckOnFailure - Supplies FALSE if NULL should be returned if 00556 the request cannot be satisfied, TRUE if 00557 a bugcheck should be issued. 00558 00559 Return Value: 00560 00561 Returns the address of the first PTE located. 00562 NULL if no system PTEs can be located and BugCheckOnFailure is FALSE. 00563 00564 Environment: 00565 00566 Kernel mode, DISPATCH_LEVEL or below. 00567 00568 --*/ 00569 00570 { 00571 PMMPTE PointerPte; 00572 PMMPTE Previous; 00573 KIRQL OldIrql; 00574 ULONG PteMask; 00575 ULONG MaskSize; 00576 ULONG Index; 00577 00578 #ifdef _MI_GUARD_PTE_ 00579 ULONG ExactPtes; 00580 00581 if (NumberOfPtes == 0) { 00582 KeBugCheckEx (SYSTEM_PTE_MISUSE, 00583 0xA, 00584 BugCheckOnFailure, 00585 NumberOfPtes, 00586 SystemPtePoolType); 00587 } 00588 00589 if (SystemPtePoolType == SystemPteSpace) { 00590 NumberOfPtes += 1; 00591 } 00592 00593 ExactPtes = NumberOfPtes; 00594 #endif 00595 00596 if (SystemPtePoolType == SystemPteSpace) { 00597 00598 MaskSize = (Alignment - 1) >> (PAGE_SHIFT - PTE_SHIFT); 00599 PteMask = MaskSize & (Offset >> (PAGE_SHIFT - PTE_SHIFT)); 00600 00601 // 00602 // Acquire the system space lock to synchronize access to this 00603 // routine. 00604 // 00605 00606 MiLockSystemSpace(OldIrql); 00607 00608 if (NumberOfPtes <= MM_PTE_TABLE_LIMIT) { 00609 Index = MmSysPteTables [NumberOfPtes]; 00610 ASSERT (NumberOfPtes <= MmSysPteIndex[Index]); 00611 PointerPte = &MmFreeSysPteListBySize[Index]; 00612 #if DBG 00613 if (MmDebug & MM_DBG_SYS_PTES) { 00614 PMMPTE PointerPte1; 00615 PointerPte1 = &MmFreeSysPteListBySize[Index]; 00616 while (PointerPte1->u.List.NextEntry != MM_EMPTY_PTE_LIST) { 00617 PMMPTE PointerFreedPte; 00618 ULONG j; 00619 00620 PointerPte1 = MmSystemPteBase + PointerPte1->u.List.NextEntry; 00621 PointerFreedPte = PointerPte1; 00622 for (j = 0; j < MmSysPteIndex[Index]; j++) { 00623 ASSERT (PointerFreedPte->u.Hard.Valid == 0); 00624 PointerFreedPte++; 00625 } 00626 } 00627 } 00628 #endif //DBG 00629 00630 Previous = PointerPte; 00631 00632 while (PointerPte->u.List.NextEntry != MM_EMPTY_PTE_LIST) { 00633 00634 // 00635 // Try to find suitable PTEs with the proper alignment. 00636 // 00637 00638 Previous = PointerPte; 00639 PointerPte = MmSystemPteBase + PointerPte->u.List.NextEntry; 00640 #if !defined(_IA64_) 00641 if (PointerPte == MmFlushPte1) { 00642 KeFlushEntireTb (TRUE, TRUE); 00643 MmFlushCounter = (MmFlushCounter + 1) & MM_FLUSH_COUNTER_MASK; 00644 MmFlushPte1 = NULL; 00645 } 00646 #endif 00647 if ((Alignment == 0) || 00648 (((ULONG_PTR)PointerPte & MaskSize) == PteMask)) { 00649 00650 #ifdef _MI_SYSPTE_DEBUG_ 00651 MiCheckPteAllocation (PointerPte, 00652 NumberOfPtes, 00653 0, 00654 MmSysPteIndex[Index]); 00655 #endif 00656 // 00657 // Proper alignment and offset, update list index. 00658 // 00659 00660 ASSERT ((PointerPte->u.List.NextEntry + MmSystemPteBase) >= 00661 MmSystemPtesStart[SystemPtePoolType] || 00662 PointerPte->u.List.NextEntry == MM_EMPTY_PTE_LIST); 00663 ASSERT ((PointerPte->u.List.NextEntry + MmSystemPteBase) <= 00664 MmSystemPtesEnd[SystemPtePoolType] || 00665 PointerPte->u.List.NextEntry == MM_EMPTY_PTE_LIST); 00666 00667 Previous->u.List.NextEntry = PointerPte->u.List.NextEntry; 00668 MmSysPteListBySizeCount [Index] -= 1; 00669 00670 #if !defined(_IA64_) 00671 if (NumberOfPtes != 1) { 00672 00673 // 00674 // Check to see if the TB should be flushed. 00675 // 00676 00677 if ((PointerPte + 1)->u.List.NextEntry == MmFlushCounter) { 00678 KeFlushEntireTb (TRUE, TRUE); 00679 MmFlushCounter = (MmFlushCounter + 1) & 00680 MM_FLUSH_COUNTER_MASK; 00681 MmFlushPte1 = NULL; 00682 } 00683 } 00684 #endif 00685 if (PointerPte->u.List.NextEntry == MM_EMPTY_PTE_LIST) { 00686 MmLastSysPteListBySize[Index] = Previous; 00687 } 00688 #if DBG 00689 00690 if (MmDebug & MM_DBG_SYS_PTES) { 00691 PMMPTE PointerPte1; 00692 PointerPte1 = &MmFreeSysPteListBySize[Index]; 00693 while (PointerPte1->u.List.NextEntry != MM_EMPTY_PTE_LIST) { 00694 PMMPTE PointerFreedPte; 00695 ULONG j; 00696 00697 PointerPte1 = MmSystemPteBase + PointerPte1->u.List.NextEntry; 00698 PointerFreedPte = PointerPte1; 00699 for (j = 0; j < MmSysPteIndex[Index]; j++) { 00700 ASSERT (PointerFreedPte->u.Hard.Valid == 0); 00701 PointerFreedPte++; 00702 } 00703 } 00704 } 00705 #endif //DBG 00706 MiUnlockSystemSpace(OldIrql); 00707 00708 #if DBG 00709 PointerPte->u.List.NextEntry = 0xABCDE; 00710 if (MmDebug & MM_DBG_SYS_PTES) { 00711 00712 PMMPTE PointerFreedPte; 00713 ULONG j; 00714 00715 PointerFreedPte = PointerPte; 00716 for (j = 0; j < MmSysPteIndex[Index]; j++) { 00717 ASSERT (PointerFreedPte->u.Hard.Valid == 0); 00718 PointerFreedPte++; 00719 } 00720 } 00721 if (PointerPte < MmSystemPtesStart[SystemPtePoolType]) { 00722 KeBugCheckEx (SYSTEM_PTE_MISUSE, 00723 0xB, 00724 (ULONG_PTR)PointerPte, 00725 NumberOfPtes, 00726 SystemPtePoolType); 00727 } 00728 if (PointerPte > MmSystemPtesEnd[SystemPtePoolType]) { 00729 KeBugCheckEx (SYSTEM_PTE_MISUSE, 00730 0xC, 00731 (ULONG_PTR)PointerPte, 00732 NumberOfPtes, 00733 SystemPtePoolType); 00734 } 00735 #endif //DBG 00736 00737 if (MmSysPteListBySizeCount[Index] < 00738 MmSysPteMinimumFree[Index]) { 00739 MiFeedSysPtePool (Index); 00740 } 00741 #ifdef _MI_GUARD_PTE_ 00742 (PointerPte + ExactPtes - 1)->u.Long = MM_KERNEL_NOACCESS_PTE; 00743 #endif 00744 return PointerPte; 00745 } 00746 } 00747 NumberOfPtes = MmSysPteIndex [Index]; 00748 } 00749 MiUnlockSystemSpace(OldIrql); 00750 } 00751 00752 #ifdef _MI_GUARD_PTE_ 00753 NumberOfPtes = ExactPtes; 00754 #endif 00755 00756 PointerPte = MiReserveSystemPtes2 (NumberOfPtes, 00757 SystemPtePoolType, 00758 Alignment, 00759 Offset, 00760 BugCheckOnFailure); 00761 00762 #if DBG 00763 if (MmDebug & MM_DBG_SYS_PTES) { 00764 00765 PMMPTE PointerFreedPte; 00766 ULONG j; 00767 00768 if (PointerPte) { 00769 PointerFreedPte = PointerPte; 00770 for (j = 0; j < NumberOfPtes; j++) { 00771 ASSERT (PointerFreedPte->u.Hard.Valid == 0); 00772 PointerFreedPte++; 00773 } 00774 } 00775 } 00776 #endif //DBG 00777 00778 #ifdef _MI_GUARD_PTE_ 00779 if (PointerPte) { 00780 (PointerPte + ExactPtes - 1)->u.Long = MM_KERNEL_NOACCESS_PTE; 00781 } 00782 #endif 00783 00784 return PointerPte; 00785 }

NTSTATUS MiResolveDemandZeroFault IN PVOID  VirtualAddress,
IN PMMPTE  PointerPte,
IN PEPROCESS  Process,
IN ULONG  PrototypePte
 

Definition at line 674 of file pagfault.c.

References APC_LEVEL, ASSERT, CONSISTENCY_LOCK_PFN, CONSISTENCY_UNLOCK_PFN, _MMINFO_COUNTERS::DemandZeroCount, FALSE, HYDRA_PROCESS, LOCK_PFN, MI_BARRIER_STAMP_ZEROED_PAGE, MI_BARRIER_SYNCHRONIZE, MI_IS_PAGE_TABLE_ADDRESS, MI_MAKE_VALID_PTE, MI_PAGE_COLOR_VA_PROCESS, MI_PFN_ELEMENT, MI_SET_PTE_DIRTY, MI_WRITE_VALID_PTE, MiAddValidPageToWorkingSet(), MiEnsureAvailablePageOrWait(), MiInitializePfn(), MiRemoveAnyPage(), MiRemoveZeroPage(), MiRemoveZeroPageIfAny, MiWaitForForkToComplete(), MiZeroPhysicalPage(), MM_PFN_LOCK_ASSERT, MmInfoCounters, MmSystemPageColor, NULL, PERFINFO_PRIVATE_PAGE_DEMAND_ZERO, PERFINFO_SOFTFAULT, PrototypePte, PsGetCurrentThread, _MMPFN::PteFrame, STATUS_REFAULT, TRUE, _MMPTE::u, _MMPFN::u1, and UNLOCK_PFN.

Referenced by MiDispatchFault(), MiResolveProtoPteFault(), and MmAccessFault().

00683 : 00684 00685 This routine resolves a demand zero page fault. 00686 00687 If the PrototypePte argument is TRUE, the PFN lock is 00688 held, the lock cannot be dropped, and the page should 00689 not be added to the working set at this time. 00690 00691 Arguments: 00692 00693 VirtualAddress - Supplies the faulting address. 00694 00695 PointerPte - Supplies the PTE for the faulting address. 00696 00697 Process - Supplies a pointer to the process object. If this 00698 parameter is NULL, then the fault is for system 00699 space and the process's working set lock is not held. 00700 00701 PrototypePte - Supplies TRUE if this is a prototype PTE. 00702 00703 Return Value: 00704 00705 status, either STATUS_SUCCESS or STATUS_REFAULT. 00706 00707 Environment: 00708 00709 Kernel mode, PFN lock held conditionally. 00710 00711 --*/ 00712 00713 00714 { 00715 PMMPFN Pfn1; 00716 PFN_NUMBER PageFrameIndex; 00717 MMPTE TempPte; 00718 ULONG PageColor; 00719 KIRQL OldIrql; 00720 LOGICAL NeedToZero; 00721 LOGICAL BarrierNeeded; 00722 ULONG BarrierStamp; 00723 00724 NeedToZero = FALSE; 00725 BarrierNeeded = FALSE; 00726 00727 PERFINFO_PRIVATE_PAGE_DEMAND_ZERO(VirtualAddress); 00728 00729 // 00730 // Check to see if a page is available, if a wait is 00731 // returned, do not continue, just return success. 00732 // 00733 00734 if (!PrototypePte) { 00735 LOCK_PFN (OldIrql); 00736 } 00737 00738 MM_PFN_LOCK_ASSERT(); 00739 00740 if (PointerPte->u.Hard.Valid == 0) { 00741 if (!MiEnsureAvailablePageOrWait (Process, 00742 VirtualAddress)) { 00743 00744 if (Process != NULL && Process != HYDRA_PROCESS && (!PrototypePte)) { 00745 // 00746 // If a fork operation is in progress and the faulting thread 00747 // is not the thread performing the fork operation, block until 00748 // the fork is completed. 00749 // 00750 00751 if ((Process->ForkInProgress != NULL) && 00752 (Process->ForkInProgress != PsGetCurrentThread())) { 00753 MiWaitForForkToComplete (Process); 00754 UNLOCK_PFN (APC_LEVEL); 00755 return STATUS_REFAULT; 00756 } 00757 00758 Process->NumberOfPrivatePages += 1; 00759 PageColor = MI_PAGE_COLOR_VA_PROCESS (VirtualAddress, 00760 &Process->NextPageColor); 00761 00762 ASSERT (MI_IS_PAGE_TABLE_ADDRESS(PointerPte)); 00763 00764 PageFrameIndex = MiRemoveZeroPageIfAny (PageColor); 00765 if (PageFrameIndex) { 00766 00767 // 00768 // This barrier check is needed after zeroing the page 00769 // and before setting the PTE valid. Note since the PFN 00770 // database entry is used to hold the sequence timestamp, 00771 // it must be captured now. Check it at the last possible 00772 // moment. 00773 // 00774 00775 Pfn1 = MI_PFN_ELEMENT (PageFrameIndex); 00776 BarrierStamp = (ULONG)Pfn1->PteFrame; 00777 } 00778 else { 00779 PageFrameIndex = MiRemoveAnyPage (PageColor); 00780 NeedToZero = TRUE; 00781 } 00782 BarrierNeeded = TRUE; 00783 00784 } else { 00785 PageColor = MI_PAGE_COLOR_VA_PROCESS (VirtualAddress, 00786 &MmSystemPageColor); 00787 // 00788 // As this is a system page, there is no need to 00789 // remove a page of zeroes, it must be initialized by 00790 // the system before being used. 00791 // 00792 00793 if (PrototypePte) { 00794 PageFrameIndex = MiRemoveZeroPage (PageColor); 00795 } else { 00796 PageFrameIndex = MiRemoveAnyPage (PageColor); 00797 } 00798 } 00799 00800 MmInfoCounters.DemandZeroCount += 1; 00801 00802 MiInitializePfn (PageFrameIndex, PointerPte, 1); 00803 00804 if (!PrototypePte) { 00805 UNLOCK_PFN (APC_LEVEL); 00806 } 00807 00808 Pfn1 = MI_PFN_ELEMENT (PageFrameIndex); 00809 00810 if (NeedToZero) { 00811 00812 MiZeroPhysicalPage (PageFrameIndex, PageColor); 00813 00814 // 00815 // Note the stamping must occur after the page is zeroed. 00816 // 00817 00818 MI_BARRIER_STAMP_ZEROED_PAGE (&BarrierStamp); 00819 } 00820 00821 // 00822 // As this page is demand zero, set the modified bit in the 00823 // PFN database element and set the dirty bit in the PTE. 00824 // 00825 00826 PERFINFO_SOFTFAULT(Pfn1, VirtualAddress, PERFINFO_LOG_TYPE_DEMANDZEROFAULT) 00827 00828 MI_MAKE_VALID_PTE (TempPte, 00829 PageFrameIndex, 00830 PointerPte->u.Soft.Protection, 00831 PointerPte); 00832 00833 if (TempPte.u.Hard.Write != 0) { 00834 MI_SET_PTE_DIRTY (TempPte); 00835 } 00836 00837 if (BarrierNeeded) { 00838 MI_BARRIER_SYNCHRONIZE (BarrierStamp); 00839 } 00840 00841 MI_WRITE_VALID_PTE (PointerPte, TempPte); 00842 00843 if (!PrototypePte) { 00844 ASSERT (Pfn1->u1.Event == 0); 00845 00846 CONSISTENCY_LOCK_PFN (OldIrql); 00847 00848 Pfn1->u1.Event = (PVOID)PsGetCurrentThread(); 00849 00850 CONSISTENCY_UNLOCK_PFN (OldIrql); 00851 00852 MiAddValidPageToWorkingSet (VirtualAddress, 00853 PointerPte, 00854 Pfn1, 00855 0); 00856 } 00857 return STATUS_PAGE_FAULT_DEMAND_ZERO; 00858 } 00859 } 00860 if (!PrototypePte) { 00861 UNLOCK_PFN (APC_LEVEL); 00862 } 00863 return STATUS_REFAULT; 00864 }

NTSTATUS MiResolveMappedFileFault IN PVOID  FaultingAddress,
IN PMMPTE  PointerPte,
IN PMMINPAGE_SUPPORT ReadBlock,
IN PEPROCESS  Process
 

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,
OUT PLOGICAL  ApcNeeded
 

NTSTATUS MiResolveTransitionFault IN PVOID  FaultingAddress,
IN PMMPTE  PointerPte,
IN PEPROCESS  Process,
IN ULONG  PfnLockHeld,
OUT PLOGICAL  ApcNeeded
 

Definition at line 868 of file pagfault.c.

References ActiveAndValid, APC_LEVEL, _ETHREAD::ApcNeeded, ASSERT, DbgPrint, FreePageList, HYDRA_PROCESS, KeEnterCriticalRegion, KeLeaveCriticalRegion, LOCK_PFN, MI_ADD_LOCKED_PAGE_CHARGE_FOR_MODIFIED_PAGE, MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE, MI_MAKE_TRANSITION_PTE_VALID, MI_PFN_ELEMENT, MI_REMOVE_LOCKED_PAGE_CHARGE, MI_SET_PTE_CLEAN, MI_SET_PTE_DIRTY, MI_WRITE_VALID_PTE, MiAddValidPageToWorkingSet(), MiDecrementReferenceCount(), MiFormatPfn(), MiGetPteAddress, MiInsertPageInList(), MiRestoreTransitionPte(), MiUnlinkPageFromList(), MiWaitForInPageComplete(), MM_DBG_COLLIDED_PAGE, MmInfoCounters, MmPagedPoolEnd, MmPagedPoolStart, MmPageLocationList, MmSpecialPoolEnd, MmSpecialPoolStart, _ETHREAD::NestedFaultCount, NT_SUCCESS, NTSTATUS(), NULL, PERFINFO_SOFTFAULT, PsGetCurrentThread, _MMPFN::PteAddress, StandbyPageList, STATUS_REFAULT, _MMINFO_COUNTERS::TransitionCount, TRUE, _MMPTE::u, _MMINPAGE_SUPPORT::u, _MMPFN::u1, _MMPFN::u2, _MMPFN::u3, UNLOCK_PFN, UNLOCK_SESSION_SPACE_WS, UNLOCK_SYSTEM_WS, UNLOCK_WS, and _MMINPAGE_SUPPORT::WaitCount.

Referenced by MiDispatchFault(), and MiResolveProtoPteFault().

00878 : 00879 00880 This routine resolves a transition page fault. 00881 00882 Arguments: 00883 00884 FaultingAddress - Supplies the faulting address. 00885 00886 PointerPte - Supplies the PTE for the faulting address. 00887 00888 CurrentProcess - Supplies a pointer to the process object. If this 00889 parameter is NULL, then the fault is for system 00890 space and the process's working set lock is not held. 00891 00892 PfnLockHeld - Supplies TRUE if the PFN lock is held, FALSE if not. 00893 00894 ApcNeeded - Supplies a pointer to a location set to TRUE if an I/O 00895 completion APC is needed to complete partial IRPs that 00896 collided. 00897 00898 It is the caller's responsibility to initialize this (usually 00899 to FALSE) on entry. However, since this routine may be called 00900 multiple times for a single fault (for the page directory, 00901 page table and the page itself), it is possible for it to 00902 occasionally be TRUE on entry. 00903 00904 If it is FALSE on exit, no completion APC is needed. 00905 00906 Return Value: 00907 00908 status, either STATUS_SUCCESS, STATUS_REFAULT or an I/O status 00909 code. 00910 00911 Environment: 00912 00913 Kernel mode, PFN lock may optionally be held. 00914 00915 --*/ 00916 00917 { 00918 PFN_NUMBER PageFrameIndex; 00919 PMMPFN Pfn1; 00920 MMPTE TempPte; 00921 NTSTATUS status; 00922 NTSTATUS PfnStatus; 00923 PMMINPAGE_SUPPORT CapturedEvent; 00924 KIRQL OldIrql; 00925 PETHREAD CurrentThread; 00926 00927 // 00928 // *********************************************************** 00929 // Transition PTE. 00930 // *********************************************************** 00931 // 00932 00933 // 00934 // A transition PTE is either on the free or modified list, 00935 // on neither list because of its ReferenceCount 00936 // or currently being read in from the disk (read in progress). 00937 // If the page is read in progress, this is a collided page 00938 // and must be handled accordingly. 00939 // 00940 00941 if (!PfnLockHeld) { 00942 LOCK_PFN (OldIrql); 00943 } 00944 00945 TempPte = *PointerPte; 00946 00947 if ((TempPte.u.Soft.Valid == 0) && 00948 (TempPte.u.Soft.Prototype == 0) && 00949 (TempPte.u.Soft.Transition == 1)) { 00950 00951 // 00952 // Still in transition format. 00953 // 00954 00955 MmInfoCounters.TransitionCount += 1; 00956 00957 PageFrameIndex = MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE (&TempPte); 00958 Pfn1 = MI_PFN_ELEMENT (PageFrameIndex); 00959 00960 if (Pfn1->u3.e1.InPageError) { 00961 00962 // 00963 // There was an in-page read error and there are other 00964 // threads colliding for this page, delay to let the 00965 // other threads complete and return. 00966 // 00967 00968 ASSERT (!NT_SUCCESS(Pfn1->u1.ReadStatus)); 00969 if (!PfnLockHeld) { 00970 UNLOCK_PFN (APC_LEVEL); 00971 } 00972 00973 return Pfn1->u1.ReadStatus; 00974 } 00975 00976 if (Pfn1->u3.e1.ReadInProgress) { 00977 00978 // 00979 // Collided page fault. 00980 // 00981 00982 #if DBG 00983 if (MmDebug & MM_DBG_COLLIDED_PAGE) { 00984 DbgPrint("MM:collided page fault\n"); 00985 } 00986 #endif 00987 00988 CapturedEvent = (PMMINPAGE_SUPPORT)Pfn1->u1.Event; 00989 00990 CurrentThread = PsGetCurrentThread(); 00991 00992 if (CapturedEvent->u.Thread == CurrentThread) { 00993 00994 // 00995 // This detects MmCopyToCachedPage deadlocks where both the 00996 // user and system address point at the same physical page. 00997 // 00998 // It also detects when the Io APC completion routine accesses 00999 // the same user page (ie: during an overlapped I/O) that 01000 // the user thread has already faulted on. 01001 // 01002 // Both cases above can result in fatal deadlocks and so must 01003 // be detected here. Return a unique status code so the 01004 // (legitimate) callers know this has happened so it can be 01005 // handled properly. In the first case above this means 01006 // restarting the entire operation immediately. In the second 01007 // case above it means requesting a callback from the Mm 01008 // once the first fault has completed. 01009 // 01010 // Note that non-legitimate callers must get back a failure 01011 // status so the thread can be terminated. 01012 // 01013 01014 ASSERT ((CurrentThread->NestedFaultCount == 1) || 01015 (CurrentThread->NestedFaultCount == 2)); 01016 01017 CurrentThread->ApcNeeded = 1; 01018 01019 if (!PfnLockHeld) { 01020 UNLOCK_PFN (APC_LEVEL); 01021 } 01022 return STATUS_MULTIPLE_FAULT_VIOLATION; 01023 } 01024 01025 // 01026 // Increment the reference count for the page so it won't be 01027 // reused until all collisions have been completed. 01028 // 01029 01030 ASSERT (Pfn1->u2.ShareCount == 0); 01031 ASSERT (Pfn1->u3.e2.ReferenceCount != 0); 01032 ASSERT (Pfn1->u3.e1.LockCharged == 1); 01033 01034 Pfn1->u3.e2.ReferenceCount += 1; 01035 01036 CapturedEvent->WaitCount += 1; 01037 01038 UNLOCK_PFN (APC_LEVEL); 01039 01040 if (CurrentProcess == HYDRA_PROCESS) { 01041 CurrentThread = NULL; 01042 UNLOCK_SESSION_SPACE_WS (APC_LEVEL); 01043 } 01044 else if (CurrentProcess != NULL) { 01045 01046 // 01047 // APCs must be explicitly disabled to prevent suspend APCs from 01048 // interrupting this thread before the wait has been issued. 01049 // Otherwise the APC can result in this page being locked 01050 // indefinitely until the suspend is released. 01051 // 01052 01053 ASSERT (CurrentThread->NestedFaultCount <= 2); 01054 CurrentThread->NestedFaultCount += 1; 01055 01056 KeEnterCriticalRegion(); 01057 UNLOCK_WS (CurrentProcess); 01058 } 01059 else { 01060 CurrentThread = NULL; 01061 UNLOCK_SYSTEM_WS (APC_LEVEL); 01062 } 01063 01064 status = MiWaitForInPageComplete (Pfn1, 01065 PointerPte, 01066 FaultingAddress, 01067 &TempPte, 01068 CapturedEvent, 01069 CurrentProcess); 01070 // 01071 // MiWaitForInPageComplete RETURNS WITH THE WORKING SET LOCK 01072 // AND PFN LOCK HELD!!! 01073 // 01074 01075 if (CurrentThread != NULL) { 01076 KeLeaveCriticalRegion(); 01077 01078 ASSERT (CurrentThread->NestedFaultCount <= 3); 01079 ASSERT (CurrentThread->NestedFaultCount != 0); 01080 01081 CurrentThread->NestedFaultCount -= 1; 01082 01083 if ((CurrentThread->ApcNeeded == 1) && 01084 (CurrentThread->NestedFaultCount == 0)) { 01085 *ApcNeeded = TRUE; 01086 CurrentThread->ApcNeeded = 0; 01087 } 01088 } 01089 01090 ASSERT (Pfn1->u3.e1.ReadInProgress == 0); 01091 01092 if (status != STATUS_SUCCESS) { 01093 PfnStatus = Pfn1->u1.ReadStatus; 01094 MI_REMOVE_LOCKED_PAGE_CHARGE(Pfn1, 9); 01095 MiDecrementReferenceCount (PageFrameIndex); 01096 01097 // 01098 // Check to see if an I/O error occurred on this page. 01099 // If so, try to free the physical page, wait a 01100 // half second and return a status of PTE_CHANGED. 01101 // This will result in success being returned to 01102 // the user and the fault will occur again and should 01103 // not be a transition fault this time. 01104 // 01105 01106 if (Pfn1->u3.e1.InPageError == 1) { 01107 ASSERT (!NT_SUCCESS(PfnStatus)); 01108 status = PfnStatus; 01109 if (Pfn1->u3.e2.ReferenceCount == 0) { 01110 01111 Pfn1->u3.e1.InPageError = 0; 01112 01113 // 01114 // Only restore the transition PTE if the address 01115 // space still exists. Another thread may have 01116 // deleted the VAD while this thread waited for the 01117 // fault to complete - in this case, the frame 01118 // will be marked as free already. 01119 // 01120 01121 if (Pfn1->u3.e1.PageLocation != FreePageList) { 01122 ASSERT (Pfn1->u3.e1.PageLocation == 01123 StandbyPageList); 01124 MiUnlinkPageFromList (Pfn1); 01125 MiRestoreTransitionPte (PageFrameIndex); 01126 01127 MiInsertPageInList(MmPageLocationList[FreePageList], 01128 PageFrameIndex); 01129 } 01130 } 01131 } 01132 01133 #if DBG 01134 if (MmDebug & MM_DBG_COLLIDED_PAGE) { 01135 DbgPrint("MM:decrement ref count - pte changed\n"); 01136 MiFormatPfn(Pfn1); 01137 } 01138 #endif 01139 if (!PfnLockHeld) { 01140 UNLOCK_PFN (APC_LEVEL); 01141 } 01142 01143 // 01144 // Instead of returning status, always return STATUS_REFAULT. 01145 // This is to support filesystems that save state in the 01146 // ETHREAD of the thread that serviced the fault ! Since 01147 // collided threads never enter the filesystem, their ETHREADs 01148 // haven't been hacked up. Since this only matters when 01149 // errors occur (specifically STATUS_VERIFY_REQUIRED today), 01150 // retry any failed I/O in the context of each collider 01151 // to give the filesystems ample opportunity. 01152 // 01153 01154 return STATUS_REFAULT; 01155 } 01156 01157 } else { 01158 01159 // 01160 // PTE refers to a normal transition PTE. 01161 // 01162 01163 ASSERT (Pfn1->u3.e1.InPageError == 0); 01164 if (Pfn1->u3.e1.PageLocation == ActiveAndValid) { 01165 01166 // 01167 // This page must contain an MmSt allocation of prototype PTEs. 01168 // Because these types of pages reside in paged pool (or special 01169 // pool) and are part of the system working set, they can be 01170 // trimmed at any time regardless of the share count. However, 01171 // if the share count is nonzero, then the page state will 01172 // remain active and the page will remain in memory - but the 01173 // PTE will be set to the transition state. Make the page 01174 // valid without incrementing the reference count, but 01175 // increment the share count. 01176 // 01177 01178 ASSERT (((Pfn1->PteAddress >= MiGetPteAddress(MmPagedPoolStart)) && 01179 (Pfn1->PteAddress <= MiGetPteAddress(MmPagedPoolEnd))) || 01180 ((Pfn1->PteAddress >= MiGetPteAddress(MmSpecialPoolStart)) && 01181 (Pfn1->PteAddress <= MiGetPteAddress(MmSpecialPoolEnd)))); 01182 01183 // 01184 // Don't increment the valid PTE count for the 01185 // page table page. 01186 // 01187 01188 ASSERT (Pfn1->u2.ShareCount != 0); 01189 ASSERT (Pfn1->u3.e2.ReferenceCount != 0); 01190 01191 } else { 01192 01193 MiUnlinkPageFromList (Pfn1); 01194 01195 // 01196 // Update the PFN database - the reference count must be 01197 // incremented as the share count is going to go from zero to 1. 01198 // 01199 01200 ASSERT (Pfn1->u2.ShareCount == 0); 01201 01202 // 01203 // The PFN reference count will be 1 already here if the 01204 // modified writer has begun a write of this page. Otherwise 01205 // it's ordinarily 0. 01206 // 01207 01208 MI_ADD_LOCKED_PAGE_CHARGE_FOR_MODIFIED_PAGE (Pfn1, 8); 01209 01210 Pfn1->u3.e2.ReferenceCount += 1; 01211 } 01212 } 01213 01214 // 01215 // Join with collided page fault code to handle updating 01216 // the transition PTE. 01217 // 01218 01219 ASSERT (Pfn1->u3.e1.InPageError == 0); 01220 01221 if (Pfn1->u2.ShareCount == 0) { 01222 MI_REMOVE_LOCKED_PAGE_CHARGE (Pfn1, 9); 01223 } 01224 01225 Pfn1->u2.ShareCount += 1; 01226 Pfn1->u3.e1.PageLocation = ActiveAndValid; 01227 01228 MI_MAKE_TRANSITION_PTE_VALID (TempPte, PointerPte); 01229 01230 // 01231 // If the modified field is set in the PFN database and this 01232 // page is not copy on modify, then set the dirty bit. 01233 // This can be done as the modified page will not be 01234 // written to the paging file until this PTE is made invalid. 01235 // 01236 01237 if (Pfn1->u3.e1.Modified && TempPte.u.Hard.Write && 01238 (TempPte.u.Hard.CopyOnWrite == 0)) { 01239 MI_SET_PTE_DIRTY (TempPte); 01240 } else { 01241 MI_SET_PTE_CLEAN (TempPte); 01242 } 01243 01244 MI_WRITE_VALID_PTE (PointerPte, TempPte); 01245 01246 if (!PfnLockHeld) { 01247 01248 if (Pfn1->u1.Event == 0) { 01249 Pfn1->u1.Event = (PVOID)PsGetCurrentThread(); 01250 } 01251 01252 UNLOCK_PFN (APC_LEVEL); 01253 01254 PERFINFO_SOFTFAULT(Pfn1, FaultingAddress, PERFINFO_LOG_TYPE_TRANSITIONFAULT) 01255 01256 MiAddValidPageToWorkingSet (FaultingAddress, 01257 PointerPte, 01258 Pfn1, 01259 0); 01260 } 01261 return STATUS_PAGE_FAULT_TRANSITION; 01262 } else { 01263 if (!PfnLockHeld) { 01264 UNLOCK_PFN (APC_LEVEL); 01265 } 01266 } 01267 return STATUS_REFAULT; 01268 }

VOID FASTCALL MiRestoreTransitionPte IN PFN_NUMBER  PageFrameIndex  ) 
 

Definition at line 1245 of file mmsup.c.

References ASSERT, _SUBSECTION::ControlArea, MI_CAPTURE_USED_PAGETABLE_ENTRIES, MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE, MI_IS_SESSION_PTE, MI_PFN_ELEMENT, MI_WRITE_INVALID_PTE, MiCheckForControlAreaDeletion(), MiDecrementShareCount(), MiGetByteOffset, MiGetPteAddress, MiGetSubsectionAddress, MiMapPageInHyperSpace(), MiUnmapPageInHyperSpace, MM_SYSTEM_SPACE_START, MmIsAddressValid(), _CONTROL_AREA::NumberOfPfnReferences, _MMPFN::OriginalPte, _MMPFN::PteAddress, _MMPFN::PteFrame, StandbyPageList, _MMPTE::u, and _MMPFN::u3.

Referenced by MiDecrementReferenceCount(), MiDispatchFault(), MiFindContiguousMemory(), MiInsertPageInList(), MiRemovePageFromList(), MiRemovePhysicalPages(), MiResolveTransitionFault(), and MmAllocatePagesForMdl().

01251 : 01252 01253 This procedure restores the original contents into the PTE (which could 01254 be a prototype PTE) referred to by the PFN database for the specified 01255 physical page. It also updates all necessary data structures to 01256 reflect the fact that the referenced PTE is no longer in transition. 01257 01258 The physical address of the referenced PTE is mapped into hyper space 01259 of the current process and the PTE is then updated. 01260 01261 Arguments: 01262 01263 PageFrameIndex - Supplies the physical page number which refers to a 01264 transition PTE. 01265 01266 Return Value: 01267 01268 none. 01269 01270 Environment: 01271 01272 Must be holding the PFN database mutex with APCs disabled. 01273 01274 --*/ 01275 01276 { 01277 PMMPFN Pfn1; 01278 PMMPTE PointerPte; 01279 PSUBSECTION Subsection; 01280 PCONTROL_AREA ControlArea; 01281 KIRQL OldIrql = 99; 01282 01283 Pfn1 = MI_PFN_ELEMENT (PageFrameIndex); 01284 01285 ASSERT (Pfn1->u3.e1.PageLocation == StandbyPageList); 01286 01287 if (Pfn1->u3.e1.PrototypePte) { 01288 01289 if (MmIsAddressValid (Pfn1->PteAddress)) { 01290 PointerPte = Pfn1->PteAddress; 01291 } else { 01292 01293 // 01294 // The page containing the prototype PTE is not valid, 01295 // map the page into hyperspace and reference it that way. 01296 // 01297 01298 PointerPte = MiMapPageInHyperSpace (Pfn1->PteFrame, &OldIrql); 01299 PointerPte = (PMMPTE)((PCHAR)PointerPte + 01300 MiGetByteOffset(Pfn1->PteAddress)); 01301 } 01302 01303 ASSERT ((MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE (PointerPte) == PageFrameIndex) && 01304 (PointerPte->u.Hard.Valid == 0)); 01305 01306 // 01307 // This page is referenced by a prototype PTE. The 01308 // segment structures need to be updated when the page 01309 // is removed from the transition state. 01310 // 01311 01312 if (Pfn1->OriginalPte.u.Soft.Prototype) { 01313 01314 // 01315 // The prototype PTE is in subsection format, calculate the 01316 // address of the control area for the subsection and decrement 01317 // the number of PFN references to the control area. 01318 // 01319 // Calculate address of subsection for this prototype PTE. 01320 // 01321 01322 Subsection = MiGetSubsectionAddress (&Pfn1->OriginalPte); 01323 ControlArea = Subsection->ControlArea; 01324 ControlArea->NumberOfPfnReferences -= 1; 01325 ASSERT ((LONG)ControlArea->NumberOfPfnReferences >= 0); 01326 01327 MiCheckForControlAreaDeletion (ControlArea); 01328 } 01329 01330 } else { 01331 01332 // 01333 // The page points to a page or page table page which may not be 01334 // for the current process. Map the page into hyperspace and 01335 // reference it through hyperspace. If the page resides in 01336 // system space (but not session space), it does not need to be 01337 // mapped as all PTEs for system space must be resident. Session 01338 // space PTEs are only mapped per session so access to them must 01339 // also go through hyperspace. 01340 // 01341 01342 PointerPte = Pfn1->PteAddress; 01343 01344 if (PointerPte < MiGetPteAddress (MM_SYSTEM_SPACE_START) || 01345 MI_IS_SESSION_PTE (PointerPte)) { 01346 01347 PointerPte = MiMapPageInHyperSpace (Pfn1->PteFrame, &OldIrql); 01348 PointerPte = (PMMPTE)((PCHAR)PointerPte + 01349 MiGetByteOffset(Pfn1->PteAddress)); 01350 } 01351 ASSERT ((MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE (PointerPte) == PageFrameIndex) && 01352 (PointerPte->u.Hard.Valid == 0)); 01353 01354 MI_CAPTURE_USED_PAGETABLE_ENTRIES (Pfn1); 01355 01356 #if _WIN64 01357 #if DBGXX 01358 MiCheckPageTableTrim(PointerPte); 01359 #endif 01360 #endif 01361 } 01362 01363 ASSERT (Pfn1->OriginalPte.u.Hard.Valid == 0); 01364 ASSERT (!((Pfn1->OriginalPte.u.Soft.Prototype == 0) && 01365 (Pfn1->OriginalPte.u.Soft.Transition == 1))); 01366 01367 MI_WRITE_INVALID_PTE (PointerPte, Pfn1->OriginalPte); 01368 01369 if (OldIrql != 99) { 01370 MiUnmapPageInHyperSpace (OldIrql); 01371 } 01372 01373 // 01374 // The PTE has been restored to its original contents and is 01375 // no longer in transition. Decrement the share count on 01376 // the page table page which contains the PTE. 01377 // 01378 01379 MiDecrementShareCount (Pfn1->PteFrame); 01380 01381 return; 01382 }

VOID FASTCALL MiReturnCommitment IN SIZE_T  QuotaCharge  ) 
 

Definition at line 442 of file mmquota.c.

References ASSERT, FALSE, MiCommitExtensionActive, MmChargeCommitmentLock, MmExtendedCommit, MmExtendedCommitLimit, MmPageFileFullExtendPages, MmTotalCommitLimit, MmTotalCommittedPages, and TRUE.

Referenced by MiCreateImageFileMap(), MiCreatePagingFileMap(), MiDereferenceSession(), MiFreeNonPagedPool(), MiFreePoolPages(), MiInitializeSessionPool(), MiLoadImageSection(), MiMapViewOfDataSection(), MiPageFileFull(), MiRemoveVad(), MiReturnPageTablePageCommitment(), MiSegmentDelete(), MiSessionCommitImagePages(), MiSessionCommitPageTables(), MiSessionCreateInternal(), MiSessionInitializeWorkingSetList(), MiSetProtectionOnSection(), MiShareSessionImage(), MmAllocateNonCachedMemory(), MmAllocatePagesForMdl(), MmCleanProcessAddressSpace(), MmCreateKernelStack(), MmCreateProcessAddressSpace(), MmDeleteKernelStack(), MmDeleteProcessAddressSpace(), MmFreeDriverInitialization(), MmFreeNonCachedMemory(), MmFreePagesFromMdl(), MmFreeSpecialPool(), MmRemovePhysicalMemory(), MmUnloadSystemImage(), NtAllocateVirtualMemory(), NtCreatePagingFile(), and NtFreeVirtualMemory().

00448 : 00449 00450 This routine releases page file quota. 00451 00452 Arguments: 00453 00454 QuotaCharge - Supplies the quota amount to charge. 00455 00456 CurrentProcess - Supplies a pointer to the current process. 00457 00458 Return Value: 00459 00460 none. 00461 00462 Environment: 00463 00464 Kernel mode, APCs disabled, WorkingSetLock and AddressCreation mutexes 00465 held. 00466 00467 --*/ 00468 00469 { 00470 KIRQL OldIrql; 00471 00472 ExAcquireFastLock (&MmChargeCommitmentLock, &OldIrql); 00473 00474 ASSERT (MmTotalCommittedPages >= QuotaCharge); 00475 00476 MmTotalCommittedPages -= QuotaCharge; 00477 00478 // 00479 // If commit allotments have been temporarily blocked then open the 00480 // floodgates provided either enough commit has been freed or the pagefile 00481 // extension has succeeded. 00482 // 00483 00484 if (MmPageFileFullExtendPages) { 00485 ASSERT (MmTotalCommittedPages >= MmPageFileFullExtendPages); 00486 MmTotalCommittedPages -= MmPageFileFullExtendPages; 00487 MmPageFileFullExtendPages = 0; 00488 } 00489 00490 // 00491 // If the system automatically granted an increase that can be returned 00492 // now, do it. 00493 // 00494 00495 if (MiCommitExtensionActive == TRUE) { 00496 00497 if ((MmExtendedCommitLimit != 0) && 00498 (MmTotalCommitLimit > MmTotalCommittedPages) && 00499 (MmTotalCommitLimit - MmTotalCommittedPages > MmExtendedCommitLimit)) { 00500 MmTotalCommitLimit -= MmExtendedCommitLimit; 00501 MmExtendedCommitLimit = 0; 00502 } 00503 00504 if (MmExtendedCommit != 0) { 00505 MmTotalCommittedPages -= MmExtendedCommit; 00506 MmExtendedCommit = 0; 00507 } 00508 00509 if ((MmExtendedCommitLimit == 0) && (MmExtendedCommit == 0)) { 00510 MiCommitExtensionActive = FALSE; 00511 } 00512 } 00513 00514 ExReleaseFastLock (&MmChargeCommitmentLock, OldIrql); 00515 return; 00516 }

VOID MiReturnPageFileQuota IN SIZE_T  QuotaCharge,
IN PEPROCESS  CurrentProcess
 

Definition at line 133 of file mmquota.c.

00140 : 00141 00142 This routine releases page file quota. 00143 00144 Arguments: 00145 00146 QuotaCharge - Supplies the quota amount to charge. 00147 00148 CurrentProcess - Supplies a pointer to the current process. 00149 00150 Return Value: 00151 00152 none. 00153 00154 Environment: 00155 00156 Kernel mode, APCs disabled, WorkingSetLock and AddressCreation mutexes 00157 held. 00158 00159 --*/ 00160 00161 { 00162 00163 PEPROCESS_QUOTA_BLOCK QuotaBlock; 00164 KIRQL OldIrql; 00165 00166 QuotaBlock = CurrentProcess->QuotaBlock; 00167 00168 retry_return: 00169 if ( QuotaBlock != &PspDefaultQuotaBlock) { 00170 ExAcquireFastLock (&QuotaBlock->QuotaLock, &OldIrql); 00171 do_return: 00172 ASSERT (CurrentProcess->PagefileUsage >= QuotaCharge); 00173 CurrentProcess->PagefileUsage -= QuotaCharge; 00174 00175 ASSERT (QuotaBlock->PagefileUsage >= QuotaCharge); 00176 QuotaBlock->PagefileUsage -= QuotaCharge; 00177 ExReleaseFastLock(&QuotaBlock->QuotaLock,OldIrql); 00178 } else { 00179 ExAcquireFastLock (&PspDefaultQuotaBlock.QuotaLock, &OldIrql); 00180 if ( (QuotaBlock = CurrentProcess->QuotaBlock) != &PspDefaultQuotaBlock ) { 00181 ExReleaseFastLock(&PspDefaultQuotaBlock.QuotaLock,OldIrql); 00182 goto retry_return; 00183 } 00184 goto do_return; 00185 } 00186 return; 00187 }

VOID MiReturnPageTablePageCommitment IN PVOID  StartingAddress,
IN PVOID  EndingAddress,
IN PEPROCESS  CurrentProcess,
IN PMMVAD  PreviousVad,
IN PMMVAD  NextVad
 

Definition at line 869 of file mmquota.c.

References ASSERT, _MMWSL::CommittedPageTables, MI_CHECK_BIT, MI_CLEAR_BIT, MI_VPN_TO_VA, MiGetPpePdeOffset, MiReturnCommitment(), MiReturnPageFileQuota(), MM_DBG_COMMIT_RETURN_PAGETABLES, MM_TRACK_COMMIT, MmWorkingSetList, NULL, _MMWSL::NumberOfCommittedPageTables, PS_JOB_STATUS_REPORT_COMMIT_CHANGES, and PsChangeJobMemoryUsage().

Referenced by MmUnmapViewOfSection(), and NtFreeVirtualMemory().

00879 : 00880 00881 This routine returns commitment for COMPLETE page table pages which 00882 span the virtual address range. For example (assuming 4k pages), 00883 if the StartingAddress = 64k and the EndingAddress = 5mb, no 00884 page table charges would be freed as a complete page table page is 00885 not covered by the range. However, if the StartingAddress was 4mb 00886 and the EndingAddress was 9mb, 1 page table page would be freed. 00887 00888 Arguments: 00889 00890 StartingAddress - Supplies the starting address of the range. 00891 00892 EndingAddress - Supplies the ending address of the range. 00893 00894 CurrentProcess - Supplies a pointer to the current process. 00895 00896 PreviousVad - Supplies a pointer to the previous VAD, NULL if none. 00897 00898 NextVad - Supplies a pointer to the next VAD, NULL if none. 00899 00900 Return Value: 00901 00902 None. 00903 00904 Environment: 00905 00906 Kernel mode, APCs disabled, WorkingSetLock and AddressCreation mutexes 00907 held. 00908 00909 --*/ 00910 00911 { 00912 #ifdef _WIN64 00913 DBG_UNREFERENCED_PARAMETER (StartingAddress); 00914 DBG_UNREFERENCED_PARAMETER (EndingAddress); 00915 DBG_UNREFERENCED_PARAMETER (CurrentProcess); 00916 DBG_UNREFERENCED_PARAMETER (PreviousVad); 00917 DBG_UNREFERENCED_PARAMETER (NextVad); 00918 #else 00919 ULONG NumberToClear; 00920 LONG FirstPage; 00921 LONG LastPage; 00922 LONG PreviousPage; 00923 LONG NextPage; 00924 00925 // 00926 // Check to see if any page table pages would be freed. 00927 // 00928 00929 ASSERT (StartingAddress != EndingAddress); 00930 00931 if (PreviousVad == NULL) { 00932 PreviousPage = -1; 00933 } else { 00934 PreviousPage = MiGetPpePdeOffset (MI_VPN_TO_VA (PreviousVad->EndingVpn)); 00935 } 00936 00937 if (NextVad == NULL) { 00938 NextPage = MiGetPpePdeOffset (MM_HIGHEST_USER_ADDRESS) + 1; 00939 } else { 00940 NextPage = MiGetPpePdeOffset (MI_VPN_TO_VA (NextVad->StartingVpn)); 00941 } 00942 00943 ASSERT (PreviousPage <= NextPage); 00944 00945 FirstPage = MiGetPpePdeOffset (StartingAddress); 00946 00947 LastPage = MiGetPpePdeOffset (EndingAddress); 00948 00949 if (PreviousPage == FirstPage) { 00950 00951 // 00952 // A VAD is within the starting page table page. 00953 // 00954 00955 FirstPage += 1; 00956 } 00957 00958 if (NextPage == LastPage) { 00959 00960 // 00961 // A VAD is within the ending page table page. 00962 // 00963 00964 LastPage -= 1; 00965 } 00966 00967 // 00968 // Indicate that the page table page is not in use. 00969 // 00970 00971 if (FirstPage > LastPage) { 00972 return; 00973 } 00974 00975 NumberToClear = 1 + LastPage - FirstPage; 00976 00977 while (FirstPage <= LastPage) { 00978 ASSERT (MI_CHECK_BIT (MmWorkingSetList->CommittedPageTables, 00979 FirstPage)); 00980 00981 MI_CLEAR_BIT (MmWorkingSetList->CommittedPageTables, FirstPage); 00982 FirstPage += 1; 00983 } 00984 00985 MmWorkingSetList->NumberOfCommittedPageTables -= NumberToClear; 00986 MiReturnCommitment (NumberToClear); 00987 MM_TRACK_COMMIT (MM_DBG_COMMIT_RETURN_PAGETABLES, NumberToClear); 00988 MiReturnPageFileQuota (NumberToClear, CurrentProcess); 00989 00990 if (CurrentProcess->JobStatus & PS_JOB_STATUS_REPORT_COMMIT_CHANGES) { 00991 PsChangeJobMemoryUsage(-(SSIZE_T)NumberToClear); 00992 } 00993 CurrentProcess->CommitCharge -= NumberToClear; 00994 00995 return; 00996 #endif 00997 }

VOID MiSectionDelete PVOID  Object  ) 
 

Definition at line 511 of file sectsup.c.

References _SEGMENT::ControlArea, DbgPrint, LOCK_PFN, MiCheckControlArea(), MiRemoveBasedSection(), MM_DBG_SECTIONS, MmSectionBasedMutex, NULL, _CONTROL_AREA::NumberOfSectionReferences, _CONTROL_AREA::NumberOfUserReferences, PSECTION, and _CONTROL_AREA::Segment.

Referenced by MiSectionInitialization().

00517 : 00518 00519 00520 This routine is called by the object management procedures whenever 00521 the last reference to a section object has been removed. This routine 00522 dereferences the associated segment object and checks to see if 00523 the segment object should be deleted by queueing the segment to the 00524 segment deletion thread. 00525 00526 Arguments: 00527 00528 Object - a pointer to the body of the section object. 00529 00530 Return Value: 00531 00532 None. 00533 00534 --*/ 00535 00536 { 00537 PSECTION Section; 00538 volatile PCONTROL_AREA ControlArea; 00539 KIRQL OldIrql; 00540 ULONG UserRef; 00541 00542 Section = (PSECTION)Object; 00543 00544 if (Section->Segment == (PSEGMENT)NULL) { 00545 00546 // 00547 // The section was never initialized, no need to remove 00548 // any structures. 00549 // 00550 return; 00551 } 00552 00553 UserRef = Section->u.Flags.UserReference; 00554 ControlArea = (volatile PCONTROL_AREA)Section->Segment->ControlArea; 00555 00556 #if DBG 00557 if (MmDebug & MM_DBG_SECTIONS) { 00558 DbgPrint("MM:deleting section %lx control %lx\n",Section, ControlArea); 00559 } 00560 #endif 00561 00562 if (Section->Address.StartingVpn != 0) { 00563 00564 // 00565 // This section is based, remove the base address from the 00566 // tree. 00567 // 00568 00569 // 00570 // Get the allocation base mutex. 00571 // 00572 00573 ExAcquireFastMutex (&MmSectionBasedMutex); 00574 00575 MiRemoveBasedSection (Section); 00576 00577 ExReleaseFastMutex (&MmSectionBasedMutex); 00578 00579 } 00580 00581 // 00582 // Decrement the number of section references to the segment for this 00583 // section. This requires APCs to be blocked and the PFN lock to 00584 // synchronize upon. 00585 // 00586 00587 LOCK_PFN (OldIrql); 00588 00589 ControlArea->NumberOfSectionReferences -= 1; 00590 ControlArea->NumberOfUserReferences -= UserRef; 00591 00592 // 00593 // This routine returns with the PFN lock released. 00594 // 00595 00596 MiCheckControlArea (ControlArea, NULL, OldIrql); 00597 00598 return; 00599 }

ULONG MiSectionInitialization VOID   ) 
 

VOID MiSegmentDelete PSEGMENT  Segment  ) 
 

Definition at line 191 of file sectsup.c.

References ASSERT, _SEGMENT::BasedAddress, _SEGMENT::ControlArea, _SECTION_OBJECT_POINTERS::DataSectionObject, DbgPrint, _CONTROL_AREA::DereferenceList, Event(), ExFreePool(), FALSE, File, _FILE_OBJECT::FileName, _CONTROL_AREA::FilePointer, FreePageList, _SECTION_OBJECT_POINTERS::ImageSectionObject, IS_PTE_NOT_DEMAND_ZERO, KeSetEvent(), _MMDEREFERENCE_SEGMENT_HEADER::Lock, LOCK_PFN, MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE, MI_PFN_ELEMENT, MI_SET_PFN_DELETED, MI_UNUSED_SEGMENTS_REMOVE_CHARGE, MI_WRITE_INVALID_PTE, MiDecrementShareCount(), MiInsertPageInList(), MiIsPteOnPdeBoundary, MiMakeSystemAddressValidPfn(), MiReleasePageFileSpace(), MiReturnCommitment(), MiUnlinkPageFromList(), MM_DBG_COMMIT_RETURN_SEGMENT_DELETE1, MM_DBG_COMMIT_RETURN_SEGMENT_DELETE2, MM_DBG_SECTIONS, MM_TRACK_COMMIT, MmDereferenceSegmentHeader, MmIsAddressValid(), MmPageLocationList, MmSectionCommitMutex, MmSharedCommit, _SUBSECTION::NextSubsection, _SEGMENT::NonExtendedPtes, NT_SUCCESS, NTSTATUS(), NULL, _SEGMENT::NumberOfCommittedPages, ObDereferenceObject, _MMPFN::OriginalPte, PERFINFO_SEGMENT_DELETE, _SEGMENT::PrototypePte, PsGetCurrentProcess, _MMPFN::PteFrame, RtlFreeAnsiString(), RtlUnicodeStringToAnsiString(), _FILE_OBJECT::SectionObjectPointer, Status, _SUBSECTION::SubsectionBase, TRUE, _CONTROL_AREA::u, _MMPTE::u, _MMPFN::u3, UNLOCK_PFN, _CONTROL_AREA::WaitingForDeletion, and ZeroPte.

Referenced by MiCheckControlArea(), MiCleanSection(), and MiDereferenceSegmentThread().

00197 : 00198 00199 This routine is called by the object management procedures whenever 00200 the last reference to a segment object has been removed. This routine 00201 releases the pool allocated for the prototype PTEs and performs 00202 consistency checks on those PTEs. 00203 00204 For segments which map files, the file object is dereferenced. 00205 00206 Note, that for a segment which maps a file, no PTEs may be valid 00207 or transition, while a segment which is backed by a paging file 00208 may have transition pages, but no valid pages (there can be no 00209 PTEs which refer to the segment). 00210 00211 00212 Arguments: 00213 00214 Segment - a pointer to the segment structure. 00215 00216 Return Value: 00217 00218 None. 00219 00220 --*/ 00221 00222 { 00223 PMMPTE PointerPte; 00224 PMMPTE LastPte; 00225 PMMPFN Pfn1; 00226 KIRQL OldIrql; 00227 KIRQL OldIrql2; 00228 volatile PFILE_OBJECT File; 00229 volatile PCONTROL_AREA ControlArea; 00230 PEVENT_COUNTER Event; 00231 MMPTE PteContents; 00232 PSUBSECTION Subsection; 00233 PSUBSECTION NextSubsection; 00234 SIZE_T CommittedPages; 00235 00236 PointerPte = Segment->PrototypePte; 00237 LastPte = PointerPte + Segment->NonExtendedPtes; 00238 00239 #if DBG 00240 if (MmDebug & MM_DBG_SECTIONS) { 00241 DbgPrint("MM:deleting segment %lx control %lx\n",Segment, Segment->ControlArea); 00242 } 00243 #endif 00244 00245 ControlArea = Segment->ControlArea; 00246 00247 ASSERT (ControlArea->u.Flags.BeingDeleted == 1); 00248 00249 LOCK_PFN (OldIrql2); 00250 if (ControlArea->DereferenceList.Flink != NULL) { 00251 00252 // 00253 // Remove this from the list of unused segments. 00254 // 00255 00256 ExAcquireSpinLock (&MmDereferenceSegmentHeader.Lock, &OldIrql); 00257 RemoveEntryList (&ControlArea->DereferenceList); 00258 00259 MI_UNUSED_SEGMENTS_REMOVE_CHARGE (ControlArea); 00260 00261 ExReleaseSpinLock (&MmDereferenceSegmentHeader.Lock, OldIrql); 00262 } 00263 UNLOCK_PFN (OldIrql2); 00264 00265 if (ControlArea->u.Flags.Image || 00266 ControlArea->u.Flags.File ) { 00267 00268 // 00269 // If there have been committed pages in this segment, adjust 00270 // the total commit count. 00271 // 00272 00273 00274 // 00275 // Unload kernel debugger symbols if any were loaded. 00276 // 00277 00278 if (ControlArea->u.Flags.DebugSymbolsLoaded != 0) { 00279 00280 // 00281 // TEMP TEMP TEMP rip out when debugger converted 00282 // 00283 00284 ANSI_STRING AnsiName; 00285 NTSTATUS Status; 00286 00287 Status = RtlUnicodeStringToAnsiString( &AnsiName, 00288 (PUNICODE_STRING)&Segment->ControlArea->FilePointer->FileName, 00289 TRUE ); 00290 00291 if (NT_SUCCESS( Status)) { 00292 DbgUnLoadImageSymbols( &AnsiName, 00293 Segment->BasedAddress, 00294 (ULONG_PTR)PsGetCurrentProcess()); 00295 RtlFreeAnsiString( &AnsiName ); 00296 } 00297 LOCK_PFN (OldIrql); 00298 ControlArea->u.Flags.DebugSymbolsLoaded = 0; 00299 UNLOCK_PFN (OldIrql); 00300 } 00301 00302 // 00303 // If the segment was deleted due to a name collision at insertion 00304 // we don't want to dereference the file pointer. 00305 // 00306 00307 if (ControlArea->u.Flags.BeingCreated == FALSE) { 00308 00309 // 00310 // Clear the segment context and dereference the file object 00311 // for this Segment. 00312 // 00313 00314 LOCK_PFN (OldIrql); 00315 00316 MiMakeSystemAddressValidPfn (Segment); 00317 File = (volatile PFILE_OBJECT)Segment->ControlArea->FilePointer; 00318 ControlArea = (volatile PCONTROL_AREA)Segment->ControlArea; 00319 00320 Event = ControlArea->WaitingForDeletion; 00321 ControlArea->WaitingForDeletion = NULL; 00322 00323 UNLOCK_PFN (OldIrql); 00324 00325 if (Event != NULL) { 00326 KeSetEvent (&Event->Event, 0, FALSE); 00327 } 00328 00329 #if DBG 00330 if (ControlArea->u.Flags.Image == 1) { 00331 ASSERT (ControlArea->FilePointer->SectionObjectPointer->ImageSectionObject != (PVOID)ControlArea); 00332 } else { 00333 ASSERT (ControlArea->FilePointer->SectionObjectPointer->DataSectionObject != (PVOID)ControlArea); 00334 } 00335 #endif //DBG 00336 00337 PERFINFO_SEGMENT_DELETE(ControlArea->FilePointer); 00338 00339 ObDereferenceObject (ControlArea->FilePointer); 00340 } 00341 00342 if (ControlArea->u.Flags.Image == 0) { 00343 00344 // 00345 // This is a mapped data file. None of the prototype 00346 // PTEs may be referencing a physical page (valid or transition). 00347 // 00348 00349 #if DBG 00350 while (PointerPte < LastPte) { 00351 00352 // 00353 // Prototype PTEs for segments backed by paging file 00354 // are either in demand zero, page file format, or transition. 00355 // 00356 00357 ASSERT (PointerPte->u.Hard.Valid == 0); 00358 ASSERT ((PointerPte->u.Soft.Prototype == 1) || 00359 (PointerPte->u.Long == 0)); 00360 PointerPte += 1; 00361 } 00362 #endif //DBG 00363 00364 // 00365 // Deallocate the control area and subsections. 00366 // 00367 00368 ASSERT (ControlArea->u.Flags.GlobalOnlyPerSession == 0); 00369 00370 Subsection = (PSUBSECTION)(ControlArea + 1); 00371 00372 Subsection = Subsection->NextSubsection; 00373 00374 while (Subsection != NULL) { 00375 ExFreePool (Subsection->SubsectionBase); 00376 NextSubsection = Subsection->NextSubsection; 00377 ExFreePool (Subsection); 00378 Subsection = NextSubsection; 00379 } 00380 00381 if (Segment->NumberOfCommittedPages != 0) { 00382 MiReturnCommitment (Segment->NumberOfCommittedPages); 00383 MM_TRACK_COMMIT (MM_DBG_COMMIT_RETURN_SEGMENT_DELETE1, 00384 Segment->NumberOfCommittedPages); 00385 00386 ExAcquireFastMutex (&MmSectionCommitMutex); 00387 MmSharedCommit -= Segment->NumberOfCommittedPages; 00388 ExReleaseFastMutex (&MmSectionCommitMutex); 00389 } 00390 00391 ExFreePool (Segment->ControlArea); 00392 ExFreePool (Segment); 00393 00394 // 00395 // The file mapped Segment object is now deleted. 00396 // 00397 00398 return; 00399 } 00400 } 00401 00402 // 00403 // This is a page file backed or image Segment. The Segment is being 00404 // deleted, remove all references to the paging file and physical memory. 00405 // 00406 00407 // 00408 // The PFN lock is required for deallocating pages from a paging 00409 // file and for deleting transition PTEs. 00410 // 00411 00412 LOCK_PFN (OldIrql); 00413 00414 MiMakeSystemAddressValidPfn (PointerPte); 00415 00416 while (PointerPte < LastPte) { 00417 00418 if (MiIsPteOnPdeBoundary(PointerPte)) { 00419 00420 // 00421 // We are on a page boundary, make sure this PTE is resident. 00422 // 00423 00424 if (MmIsAddressValid (PointerPte) == FALSE) { 00425 00426 MiMakeSystemAddressValidPfn (PointerPte); 00427 } 00428 } 00429 00430 PteContents = *PointerPte; 00431 00432 // 00433 // Prototype PTEs for Segments backed by paging file 00434 // are either in demand zero, page file format, or transition. 00435 // 00436 00437 ASSERT (PteContents.u.Hard.Valid == 0); 00438 00439 if (PteContents.u.Soft.Prototype == 0) { 00440 00441 if (PteContents.u.Soft.Transition == 1) { 00442 00443 // 00444 // Prototype PTE in transition, put the page on the free list. 00445 // 00446 00447 Pfn1 = MI_PFN_ELEMENT (PteContents.u.Trans.PageFrameNumber); 00448 00449 MI_SET_PFN_DELETED (Pfn1); 00450 00451 MiDecrementShareCount (Pfn1->PteFrame); 00452 00453 // 00454 // Check the reference count for the page, if the reference 00455 // count is zero and the page is not on the freelist, 00456 // move the page to the free list, if the reference 00457 // count is not zero, ignore this page. 00458 // When the reference count goes to zero, it will be placed 00459 // on the free list. 00460 // 00461 00462 if (Pfn1->u3.e2.ReferenceCount == 0) { 00463 MiUnlinkPageFromList (Pfn1); 00464 MiReleasePageFileSpace (Pfn1->OriginalPte); 00465 MiInsertPageInList (MmPageLocationList[FreePageList], 00466 MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE (&PteContents)); 00467 } 00468 00469 } else { 00470 00471 // 00472 // This is not a prototype PTE, if any paging file 00473 // space has been allocated, release it. 00474 // 00475 00476 if (IS_PTE_NOT_DEMAND_ZERO (PteContents)) { 00477 MiReleasePageFileSpace (PteContents); 00478 } 00479 } 00480 } 00481 #if DBG 00482 MI_WRITE_INVALID_PTE (PointerPte, ZeroPte); 00483 #endif 00484 PointerPte += 1; 00485 } 00486 00487 UNLOCK_PFN (OldIrql); 00488 00489 // 00490 // If there have been committed pages in this segment, adjust 00491 // the total commit count. 00492 // 00493 00494 if (Segment->NumberOfCommittedPages != 0) { 00495 MiReturnCommitment (Segment->NumberOfCommittedPages); 00496 MM_TRACK_COMMIT (MM_DBG_COMMIT_RETURN_SEGMENT_DELETE2, 00497 Segment->NumberOfCommittedPages); 00498 00499 ExAcquireFastMutex (&MmSectionCommitMutex); 00500 MmSharedCommit -= Segment->NumberOfCommittedPages; 00501 ExReleaseFastMutex (&MmSectionCommitMutex); 00502 } 00503 00504 ExFreePool (Segment->ControlArea); 00505 ExFreePool (Segment); 00506 00507 return; 00508 }

VOID MiSessionAddProcess IN PEPROCESS  NewProcess  ) 
 

NTSTATUS MiSessionCommitImagePages PVOID  BaseAddr,
SIZE_T  Size
 

NTSTATUS MiSessionCommitPageTables PVOID  StartVa,
PVOID  EndVa
 

Referenced by MiMapViewInSystemSpace().

NTSTATUS MiSessionCopyOnWrite IN PMM_SESSION_SPACE  SessionSpace,
IN PVOID  FaultingAddress,
IN PMMPTE  PointerPte
 

Definition at line 4446 of file pagfault.c.

References ASSERT, _MMINFO_COUNTERS::CopyOnWriteCount, _MM_SESSION_SPACE::CopyOnWriteCount, HYDRA_PROCESS, LOCK_PFN, MI_FLUSH_SINGLE_SESSION_TB, MI_GET_PAGE_FRAME_FROM_PTE, MI_GET_SECONDARY_COLOR, MI_IS_PTE_DIRTY, MI_PFN_ELEMENT, MI_SET_ACCESSED_IN_PTE, MI_SET_PTE_DIRTY, MiDecrementShareCount(), MiEnsureAvailablePageOrWait(), MiGetVirtualAddressMappedByPte, MiInitializeCopyOnWritePfn(), MiLocateWsle(), MiMapPageInHyperSpace(), MiRemoveAnyPage(), MiUnmapPageInHyperSpace, MmInfoCounters, MmSessionSpace, NULL, PAGE_SIZE, TRUE, _MMPTE::u, _MMPFN::u1, _MMPFN::u3, UNLOCK_PFN, and WSLE_NUMBER.

Referenced by MmAccessFault().

04454 : 04455 04456 This function handles copy on write for image mapped session space. 04457 04458 Arguments: 04459 04460 SessionSpace - Supplies the session space being referenced. 04461 04462 FaultingAddress - Supplies the address which caused the page fault. 04463 04464 PointerPte - Supplies the pointer to the PTE which caused the page fault. 04465 04466 Return Value: 04467 04468 STATUS_SUCCESS. 04469 04470 Environment: 04471 04472 Kernel mode, APCs disabled, session WSL held. 04473 04474 --*/ 04475 04476 { 04477 MMPTE TempPte; 04478 MMPTE PreviousPte; 04479 PFN_NUMBER PageFrameIndex; 04480 PFN_NUMBER NewPageIndex; 04481 PULONG CopyTo; 04482 KIRQL OldIrql; 04483 PMMPFN Pfn1; 04484 PVOID VirtualAddress; 04485 WSLE_NUMBER WorkingSetIndex; 04486 04487 #if defined(_IA64_) 04488 UNREFERENCED_PARAMETER (FaultingAddress); 04489 #endif 04490 04491 PageFrameIndex = MI_GET_PAGE_FRAME_FROM_PTE (PointerPte); 04492 Pfn1 = MI_PFN_ELEMENT (PageFrameIndex); 04493 04494 ASSERT (Pfn1->u3.e1.PrototypePte == 1); 04495 04496 // 04497 // Acquire the PFN mutex. 04498 // 04499 04500 VirtualAddress = MiGetVirtualAddressMappedByPte (PointerPte); 04501 04502 WorkingSetIndex = MiLocateWsle (VirtualAddress, 04503 SessionSpace->Vm.VmWorkingSetList, 04504 Pfn1->u1.WsIndex); 04505 04506 LOCK_PFN (OldIrql); 04507 04508 // 04509 // The page must be copied into a new page. 04510 // 04511 04512 if (MiEnsureAvailablePageOrWait(HYDRA_PROCESS, NULL)) { 04513 04514 // 04515 // A wait operation was performed to obtain an available 04516 // page and the working set mutex and PFN mutexes have 04517 // been released and various things may have changed for 04518 // the worse. Rather than examine all the conditions again, 04519 // return and if things are still proper, the fault will 04520 // be taken again. 04521 // 04522 04523 UNLOCK_PFN (OldIrql); 04524 return STATUS_SUCCESS; 04525 } 04526 04527 // 04528 // Verify that the page did not go into transition while the 04529 // PFN lock was released. If it changed state, refault it in. 04530 // 04531 04532 TempPte = *(volatile MMPTE *)PointerPte; 04533 04534 if (!(TempPte.u.Hard.Valid && TempPte.u.Hard.Write == 0)) { 04535 UNLOCK_PFN (OldIrql); 04536 return STATUS_SUCCESS; 04537 } 04538 04539 // 04540 // Increment the number of private pages. 04541 // 04542 04543 MmInfoCounters.CopyOnWriteCount += 1; 04544 04545 MmSessionSpace->CopyOnWriteCount += 1; 04546 04547 // 04548 // A page is being copied and made private, the global state of 04549 // the shared page does not need to be updated at this point because 04550 // it is guaranteed to be clean - no POSIX-style forking is allowed on 04551 // session addresses. 04552 // 04553 04554 ASSERT (Pfn1->u3.e1.Modified == 0); 04555 ASSERT (!MI_IS_PTE_DIRTY(*PointerPte)); 04556 04557 // 04558 // Get a new page with the same color as this page. 04559 // 04560 04561 NewPageIndex = MiRemoveAnyPage (MI_GET_SECONDARY_COLOR (PageFrameIndex, 04562 Pfn1)); 04563 04564 MiInitializeCopyOnWritePfn (NewPageIndex, 04565 PointerPte, 04566 WorkingSetIndex, 04567 SessionSpace); 04568 04569 UNLOCK_PFN (OldIrql); 04570 04571 // 04572 // Copy the accessed readonly page into the newly allocated writable page. 04573 // 04574 04575 CopyTo = (PULONG)MiMapPageInHyperSpace (NewPageIndex, &OldIrql); 04576 04577 RtlCopyMemory (CopyTo, VirtualAddress, PAGE_SIZE); 04578 04579 MiUnmapPageInHyperSpace (OldIrql); 04580 04581 // 04582 // Since the page was a copy on write page, make it 04583 // accessed, dirty and writable. Also clear the copy-on-write 04584 // bit in the PTE. 04585 // 04586 04587 MI_SET_PTE_DIRTY (TempPte); 04588 TempPte.u.Hard.Write = 1; 04589 MI_SET_ACCESSED_IN_PTE (&TempPte, 1); 04590 TempPte.u.Hard.CopyOnWrite = 0; 04591 TempPte.u.Hard.PageFrameNumber = NewPageIndex; 04592 04593 // 04594 // If the modify bit is set in the PFN database for the 04595 // page, the data cache must be flushed. This is due to the 04596 // fact that this process may have been cloned and the cache 04597 // still contains stale data destined for the page we are 04598 // going to remove. 04599 // 04600 04601 ASSERT (TempPte.u.Hard.Valid == 1); 04602 04603 LOCK_PFN (OldIrql); 04604 04605 // 04606 // Flush the TB entry for this page. 04607 // 04608 04609 MI_FLUSH_SINGLE_SESSION_TB (FaultingAddress, 04610 TRUE, 04611 TRUE, 04612 (PHARDWARE_PTE)PointerPte, 04613 TempPte.u.Flush, 04614 PreviousPte); 04615 04616 ASSERT (Pfn1->u3.e1.PrototypePte == 1); 04617 04618 // 04619 // Decrement the share count for the page which was copied 04620 // as this PTE no longer refers to it. 04621 // 04622 04623 MiDecrementShareCount (PageFrameIndex); 04624 04625 UNLOCK_PFN (OldIrql); 04626 return STATUS_SUCCESS; 04627 }

NTSTATUS MiSessionInitializeWorkingSetList VOID   ) 
 

Definition at line 1881 of file wslist.c.

References _MMSUPPORT::AllowWorkingSetAdjustment, ASSERT, BYTES_TO_PAGES, _MM_SESSION_SPACE::CommittedPages, CONSISTENCY_LOCK_PFN, CONSISTENCY_UNLOCK_PFN, DbgPrint, ExDeleteResource, ExInitializeResource, FALSE, _MMWSL::FirstDynamic, _MMWSL::FirstFree, _MMWSL::HashTable, _MMWSL::HashTableSize, _MMWSL::HashTableStart, _MMWSL::HighestPermittedHashAddress, Index, _MMWSL::LastEntry, _MMWSL::LastInitializedWsle, LOCK_EXPANSION, LOCK_PFN, _MMSUPPORT::MaximumWorkingSetSize, MI_GET_PAGE_COLOR_FROM_VA, MI_NONPAGABLE_MEMORY_AVAILABLE, MI_PFN_ELEMENT, MI_SESSION_MAXIMUM_WORKING_SET, MI_SESSION_SPACE_WORKING_SET_MAXIMUM, MI_SESSION_SPACE_WORKING_SET_MINIMUM, MI_SESSION_SPACE_WS, MI_SESSION_VIEW_START, MI_SET_PTE_DIRTY, MI_SET_PTE_IN_WORKING_SET, MI_WRITE_VALID_PTE, MiChargeCommitment(), MiEnsureAvailablePageOrWait(), MiFillMemoryPte, MiGetPdeAddress, MiGetPdeSessionIndex, MiGetPteAddress, MiGetVirtualAddressMappedByPte, MiGrowWsleHash(), MiInitializePfn(), MiInitializePfnForOtherProcess(), _MMSUPPORT::MinimumWorkingSetSize, MiRemoveAnyPage(), MiRemoveZeroPage(), MiRemoveZeroPageIfAny, MiReturnCommitment(), MiSessionWsList, MiZeroPhysicalPage(), MM_BUMP_COUNTER, MM_BUMP_SESS_COUNTER, MM_BUMP_SESSION_FAILURES, MM_DBG_COMMIT_RETURN_SESSION_WSL_FAILURE, MM_DBG_COMMIT_SESSION_WS_INIT, MM_DBG_SESSION_WS_PAGE_ALLOC, MM_DBG_SESSION_WS_PAGETABLE_ALLOC, MM_DEMAND_ZERO_WRITE_PTE, MM_FREE_WSLE_SHIFT, MM_SESSION_FAILURE_NO_COMMIT, MM_SESSION_FAILURE_NO_RESIDENT, MM_TRACK_COMMIT, MM_VA_MAPPED_BY_PDE, MmResidentAvailablePages, MmSessionSpace, _MMWSL::NextSlot, _MM_SESSION_SPACE::NonPagablePages, NULL, PAGE_ALIGN, PAGE_SHIFT, PAGE_SIZE, _MM_SESSION_SPACE::PagedPoolStart, _MM_SESSION_SPACE::PageTables, _MMWSL::Quota, SESSION_GLOBAL, _MM_SESSION_SPACE::SessionPageDirectoryIndex, TRUE, _MMPTE::u, _MMSUPPORT::u, _MM_SESSION_SPACE::u, _MMPFN::u1, _MMWSLE::u1, UNLOCK_EXPANSION, UNLOCK_PFN, _MMWSL::UsedPageTableEntries, ValidKernelPdeLocal, ValidKernelPteLocal, _MM_SESSION_SPACE::Vm, _MMSUPPORT::VmWorkingSetList, _MM_SESSION_SPACE::WorkingSetLockOwner, _MMSUPPORT::WorkingSetSize, _MM_SESSION_SPACE::Wsle, _MMWSL::Wsle, WSLE_NULL_INDEX, WSLE_NUMBER, _MM_SESSION_SPACE::WsListEntry, _MM_SESSION_SPACE::WsLock, and ZeroKernelPte.

Referenced by MmSessionCreate().

01887 : 01888 01889 This function initializes the working set for the session space and adds 01890 it to the list of session space working sets. 01891 01892 Arguments: 01893 01894 None. 01895 01896 Return Value: 01897 01898 NT_SUCCESS if success or STATUS_NO_MEMORY on failure. 01899 01900 Environment: 01901 01902 Kernel mode, APC_LEVEL or below, no mutexes held. 01903 01904 --*/ 01905 01906 { 01907 ULONG i; 01908 KIRQL OldIrql; 01909 PMMPTE PointerPte; 01910 PMMPTE PointerPde; 01911 MMPTE TempPte; 01912 PMMWSLE WslEntry; 01913 PMMPFN Pfn1; 01914 ULONG PageColor; 01915 PFN_NUMBER ResidentPages; 01916 ULONG Index; 01917 PFN_NUMBER PageFrameIndex; 01918 ULONG CurrentEntry; 01919 ULONG NumberOfEntriesMapped; 01920 ULONG_PTR AdditionalBytes; 01921 ULONG NumberOfEntriesMappedByFirstPage; 01922 ULONG WorkingSetMaximum; 01923 PMM_SESSION_SPACE SessionGlobal; 01924 LOGICAL AllocatedPageTable; 01925 01926 // 01927 // Use the global address for pointer references by 01928 // MmWorkingSetManager before it attaches to the address space. 01929 // 01930 01931 SessionGlobal = SESSION_GLOBAL (MmSessionSpace); 01932 01933 // 01934 // Set up the working set variables. 01935 // 01936 01937 WorkingSetMaximum = MI_SESSION_SPACE_WORKING_SET_MAXIMUM; 01938 01939 MmSessionSpace->Vm.VmWorkingSetList = (PMMWSL)MI_SESSION_SPACE_WS; 01940 #if defined (_WIN64) 01941 MmSessionSpace->Wsle = (PMMWSLE)(MmSessionSpace->Vm.VmWorkingSetList + 1); 01942 #else 01943 MmSessionSpace->Wsle = 01944 (PMMWSLE)(&MmSessionSpace->Vm.VmWorkingSetList->UsedPageTableEntries[0]); 01945 #endif 01946 01947 ASSERT (MmSessionSpace->WorkingSetLockOwner == NULL); 01948 ASSERT (MmSessionSpace->WorkingSetLockOwnerCount == 0); 01949 01950 // 01951 // Build the PDE entry for the working set - note that the global bit 01952 // must be turned off. 01953 // 01954 01955 PointerPde = MiGetPdeAddress (MmSessionSpace->Vm.VmWorkingSetList); 01956 01957 // 01958 // The page table page for the working set and its first data page 01959 // are charged against MmResidentAvailablePages and for commitment. 01960 // 01961 01962 if (PointerPde->u.Hard.Valid == 1) { 01963 01964 // 01965 // The page directory entry for the working set is the same 01966 // as for another range in the session space. Share the PDE. 01967 // 01968 01969 #ifndef _IA64_ 01970 ASSERT (PointerPde->u.Hard.Global == 0); 01971 #endif 01972 AllocatedPageTable = FALSE; 01973 ResidentPages = 1; 01974 } 01975 else { 01976 AllocatedPageTable = TRUE; 01977 ResidentPages = 2; 01978 } 01979 01980 01981 PointerPte = MiGetPteAddress (MmSessionSpace->Vm.VmWorkingSetList); 01982 01983 // 01984 // The data pages needed to map up to maximum working set size are also 01985 // charged against MmResidentAvailablePages and for commitment. 01986 // 01987 01988 NumberOfEntriesMappedByFirstPage = (WSLE_NUMBER)( 01989 ((PMMWSLE)((ULONG_PTR)MmSessionSpace->Vm.VmWorkingSetList + PAGE_SIZE)) - 01990 MmSessionSpace->Wsle); 01991 01992 if (WorkingSetMaximum > NumberOfEntriesMappedByFirstPage) { 01993 AdditionalBytes = (WorkingSetMaximum - NumberOfEntriesMappedByFirstPage) * sizeof (MMWSLE); 01994 ResidentPages += BYTES_TO_PAGES (AdditionalBytes); 01995 } 01996 01997 if (MiChargeCommitment (ResidentPages, NULL) == FALSE) { 01998 #if DBG 01999 DbgPrint("MiSessionInitializeWorkingSetList: No commit for %d pages\n", 02000 ResidentPages); 02001 02002 #endif 02003 MM_BUMP_SESSION_FAILURES (MM_SESSION_FAILURE_NO_COMMIT); 02004 return STATUS_NO_MEMORY; 02005 } 02006 02007 MM_TRACK_COMMIT (MM_DBG_COMMIT_SESSION_WS_INIT, ResidentPages); 02008 02009 // 02010 // Use the global address for resources since they are linked 02011 // into the global system wide resource list. 02012 // 02013 02014 ExInitializeResource (&SessionGlobal->WsLock); 02015 02016 LOCK_PFN (OldIrql); 02017 02018 // 02019 // Check to make sure the physical pages are available. 02020 // 02021 02022 if ((SPFN_NUMBER)ResidentPages > MI_NONPAGABLE_MEMORY_AVAILABLE() - 20) { 02023 #if DBG 02024 DbgPrint("MiSessionInitializeWorkingSetList: No Resident Pages %d, Need %d\n", 02025 MmResidentAvailablePages, 02026 ResidentPages); 02027 #endif 02028 UNLOCK_PFN (OldIrql); 02029 02030 MiReturnCommitment (ResidentPages); 02031 MM_TRACK_COMMIT (MM_DBG_COMMIT_RETURN_SESSION_WSL_FAILURE, ResidentPages); 02032 ExDeleteResource (&SessionGlobal->WsLock); 02033 MM_BUMP_SESSION_FAILURES (MM_SESSION_FAILURE_NO_RESIDENT); 02034 return STATUS_NO_MEMORY; 02035 } 02036 02037 MmResidentAvailablePages -= ResidentPages; 02038 02039 MM_BUMP_COUNTER(50, ResidentPages); 02040 02041 if (AllocatedPageTable == TRUE) { 02042 02043 MM_BUMP_SESS_COUNTER (MM_DBG_SESSION_WS_PAGETABLE_ALLOC, 1); 02044 02045 MiEnsureAvailablePageOrWait (NULL, NULL); 02046 02047 PageColor = MI_GET_PAGE_COLOR_FROM_VA (NULL); 02048 02049 PageFrameIndex = MiRemoveZeroPageIfAny (PageColor); 02050 if (PageFrameIndex == 0) { 02051 PageFrameIndex = MiRemoveAnyPage (PageColor); 02052 UNLOCK_PFN (OldIrql); 02053 MiZeroPhysicalPage (PageFrameIndex, PageColor); 02054 LOCK_PFN (OldIrql); 02055 } 02056 02057 // 02058 // The global bit is masked off since we need to make sure the TB entry 02059 // is flushed when we switch to a process in a different session space. 02060 // 02061 02062 TempPte.u.Long = ValidKernelPdeLocal.u.Long; 02063 TempPte.u.Hard.PageFrameNumber = PageFrameIndex; 02064 MI_WRITE_VALID_PTE (PointerPde, TempPte); 02065 02066 #if !defined (_WIN64) 02067 02068 // 02069 // Add this to the session structure so other processes can fault it in. 02070 // 02071 02072 Index = MiGetPdeSessionIndex (MmSessionSpace->Vm.VmWorkingSetList); 02073 02074 MmSessionSpace->PageTables[Index] = TempPte; 02075 02076 #endif 02077 02078 // 02079 // This page frame references the session space page table page. 02080 // 02081 02082 MiInitializePfnForOtherProcess (PageFrameIndex, 02083 PointerPde, 02084 MmSessionSpace->SessionPageDirectoryIndex); 02085 02086 MiFillMemoryPte (PointerPte, PAGE_SIZE, ZeroKernelPte.u.Long); 02087 02088 Pfn1 = MI_PFN_ELEMENT (PageFrameIndex); 02089 02090 // 02091 // This page is never paged, ensure that its WsIndex stays clear so the 02092 // release of the page will be handled correctly. 02093 // 02094 02095 ASSERT (Pfn1->u1.WsIndex == 0); 02096 02097 KeFillEntryTb ((PHARDWARE_PTE) PointerPde, PointerPte, FALSE); 02098 } 02099 02100 MiEnsureAvailablePageOrWait (NULL, NULL); 02101 02102 PageColor = MI_GET_PAGE_COLOR_FROM_VA (NULL); 02103 02104 PageFrameIndex = MiRemoveZeroPageIfAny (PageColor); 02105 if (PageFrameIndex == 0) { 02106 PageFrameIndex = MiRemoveAnyPage (PageColor); 02107 UNLOCK_PFN (OldIrql); 02108 MiZeroPhysicalPage (PageFrameIndex, PageColor); 02109 LOCK_PFN (OldIrql); 02110 } 02111 02112 MM_BUMP_SESS_COUNTER (MM_DBG_SESSION_WS_PAGE_ALLOC, ResidentPages - 1); 02113 02114 #if DBG 02115 Pfn1 = MI_PFN_ELEMENT (PageFrameIndex); 02116 ASSERT (Pfn1->u1.WsIndex == 0); 02117 #endif 02118 02119 // 02120 // The global bit is masked off since we need to make sure the TB entry 02121 // is flushed when we switch to a process in a different session space. 02122 // 02123 02124 TempPte.u.Long = ValidKernelPteLocal.u.Long; 02125 MI_SET_PTE_DIRTY (TempPte); 02126 TempPte.u.Hard.PageFrameNumber = PageFrameIndex; 02127 02128 MI_WRITE_VALID_PTE (PointerPte, TempPte); 02129 02130 MiInitializePfn (PageFrameIndex, PointerPte, 1); 02131 02132 #if DBG 02133 Pfn1 = MI_PFN_ELEMENT (PageFrameIndex); 02134 ASSERT (Pfn1->u1.WsIndex == 0); 02135 #endif 02136 02137 UNLOCK_PFN (OldIrql); 02138 02139 KeFillEntryTb ((PHARDWARE_PTE) PointerPte, 02140 (PMMPTE)MmSessionSpace->Vm.VmWorkingSetList, 02141 FALSE); 02142 02143 // 02144 // Fill in the reserved slots starting with the session data page. 02145 // 02146 02147 WslEntry = MmSessionSpace->Wsle; 02148 02149 WslEntry->u1.VirtualAddress = (PVOID)MmSessionSpace; 02150 WslEntry->u1.e1.Valid = 1; 02151 WslEntry->u1.e1.LockedInWs = 1; 02152 WslEntry->u1.e1.Direct = 1; 02153 02154 Pfn1 = MI_PFN_ELEMENT (MiGetPteAddress (WslEntry->u1.VirtualAddress)->u.Hard.PageFrameNumber); 02155 02156 ASSERT (Pfn1->u1.WsIndex == 0); 02157 02158 // 02159 // The next reserved slot is for the page table page mapping 02160 // the session data page. 02161 // 02162 02163 WslEntry += 1; 02164 02165 WslEntry->u1.VirtualAddress = MiGetPteAddress (MmSessionSpace); 02166 WslEntry->u1.e1.Valid = 1; 02167 WslEntry->u1.e1.LockedInWs = 1; 02168 WslEntry->u1.e1.Direct = 1; 02169 02170 Pfn1 = MI_PFN_ELEMENT (MiGetPteAddress (WslEntry->u1.VirtualAddress)->u.Hard.PageFrameNumber); 02171 02172 ASSERT (Pfn1->u1.WsIndex == 0); 02173 02174 CONSISTENCY_LOCK_PFN (OldIrql); 02175 02176 Pfn1->u1.WsIndex = (WSLE_NUMBER)(WslEntry - MmSessionSpace->Wsle); 02177 02178 CONSISTENCY_UNLOCK_PFN (OldIrql); 02179 02180 // 02181 // The next reserved slot is for the working set page. 02182 // 02183 02184 WslEntry += 1; 02185 02186 WslEntry->u1.VirtualAddress = MmSessionSpace->Vm.VmWorkingSetList; 02187 WslEntry->u1.e1.Valid = 1; 02188 WslEntry->u1.e1.LockedInWs = 1; 02189 WslEntry->u1.e1.Direct = 1; 02190 02191 Pfn1 = MI_PFN_ELEMENT (PageFrameIndex); 02192 02193 ASSERT (Pfn1->u1.WsIndex == 0); 02194 02195 CONSISTENCY_LOCK_PFN (OldIrql); 02196 02197 Pfn1->u1.WsIndex = (WSLE_NUMBER)(WslEntry - MmSessionSpace->Wsle); 02198 02199 CONSISTENCY_UNLOCK_PFN (OldIrql); 02200 02201 if (AllocatedPageTable == TRUE) { 02202 02203 // 02204 // The next reserved slot is for the page table page 02205 // mapping the working set page. 02206 // 02207 02208 WslEntry += 1; 02209 02210 WslEntry->u1.VirtualAddress = (PVOID)PointerPte; 02211 WslEntry->u1.e1.Valid = 1; 02212 WslEntry->u1.e1.LockedInWs = 1; 02213 WslEntry->u1.e1.Direct = 1; 02214 02215 Pfn1 = MI_PFN_ELEMENT (MiGetPteAddress (WslEntry->u1.VirtualAddress)->u.Hard.PageFrameNumber); 02216 02217 ASSERT (Pfn1->u1.WsIndex == 0); 02218 02219 CONSISTENCY_LOCK_PFN (OldIrql); 02220 02221 Pfn1->u1.WsIndex = (WSLE_NUMBER)(WslEntry - MmSessionSpace->Wsle); 02222 02223 CONSISTENCY_UNLOCK_PFN (OldIrql); 02224 } 02225 02226 // 02227 // The next reserved slot is for the page table page 02228 // mapping the first session paged pool page. 02229 // 02230 02231 WslEntry += 1; 02232 02233 WslEntry->u1.VirtualAddress = (PVOID)MiGetPteAddress (MmSessionSpace->PagedPoolStart); 02234 WslEntry->u1.e1.Valid = 1; 02235 WslEntry->u1.e1.LockedInWs = 1; 02236 WslEntry->u1.e1.Direct = 1; 02237 02238 Pfn1 = MI_PFN_ELEMENT (MiGetPteAddress (WslEntry->u1.VirtualAddress)->u.Hard.PageFrameNumber); 02239 02240 ASSERT (Pfn1->u1.WsIndex == 0); 02241 02242 CONSISTENCY_LOCK_PFN (OldIrql); 02243 02244 Pfn1->u1.WsIndex = (WSLE_NUMBER)(WslEntry - MmSessionSpace->Wsle); 02245 02246 CONSISTENCY_UNLOCK_PFN (OldIrql); 02247 02248 CurrentEntry = (WSLE_NUMBER)(WslEntry + 1 - MmSessionSpace->Wsle); 02249 02250 MmSessionSpace->Vm.u.Flags.SessionSpace = 1; 02251 MmSessionSpace->Vm.MinimumWorkingSetSize = MI_SESSION_SPACE_WORKING_SET_MINIMUM; 02252 MmSessionSpace->Vm.MaximumWorkingSetSize = WorkingSetMaximum; 02253 02254 // 02255 // Don't trim from this session till we're finished setting up and 02256 // it's got some pages in it... 02257 // 02258 02259 MmSessionSpace->Vm.AllowWorkingSetAdjustment = FALSE; 02260 02261 MmSessionSpace->Vm.VmWorkingSetList->LastEntry = MI_SESSION_SPACE_WORKING_SET_MINIMUM; 02262 MmSessionSpace->Vm.VmWorkingSetList->Quota = MmSessionSpace->Vm.VmWorkingSetList->LastEntry; 02263 MmSessionSpace->Vm.VmWorkingSetList->HashTable = NULL; 02264 MmSessionSpace->Vm.VmWorkingSetList->HashTableSize = 0; 02265 MmSessionSpace->Vm.VmWorkingSetList->Wsle = MmSessionSpace->Wsle; 02266 02267 MmSessionSpace->Vm.VmWorkingSetList->HashTableStart = 02268 (PVOID)((PCHAR)PAGE_ALIGN (&MmSessionSpace->Wsle[MI_SESSION_MAXIMUM_WORKING_SET]) + PAGE_SIZE); 02269 02270 #if defined (_X86PAE_) 02271 02272 // 02273 // One less page table page is needed on PAE systems. 02274 // 02275 02276 MmSessionSpace->Vm.VmWorkingSetList->HighestPermittedHashAddress = 02277 (PVOID)(MI_SESSION_VIEW_START - MM_VA_MAPPED_BY_PDE); 02278 #else 02279 MmSessionSpace->Vm.VmWorkingSetList->HighestPermittedHashAddress = 02280 (PVOID)MI_SESSION_VIEW_START; 02281 #endif 02282 02283 NumberOfEntriesMapped = (WSLE_NUMBER)(((PMMWSLE)((ULONG_PTR)MmSessionSpace->Vm.VmWorkingSetList + 02284 PAGE_SIZE)) - MmSessionSpace->Wsle); 02285 02286 LOCK_PFN (OldIrql); 02287 02288 while (NumberOfEntriesMapped < WorkingSetMaximum) { 02289 02290 PointerPte += 1; 02291 02292 MiEnsureAvailablePageOrWait (NULL, NULL); 02293 02294 PageFrameIndex = MiRemoveZeroPage(MI_GET_PAGE_COLOR_FROM_VA (NULL)); 02295 02296 PointerPte->u.Long = MM_DEMAND_ZERO_WRITE_PTE; 02297 02298 MiInitializePfn (PageFrameIndex, PointerPte, 1); 02299 02300 TempPte.u.Hard.PageFrameNumber = PageFrameIndex; 02301 02302 MI_SET_PTE_IN_WORKING_SET (&TempPte, CurrentEntry); 02303 02304 MI_WRITE_VALID_PTE (PointerPte, TempPte); 02305 02306 WslEntry += 1; 02307 02308 WslEntry->u1.VirtualAddress = MiGetVirtualAddressMappedByPte (PointerPte); 02309 WslEntry->u1.e1.Valid = 1; 02310 WslEntry->u1.e1.LockedInWs = 1; 02311 WslEntry->u1.e1.Direct = 1; 02312 02313 Pfn1 = MI_PFN_ELEMENT (PointerPte->u.Hard.PageFrameNumber); 02314 02315 ASSERT (Pfn1->u1.WsIndex == 0); 02316 Pfn1->u1.WsIndex = CurrentEntry; 02317 02318 // MiInsertWsle(CurrentEntry, MmWorkingSetList); 02319 02320 CurrentEntry += 1; 02321 02322 NumberOfEntriesMapped += PAGE_SIZE / sizeof(MMWSLE); 02323 } 02324 02325 UNLOCK_PFN (OldIrql); 02326 02327 MmSessionSpace->Vm.WorkingSetSize = CurrentEntry; 02328 MmSessionSpace->Vm.VmWorkingSetList->FirstFree = CurrentEntry; 02329 MmSessionSpace->Vm.VmWorkingSetList->FirstDynamic = CurrentEntry; 02330 MmSessionSpace->Vm.VmWorkingSetList->NextSlot = CurrentEntry; 02331 02332 MmSessionSpace->NonPagablePages += ResidentPages; 02333 MmSessionSpace->CommittedPages += ResidentPages; 02334 02335 // 02336 // Initialize the following slots as free. 02337 // 02338 02339 WslEntry = MmSessionSpace->Wsle + CurrentEntry; 02340 02341 for (i = CurrentEntry + 1; i < NumberOfEntriesMapped; i += 1) { 02342 02343 // 02344 // Build the free list, note that the first working 02345 // set entries (CurrentEntry) are not on the free list. 02346 // These entries are reserved for the pages which 02347 // map the working set and the page which contains the PDE. 02348 // 02349 02350 WslEntry->u1.Long = i << MM_FREE_WSLE_SHIFT; 02351 WslEntry += 1; 02352 } 02353 02354 WslEntry->u1.Long = WSLE_NULL_INDEX << MM_FREE_WSLE_SHIFT; // End of list. 02355 02356 MmSessionSpace->Vm.VmWorkingSetList->LastInitializedWsle = NumberOfEntriesMapped - 1; 02357 02358 if (WorkingSetMaximum > ((1536*1024) >> PAGE_SHIFT)) { 02359 02360 // 02361 // The working set list consists of more than a single page. 02362 // 02363 02364 MiGrowWsleHash (&MmSessionSpace->Vm); 02365 } 02366 02367 // 02368 // Put this session's working set in lists using its global address. 02369 // 02370 02371 LOCK_EXPANSION (OldIrql); 02372 02373 InsertTailList (&MiSessionWsList, &SessionGlobal->WsListEntry); 02374 02375 MmSessionSpace->u.Flags.HasWsLock = 1; 02376 02377 MmSessionSpace->u.Flags.SessionListInserted = 1; 02378 02379 UNLOCK_EXPANSION (OldIrql); 02380 02381 return STATUS_SUCCESS; 02382 }

VOID MiSessionInSwapProcess IN PEPROCESS  Process  ) 
 

Definition at line 2737 of file session.c.

References ASSERT, DbgPrint, _MM_SESSION_SPACE::GlobalVirtualAddress, LOCK_EXPANSION, MI_GET_DIRECTORY_FRAME_FROM_PROCESS, MI_GET_PAGE_FRAME_FROM_PTE, MiGetPdeOffset, MiGetPpeOffset, MiGetPteAddress, MiGetPteOffset, MiHydra, MiMapPageInHyperSpace(), MiUnmapPageInHyperSpace, MM_DBG_SESSIONS, MmSessionSpace, _MM_SESSION_SPACE::ProcessList, _MM_SESSION_SPACE::ProcessOutSwapCount, _MM_SESSION_SPACE::ReferenceCount, _MM_SESSION_SPACE::SessionId, TRUE, _MMSUPPORT::u, UNLOCK_EXPANSION, _MM_SESSION_SPACE::Vm, and _MMSUPPORT::WorkingSetSize.

Referenced by MmInSwapProcess().

02743 : 02744 02745 This routine in swaps the specified process. 02746 02747 Arguments: 02748 02749 Process - Supplies a pointer to the process that is to be swapped 02750 into memory. 02751 02752 Return Value: 02753 02754 None. 02755 02756 Environment: 02757 02758 Kernel mode. This routine must not enter a wait state for memory resources 02759 or the system will deadlock. 02760 02761 --*/ 02762 02763 { 02764 MMPTE TempPte; 02765 PFN_NUMBER PdePage; 02766 PMMPTE PageDirectoryMap; 02767 KIRQL OldIrql; 02768 PFN_NUMBER SessionPage; 02769 PMM_SESSION_SPACE SessionGlobal; 02770 #if DBG 02771 ULONG InCount; 02772 ULONG OutCount; 02773 PLIST_ENTRY NextEntry; 02774 #endif 02775 #if defined (_X86PAE_) 02776 ULONG i; 02777 PPAE_ENTRY PaeVa; 02778 #endif 02779 02780 ASSERT (MiHydra == TRUE && Process->Vm.u.Flags.ProcessInSession == 1); 02781 02782 // 02783 // smss doesn't count when we catch it before it has detached from the 02784 // session it is currently creating. 02785 // 02786 02787 if (Process->Vm.u.Flags.SessionLeader == 1) { 02788 return; 02789 } 02790 02791 ASSERT (MiHydra == TRUE && Process->Vm.u.Flags.ProcessInSession == 1); 02792 02793 // 02794 // smss doesn't count when we swap it before it has detached from the 02795 // session it is currently creating. 02796 // 02797 02798 if (Process->Vm.u.Flags.SessionLeader == 1) { 02799 return; 02800 } 02801 02802 #if defined (_X86PAE_) 02803 PaeVa = Process->PaeTop; 02804 02805 #if DBG 02806 for (i = 0; i < PD_PER_SYSTEM; i += 1) { 02807 ASSERT (PaeVa->PteEntry[i].u.Hard.Valid == 1); 02808 } 02809 #endif 02810 02811 PdePage = MI_GET_PAGE_FRAME_FROM_PTE (&PaeVa->PteEntry[MiGetPdPteOffset(MmSessionSpace)]); 02812 02813 #else 02814 PdePage = MI_GET_DIRECTORY_FRAME_FROM_PROCESS(Process); 02815 #endif 02816 02817 PageDirectoryMap = MiMapPageInHyperSpace (PdePage, &OldIrql); 02818 02819 #if defined (_WIN64) 02820 TempPte = PageDirectoryMap[MiGetPpeOffset(MmSessionSpace)]; 02821 02822 MiUnmapPageInHyperSpace (OldIrql); 02823 02824 PdePage = MI_GET_PAGE_FRAME_FROM_PTE (&TempPte); 02825 02826 PageDirectoryMap = MiMapPageInHyperSpace (PdePage, &OldIrql); 02827 #endif 02828 02829 TempPte = PageDirectoryMap[MiGetPdeOffset(MmSessionSpace)]; 02830 02831 MiUnmapPageInHyperSpace (OldIrql); 02832 02833 PdePage = MI_GET_PAGE_FRAME_FROM_PTE (&TempPte); 02834 02835 PageDirectoryMap = MiMapPageInHyperSpace (PdePage, &OldIrql); 02836 02837 TempPte = PageDirectoryMap[MiGetPteOffset(MmSessionSpace)]; 02838 02839 MiUnmapPageInHyperSpace (OldIrql); 02840 02841 SessionPage = MI_GET_PAGE_FRAME_FROM_PTE (&TempPte); 02842 02843 SessionGlobal = (PMM_SESSION_SPACE) MiMapPageInHyperSpace (SessionPage, 02844 &OldIrql); 02845 02846 ASSERT (MI_GET_PAGE_FRAME_FROM_PTE (MiGetPteAddress(SessionGlobal->GlobalVirtualAddress)) == SessionPage); 02847 02848 SessionGlobal = SessionGlobal->GlobalVirtualAddress; 02849 02850 MiUnmapPageInHyperSpace (OldIrql); 02851 02852 LOCK_EXPANSION (OldIrql); 02853 02854 #if DBG 02855 ASSERT ((LONG)SessionGlobal->ProcessOutSwapCount > 0); 02856 02857 InCount = 0; 02858 OutCount = 0; 02859 NextEntry = SessionGlobal->ProcessList.Flink; 02860 02861 while (NextEntry != &SessionGlobal->ProcessList) { 02862 Process = CONTAINING_RECORD (NextEntry, EPROCESS, SessionProcessLinks); 02863 02864 if (Process->ProcessOutswapEnabled == TRUE) { 02865 OutCount += 1; 02866 } 02867 else { 02868 InCount += 1; 02869 } 02870 02871 NextEntry = NextEntry->Flink; 02872 } 02873 02874 if (InCount + OutCount > SessionGlobal->ReferenceCount) { 02875 DbgPrint ("MiSessionInSwapProcess : count mismatch %p %x %x %x\n", 02876 SessionGlobal, 02877 SessionGlobal->ReferenceCount, 02878 InCount, 02879 OutCount); 02880 DbgBreakPoint (); 02881 } 02882 02883 if (SessionGlobal->ProcessOutSwapCount != OutCount) { 02884 DbgPrint ("MiSessionInSwapProcess : out count mismatch %p %x %x %x %x\n", 02885 SessionGlobal, 02886 SessionGlobal->ReferenceCount, 02887 SessionGlobal->ProcessOutSwapCount, 02888 InCount, 02889 OutCount); 02890 DbgBreakPoint (); 02891 } 02892 02893 ASSERT (SessionGlobal->ProcessOutSwapCount <= SessionGlobal->ReferenceCount); 02894 02895 MiSessionSwap[MiSwapIndex].Flag = 2; 02896 MiSessionSwap[MiSwapIndex].Process = Process; 02897 MiSessionSwap[MiSwapIndex].Session = SessionGlobal; 02898 MiSessionSwap[MiSwapIndex].OutSwapCount = SessionGlobal->ProcessOutSwapCount; 02899 MiSwapIndex += 1; 02900 if (MiSwapIndex == 0x100) { 02901 MiSwapIndex = 0; 02902 } 02903 #endif 02904 02905 if (SessionGlobal->ProcessOutSwapCount == SessionGlobal->ReferenceCount) { 02906 #if DBG 02907 MiSessionInfo[2] += 1; 02908 if (MmDebug & MM_DBG_SESSIONS) { 02909 DbgPrint ("Mm: First process (%d total) just swapped back in for session %d, %d pages\n", 02910 SessionGlobal->ProcessOutSwapCount, 02911 SessionGlobal->SessionId, 02912 SessionGlobal->Vm.WorkingSetSize); 02913 } 02914 #endif 02915 SessionGlobal->Vm.u.Flags.TrimHard = 0; 02916 } 02917 #if DBG 02918 else { 02919 MiSessionInfo[3] += 1; 02920 } 02921 #endif 02922 02923 SessionGlobal->ProcessOutSwapCount -= 1; 02924 02925 ASSERT ((LONG)SessionGlobal->ProcessOutSwapCount >= 0); 02926 02927 UNLOCK_EXPANSION (OldIrql); 02928 } }

PIMAGE_ENTRY_IN_SESSION MiSessionLookupImage IN PVOID  BaseAddress  ) 
 

Definition at line 518 of file sessload.c.

References _IMAGE_ENTRY_IN_SESSION::Address, _MM_SESSION_SPACE::ImageList, LOCK_SESSION_SPACE_WS, MmSessionSpace, NULL, SYSLOAD_LOCK_OWNED_BY_ME, and UNLOCK_SESSION_SPACE_WS.

Referenced by MiShareSessionImage(), and MmUnloadSystemImage().

00524 : 00525 00526 This routine looks up the image entry within the current session by the 00527 specified base address. 00528 00529 Arguments: 00530 00531 BaseAddress - Supplies the base address for the executable image. 00532 00533 Return Value: 00534 00535 The image entry within this session on success or NULL on failure. 00536 00537 Environment: 00538 00539 Kernel mode, APC_LEVEL and below, MmSystemLoadLock held. 00540 00541 --*/ 00542 00543 { 00544 PLIST_ENTRY NextEntry; 00545 PIMAGE_ENTRY_IN_SESSION Image; 00546 KIRQL OldIrql; 00547 00548 SYSLOAD_LOCK_OWNED_BY_ME (); 00549 00550 LOCK_SESSION_SPACE_WS (OldIrql); 00551 00552 NextEntry = MmSessionSpace->ImageList.Flink; 00553 00554 while (NextEntry != &MmSessionSpace->ImageList) { 00555 00556 Image = CONTAINING_RECORD(NextEntry, IMAGE_ENTRY_IN_SESSION, Link); 00557 00558 if (Image->Address == BaseAddress) { 00559 UNLOCK_SESSION_SPACE_WS (OldIrql); 00560 return Image; 00561 } 00562 00563 NextEntry = NextEntry->Flink; 00564 } 00565 00566 UNLOCK_SESSION_SPACE_WS (OldIrql); 00567 return NULL; 00568 }

VOID MiSessionOutSwapProcess IN PEPROCESS  Process  ) 
 

Definition at line 2551 of file session.c.

References ASSERT, DbgPrint, _MM_SESSION_SPACE::GlobalVirtualAddress, KeQuerySystemTime(), _MM_SESSION_SPACE::LastProcessSwappedOutTime, LOCK_EXPANSION, MI_GET_DIRECTORY_FRAME_FROM_PROCESS, MI_GET_PAGE_FRAME_FROM_PTE, MiGetPdeOffset, MiGetPpeOffset, MiGetPteAddress, MiGetPteOffset, MiHydra, MiMapPageInHyperSpace(), MiUnmapPageInHyperSpace, MM_DBG_SESSIONS, MmSessionSpace, _MM_SESSION_SPACE::ProcessList, _MM_SESSION_SPACE::ProcessOutSwapCount, _MM_SESSION_SPACE::ReferenceCount, _MM_SESSION_SPACE::SessionId, TRUE, _MMSUPPORT::u, UNLOCK_EXPANSION, _MM_SESSION_SPACE::Vm, and _MMSUPPORT::WorkingSetSize.

Referenced by MmOutSwapProcess().

02557 : 02558 02559 This routine notifies the containing session that the specified process is 02560 being outswapped. When all the processes within a session have been 02561 outswapped, the containing session undergoes a heavy trim. 02562 02563 Arguments: 02564 02565 Process - Supplies a pointer to the process that is swapped out of memory. 02566 02567 Return Value: 02568 02569 None. 02570 02571 Environment: 02572 02573 Kernel mode. This routine must not enter a wait state for memory resources 02574 or the system will deadlock. 02575 02576 --*/ 02577 02578 { 02579 MMPTE TempPte; 02580 PFN_NUMBER PdePage; 02581 PMMPTE PageDirectoryMap; 02582 KIRQL OldIrql; 02583 PFN_NUMBER SessionPage; 02584 PMM_SESSION_SPACE SessionGlobal; 02585 #if DBG 02586 ULONG InCount; 02587 ULONG OutCount; 02588 PLIST_ENTRY NextEntry; 02589 #endif 02590 #if defined (_X86PAE_) 02591 ULONG i; 02592 PPAE_ENTRY PaeVa; 02593 #endif 02594 02595 ASSERT (MiHydra == TRUE && Process->Vm.u.Flags.ProcessInSession == 1); 02596 02597 // 02598 // smss doesn't count when we swap it before it has detached from the 02599 // session it is currently creating. 02600 // 02601 02602 if (Process->Vm.u.Flags.SessionLeader == 1) { 02603 return; 02604 } 02605 02606 #if defined (_X86PAE_) 02607 PaeVa = Process->PaeTop; 02608 02609 #if DBG 02610 for (i = 0; i < PD_PER_SYSTEM; i += 1) { 02611 ASSERT (PaeVa->PteEntry[i].u.Hard.Valid == 1); 02612 } 02613 #endif 02614 02615 PdePage = MI_GET_PAGE_FRAME_FROM_PTE (&PaeVa->PteEntry[MiGetPdPteOffset(MmSessionSpace)]); 02616 02617 #else 02618 02619 PdePage = MI_GET_DIRECTORY_FRAME_FROM_PROCESS(Process); 02620 02621 #endif 02622 02623 PageDirectoryMap = MiMapPageInHyperSpace (PdePage, &OldIrql); 02624 02625 #if defined (_WIN64) 02626 TempPte = PageDirectoryMap[MiGetPpeOffset(MmSessionSpace)]; 02627 02628 MiUnmapPageInHyperSpace (OldIrql); 02629 02630 PdePage = MI_GET_PAGE_FRAME_FROM_PTE (&TempPte); 02631 02632 PageDirectoryMap = MiMapPageInHyperSpace (PdePage, &OldIrql); 02633 #endif 02634 02635 TempPte = PageDirectoryMap[MiGetPdeOffset(MmSessionSpace)]; 02636 02637 MiUnmapPageInHyperSpace (OldIrql); 02638 02639 PdePage = MI_GET_PAGE_FRAME_FROM_PTE (&TempPte); 02640 02641 PageDirectoryMap = MiMapPageInHyperSpace (PdePage, &OldIrql); 02642 02643 TempPte = PageDirectoryMap[MiGetPteOffset(MmSessionSpace)]; 02644 02645 MiUnmapPageInHyperSpace (OldIrql); 02646 02647 SessionPage = MI_GET_PAGE_FRAME_FROM_PTE (&TempPte); 02648 02649 SessionGlobal = (PMM_SESSION_SPACE) MiMapPageInHyperSpace ( SessionPage, 02650 &OldIrql); 02651 02652 ASSERT (MI_GET_PAGE_FRAME_FROM_PTE (MiGetPteAddress(SessionGlobal->GlobalVirtualAddress)) == SessionPage); 02653 02654 SessionGlobal = SessionGlobal->GlobalVirtualAddress; 02655 02656 MiUnmapPageInHyperSpace (OldIrql); 02657 02658 LOCK_EXPANSION (OldIrql); 02659 02660 SessionGlobal->ProcessOutSwapCount += 1; 02661 02662 #if DBG 02663 ASSERT ((LONG)SessionGlobal->ProcessOutSwapCount > 0); 02664 02665 InCount = 0; 02666 OutCount = 0; 02667 NextEntry = SessionGlobal->ProcessList.Flink; 02668 02669 while (NextEntry != &SessionGlobal->ProcessList) { 02670 Process = CONTAINING_RECORD (NextEntry, EPROCESS, SessionProcessLinks); 02671 02672 if (Process->ProcessOutswapEnabled == TRUE) { 02673 OutCount += 1; 02674 } 02675 else { 02676 InCount += 1; 02677 } 02678 02679 NextEntry = NextEntry->Flink; 02680 } 02681 02682 if (InCount + OutCount > SessionGlobal->ReferenceCount) { 02683 DbgPrint ("MiSessionOutSwapProcess : process count mismatch %p %x %x %x\n", 02684 SessionGlobal, 02685 SessionGlobal->ReferenceCount, 02686 InCount, 02687 OutCount); 02688 DbgBreakPoint (); 02689 } 02690 02691 if (SessionGlobal->ProcessOutSwapCount != OutCount) { 02692 DbgPrint ("MiSessionOutSwapProcess : out count mismatch %p %x %x %x %x\n", 02693 SessionGlobal, 02694 SessionGlobal->ReferenceCount, 02695 SessionGlobal->ProcessOutSwapCount, 02696 InCount, 02697 OutCount); 02698 DbgBreakPoint (); 02699 } 02700 02701 ASSERT (SessionGlobal->ProcessOutSwapCount <= SessionGlobal->ReferenceCount); 02702 02703 MiSessionSwap[MiSwapIndex].Flag = 1; 02704 MiSessionSwap[MiSwapIndex].Process = Process; 02705 MiSessionSwap[MiSwapIndex].Session = SessionGlobal; 02706 MiSessionSwap[MiSwapIndex].OutSwapCount = SessionGlobal->ProcessOutSwapCount; 02707 MiSwapIndex += 1; 02708 if (MiSwapIndex == 0x100) { 02709 MiSwapIndex = 0; 02710 } 02711 #endif 02712 02713 if (SessionGlobal->ProcessOutSwapCount == SessionGlobal->ReferenceCount) { 02714 SessionGlobal->Vm.u.Flags.TrimHard = 1; 02715 #if DBG 02716 if (MmDebug & MM_DBG_SESSIONS) { 02717 DbgPrint ("Mm: Last process (%d total) just swapped out for session %d, %d pages\n", 02718 SessionGlobal->ProcessOutSwapCount, 02719 SessionGlobal->SessionId, 02720 SessionGlobal->Vm.WorkingSetSize); 02721 } 02722 MiSessionInfo[0] += 1; 02723 #endif 02724 KeQuerySystemTime (&SessionGlobal->LastProcessSwappedOutTime); 02725 } 02726 #if DBG 02727 else { 02728 MiSessionInfo[1] += 1; 02729 } 02730 #endif 02731 02732 UNLOCK_EXPANSION (OldIrql); 02733 }

VOID MiSessionRemoveProcess VOID   ) 
 

Definition at line 259 of file session.c.

References ASSERT, LOCK_EXPANSION, MiDereferenceSession(), MmIsAddressValid(), MmSessionSpace, _MM_SESSION_SPACE::ProcessList, PsGetCurrentProcess, SESSION_GLOBAL, _EPROCESS::SessionProcessLinks, TRUE, _MMSUPPORT::u, UNLOCK_EXPANSION, and _EPROCESS::Vm.

00265 : 00266 00267 This routine removes the current process from the current session space. 00268 This may trigger a substantial round of dereferencing and resource freeing 00269 if it is also the last process in the session, (holding the last image 00270 in the group, etc). 00271 00272 Arguments: 00273 00274 None. 00275 00276 Return Value: 00277 00278 None. 00279 00280 Environment: 00281 00282 Kernel mode, APC_LEVEL and below, but queueing of APCs to this thread has 00283 been permanently disabled. This is the last thread in the process 00284 being deleted. The caller has ensured that this process is not 00285 on the expansion list and therefore there can be no races in regards to 00286 trimming. 00287 00288 --*/ 00289 00290 { 00291 KIRQL OldIrql; 00292 PEPROCESS CurrentProcess; 00293 #if DBG 00294 ULONG Found; 00295 PEPROCESS Process; 00296 PLIST_ENTRY NextEntry; 00297 PMM_SESSION_SPACE SessionGlobal; 00298 #endif 00299 00300 CurrentProcess = PsGetCurrentProcess(); 00301 00302 if (CurrentProcess->Vm.u.Flags.ProcessInSession == 0) { 00303 return; 00304 } 00305 00306 ASSERT (MmIsAddressValid (MmSessionSpace) == TRUE); 00307 00308 // 00309 // Remove this process from the list of processes in the current session. 00310 // 00311 00312 LOCK_EXPANSION (OldIrql); 00313 00314 #if DBG 00315 00316 SessionGlobal = SESSION_GLOBAL(MmSessionSpace); 00317 00318 Found = 0; 00319 NextEntry = SessionGlobal->ProcessList.Flink; 00320 00321 while (NextEntry != &SessionGlobal->ProcessList) { 00322 Process = CONTAINING_RECORD (NextEntry, EPROCESS, SessionProcessLinks); 00323 00324 if (Process == CurrentProcess) { 00325 Found = 1; 00326 } 00327 00328 NextEntry = NextEntry->Flink; 00329 } 00330 00331 ASSERT (Found == 1); 00332 00333 #endif 00334 00335 RemoveEntryList (&CurrentProcess->SessionProcessLinks); 00336 00337 UNLOCK_EXPANSION (OldIrql); 00338 00339 // 00340 // Decrement this process' reference count to the session. If this 00341 // is the last reference, then the entire session will be destroyed 00342 // upon return. This includes unloading drivers, unmapping pools, 00343 // freeing page tables, etc. 00344 // 00345 00346 MiDereferenceSession (); 00347 }

VOID MiSessionUnlinkWorkingSet VOID   ) 
 

VOID MiSessionUnloadAllImages VOID   ) 
 

Definition at line 572 of file sessload.c.

References _IMAGE_ENTRY_IN_SESSION::Address, ASSERT, _MM_SESSION_SPACE::ImageList, MiLookupPsLoadedModule(), MmSessionSpace, MmUnloadSystemImage(), NTSTATUS(), _MM_SESSION_SPACE::ReferenceCount, and Status.

Referenced by MiDereferenceSession().

00578 : 00579 00580 This routine dereferences each image that has been loaded in the 00581 current session space. 00582 00583 As each image is dereferenced, checks are made: 00584 00585 If this session's reference count to the image reaches zero, the VA 00586 range in this session is deleted. If the reference count to the image 00587 in the SESSIONWIDE list drops to zero, then the SESSIONWIDE's VA 00588 reservation is removed and the address space is made available to any 00589 new image. 00590 00591 If this is the last systemwide reference to the driver then the driver 00592 is deleted from memory. 00593 00594 Arguments: 00595 00596 None. 00597 00598 Return Value: 00599 00600 None. 00601 00602 Environment: 00603 00604 Kernel mode. This is called in one of two contexts: 00605 1. the last thread in the last process of the current session space. 00606 2. or by any thread in the SMSS process. 00607 00608 --*/ 00609 00610 { 00611 NTSTATUS Status; 00612 PLIST_ENTRY NextEntry; 00613 PIMAGE_ENTRY_IN_SESSION Module; 00614 PLDR_DATA_TABLE_ENTRY ImageHandle; 00615 00616 ASSERT (MmSessionSpace->ReferenceCount == 1); 00617 00618 // 00619 // The session's working set lock does not need to be acquired here since 00620 // no thread can be faulting on these addresses. 00621 // 00622 00623 NextEntry = MmSessionSpace->ImageList.Flink; 00624 00625 while (NextEntry != &MmSessionSpace->ImageList) { 00626 00627 Module = CONTAINING_RECORD(NextEntry, IMAGE_ENTRY_IN_SESSION, Link); 00628 00629 // 00630 // Lookup the image entry in the system PsLoadedModuleList, 00631 // unload the image and delete it. 00632 // 00633 00634 ImageHandle = MiLookupPsLoadedModule (Module->Address); 00635 00636 ASSERT (ImageHandle); 00637 00638 Status = MmUnloadSystemImage (ImageHandle); 00639 00640 // 00641 // Restart the search at the beginning since the entry has been deleted. 00642 // 00643 00644 ASSERT (MmSessionSpace->ReferenceCount == 1); 00645 00646 NextEntry = MmSessionSpace->ImageList.Flink; 00647 } 00648 }

NTSTATUS MiSessionWideGetImageSize IN PVOID  BaseAddress,
OUT PSIZE_T NumberOfBytes  OPTIONAL,
OUT PSIZE_T CommitPages  OPTIONAL
 

Definition at line 866 of file sessload.c.

References _SESSIONWIDE_DRIVER_ADDRESS::Address, MmSessionWideAddressList, PSESSIONWIDE_DRIVER_ADDRESS, _SESSIONWIDE_DRIVER_ADDRESS::Size, SYSLOAD_LOCK_OWNED_BY_ME, and _SESSIONWIDE_DRIVER_ADDRESS::WritablePages.

Referenced by MiShareSessionImage(), and MmUnloadSystemImage().

00874 : 00875 00876 Lookup the size allocated and committed for the image at the base address. 00877 This ensures that we free every page that may have been allocated due 00878 to rounding up. 00879 00880 Arguments: 00881 00882 BaseAddress - Supplies the preferred address that the driver has 00883 been linked (rebased) at. If this address is available, 00884 the driver will require no relocation. 00885 00886 NumberOfBytes - Supplies a pointer to store the image size into. 00887 00888 CommitPages - Supplies a pointer to store the number of committed pages 00889 that were charged for this image. 00890 00891 Return Value: 00892 00893 Returns STATUS_SUCCESS on success, STATUS_NOT_FOUND on failure. 00894 00895 Environment: 00896 00897 Kernel mode, APC_LEVEL and below, MmSystemLoadLock held. 00898 00899 --*/ 00900 00901 { 00902 PLIST_ENTRY NextEntry; 00903 PSESSIONWIDE_DRIVER_ADDRESS SessionWideEntry; 00904 00905 SYSLOAD_LOCK_OWNED_BY_ME (); 00906 00907 NextEntry = MmSessionWideAddressList.Flink; 00908 00909 while (NextEntry != &MmSessionWideAddressList) { 00910 00911 SessionWideEntry = CONTAINING_RECORD (NextEntry, 00912 SESSIONWIDE_DRIVER_ADDRESS, 00913 Link); 00914 00915 if (BaseAddress == SessionWideEntry->Address) { 00916 00917 if (ARGUMENT_PRESENT (NumberOfBytes)) { 00918 *NumberOfBytes = SessionWideEntry->Size; 00919 } 00920 00921 if (ARGUMENT_PRESENT (CommitPages)) { 00922 *CommitPages = SessionWideEntry->WritablePages; 00923 } 00924 00925 return STATUS_SUCCESS; 00926 } 00927 00928 NextEntry = NextEntry->Flink; 00929 } 00930 00931 return STATUS_NOT_FOUND; 00932 }

VOID MiSessionWideInitializeAddresses VOID   ) 
 

Definition at line 652 of file sessload.c.

References MmSessionWideAddressList.

Referenced by MmInitSystem().

00658 : 00659 00660 This routine is called at system initialization to set up the group 00661 address list. 00662 00663 Arguments: 00664 00665 None. 00666 00667 Return Value: 00668 00669 None. 00670 00671 Environment: 00672 00673 Kernel mode. 00674 00675 --*/ 00676 00677 { 00678 InitializeListHead (&MmSessionWideAddressList); 00679 }

NTSTATUS MiSessionWideReserveImageAddress IN PUNICODE_STRING  pImageName,
IN PSECTION  Section,
IN ULONG_PTR  Alignment,
OUT PVOID *  ppAddr,
OUT PBOOLEAN  pAlreadyLoaded
 

Definition at line 936 of file sessload.c.

References _SESSIONWIDE_DRIVER_ADDRESS::Address, ASSERT, DbgPrint, FALSE, _SESSIONWIDE_DRIVER_ADDRESS::FullDllName, MI_ROUND_TO_SIZE, MI_SESSION_IMAGE_SIZE, MI_SESSION_IMAGE_START, MiGetWritablePagesInSection(), MiSessionInsertImage(), MiSessionWideDereferenceImage(), MiSessionWideInsertImageAddress(), MM_BUMP_SESSION_FAILURES, MM_DBG_SESSIONS, MM_SESSION_FAILURE_NO_IMAGE_VA_SPACE, MmIsAddressValid(), MmSessionSpace, MmSessionWideAddressList, NT_SUCCESS, NTSTATUS(), NULL, PAGE_SHIFT, PAGED_CODE, PSESSIONWIDE_DRIVER_ADDRESS, PsGetCurrentProcess, _SESSIONWIDE_DRIVER_ADDRESS::ReferenceCount, RtlEqualUnicodeString(), _SESSIONWIDE_DRIVER_ADDRESS::Size, Status, SYSLOAD_LOCK_OWNED_BY_ME, and TRUE.

Referenced by MiLoadImageSection().

00946 : 00947 00948 This routine allocates a range of virtual address space within 00949 session space. This address range is unique system-wide and in this 00950 manner, code and pristine data of session drivers can be shared across 00951 multiple sessions. 00952 00953 This routine does not actually commit pages, but reserves the virtual 00954 address region for the named image. An entry is created here and attached 00955 to the current session space to track the loaded image. Thus if all 00956 the references to a given range go away, the range can then be reused. 00957 00958 Arguments: 00959 00960 ImageName - Supplies the name of the driver that will be loaded into 00961 the allocated space. 00962 00963 Section - Supplies the section (and thus, the preferred address that the 00964 driver has been linked (rebased) at. If this address is 00965 available, the driver will require no relocation. The section 00966 is also used to derive the number of bytes to reserve. 00967 00968 Alignment - Supplies the virtual address alignment for the address. 00969 00970 AssignedAddress - Supplies a pointer to a variable that receives the 00971 allocated address if the routine succeeds. 00972 00973 AlreadyLoaded - Supplies a pointer to a variable that receives TRUE if the 00974 specified image name has already been loaded. 00975 00976 Return Value: 00977 00978 Returns STATUS_SUCCESS on success, various NTSTATUS codes on failure. 00979 00980 Environment: 00981 00982 Kernel mode, APC_LEVEL and below, MmSystemLoadLock held. 00983 00984 --*/ 00985 00986 { 00987 PLIST_ENTRY NextEntry; 00988 PSESSIONWIDE_DRIVER_ADDRESS Vaddr; 00989 NTSTATUS Status; 00990 PWCHAR pName; 00991 PVOID NewAddress; 00992 ULONG_PTR AvailableAddress; 00993 ULONG_PTR SessionSpaceEnd; 00994 PVOID PreferredAddress; 00995 ULONG_PTR NumberOfBytes; 00996 ULONG WritablePages; 00997 BOOLEAN AtPreferredAddress; 00998 00999 PAGED_CODE(); 01000 01001 SYSLOAD_LOCK_OWNED_BY_ME (); 01002 01003 ASSERT (PsGetCurrentProcess()->Vm.u.Flags.ProcessInSession == 1); 01004 ASSERT (MmIsAddressValid (MmSessionSpace) == TRUE); 01005 01006 pName = NULL; 01007 *AlreadyLoaded = FALSE; 01008 PreferredAddress = Section->Segment->BasedAddress; 01009 NumberOfBytes = Section->Segment->TotalNumberOfPtes << PAGE_SHIFT; 01010 01011 AvailableAddress = MI_SESSION_IMAGE_START; 01012 NumberOfBytes = MI_ROUND_TO_SIZE (NumberOfBytes, Alignment); 01013 SessionSpaceEnd = AvailableAddress + MI_SESSION_IMAGE_SIZE; 01014 01015 Status = MiGetWritablePagesInSection(Section, &WritablePages); 01016 01017 if (!NT_SUCCESS(Status)) { 01018 WritablePages = Section->Segment->TotalNumberOfPtes; 01019 } 01020 01021 // 01022 // If the requested address is not properly aligned or not in the session 01023 // space region, pick an address for it. This image will not be shared. 01024 // 01025 01026 if ((ULONG_PTR)PreferredAddress & (Alignment - 1)) { 01027 01028 #if DBG 01029 DbgPrint("MiSessionWideReserveImageAddress: Bad alignment 0x%x for PreferredAddress 0x%x\n", 01030 Alignment, 01031 PreferredAddress); 01032 #endif 01033 01034 PreferredAddress = NULL; 01035 } 01036 else if ((ULONG_PTR)PreferredAddress < AvailableAddress || 01037 ((ULONG_PTR)PreferredAddress + NumberOfBytes >= SessionSpaceEnd)) { 01038 01039 #if DBG 01040 if (MmDebug & MM_DBG_SESSIONS) { 01041 DbgPrint ("MiSessionWideReserveImageAddress: PreferredAddress 0x%x not in session space\n", PreferredAddress); 01042 } 01043 #endif 01044 01045 PreferredAddress = NULL; 01046 } 01047 01048 // 01049 // Check the system wide session space image list to see if the 01050 // image name has already been given a slot. 01051 // 01052 01053 NextEntry = MmSessionWideAddressList.Flink; 01054 01055 while (NextEntry != &MmSessionWideAddressList) { 01056 01057 Vaddr = CONTAINING_RECORD (NextEntry, 01058 SESSIONWIDE_DRIVER_ADDRESS, 01059 Link); 01060 01061 if (Vaddr->FullDllName.Buffer != NULL) { 01062 01063 if (RtlEqualUnicodeString(ImageName, &Vaddr->FullDllName, TRUE)) { 01064 01065 // 01066 // The size requested should be the same. 01067 // 01068 01069 if (Vaddr->Size < NumberOfBytes) { 01070 #if DBG 01071 DbgPrint ("MiSessionWideReserveImageAddress: Size %d Larger than Entry %d, DLL %wZ\n", 01072 NumberOfBytes, 01073 Vaddr->Size, 01074 ImageName); 01075 #endif 01076 01077 return STATUS_CONFLICTING_ADDRESSES; 01078 } 01079 01080 // 01081 // This image has already been loaded systemwide. If it's 01082 // already been loaded in this session space as well, just 01083 // bump the reference count using the already allocated 01084 // address. Otherwise, insert it into this session space. 01085 // 01086 01087 Status = MiSessionInsertImage (Vaddr->Address); 01088 01089 if (Status == STATUS_ALREADY_COMMITTED) { 01090 01091 *AlreadyLoaded = TRUE; 01092 *AssignedAddress = Vaddr->Address; 01093 01094 return STATUS_SUCCESS; 01095 } 01096 01097 if (!NT_SUCCESS (Status)) { 01098 return Status; 01099 } 01100 01101 // 01102 // Bump the reference count as this is a new entry. 01103 // 01104 01105 Vaddr->ReferenceCount += 1; 01106 01107 *AssignedAddress = Vaddr->Address; 01108 01109 return STATUS_SUCCESS; 01110 } 01111 } 01112 01113 // 01114 // Note this list must be sorted by ascending address. 01115 // See if the PreferredAddress and size collide with any entries. 01116 // 01117 01118 if (PreferredAddress) { 01119 01120 if ((PreferredAddress >= Vaddr->Address) && 01121 (PreferredAddress < (PVOID)((ULONG_PTR)Vaddr->Address + Vaddr->Size))) { 01122 PreferredAddress = NULL; 01123 } 01124 else if ((PreferredAddress < Vaddr->Address) && 01125 ((PVOID)((ULONG_PTR)PreferredAddress + NumberOfBytes) > Vaddr->Address)) { 01126 PreferredAddress = NULL; 01127 } 01128 } 01129 01130 // 01131 // Check for an available general allocation slot. 01132 // 01133 01134 if (((PVOID)AvailableAddress >= Vaddr->Address) && 01135 (AvailableAddress <= (ULONG_PTR)Vaddr->Address + Vaddr->Size)) { 01136 01137 AvailableAddress = (ULONG_PTR)Vaddr->Address + Vaddr->Size; 01138 01139 if (AvailableAddress & (Alignment - 1)) { 01140 AvailableAddress = MI_ROUND_TO_SIZE (AvailableAddress, Alignment); 01141 } 01142 } 01143 else if (AvailableAddress + NumberOfBytes > (ULONG_PTR)Vaddr->Address) { 01144 01145 AvailableAddress = (ULONG_PTR)Vaddr->Address + Vaddr->Size; 01146 01147 if (AvailableAddress & (Alignment - 1)) { 01148 AvailableAddress = MI_ROUND_TO_SIZE (AvailableAddress, Alignment); 01149 } 01150 } 01151 01152 NextEntry = NextEntry->Flink; 01153 } 01154 01155 if (PreferredAddress == NULL && (AvailableAddress + NumberOfBytes > (MI_SESSION_IMAGE_START + MI_SESSION_IMAGE_SIZE))) { 01156 MM_BUMP_SESSION_FAILURES (MM_SESSION_FAILURE_NO_IMAGE_VA_SPACE); 01157 return STATUS_NO_MEMORY; 01158 } 01159 01160 // 01161 // Try to put the module into its requested address so it can be shared. 01162 // 01163 01164 if (PreferredAddress) { 01165 01166 #if DBG 01167 if (MmDebug & MM_DBG_SESSIONS) { 01168 DbgPrint ("MiSessionWideReserveImageAddress: Code Sharing on %wZ, Address 0x%x\n",ImageName,PreferredAddress); 01169 } 01170 #endif 01171 01172 NewAddress = PreferredAddress; 01173 } 01174 else { 01175 ASSERT (AvailableAddress != 0); 01176 ASSERT ((AvailableAddress & (Alignment - 1)) == 0); 01177 01178 #if DBG 01179 DbgPrint ("MiSessionWideReserveImageAddress: NO Code Sharing on %wZ, Address 0x%x\n",ImageName,AvailableAddress); 01180 #endif 01181 01182 NewAddress = (PVOID)AvailableAddress; 01183 } 01184 01185 // 01186 // Create a new node entry for the address range. 01187 // 01188 01189 if (NewAddress == PreferredAddress) { 01190 AtPreferredAddress = TRUE; 01191 } 01192 else { 01193 AtPreferredAddress = FALSE; 01194 } 01195 01196 Status = MiSessionWideInsertImageAddress (NewAddress, 01197 NumberOfBytes, 01198 WritablePages, 01199 ImageName, 01200 AtPreferredAddress); 01201 01202 if (!NT_SUCCESS(Status)) { 01203 return Status; 01204 } 01205 01206 // 01207 // Create an entry for this image in the current session space. 01208 // 01209 01210 Status = MiSessionInsertImage (NewAddress); 01211 01212 if (!NT_SUCCESS(Status)) { 01213 MiSessionWideDereferenceImage (NewAddress); 01214 return Status; 01215 } 01216 01217 *AssignedAddress = NewAddress; 01218 01219 return STATUS_SUCCESS; 01220 }

VOID MiSetDirtyBit IN PVOID  FaultingAddress,
IN PMMPTE  PointerPte,
IN ULONG  PfnHeld
 

Definition at line 28 of file alpha/setdirty.c.

References MI_PFN_ELEMENT, MI_SET_ACCESSED_IN_PTE, MiReleasePageFileSpace(), MM_PTE_DIRTY, _MMPFN::OriginalPte, TRUE, _MMPTE::u, and _MMPFN::u3.

00036 : 00037 00038 This routine sets dirty in the specified PTE and the modify bit in the 00039 correpsonding PFN element. If any page file space is allocated, it 00040 is deallocated. 00041 00042 Arguments: 00043 00044 FaultingAddress - Supplies the faulting address. 00045 00046 PointerPte - Supplies a pointer to the corresponding valid PTE. 00047 00048 PfnHeld - Supplies TRUE if the PFN mutex is already held. 00049 00050 Return Value: 00051 00052 None. 00053 00054 Environment: 00055 00056 Kernel mode, APC's disabled, Working set mutex held. 00057 00058 --*/ 00059 00060 { 00061 MMPTE TempPte; 00062 ULONG PageFrameIndex; 00063 PMMPFN Pfn1; 00064 KIRQL OldIrql; 00065 00066 // 00067 // The TB entry must be flushed as the valid PTE with the dirty bit clear 00068 // has been fetched into the TB. If it isn't flushed, another fault 00069 // is generated as the dirty bit is not set in the cached TB entry. 00070 // 00071 00072 // KiFlushSingleDataTb( FaultingAddress ); 00073 __dtbis( FaultingAddress ); 00074 00075 // 00076 // The page is NOT copy on write, update the PTE setting both the 00077 // dirty bit and the accessed bit. Note, that as this PTE is in 00078 // the TB, the TB must be flushed. 00079 // 00080 00081 PageFrameIndex = PointerPte->u.Hard.PageFrameNumber; 00082 Pfn1 = MI_PFN_ELEMENT (PageFrameIndex); 00083 00084 TempPte = *PointerPte; 00085 TempPte.u.Hard.Dirty = 1; 00086 MI_SET_ACCESSED_IN_PTE (&TempPte, 1); 00087 *PointerPte = TempPte; 00088 00089 // 00090 // If the PFN database lock is not held, then do not update the 00091 // PFN database. 00092 // 00093 00094 if (PfnHeld) { 00095 00096 // 00097 // Set the modified field in the PFN database, also, if the physical 00098 // page is currently in a paging file, free up the page file space 00099 // as the contents are now worthless. 00100 // 00101 00102 if ( (Pfn1->OriginalPte.u.Soft.Prototype == 0) && 00103 (Pfn1->u3.e1.WriteInProgress == 0) ) { 00104 00105 // 00106 // This page is in page file format, deallocate the page file space. 00107 // 00108 00109 MiReleasePageFileSpace (Pfn1->OriginalPte); 00110 00111 // 00112 // Change original PTE to indicate no page file space is reserved, 00113 // otherwise the space will be deallocated when the PTE is 00114 // deleted. 00115 // 00116 00117 Pfn1->OriginalPte.u.Soft.PageFileHigh = 0; 00118 } 00119 00120 Pfn1->u3.e1.Modified = 1; 00121 00122 } 00123 00124 00125 return; 00126 } }

VOID MiSetImageProtect IN PSEGMENT  Segment,
IN ULONG  Protection
 

Definition at line 5376 of file sysload.c.

References ASSERT, MiSetProtectionOnTransitionPte(), MM_PROTECTION_WRITE_MASK, MmLockPagedPool(), MMPTE, MmUnlockPagedPool(), _SUBSECTION::u, _MMPTE::u, and ZeroPte.

Referenced by MiLoadSystemImage(), and MiShareSessionImage().

05383 : 05384 05385 This function sets the protection of all prototype PTEs to the specified 05386 protection. 05387 05388 Arguments: 05389 05390 Segment - Supplies a pointer to the segment to protect. 05391 05392 Protection - Supplies the protection value to set. 05393 05394 Return Value: 05395 05396 None. 05397 05398 --*/ 05399 05400 { 05401 PMMPTE PointerPte; 05402 PMMPTE LastPte; 05403 MMPTE PteContents; 05404 PSUBSECTION SubSection; 05405 05406 // 05407 // Set the subsection protections. 05408 // 05409 05410 ASSERT (Segment->ControlArea->u.Flags.GlobalOnlyPerSession == 0); 05411 05412 if ((Protection & MM_PROTECTION_WRITE_MASK) == 0) { 05413 SubSection = (PSUBSECTION)(Segment->ControlArea + 1); 05414 SubSection->u.SubsectionFlags.Protection = Protection; 05415 SubSection->u.SubsectionFlags.ReadOnly = 1; 05416 } 05417 05418 PointerPte = Segment->PrototypePte; 05419 LastPte = PointerPte + Segment->NonExtendedPtes; 05420 05421 MmLockPagedPool (PointerPte, (LastPte - PointerPte) * sizeof (MMPTE)); 05422 05423 do { 05424 PteContents = *PointerPte; 05425 ASSERT (PteContents.u.Hard.Valid == 0); 05426 if (PteContents.u.Long != ZeroPte.u.Long) { 05427 if ((PteContents.u.Soft.Prototype == 0) && 05428 (PteContents.u.Soft.Transition == 1)) { 05429 if (MiSetProtectionOnTransitionPte (PointerPte, Protection)) { 05430 continue; 05431 } 05432 } 05433 else { 05434 PointerPte->u.Soft.Protection = Protection; 05435 } 05436 } 05437 PointerPte += 1; 05438 } while (PointerPte < LastPte); 05439 05440 PointerPte = Segment->PrototypePte; 05441 MmUnlockPagedPool (PointerPte, (LastPte - PointerPte) * sizeof (MMPTE)); 05442 05443 return; 05444 }

VOID MiSetModifyBit IN PMMPFN  Pfn  ) 
 

Definition at line 26 of file setmodfy.c.

References MiReleasePageFileSpace().

00032 : 00033 00034 This routine sets the modify bit in the specified PFN element 00035 and deallocates and allocated page file space. 00036 00037 Arguments: 00038 00039 Pfn - Supplies the pointer to the PFN element to update. 00040 00041 Return Value: 00042 00043 None. 00044 00045 Environment: 00046 00047 Kernel mode, APCs disabled, Working set mutex held and PFN lock held. 00048 00049 --*/ 00050 00051 { 00052 00053 // 00054 // Set the modified field in the PFN database, also, if the physical 00055 // page is currently in a paging file, free up the page file space 00056 // as the contents are now worthless. 00057 // 00058 00059 Pfn->u3.e1.Modified = 1; 00060 00061 if (Pfn->OriginalPte.u.Soft.Prototype == 0) { 00062 00063 // 00064 // This page is in page file format, deallocate the page file space. 00065 // 00066 00067 MiReleasePageFileSpace (Pfn->OriginalPte); 00068 00069 // 00070 // Change original PTE to indicate no page file space is reserved, 00071 // otherwise the space will be deallocated when the PTE is 00072 // deleted. 00073 // 00074 00075 Pfn->OriginalPte.u.Soft.PageFileHigh = 0; 00076 } 00077 00078 00079 return; 00080 }

ULONG MiSetProtectionOnSection IN PEPROCESS  Process,
IN PMMVAD  Vad,
IN PVOID  StartingAddress,
IN PVOID  EndingAddress,
IN ULONG  NewProtect,
OUT PULONG  CapturedOldProtect,
IN ULONG  DontCharge
 

Definition at line 1110 of file protect.c.

References ASSERT, EXCEPTION_EXECUTE_HANDLER, ExRaiseStatus(), FALSE, Index, LOCK_WS_UNSAFE, MI_CONVERT_FROM_PTE_PROTECTION, MI_GET_USED_PTES_HANDLE, MI_GET_WORKING_SET_FROM_PTE, MI_INCREMENT_USED_PTES_BY_HANDLE, MI_IS_PTE_PROTECTION_COPY_WRITE, MI_MAKE_VALID_PTE, MI_PFN_ELEMENT, MI_PTE_LOOKUP_NEEDED, MI_SET_PTE_IN_WORKING_SET, MI_VA_TO_VPN, MI_WRITE_INVALID_PTE, MiCaptureSystemPte(), MiChangeNoAccessForkPte(), MiChargeCommitment(), MiChargePageFileQuota(), MiCopyOnWrite(), MiDoesPdeExistAndMakeValid(), MiDoesPpeExistAndMakeValid, MiFlushTbAndCapture(), MiGetPageProtection(), MiGetPdeAddress, MiGetPpeAddress, MiGetProtoPteAddress, MiGetPteAddress, MiGetVirtualAddressMappedByPte, MiIsPteOnPdeBoundary, MiLocateWsle(), MiMakePdeExistAndMakeValid(), MiMakePpeExistAndMakeValid, MiMakeProtectionMask(), MiPteToProto, MiRemovePageFromWorkingSet(), MiReturnCommitment(), MiReturnPageFileQuota(), MiSetProtectionOnTransitionPte(), MM_COPY_ON_WRITE_MASK, MM_DBG_COMMIT_RETURN_PROTECTION, MM_DBG_COMMIT_SET_PROTECTION, MM_PROTECTION_COPY_MASK, MM_TRACK_COMMIT, MmWorkingSetList, MmWsle, NTSTATUS(), NULL, _MMPFN::OriginalPte, PAGED_CODE, PrototypePte, PS_JOB_STATUS_REPORT_COMMIT_CHANGES, PsChangeJobMemoryUsage(), PsReportProcessMemoryLimitViolation(), _MMPFN::PteAddress, TRUE, _MMPTE::u, _MMPFN::u1, _MMWSLE::u1, _MMPFN::u3, UNLOCK_WS_UNSAFE, and VOID().

Referenced by MiProtectVirtualMemory(), and NtAllocateVirtualMemory().

01122 : 01123 01124 This routine changes the protection on a region of committed pages 01125 within the virtual address space of the subject process. Setting 01126 the protection on a range of pages causes the old protection to be 01127 replaced by the specified protection value. 01128 01129 Arguments: 01130 01131 Process - Supplies a pointer to the current process. 01132 01133 FoundVad - Supplies a pointer to the VAD containing the range to protect. 01134 01135 StartingAddress - Supplies the starting address to protect. 01136 01137 EndingAddress - Supplies the ending address to protect. 01138 01139 NewProtect - Supplies the new protection to set. 01140 01141 CapturedOldProtect - Supplies the address of a kernel owned pointer to 01142 store (without probing) the old protection into. 01143 01144 DontCharge - Supplies TRUE if no quota or commitment should be charged. 01145 01146 Return Value: 01147 01148 Returns TRUE if a locked page was removed from the working set (protection 01149 was guard page or no-access, FALSE otherwise. 01150 01151 Exceptions raised for page file quota or commitment violations. 01152 01153 Environment: 01154 01155 Kernel mode, working set mutex held, address creation mutex held 01156 APCs disabled. 01157 01158 --*/ 01159 01160 { 01161 PMMPTE PointerPte; 01162 PMMPTE LastPte; 01163 PMMPTE PointerPde; 01164 PMMPTE PointerPpe; 01165 PMMPTE PointerProtoPte; 01166 PMMPFN Pfn1; 01167 MMPTE TempPte; 01168 MMPTE PreviousPte; 01169 ULONG Locked; 01170 ULONG ProtectionMask; 01171 ULONG ProtectionMaskNotCopy; 01172 ULONG NewProtectionMask; 01173 MMPTE PteContents; 01174 ULONG Index; 01175 PULONG Va; 01176 ULONG WriteCopy; 01177 ULONG DoAgain; 01178 ULONG Waited; 01179 SIZE_T QuotaCharge; 01180 PVOID UsedPageTableHandle; 01181 PVOID UsedPageDirectoryHandle; 01182 ULONG WorkingSetIndex; 01183 01184 PAGED_CODE(); 01185 01186 Locked = FALSE; 01187 WriteCopy = FALSE; 01188 QuotaCharge = 0; 01189 01190 // 01191 // Make the protection field. 01192 // 01193 01194 ASSERT (FoundVad->u.VadFlags.PrivateMemory == 0); 01195 01196 if ((FoundVad->u.VadFlags.ImageMap == 1) || 01197 (FoundVad->u2.VadFlags2.CopyOnWrite == 1)) { 01198 01199 if (NewProtect & PAGE_READWRITE) { 01200 NewProtect &= ~PAGE_READWRITE; 01201 NewProtect |= PAGE_WRITECOPY; 01202 } 01203 01204 if (NewProtect & PAGE_EXECUTE_READWRITE) { 01205 NewProtect &= ~PAGE_EXECUTE_READWRITE; 01206 NewProtect |= PAGE_EXECUTE_WRITECOPY; 01207 } 01208 } 01209 01210 ProtectionMask = MiMakeProtectionMask (NewProtect); 01211 01212 // 01213 // Determine if copy on write is being set. 01214 // 01215 01216 ProtectionMaskNotCopy = ProtectionMask; 01217 if ((ProtectionMask & MM_COPY_ON_WRITE_MASK) == MM_COPY_ON_WRITE_MASK) { 01218 WriteCopy = TRUE; 01219 ProtectionMaskNotCopy &= ~MM_PROTECTION_COPY_MASK; 01220 } 01221 01222 #if defined(_MIALT4K_) 01223 01224 if ((Process->Wow64Process != NULL) && 01225 (FoundVad->u.VadFlags.ImageMap == 0) && 01226 (FoundVad->u2.VadFlags2.CopyOnWrite == 0) && 01227 (WriteCopy)) { 01228 01229 NTSTATUS status; 01230 01231 status = MiSetCopyPagesFor4kPage(Process, 01232 &FoundVad, 01233 &StartingAddress, 01234 &EndingAddress, 01235 ProtectionMask); 01236 01237 if (status != STATUS_SUCCESS) { 01238 ExRaiseStatus (status); 01239 } 01240 01241 } 01242 01243 #endif 01244 01245 PointerPpe = MiGetPpeAddress (StartingAddress); 01246 PointerPde = MiGetPdeAddress (StartingAddress); 01247 PointerPte = MiGetPteAddress (StartingAddress); 01248 LastPte = MiGetPteAddress (EndingAddress); 01249 01250 #if defined (_WIN64) 01251 MiMakePpeExistAndMakeValid (PointerPpe, Process, FALSE); 01252 if (PointerPde->u.Long == 0) { 01253 UsedPageDirectoryHandle = MI_GET_USED_PTES_HANDLE (PointerPte); 01254 MI_INCREMENT_USED_PTES_BY_HANDLE (UsedPageDirectoryHandle); 01255 } 01256 #endif 01257 01258 MiMakePdeExistAndMakeValid(PointerPde, Process, FALSE); 01259 01260 // 01261 // Capture the protection for the first page. 01262 // 01263 01264 if (PointerPte->u.Long != 0) { 01265 01266 *CapturedOldProtect = MiGetPageProtection (PointerPte, Process); 01267 01268 // 01269 // Make sure the Page table page is still resident. 01270 // 01271 01272 PointerPpe = MiGetPteAddress (PointerPde); 01273 01274 do { 01275 01276 (VOID)MiDoesPpeExistAndMakeValid (PointerPpe, Process, FALSE, &Waited); 01277 Waited = 0; 01278 01279 (VOID)MiDoesPdeExistAndMakeValid (PointerPde, Process, FALSE, &Waited); 01280 } while (Waited != 0); 01281 01282 } else { 01283 01284 // 01285 // Get the protection from the VAD, unless image file. 01286 // 01287 01288 if (FoundVad->u.VadFlags.ImageMap == 0) { 01289 01290 // 01291 // This is not an image file, the protection is in the VAD. 01292 // 01293 01294 *CapturedOldProtect = 01295 MI_CONVERT_FROM_PTE_PROTECTION(FoundVad->u.VadFlags.Protection); 01296 } else { 01297 01298 // 01299 // This is an image file, the protection is in the 01300 // prototype PTE. 01301 // 01302 01303 PointerProtoPte = MiGetProtoPteAddress (FoundVad, 01304 MI_VA_TO_VPN ( 01305 MiGetVirtualAddressMappedByPte (PointerPte))); 01306 01307 TempPte = MiCaptureSystemPte (PointerProtoPte, Process); 01308 01309 *CapturedOldProtect = MiGetPageProtection (&TempPte, 01310 Process); 01311 01312 // 01313 // Make sure the Page directory and table pages are still resident. 01314 // 01315 01316 PointerPpe = MiGetPteAddress (PointerPde); 01317 01318 do { 01319 01320 (VOID)MiDoesPpeExistAndMakeValid(PointerPpe, Process, FALSE, &Waited); 01321 Waited = 0; 01322 01323 (VOID)MiDoesPdeExistAndMakeValid(PointerPde, Process, FALSE, &Waited); 01324 } while (Waited != 0); 01325 } 01326 } 01327 01328 // 01329 // If the page protection is being change to be copy-on-write, the 01330 // commitment and page file quota for the potentially dirty private pages 01331 // must be calculated and charged. This must be done before any 01332 // protections are changed as the changes cannot be undone. 01333 // 01334 01335 if (WriteCopy) { 01336 01337 // 01338 // Calculate the charges. If the page is shared and not write copy 01339 // it is counted as a charged page. 01340 // 01341 01342 while (PointerPte <= LastPte) { 01343 01344 if (MiIsPteOnPdeBoundary (PointerPte)) { 01345 01346 PointerPde = MiGetPteAddress (PointerPte); 01347 PointerPpe = MiGetPteAddress (PointerPde); 01348 01349 do { 01350 01351 while (!MiDoesPpeExistAndMakeValid(PointerPpe, Process, FALSE, &Waited)) { 01352 01353 // 01354 // No PPE exists for this address. Therefore 01355 // all the PTEs are shared and not copy on write. 01356 // go to the next PPE. 01357 // 01358 01359 PointerPpe += 1; 01360 PointerPde = MiGetVirtualAddressMappedByPte (PointerPpe); 01361 PointerProtoPte = PointerPte; 01362 PointerPte = MiGetVirtualAddressMappedByPte (PointerPde); 01363 01364 if (PointerPte > LastPte) { 01365 QuotaCharge += 1 + LastPte - PointerProtoPte; 01366 goto Done; 01367 } 01368 QuotaCharge += PointerPte - PointerProtoPte; 01369 } 01370 01371 Waited = 0; 01372 01373 while (!MiDoesPdeExistAndMakeValid(PointerPde, Process, FALSE, &Waited)) { 01374 01375 // 01376 // No PDE exists for this address. Therefore 01377 // all the PTEs are shared and not copy on write. 01378 // go to the next PDE. 01379 // 01380 01381 PointerPde += 1; 01382 PointerProtoPte = PointerPte; 01383 PointerPpe = MiGetPteAddress (PointerPde); 01384 PointerPte = MiGetVirtualAddressMappedByPte (PointerPde); 01385 01386 if (PointerPte > LastPte) { 01387 QuotaCharge += 1 + LastPte - PointerProtoPte; 01388 goto Done; 01389 } 01390 QuotaCharge += PointerPte - PointerProtoPte; 01391 #if defined (_WIN64) 01392 if (MiIsPteOnPdeBoundary (PointerPde)) { 01393 Waited = 1; 01394 break; 01395 } 01396 #endif 01397 } 01398 } while (Waited != 0); 01399 } 01400 01401 PteContents = *PointerPte; 01402 01403 if (PteContents.u.Long == 0) { 01404 01405 // 01406 // The PTE has not been evaluated, assume copy on write. 01407 // 01408 01409 QuotaCharge += 1; 01410 01411 } else if ((PteContents.u.Hard.Valid == 1) && 01412 (PteContents.u.Hard.CopyOnWrite == 0)) { 01413 01414 // 01415 // See if this is a prototype PTE, if so charge it. 01416 // 01417 01418 Pfn1 = MI_PFN_ELEMENT (PteContents.u.Hard.PageFrameNumber); 01419 01420 if (Pfn1->u3.e1.PrototypePte == 1) { 01421 QuotaCharge += 1; 01422 } 01423 } else { 01424 01425 if (PteContents.u.Soft.Prototype == 1) { 01426 01427 // 01428 // This is a prototype PTE. Charge if it is not 01429 // in copy on write format. 01430 // 01431 01432 if (PteContents.u.Soft.PageFileHigh == MI_PTE_LOOKUP_NEEDED) { 01433 01434 // 01435 // Page protection is within the PTE. 01436 // 01437 01438 if (!MI_IS_PTE_PROTECTION_COPY_WRITE(PteContents.u.Soft.Protection)) { 01439 QuotaCharge += 1; 01440 } 01441 } else { 01442 01443 // 01444 // The PTE references the prototype directly, therefore 01445 // it can't be copy on write. Charge. 01446 // 01447 01448 QuotaCharge += 1; 01449 } 01450 } 01451 } 01452 PointerPte += 1; 01453 } 01454 01455 Done: 01456 NOTHING; 01457 01458 // 01459 // Charge for the quota. 01460 // 01461 01462 if (!DontCharge) { 01463 MiChargePageFileQuota (QuotaCharge, Process); 01464 01465 if (Process->CommitChargeLimit) { 01466 if (Process->CommitCharge + QuotaCharge > Process->CommitChargeLimit) { 01467 MiReturnPageFileQuota (QuotaCharge, Process); 01468 if (Process->Job) { 01469 PsReportProcessMemoryLimitViolation (); 01470 } 01471 ExRaiseStatus (STATUS_COMMITMENT_LIMIT); 01472 } 01473 } 01474 if (Process->JobStatus & PS_JOB_STATUS_REPORT_COMMIT_CHANGES) { 01475 if (PsChangeJobMemoryUsage(QuotaCharge) == FALSE) { 01476 MiReturnPageFileQuota (QuotaCharge, Process); 01477 ExRaiseStatus (STATUS_COMMITMENT_LIMIT); 01478 } 01479 } 01480 01481 if (MiChargeCommitment (QuotaCharge, Process) == FALSE) { 01482 if (Process->JobStatus & PS_JOB_STATUS_REPORT_COMMIT_CHANGES) { 01483 01484 // 01485 // Temporarily up the process commit charge as the 01486 // job code will be referencing it as though everything 01487 // has succeeded. 01488 // 01489 01490 Process->CommitCharge += QuotaCharge; 01491 PsChangeJobMemoryUsage(-(SSIZE_T)QuotaCharge); 01492 Process->CommitCharge -= QuotaCharge; 01493 } 01494 MiReturnPageFileQuota (QuotaCharge, Process); 01495 ExRaiseStatus STATUS_COMMITMENT_LIMIT; 01496 } 01497 01498 // 01499 // Add the quota into the charge to the VAD. 01500 // 01501 01502 MM_TRACK_COMMIT (MM_DBG_COMMIT_SET_PROTECTION, QuotaCharge); 01503 FoundVad->u.VadFlags.CommitCharge += QuotaCharge; 01504 Process->CommitCharge += QuotaCharge; 01505 if (Process->CommitCharge > Process->CommitChargePeak) { 01506 Process->CommitChargePeak = Process->CommitCharge; 01507 } 01508 } 01509 } 01510 01511 // 01512 // For all the PTEs in the specified address range, set the 01513 // protection depending on the state of the PTE. 01514 // 01515 01516 // 01517 // If the PTE was copy on write (but not written) and the 01518 // new protection is NOT copy-on-write, return page file quota 01519 // and commitment. 01520 // 01521 01522 PointerPpe = MiGetPpeAddress (StartingAddress); 01523 PointerPde = MiGetPdeAddress (StartingAddress); 01524 PointerPte = MiGetPteAddress (StartingAddress); 01525 01526 do { 01527 01528 MiDoesPpeExistAndMakeValid (PointerPpe, Process, FALSE, &Waited); 01529 01530 Waited = 0; 01531 01532 MiDoesPdeExistAndMakeValid (PointerPde, Process, FALSE, &Waited); 01533 01534 } while (Waited != 0); 01535 01536 QuotaCharge = 0; 01537 01538 while (PointerPte <= LastPte) { 01539 01540 if (MiIsPteOnPdeBoundary (PointerPte)) { 01541 PointerPde = MiGetPteAddress (PointerPte); 01542 PointerPpe = MiGetPdeAddress (PointerPte); 01543 01544 #if defined (_WIN64) 01545 MiMakePpeExistAndMakeValid (PointerPpe, Process, FALSE); 01546 if (PointerPde->u.Long == 0) { 01547 UsedPageDirectoryHandle = MI_GET_USED_PTES_HANDLE (PointerPte); 01548 MI_INCREMENT_USED_PTES_BY_HANDLE (UsedPageDirectoryHandle); 01549 } 01550 #endif 01551 01552 MiMakePdeExistAndMakeValid (PointerPde, Process, FALSE); 01553 } 01554 01555 PteContents = *PointerPte; 01556 01557 if (PteContents.u.Long == 0) { 01558 01559 // 01560 // The PTE is zero, set it into prototype PTE format 01561 // with the protection in the prototype PTE. 01562 // 01563 01564 TempPte = PrototypePte; 01565 TempPte.u.Soft.Protection = ProtectionMask; 01566 MI_WRITE_INVALID_PTE (PointerPte, TempPte); 01567 01568 // 01569 // Increment the count of non-zero page table entries 01570 // for this page table and the number of private pages 01571 // for the process. 01572 // 01573 01574 UsedPageTableHandle = MI_GET_USED_PTES_HANDLE (MiGetVirtualAddressMappedByPte (PointerPte)); 01575 01576 MI_INCREMENT_USED_PTES_BY_HANDLE (UsedPageTableHandle); 01577 01578 } else if (PteContents.u.Hard.Valid == 1) { 01579 01580 // 01581 // Set the protection into both the PTE and the original PTE 01582 // in the PFN database for private pages only. 01583 // 01584 01585 NewProtectionMask = ProtectionMask; 01586 01587 Pfn1 = MI_PFN_ELEMENT (PteContents.u.Hard.PageFrameNumber); 01588 01589 if ((NewProtect & PAGE_NOACCESS) || 01590 (NewProtect & PAGE_GUARD)) { 01591 01592 Locked = MiRemovePageFromWorkingSet (PointerPte, 01593 Pfn1, 01594 &Process->Vm ); 01595 continue; 01596 01597 } else { 01598 01599 if (Pfn1->u3.e1.PrototypePte == 1) { 01600 01601 // 01602 // The true protection may be in the WSLE, locate 01603 // the WSLE. 01604 // 01605 01606 Va = (PULONG)MiGetVirtualAddressMappedByPte (PointerPte); 01607 Index = MiLocateWsle ((PVOID)Va, MmWorkingSetList, 01608 Pfn1->u1.WsIndex); 01609 01610 // 01611 // Check to see if this is a prototype PTE. This 01612 // is done by comparing the PTE address in the 01613 // PFN database to the PTE address indicated by the 01614 // VAD. If they are not equal, this is a prototype 01615 // PTE. 01616 // 01617 01618 if (Pfn1->PteAddress != 01619 MiGetProtoPteAddress (FoundVad, 01620 MI_VA_TO_VPN ((PVOID)Va))) { 01621 01622 // 01623 // This PTE refers to a fork prototype PTE, make it 01624 // private. 01625 // 01626 01627 MiCopyOnWrite ((PVOID)Va, PointerPte); 01628 01629 if (WriteCopy) { 01630 QuotaCharge += 1; 01631 } 01632 01633 // 01634 // This may have released the working set mutex and 01635 // the page table page may no longer be in memory. 01636 // 01637 01638 PointerPpe = MiGetPteAddress (PointerPde); 01639 01640 do { 01641 01642 (VOID)MiDoesPpeExistAndMakeValid (PointerPpe, 01643 Process, 01644 FALSE, 01645 &Waited); 01646 01647 Waited = 0; 01648 01649 (VOID)MiDoesPdeExistAndMakeValid (PointerPde, 01650 Process, 01651 FALSE, 01652 &Waited); 01653 01654 } while (Waited != 0); 01655 01656 // 01657 // Do the loop again. 01658 // 01659 01660 continue; 01661 01662 } else { 01663 01664 // 01665 // Update the protection field in the WSLE and 01666 // the PTE. 01667 // 01668 // 01669 // If the PTE is copy on write uncharge the 01670 // previously charged quota. 01671 // 01672 01673 if ((!WriteCopy) && (PteContents.u.Hard.CopyOnWrite == 1)) { 01674 QuotaCharge += 1; 01675 } 01676 01677 MmWsle[Index].u1.e1.Protection = ProtectionMask; 01678 MmWsle[Index].u1.e1.SameProtectAsProto = 0; 01679 } 01680 01681 } else { 01682 01683 // 01684 // Page is private (copy on written), protection mask 01685 // is stored in the original pte field. 01686 // 01687 01688 #if PFN_CONSISTENCY 01689 MiSetOriginalPteProtection (Pfn1, ProtectionMaskNotCopy); 01690 #else 01691 Pfn1->OriginalPte.u.Soft.Protection = ProtectionMaskNotCopy; 01692 #endif 01693 NewProtectionMask = ProtectionMaskNotCopy; 01694 } 01695 01696 MI_MAKE_VALID_PTE (TempPte, 01697 PteContents.u.Hard.PageFrameNumber, 01698 NewProtectionMask, 01699 PointerPte); 01700 01701 WorkingSetIndex = MI_GET_WORKING_SET_FROM_PTE (&PteContents); 01702 01703 MI_SET_PTE_IN_WORKING_SET (&TempPte, WorkingSetIndex); 01704 } 01705 01706 // 01707 // Flush the TB as we have changed the protection 01708 // of a valid PTE. 01709 // 01710 01711 PreviousPte.u.Flush = MiFlushTbAndCapture (PointerPte, 01712 TempPte.u.Flush, 01713 Pfn1); 01714 } else { 01715 01716 if (PteContents.u.Soft.Prototype == 1) { 01717 01718 // 01719 // The PTE is in prototype PTE format. 01720 // 01721 01722 // 01723 // Is it a fork prototype PTE? 01724 // 01725 01726 Va = (PULONG)MiGetVirtualAddressMappedByPte (PointerPte); 01727 01728 if ((PteContents.u.Soft.PageFileHigh != MI_PTE_LOOKUP_NEEDED) && 01729 (MiPteToProto (PointerPte) != 01730 MiGetProtoPteAddress (FoundVad, 01731 MI_VA_TO_VPN ((PVOID)Va)))) { 01732 01733 // 01734 // This PTE refers to a fork prototype PTE, make the 01735 // page private. This is accomplished by releasing 01736 // the working set mutex, reading the page thereby 01737 // causing a fault, and re-executing the loop, hopefully, 01738 // this time, we'll find the page present and will 01739 // turn it into a private page. 01740 // 01741 // Note, that page with prototype = 1 cannot be 01742 // no-access. 01743 // 01744 01745 DoAgain = TRUE; 01746 01747 while (PteContents.u.Hard.Valid == 0) { 01748 01749 UNLOCK_WS_UNSAFE (Process); 01750 01751 try { 01752 01753 *(volatile ULONG *)Va; 01754 } except (EXCEPTION_EXECUTE_HANDLER) { 01755 01756 if (GetExceptionCode() != 01757 STATUS_GUARD_PAGE_VIOLATION) { 01758 01759 // 01760 // The prototype PTE must be noaccess. 01761 // 01762 01763 DoAgain = MiChangeNoAccessForkPte (PointerPte, 01764 ProtectionMask); 01765 } 01766 } 01767 01768 PointerPpe = MiGetPteAddress (PointerPde); 01769 01770 LOCK_WS_UNSAFE (Process); 01771 01772 do { 01773 01774 (VOID)MiDoesPpeExistAndMakeValid (PointerPpe, 01775 Process, 01776 FALSE, 01777 &Waited); 01778 01779 Waited = 0; 01780 01781 (VOID)MiDoesPdeExistAndMakeValid (PointerPde, 01782 Process, 01783 FALSE, 01784 &Waited); 01785 01786 } while (Waited != 0); 01787 01788 PteContents = *(volatile MMPTE *)PointerPte; 01789 } 01790 01791 if (DoAgain) { 01792 continue; 01793 } 01794 01795 } else { 01796 01797 // 01798 // If the new protection is not write-copy, the PTE 01799 // protection is not in the prototype PTE (can't be 01800 // write copy for sections), and the protection in 01801 // the PTE is write-copy, release the page file 01802 // quota and commitment for this page. 01803 // 01804 01805 if ((!WriteCopy) && 01806 (PteContents.u.Soft.PageFileHigh == MI_PTE_LOOKUP_NEEDED)) { 01807 if (MI_IS_PTE_PROTECTION_COPY_WRITE(PteContents.u.Soft.Protection)) { 01808 QuotaCharge += 1; 01809 } 01810 01811 } 01812 01813 // 01814 // The PTE is a prototype PTE. Make the high part 01815 // of the PTE indicate that the protection field 01816 // is in the PTE itself. 01817 // 01818 01819 MI_WRITE_INVALID_PTE (PointerPte, PrototypePte); 01820 PointerPte->u.Soft.Protection = ProtectionMask; 01821 } 01822 01823 } else { 01824 01825 if (PteContents.u.Soft.Transition == 1) { 01826 01827 // 01828 // This is a transition PTE. (Page is private) 01829 // 01830 01831 if (MiSetProtectionOnTransitionPte ( 01832 PointerPte, 01833 ProtectionMaskNotCopy)) { 01834 continue; 01835 } 01836 01837 } else { 01838 01839 // 01840 // Must be page file space or demand zero. 01841 // 01842 01843 PointerPte->u.Soft.Protection = ProtectionMaskNotCopy; 01844 } 01845 } 01846 } 01847 01848 PointerPte += 1; 01849 } 01850 01851 // 01852 // Return the quota charge and the commitment, if any. 01853 // 01854 01855 if ((QuotaCharge > 0) && (!DontCharge)) { 01856 01857 MiReturnCommitment (QuotaCharge); 01858 MM_TRACK_COMMIT (MM_DBG_COMMIT_RETURN_PROTECTION, QuotaCharge); 01859 MiReturnPageFileQuota (QuotaCharge, Process); 01860 01861 ASSERT (QuotaCharge <= FoundVad->u.VadFlags.CommitCharge); 01862 01863 FoundVad->u.VadFlags.CommitCharge -= QuotaCharge; 01864 if (Process->JobStatus & PS_JOB_STATUS_REPORT_COMMIT_CHANGES) { 01865 PsChangeJobMemoryUsage(-(SSIZE_T)QuotaCharge); 01866 } 01867 Process->CommitCharge -= QuotaCharge; 01868 } 01869 01870 return Locked; 01871 }

NTSTATUS MiShareSessionImage IN PSECTION  Section,
IN OUT PSIZE_T  ViewSize
 

Definition at line 119 of file sessload.c.

References ASSERT, BYTES_TO_PAGES, _MM_SESSION_SPACE::CommittedPages, _SEGMENT::ControlArea, ExPageLockHandle, FALSE, _IMAGE_ENTRY_IN_SESSION::LastAddress, LOCK_PFN, LOCK_SESSION_SPACE_WS, MiAddMappedPtes(), MiChargeCommitment(), MiCheckControlArea(), MiCheckPurgeAndUpMapCount(), MiGetPteAddress, MiReturnCommitment(), MiSessionCommitPageTables(), MiSessionLookupImage(), MiSessionWideGetImageSize(), MiSetImageProtect(), MM_BUMP_SESS_COUNTER, MM_BUMP_SESSION_FAILURES, MM_DBG_COMMIT_SESSION_SHARED_IMAGE, MM_DBG_SESSION_SYSMAPPED_PAGES_ALLOC, MM_DBG_SESSION_SYSMAPPED_PAGES_COMMITTED, MM_EXECUTE_READ, MM_SESSION_FAILURE_NO_COMMIT, MM_TRACK_COMMIT, MmIsAddressValid(), MmLockPagableSectionByHandle(), MmSessionSpace, MmUnlockPagableImageSection(), NT_SUCCESS, NTSTATUS(), NULL, _CONTROL_AREA::NumberOfMappedViews, _CONTROL_AREA::NumberOfUserReferences, PAGE_SIZE, PAGED_CODE, _IMAGE_ENTRY_IN_SESSION::PrototypePtes, _CONTROL_AREA::Segment, Status, SYSLOAD_LOCK_OWNED_BY_ME, TRUE, _CONTROL_AREA::u, _MMPTE::u, UNLOCK_PFN, and UNLOCK_SESSION_SPACE_WS.

Referenced by MiLoadImageSection().

00126 : 00127 00128 This routine maps the given image into the current session space. 00129 This allows the image to be executed backed by the image file in the 00130 filesystem and allow code and read-only data to be shared. 00131 00132 Arguments: 00133 00134 Section - Supplies a pointer to a section. 00135 00136 ViewSize - Supplies the size in bytes of the view desired. 00137 00138 Return Value: 00139 00140 Returns STATUS_SUCCESS on success, various NTSTATUS codes on failure. 00141 00142 Environment: 00143 00144 Kernel mode, APC_LEVEL and below, MmSystemLoadLock held. 00145 00146 --*/ 00147 00148 { 00149 KIRQL WsIrql; 00150 KIRQL OldIrql; 00151 PSUBSECTION Subsection; 00152 PCONTROL_AREA ControlArea; 00153 ULONG NumberOfPtes; 00154 PMMPTE StartPte; 00155 PMMPTE EndPte; 00156 PVOID AllocationStart; 00157 SIZE_T AllocationSize; 00158 NTSTATUS Status; 00159 BOOLEAN FirstMapped; 00160 PVOID MappedBase; 00161 SIZE_T CommittedPages; 00162 PIMAGE_ENTRY_IN_SESSION DriverImage; 00163 00164 PAGED_CODE(); 00165 00166 SYSLOAD_LOCK_OWNED_BY_ME (); 00167 00168 if (*ViewSize == 0) { 00169 return STATUS_SUCCESS; 00170 } 00171 00172 ASSERT (MmIsAddressValid (MmSessionSpace) == TRUE); 00173 00174 MappedBase = Section->Segment->BasedAddress; 00175 00176 ASSERT (((ULONG_PTR)MappedBase % PAGE_SIZE) == 0); 00177 ASSERT ((*ViewSize % PAGE_SIZE) == 0); 00178 00179 MmLockPagableSectionByHandle (ExPageLockHandle); 00180 00181 LOCK_SESSION_SPACE_WS (WsIrql); 00182 00183 // 00184 // Check to see if a purge operation is in progress and if so, wait 00185 // for the purge to complete. In addition, up the count of mapped 00186 // views for this control area. 00187 // 00188 00189 ControlArea = Section->Segment->ControlArea; 00190 00191 ASSERT (ControlArea->u.Flags.GlobalOnlyPerSession == 0); 00192 00193 Subsection = (PSUBSECTION)(ControlArea + 1); 00194 00195 if (MiCheckPurgeAndUpMapCount (ControlArea) == FALSE) { 00196 UNLOCK_SESSION_SPACE_WS(WsIrql); 00197 MmUnlockPagableImageSection(ExPageLockHandle); 00198 return STATUS_INSUFFICIENT_RESOURCES; 00199 } 00200 00201 if (*ViewSize == 0) { 00202 00203 *ViewSize = Section->SizeOfSection.LowPart; 00204 00205 } 00206 else if (*ViewSize > Section->SizeOfSection.LowPart) { 00207 00208 // 00209 // Section offset or view size past size of section. 00210 // 00211 00212 UNLOCK_SESSION_SPACE_WS(WsIrql); 00213 LOCK_PFN (OldIrql); 00214 ControlArea->NumberOfMappedViews -= 1; 00215 ControlArea->NumberOfUserReferences -= 1; 00216 00217 // 00218 // Check to see if the control area (segment) should be deleted. 00219 // This routine releases the PFN lock. 00220 // 00221 00222 MiCheckControlArea (ControlArea, NULL, OldIrql); 00223 00224 MmUnlockPagableImageSection(ExPageLockHandle); 00225 return STATUS_INVALID_VIEW_SIZE; 00226 } 00227 00228 AllocationStart = MappedBase; 00229 00230 AllocationSize = *ViewSize; 00231 00232 // 00233 // Calculate the PTE ranges and amount. 00234 // 00235 00236 StartPte = MiGetPteAddress (AllocationStart); 00237 00238 EndPte = MiGetPteAddress ((PCHAR)AllocationStart + AllocationSize); 00239 00240 NumberOfPtes = BYTES_TO_PAGES (AllocationSize); 00241 00242 Status = MiSessionWideGetImageSize (MappedBase, 00243 NULL, 00244 &CommittedPages); 00245 00246 if (!NT_SUCCESS(Status)) { 00247 CommittedPages = NumberOfPtes; 00248 } 00249 00250 Status = STATUS_SUCCESS; 00251 00252 if (MiChargeCommitment (CommittedPages, NULL) == FALSE) { 00253 MM_BUMP_SESSION_FAILURES (MM_SESSION_FAILURE_NO_COMMIT); 00254 Status = STATUS_NO_MEMORY; 00255 } 00256 00257 if (!NT_SUCCESS(Status)) { 00258 00259 // 00260 // Don't bother releasing the page tables or their commit here, another 00261 // load will happen shortly or the whole session will go away. On 00262 // session exit everything will be released automatically. 00263 // 00264 00265 UNLOCK_SESSION_SPACE_WS(WsIrql); 00266 00267 LOCK_PFN (OldIrql); 00268 ControlArea->NumberOfMappedViews -= 1; 00269 ControlArea->NumberOfUserReferences -= 1; 00270 00271 // 00272 // Check to see if the control area (segment) should be deleted. 00273 // This routine releases the PFN lock. 00274 // 00275 00276 MiCheckControlArea (ControlArea, NULL, OldIrql); 00277 00278 MmUnlockPagableImageSection(ExPageLockHandle); 00279 return STATUS_NO_MEMORY; 00280 } 00281 00282 MmSessionSpace->CommittedPages += CommittedPages; 00283 00284 // 00285 // Make sure we have page tables for the PTE 00286 // entries we must fill in the session space structure. 00287 // 00288 00289 Status = MiSessionCommitPageTables (AllocationStart, 00290 (PVOID)((PCHAR)AllocationStart + AllocationSize)); 00291 00292 if (!NT_SUCCESS(Status)) { 00293 00294 MmSessionSpace->CommittedPages -= CommittedPages; 00295 UNLOCK_SESSION_SPACE_WS (WsIrql); 00296 00297 LOCK_PFN (OldIrql); 00298 ControlArea->NumberOfMappedViews -= 1; 00299 ControlArea->NumberOfUserReferences -= 1; 00300 00301 // 00302 // Check to see if the control area (segment) should be deleted. 00303 // This routine releases the PFN lock. 00304 // 00305 00306 MiCheckControlArea (ControlArea, NULL, OldIrql); 00307 00308 MmUnlockPagableImageSection (ExPageLockHandle); 00309 MiReturnCommitment (CommittedPages); 00310 00311 return STATUS_NO_MEMORY; 00312 } 00313 00314 MM_TRACK_COMMIT (MM_DBG_COMMIT_SESSION_SHARED_IMAGE, CommittedPages); 00315 00316 MM_BUMP_SESS_COUNTER (MM_DBG_SESSION_SYSMAPPED_PAGES_COMMITTED, CommittedPages); 00317 00318 MM_BUMP_SESS_COUNTER (MM_DBG_SESSION_SYSMAPPED_PAGES_ALLOC, NumberOfPtes); 00319 00320 #if DBG 00321 while (StartPte < EndPte) { 00322 ASSERT (StartPte->u.Long == 0); 00323 StartPte += 1; 00324 } 00325 StartPte = MiGetPteAddress (AllocationStart); 00326 #endif 00327 00328 // 00329 // Flag that the image is mapped into system space. 00330 // 00331 00332 if (Section->u.Flags.Image) { 00333 00334 FirstMapped = FALSE; 00335 00336 LOCK_PFN (OldIrql); 00337 if (ControlArea->u.Flags.ImageMappedInSystemSpace == 0) { 00338 FirstMapped = TRUE; 00339 ControlArea->u.Flags.ImageMappedInSystemSpace = 1; 00340 } 00341 UNLOCK_PFN (OldIrql); 00342 00343 // 00344 // Initialize all of the pages to copy on write - later read only 00345 // protections will be set on the code pages. 00346 // 00347 00348 if (FirstMapped == TRUE) { 00349 MiSetImageProtect (Section->Segment, MM_EXECUTE_READ); 00350 } 00351 } 00352 00353 // 00354 // Initialize the PTEs as copy on write, pointing at the prototype PTEs. 00355 // 00356 00357 MiAddMappedPtes (StartPte, 00358 NumberOfPtes, 00359 ControlArea); 00360 00361 UNLOCK_SESSION_SPACE_WS(WsIrql); 00362 00363 // 00364 // No session space image faults may be taken until these fields of the 00365 // image entry are initialized. 00366 // 00367 00368 DriverImage = MiSessionLookupImage (AllocationStart); 00369 ASSERT (DriverImage); 00370 00371 DriverImage->LastAddress = (PVOID)((PCHAR)AllocationStart + AllocationSize - 1); 00372 DriverImage->PrototypePtes = Section->Segment->PrototypePte; 00373 00374 MmUnlockPagableImageSection(ExPageLockHandle); 00375 00376 return STATUS_SUCCESS; 00377 }

LONGLONG MiStartingOffset IN PSUBSECTION  Subsection,
IN PMMPTE  PteAddress
 

Definition at line 916 of file flushsec.c.

References Mi4KStartFromSubsection, MI_STARTING_OFFSET, MM4K_SHIFT, and PAGE_SHIFT.

Referenced by MiCleanSection(), MiFlushSectionInternal(), MiGatherMappedPages(), MiResolveMappedFileFault(), and MmShutdownSystem().

00923 : 00924 00925 This function calculates the file offset given a subsection and a PTE 00926 offset. Note that images are stored in 512-byte units whereas data is 00927 stored in 4K units. 00928 00929 When this is all debugged, this should be made into a macro. 00930 00931 Arguments: 00932 00933 Subsection - Supplies a subsection to reference for the file address. 00934 00935 PteAddress - Supplies a PTE within the subsection 00936 00937 Return Value: 00938 00939 Returns the file offset to obtain the backing data from. 00940 00941 --*/ 00942 00943 { 00944 LONGLONG PteByteOffset; 00945 LARGE_INTEGER StartAddress; 00946 00947 if (Subsection->ControlArea->u.Flags.Image == 1) { 00948 return MI_STARTING_OFFSET ( Subsection, 00949 PteAddress); 00950 } 00951 00952 PteByteOffset = (LONGLONG)((PteAddress - Subsection->SubsectionBase)) 00953 << PAGE_SHIFT; 00954 00955 Mi4KStartFromSubsection (&StartAddress, Subsection); 00956 00957 StartAddress.QuadPart = StartAddress.QuadPart << MM4K_SHIFT; 00958 00959 PteByteOffset += StartAddress.QuadPart; 00960 00961 return PteByteOffset; 00962 }

VOID MiSwapWslEntries IN WSLE_NUMBER  SwapEntry,
IN WSLE_NUMBER  Entry,
IN PMMSUPPORT  WsInfo
 

Definition at line 576 of file wstree.c.

References ASSERT, _MMWSL::FirstFree, _MMWSL::HashTable, _MMWSLE_HASH::Index, _MMWSL::LastInitializedWsle, LOCK_PFN, MI_PFN_ELEMENT, MI_SET_PTE_IN_WORKING_SET, MiGetPteAddress, MiLookupWsleHashIndex(), MiRemoveWsleFromFreeList(), MM_FREE_WSLE_SHIFT, _MMPTE::u, _MMWSLE::u1, _MMPFN::u1, UNLOCK_PFN, _MMWSL::Wsle, WSLE_NULL_INDEX, and WSLE_NUMBER.

Referenced by MiAddWorkingSetPage(), MiAddWsleHash(), MiAllocatePoolPages(), MiDecommitPages(), MiDeleteAddressesInWorkingSet(), MiDeletePte(), MiDeleteSystemPagableVm(), MiLockCode(), MiRemovePageFromWorkingSet(), MiSessionCommitPageTables(), MiUpdateWsle(), NtLockVirtualMemory(), and NtUnlockVirtualMemory().

00584 : 00585 00586 This routine swaps the working set list entries Entry and SwapEntry 00587 in the specified working set list (process or system cache). 00588 00589 Arguments: 00590 00591 SwapEntry - Supplies the first entry to swap. This entry must be 00592 valid, i.e. in the working set at the current time. 00593 00594 Entry - Supplies the other entry to swap. This entry may be valid 00595 or invalid. 00596 00597 WsInfo - Supplies the working set list. 00598 00599 Return Value: 00600 00601 None. 00602 00603 Environment: 00604 00605 Kernel mode, Working set lock and PFN lock held (if system cache), 00606 APCs disabled. 00607 00608 --*/ 00609 00610 { 00611 MMWSLE WsleEntry; 00612 MMWSLE WsleSwap; 00613 PMMPTE PointerPte; 00614 PMMPFN Pfn1; 00615 PMMWSLE Wsle; 00616 PMMWSL WorkingSetList; 00617 PMMWSLE_HASH Table; 00618 #if DBG 00619 WSLE_NUMBER CurrentSize = WsInfo->WorkingSetSize; 00620 #endif //DBG 00621 #if PFN_CONSISTENCY 00622 KIRQL OldIrql; 00623 #endif 00624 00625 WorkingSetList = WsInfo->VmWorkingSetList; 00626 Wsle = WorkingSetList->Wsle; 00627 00628 WsleSwap = Wsle[SwapEntry]; 00629 00630 ASSERT (WsleSwap.u1.e1.Valid != 0); 00631 00632 WsleEntry = Wsle[Entry]; 00633 00634 Table = WorkingSetList->HashTable; 00635 00636 if (WsleEntry.u1.e1.Valid == 0) { 00637 00638 // 00639 // Entry is not on any list. Remove it from the free list. 00640 // 00641 00642 MiRemoveWsleFromFreeList (Entry, Wsle, WorkingSetList); 00643 00644 // 00645 // Copy the Entry to this free one. 00646 // 00647 00648 Wsle[Entry] = WsleSwap; 00649 00650 PointerPte = MiGetPteAddress (WsleSwap.u1.VirtualAddress); 00651 00652 if (WsleSwap.u1.e1.Direct) { 00653 Pfn1 = MI_PFN_ELEMENT (PointerPte->u.Hard.PageFrameNumber); 00654 #if PFN_CONSISTENCY 00655 OldIrql = 99; 00656 if (PFN_LOCK_OWNED_BY_ME() == 0) { 00657 LOCK_PFN (OldIrql); 00658 } 00659 #endif 00660 Pfn1->u1.WsIndex = Entry; 00661 #if PFN_CONSISTENCY 00662 if (OldIrql != 99) { 00663 UNLOCK_PFN (OldIrql); 00664 } 00665 #endif 00666 } else { 00667 00668 // 00669 // Update hash table. 00670 // 00671 00672 if (Table) { 00673 Table [ MiLookupWsleHashIndex (WsleSwap.u1.Long, 00674 WorkingSetList)].Index = Entry; 00675 } 00676 } 00677 00678 MI_SET_PTE_IN_WORKING_SET (PointerPte, Entry); 00679 00680 // 00681 // Put entry on free list. 00682 // 00683 00684 ASSERT (WorkingSetList->FirstFree <= WorkingSetList->LastInitializedWsle); 00685 Wsle[SwapEntry].u1.Long = WorkingSetList->FirstFree << MM_FREE_WSLE_SHIFT; 00686 WorkingSetList->FirstFree = SwapEntry; 00687 ASSERT ((WorkingSetList->FirstFree <= WorkingSetList->LastInitializedWsle) || 00688 (WorkingSetList->FirstFree == WSLE_NULL_INDEX)); 00689 00690 } else { 00691 00692 // 00693 // Both entries are valid. 00694 // 00695 00696 Wsle[SwapEntry] = WsleEntry; 00697 00698 PointerPte = MiGetPteAddress (WsleEntry.u1.VirtualAddress); 00699 00700 if (WsleEntry.u1.e1.Direct) { 00701 00702 // 00703 // Swap the PFN WsIndex element to point to the new slot. 00704 // 00705 00706 Pfn1 = MI_PFN_ELEMENT (PointerPte->u.Hard.PageFrameNumber); 00707 #if PFN_CONSISTENCY 00708 OldIrql = 99; 00709 if (PFN_LOCK_OWNED_BY_ME() == 0) { 00710 LOCK_PFN (OldIrql); 00711 } 00712 #endif 00713 Pfn1->u1.WsIndex = SwapEntry; 00714 #if PFN_CONSISTENCY 00715 if (OldIrql != 99) { 00716 UNLOCK_PFN (OldIrql); 00717 } 00718 #endif 00719 } else { 00720 00721 // 00722 // Update hash table. 00723 // 00724 00725 if (Table) { 00726 Table[ MiLookupWsleHashIndex (WsleEntry.u1.Long, 00727 WorkingSetList)].Index = SwapEntry; 00728 } 00729 } 00730 00731 MI_SET_PTE_IN_WORKING_SET (PointerPte, SwapEntry); 00732 00733 Wsle[Entry] = WsleSwap; 00734 00735 PointerPte = MiGetPteAddress (WsleSwap.u1.VirtualAddress); 00736 00737 if (WsleSwap.u1.e1.Direct) { 00738 00739 Pfn1 = MI_PFN_ELEMENT (PointerPte->u.Hard.PageFrameNumber); 00740 #if PFN_CONSISTENCY 00741 OldIrql = 99; 00742 if (PFN_LOCK_OWNED_BY_ME() == 0) { 00743 LOCK_PFN (OldIrql); 00744 } 00745 #endif 00746 Pfn1->u1.WsIndex = Entry; 00747 #if PFN_CONSISTENCY 00748 if (OldIrql != 99) { 00749 UNLOCK_PFN (OldIrql); 00750 } 00751 #endif 00752 } else { 00753 if (Table) { 00754 Table[ MiLookupWsleHashIndex (WsleSwap.u1.Long, 00755 WorkingSetList)].Index = Entry; 00756 } 00757 } 00758 MI_SET_PTE_IN_WORKING_SET (PointerPte, Entry); 00759 } 00760 ASSERT (CurrentSize == WsInfo->WorkingSetSize); 00761 return; 00762 }

VOID MiTakePageFromWorkingSet IN ULONG  Entry,
IN PMMSUPPORT  WsInfo,
IN PMMPTE  PointerPte
 

LOGICAL MiTriageAddDrivers IN PLOADER_PARAMETER_BLOCK  LoaderBlock  ) 
 

Referenced by MiInitializeDriverVerifierList().

LOGICAL MiTriageSystem IN PLOADER_PARAMETER_BLOCK  LoaderBlock  ) 
 

Referenced by MmInitSystem().

LOGICAL MiTriageVerifyDriver IN PLDR_DATA_TABLE_ENTRY  DataTableEntry  ) 
 

ULONG MiTrimWorkingSet ULONG  Reduction,
IN PMMSUPPORT  WsInfo,
IN ULONG  ForcedReduction
 

Definition at line 3612 of file wslist.c.

References FALSE, _MMWSL::FirstDynamic, _MMWSL::LastEntry, MI_GET_ACCESSED_IN_PTE, MI_GET_WSLE_AGE, MI_SET_ACCESSED_IN_PTE, MiFreeWsle(), MiGetPteAddress, MiRemoveWorkingSetPages(), MM_SYSTEM_WS_LOCK_ASSERT, MmSystemCacheWs, _MMWSL::NextSlot, PAGE_SIZE, PERFINFO_GET_PAGE_INFO_WITH_DECL, PERFINFO_LOG_WS_REMOVAL, _MMWSL::Quota, TRUE, _MMSUPPORT::u, _MMWSLE::u1, _MMWSLE::VirtualAddress, and _MMWSL::Wsle.

Referenced by MiDoReplacement(), MmSetMemoryPriorityProcess(), and MmWorkingSetManager().

03620 : 03621 03622 This function reduces the working set by the specified amount. 03623 03624 Arguments: 03625 03626 Reduction - Supplies the number of pages to remove from the working 03627 set. 03628 03629 WsInfo - Supplies a pointer to the working set information for the 03630 process (or system cache) to trim. 03631 03632 ForcedReductionOrTrimAge - If using fault-based trimming, this is set to 03633 TRUE if the reduction is being done to free up 03634 pages in which case we should try to reduce 03635 working set pages as well. Set to FALSE when 03636 the reduction is trying to increase the fault 03637 rates in which case the policy should be more 03638 like locate and reserve. 03639 03640 If using claim-based trimming, this is the age 03641 value to use - ie: pages of this age or older 03642 will be removed. 03643 03644 Return Value: 03645 03646 Returns the actual number of pages removed. 03647 03648 Environment: 03649 03650 Kernel mode, APCs disabled, working set lock. PFN lock NOT held. 03651 03652 --*/ 03653 03654 { 03655 ULONG TryToFree; 03656 ULONG StartEntry; 03657 ULONG LastEntry; 03658 PMMWSL WorkingSetList; 03659 PMMWSLE Wsle; 03660 PMMPTE PointerPte; 03661 ULONG NumberLeftToRemove; 03662 ULONG LoopCount; 03663 ULONG EndCount; 03664 BOOLEAN StartFromZero; 03665 03666 NumberLeftToRemove = Reduction; 03667 WorkingSetList = WsInfo->VmWorkingSetList; 03668 Wsle = WorkingSetList->Wsle; 03669 03670 #if DBG 03671 if (WsInfo == &MmSystemCacheWs) { 03672 MM_SYSTEM_WS_LOCK_ASSERT(); 03673 } 03674 #endif //DBG 03675 03676 LastEntry = WorkingSetList->LastEntry; 03677 03678 TryToFree = WorkingSetList->NextSlot; 03679 if (TryToFree > LastEntry || TryToFree < WorkingSetList->FirstDynamic) { 03680 TryToFree = WorkingSetList->FirstDynamic; 03681 } 03682 03683 StartEntry = TryToFree; 03684 03685 #ifdef _MI_USE_CLAIMS_ 03686 03687 while (NumberLeftToRemove != 0) { 03688 if (Wsle[TryToFree].u1.e1.Valid == 1) { 03689 PointerPte = MiGetPteAddress (Wsle[TryToFree].u1.VirtualAddress); 03690 03691 if ((ForcedReductionOrTrimAge == 0) || 03692 ((MI_GET_ACCESSED_IN_PTE (PointerPte) == 0) && 03693 (MI_GET_WSLE_AGE(PointerPte, &Wsle[TryToFree]) >= ForcedReductionOrTrimAge))) { 03694 03695 PERFINFO_GET_PAGE_INFO_WITH_DECL(PointerPte); 03696 03697 if (MiFreeWsle (TryToFree, WsInfo, PointerPte)) { 03698 PERFINFO_LOG_WS_REMOVAL(PERFINFO_LOG_TYPE_OUTWS_VOLUNTRIM, WsInfo); 03699 NumberLeftToRemove -= 1; 03700 } 03701 } 03702 } 03703 TryToFree += 1; 03704 03705 if (TryToFree > LastEntry) { 03706 TryToFree = WorkingSetList->FirstDynamic; 03707 } 03708 03709 if (TryToFree == StartEntry) { 03710 break; 03711 } 03712 } 03713 03714 #else 03715 03716 LoopCount = 0; 03717 03718 if (ForcedReductionOrTrimAge) { 03719 EndCount = 4; 03720 } else { 03721 EndCount = 1; 03722 } 03723 03724 StartFromZero = FALSE; 03725 03726 while (NumberLeftToRemove != 0 && LoopCount != EndCount) { 03727 while ((NumberLeftToRemove != 0) && (TryToFree <= LastEntry)) { 03728 03729 if (Wsle[TryToFree].u1.e1.Valid == 1) { 03730 PointerPte = MiGetPteAddress (Wsle[TryToFree].u1.VirtualAddress); 03731 if (MI_GET_ACCESSED_IN_PTE (PointerPte)) { 03732 03733 // 03734 // If accessed bit is set, clear it. If accessed 03735 // bit is clear, remove from working set. 03736 // 03737 03738 MI_SET_ACCESSED_IN_PTE (PointerPte, 0); 03739 } else { 03740 PERFINFO_GET_PAGE_INFO_WITH_DECL(PointerPte); 03741 if (MiFreeWsle (TryToFree, WsInfo, PointerPte)) { 03742 PERFINFO_LOG_WS_REMOVAL(PERFINFO_LOG_TYPE_OUTWS_VOLUNTRIM, WsInfo); 03743 NumberLeftToRemove -= 1; 03744 } 03745 } 03746 } 03747 TryToFree += 1; 03748 03749 if (StartFromZero == TRUE && EndCount == 1 && TryToFree >= StartEntry) { 03750 LoopCount = EndCount; 03751 if (TryToFree > LastEntry) { 03752 TryToFree = WorkingSetList->FirstDynamic; 03753 } 03754 break; 03755 } 03756 } 03757 03758 if (TryToFree > LastEntry) { 03759 TryToFree = WorkingSetList->FirstDynamic; 03760 if (StartFromZero == TRUE) { 03761 03762 // 03763 // We've already wrapped once but didn't get back to 03764 // the StartEntry. Use the first dynamic as our base now. 03765 // 03766 03767 StartEntry = TryToFree; 03768 } 03769 else { 03770 StartFromZero = TRUE; 03771 } 03772 03773 if (TryToFree >= StartEntry) { 03774 03775 // 03776 // We've wrapped. If this is not a forced trim, then bail 03777 // now so we don't cannibalize entries we just cleared the 03778 // access bit for because they haven't had a fair chance to 03779 // be re-accessed yet. 03780 // 03781 03782 LoopCount += 1; 03783 StartFromZero = FALSE; 03784 } 03785 } 03786 } 03787 03788 #endif 03789 03790 WorkingSetList->NextSlot = TryToFree; 03791 03792 // 03793 // If this is not the system cache or a session working set, see if the 03794 // working set list can be contracted. 03795 // 03796 03797 if (WsInfo != &MmSystemCacheWs && WsInfo->u.Flags.SessionSpace == 0) { 03798 03799 // 03800 // Make sure we are at least a page above the working set maximum. 03801 // 03802 03803 if (WorkingSetList->FirstDynamic == WsInfo->WorkingSetSize) { 03804 MiRemoveWorkingSetPages (WorkingSetList, WsInfo); 03805 } else { 03806 03807 if ((WorkingSetList->Quota + 15 + (PAGE_SIZE / sizeof(MMWSLE))) < 03808 WorkingSetList->LastEntry) { 03809 if ((WsInfo->MaximumWorkingSetSize + 15 + (PAGE_SIZE / sizeof(MMWSLE))) < 03810 WorkingSetList->LastEntry ) { 03811 MiRemoveWorkingSetPages (WorkingSetList, WsInfo); 03812 } 03813 } 03814 } 03815 } 03816 return Reduction - NumberLeftToRemove; 03817 }

VOID MiUnlinkFreeOrZeroedPage IN PFN_NUMBER  Page  ) 
 

Definition at line 821 of file pfnlist.c.

References ASSERT, _MMPFNLIST::Blink, _MMCOLOR_TABLES::Blink, _MMPFNLIST::Flink, _MMCOLOR_TABLES::Flink, FreePageList, _MMPFNLIST::ListName, MI_GET_COLOR_FROM_SECONDARY, MI_GET_SECONDARY_COLOR, MI_PFN_ELEMENT, MiObtainFreePages(), MM_EMPTY_LIST, MM_PFN_LOCK_ASSERT, MmAvailablePages, MmFreePagesByColor, MmMinimumFreePages, MmPageLocationList, MmPfnDatabase, _MMPFN::OriginalPte, PERFINFO_UNLINKFREEPAGE, _MMPFNLIST::Total, _MMPTE::u, _MMPFN::u1, _MMPFN::u2, and _MMPFN::u3.

Referenced by MiFindContiguousMemory(), MiInitMachineDependent(), MiRemovePhysicalPages(), and MmAllocatePagesForMdl().

00827 : 00828 00829 This procedure removes a page from the middle of a list. This is 00830 designed for the removing of free or zeroed pages from the middle of 00831 their lists. 00832 00833 Arguments: 00834 00835 Pfn - Supplies a pointer to the PFN database element for the physical 00836 page to remove from the list. 00837 00838 Return Value: 00839 00840 None. 00841 00842 Environment: 00843 00844 Must be holding the PFN database mutex with APCs disabled. 00845 00846 --*/ 00847 00848 { 00849 PMMPFNLIST ListHead; 00850 PFN_NUMBER Previous; 00851 PFN_NUMBER Next; 00852 PMMPFN Pfn2; 00853 PMMPFN Pfn; 00854 ULONG Color; 00855 00856 Pfn = MI_PFN_ELEMENT (Page); 00857 00858 MM_PFN_LOCK_ASSERT(); 00859 00860 ListHead = MmPageLocationList[Pfn->u3.e1.PageLocation]; 00861 ASSERT (ListHead->Total != 0); 00862 ListHead->Total -= 1; 00863 00864 ASSERT (ListHead->ListName <= FreePageList); 00865 ASSERT (Pfn->u3.e1.WriteInProgress == 0); 00866 ASSERT (Pfn->u3.e1.ReadInProgress == 0); 00867 00868 PERFINFO_UNLINKFREEPAGE((ULONG_PTR)(Pfn - MmPfnDatabase), Pfn->u3.e1.PageLocation); 00869 00870 Next = Pfn->u1.Flink; 00871 Pfn->u1.Flink = 0; // Assumes Flink width is >= WsIndex width 00872 Previous = Pfn->u2.Blink; 00873 Pfn->u2.Blink = 0; 00874 00875 if (Next == MM_EMPTY_LIST) { 00876 ListHead->Blink = Previous; 00877 } else { 00878 Pfn2 = MI_PFN_ELEMENT(Next); 00879 Pfn2->u2.Blink = Previous; 00880 } 00881 00882 if (Previous == MM_EMPTY_LIST) { 00883 ListHead->Flink = Next; 00884 } else { 00885 Pfn2 = MI_PFN_ELEMENT(Previous); 00886 Pfn2->u1.Flink = Next; 00887 } 00888 00889 // 00890 // We are removing a page from the middle of the free or zeroed page list. 00891 // The secondary color tables must be updated at this time. 00892 // 00893 00894 Color = MI_GET_SECONDARY_COLOR (Page, Pfn); 00895 ASSERT (Pfn->u3.e1.PageColor == MI_GET_COLOR_FROM_SECONDARY(Color)); 00896 00897 // 00898 // Walk down the list and remove the page. 00899 // 00900 00901 Next = MmFreePagesByColor[ListHead->ListName][Color].Flink; 00902 if (Next == Page) { 00903 MmFreePagesByColor[ListHead->ListName][Color].Flink = 00904 (PFN_NUMBER) Pfn->OriginalPte.u.Long; 00905 } else { 00906 00907 // 00908 // Walk the list to find the parent. 00909 // 00910 00911 for (; ; ) { 00912 Pfn2 = MI_PFN_ELEMENT (Next); 00913 Next = (PFN_NUMBER) Pfn2->OriginalPte.u.Long; 00914 if (Page == Next) { 00915 Pfn2->OriginalPte.u.Long = Pfn->OriginalPte.u.Long; 00916 if ((PFN_NUMBER) Pfn->OriginalPte.u.Long == MM_EMPTY_LIST) { 00917 MmFreePagesByColor[ListHead->ListName][Color].Blink = Pfn2; 00918 } 00919 break; 00920 } 00921 } 00922 } 00923 00924 MmAvailablePages -= 1; 00925 00926 if (MmAvailablePages < MmMinimumFreePages) { 00927 00928 // 00929 // Obtain free pages. 00930 // 00931 00932 MiObtainFreePages(); 00933 } 00934 00935 return; 00936 }

VOID FASTCALL MiUnlinkPageFromList IN PMMPFN  Pfn  ) 
 

Definition at line 667 of file pfnlist.c.

References ASSERT, _MMPFNLIST::Blink, DbgPrint, _MMPFNLIST::Flink, KeBugCheckEx(), _MMPFNLIST::ListName, MI_PFN_ELEMENT, MI_TALLY_TRANSITION_PAGE_REMOVAL, MiFormatPfn(), MiObtainFreePages(), MM_DBG_PAGE_IN_LIST, MM_EMPTY_LIST, MM_PFN_LOCK_ASSERT, MmAvailablePages, MmHighestPhysicalPage, MmMinimumFreePages, MmModifiedPageListByColor, MmModifiedPageListHead, MmPageLocationList, MmPfnDatabase, MmTotalPagesForPagingFile, ModifiedNoWritePageList, ModifiedPageList, PERFINFO_UNLINKPAGE, StandbyPageList, _MMPFNLIST::Total, _MMPFN::u1, and _MMPFN::u2.

Referenced by MiCleanSection(), MiDecommitPages(), MiDecrementCloneBlockReference(), MiDeletePte(), MiDeleteSystemPagableVm(), MiDispatchFault(), MiFindContiguousMemory(), MiFlushSectionInternal(), MiGatherMappedPages(), MiGatherPagefilePages(), MiLockCode(), MiMakeOutswappedPageResident(), MiModifiedPageWriterWorker(), MiPurgeImageSection(), MiRemovePhysicalPages(), MiResetVirtualMemory(), MiResolveTransitionFault(), MiSegmentDelete(), MmAllocatePagesForMdl(), MmCheckCachedPageState(), MmCopyToCachedPage(), MmPurgeSection(), MmRemovePhysicalMemory(), and MmShutdownSystem().

00673 : 00674 00675 This procedure removes a page from the middle of a list. This is 00676 designed for the faulting of transition pages from the standby and 00677 modified list and making them active and valid again. 00678 00679 Arguments: 00680 00681 Pfn - Supplies a pointer to the PFN database element for the physical 00682 page to remove from the list. 00683 00684 Return Value: 00685 00686 none. 00687 00688 Environment: 00689 00690 Must be holding the PFN database mutex with APCs disabled. 00691 00692 --*/ 00693 00694 { 00695 PMMPFNLIST ListHead; 00696 PFN_NUMBER Previous; 00697 PFN_NUMBER Next; 00698 PMMPFN Pfn2; 00699 00700 MM_PFN_LOCK_ASSERT(); 00701 00702 PERFINFO_UNLINKPAGE((ULONG_PTR)(Pfn - MmPfnDatabase), Pfn->u3.e1.PageLocation); 00703 00704 // 00705 // Page not on standby or modified list, check to see if the 00706 // page is currently being written by the modified page 00707 // writer, if so, just return this page. The reference 00708 // count for the page will be incremented, so when the modified 00709 // page write completes, the page will not be put back on 00710 // the list, rather, it will remain active and valid. 00711 // 00712 00713 if (Pfn->u3.e2.ReferenceCount > 0) { 00714 00715 // 00716 // The page was not on any "transition lists", check to see 00717 // if this has I/O in progress. 00718 // 00719 00720 if (Pfn->u2.ShareCount == 0) { 00721 #if DBG 00722 if (MmDebug & MM_DBG_PAGE_IN_LIST) { 00723 DbgPrint("unlinking page not in list...\n"); 00724 MiFormatPfn(Pfn); 00725 } 00726 #endif 00727 return; 00728 } 00729 KdPrint(("MM:attempt to remove page from wrong page list\n")); 00730 KeBugCheckEx (PFN_LIST_CORRUPT, 00731 2, 00732 Pfn - MmPfnDatabase, 00733 MmHighestPhysicalPage, 00734 Pfn->u3.e2.ReferenceCount); 00735 return; 00736 } 00737 00738 ListHead = MmPageLocationList[Pfn->u3.e1.PageLocation]; 00739 00740 // 00741 // Must not remove pages from free or zeroed without updating 00742 // the colored lists. 00743 // 00744 00745 ASSERT (ListHead->ListName >= StandbyPageList); 00746 00747 // 00748 // On MIPS R4000 modified pages destined for the paging file are 00749 // kept on separate lists which group pages of the same color 00750 // together 00751 // 00752 00753 if ((ListHead == &MmModifiedPageListHead) && 00754 (Pfn->OriginalPte.u.Soft.Prototype == 0)) { 00755 00756 // 00757 // This page is destined for the paging file (not 00758 // a mapped file). Change the list head to the 00759 // appropriate colored list head. 00760 // 00761 00762 ListHead->Total -= 1; 00763 MmTotalPagesForPagingFile -= 1; 00764 ListHead = &MmModifiedPageListByColor [Pfn->u3.e1.PageColor]; 00765 } 00766 00767 ASSERT (Pfn->u3.e1.WriteInProgress == 0); 00768 ASSERT (Pfn->u3.e1.ReadInProgress == 0); 00769 ASSERT (ListHead->Total != 0); 00770 00771 Next = Pfn->u1.Flink; 00772 Pfn->u1.Flink = 0; // Assumes Flink width is >= WsIndex width 00773 Previous = Pfn->u2.Blink; 00774 Pfn->u2.Blink = 0; 00775 00776 if (Next == MM_EMPTY_LIST) { 00777 ListHead->Blink = Previous; 00778 } else { 00779 Pfn2 = MI_PFN_ELEMENT(Next); 00780 Pfn2->u2.Blink = Previous; 00781 } 00782 00783 if (Previous == MM_EMPTY_LIST) { 00784 ListHead->Flink = Next; 00785 } else { 00786 Pfn2 = MI_PFN_ELEMENT(Previous); 00787 Pfn2->u1.Flink = Next; 00788 } 00789 00790 ListHead->Total -= 1; 00791 00792 // 00793 // Check to see if we now have one less page available. 00794 // 00795 00796 if (ListHead->ListName <= StandbyPageList) { 00797 MmAvailablePages -= 1; 00798 00799 if (ListHead->ListName == StandbyPageList) { 00800 MI_TALLY_TRANSITION_PAGE_REMOVAL (Pfn); 00801 } 00802 00803 if (MmAvailablePages < MmMinimumFreePages) { 00804 00805 // 00806 // Obtain free pages. 00807 // 00808 00809 MiObtainFreePages(); 00810 00811 } 00812 } 00813 else if (ListHead->ListName == ModifiedPageList || ListHead->ListName == ModifiedNoWritePageList) { 00814 MI_TALLY_TRANSITION_PAGE_REMOVAL (Pfn); 00815 } 00816 00817 return; 00818 }

NTSTATUS MiUnloadSessionImageByForce IN SIZE_T  NumberOfPtes,
IN PVOID  ImageBase
 

VOID FASTCALL MiUnlockPagedAddress IN PVOID  VirtualAddress,
IN ULONG  PfnLockHeld
 

Definition at line 1123 of file mmsup.c.

References ASSERT, FALSE, LOCK_PFN2, MI_GET_PAGE_FRAME_FROM_PTE, MI_PFN_ELEMENT, MI_REMOVE_LOCKED_PAGE_CHARGE, MiDecrementReferenceCount(), MiGetPteAddress, _MMPTE::u, _MMPFN::u3, and UNLOCK_PFN2.

Referenced by MiCloneProcessAddressSpace().

01130 : 01131 01132 This routine checks to see if the virtual address is valid, and if 01133 not makes it valid. 01134 01135 Arguments: 01136 01137 VirtualAddress - Supplies the virtual address to make valid. 01138 01139 01140 Return Value: 01141 01142 None. 01143 01144 Environment: 01145 01146 Kernel mode. PFN LOCK MUST NOT BE HELD. 01147 01148 --*/ 01149 01150 { 01151 PMMPFN Pfn1; 01152 PMMPTE PointerPte; 01153 KIRQL OldIrql; 01154 PFN_NUMBER PageFrameIndex; 01155 01156 PointerPte = MiGetPteAddress(VirtualAddress); 01157 01158 // 01159 // Address must be within paged pool. 01160 // 01161 01162 if (PfnLockHeld == FALSE) { 01163 LOCK_PFN2 (OldIrql); 01164 } 01165 01166 ASSERT (PointerPte->u.Hard.Valid == 1); 01167 PageFrameIndex = MI_GET_PAGE_FRAME_FROM_PTE (PointerPte); 01168 Pfn1 = MI_PFN_ELEMENT (PageFrameIndex); 01169 01170 ASSERT (Pfn1->u3.e2.ReferenceCount > 1); 01171 01172 MI_REMOVE_LOCKED_PAGE_CHARGE(Pfn1, 7); 01173 01174 MiDecrementReferenceCount (PageFrameIndex); 01175 01176 if (PfnLockHeld == FALSE) { 01177 UNLOCK_PFN2 (OldIrql); 01178 } 01179 return; 01180 }

VOID MiUnmapImageHeaderInHyperSpace VOID   ) 
 

Definition at line 243 of file alpha/hypermap.c.

References ASSERT, Event(), FALSE, IMAGE_MAPPING_PTE, KeFlushSingleTb(), KePulseEvent(), LOCK_PFN, MiGetPteAddress, MmWorkingSetList, NULL, TRUE, _MMPTE::u, UNLOCK_PFN, and _MMWSL::WaitingForImageMapping.

Referenced by MiCreateImageFileMap().

00249 : 00250 00251 This procedure unmaps the PTE reserved for mapping the image 00252 header, flushes the TB, and, if the WaitingForImageMapping field 00253 is not NULL, sets the specified event. 00254 00255 On ALPHA, no action is required as the super-page address of the page 00256 was used. 00257 00258 Arguments: 00259 00260 None. 00261 00262 Return Value: 00263 00264 None. 00265 00266 Environment: 00267 00268 Kernel mode. 00269 00270 --*/ 00271 00272 { 00273 MMPTE TempPte; 00274 PMMPTE PointerPte; 00275 KIRQL OldIrql; 00276 PKEVENT Event; 00277 00278 PointerPte = MiGetPteAddress (IMAGE_MAPPING_PTE); 00279 00280 TempPte.u.Long = 0; 00281 00282 LOCK_PFN (OldIrql); 00283 00284 // 00285 // Capture the current state of the event field and clear it out. 00286 // 00287 00288 Event = MmWorkingSetList->WaitingForImageMapping; 00289 00290 MmWorkingSetList->WaitingForImageMapping = (PKEVENT)NULL; 00291 00292 ASSERT (PointerPte->u.Long != 0); 00293 00294 KeFlushSingleTb (IMAGE_MAPPING_PTE, TRUE, FALSE, 00295 (PHARDWARE_PTE)PointerPte, TempPte.u.Hard); 00296 00297 UNLOCK_PFN (OldIrql); 00298 00299 if (Event != (PKEVENT)NULL) { 00300 00301 // 00302 // If there was an event specified, set the event. 00303 // 00304 00305 KePulseEvent (Event, 0, FALSE); 00306 } 00307 00308 return; 00309 }

VOID MiUnmapSinglePage IN PVOID  BaseAddress  ) 
 

Definition at line 2543 of file iosup.c.

References ASSERT, MI_IS_PHYSICAL_ADDRESS, MiGetPteAddress, MiReleaseSystemPtes(), PAGED_CODE, and SystemPteSpace.

Referenced by MiCloneProcessAddressSpace().

02549 : 02550 02551 This routine unmaps a single locked pages which was previously mapped via 02552 an MiMapSinglePage call. 02553 02554 Arguments: 02555 02556 VirtualAddress - Supplies the virtual address used to map the page. 02557 02558 Return Value: 02559 02560 None. 02561 02562 Environment: 02563 02564 Kernel mode. APC_LEVEL or below, base address is within system space. 02565 02566 --*/ 02567 02568 { 02569 PMMPTE PointerPte; 02570 02571 PAGED_CODE (); 02572 02573 ASSERT (MI_IS_PHYSICAL_ADDRESS (VirtualAddress) == 0); 02574 ASSERT (VirtualAddress >= MM_SYSTEM_RANGE_START); 02575 02576 PointerPte = MiGetPteAddress (VirtualAddress); 02577 02578 MiReleaseSystemPtes (PointerPte, 1, SystemPteSpace); 02579 return; 02580 }

VOID MiUpdateImageHeaderPage IN PMMPTE  PointerPte,
IN PFN_NUMBER  PageFrameNumber,
IN PCONTROL_AREA  ControlArea
 

Definition at line 4450 of file creasect.c.

References LOCK_PFN, MiDecrementReferenceCount(), MiInitializeTransitionPfn(), MiMakeSystemAddressValidPfn(), and UNLOCK_PFN.

Referenced by MiCheckForCrashDump(), and MiCreateImageFileMap().

04458 : 04459 04460 This non-pagable function acquires the PFN lock, and 04461 turns the specified prototype PTE into a transition PTE 04462 referring to the specified physical page. It then 04463 decrements the reference count causing the page to 04464 be placed on the standby or modified list. 04465 04466 Arguments: 04467 04468 PointerPte - Supplies the PTE to set into the transition state. 04469 04470 PageFrameNumber - Supplies the physical page. 04471 04472 ControlArea - Supplies the control area for the prototype PTEs. 04473 04474 Return Value: 04475 04476 None. 04477 04478 --*/ 04479 04480 { 04481 KIRQL OldIrql; 04482 04483 LOCK_PFN (OldIrql); 04484 04485 MiMakeSystemAddressValidPfn (PointerPte); 04486 04487 MiInitializeTransitionPfn (PageFrameNumber, PointerPte, 0xFFFFFFFF); 04488 ControlArea->NumberOfPfnReferences += 1; 04489 04490 // 04491 // Add the page to the standby list. 04492 // 04493 04494 MiDecrementReferenceCount (PageFrameNumber); 04495 04496 UNLOCK_PFN (OldIrql); 04497 return; 04498 }

VOID FASTCALL MiUpdateModifiedWriterMdls IN ULONG  PageFileNumber  ) 
 

Definition at line 1098 of file deleteva.c.

References _MMMOD_WRITER_MDL_ENTRY::CurrentList, _MMPAGING_FILE::Entry, _MMMOD_WRITER_LISTHEAD::Event, FALSE, KeSetEvent(), _MMMOD_WRITER_MDL_ENTRY::Links, _MMMOD_WRITER_LISTHEAD::ListHead, MM_IO_IN_PROGRESS, MM_PAGING_FILE_MDLS, MmFreePagingSpaceLow, MmNumberOfActiveMdlEntries, MmPagingFile, MmPagingFileHeader, _MMMOD_WRITER_MDL_ENTRY::PagingListHead, and PMMMOD_WRITER_MDL_ENTRY.

Referenced by MiAttemptPageFileExtension(), MiExtendPagingFileMaximum(), and MiReleasePageFileSpace().

01104 : 01105 01106 This routine ensures the MDLs for the specified paging file 01107 are in the proper state such that paging i/o can continue. 01108 01109 Arguments: 01110 01111 PageFileNumber - Supplies the page file number to check the MDLs for. 01112 01113 Return Value: 01114 01115 None. 01116 01117 Environment: 01118 01119 Kernel mode, PFN lock held. 01120 01121 --*/ 01122 01123 { 01124 ULONG i; 01125 PMMMOD_WRITER_MDL_ENTRY WriterEntry; 01126 01127 // 01128 // Put the MDL entries into the active list. 01129 // 01130 01131 for (i = 0; i < MM_PAGING_FILE_MDLS; i += 1) { 01132 01133 if ((MmPagingFile[PageFileNumber]->Entry[i]->Links.Flink != 01134 MM_IO_IN_PROGRESS) 01135 && 01136 (MmPagingFile[PageFileNumber]->Entry[i]->CurrentList == 01137 &MmFreePagingSpaceLow)) { 01138 01139 // 01140 // Remove this entry and put it on the active list. 01141 // 01142 01143 WriterEntry = MmPagingFile[PageFileNumber]->Entry[i]; 01144 RemoveEntryList (&WriterEntry->Links); 01145 WriterEntry->CurrentList = &MmPagingFileHeader.ListHead; 01146 01147 KeSetEvent (&WriterEntry->PagingListHead->Event, 0, FALSE); 01148 01149 InsertTailList (&WriterEntry->PagingListHead->ListHead, 01150 &WriterEntry->Links); 01151 MmNumberOfActiveMdlEntries += 1; 01152 } 01153 } 01154 01155 return; 01156 }

VOID MiUpdateWsle IN PWSLE_NUMBER  DesiredIndex,
IN PVOID  VirtualAddress,
IN PMMWSL  WorkingSetList,
IN PMMPFN  Pfn
 

VOID MiVerifierCheckThunks IN PLDR_DATA_TABLE_ENTRY  DataTableEntry  ) 
 

Definition at line 3982 of file verifier.c.

References _DRIVER_SPECIFIED_VERIFIER_THUNKS::DataTableEntry, ExFreePool(), MiActiveVerifierThunks, MiVerifierDriverAddedThunkListHead, PAGED_CODE, and PDRIVER_SPECIFIED_VERIFIER_THUNKS.

03988 : 03989 03990 This routine adds another set of thunks to the verifier list. 03991 03992 Arguments: 03993 03994 DataTableEntry - Supplies the data table entry for the driver. 03995 03996 Return Value: 03997 03998 None. 03999 04000 Environment: 04001 04002 Kernel mode. APC_LEVEL and below. 04003 The system load lock must be held by the caller. 04004 04005 --*/ 04006 04007 { 04008 PLIST_ENTRY NextEntry; 04009 PDRIVER_SPECIFIED_VERIFIER_THUNKS ThunkTableBase; 04010 04011 PAGED_CODE (); 04012 04013 // 04014 // N.B. The DataTableEntry can move (see MiInitializeLoadedModuleList), 04015 // but this only happens long before IoInitialize so this is safe. 04016 // 04017 04018 NextEntry = MiVerifierDriverAddedThunkListHead.Flink; 04019 while (NextEntry != &MiVerifierDriverAddedThunkListHead) { 04020 04021 ThunkTableBase = CONTAINING_RECORD(NextEntry, 04022 DRIVER_SPECIFIED_VERIFIER_THUNKS, 04023 ListEntry); 04024 04025 if (ThunkTableBase->DataTableEntry == DataTableEntry) { 04026 RemoveEntryList (NextEntry); 04027 NextEntry = NextEntry->Flink; 04028 ExFreePool (ThunkTableBase); 04029 MiActiveVerifierThunks -= 1; 04030 04031 // 04032 // Keep looking as the driver may have made multiple calls. 04033 // 04034 04035 continue; 04036 } 04037 04038 NextEntry = NextEntry->Flink; 04039 } 04040 }

VOID MiVerifyingDriverUnloading IN PLDR_DATA_TABLE_ENTRY  DataTableEntry  ) 
 

Definition at line 3625 of file verifier.c.

References ASSERT, _MI_VERIFIER_DRIVER_ENTRY::BaseName, _MI_VERIFIER_DRIVER_ENTRY::CurrentNonPagedPoolAllocations, _MI_VERIFIER_DRIVER_ENTRY::CurrentPagedPoolAllocations, DbgPrint, _MI_VERIFIER_DRIVER_ENTRY::EndAddress, ExFreePool(), FALSE, KeBugCheckEx(), KernelVerifier, KiStackProtectTime, MiActiveVerifies, MiEnableRandomSpecialPool(), MiNoPageOnRaiseIrql, MiSuspectDriverList, MiVerifierStackProtectTime, MmVerifierData, _MI_VERIFIER_DRIVER_ENTRY::NonPagedBytes, NULL, _MI_VERIFIER_DRIVER_ENTRY::PagedBytes, _MI_VERIFIER_DRIVER_ENTRY::PoolHash, _MI_VERIFIER_DRIVER_ENTRY::PoolHashFree, _MI_VERIFIER_DRIVER_ENTRY::PoolHashReserved, _MI_VERIFIER_DRIVER_ENTRY::PoolHashSize, RtlEqualUnicodeString(), _MI_VERIFIER_DRIVER_ENTRY::StartAddress, TRUE, _MI_VERIFIER_DRIVER_ENTRY::Unloads, VerifierListLock, _MI_VERIFIER_DRIVER_ENTRY::VerifierPoolLock, VI_POOL_FREELIST_END, and ViBadDriver.

Referenced by MmUnloadSystemImage().

03631 : 03632 03633 This function is called as a driver that was being verified is now being 03634 unloaded. 03635 03636 Arguments: 03637 03638 DataTableEntry - Supplies the data table entry for the driver. 03639 03640 Return Value: 03641 03642 TRUE if thunking was applied, FALSE if not. 03643 03644 Environment: 03645 03646 Kernel mode, Phase 0 Initialization and normal runtime. 03647 Non paged pool exists in Phase0, but paged pool does not. 03648 Post-Phase0 serialization is provided by the MmSystemLoadLock. 03649 03650 --*/ 03651 03652 { 03653 KIRQL OldIrql; 03654 LOGICAL Found; 03655 PLIST_ENTRY NextEntry; 03656 PMI_VERIFIER_DRIVER_ENTRY Verifier; 03657 PVI_POOL_ENTRY OldHashTable; 03658 03659 Found = FALSE; 03660 NextEntry = MiSuspectDriverList.Flink; 03661 while (NextEntry != &MiSuspectDriverList) { 03662 03663 Verifier = CONTAINING_RECORD(NextEntry, 03664 MI_VERIFIER_DRIVER_ENTRY, 03665 Links); 03666 03667 if (RtlEqualUnicodeString (&Verifier->BaseName, 03668 &DataTableEntry->BaseDllName, 03669 TRUE)) { 03670 03671 Found = TRUE; 03672 break; 03673 } 03674 NextEntry = NextEntry->Flink; 03675 } 03676 03677 ASSERT (Found == TRUE); 03678 03679 if (MmVerifierData.Level & DRIVER_VERIFIER_TRACK_POOL_ALLOCATIONS) { 03680 03681 // 03682 // Better not be any pool left that wasn't freed. Walk the pagable 03683 // allocations in an attempt to make them all resident for a 03684 // kernel debugger session. 03685 // 03686 03687 if (Verifier->PagedBytes) { 03688 03689 #if DBG 03690 DbgPrint ("Driver %wZ leaked %d paged pool allocations (0x%x bytes)\n", 03691 &DataTableEntry->FullDllName, 03692 Verifier->CurrentPagedPoolAllocations, 03693 Verifier->PagedBytes); 03694 #endif 03695 03696 // 03697 // It would be nice to fault in the driver's paged pool allocations 03698 // now to make debugging easier, but this cannot be easily done 03699 // in a deadlock free manner. 03700 // 03701 // At least disable the paging of pool on IRQL raising in attempt 03702 // to keep some of these allocations resident for debugging. 03703 // No need to undo the increment as we're about to bugcheck anyway. 03704 // 03705 03706 InterlockedIncrement ((PLONG)&MiNoPageOnRaiseIrql); 03707 } 03708 03709 #if DBG 03710 if (Verifier->NonPagedBytes) { 03711 DbgPrint ("Driver %wZ leaked %d nonpaged pool allocations (0x%x bytes)\n", 03712 &DataTableEntry->FullDllName, 03713 Verifier->CurrentNonPagedPoolAllocations, 03714 Verifier->NonPagedBytes); 03715 } 03716 #endif 03717 03718 if (Verifier->PagedBytes || Verifier->NonPagedBytes) { 03719 #if 0 03720 DbgBreakPoint (); 03721 InterlockedDecrement (&MiNoPageOnRaiseIrql); 03722 #else 03723 // 03724 // Snap this so the build/BVT lab can easily triage the culprit. 03725 // 03726 03727 ViBadDriver = &Verifier->BaseName; 03728 03729 KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION, 03730 0x60, 03731 Verifier->PagedBytes, 03732 Verifier->NonPagedBytes, 03733 Verifier->CurrentPagedPoolAllocations + 03734 Verifier->CurrentNonPagedPoolAllocations); 03735 #endif 03736 } 03737 03738 ExAcquireSpinLock (&Verifier->VerifierPoolLock, &OldIrql); 03739 03740 if (Verifier->PoolHashReserved != 0) { 03741 KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION, 03742 0x61, 03743 Verifier->PagedBytes, 03744 Verifier->NonPagedBytes, 03745 Verifier->CurrentPagedPoolAllocations + 03746 Verifier->CurrentNonPagedPoolAllocations); 03747 } 03748 03749 OldHashTable = Verifier->PoolHash; 03750 if (OldHashTable != NULL) { 03751 Verifier->PoolHashSize = 0; 03752 Verifier->PoolHashFree = VI_POOL_FREELIST_END; 03753 Verifier->PoolHash = NULL; 03754 } 03755 else { 03756 ASSERT (Verifier->PoolHashSize == 0); 03757 ASSERT (Verifier->PoolHashFree == VI_POOL_FREELIST_END); 03758 } 03759 03760 ExReleaseSpinLock (&Verifier->VerifierPoolLock, OldIrql); 03761 03762 if (OldHashTable != NULL) { 03763 ExFreePool (OldHashTable); 03764 } 03765 03766 // 03767 // Clear these fields so reuse of stale addresses don't trigger 03768 // erroneous bucket fills. 03769 // 03770 03771 ExAcquireSpinLock (&VerifierListLock, &OldIrql); 03772 Verifier->StartAddress = NULL; 03773 Verifier->EndAddress = NULL; 03774 ExReleaseSpinLock (&VerifierListLock, OldIrql); 03775 } 03776 03777 Verifier->Unloads += 1; 03778 MmVerifierData.Unloads += 1; 03779 MiActiveVerifies -= 1; 03780 03781 if (MiActiveVerifies == 0) { 03782 03783 if (MmVerifierData.Level & DRIVER_VERIFIER_FORCE_IRQL_CHECKING) { 03784 03785 // 03786 // Return to normal thread stack protection. 03787 // 03788 03789 if (KernelVerifier == FALSE) { 03790 KiStackProtectTime = MiVerifierStackProtectTime; 03791 } 03792 } 03793 03794 #ifndef NO_POOL_CHECKS 03795 MiEnableRandomSpecialPool (TRUE); 03796 #endif 03797 } 03798 }

VOID MiWaitForForkToComplete IN PEPROCESS  CurrentProcess  ) 
 

Definition at line 1980 of file forksup.c.

References APC_LEVEL, LOCK_ADDRESS_SPACE, LOCK_PFN, LOCK_WS_REGARDLESS, UNLOCK_ADDRESS_SPACE, UNLOCK_PFN, and UNLOCK_WS_REGARDLESS.

Referenced by MiCopyOnWrite(), MiDecrementCloneBlockReference(), MiResolveDemandZeroFault(), and MmAccessFault().

01986 : 01987 01988 This routine waits for the current process to complete a fork 01989 operation. 01990 01991 Arguments: 01992 01993 CurrentProcess - Supplies the current process value. 01994 01995 Return Value: 01996 01997 None. 01998 01999 Environment: 02000 02001 Kernel mode, APCs disabled, working set mutex and PFN mutex held. 02002 02003 --*/ 02004 02005 { 02006 ULONG OldIrql; 02007 LOGICAL WsHeldSafe; 02008 02009 // 02010 // A fork operation is in progress and the count of clone-blocks 02011 // and other structures may not be changed. Release the mutexes 02012 // and wait for the address creation mutex which governs the 02013 // fork operation. 02014 // 02015 02016 UNLOCK_PFN (APC_LEVEL); 02017 02018 // 02019 // The working set mutex may have been acquired safely or unsafely 02020 // by our caller. Handle both cases here and below, carefully making sure 02021 // that the OldIrql left in the WS mutex on return is the same as on entry. 02022 // 02023 02024 OldIrql = CurrentProcess->WorkingSetLock.OldIrql; 02025 02026 UNLOCK_WS_REGARDLESS (CurrentProcess, WsHeldSafe); 02027 02028 // 02029 // Explicitly acquire the working set lock safely as it may be released and 02030 // reacquired by our caller. 02031 // 02032 02033 LOCK_ADDRESS_SPACE (CurrentProcess); 02034 02035 // 02036 // The working set lock may have been acquired safely or unsafely 02037 // by our caller. Reacquire it in the same manner our caller did. 02038 // 02039 02040 LOCK_WS_REGARDLESS (CurrentProcess, WsHeldSafe); 02041 02042 // 02043 // Release the address creation mutex, the working set mutex 02044 // must be held to set the ForkInProgress field. 02045 // 02046 02047 UNLOCK_ADDRESS_SPACE (CurrentProcess); 02048 02049 // 02050 // Ensure the previous IRQL is correctly set to its entry value. 02051 // 02052 02053 CurrentProcess->WorkingSetLock.OldIrql = OldIrql; 02054 02055 // 02056 // Get the PFN lock again. 02057 // 02058 02059 LOCK_PFN (OldIrql); 02060 return; 02061 } #if DBG

NTSTATUS MiWaitForInPageComplete IN PMMPFN  Pfn,
IN PMMPTE  PointerPte,
IN PVOID  FaultingAddress,
IN PMMPTE  PointerPteContents,
IN PMMINPAGE_SUPPORT  InPageSupport,
IN PEPROCESS  CurrentProcess
 

Definition at line 2335 of file pagfault.c.

References ASSERT, BYTE_OFFSET, _MDL::ByteCount, DbgPrint, FALSE, HYDRA_PROCESS, KeBugCheckEx(), KernelMode, KeWaitForSingleObject(), LOCK_PFN, LOCK_SESSION_SPACE_WS, LOCK_SYSTEM_WS, LOCK_WS, _MDL::MappedSystemVa, MDL_LOCK_HELD, MDL_MAPPED_TO_SYSTEM_VA, _MDL::MdlFlags, MI_INSERT_USED_PAGETABLE_ENTRIES_IN_PFN, MI_IS_SYSTEM_CACHE_ADDRESS, MI_MAGIC_AWE_PTEFRAME, MI_PFN_ELEMENT, MI_PTE_LOOKUP_NEEDED, MI_ZERO_USED_PAGETABLE_ENTRIES_IN_PFN, MiCheckVirtualAddress(), MiFaultRetries, MiFindActualFaultingPte(), MiFreeInPageSupportBlock(), MiIoRetryLevel, MiMapPageInHyperSpace(), MiPteToProto, MiUnmapPageInHyperSpace, MiUserFaultRetries, MiUserIoRetryLevel, MiZeroPhysicalPage(), MmIsAddressValid(), MmIsRetryIoStatus, MmUnmapLockedPages(), NT_SUCCESS, NTSTATUS(), NULL, Offset, PAGE_SHIFT, PAGE_SIZE, _MMPFN::PteAddress, _MMPFN::PteFrame, STATUS_PTE_CHANGED, STATUS_REFAULT, TRUE, _MMPTE::u, _MMPFN::u1, _MMPFN::u3, and WrPageIn.

Referenced by MiDispatchFault(), and MiResolveTransitionFault().

02346 : 02347 02348 Waits for a page read to complete. 02349 02350 Arguments: 02351 02352 Pfn - Supplies a pointer to the PFN element for the page being read. 02353 02354 PointerPte - Supplies a pointer to the pte that is in the transition 02355 state. 02356 02357 FaultingAddress - Supplies the faulting address. 02358 02359 PointerPteContents - Supplies the contents of the PTE before the 02360 working set lock was released. 02361 02362 InPageSupport - Supplies a pointer to the inpage support structure 02363 for this read operation. 02364 02365 Return Value: 02366 02367 Returns the status of the in page. 02368 02369 Note that the working set lock is held upon return !!! 02370 02371 Environment: 02372 02373 Kernel mode, APCs disabled. Neither the working set lock nor 02374 the PFN lock may be held. 02375 02376 --*/ 02377 02378 { 02379 PMMPTE NewPointerPte; 02380 PMMPTE ProtoPte; 02381 PMMPFN Pfn1; 02382 PMMPFN Pfn; 02383 PULONG Va; 02384 PPFN_NUMBER Page; 02385 PPFN_NUMBER LastPage; 02386 ULONG Offset; 02387 ULONG Protection; 02388 PMDL Mdl; 02389 KIRQL OldIrql; 02390 NTSTATUS status; 02391 NTSTATUS status2; 02392 02393 // 02394 // Wait for the I/O to complete. Note that we can't wait for all 02395 // the objects simultaneously as other threads/processes could be 02396 // waiting for the same event. The first thread which completes 02397 // the wait and gets the PFN mutex may reuse the event for another 02398 // fault before this thread completes its wait. 02399 // 02400 02401 KeWaitForSingleObject( &InPageSupport->Event, 02402 WrPageIn, 02403 KernelMode, 02404 FALSE, 02405 (PLARGE_INTEGER)NULL); 02406 02407 if (CurrentProcess == HYDRA_PROCESS) { 02408 LOCK_SESSION_SPACE_WS (OldIrql); 02409 } 02410 else if (CurrentProcess != NULL) { 02411 LOCK_WS (CurrentProcess); 02412 } 02413 else { 02414 LOCK_SYSTEM_WS (OldIrql); 02415 } 02416 02417 LOCK_PFN (OldIrql); 02418 02419 ASSERT (Pfn2->u3.e2.ReferenceCount != 0); 02420 02421 // 02422 // Check to see if this is the first thread to complete the in-page 02423 // operation. 02424 // 02425 02426 Pfn = InPageSupport->Pfn; 02427 if (Pfn2 != Pfn) { 02428 ASSERT (Pfn2->PteFrame != MI_MAGIC_AWE_PTEFRAME); 02429 Pfn2->u3.e1.ReadInProgress = 0; 02430 } 02431 02432 // 02433 // Another thread has already serviced the read, check the 02434 // io-error flag in the PFN database to ensure the in-page 02435 // was successful. 02436 // 02437 02438 if (Pfn2->u3.e1.InPageError == 1) { 02439 ASSERT (!NT_SUCCESS(Pfn2->u1.ReadStatus)); 02440 MiFreeInPageSupportBlock (InPageSupport); 02441 02442 if (MmIsRetryIoStatus(Pfn2->u1.ReadStatus)) { 02443 return STATUS_REFAULT; 02444 } 02445 return Pfn2->u1.ReadStatus; 02446 } 02447 02448 if (InPageSupport->Completed == FALSE) { 02449 02450 #if defined(_PREFETCH_) 02451 02452 // 02453 // The ReadInProgress bit for the dummy page is constantly cleared 02454 // below as there are generally multiple inpage blocks pointing to 02455 // the same dummy page. 02456 // 02457 02458 ASSERT ((Pfn->u3.e1.ReadInProgress == 1) || 02459 (Pfn->PteAddress == MI_PF_DUMMY_PAGE_PTE)); 02460 #else 02461 ASSERT (Pfn->u3.e1.ReadInProgress == 1); 02462 #endif 02463 02464 InPageSupport->Completed = TRUE; 02465 02466 Mdl = &InPageSupport->Mdl; 02467 02468 #if defined(_PREFETCH_) 02469 02470 if (InPageSupport->PrefetchMdl != NULL) { 02471 02472 // 02473 // This is a prefetcher-issued read. 02474 // 02475 02476 Mdl = InPageSupport->PrefetchMdl; 02477 } 02478 02479 #endif 02480 02481 if (Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA) { 02482 #if DBG 02483 Mdl->MdlFlags |= MDL_LOCK_HELD; 02484 #endif //DBG 02485 02486 MmUnmapLockedPages (Mdl->MappedSystemVa, Mdl); 02487 02488 #if DBG 02489 Mdl->MdlFlags &= ~MDL_LOCK_HELD; 02490 #endif //DBG 02491 } 02492 02493 ASSERT (Pfn->PteFrame != MI_MAGIC_AWE_PTEFRAME); 02494 02495 Pfn->u3.e1.ReadInProgress = 0; 02496 Pfn->u1.Event = (PKEVENT)NULL; 02497 02498 #if defined (_WIN64) 02499 // 02500 // Page directory and page table pages are never clustered, 02501 // ensure this is never violated as only one UsedPageTableEntries 02502 // is kept in the inpage support block. 02503 // 02504 02505 if (InPageSupport->UsedPageTableEntries) { 02506 Page = (PPFN_NUMBER)(Mdl + 1); 02507 LastPage = Page + ((Mdl->ByteCount - 1) >> PAGE_SHIFT); 02508 ASSERT (Page == LastPage); 02509 } 02510 02511 #if DBGXX 02512 MiCheckPageTableInPage (Pfn, InPageSupport); 02513 #endif 02514 #endif 02515 02516 MI_INSERT_USED_PAGETABLE_ENTRIES_IN_PFN(Pfn, InPageSupport); 02517 02518 // 02519 // Check the IO_STATUS_BLOCK to ensure the in-page completed successfully. 02520 // 02521 02522 if (!NT_SUCCESS(InPageSupport->IoStatus.Status)) { 02523 02524 if (InPageSupport->IoStatus.Status == STATUS_END_OF_FILE) { 02525 02526 // 02527 // An attempt was made to read past the end of file 02528 // zero all the remaining bytes in the read. 02529 // 02530 02531 Page = (PPFN_NUMBER)(Mdl + 1); 02532 LastPage = Page + ((Mdl->ByteCount - 1) >> PAGE_SHIFT); 02533 02534 while (Page <= LastPage) { 02535 MiZeroPhysicalPage (*Page, 0); 02536 02537 MI_ZERO_USED_PAGETABLE_ENTRIES_IN_PFN(MI_PFN_ELEMENT(*Page)); 02538 02539 Page += 1; 02540 } 02541 02542 } else { 02543 02544 // 02545 // In page io error occurred. 02546 // 02547 02548 status = InPageSupport->IoStatus.Status; 02549 status2 = InPageSupport->IoStatus.Status; 02550 02551 if (status != STATUS_VERIFY_REQUIRED) { 02552 02553 LOGICAL Retry; 02554 02555 Retry = FALSE; 02556 #if DBG 02557 DbgPrint ("MM: inpage I/O error %X\n", 02558 InPageSupport->IoStatus.Status); 02559 #endif 02560 02561 // 02562 // If this page is for paged pool or for paged 02563 // kernel code or page table pages, bugcheck. 02564 // 02565 02566 if ((FaultingAddress > MM_HIGHEST_USER_ADDRESS) && 02567 (!MI_IS_SYSTEM_CACHE_ADDRESS(FaultingAddress))) { 02568 02569 if (MmIsRetryIoStatus(status)) { 02570 02571 MiFaultRetries -= 1; 02572 if (MiFaultRetries != 0) { 02573 Retry = TRUE; 02574 } else { 02575 MiFaultRetries = MiIoRetryLevel; 02576 } 02577 } 02578 02579 if (Retry == FALSE) { 02580 02581 ULONG_PTR PteContents; 02582 02583 // 02584 // The prototype PTE resides in paged pool which may 02585 // not be resident at this point. Check first. 02586 // 02587 02588 if (MmIsAddressValid (PointerPte) == TRUE) { 02589 PteContents = *(PULONG_PTR)PointerPte; 02590 } 02591 else { 02592 PteContents = (ULONG_PTR)-1; 02593 } 02594 02595 KeBugCheckEx (KERNEL_DATA_INPAGE_ERROR, 02596 (ULONG_PTR)PointerPte, 02597 status, 02598 (ULONG_PTR)FaultingAddress, 02599 PteContents); 02600 } 02601 status2 = STATUS_REFAULT; 02602 } 02603 else { 02604 02605 if (MmIsRetryIoStatus(status)) { 02606 02607 MiUserFaultRetries -= 1; 02608 if (MiUserFaultRetries != 0) { 02609 Retry = TRUE; 02610 } else { 02611 MiUserFaultRetries = MiUserIoRetryLevel; 02612 } 02613 } 02614 02615 if (Retry == TRUE) { 02616 status2 = STATUS_REFAULT; 02617 } 02618 } 02619 } 02620 02621 Page = (PPFN_NUMBER)(Mdl + 1); 02622 LastPage = Page + ((Mdl->ByteCount - 1) >> PAGE_SHIFT); 02623 02624 while (Page <= LastPage) { 02625 Pfn1 = MI_PFN_ELEMENT (*Page); 02626 ASSERT (Pfn1->u3.e2.ReferenceCount != 0); 02627 Pfn1->u3.e1.InPageError = 1; 02628 Pfn1->u1.ReadStatus = status; 02629 02630 #if DBG 02631 { 02632 KIRQL Old; 02633 Va = (PULONG)MiMapPageInHyperSpace (*Page,&Old); 02634 RtlFillMemoryUlong (Va, PAGE_SIZE, 0x50444142); 02635 MiUnmapPageInHyperSpace (Old); 02636 } 02637 #endif //DBG 02638 Page += 1; 02639 } 02640 02641 MiFreeInPageSupportBlock (InPageSupport); 02642 return status2; 02643 } 02644 } else { 02645 02646 MiFaultRetries = MiIoRetryLevel; 02647 MiUserFaultRetries = MiUserIoRetryLevel; 02648 02649 if (InPageSupport->IoStatus.Information != Mdl->ByteCount) { 02650 02651 ASSERT (InPageSupport->IoStatus.Information != 0); 02652 02653 // 02654 // Less than a full page was read - zero the remainder 02655 // of the page. 02656 // 02657 02658 Page = (PPFN_NUMBER)(Mdl + 1); 02659 LastPage = Page + ((Mdl->ByteCount - 1) >> PAGE_SHIFT); 02660 Page += ((InPageSupport->IoStatus.Information - 1) >> PAGE_SHIFT); 02661 02662 Offset = BYTE_OFFSET (InPageSupport->IoStatus.Information); 02663 02664 if (Offset != 0) { 02665 KIRQL Old; 02666 Va = (PULONG)((PCHAR)MiMapPageInHyperSpace (*Page, &Old) 02667 + Offset); 02668 02669 RtlZeroMemory (Va, PAGE_SIZE - Offset); 02670 MiUnmapPageInHyperSpace (Old); 02671 } 02672 02673 // 02674 // Zero any remaining pages within the MDL. 02675 // 02676 02677 Page += 1; 02678 02679 while (Page <= LastPage) { 02680 MiZeroPhysicalPage (*Page, 0); 02681 Page += 1; 02682 } 02683 } 02684 } 02685 } 02686 02687 MiFreeInPageSupportBlock (InPageSupport); 02688 02689 // 02690 // Check to see if the faulting PTE has changed. 02691 // 02692 02693 NewPointerPte = MiFindActualFaultingPte (FaultingAddress); 02694 02695 // 02696 // If this PTE is in prototype PTE format, make the pointer to the 02697 // PTE point to the prototype PTE. 02698 // 02699 02700 if (NewPointerPte == (PMMPTE)NULL) { 02701 return STATUS_PTE_CHANGED; 02702 } 02703 02704 if (NewPointerPte != PointerPte) { 02705 02706 // 02707 // Check to make sure the NewPointerPte is not a prototype PTE 02708 // which refers to the page being made valid. 02709 // 02710 02711 if (NewPointerPte->u.Soft.Prototype == 1) { 02712 if (NewPointerPte->u.Soft.PageFileHigh == MI_PTE_LOOKUP_NEEDED) { 02713 02714 ProtoPte = MiCheckVirtualAddress (FaultingAddress, 02715 &Protection); 02716 02717 } else { 02718 ProtoPte = MiPteToProto (NewPointerPte); 02719 } 02720 02721 // 02722 // Make sure the prototype PTE refers to the PTE made valid. 02723 // 02724 02725 if (ProtoPte != PointerPte) { 02726 return STATUS_PTE_CHANGED; 02727 } 02728 02729 // 02730 // If the only difference is the owner mask, everything is okay. 02731 // 02732 02733 if (ProtoPte->u.Long != PointerPteContents->u.Long) { 02734 return STATUS_PTE_CHANGED; 02735 } 02736 } else { 02737 return STATUS_PTE_CHANGED; 02738 } 02739 } else { 02740 02741 if (NewPointerPte->u.Long != PointerPteContents->u.Long) { 02742 return STATUS_PTE_CHANGED; 02743 } 02744 } 02745 return STATUS_SUCCESS; 02746 }

VOID FASTCALL MiZeroPhysicalPage IN PFN_NUMBER  PageFrameIndex,
IN ULONG  Color
 

Definition at line 1184 of file mmsup.c.

References KeZeroPage, MiMapPageInHyperSpace(), MiUnmapPageInHyperSpace, MM_COLOR_MASK, PAGE_SHIFT, and PAGE_SIZE.

Referenced by MiInitMachineDependent(), MiRemoveZeroPage(), MiResolveDemandZeroFault(), MiSessionCommitImagePages(), MiSessionCommitPageTables(), MiSessionCreateInternal(), MiSessionInitializeWorkingSetList(), MiWaitForInPageComplete(), MmAccessFault(), MmAllocatePagesForMdl(), and MmCreateProcessAddressSpace().

01191 : 01192 01193 This procedure maps the specified physical page into hyper space 01194 and fills the page with zeros. 01195 01196 Arguments: 01197 01198 PageFrameIndex - Supplies the physical page number to fill with 01199 zeroes. 01200 01201 Return Value: 01202 01203 none. 01204 01205 Environment: 01206 01207 Kernel mode. 01208 01209 --*/ 01210 01211 { 01212 PULONG va; 01213 KIRQL OldIrql; 01214 01215 #if defined(_ALPHA_) 01216 01217 HalZeroPage((PVOID)ULongToPtr((PageColor & MM_COLOR_MASK) << PAGE_SHIFT), 01218 (PVOID)ULongToPtr((PageColor & MM_COLOR_MASK) << PAGE_SHIFT), 01219 PageFrameIndex); 01220 #else 01221 01222 UNREFERENCED_PARAMETER (PageColor); 01223 01224 va = (PULONG)MiMapPageInHyperSpace (PageFrameIndex, &OldIrql); 01225 01226 #if defined(_X86_) 01227 01228 KeZeroPage(va); 01229 01230 #else 01231 01232 RtlZeroMemory (va, PAGE_SIZE); 01233 01234 #endif // X86 01235 01236 MiUnmapPageInHyperSpace (OldIrql); 01237 01238 #endif // ALPHA 01239 01240 return; 01241 }

VOID NodeTreeWalk PMMADDRESS_NODE  Start  ) 
 


Variable Documentation

MMPTE DemandZeroPde
 

Definition at line 4422 of file mi.h.

MMPTE DemandZeroPte
 

Definition at line 4424 of file mi.h.

PEPROCESS ExpDefaultErrorPortProcess
 

Definition at line 230 of file mi.h.

ULONG ExpMultiUserTS
 

Definition at line 4440 of file mi.h.

MMPTE GlobalPte
 

Definition at line 4911 of file mi.h.

MMPTE KernelPrototypePte
 

Definition at line 4426 of file mi.h.

LOGICAL KernelVerifier
 

Definition at line 4195 of file mi.h.

ULONG MiActiveVerifierThunks
 

Definition at line 4192 of file mi.h.

Referenced by MiVerifierCheckThunks(), MmAddVerifierThunks(), and MmUnloadSystemImage().

ULONG_PTR MiActiveWriteWatch
 

Definition at line 2440 of file mi.h.

Referenced by MiEliminateWorkingSetEntry(), MiFlushTbAndCapture(), MiPhysicalViewInserter(), and MiPhysicalViewRemover().

ULONG MiDelayPageFaults
 

Definition at line 4555 of file mi.h.

Referenced by MiAllocateContiguousMemory(), MmAccessFault(), MmGatherMemoryForHibernate(), and MmRemovePhysicalMemory().

ULONG MiFaultRetries
 

Definition at line 246 of file mi.h.

Referenced by MiApplyDriverVerifier(), and MiWaitForInPageComplete().

PMMINPAGE_SUPPORT MiGetInPageSupportBlock(VOID)
 

PMMPTE MiHighestUserPde
 

Definition at line 5701 of file mi.h.

Referenced by MiDetermineUserGlobalPteMask(), and MmInitSystem().

PMMPTE MiHighestUserPte
 

Definition at line 5700 of file mi.h.

Referenced by MiAccessCheck(), MiDeletePte(), MiDeleteSystemPagableVm(), MiDetermineUserGlobalPteMask(), and MmInitSystem().

BOOLEAN MiHydra
 

Definition at line 4438 of file mi.h.

Referenced by MiAttachSession(), MiCheckAndSetSystemTrimCriteria(), MiCheckControlArea(), MiCheckForControlAreaDeletion(), MiCheckPdeForPagedPool(), MiCheckPdeForSessionSpace(), MiCheckProcessTrimCriteria(), MiCleanSection(), MiCompleteProtoPteFault(), MiCreateImageFileMap(), MiDetachSession(), MiDispatchFault(), MiEmptyAllWorkingSets(), MiEmptyAllWorkingSetsWorker(), MiEmptyWorkingSet(), MiEnablePagingTheExecutive(), MiFreePoolPages(), MiInitializeSpecialPool(), MiInitializeSystemSpaceMap(), MiInitMachineDependent(), MiLoadImageSection(), MiLoadSystemImage(), MiRearrangeWorkingSetExpansionList(), MiRemoveFromSystemSpace(), MiRemoveMappedPtes(), MiSessionInSwapProcess(), MiSessionOutSwapProcess(), MmAccessFault(), MmCleanProcessAddressSpace(), MmCreateProcessAddressSpace(), MmCreateSection(), MmFlushImageSection(), MmForceSectionClosed(), MmInitSystem(), MmInSwapProcess(), MmMapViewInSessionSpace(), MmOutSwapProcess(), MmSessionCreate(), MmSessionDelete(), MmSessionSetUnloadAddress(), MmUnmapViewInSessionSpace(), MmWorkingSetManager(), and VeAllocatePoolWithTagPriority().

ULONG MiIoRetryLevel
 

Definition at line 245 of file mi.h.

Referenced by MiApplyDriverVerifier(), MiFlushSectionInternal(), MiMakeOutswappedPageResident(), and MiWaitForInPageComplete().

KEVENT MiMappedPagesTooOldEvent
 

Definition at line 5138 of file mi.h.

Referenced by MiModifiedPageWriterTimerDispatch(), MiModifiedPageWriterWorker(), and MmInitSystem().

LARGE_INTEGER MiModifiedPageLife
 

Definition at line 5134 of file mi.h.

Referenced by MiInsertPageInList(), MiModifiedPageWriterWorker(), and MmInitSystem().

KTIMER MiModifiedPageWriterTimer
 

Definition at line 5142 of file mi.h.

Referenced by MiInsertPageInList(), MiModifiedPageWriterWorker(), and MmInitSystem().

KDPC MiModifiedPageWriterTimerDpc
 

Definition at line 5140 of file mi.h.

Referenced by MiInsertPageInList(), MiModifiedPageWriterWorker(), and MmInitSystem().

ULONG MiOverCommitCallCount
 

Definition at line 5162 of file mi.h.

Referenced by MiCauseOverCommitPopup().

ULONG MiRequestedSystemPtes
 

Definition at line 4664 of file mi.h.

Referenced by MiInitializeSpecialPool(), MiInitMachineDependent(), and MmInitSystem().

PMMPTE MiSessionBasePte
 

Definition at line 5703 of file mi.h.

Referenced by MmInitSystem().

ULONG MiSessionCount
 

Definition at line 5611 of file mi.h.

Referenced by MiDereferenceSession(), and MmSessionCreate().

PMMPTE MiSessionLastPte
 

Definition at line 5704 of file mi.h.

Referenced by MmInitSystem().

LIST_ENTRY MiSessionWsList
 

Definition at line 5771 of file mi.h.

Referenced by MiInitializeSessionWsSupport(), and MiSessionInitializeWorkingSetList().

ULONG MiSpecialPagesNonPaged
 

Definition at line 4331 of file mi.h.

Referenced by MiAllocateSpecialPool(), and MmFreeSpecialPool().

ULONG MiSpecialPagesNonPagedMaximum
 

Definition at line 4332 of file mi.h.

Referenced by MiAllocateSpecialPool(), and MiInitializeSpecialPool().

LIST_ENTRY MiSuspectDriverList
 

Definition at line 4193 of file mi.h.

Referenced by MiApplyDriverVerifier(), MiInitializeDriverVerifierList(), MiVerifyingDriverUnloading(), MmGetVerifierInformation(), ViInsertVerifierEntry(), and ViLocateVerifierEntry().

ULONG_PTR MiSystemViewStart
 

Definition at line 4744 of file mi.h.

Referenced by MiInitializeSystemSpaceMap(), and MmInitSystem().

BOOLEAN MiTimerPending
 

Definition at line 5136 of file mi.h.

Referenced by MiInsertPageInList(), MiModifiedPageWriterTimerDispatch(), and MiModifiedPageWriterWorker().

BOOLEAN MiTrackingAborted
 

Definition at line 2676 of file mi.h.

Referenced by MiAddMdlTracker(), MiFreeMdlTracker(), and MmCleanProcessAddressSpace().

PUNLOADED_DRIVERS MiUnloadedDrivers
 

Definition at line 2694 of file mi.h.

SIZE_T MiUnusedSegmentNonPagedPoolUsage
 

Definition at line 4960 of file mi.h.

SIZE_T MiUnusedSegmentPagedPoolUsage
 

Definition at line 4953 of file mi.h.

ULONG MiUserFaultRetries
 

Definition at line 248 of file mi.h.

Referenced by MiApplyDriverVerifier(), and MiWaitForInPageComplete().

ULONG MiUserIoRetryLevel
 

Definition at line 247 of file mi.h.

Referenced by MiApplyDriverVerifier(), and MiWaitForInPageComplete().

LARGE_INTEGER Mm30Milliseconds
 

Definition at line 217 of file mi.h.

Referenced by MiFlushAllPages(), MiFlushSectionInternal(), MiGatherPagefilePages(), MiModifiedPageWriterWorker(), MiWriteComplete(), MmAccessFault(), and MmGatherMemoryForHibernate().

ULONG MmAliasAlignment
 

Definition at line 4775 of file mi.h.

ULONG MmAliasAlignmentMask
 

Definition at line 4789 of file mi.h.

ULONG MmAliasAlignmentOffset
 

Definition at line 4782 of file mi.h.

PFN_NUMBER MmAllocatedNonPagedPool
 

Definition at line 4650 of file mi.h.

MMPAGE_FILE_EXPANSION MmAttemptForCantExtend
 

Definition at line 5073 of file mi.h.

Referenced by MiChargeCommitmentCantExpand(), MiIssuePageExtendRequestNoWait(), and MmInitSystem().

PFN_COUNT MmAvailablePages
 

Definition at line 4480 of file mi.h.

KEVENT MmAvailablePagesEvent
 

Definition at line 4581 of file mi.h.

Referenced by MiEnsureAvailablePageOrWait(), MiInsertPageInList(), MiInsertStandbyListAtFront(), and MmInitSystem().

KEVENT MmAvailablePagesEventHigh
 

Definition at line 4583 of file mi.h.

Referenced by MiEnsureAvailablePageOrWait(), MiInsertPageInList(), MiInsertStandbyListAtFront(), and MmInitSystem().

MMPFNLIST MmBadPageListHead
 

Definition at line 4569 of file mi.h.

KSPIN_LOCK MmChargeCommitmentLock
 

Definition at line 4899 of file mi.h.

Referenced by MiAttemptPageFileReduction(), MiCauseOverCommitPopup(), MiChargeCommitment(), MiChargeCommitmentCantExpand(), MiCheckForUserStackOverflow(), MiContractPagingFiles(), MiExtendPagingFiles(), MiInsertConflictInList(), MiInsertPageFileInList(), MiIssuePageExtendRequestNoWait(), MiPageFileFull(), MiRemoveConflictFromList(), MiReturnCommitment(), MmAddPhysicalMemory(), MmInitSystem(), and MmRemovePhysicalMemory().

ULONG MmCodeClusterSize
 

Definition at line 4854 of file mi.h.

Referenced by MiResolveMappedFileFault(), and MmInitSystem().

KEVENT MmCollidedFlushEvent
 

Definition at line 5098 of file mi.h.

Referenced by MiFlushSectionInternal(), and MmInitSystem().

KEVENT MmCollidedLockEvent
 

Definition at line 5100 of file mi.h.

Referenced by MmInitSystem(), MmLockPagableSectionByHandle(), and MmUnlockPagableImageSection().

PMMPTE MmCrashDumpPte
 

Definition at line 5160 of file mi.h.

LARGE_INTEGER MmCriticalSectionTimeout
 

Definition at line 218 of file mi.h.

Referenced by MmCreatePeb(), and MmInitSystem().

ULONG MmCritsectTimeoutSeconds
 

Definition at line 224 of file mi.h.

ULONG MmDataClusterSize
 

Definition at line 4852 of file mi.h.

Referenced by MiResolveMappedFileFault(), and MmInitSystem().

PMMPTE MmDebugPte
 

Definition at line 5158 of file mi.h.

SIZE_T MmDefaultMaximumNonPagedPool
 

Definition at line 4640 of file mi.h.

Referenced by MiInitMachineDependent().

MMDEREFERENCE_SEGMENT_HEADER MmDereferenceSegmentHeader
 

Definition at line 4944 of file mi.h.

Referenced by MiChargeCommitmentCantExpand(), MiCheckForControlAreaDeletion(), MiContractPagingFiles(), MiDereferenceSegmentThread(), MiIssuePageExtendRequest(), MiIssuePageExtendRequestNoWait(), MiSectionInitialization(), and MiSegmentDelete().

ULONG MmDisablePagingExecutive
 

Definition at line 4929 of file mi.h.

LOGICAL MmDontVerifyRandomDrivers
 

Definition at line 4074 of file mi.h.

FAST_MUTEX MmDynamicMemoryMutex
 

Definition at line 1369 of file mi.h.

Referenced by MiCheckForCrashDump(), MiFindContiguousMemory(), MmAddPhysicalMemory(), MmAllocatePagesForMdl(), MmGetPhysicalMemoryRanges(), MmInitSystem(), and MmRemovePhysicalMemory().

LOGICAL MmDynamicPfn
 

Definition at line 1367 of file mi.h.

ULONG MmEnforceWriteProtection
 

Definition at line 4077 of file mi.h.

ULONG MmExpandedPoolBitPosition
 

Definition at line 4656 of file mi.h.

Referenced by MiFreePoolPages(), and MiInitializeNonPagedPool().

KSPIN_LOCK MmExpansionLock
 

Definition at line 4905 of file mi.h.

Referenced by MmInitSystem(), and MmTrimAllSystemPagableMemory().

SIZE_T MmExtendedCommit
 

Definition at line 232 of file mi.h.

PMMPFN MmFirstDeadKernelStack
 

Definition at line 4798 of file mi.h.

Referenced by MmCreateKernelStack(), and MmDeleteKernelStack().

MMPTE MmFirstFreeSystemPte[MaximumPtePoolTypes]
 

Definition at line 4742 of file mi.h.

Referenced by MiInitializeSystemPtes(), MiReleaseSystemPtes(), and MiReserveSystemPtes2().

PMMPTE MmFirstReservedMappingPte
 

Definition at line 4616 of file mi.h.

Referenced by MiInitMachineDependent(), and MiMapPageInHyperSpace().

ULONG MmFlushCounter
 

Definition at line 4696 of file mi.h.

Referenced by MiFlushPteList(), MiInitializeSystemPtes(), MiReleaseSystemPtes(), and MiReserveSystemPtes().

PFN_NUMBER MmFreeGoal
 

Definition at line 5120 of file mi.h.

Referenced by MiCheckAndSetSystemTrimCriteria(), MiCheckProcessTrimCriteria(), MiGatherMappedPages(), MiModifiedPageWriterWorker(), MiResolveMappedFileFault(), and MmShutdownSystem().

MMPFNLIST MmFreePageListHead
 

Definition at line 4561 of file mi.h.

LIST_ENTRY MmFreePagingSpaceLow
 

Definition at line 5090 of file mi.h.

Referenced by MiExtendPagingFileMaximum(), MiGatherPagefilePages(), MiModifiedPageWriter(), MiUpdateModifiedWriterMdls(), and MiWriteComplete().

LARGE_INTEGER MmHalfSecond
 

Definition at line 216 of file mi.h.

Referenced by MiAllocateContiguousMemory(), MiMakeOutswappedPageResident(), MmAccessFault(), MmRemovePhysicalMemory(), and NtCreateSection().

PHARD_FAULT_NOTIFY_ROUTINE MmHardFaultNotifyRoutine
 

Definition at line 5171 of file mi.h.

Referenced by MiDispatchFault(), MmInitSystem(), and MmSetHardFaultNotifyRoutine().

SIZE_T MmHeapDeCommitFreeBlockThreshold
 

Definition at line 4686 of file mi.h.

SIZE_T MmHeapDeCommitTotalFreeThreshold
 

Definition at line 4684 of file mi.h.

SIZE_T MmHeapSegmentCommit
 

Definition at line 4682 of file mi.h.

SIZE_T MmHeapSegmentReserve
 

Definition at line 4680 of file mi.h.

PFN_NUMBER MmHiberPages
 

Definition at line 238 of file mi.h.

Referenced by MiInitMachineDependent().

PFN_NUMBER MmHighestPhysicalPage
 

Definition at line 4467 of file mi.h.

PFN_NUMBER MmHighestPossiblePhysicalPage
 

Definition at line 4473 of file mi.h.

PVOID MmHighSectionBase
 

Definition at line 4821 of file mi.h.

Referenced by MmCreateSection(), and MmInitSystem().

KEVENT MmImageMappingPteEvent
 

Definition at line 4846 of file mi.h.

Referenced by MiMapImageHeaderInHyperSpace(), and MmInitSystem().

ULONG MmLargePageMinimum
 

Definition at line 4367 of file mi.h.

PMMPTE MmLastReservedMappingPte
 

Definition at line 4618 of file mi.h.

Referenced by MiInitMachineDependent().

LIST_ENTRY MmLockConflictList
 

Definition at line 995 of file mi.h.

Referenced by MiCheckForUserStackOverflow(), MiInsertConflictInList(), and MmInitSystem().

SIZE_T MmLockPagesLimit
 

Definition at line 4668 of file mi.h.

Referenced by MmInitSystem(), and MmProbeAndLockPages().

ULONG MmLockPagesPercentage
 

Definition at line 4334 of file mi.h.

PFN_NUMBER MmLowestPhysicalPage
 

Definition at line 4461 of file mi.h.

ACCESS_MASK MmMakeFileAccess[8]
 

Definition at line 204 of file mi.h.

Referenced by MmCreateSection().

ULONG MmMakeProtectNotWriteCopy[32]
 

Definition at line 202 of file mi.h.

ACCESS_MASK MmMakeSectionAccess[8]
 

Definition at line 203 of file mi.h.

Referenced by NtMapViewOfSection().

MMMOD_WRITER_LISTHEAD MmMappedFileHeader
 

Definition at line 5081 of file mi.h.

Referenced by MiGatherMappedPages(), MiModifiedPageWriter(), and MiModifiedPageWriterWorker().

KEVENT MmMappedFileIoComplete
 

Definition at line 4610 of file mi.h.

Referenced by MiCleanSection(), MiWriteComplete(), MmInitSystem(), and MmPurgeSection().

PMMMOD_WRITER_MDL_ENTRY MmMappedFileMdl[MM_MAPPED_FILE_MDLS]
 

Definition at line 5088 of file mi.h.

Referenced by MiModifiedPageWriter().

ULONG MmMaxAdditionNonPagedPoolPerMb
 

Definition at line 4644 of file mi.h.

Referenced by MiInitMachineDependent().

ULONG MmMaximumDeadKernelStacks
 

Definition at line 4797 of file mi.h.

Referenced by MmDeleteKernelStack(), and MmInitSystem().

SIZE_T MmMaximumNonPagedPoolInBytes
 

Definition at line 4648 of file mi.h.

SIZE_T MmMaxUnusedSegmentNonPagedPoolUsage
 

Definition at line 4957 of file mi.h.

Referenced by MiCheckControlArea(), MiRemoveUnusedSegments(), and MmInitSystem().

SIZE_T MmMaxUnusedSegmentPagedPoolUsage
 

Definition at line 4950 of file mi.h.

Referenced by MiCheckControlArea(), MiRemoveUnusedSegments(), and MmInitSystem().

ULONG MmMinAdditionNonPagedPoolPerMb
 

Definition at line 4642 of file mi.h.

Referenced by MiInitMachineDependent().

ULONG MmMinimumFreeDiskSpace
 

Definition at line 5128 of file mi.h.

Referenced by MiAttemptPageFileExtension().

PFN_NUMBER MmMinimumFreePages
 

Definition at line 5118 of file mi.h.

Referenced by MiCheckAndSetSystemTrimCriteria(), MiCheckSystemTrimEndCriteria(), MiRemovePageByColor(), MiRemovePageFromList(), MiUnlinkFreeOrZeroedPage(), MiUnlinkPageFromList(), MmInitSystem(), and MmWorkingSetManager().

PFN_NUMBER MmMinimumFreePagesToZero
 

Definition at line 4604 of file mi.h.

Referenced by MiInsertPageInList().

SIZE_T MmMinimumNonPagedPoolSize
 

Definition at line 4638 of file mi.h.

Referenced by MiInitMachineDependent().

ULONG MmMinimumPageFileReduction
 

Definition at line 5132 of file mi.h.

Referenced by MiAttemptPageFileReduction(), and MiContractPagingFiles().

PFN_NUMBER MmMinimumWorkingSetSize
 

Definition at line 5152 of file mi.h.

Referenced by MmAdjustWorkingSetSize().

MMPFNLIST MmModifiedNoWritePageListHead
 

Definition at line 4567 of file mi.h.

MMPFNLIST MmModifiedPageListByColor[MM_MAXIMUM_NUMBER_OF_COLORS]
 

Definition at line 4573 of file mi.h.

MMPFNLIST MmModifiedPageListHead
 

Definition at line 4565 of file mi.h.

PFN_NUMBER MmModifiedPageMaximum
 

Definition at line 5122 of file mi.h.

Referenced by MiInsertPageInList(), MmAccessFault(), MmInitSystem(), and MmWorkingSetManager().

PFN_NUMBER MmModifiedPageMinimum
 

Definition at line 5124 of file mi.h.

Referenced by MmInitSystem().

KEVENT MmModifiedPageWriterEvent
 

Definition at line 5096 of file mi.h.

Referenced by MiFlushAllPages(), MiInsertPageInList(), MiModifiedPageWriterWorker(), MiObtainFreePages(), MmInitSystem(), MmShutdownSystem(), and MmWorkingSetManager().

ULONG MmModifiedWriteClusterSize
 

Definition at line 5126 of file mi.h.

Referenced by MiCleanSection(), MiFlushSectionInternal(), MiGatherMappedPages(), MiGatherPagefilePages(), MiModifiedPageWriter(), MiObtainFreePages(), MmShutdownSystem(), and NtCreatePagingFile().

ULONG MmModNoWriteInsert
 

Definition at line 4575 of file mi.h.

Referenced by MiGatherMappedPages(), MiModifiedPageWriterWorker(), and MiObtainFreePages().

PFN_NUMBER MmMoreThanEnoughFreePages
 

Definition at line 4486 of file mi.h.

Referenced by MiCheckAndSetSystemTrimCriteria(), MiCheckProcessTrimCriteria(), MiDoReplacement(), MiModifiedPageWriterWorker(), MmAccessFault(), MmInitSystem(), and MmSetMemoryPriorityProcess().

ULONG MmMustSucceedPoolBitPosition
 

Definition at line 4660 of file mi.h.

Referenced by MiFreePoolPages(), and MiInitializeNonPagedPool().

PVOID MmNonPagedMustSucceed
 

Definition at line 4710 of file mi.h.

Referenced by MiAllocatePoolPages(), MiFreePoolPages(), MiInitializeNonPagedPool(), and MiInitMachineDependent().

PVOID MmNonPagedPoolEnd
 

Definition at line 4704 of file mi.h.

PVOID MmNonPagedPoolExpansionStart
 

Definition at line 4654 of file mi.h.

Referenced by MiAllocatePoolPages(), MiFreePoolPages(), MiInitializeNonPagedPool(), MiInitMachineDependent(), and MmAccessFault().

LIST_ENTRY MmNonPagedPoolFreeListHead[MI_MAX_FREE_LIST_HEADS]
 

Definition at line 4690 of file mi.h.

Referenced by MiAllocatePoolPages(), MiFindContiguousMemory(), MiFreePoolPages(), MiInitializeNonPagedPool(), and MmSetKernelDumpRange().

PVOID MmNonPagedPoolStart
 

Definition at line 4702 of file mi.h.

PVOID MmNonPagedSystemStart
 

Definition at line 4626 of file mi.h.

ULONG MmNumberDeadKernelStacks
 

Definition at line 4796 of file mi.h.

Referenced by MmCreateKernelStack(), and MmDeleteKernelStack().

ULONG MmNumberOfActiveMdlEntries
 

Definition at line 5092 of file mi.h.

Referenced by MiGatherPagefilePages(), MiInsertPageFileInList(), MiReleasePageFileSpace(), MiUpdateModifiedWriterMdls(), and MiWriteComplete().

PFN_NUMBER MmNumberOfFreeNonPagedPool
 

Definition at line 4658 of file mi.h.

Referenced by MiAllocatePoolPages(), MiFindContiguousMemory(), MiFreePoolPages(), and MiInitializeNonPagedPool().

ULONG MmNumberOfPagingFiles
 

Definition at line 5094 of file mi.h.

PFN_COUNT MmNumberOfPhysicalPages
 

Definition at line 4455 of file mi.h.

ULONG MmNumberOfSystemPtes
 

Definition at line 4662 of file mi.h.

LARGE_INTEGER MmOneSecond
 

Definition at line 213 of file mi.h.

Referenced by MiFlushSectionInternal(), MiIssuePageExtendRequest(), and MiMapImageHeaderInHyperSpace().

SIZE_T MmOverCommit
 

Definition at line 5110 of file mi.h.

PVOID MmPageAlignedPoolBase[2]
 

Definition at line 4732 of file mi.h.

Referenced by MiAllocatePoolPages(), MiBuildPagedPool(), MiFreePoolPages(), and MiInitMachineDependent().

PMMPTE MmPagedPoolBasePde
 

Definition at line 4678 of file mi.h.

Referenced by MiBuildPagedPool().

PVOID MmPagedPoolEnd
 

Definition at line 4708 of file mi.h.

MM_PAGED_POOL_INFO MmPagedPoolInfo
 

Definition at line 4730 of file mi.h.

PVOID MmPagedPoolStart
 

Definition at line 4706 of file mi.h.

PPAGE_FAULT_NOTIFY_ROUTINE MmPageFaultNotifyRoutine
 

Definition at line 5170 of file mi.h.

Referenced by MmAccessFault(), MmInitSystem(), and MmSetPageFaultNotifyRoutine().

FAST_MUTEX MmPageFileCreationLock
 

Definition at line 4860 of file mi.h.

Referenced by MmInitSystem(), and NtCreatePagingFile().

ULONG MmPageFileExtension
 

Definition at line 5130 of file mi.h.

Referenced by MiAttemptPageFileExtension().

PMMPFNLIST MmPageLocationList[NUMBER_OF_PAGE_LISTS]
 

Definition at line 4571 of file mi.h.

Referenced by MiCleanSection(), MiDecommitPages(), MiDecrementCloneBlockReference(), MiDecrementReferenceCount(), MiDeletePte(), MiDeleteSystemPagableVm(), MiDispatchFault(), MiFreeInitializationCode(), MiGatherMappedPages(), MiInitMachineDependent(), MiInsertPageInList(), MiPurgeImageSection(), MiRemovePageByColor(), MiRemovePhysicalPages(), MiResetVirtualMemory(), MiResolveTransitionFault(), MiSegmentDelete(), MiUnlinkFreeOrZeroedPage(), MiUnlinkPageFromList(), MmAddPhysicalMemory(), MmAllocatePagesForMdl(), MmDeleteProcessAddressSpace(), MmFreeLoaderBlock(), MmPurgeSection(), MmRemovePhysicalMemory(), and MmZeroPageThread().

PFN_NUMBER MmPagesAboveWsMaximum
 

Definition at line 4513 of file mi.h.

PFN_NUMBER MmPagesAboveWsMinimum
 

Definition at line 4506 of file mi.h.

Referenced by MiAddWorkingSetPage(), MiCheckAndSetSystemTrimCriteria(), MiFreeWsle(), MiLocateAndReserveWsle(), MiObtainFreePages(), MiReleaseWsle(), MmAdjustWorkingSetSize(), and MmCleanProcessAddressSpace().

PFN_NUMBER MmPagesAboveWsThreshold
 

Definition at line 4520 of file mi.h.

Referenced by MiObtainFreePages().

PMMPAGING_FILE MmPagingFile[MAX_PAGE_FILES]
 

Definition at line 5083 of file mi.h.

Referenced by MiAttemptPageFileExtension(), MiAttemptPageFileReduction(), MiCheckForCrashDump(), MiContractPagingFiles(), MiExtendPagingFileMaximum(), MiExtendPagingFiles(), MiInsertPageFileInList(), MiMakeOutswappedPageResident(), MiModifiedPageWriterWorker(), MiPageFileFull(), MiReleasePageFileSpace(), MiResolvePageFileFault(), MiUpdateModifiedWriterMdls(), MmGetPageFileInformation(), MmShutdownSystem(), and NtCreatePagingFile().

PKEVENT MmPagingFileCreated
 

Definition at line 4866 of file mi.h.

ULONG_PTR MmPagingFileDebug[]
 

Definition at line 4872 of file mi.h.

Referenced by MiCheckForCrashDump(), MiGatherPagefilePages(), MiReleasePageFileSpace(), MiResolvePageFileFault(), and MiWriteComplete().

MMMOD_WRITER_LISTHEAD MmPagingFileHeader
 

Definition at line 5079 of file mi.h.

Referenced by MiGatherPagefilePages(), MiInsertPageFileInList(), MiModifiedPageWriter(), MiModifiedPageWriterWorker(), MiUpdateModifiedWriterMdls(), MiWriteComplete(), and NtCreatePagingFile().

SIZE_T MmPeakCommitment
 

Definition at line 3982 of file mi.h.

PMMPFN MmPfnDatabase
 

Definition at line 4557 of file mi.h.

KSPIN_LOCK MmPfnLock
 

Definition at line 4880 of file mi.h.

ULONG MmProcessColorSeed
 

Definition at line 4921 of file mi.h.

Referenced by MmCreateProcessAddressSpace().

LOGICAL MmProtectFreedNonPagedPool
 

Definition at line 4076 of file mi.h.

ULONG MmProtectToPteMask[32]
 

Definition at line 201 of file mi.h.

Referenced by MiInitMachineDependent().

ULONG MmProtectToValue[32]
 

Definition at line 200 of file mi.h.

SPFN_NUMBER MmResidentAvailablePages
 

Definition at line 4499 of file mi.h.

SIZE_T MmResTrack[MM_BUMP_COUNTER_MAX]
 

Definition at line 5164 of file mi.h.

ULONG MmSecondaryColors
 

Definition at line 4919 of file mi.h.

FAST_MUTEX MmSectionBasedMutex
 

Definition at line 4833 of file mi.h.

Referenced by MiMapViewOfDataSection(), MiRemoveMappedView(), MiSectionDelete(), MmCreateSection(), MmExtendSection(), and MmInitSystem().

PMMADDRESS_NODE MmSectionBasedRoot
 

Definition at line 4819 of file mi.h.

Referenced by MiFindEmptySectionBaseDown(), MiInsertBasedSection(), MiRemoveBasedSection(), MiSectionInitialization(), and MmCreateSection().

FAST_MUTEX MmSectionCommitMutex
 

Definition at line 4827 of file mi.h.

Referenced by MiCreateImageFileMap(), MiCreatePagingFileMap(), MiMapViewOfDataSection(), MiProtectVirtualMemory(), MiSegmentDelete(), MmInitSystem(), and NtAllocateVirtualMemory().

ERESOURCE MmSectionExtendResource
 

Definition at line 4839 of file mi.h.

Referenced by MmExtendSection(), and MmInitSystem().

ERESOURCE MmSectionExtendSetResource
 

Definition at line 4840 of file mi.h.

Referenced by MmExtendSection(), and MmInitSystem().

MMSESSION MmSession
 

Definition at line 2642 of file mi.h.

Referenced by MiInitializeSystemSpaceMap(), MiLoadSystemImage(), MiMapViewInSystemSpace(), MiUnmapViewInSystemSpace(), MmMapViewInSessionSpace(), MmMapViewInSystemSpace(), MmUnmapViewInSessionSpace(), and MmUnmapViewInSystemSpace().

ULONG_PTR MmSessionBase
 

Definition at line 5211 of file mi.h.

Referenced by MiAllocatePoolPages(), MiAttachSession(), MiDereferenceSession(), MiDetachSession(), MiInitMachineDependent(), MiSessionCommitPageTables(), MiSessionCreateInternal(), MmInitSystem(), and MmSessionCreate().

ULONG MmSessionFailureCauses[MM_SESSION_FAILURE_CAUSES]
 

Definition at line 5378 of file mi.h.

PMM_SESSION_SPACE MmSessionSpace
 

Definition at line 5609 of file mi.h.

Referenced by MiAddValidPageToWorkingSet(), MiAddWorkingSetPage(), MiAddWsleHash(), MiAllocatePoolPages(), MiCheckPdeForSessionSpace(), MiCheckSessionPoolAllocations(), MiCheckVirtualAddress(), MiDeleteSystemPagableVm(), MiDereferenceSession(), MiDetachSession(), MiFreePoolPages(), MiFreeSessionPoolBitMaps(), MiFreeSessionSpaceMap(), MiInitializeSessionPool(), MiInsertWsle(), MiLoadImageSection(), MiLoadSystemImage(), MiLockCode(), MiRemoveImageSessionWide(), MiResolveMappedFileFault(), MiResolvePageFileFault(), MiSessionAddProcess(), MiSessionCommitImagePages(), MiSessionCommitPageTables(), MiSessionCopyOnWrite(), MiSessionCreateInternal(), MiSessionInitializeWorkingSetList(), MiSessionInsertImage(), MiSessionInSwapProcess(), MiSessionLookupImage(), MiSessionOutSwapProcess(), MiSessionPoolAllocated(), MiSessionPoolFreed(), MiSessionPoolVector(), MiSessionRemoveImage(), MiSessionRemoveProcess(), MiSessionUnloadAllImages(), MiSessionWideReserveImageAddress(), MiSetPagingOfDriver(), MiShareSessionImage(), MiUnmapViewInSystemSpace(), MiUpdateWsle(), MmAccessFault(), MmCreateProcessAddressSpace(), MmInitSystem(), MmMapViewInSessionSpace(), MmResourcesAvailable(), MmSessionCreate(), MmSessionDelete(), MmSessionSetUnloadAddress(), MmUnloadSystemImage(), MmUnmapViewInSessionSpace(), and MmWorkingSetManager().

LARGE_INTEGER MmSevenMinutes
 

Definition at line 211 of file mi.h.

Referenced by MiEnsureAvailablePageOrWait().

SIZE_T MmSharedCommit
 

Definition at line 5112 of file mi.h.

LARGE_INTEGER MmShortTime
 

Definition at line 215 of file mi.h.

Referenced by MiCheckControlAreaStatus(), MiCheckSystemTrimEndCriteria(), MiCleanSection(), MiCloneProcessAddressSpace(), MiDispatchFault(), MiEmptyWorkingSet(), MiModifiedPageWriterWorker(), MiPurgeImageSection(), MiRemoveUnusedSegments(), MiResolveProtoPteFault(), MmAccessFault(), MmCopyToCachedPage(), MmFlushSection(), MmFlushVirtualMemory(), MmGetSystemRoutineAddress(), and MmWorkingSetManager().

PFN_NUMBER MmSizeOfNonPagedMustSucceed
 

Definition at line 4652 of file mi.h.

Referenced by MiInitializeNonPagedPool(), and MiInitMachineDependent().

SIZE_T MmSizeOfNonPagedPoolInBytes
 

Definition at line 4636 of file mi.h.

SIZE_T MmSizeOfPagedPoolInBytes
 

Definition at line 4646 of file mi.h.

LOGICAL MmSnapUnloads
 

Definition at line 2683 of file mi.h.

MMPFNLIST MmStandbyPageListHead
 

Definition at line 4563 of file mi.h.

ULONG_PTR MmSubsectionBase
 

Definition at line 4434 of file mi.h.

ULONG_PTR MmSubsectionTopPage
 

Definition at line 4436 of file mi.h.

Referenced by MiAllocatePoolPages(), and MiInitMachineDependent().

PRTL_BITMAP MmSystemCacheAllocationMap
 

Definition at line 4760 of file mi.h.

PVOID MmSystemCacheEnd
 

Definition at line 4758 of file mi.h.

PRTL_BITMAP MmSystemCacheEndingMap
 

Definition at line 4762 of file mi.h.

PVOID MmSystemCacheStart
 

Definition at line 4756 of file mi.h.

PMMWSL MmSystemCacheWorkingSetList
 

Definition at line 4752 of file mi.h.

Referenced by MiDeleteSystemPagableVm(), MiInitializeSystemCache(), MiInsertWsle(), MiLockCode(), MiRemoveWsle(), MiUpdateWsle(), MmCheckCachedPageState(), MmCopyToCachedPage(), MmInitSystem(), MmUnmapViewInSystemCache(), and MmWorkingSetManager().

PMMWSLE MmSystemCacheWsle
 

Definition at line 4754 of file mi.h.

Referenced by MiAddValidPageToWorkingSet(), MiEliminateWorkingSetEntry(), MiInitializeSystemCache(), MiUpdateWsle(), MmCheckCachedPageState(), and MmCopyToCachedPage().

PFN_NUMBER MmSystemCacheWsMaximum
 

Definition at line 4766 of file mi.h.

Referenced by MiInitializeSystemCache(), and MmInitSystem().

PFN_NUMBER MmSystemCacheWsMinimum
 

Definition at line 4764 of file mi.h.

Referenced by MiInitializeSystemCache(), and MmInitSystem().

KMUTANT MmSystemLoadLock
 

Definition at line 928 of file mi.h.

Referenced by MiLoadSystemImage(), MiLookupPsLoadedModule(), MmAddVerifierThunks(), MmGetVerifierInformation(), MmInitSystem(), MmSetVerifierInformation(), and MmUnloadSystemImage().

PETHREAD MmSystemLockOwner
 

Definition at line 996 of file mi.h.

Referenced by MiEmptyWorkingSet(), MiEnsureAvailablePageOrWait(), MmAccessFault(), MmTrimAllSystemPagableMemory(), and MmWorkingSetManager().

PFN_NUMBER MmSystemLockPagesCount
 

Definition at line 1371 of file mi.h.

Referenced by MmMapLockedPagesSpecifyCache(), and MmProbeAndLockPages().

ULONG MmSystemPageColor
 

Definition at line 4917 of file mi.h.

Referenced by MiResolveDemandZeroFault().

ULONG MmSystemPageDirectory
 

Definition at line 4673 of file mi.h.

Referenced by MiAllocatePoolPages(), MiBuildPagedPool(), and MiFillSystemPageDirectory().

PMMPTE MmSystemPagePtes
 

Definition at line 4670 of file mi.h.

Referenced by MiAllocatePoolPages(), MiBuildPagedPool(), MiCheckPdeForPagedPool(), MiFillSystemPageDirectory(), and MiRemoveMappedPtes().

PFN_NUMBER MmSystemProcessWorkingSetMax
 

Definition at line 5150 of file mi.h.

Referenced by MiInitMachineDependent().

PFN_NUMBER MmSystemProcessWorkingSetMin
 

Definition at line 5148 of file mi.h.

Referenced by MiInitMachineDependent().

PMMPTE MmSystemPteBase
 

Definition at line 4806 of file mi.h.

Referenced by MiAllocateSpecialPool(), MiInitializeSpecialPool(), MiInitializeSystemPtes(), MiReleaseSystemPtes(), MiReserveSystemPtes(), MiReserveSystemPtes2(), and MmFreeSpecialPool().

KSPIN_LOCK MmSystemSpaceLock
 

Definition at line 4893 of file mi.h.

PCHAR MmSystemSpaceViewStart
 

Definition at line 4628 of file mi.h.

ERESOURCE MmSystemWsLock
 

Definition at line 4887 of file mi.h.

Referenced by MiEmptyWorkingSet(), MmInitSystem(), MmTrimAllSystemPagableMemory(), and MmWorkingSetManager().

SIZE_T MmTotalCommitLimit
 

Definition at line 5108 of file mi.h.

SIZE_T MmTotalCommitLimitMaximum
 

Definition at line 3984 of file mi.h.

SIZE_T MmTotalCommittedPages
 

Definition at line 5106 of file mi.h.

ULONG MmTotalFreeSystemPtes[MaximumPtePoolTypes]
 

Definition at line 4666 of file mi.h.

LOGICAL MmTrackLockedPages
 

Definition at line 2675 of file mi.h.

LOGICAL MmTrackPtes
 

Definition at line 4079 of file mi.h.

LARGE_INTEGER MmTwentySeconds
 

Definition at line 214 of file mi.h.

Referenced by MiIssuePageExtendRequest(), and MmShutdownSystem().

KEVENT MmUnusedSegmentCleanup
 

Definition at line 4948 of file mi.h.

Referenced by MiAllocatePoolPages(), MiCheckControlArea(), MiDereferenceSegmentThread(), MiSectionInitialization(), and MmResourcesAvailable().

ULONG MmUnusedSegmentCount
 

Definition at line 4966 of file mi.h.

Referenced by MiRemoveUnusedSegments().

LIST_ENTRY MmUnusedSegmentList
 

Definition at line 4946 of file mi.h.

Referenced by MiAllocatePoolPages(), MiCheckControlArea(), MiRemoveUnusedSegments(), MiSectionInitialization(), and MmResourcesAvailable().

SIZE_T MmUnusedSegmentNonPagedPoolReduction
 

Definition at line 4962 of file mi.h.

Referenced by MiRemoveUnusedSegments(), and MmInitSystem().

SIZE_T MmUnusedSegmentNonPagedPoolUsage
 

Definition at line 4959 of file mi.h.

Referenced by MiCheckControlArea(), and MiRemoveUnusedSegments().

SIZE_T MmUnusedSegmentPagedPoolReduction
 

Definition at line 4955 of file mi.h.

Referenced by MiRemoveUnusedSegments(), and MmInitSystem().

SIZE_T MmUnusedSegmentPagedPoolUsage
 

Definition at line 4952 of file mi.h.

Referenced by MiCheckControlArea(), and MiRemoveUnusedSegments().

ULONG MmUnusedSegmentTrimLevel
 

Definition at line 4964 of file mi.h.

MM_DRIVER_VERIFIER_DATA MmVerifierData
 

Definition at line 4197 of file mi.h.

WCHAR MmVerifyDriverBuffer[]
 

Definition at line 4070 of file mi.h.

ULONG MmVerifyDriverBufferLength
 

Definition at line 4071 of file mi.h.

ULONG MmVerifyDriverLevel
 

Definition at line 4072 of file mi.h.

PMMVAD MmVirtualAddressDescriptorRoot
 

Definition at line 4817 of file mi.h.

MMWORKING_SET_EXPANSION_HEAD MmWorkingSetExpansionHead
 

Definition at line 5071 of file mi.h.

Referenced by MiEmptyAllWorkingSetsWorker(), MiInitializeSystemCache(), MiRearrangeWorkingSetExpansionList(), MiSessionAddProcess(), MmAllowWorkingSetExpansion(), MmInitSystem(), MmInSwapProcess(), MmTrimAllSystemPagableMemory(), and MmWorkingSetManager().

PMMWSL MmWorkingSetList
 

Definition at line 442 of file miglobal.c.

Referenced by MiCloneProcessAddressSpace(), MiCopyOnWrite(), MiDecommitPages(), MiDeleteAddressesInWorkingSet(), MiDeletePte(), MiEmptyAllWorkingSetsWorker(), MiGetPageProtection(), MiGetWorkingSetInfo(), MiInitializeWorkingSetList(), MiInitMachineDependent(), MiInsertVad(), MiInsertWsle(), MiMapImageHeaderInHyperSpace(), MiReturnPageTablePageCommitment(), MiSetProtectionOnSection(), MiUnmapImageHeaderInHyperSpace(), MmAccessFault(), MmCleanProcessAddressSpace(), MmCreateProcessAddressSpace(), MmInitializeProcessAddressSpace(), MmInSwapProcess(), MmOutSwapProcess(), MmSetMemoryPriorityProcess(), MmWorkingSetManager(), NtLockVirtualMemory(), NtUnlockVirtualMemory(), and PspCreateProcess().

LARGE_INTEGER MmWorkingSetProtectionTime
 

Definition at line 212 of file mi.h.

Referenced by MiCheckProcessTrimCriteria().

PFN_NUMBER MmWorkingSetSizeExpansion
 

Definition at line 4533 of file mi.h.

Referenced by MiDoReplacement().

PFN_NUMBER MmWorkingSetSizeIncrement
 

Definition at line 4527 of file mi.h.

Referenced by MiDoReplacement().

PFN_NUMBER MmWsAdjustThreshold
 

Definition at line 4540 of file mi.h.

Referenced by MiDoReplacement().

PFN_NUMBER MmWsExpandThreshold
 

Definition at line 4547 of file mi.h.

Referenced by MiDoReplacement().

PMMWSLE MmWsle
 

Definition at line 444 of file miglobal.c.

Referenced by MiAddValidPageToWorkingSet(), MiCloneProcessAddressSpace(), MiCopyOnWrite(), MiDecommitPages(), MiDeleteAddressesInWorkingSet(), MiDeletePte(), MiEliminateWorkingSetEntry(), MiGetPageProtection(), MiGetWorkingSetInfo(), MiInitializeCopyOnWritePfn(), MiInitializeWorkingSetList(), MiInitMachineDependent(), MiSetProtectionOnSection(), MiUpdateWsle(), MmCleanProcessAddressSpace(), NtLockVirtualMemory(), and NtUnlockVirtualMemory().

PFN_NUMBER MmWsTrimReductionGoal
 

Definition at line 4553 of file mi.h.

MMPFNLIST MmZeroedPageListHead
 

Definition at line 4559 of file mi.h.

KEVENT MmZeroingPageEvent
 

Definition at line 4589 of file mi.h.

Referenced by MiInsertPageInList(), MmInitSystem(), and MmZeroPageThread().

BOOLEAN MmZeroingPageThreadActive
 

Definition at line 4598 of file mi.h.

Referenced by MiInsertPageInList(), MmInitSystem(), and MmZeroPageThread().

MMPTE NoAccessPte
 

Definition at line 4432 of file mi.h.

MMPTE PrototypePte
 

Definition at line 4430 of file mi.h.

MMPTE TransitionPde
 

Definition at line 4428 of file mi.h.

MMPTE ValidKernelPde
 

Definition at line 4412 of file mi.h.

MMPTE ValidKernelPdeLocal
 

Definition at line 4414 of file mi.h.

MMPTE ValidKernelPte
 

Definition at line 4410 of file mi.h.

MMPTE ValidKernelPteLocal
 

Definition at line 4408 of file mi.h.

MMPTE ValidPdePde
 

Definition at line 4420 of file mi.h.

MMPTE ValidPtePte
 

Definition at line 4418 of file mi.h.

MMPTE ValidUserPte
 

Definition at line 4416 of file mi.h.

PRTL_BITMAP VerifierLargePagedPoolMap
 

Definition at line 4734 of file mi.h.

Referenced by MiAllocatePoolPages(), MiBuildPagedPool(), and MiFreePoolPages().

MMPTE ZeroKernelPte
 

Definition at line 4406 of file mi.h.

MMPTE ZeroPte
 

Definition at line 4404 of file mi.h.


Generated on Sat May 15 19:44:42 2004 for test by doxygen 1.3.7