PGMInternal.h revision fd5e233320b7b83463ab52fd1182b95ba89d5c65
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * PGM - Internal header file.
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * Copyright (C) 2006-2007 Sun Microsystems, Inc.
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * available from http://www.virtualbox.org. This file is free software;
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * you can redistribute it and/or modify it under the terms of the GNU
c58f1213e628a545081c70e26c6b67a841cff880vboxsync * General Public License (GPL) as published by the Free Software
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
82bcaaf8077ba892f39afb721dca149353c63d2cvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
82bcaaf8077ba892f39afb721dca149353c63d2cvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
82bcaaf8077ba892f39afb721dca149353c63d2cvboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
82bcaaf8077ba892f39afb721dca149353c63d2cvboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
82bcaaf8077ba892f39afb721dca149353c63d2cvboxsync * additional information or have any questions.
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync/** @defgroup grp_pgm_int Internals
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * @ingroup grp_pgm
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * @internal
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync/** @name PGM Compile Time Config
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * Solve page is out of sync issues inside Guest Context (in PGMGC.cpp).
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * Comment it if it will break something.
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * Check and skip global PDEs for non-global flushes
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * Sync N pages instead of a whole page table
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * Number of pages to sync during a page fault
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * When PGMPOOL_WITH_GCPHYS_TRACKING is enabled using high values here
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * causes a lot of unnecessary extents and also is slower than taking more \#PFs.
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * Number of PGMPhysRead/Write cache entries (must be <= sizeof(uint64_t))
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync#define PGM_MAX_PHYSCACHE_ENTRIES_MASK (PGM_MAX_PHYSCACHE_ENTRIES-1)
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * Enable caching of PGMR3PhysRead/WriteByte/Word/Dword
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync/** @def PGMPOOL_WITH_CACHE
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * Enable agressive caching using the page pool.
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * This requires PGMPOOL_WITH_USER_TRACKING and PGMPOOL_WITH_MONITORING.
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync/** @def PGMPOOL_WITH_MIXED_PT_CR3
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * When defined, we'll deal with 'uncachable' pages.
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync/** @def PGMPOOL_WITH_MONITORING
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * Monitor the guest pages which are shadowed.
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * When this is enabled, PGMPOOL_WITH_CACHE or PGMPOOL_WITH_GCPHYS_TRACKING must
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * be enabled as well.
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * @remark doesn't really work without caching now. (Mixed PT/CR3 change.)
ff1ea1a768f003a41f4b02f742060708e633819avboxsync/** @def PGMPOOL_WITH_GCPHYS_TRACKING
ff1ea1a768f003a41f4b02f742060708e633819avboxsync * Tracking the of shadow pages mapping guest physical pages.
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * This is very expensive, the current cache prototype is trying to figure out
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * whether it will be acceptable with an agressive caching policy.
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync#if defined(PGMPOOL_WITH_CACHE) || defined(PGMPOOL_WITH_MONITORING)
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync/** @def PGMPOOL_WITH_USER_TRACKING
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * Tracking users of shadow pages. This is required for the linking of shadow page
49e18d6e5fc87bd475db9dcacbfee7c98e2d1b30vboxsync * tables and physical guest addresses.
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync#if defined(PGMPOOL_WITH_GCPHYS_TRACKING) || defined(PGMPOOL_WITH_CACHE) || defined(PGMPOOL_WITH_MONITORING)
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync/** @def PGMPOOL_CFG_MAX_GROW
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * The maximum number of pages to add to the pool in one go.
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync/** @def VBOX_STRICT_PGM_HANDLER_VIRTUAL
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * Enables some extra assertions for virtual handlers (mainly phys2virt related).
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync/** @name PDPT and PML4 flags.
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * These are placed in the three bits available for system programs in
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * the PDPT and PML4 entries.
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync/** The entry is a permanent one and it's must always be present.
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * Never free such an entry. */
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync/** Mapping (hypervisor allocated pagetable). */
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync/** @name Page directory flags.
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * These are placed in the three bits available for system programs in
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * the page directory entries.
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync/** Mapping (hypervisor allocated pagetable). */
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync/** Made read-only to facilitate dirty bit tracking. */
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync/** @name Page flags.
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * These are placed in the three bits available for system programs in
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * the page entries.
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync/** Made read-only to facilitate dirty bit tracking. */
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync/** Scanned and approved by CSAM (tm).
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * NOTE: Must be identical to the one defined in CSAMInternal.h!!
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * @todo Move PGM_PTFLAGS_* and PGM_PDFLAGS_* to VBox/pgm.h. */
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync/** @name Defines used to indicate the shadow and guest paging in the templates.
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync/** Macro for checking if the guest is using paging.
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * @param uGstType PGM_TYPE_*
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * @param uShwType PGM_TYPE_*
ebe394fa0ecbdea5feff1a5edfc2e17a2ccfbd25vboxsync * @remark ASSUMES certain order of the PGM_TYPE_* values.
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync/** Macro for checking if the guest supports the NX bit.
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * @param uGstType PGM_TYPE_*
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * @param uShwType PGM_TYPE_*
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * @remark ASSUMES certain order of the PGM_TYPE_* values.
ff1ea1a768f003a41f4b02f742060708e633819avboxsync/** @def PGM_HCPHYS_2_PTR
ff1ea1a768f003a41f4b02f742060708e633819avboxsync * Maps a HC physical page pool address to a virtual address.
d0e467f88aeb4288b409908dbe1b96d07c7133b2vboxsync * @returns VBox status code.
d0e467f88aeb4288b409908dbe1b96d07c7133b2vboxsync * @param pVM The VM handle.
d0e467f88aeb4288b409908dbe1b96d07c7133b2vboxsync * @param HCPhys The HC physical address to map to a virtual one.
d0e467f88aeb4288b409908dbe1b96d07c7133b2vboxsync * @param ppv Where to store the virtual address. No need to cast this.
bf7f0c7283957d64d924ab166eda258706eb7531vboxsync * @remark In GC this uses PGMGCDynMapHCPage(), so it will consume of the
1b419671a64ecb9cba31cf9350b4028de0a5db1cvboxsync * small page window employeed by that function. Be careful.
bf7f0c7283957d64d924ab166eda258706eb7531vboxsync * @remark There is no need to assert on the result.
1b419671a64ecb9cba31cf9350b4028de0a5db1cvboxsync#if defined(IN_RC) || defined(VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0)
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync/** @def PGM_GCPHYS_2_PTR
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * Maps a GC physical page address to a virtual address.
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * @returns VBox status code.
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * @param pVM The VM handle.
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * @param GCPhys The GC physical address to map to a virtual one.
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * @param ppv Where to store the virtual address. No need to cast this.
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * @remark In GC this uses PGMGCDynMapGCPage(), so it will consume of the
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * small page window employeed by that function. Be careful.
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * @remark There is no need to assert on the result.
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync#if defined(IN_RC) || defined(VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0)
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync PGMPhysGCPhys2HCPtr(pVM, GCPhys, 1 /* one page only */, (void **)(ppv)) /** @todo this isn't asserting, use PGMRamGCPhys2HCPtr! */
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync/** @def PGM_GCPHYS_2_PTR_EX
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * Maps a unaligned GC physical page address to a virtual address.
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * @returns VBox status code.
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * @param pVM The VM handle.
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * @param GCPhys The GC physical address to map to a virtual one.
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * @param ppv Where to store the virtual address. No need to cast this.
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * @remark In GC this uses PGMGCDynMapGCPage(), so it will consume of the
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * small page window employeed by that function. Be careful.
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * @remark There is no need to assert on the result.
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync#if defined(IN_RC) || defined(VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0)
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync PGMPhysGCPhys2HCPtr(pVM, GCPhys, 1 /* one page only */, (void **)(ppv)) /** @todo this isn't asserting, use PGMRamGCPhys2HCPtr! */
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync/** @def PGM_INVL_PG
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * Invalidates a page when in GC does nothing in HC.
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * @param GCVirt The virtual address of the page to invalidate.
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync# define PGM_INVL_PG(GCVirt) ASMInvalidatePage((void *)(GCVirt))
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync# define PGM_INVL_PG(GCVirt) HWACCMInvalidatePage(pVM, (RTGCPTR)(GCVirt))
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync# define PGM_INVL_PG(GCVirt) HWACCMInvalidatePage(pVM, (RTGCPTR)(GCVirt))
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync/** @def PGM_INVL_BIG_PG
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * Invalidates a 4MB page directory entry when in GC does nothing in HC.
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * @param GCVirt The virtual address within the page directory to invalidate.
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync# define PGM_INVL_BIG_PG(GCVirt) HWACCMFlushTLB(pVM)
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync# define PGM_INVL_BIG_PG(GCVirt) HWACCMFlushTLB(pVM)
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync/** @def PGM_INVL_GUEST_TLBS()
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * Invalidates all guest TLBs.
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * Structure for tracking GC Mappings.
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * This structure is used by linked list in both GC and HC.
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsynctypedef struct PGMMAPPING
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync /** Pointer to next entry. */
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync /** Pointer to next entry. */
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync /** Pointer to next entry. */
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync /** Start Virtual address. */
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync /** Last Virtual address (inclusive). */
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync /** Range size (bytes). */
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync /** Pointer to relocation callback function. */
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync /** User argument to the callback. */
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync /** Mapping description / name. For easing debugging. */
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync /** Number of page tables. */
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync#if HC_ARCH_BITS != GC_ARCH_BITS || GC_ARCH_BITS == 64
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync /** Array of page table mapping data. Each entry
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * describes one page table. The array can be longer
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * than the declared length.
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync /** The HC physical address of the page table. */
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync /** The HC physical address of the first PAE page table. */
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync /** The HC physical address of the second PAE page table. */
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync /** The HC virtual address of the 32-bit page table. */
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync /** The HC virtual address of the two PAE page table. (i.e 1024 entries instead of 512) */
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync /** The GC virtual address of the 32-bit page table. */
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync /** The GC virtual address of the two PAE page table. */
15d01c99464d6518f5cf6e7993e1357308fa12aevboxsync /** The GC virtual address of the 32-bit page table. */
15d01c99464d6518f5cf6e7993e1357308fa12aevboxsync /** The GC virtual address of the two PAE page table. */
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync/** Pointer to structure for tracking GC Mappings. */
1343c0dc573781e1f309076f3d9819915bff1705vboxsync * Physical page access handler structure.
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * This is used to keep track of physical address ranges
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * which are being monitored in some kind of way.
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync /** Access type. */
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync /** Number of pages to update. */
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync /** Pointer to R3 callback function. */
1343c0dc573781e1f309076f3d9819915bff1705vboxsync /** User argument for R3 handlers. */
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync /** Pointer to R0 callback function. */
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync /** User argument for R0 handlers. */
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync /** Pointer to GC callback function. */
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync /** User argument for RC handlers. */
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync /** Description / Name. For easing debugging. */
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync /** Profiling of this handler. */
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync/** Pointer to a physical page access handler structure. */
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * Cache node for the physical addresses covered by a virtual handler.
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync /** Core node for the tree based on physical ranges. */
ee271ac5f5a0f262528a59171392bffd9108509bvboxsync /** Offset from this struct to the PGMVIRTHANDLER structure. */
ebe394fa0ecbdea5feff1a5edfc2e17a2ccfbd25vboxsync /** Offset of the next alias relative to this one.
ee271ac5f5a0f262528a59171392bffd9108509bvboxsync * Bit 0 is used for indicating whether we're in the tree.
ee271ac5f5a0f262528a59171392bffd9108509bvboxsync * Bit 1 is used for indicating that we're the head node.
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync/** Pointer to a phys to virtual handler structure. */
abe2f4a16e43726264648542b029e782337fbc9cvboxsync/** The bit in PGMPHYS2VIRTHANDLER::offNextAlias used to indicate that the
abe2f4a16e43726264648542b029e782337fbc9cvboxsync * node is in the tree. */
abe2f4a16e43726264648542b029e782337fbc9cvboxsync/** The bit in PGMPHYS2VIRTHANDLER::offNextAlias used to indicate that the
abe2f4a16e43726264648542b029e782337fbc9cvboxsync * node is in the head of an alias chain.
abe2f4a16e43726264648542b029e782337fbc9cvboxsync * The PGMPHYS2VIRTHANDLER_IN_TREE is always set if this bit is set. */
abe2f4a16e43726264648542b029e782337fbc9cvboxsync/** The mask to apply to PGMPHYS2VIRTHANDLER::offNextAlias to get the offset. */
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * Virtual page access handler structure.
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * This is used to keep track of virtual address ranges
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * which are being monitored in some kind of way.
d0e467f88aeb4288b409908dbe1b96d07c7133b2vboxsync /** Core node for the tree based on virtual ranges. */
ebe394fa0ecbdea5feff1a5edfc2e17a2ccfbd25vboxsync /** Size of the range (in bytes). */
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync /** Number of cache pages. */
d0e467f88aeb4288b409908dbe1b96d07c7133b2vboxsync /** Access type. */
d0e467f88aeb4288b409908dbe1b96d07c7133b2vboxsync /** Pointer to the RC callback function. */
ebe394fa0ecbdea5feff1a5edfc2e17a2ccfbd25vboxsync /** Pointer to the R3 callback function for invalidation. */
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync /** Pointer to the R3 callback function. */
ff1ea1a768f003a41f4b02f742060708e633819avboxsync /** Description / Name. For easing debugging. */
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync /** Profiling of this handler. */
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync /** Array of cached physical addresses for the monitored ranged. */
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync PGMPHYS2VIRTHANDLER aPhysToVirt[HC_ARCH_BITS == 32 ? 1 : 2];
d0e467f88aeb4288b409908dbe1b96d07c7133b2vboxsync/** Pointer to a virtual page access handler structure. */
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * Page type.
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * @remarks This enum has to fit in a 3-bit field (see PGMPAGE::u3Type).
ebe394fa0ecbdea5feff1a5edfc2e17a2ccfbd25vboxsync * @todo convert to \#defines.
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync /** The usual invalid zero entry. */
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync /** RAM page. (RWX) */
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync /** MMIO2 page. (RWX) */
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync /** Shadowed ROM. (RWX) */
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync /** ROM page. (R-X) */
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync /** MMIO page. (---) */
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync /** End of valid entries. */
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync/** @name Page type predicates.
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync#define PGMPAGETYPE_IS_READABLE(type) ( (type) <= PGMPAGETYPE_ROM )
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync#define PGMPAGETYPE_IS_WRITEABLE(type) ( (type) <= PGMPAGETYPE_ROM_SHADOW )
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync#define PGMPAGETYPE_IS_RWX(type) ( (type) <= PGMPAGETYPE_ROM_SHADOW )
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync#define PGMPAGETYPE_IS_ROX(type) ( (type) == PGMPAGETYPE_ROM )
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync#define PGMPAGETYPE_IS_NP(type) ( (type) == PGMPAGETYPE_MMIO )
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * A Physical Guest Page tracking structure.
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * The format of this structure is complicated because we have to fit a lot
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * of information into as few bits as possible. The format is also subject
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * to change (there is one comming up soon). Which means that for we'll be
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * using PGM_PAGE_GET_*, PGM_PAGE_IS_ and PGM_PAGE_SET_* macros for *all*
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * accessess to the structure.
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsynctypedef struct PGMPAGE
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync /** The physical address and a whole lot of other stuff. All bits are used! */
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync /** The page state. */
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync /** Flag indicating that a write monitored page was written to when set. */
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync /** For later. */
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync /** The Page ID.
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * @todo Merge with HCPhys once we've liberated HCPhys of its stuff.
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync * The HCPhys will be 100% static. */
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync /** The page type (PGMPAGETYPE). */
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync /** The physical handler state (PGM_PAGE_HNDL_PHYS_STATE*) */
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync /** The virtual handler state (PGM_PAGE_HNDL_VIRT_STATE*) */
cb4a18edeb5422163b264fe5a66276769cfe864dvboxsync/** Pointer to a physical guest page. */
#ifdef VBOX_WITH_NEW_PHYS_CODE
#define PGM_PAGE_STATE_ZERO 0
#define PGM_PAGE_SET_PAGEID(pPage, _idPage) do { (pPage)->HCPhys = (((pPage)->HCPhys) & UINT64_C(0x0000fffffffff000)) \
# define PGM_PAGE_GET_CHUNKID(pPage) ( (uint32_t)((pPage)->HCPhys >> (48 + (GMM_CHUNKID_SHIFT - 12)) )
# define PGM_PAGE_GET_CHUNKID(pPage) ( ( (uint32_t)((pPage)->HCPhys >> 48) << (12 - GMM_CHUNKID_SHIFT) ) \
#ifdef VBOX_WITH_NEW_PHYS_CODE
#define PGM_PAGE_HNDL_PHYS_STATE_NONE 0
#define PGM_PAGE_HAS_ANY_PHYSICAL_HANDLERS(pPage) ( (pPage)->u2HandlerPhysStateX != PGM_PAGE_HNDL_PHYS_STATE_NONE )
#define PGM_PAGE_HAS_ACTIVE_PHYSICAL_HANDLERS(pPage) ( (pPage)->u2HandlerPhysStateX >= PGM_PAGE_HNDL_PHYS_STATE_WRITE )
#define PGM_PAGE_HNDL_VIRT_STATE_NONE 0
#define PGM_PAGE_HAS_ANY_VIRTUAL_HANDLERS(pPage) ( (pPage)->u2HandlerVirtStateX != PGM_PAGE_HNDL_VIRT_STATE_NONE )
typedef struct PGMRAMRANGE
#ifndef VBOX_WITH_NEW_PHYS_CODE
#ifdef VBOX_WITH_NEW_PHYS_CODE
} PGMRAMRANGE;
(pRam->fFlags & MM_RAM_FLAGS_DYNAMIC_ALLOC) ? (RTHCPTR)((pRam)->paChunkR3Ptrs[(off) >> PGM_DYNAMIC_CHUNK_SHIFT] + ((off) & PGM_DYNAMIC_CHUNK_OFFSET_MASK)) \
typedef struct PGMROMPAGE
} PGMROMPAGE;
typedef struct PGMROMRANGE
} PGMROMRANGE;
typedef struct PGMMMIO2RANGE
bool fMapped;
bool fOverlapping;
* PGMPhysRead/Write cache entry
typedef struct PGMPHYSCACHEENTRY
* PGMPhysRead/Write cache to reduce REM memory access overhead
typedef struct PGMPHYSCACHE
} PGMPHYSCACHE;
typedef struct PGMCHUNKR3MAP
void *pv;
typedef struct PGMCHUNKR3MAPTLBE
#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE
typedef struct PGMCHUNKR3MAPTLB
typedef struct PGMPAGER3MAPTLBE
#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE
#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE
#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE
typedef struct PGMPAGER3MAPTLB
#ifdef IN_RC
typedef void * PPGMPAGEMAP;
typedef void ** PPPGMPAGEMAP;
#define NIL_PGMPOOL_IDX 0
typedef struct PGMPOOLUSER
#pragma pack()
typedef struct PGMPOOLPHYSEXT
#pragma pack()
typedef enum PGMPOOLKIND
PGMPOOLKIND_INVALID = 0,
} PGMPOOLKIND;
typedef struct PGMPOOLPAGE
#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE
#ifdef PGMPOOL_WITH_USER_TRACKING
#ifdef PGMPOOL_WITH_MONITORING
#ifdef PGMPOOL_WITH_CACHE
bool fZeroed;
bool fSeenNonGlobal;
bool fMonitored;
bool fCached;
bool volatile fReusedFlushPending;
bool fCR3Mix;
#ifdef PGMPOOL_WITH_CACHE
typedef struct PGMPOOL
#ifdef PGMPOOL_WITH_USER_TRACKING
#ifdef PGMPOOL_WITH_GCPHYS_TRACKING
#ifdef PGMPOOL_WITH_CACHE
bool fCacheEnabled;
#ifdef PGMPOOL_WITH_MONITORING
#ifdef VBOX_WITH_STATISTICS
# ifdef PGMPOOL_WITH_USER_TRACKING
# ifdef PGMPOOL_WITH_GCPHYS_TRACKING
# ifdef PGMPOOL_WITH_MONITORING
# ifdef PGMPOOL_WITH_CACHE
typedef struct PGMTREES
} PGMTREES;
#ifdef IN_RC
# ifdef IN_RING3
typedef struct PGMMODEDATA
DECLR3CALLBACKMEMBER(int, pfnR3ShwGetPage,(PVM pVM, RTGCPTR GCPtr, uint64_t *pfFlags, PRTHCPHYS pHCPhys));
DECLR3CALLBACKMEMBER(int, pfnR3ShwModifyPage,(PVM pVM, RTGCPTR GCPtr, size_t cbPages, uint64_t fFlags, uint64_t fMask));
DECLRCCALLBACKMEMBER(int, pfnRCShwGetPage,(PVM pVM, RTGCPTR GCPtr, uint64_t *pfFlags, PRTHCPHYS pHCPhys));
DECLRCCALLBACKMEMBER(int, pfnRCShwModifyPage,(PVM pVM, RTGCPTR GCPtr, size_t cbPages, uint64_t fFlags, uint64_t fMask));
DECLR0CALLBACKMEMBER(int, pfnR0ShwGetPage,(PVM pVM, RTGCPTR GCPtr, uint64_t *pfFlags, PRTHCPHYS pHCPhys));
DECLR0CALLBACKMEMBER(int, pfnR0ShwModifyPage,(PVM pVM, RTGCPTR GCPtr, size_t cbPages, uint64_t fFlags, uint64_t fMask));
DECLR3CALLBACKMEMBER(int, pfnR3GstGetPage,(PVM pVM, RTGCPTR GCPtr, uint64_t *pfFlags, PRTGCPHYS pGCPhys));
DECLR3CALLBACKMEMBER(int, pfnR3GstModifyPage,(PVM pVM, RTGCPTR GCPtr, size_t cbPages, uint64_t fFlags, uint64_t fMask));
DECLRCCALLBACKMEMBER(int, pfnRCGstGetPage,(PVM pVM, RTGCPTR GCPtr, uint64_t *pfFlags, PRTGCPHYS pGCPhys));
DECLRCCALLBACKMEMBER(int, pfnRCGstModifyPage,(PVM pVM, RTGCPTR GCPtr, size_t cbPages, uint64_t fFlags, uint64_t fMask));
DECLR0CALLBACKMEMBER(int, pfnR0GstGetPage,(PVM pVM, RTGCPTR GCPtr, uint64_t *pfFlags, PRTGCPHYS pGCPhys));
DECLR0CALLBACKMEMBER(int, pfnR0GstModifyPage,(PVM pVM, RTGCPTR GCPtr, size_t cbPages, uint64_t fFlags, uint64_t fMask));
DECLR3CALLBACKMEMBER(int, pfnR3BthSyncCR3,(PVM pVM, uint64_t cr0, uint64_t cr3, uint64_t cr4, bool fGlobal));
DECLR3CALLBACKMEMBER(int, pfnR3BthSyncPage,(PVM pVM, X86PDE PdeSrc, RTGCPTR GCPtrPage, unsigned cPages, unsigned uError));
DECLR3CALLBACKMEMBER(int, pfnR3BthVerifyAccessSyncPage,(PVM pVM, RTGCPTR GCPtrPage, unsigned fFlags, unsigned uError));
#ifdef VBOX_STRICT
DECLR3CALLBACKMEMBER(unsigned, pfnR3BthAssertCR3,(PVM pVM, uint64_t cr3, uint64_t cr4, RTGCPTR GCPtr, RTGCPTR cb));
DECLRCCALLBACKMEMBER(int, pfnRCBthTrap0eHandler,(PVM pVM, RTGCUINT uErr, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault));
DECLRCCALLBACKMEMBER(int, pfnRCBthSyncCR3,(PVM pVM, uint64_t cr0, uint64_t cr3, uint64_t cr4, bool fGlobal));
DECLRCCALLBACKMEMBER(int, pfnRCBthSyncPage,(PVM pVM, X86PDE PdeSrc, RTGCPTR GCPtrPage, unsigned cPages, unsigned uError));
DECLRCCALLBACKMEMBER(int, pfnRCBthVerifyAccessSyncPage,(PVM pVM, RTGCPTR GCPtrPage, unsigned fFlags, unsigned uError));
#ifdef VBOX_STRICT
DECLRCCALLBACKMEMBER(unsigned, pfnRCBthAssertCR3,(PVM pVM, uint64_t cr3, uint64_t cr4, RTGCPTR GCPtr, RTGCPTR cb));
DECLR0CALLBACKMEMBER(int, pfnR0BthTrap0eHandler,(PVM pVM, RTGCUINT uErr, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault));
DECLR0CALLBACKMEMBER(int, pfnR0BthSyncCR3,(PVM pVM, uint64_t cr0, uint64_t cr3, uint64_t cr4, bool fGlobal));
DECLR0CALLBACKMEMBER(int, pfnR0BthSyncPage,(PVM pVM, X86PDE PdeSrc, RTGCPTR GCPtrPage, unsigned cPages, unsigned uError));
DECLR0CALLBACKMEMBER(int, pfnR0BthVerifyAccessSyncPage,(PVM pVM, RTGCPTR GCPtrPage, unsigned fFlags, unsigned uError));
#ifdef VBOX_STRICT
DECLR0CALLBACKMEMBER(unsigned, pfnR0BthAssertCR3,(PVM pVM, uint64_t cr3, uint64_t cr4, RTGCPTR GCPtr, RTGCPTR cb));
typedef struct PGM
#ifndef VBOX_WITH_2X_4GB_ADDR_SPACE
#ifndef VBOX_WITH_2X_4GB_ADDR_SPACE
#ifndef VBOX_WITH_2X_4GB_ADDR_SPACE
/** The physical addresses of the guest page directories (PAE) pointed to by apGstPagePDsHC/GC. */
#ifndef VBOX_WITH_2X_4GB_ADDR_SPACE
#ifndef VBOX_WITH_2X_4GB_ADDR_SPACE
#ifndef VBOX_WITH_2X_4GB_ADDR_SPACE
DECLR3CALLBACKMEMBER(int, pfnR3ShwGetPage,(PVM pVM, RTGCPTR GCPtr, uint64_t *pfFlags, PRTHCPHYS pHCPhys));
DECLR3CALLBACKMEMBER(int, pfnR3ShwModifyPage,(PVM pVM, RTGCPTR GCPtr, size_t cbPages, uint64_t fFlags, uint64_t fMask));
DECLRCCALLBACKMEMBER(int, pfnRCShwGetPage,(PVM pVM, RTGCPTR GCPtr, uint64_t *pfFlags, PRTHCPHYS pHCPhys));
DECLRCCALLBACKMEMBER(int, pfnRCShwModifyPage,(PVM pVM, RTGCPTR GCPtr, size_t cbPages, uint64_t fFlags, uint64_t fMask));
DECLR0CALLBACKMEMBER(int, pfnR0ShwGetPage,(PVM pVM, RTGCPTR GCPtr, uint64_t *pfFlags, PRTHCPHYS pHCPhys));
DECLR0CALLBACKMEMBER(int, pfnR0ShwModifyPage,(PVM pVM, RTGCPTR GCPtr, size_t cbPages, uint64_t fFlags, uint64_t fMask));
DECLR3CALLBACKMEMBER(int, pfnR3GstGetPage,(PVM pVM, RTGCPTR GCPtr, uint64_t *pfFlags, PRTGCPHYS pGCPhys));
DECLR3CALLBACKMEMBER(int, pfnR3GstModifyPage,(PVM pVM, RTGCPTR GCPtr, size_t cbPages, uint64_t fFlags, uint64_t fMask));
DECLRCCALLBACKMEMBER(int, pfnRCGstGetPage,(PVM pVM, RTGCPTR GCPtr, uint64_t *pfFlags, PRTGCPHYS pGCPhys));
DECLRCCALLBACKMEMBER(int, pfnRCGstModifyPage,(PVM pVM, RTGCPTR GCPtr, size_t cbPages, uint64_t fFlags, uint64_t fMask));
DECLR0CALLBACKMEMBER(int, pfnR0GstGetPage,(PVM pVM, RTGCPTR GCPtr, uint64_t *pfFlags, PRTGCPHYS pGCPhys));
DECLR0CALLBACKMEMBER(int, pfnR0GstModifyPage,(PVM pVM, RTGCPTR GCPtr, size_t cbPages, uint64_t fFlags, uint64_t fMask));
DECLR3CALLBACKMEMBER(int, pfnR3BthSyncCR3,(PVM pVM, uint64_t cr0, uint64_t cr3, uint64_t cr4, bool fGlobal));
DECLR3CALLBACKMEMBER(int, pfnR3BthSyncPage,(PVM pVM, X86PDE PdeSrc, RTGCPTR GCPtrPage, unsigned cPages, unsigned uError));
DECLR3CALLBACKMEMBER(int, pfnR3BthVerifyAccessSyncPage,(PVM pVM, RTGCPTR GCPtrPage, unsigned fFlags, unsigned uError));
DECLR3CALLBACKMEMBER(unsigned, pfnR3BthAssertCR3,(PVM pVM, uint64_t cr3, uint64_t cr4, RTGCPTR GCPtr, RTGCPTR cb));
DECLR0CALLBACKMEMBER(int, pfnR0BthTrap0eHandler,(PVM pVM, RTGCUINT uErr, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault));
DECLR0CALLBACKMEMBER(int, pfnR0BthSyncCR3,(PVM pVM, uint64_t cr0, uint64_t cr3, uint64_t cr4, bool fGlobal));
DECLR0CALLBACKMEMBER(int, pfnR0BthSyncPage,(PVM pVM, X86PDE PdeSrc, RTGCPTR GCPtrPage, unsigned cPages, unsigned uError));
DECLR0CALLBACKMEMBER(int, pfnR0BthVerifyAccessSyncPage,(PVM pVM, RTGCPTR GCPtrPage, unsigned fFlags, unsigned uError));
DECLR0CALLBACKMEMBER(unsigned, pfnR0BthAssertCR3,(PVM pVM, uint64_t cr3, uint64_t cr4, RTGCPTR GCPtr, RTGCPTR cb));
DECLRCCALLBACKMEMBER(int, pfnRCBthTrap0eHandler,(PVM pVM, RTGCUINT uErr, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault));
DECLRCCALLBACKMEMBER(int, pfnRCBthSyncCR3,(PVM pVM, uint64_t cr0, uint64_t cr3, uint64_t cr4, bool fGlobal));
DECLRCCALLBACKMEMBER(int, pfnRCBthSyncPage,(PVM pVM, X86PDE PdeSrc, RTGCPTR GCPtrPage, unsigned cPages, unsigned uError));
DECLRCCALLBACKMEMBER(int, pfnRCBthVerifyAccessSyncPage,(PVM pVM, RTGCPTR GCPtrPage, unsigned fFlags, unsigned uError));
DECLRCCALLBACKMEMBER(unsigned, pfnRCBthAssertCR3,(PVM pVM, uint64_t cr3, uint64_t cr4, RTGCPTR GCPtr, RTGCPTR cb));
bool fMappingsFixed;
bool fDisableMappings;
bool fNoMorePhysWrites;
bool fPhysCacheFlushPending;
#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE
uint32_t c;
* @cfgm PGM/MaxRing3Chunks */
} ChunkR3Map;
# ifdef PGMPOOL_WITH_GCPHYS_TRACKING
STAMCOUNTER StatTrackAliased; /**< The number of times switching to cRef2, i.e. the page is being shadowed by two PTs. */
STAMCOUNTER StatTrackAliasedLots; /**< The number of times we're hitting pages which has overflowed cRef2. */
STAMCOUNTER StatR3DetectedConflicts; /**< R3: Number of times PGMR3MapHasConflicts() detected a conflict. */
STAMPROFILE StatR3ResolveConflict; /**< R3: pgmR3SyncPTResolveConflict() profiling (includes the entire relocation). */
STAMCOUNTER StatR3GuestPDWrite; /**< R3: The total number of times pgmHCGuestPDWriteHandler() was called. */
STAMCOUNTER StatR3GuestPDWriteConflict; /**< R3: The number of times GuestPDWriteContlict() detected a conflict. */
STAMCOUNTER StatRCInvlPgConflict; /**< RC: Number of times PGMInvalidatePage() detected a mapping conflict. */
STAMCOUNTER StatRCInvlPgSyncMonCR3; /**< RC: Number of times PGMInvalidatePage() ran into PGM_SYNC_MONITOR_CR3. */
STAMPROFILE StatRZTrap0eTime2CSAM; /**< RC/R0: Profiling of the Trap0eHandler body when the cause is CSAM. */
STAMPROFILE StatRZTrap0eTime2DirtyAndAccessed; /**< RC/R0: Profiling of the Trap0eHandler body when the cause is dirty and/or accessed bit emulation. */
STAMPROFILE StatRZTrap0eTime2GuestTrap; /**< RC/R0: Profiling of the Trap0eHandler body when the cause is a guest trap. */
STAMPROFILE StatRZTrap0eTime2HndPhys; /**< RC/R0: Profiling of the Trap0eHandler body when the cause is a physical handler. */
STAMPROFILE StatRZTrap0eTime2HndVirt; /**< RC/R0: Profiling of the Trap0eHandler body when the cause is a virtual handler. */
STAMPROFILE StatRZTrap0eTime2HndUnhandled; /**< RC/R0: Profiling of the Trap0eHandler body when the cause is access outside the monitored areas of a monitored page. */
STAMPROFILE StatRZTrap0eTime2Misc; /**< RC/R0: Profiling of the Trap0eHandler body when the cause is not known. */
STAMPROFILE StatRZTrap0eTime2OutOfSync; /**< RC/R0: Profiling of the Trap0eHandler body when the cause is an out-of-sync page. */
STAMPROFILE StatRZTrap0eTime2OutOfSyncHndPhys; /**< RC/R0: Profiling of the Trap0eHandler body when the cause is an out-of-sync physical handler page. */
STAMPROFILE StatRZTrap0eTime2OutOfSyncHndVirt; /**< RC/R0: Profiling of the Trap0eHandler body when the cause is an out-of-sync virtual handler page. */
STAMPROFILE StatRZTrap0eTime2OutOfSyncHndObs; /**< RC/R0: Profiling of the Trap0eHandler body when the cause is an obsolete handler page. */
STAMPROFILE StatRZTrap0eTime2SyncPT; /**< RC/R0: Profiling of the Trap0eHandler body when the cause is lazy syncing of a PT. */
STAMCOUNTER StatRZTrap0eConflicts; /**< RC/R0: The number of times \#PF was caused by an undetected conflict. */
STAMCOUNTER StatRZTrap0eHandlersMapping; /**< RC/R0: Number of traps due to access handlers in mappings. */
STAMCOUNTER StatRZTrap0eHandlersPhysical; /**< RC/R0: Number of traps due to physical access handlers. */
STAMCOUNTER StatRZTrap0eHandlersVirtual; /**< RC/R0: Number of traps due to virtual access handlers. */
STAMCOUNTER StatRZTrap0eHandlersVirtualByPhys; /**< RC/R0: Number of traps due to virtual access handlers found by physical address. */
STAMCOUNTER StatRZTrap0eHandlersVirtualUnmarked;/**< RC/R0: Number of traps due to virtual access handlers found by virtual address (without proper physical flags). */
STAMCOUNTER StatRZTrap0eHandlersUnhandled; /**< RC/R0: Number of traps due to access outside range of monitored page(s). */
STAMCOUNTER StatRZTrap0eHandlersInvalid; /**< RC/R0: Number of traps due to access to invalid physical memory. */
STAMCOUNTER StatRZTrap0eGuestPFUnh; /**< RC/R0: Real guest #PF ending up at the end of the #PF code. */
STAMCOUNTER StatRZGuestCR3WriteHandled; /**< RC/R0: The number of times WriteHandlerCR3() was successfully called. */
STAMCOUNTER StatRZGuestCR3WriteUnhandled; /**< RC/R0: The number of times WriteHandlerCR3() was called and we had to fall back to the recompiler. */
STAMCOUNTER StatRZGuestCR3WriteConflict; /**< RC/R0: The number of times WriteHandlerCR3() was called and a conflict was detected. */
STAMCOUNTER StatRZGuestROMWriteHandled; /**< RC/R0: The number of times pgmPhysRomWriteHandler() was successfully called. */
STAMCOUNTER StatRZGuestROMWriteUnhandled; /**< RC/R0: The number of times pgmPhysRomWriteHandler() was called and we had to fall back to the recompiler */
STAMPROFILE StatRZSyncCR3Handlers; /**< RC/R0: Profiling of the PGMSyncCR3() update handler section. */
STAMPROFILE StatRZSyncCR3HandlerVirtualReset; /**< RC/R0: Profiling of the virtual handler resets. */
STAMPROFILE StatRZSyncCR3HandlerVirtualUpdate; /**< RC/R0: Profiling of the virtual handler updates. */
STAMCOUNTER StatRZSyncCR3DstCacheHit; /**< RC/R0: The number of times we got some kind of cache hit on a page table. */
STAMCOUNTER StatRZSyncCR3DstFreed; /**< RC/R0: The number of times we've had to free a shadow entry. */
STAMCOUNTER StatRZSyncCR3DstFreedSrcNP; /**< RC/R0: The number of times we've had to free a shadow entry for which the source entry was not present. */
STAMCOUNTER StatRZSyncCR3DstNotPresent; /**< RC/R0: The number of times we've encountered a not present shadow entry for a present guest entry. */
STAMCOUNTER StatRZSyncCR3DstSkippedGlobalPD; /**< RC/R0: The number of times a global page directory wasn't flushed. */
STAMCOUNTER StatRZSyncCR3DstSkippedGlobalPT; /**< RC/R0: The number of times a page table with only global entries wasn't flushed. */
STAMCOUNTER StatRZSyncPagePDNAs; /**< RC/R0: The number of time we've marked a PD not present from SyncPage to virtualize the accessed bit. */
STAMCOUNTER StatRZSyncPagePDOutOfSync; /**< RC/R0: The number of time we've encountered an out-of-sync PD in SyncPage. */
STAMCOUNTER StatRZAccessedPage; /**< RC/R0: The number of pages marked not present for accessed bit emulation. */
STAMPROFILE StatRZDirtyBitTracking; /**< RC/R0: Profiling the dirty bit tracking in CheckPageFault().. */
STAMCOUNTER StatRZDirtyPage; /**< RC/R0: The number of pages marked read-only for dirty bit tracking. */
STAMCOUNTER StatRZDirtyPageBig; /**< RC/R0: The number of pages marked read-only for dirty bit tracking. */
STAMCOUNTER StatRZDirtyPageTrap; /**< RC/R0: The number of traps generated for dirty bit tracking. */
STAMCOUNTER StatRZDirtyTrackRealPF; /**< RC/R0: The number of real pages faults during dirty bit tracking. */
STAMCOUNTER StatRZDirtiedPage; /**< RC/R0: The number of pages marked dirty because of write accesses. */
STAMCOUNTER StatRZPageAlreadyDirty; /**< RC/R0: The number of pages already marked dirty because of write accesses. */
STAMCOUNTER StatRZInvalidatePage4KBPages; /**< RC/R0: The number of times PGMInvalidatePage() was called for a 4KB page. */
STAMCOUNTER StatRZInvalidatePage4MBPages; /**< RC/R0: The number of times PGMInvalidatePage() was called for a 4MB page. */
STAMCOUNTER StatRZInvalidatePage4MBPagesSkip; /**< RC/R0: The number of times PGMInvalidatePage() skipped a 4MB page. */
STAMCOUNTER StatRZInvalidatePagePDMappings; /**< RC/R0: The number of times PGMInvalidatePage() was called for a page directory containing mappings (no conflict). */
STAMCOUNTER StatRZInvalidatePagePDNAs; /**< RC/R0: The number of times PGMInvalidatePage() was called for a not accessed page directory. */
STAMCOUNTER StatRZInvalidatePagePDNPs; /**< RC/R0: The number of times PGMInvalidatePage() was called for a not present page directory. */
STAMCOUNTER StatRZInvalidatePagePDOutOfSync; /**< RC/R0: The number of times PGMInvalidatePage() was called for an out of sync page directory. */
STAMCOUNTER StatRZInvalidatePageSkipped; /**< RC/R0: The number of times PGMInvalidatePage() was skipped due to not present shw or pending pending SyncCR3. */
STAMPROFILE StatRZVirtHandlerSearchByPhys; /**< RC/R0: Profiling of pgmHandlerVirtualFindByPhysAddr. */
STAMCOUNTER StatRZPhysHandlerReset; /**< RC/R0: The number of times PGMHandlerPhysicalReset is called. */
STAMCOUNTER StatRZPageOutOfSyncUser; /**< RC/R0: The number of times user page is out of sync was detected in #PF or VerifyAccessSyncPage. */
STAMCOUNTER StatRZPageOutOfSyncSupervisor; /**< RC/R0: The number of times supervisor page is out of sync was detected in in #PF or VerifyAccessSyncPage. */
STAMCOUNTER StatRZPageReplaceShared; /**< RC/R0: Times a shared page has been replaced by a private one. */
STAMCOUNTER StatRZPageReplaceZero; /**< RC/R0: Times the zero page has been replaced by a private one. */
/// @todo STAMCOUNTER StatRZPageHandyAllocs; /**< RC/R0: The number of times we've executed GMMR3AllocateHandyPages. */
STAMCOUNTER StatRZFlushTLBNewCR3; /**< RC/R0: The number of times PGMFlushTLB was called with a new CR3, non-global. (switch) */
STAMCOUNTER StatRZFlushTLBNewCR3Global; /**< RC/R0: The number of times PGMFlushTLB was called with a new CR3, global. (switch) */
STAMCOUNTER StatRZFlushTLBSameCR3; /**< RC/R0: The number of times PGMFlushTLB was called with the same CR3, non-global. (flush) */
STAMCOUNTER StatRZFlushTLBSameCR3Global; /**< RC/R0: The number of times PGMFlushTLB was called with the same CR3, global. (flush) */
STAMPROFILE StatR3SyncCR3Handlers; /**< R3: Profiling of the PGMSyncCR3() update handler section. */
STAMPROFILE StatR3SyncCR3HandlerVirtualUpdate; /**< R3: Profiling of the virtual handler updates. */
STAMCOUNTER StatR3SyncCR3DstFreed; /**< R3: The number of times we've had to free a shadow entry. */
STAMCOUNTER StatR3SyncCR3DstFreedSrcNP; /**< R3: The number of times we've had to free a shadow entry for which the source entry was not present. */
STAMCOUNTER StatR3SyncCR3DstNotPresent; /**< R3: The number of times we've encountered a not present shadow entry for a present guest entry. */
STAMCOUNTER StatR3SyncCR3DstSkippedGlobalPD; /**< R3: The number of times a global page directory wasn't flushed. */
STAMCOUNTER StatR3SyncCR3DstSkippedGlobalPT; /**< R3: The number of times a page table with only global entries wasn't flushed. */
STAMCOUNTER StatR3SyncCR3DstCacheHit; /**< R3: The number of times we got some kind of cache hit on a page table. */
STAMCOUNTER StatR3SyncPagePDNAs; /**< R3: The number of time we've marked a PD not present from SyncPage to virtualize the accessed bit. */
STAMCOUNTER StatR3SyncPagePDOutOfSync; /**< R3: The number of time we've encountered an out-of-sync PD in SyncPage. */
STAMCOUNTER StatR3AccessedPage; /**< R3: The number of pages marked not present for accessed bit emulation. */
STAMPROFILE StatR3DirtyBitTracking; /**< R3: Profiling the dirty bit tracking in CheckPageFault(). */
STAMCOUNTER StatR3DirtyPage; /**< R3: The number of pages marked read-only for dirty bit tracking. */
STAMCOUNTER StatR3DirtyPageBig; /**< R3: The number of pages marked read-only for dirty bit tracking. */
STAMCOUNTER StatR3DirtyTrackRealPF; /**< R3: The number of real pages faults during dirty bit tracking. */
STAMCOUNTER StatR3DirtiedPage; /**< R3: The number of pages marked dirty because of write accesses. */
STAMCOUNTER StatR3PageAlreadyDirty; /**< R3: The number of pages already marked dirty because of write accesses. */
STAMCOUNTER StatR3InvalidatePage4KBPages; /**< R3: The number of times PGMInvalidatePage() was called for a 4KB page. */
STAMCOUNTER StatR3InvalidatePage4MBPages; /**< R3: The number of times PGMInvalidatePage() was called for a 4MB page. */
STAMCOUNTER StatR3InvalidatePage4MBPagesSkip; /**< R3: The number of times PGMInvalidatePage() skipped a 4MB page. */
STAMCOUNTER StatR3InvalidatePagePDNAs; /**< R3: The number of times PGMInvalidatePage() was called for a not accessed page directory. */
STAMCOUNTER StatR3InvalidatePagePDNPs; /**< R3: The number of times PGMInvalidatePage() was called for a not present page directory. */
STAMCOUNTER StatR3InvalidatePagePDMappings; /**< R3: The number of times PGMInvalidatePage() was called for a page directory containing mappings (no conflict). */
STAMCOUNTER StatR3InvalidatePagePDOutOfSync; /**< R3: The number of times PGMInvalidatePage() was called for an out of sync page directory. */
STAMCOUNTER StatR3InvalidatePageSkipped; /**< R3: The number of times PGMInvalidatePage() was skipped due to not present shw or pending pending SyncCR3. */
STAMPROFILE StatR3VirtHandlerSearchByPhys; /**< R3: Profiling of pgmHandlerVirtualFindByPhysAddr. */
STAMCOUNTER StatR3PhysHandlerReset; /**< R3: The number of times PGMHandlerPhysicalReset is called. */
STAMCOUNTER StatR3PageOutOfSyncUser; /**< R3: The number of times user page is out of sync was detected in #PF or VerifyAccessSyncPage. */
STAMCOUNTER StatR3PageOutOfSyncSupervisor; /**< R3: The number of times supervisor page is out of sync was detected in in #PF or VerifyAccessSyncPage. */
STAMCOUNTER StatR3PageReplaceShared; /**< R3: Times a shared page has been replaced by a private one. */
STAMCOUNTER StatR3PageReplaceZero; /**< R3: Times the zero page has been replaced by a private one. */
/// @todo STAMCOUNTER StatR3PageHandyAllocs; /**< R3: The number of times we've executed GMMR3AllocateHandyPages. */
STAMCOUNTER StatR3FlushTLBNewCR3; /**< R3: The number of times PGMFlushTLB was called with a new CR3, non-global. (switch) */
STAMCOUNTER StatR3FlushTLBNewCR3Global; /**< R3: The number of times PGMFlushTLB was called with a new CR3, global. (switch) */
STAMCOUNTER StatR3FlushTLBSameCR3; /**< R3: The number of times PGMFlushTLB was called with the same CR3, non-global. (flush) */
STAMCOUNTER StatR3FlushTLBSameCR3Global; /**< R3: The number of times PGMFlushTLB was called with the same CR3, global. (flush) */
} PGM;
typedef struct PGMCPU
} PGMCPU;
VMMRCDECL(int) pgmGCGuestPDWriteHandler(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pRegFrame, void *pvFault, RTGCPHYS GCPhysFault, void *pvUser);
VMMDECL(int) pgmPhysRomWriteHandler(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pRegFrame, void *pvFault, RTGCPHYS GCPhysFault, void *pvUser);
int pgmR3SyncPTResolveConflict(PVM pVM, PPGMMAPPING pMapping, PX86PD pPDSrc, RTGCPTR GCPtrOldMapping);
void pgmR3MapRelocate(PVM pVM, PPGMMAPPING pMapping, RTGCPTR GCPtrOldMapping, RTGCPTR GCPtrNewMapping);
int pgmHandlerVirtualFindByPhysAddr(PVM pVM, RTGCPHYS GCPhys, PPGMVIRTHANDLER *ppVirt, unsigned *piPage);
# define pgmHandlerVirtualDumpPhysPages(a) do { } while (0)
#ifdef IN_RING3
#ifndef VBOX_WITH_NEW_PHYS_CODE
int pgmPoolAlloc(PVM pVM, RTGCPHYS GCPhys, PGMPOOLKIND enmKind, uint16_t iUser, uint32_t iUserTable, PPPGMPOOLPAGE ppPage);
#ifdef PGMPOOL_WITH_MONITORING
# ifdef IN_RING3
void pgmPoolMonitorChainChanging(PPGMPOOL pPool, PPGMPOOLPAGE pPage, RTGCPHYS GCPhysFault, RTHCPTR pvAddress, PDISCPUSTATE pCpu);
void pgmPoolMonitorChainChanging(PPGMPOOL pPool, PPGMPOOLPAGE pPage, RTGCPHYS GCPhysFault, RTGCPTR pvAddress, PDISCPUSTATE pCpu);
return pRam;
return NULL;
#ifndef VBOX_WITH_NEW_PHYS_CODE
#ifdef IN_RING3
return rc;
return VINF_SUCCESS;
DECLINLINE(int) pgmPhysGetPageWithHintEx(PPGM pPGM, RTGCPHYS GCPhys, PPPGMPAGE ppPage, PPGMRAMRANGE *ppRamHint)
if ( !pRam
#ifndef VBOX_WITH_NEW_PHYS_CODE
#ifdef IN_RING3
return rc;
return VINF_SUCCESS;
return NULL;
DECLINLINE(int) pgmPhysGetPageAndRangeEx(PPGM pPGM, RTGCPHYS GCPhys, PPPGMPAGE ppPage, PPGMRAMRANGE *ppRam)
#ifndef VBOX_WITH_NEW_PHYS_CODE
#ifdef IN_RING3
return rc;
return VINF_SUCCESS;
return rc;
return VINF_SUCCESS;
#ifndef IN_RC
int rc;
return rc;
# ifndef VBOX_WITH_NEW_PHYS_CODE
return rc;
return VINF_SUCCESS;
*pHCPtr = (RTHCPTR)((RTHCUINTPTR)pRam->pvR3 + off); /** @todo @bugref{1865,3202}: Code is converting R3 pointer and maybe using it in R0! */
return VINF_SUCCESS;
DECLINLINE(int) pgmRamGCPhys2HCPtrWithRange(PVM pVM, PPGMRAMRANGE pRam, RTGCPHYS GCPhys, PRTHCPTR pHCPtr)
#ifdef IN_RING3
return rc;
return VINF_SUCCESS;
*pHCPtr = (RTHCPTR)((RTHCUINTPTR)pRam->pvR3 + off); /** @todo @bugref{1865,3202}: Code is converting R3 pointer and maybe using it in R0! */
return VINF_SUCCESS;
DECLINLINE(int) pgmRamGCPhys2HCPtrAndHCPhysWithFlags(PPGM pPGM, RTGCPHYS GCPhys, PRTHCPTR pHCPtr, PRTHCPHYS pHCPhys)
return rc;
return VINF_SUCCESS;
*pHCPtr = (RTHCPTR)((RTHCUINTPTR)pRam->pvR3 + off); /** @todo @bugref{1865,3202}: Code is converting R3 pointer and maybe using it in R0! */
return VINF_SUCCESS;
*pHCPtr = 0;
return rc;
return VINF_SUCCESS;
DECLINLINE(int) pgmRamFlagsClearByGCPhysWithHint(PPGM pPGM, RTGCPHYS GCPhys, unsigned fFlags, PPGMRAMRANGE *ppRamHint)
return rc;
return VINF_SUCCESS;
return rc;
return VINF_SUCCESS;
DECLINLINE(int) pgmRamFlagsSetByGCPhysWithHint(PPGM pPGM, RTGCPHYS GCPhys, unsigned fFlags, PPGMRAMRANGE *ppRamHint)
return rc;
return VINF_SUCCESS;
return pGuestPD;
return pGuestPDPT;
return pPD;
/* returning NULL is ok if we assume it's just an invalid page of some kind emulated as all 0s. (not quite true) */
return NULL;
/* returning NIL_RTGCPHYS is ok if we assume it's just an invalid page or something which we'll emulate as all 0s. (not quite true) */
return NULL;
return ZeroPde;
if (pPdpe)
return pPD;
/* returning NIL_RTGCPHYS is ok if we assume it's just an invalid page of some kind emulated as all 0s. */
return NULL;
#ifndef IN_RC
return pGuestPml4;
return NULL;
DECLINLINE(X86PDEPAE) pgmGstGetLongModePDEEx(PPGM pPGM, RTGCPTR64 GCPtr, PX86PML4E *ppPml4e, PX86PDPE pPdpe)
return ZeroPde;
return ZeroPde;
return NULL;
DECLINLINE(PX86PDPAE) pgmGstGetLongModePDPtr(PPGM pPGM, RTGCPTR64 GCPtr, PX86PML4E *ppPml4e, PX86PDPE pPdpe, unsigned *piPD)
return pPD;
return pShwPdpt;
return pPD;
return pPD;
#ifndef IN_RC
return pShwPml4;
return pPD;
return NULL;
return pPage
return PGM_PAGE_HNDL_PHYS_STATE_WRITE;
case PGMPHYSHANDLERTYPE_MMIO:
return PGM_PAGE_HNDL_PHYS_STATE_ALL;
case PGMVIRTHANDLERTYPE_WRITE:
return PGM_PAGE_HNDL_VIRT_STATE_WRITE;
case PGMVIRTHANDLERTYPE_ALL:
return PGM_PAGE_HNDL_VIRT_STATE_ALL;
("pPhys2Virt=%p:{.Core.Key=%RGp, .Core.KeyLast=%RGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32}\n",
pPhys2Virt, pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast, pPhys2Virt->offVirtHandler, pPhys2Virt->offNextAlias));
PPGMPHYS2VIRTHANDLER pRemove = (PPGMPHYS2VIRTHANDLER)RTAvlroGCPhysRemove(&pPGM->CTX_SUFF(pTrees)->PhysToVirtHandlers, pPhys2Virt->Core.Key); NOREF(pRemove);
("pPhys2Virt=%p:{.Core.Key=%RGp, .Core.KeyLast=%RGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32}\n",
pPhys2Virt, pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast, pPhys2Virt->offVirtHandler, pPhys2Virt->offNextAlias));
("wanted: pPhys2Virt=%p:{.Core.Key=%RGp, .Core.KeyLast=%RGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32}\n"
" got: pRemove=%p:{.Core.Key=%RGp, .Core.KeyLast=%RGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32}\n",
pPhys2Virt, pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast, pPhys2Virt->offVirtHandler, pPhys2Virt->offNextAlias,
pRemove, pRemove->Core.Key, pRemove->Core.KeyLast, pRemove->offVirtHandler, pRemove->offNextAlias));
PPGMPHYS2VIRTHANDLER pNext = (PPGMPHYS2VIRTHANDLER)((intptr_t)pPhys2Virt + (pPhys2Virt->offNextAlias & PGMPHYS2VIRTHANDLER_OFF_MASK));
PPGMPHYS2VIRTHANDLER pPrev = (PPGMPHYS2VIRTHANDLER)RTAvlroGCPhysGet(&pPGM->CTX_SUFF(pTrees)->PhysToVirtHandlers, pPhys2Virt->Core.Key);
("pPhys2Virt=%p:{.Core.Key=%RGp, .Core.KeyLast=%RGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32} pPrev=%p\n",
pPhys2Virt, pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast, pPhys2Virt->offVirtHandler, pPhys2Virt->offNextAlias, pPrev));
PPGMPHYS2VIRTHANDLER pNext = (PPGMPHYS2VIRTHANDLER)((intptr_t)pPrev + (pPrev->offNextAlias & PGMPHYS2VIRTHANDLER_OFF_MASK));
LogFlow(("pgmHandlerVirtualClearPage: removed %p:{.offNextAlias=%#RX32} from alias chain. prev %p:{.offNextAlias=%#RX32} [%RGp-%RGp]\n",
pPhys2Virt, pPhys2Virt->offNextAlias, pPrev, pPrev->offNextAlias, pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast));
PPGMPHYS2VIRTHANDLER pNewNext = (PPGMPHYS2VIRTHANDLER)((intptr_t)pPhys2Virt + (pPhys2Virt->offNextAlias & PGMPHYS2VIRTHANDLER_OFF_MASK));
("pPhys2Virt=%p:{.Core.Key=%RGp, .Core.KeyLast=%RGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32} pPrev=%p\n",
pPhys2Virt, pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast, pPhys2Virt->offVirtHandler, pPhys2Virt->offNextAlias, pPrev));
pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast, pPhys2Virt->offNextAlias, R3STRING(pCur->pszDesc)));
PPGMPOOLPAGE pPage = (PPGMPOOLPAGE)RTAvloHCPhysGet(&pPool->HCPhysTree, HCPhys & X86_PTE_PAE_PG_MASK);
AssertFatalMsg(pPage && pPage->enmKind != PGMPOOLKIND_FREE, ("HCPhys=%RHp pPage=%p type=%d\n", HCPhys, pPage, (pPage) ? pPage->enmKind : 0));
return pPage;
#ifdef PGMPOOL_WITH_GCPHYS_TRACKING
# ifdef LOG_ENABLED
#ifdef PGMPOOL_WITH_CACHE
* @todo inline in PGMInternal.h!
#ifdef IN_RING0