diff options
Diffstat (limited to 'include/VBox/vmm')
53 files changed, 5189 insertions, 4086 deletions
diff --git a/include/VBox/vmm/cfgm.h b/include/VBox/vmm/cfgm.h index 9b4e47ab..dbc8e527 100644 --- a/include/VBox/vmm/cfgm.h +++ b/include/VBox/vmm/cfgm.h @@ -3,7 +3,7 @@ */ /* - * Copyright (C) 2006-2010 Oracle Corporation + * Copyright (C) 2006-2013 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -74,19 +74,20 @@ typedef enum CFGMCONFIGTYPE * can make any necessary per-thread initializations at this point. * * @returns VBox status code. - * @param pVM VM handle. + * @param pUVM The user mode VM handle. + * @param pVM The shared VM handle. * @param pvUser The argument supplied to VMR3Create(). */ -typedef DECLCALLBACK(int) FNCFGMCONSTRUCTOR(PVM pVM, void *pvUser); +typedef DECLCALLBACK(int) FNCFGMCONSTRUCTOR(PUVM pUVM, PVM pVM, void *pvUser); /** Pointer to a FNCFGMCONSTRUCTOR(). */ typedef FNCFGMCONSTRUCTOR *PFNCFGMCONSTRUCTOR; VMMR3DECL(int) CFGMR3Init(PVM pVM, PFNCFGMCONSTRUCTOR pfnCFGMConstructor, void *pvUser); VMMR3DECL(int) CFGMR3Term(PVM pVM); - - -VMMR3DECL(PCFGMNODE) CFGMR3CreateTree(PVM pVM); VMMR3DECL(int) CFGMR3ConstructDefaultTree(PVM pVM); + +VMMR3DECL(PCFGMNODE) CFGMR3CreateTree(PUVM pUVM); +VMMR3DECL(int) CFGMR3DestroyTree(PCFGMNODE pRoot); VMMR3DECL(void) CFGMR3Dump(PCFGMNODE pRoot); VMMR3DECL(int) CFGMR3DuplicateSubTree(PCFGMNODE pRoot, PCFGMNODE *ppCopy); VMMR3DECL(int) CFGMR3ReplaceSubTree(PCFGMNODE pRoot, PCFGMNODE pNewRoot); @@ -185,6 +186,7 @@ VMMR3DECL(int) CFGMR3QueryStringAllocDef(PCFGMNODE pNode, const char *p * @{ */ VMMR3DECL(PCFGMNODE) CFGMR3GetRoot(PVM pVM); +VMMR3DECL(PCFGMNODE) CFGMR3GetRootU(PUVM pUVM); VMMR3DECL(PCFGMNODE) CFGMR3GetParent(PCFGMNODE pNode); VMMR3DECL(PCFGMNODE) CFGMR3GetParentEx(PVM pVM, PCFGMNODE pNode); VMMR3DECL(PCFGMNODE) CFGMR3GetChild(PCFGMNODE pNode, const char *pszPath); diff --git a/include/VBox/vmm/cpum.h b/include/VBox/vmm/cpum.h index 0b4abf33..d3ca4c02 100644 --- a/include/VBox/vmm/cpum.h +++ b/include/VBox/vmm/cpum.h @@ -3,7 +3,7 @@ */ /* - * Copyright (C) 2006-2012 Oracle Corporation + * Copyright (C) 2006-2013 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -77,13 +77,259 @@ typedef enum CPUMCPUVENDOR CPUMCPUVENDOR_INTEL, CPUMCPUVENDOR_AMD, CPUMCPUVENDOR_VIA, + CPUMCPUVENDOR_CYRIX, CPUMCPUVENDOR_UNKNOWN, - CPUMCPUVENDOR_SYNTHETIC, /** 32bit hackishness. */ CPUMCPUVENDOR_32BIT_HACK = 0x7fffffff } CPUMCPUVENDOR; +/** + * X86 and AMD64 CPU microarchitectures and in processor generations. + * + * @remarks The separation here is sometimes a little bit too finely grained, + * and the differences is more like processor generation than micro + * arch. This can be useful, so we'll provide functions for getting at + * more coarse grained info. + */ +typedef enum CPUMMICROARCH +{ + kCpumMicroarch_Invalid = 0, + + kCpumMicroarch_Intel_First, + + kCpumMicroarch_Intel_8086 = kCpumMicroarch_Intel_First, + kCpumMicroarch_Intel_80186, + kCpumMicroarch_Intel_80286, + kCpumMicroarch_Intel_80386, + kCpumMicroarch_Intel_80486, + kCpumMicroarch_Intel_P5, + + kCpumMicroarch_Intel_P6_Core_Atom_First, + kCpumMicroarch_Intel_P6 = kCpumMicroarch_Intel_P6_Core_Atom_First, + kCpumMicroarch_Intel_P6_II, + kCpumMicroarch_Intel_P6_III, + + kCpumMicroarch_Intel_P6_M_Banias, + kCpumMicroarch_Intel_P6_M_Dothan, + kCpumMicroarch_Intel_Core_Yonah, /**< Core, also known as Enhanced Pentium M. */ + + kCpumMicroarch_Intel_Core2_First, + kCpumMicroarch_Intel_Core2_Merom = kCpumMicroarch_Intel_Core2_First, + kCpumMicroarch_Intel_Core2_Penryn, + + kCpumMicroarch_Intel_Core7_First, + kCpumMicroarch_Intel_Core7_Nehalem = kCpumMicroarch_Intel_Core7_First, + kCpumMicroarch_Intel_Core7_Westmere, + kCpumMicroarch_Intel_Core7_SandyBridge, + kCpumMicroarch_Intel_Core7_IvyBridge, + kCpumMicroarch_Intel_Core7_Haswell, + kCpumMicroarch_Intel_Core7_Broadwell, + kCpumMicroarch_Intel_Core7_Skylake, + kCpumMicroarch_Intel_Core7_Cannonlake, + kCpumMicroarch_Intel_Core7_End, + + kCpumMicroarch_Intel_Atom_First, + kCpumMicroarch_Intel_Atom_Bonnell = kCpumMicroarch_Intel_Atom_First, + kCpumMicroarch_Intel_Atom_Lincroft, /**< Second generation bonnell (44nm). */ + kCpumMicroarch_Intel_Atom_Saltwell, /**< 32nm shrink of Bonnell. */ + kCpumMicroarch_Intel_Atom_Silvermont, /**< 22nm */ + kCpumMicroarch_Intel_Atom_Airmount, /**< 14nm */ + kCpumMicroarch_Intel_Atom_Goldmont, /**< 14nm */ + kCpumMicroarch_Intel_Atom_Unknown, + kCpumMicroarch_Intel_Atom_End, + + kCpumMicroarch_Intel_P6_Core_Atom_End, + + kCpumMicroarch_Intel_NB_First, + kCpumMicroarch_Intel_NB_Willamette = kCpumMicroarch_Intel_NB_First, /**< 180nm */ + kCpumMicroarch_Intel_NB_Northwood, /**< 130nm */ + kCpumMicroarch_Intel_NB_Prescott, /**< 90nm */ + kCpumMicroarch_Intel_NB_Prescott2M, /**< 90nm */ + kCpumMicroarch_Intel_NB_CedarMill, /**< 65nm */ + kCpumMicroarch_Intel_NB_Gallatin, /**< 90nm Xeon, Pentium 4 Extreme Edition ("Emergency Edition"). */ + kCpumMicroarch_Intel_NB_Unknown, + kCpumMicroarch_Intel_NB_End, + + kCpumMicroarch_Intel_Unknown, + kCpumMicroarch_Intel_End, + + kCpumMicroarch_AMD_First, + kCpumMicroarch_AMD_Am286 = kCpumMicroarch_AMD_First, + kCpumMicroarch_AMD_Am386, + kCpumMicroarch_AMD_Am486, + kCpumMicroarch_AMD_Am486Enh, /**< Covers Am5x86 as well. */ + kCpumMicroarch_AMD_K5, + kCpumMicroarch_AMD_K6, + + kCpumMicroarch_AMD_K7_First, + kCpumMicroarch_AMD_K7_Palomino = kCpumMicroarch_AMD_K7_First, + kCpumMicroarch_AMD_K7_Spitfire, + kCpumMicroarch_AMD_K7_Thunderbird, + kCpumMicroarch_AMD_K7_Morgan, + kCpumMicroarch_AMD_K7_Thoroughbred, + kCpumMicroarch_AMD_K7_Barton, + kCpumMicroarch_AMD_K7_Unknown, + kCpumMicroarch_AMD_K7_End, + + kCpumMicroarch_AMD_K8_First, + kCpumMicroarch_AMD_K8_130nm = kCpumMicroarch_AMD_K8_First, /**< 130nm Clawhammer, Sledgehammer, Newcastle, Paris, Odessa, Dublin */ + kCpumMicroarch_AMD_K8_90nm, /**< 90nm shrink */ + kCpumMicroarch_AMD_K8_90nm_DualCore, /**< 90nm with two cores. */ + kCpumMicroarch_AMD_K8_90nm_AMDV, /**< 90nm with AMD-V (usually) and two cores (usually). */ + kCpumMicroarch_AMD_K8_65nm, /**< 65nm shrink. */ + kCpumMicroarch_AMD_K8_End, + + kCpumMicroarch_AMD_K10, + kCpumMicroarch_AMD_K10_Lion, + kCpumMicroarch_AMD_K10_Llano, + kCpumMicroarch_AMD_Bobcat, + kCpumMicroarch_AMD_Jaguar, + + kCpumMicroarch_AMD_15h_First, + kCpumMicroarch_AMD_15h_Bulldozer = kCpumMicroarch_AMD_15h_First, + kCpumMicroarch_AMD_15h_Piledriver, + kCpumMicroarch_AMD_15h_Steamroller, /**< Yet to be released, might have different family. */ + kCpumMicroarch_AMD_15h_Excavator, /**< Yet to be released, might have different family. */ + kCpumMicroarch_AMD_15h_Unknown, + kCpumMicroarch_AMD_15h_End, + + kCpumMicroarch_AMD_16h_First, + kCpumMicroarch_AMD_16h_End, + + kCpumMicroarch_AMD_Unknown, + kCpumMicroarch_AMD_End, + + kCpumMicroarch_VIA_First, + kCpumMicroarch_Centaur_C6 = kCpumMicroarch_VIA_First, + kCpumMicroarch_Centaur_C2, + kCpumMicroarch_Centaur_C3, + kCpumMicroarch_VIA_C3_M2, + kCpumMicroarch_VIA_C3_C5A, /**< 180nm Samuel - Cyrix III, C3, 1GigaPro. */ + kCpumMicroarch_VIA_C3_C5B, /**< 150nm Samuel 2 - Cyrix III, C3, 1GigaPro, Eden ESP, XP 2000+. */ + kCpumMicroarch_VIA_C3_C5C, /**< 130nm Ezra - C3, Eden ESP. */ + kCpumMicroarch_VIA_C3_C5N, /**< 130nm Ezra-T - C3. */ + kCpumMicroarch_VIA_C3_C5XL, /**< 130nm Nehemiah - C3, Eden ESP, Eden-N. */ + kCpumMicroarch_VIA_C3_C5P, /**< 130nm Nehemiah+ - C3. */ + kCpumMicroarch_VIA_C7_C5J, /**< 90nm Esther - C7, C7-D, C7-M, Eden, Eden ULV. */ + kCpumMicroarch_VIA_Isaiah, + kCpumMicroarch_VIA_Unknown, + kCpumMicroarch_VIA_End, + + kCpumMicroarch_Cyrix_First, + kCpumMicroarch_Cyrix_5x86 = kCpumMicroarch_Cyrix_First, + kCpumMicroarch_Cyrix_M1, + kCpumMicroarch_Cyrix_MediaGX, + kCpumMicroarch_Cyrix_MediaGXm, + kCpumMicroarch_Cyrix_M2, + kCpumMicroarch_Cyrix_Unknown, + kCpumMicroarch_Cyrix_End, + + kCpumMicroarch_Unknown, + + kCpumMicroarch_32BitHack = 0x7fffffff +} CPUMMICROARCH; + + +/** Predicate macro for catching netburst CPUs. */ +#define CPUMMICROARCH_IS_INTEL_NETBURST(a_enmMicroarch) \ + ((a_enmMicroarch) >= kCpumMicroarch_Intel_NB_First && (a_enmMicroarch) <= kCpumMicroarch_Intel_NB_End) + +/** Predicate macro for catching Core7 CPUs. */ +#define CPUMMICROARCH_IS_INTEL_CORE7(a_enmMicroarch) \ + ((a_enmMicroarch) >= kCpumMicroarch_Intel_Core7_First && (a_enmMicroarch) <= kCpumMicroarch_Intel_Core7_End) + +/** Predicate macro for catching AMD Family OFh CPUs (aka K8). */ +#define CPUMMICROARCH_IS_AMD_FAM_0FH(a_enmMicroarch) \ + ((a_enmMicroarch) >= kCpumMicroarch_AMD_K8_First && (a_enmMicroarch) <= kCpumMicroarch_AMD_K8_End) + +/** Predicate macro for catching AMD Family 10H CPUs (aka K10). */ +#define CPUMMICROARCH_IS_AMD_FAM_10H(a_enmMicroarch) ((a_enmMicroarch) == kCpumMicroarch_AMD_K10) + +/** Predicate macro for catching AMD Family 11H CPUs (aka Lion). */ +#define CPUMMICROARCH_IS_AMD_FAM_11H(a_enmMicroarch) ((a_enmMicroarch) == kCpumMicroarch_AMD_K10_Lion) + +/** Predicate macro for catching AMD Family 12H CPUs (aka Llano). */ +#define CPUMMICROARCH_IS_AMD_FAM_12H(a_enmMicroarch) ((a_enmMicroarch) == kCpumMicroarch_AMD_K10_Llano) + +/** Predicate macro for catching AMD Family 14H CPUs (aka Bobcat). */ +#define CPUMMICROARCH_IS_AMD_FAM_14H(a_enmMicroarch) ((a_enmMicroarch) == kCpumMicroarch_AMD_Bobcat) + +/** Predicate macro for catching AMD Family 15H CPUs (bulldozer and it's + * decendants). */ +#define CPUMMICROARCH_IS_AMD_FAM_15H(a_enmMicroarch) \ + ((a_enmMicroarch) >= kCpumMicroarch_AMD_15h_First && (a_enmMicroarch) <= kCpumMicroarch_AMD_15h_End) + +/** Predicate macro for catching AMD Family 16H CPUs. */ +#define CPUMMICROARCH_IS_AMD_FAM_16H(a_enmMicroarch) \ + ((a_enmMicroarch) >= kCpumMicroarch_AMD_16h_First && (a_enmMicroarch) <= kCpumMicroarch_AMD_16h_End) + + + +/** + * CPUID leaf. + */ +typedef struct CPUMCPUIDLEAF +{ + /** The leaf number. */ + uint32_t uLeaf; + /** The sub-leaf number. */ + uint32_t uSubLeaf; + /** Sub-leaf mask. This is 0 when sub-leaves aren't used. */ + uint32_t fSubLeafMask; + + /** The EAX value. */ + uint32_t uEax; + /** The EBX value. */ + uint32_t uEbx; + /** The ECX value. */ + uint32_t uEcx; + /** The EDX value. */ + uint32_t uEdx; + + /** Flags. */ + uint32_t fFlags; +} CPUMCPUIDLEAF; +/** Pointer to a CPUID leaf. */ +typedef CPUMCPUIDLEAF *PCPUMCPUIDLEAF; +/** Pointer to a const CPUID leaf. */ +typedef CPUMCPUIDLEAF const *PCCPUMCPUIDLEAF; + +/** @name CPUMCPUIDLEAF::fFlags + * @{ */ +/** Indicates that ECX (the sub-leaf indicator) doesn't change when + * requesting the final leaf and all undefined leaves that follows it. + * Observed for 0x0000000b on Intel. */ +#define CPUMCPUIDLEAF_F_SUBLEAVES_ECX_UNCHANGED RT_BIT_32(0) +/** @} */ + +/** + * Method used to deal with unknown CPUID leafs. + */ +typedef enum CPUMUKNOWNCPUID +{ + /** Invalid zero value. */ + CPUMUKNOWNCPUID_INVALID = 0, + /** Use given default values (DefCpuId). */ + CPUMUKNOWNCPUID_DEFAULTS, + /** Return the last standard leaf. + * Intel Sandy Bridge has been observed doing this. */ + CPUMUKNOWNCPUID_LAST_STD_LEAF, + /** Return the last standard leaf, with ecx observed. + * Intel Sandy Bridge has been observed doing this. */ + CPUMUKNOWNCPUID_LAST_STD_LEAF_WITH_ECX, + /** The register values are passed thru unmodified. */ + CPUMUKNOWNCPUID_PASSTHRU, + /** End of valid value. */ + CPUMUKNOWNCPUID_END, + /** Ensure 32-bit type. */ + CPUMUKNOWNCPUID_32BIT_HACK = 0x7fffffff +} CPUMUKNOWNCPUID; +/** Pointer to unknown CPUID leaf method. */ +typedef CPUMUKNOWNCPUID *PCPUMUKNOWNCPUID; + + + /** @name Guest Register Getters. * @{ */ VMMDECL(void) CPUMGetGuestGDTR(PVMCPU pVCpu, PVBOXGDTR pGDTR); @@ -172,6 +418,8 @@ VMMDECL(bool) CPUMGetGuestCpuIdFeature(PVM pVM, CPUMCPUIDFEATURE enmFeatur VMMDECL(void) CPUMSetGuestCtx(PVMCPU pVCpu, const PCPUMCTX pCtx); VMM_INT_DECL(void) CPUMGuestLazyLoadHiddenCsAndSs(PVMCPU pVCpu); VMM_INT_DECL(void) CPUMGuestLazyLoadHiddenSelectorReg(PVMCPU pVCpu, PCPUMSELREG pSReg); +VMMR0_INT_DECL(void) CPUMR0SetGuestTscAux(PVMCPU pVCpu, uint64_t uValue); +VMMR0_INT_DECL(uint64_t) CPUMR0GetGuestTscAux(PVMCPU pVCpu); /** @} */ @@ -215,7 +463,18 @@ DECLINLINE(bool) CPUMIsGuestInRealModeEx(PCPUMCTX pCtx) DECLINLINE(bool) CPUMIsGuestInRealOrV86ModeEx(PCPUMCTX pCtx) { return !(pCtx->cr0 & X86_CR0_PE) - || pCtx->eflags.Bits.u1VM; /** @todo verify that this cannot be set in long mode. */ + || pCtx->eflags.Bits.u1VM; /* Cannot be set in long mode. Intel spec 2.3.1 "System Flags and Fields in IA-32e Mode". */ +} + +/** + * Tests if the guest is running in virtual 8086 mode. + * + * @returns @c true if it is, @c false if not. + * @param pCtx Current CPU context + */ +DECLINLINE(bool) CPUMIsGuestInV86ModeEx(PCPUMCTX pCtx) +{ + return (pCtx->eflags.Bits.u1VM == 1); } /** @@ -259,6 +518,17 @@ DECLINLINE(bool) CPUMIsGuestIn64BitCodeEx(PCPUMCTX pCtx) } /** + * Tests if the guest has paging enabled or not. + * + * @returns true if paging is enabled, otherwise false. + * @param pCtx Current CPU context + */ +DECLINLINE(bool) CPUMIsGuestPagingEnabledEx(PCPUMCTX pCtx) +{ + return !!(pCtx->cr0 & X86_CR0_PG); +} + +/** * Tests if the guest is running in PAE mode or not. * * @returns true if in PAE mode, otherwise false. @@ -266,9 +536,11 @@ DECLINLINE(bool) CPUMIsGuestIn64BitCodeEx(PCPUMCTX pCtx) */ DECLINLINE(bool) CPUMIsGuestInPAEModeEx(PCPUMCTX pCtx) { - return ( (pCtx->cr4 & X86_CR4_PAE) - && CPUMIsGuestInPagedProtectedModeEx(pCtx) - && !CPUMIsGuestInLongModeEx(pCtx)); + /* Intel mentions EFER.LMA and EFER.LME in different parts of their spec. We shall use EFER.LMA rather + than EFER.LME as it reflects if the CPU has entered paging with EFER.LME set. */ + return ( (pCtx->cr4 & X86_CR4_PAE) + && CPUMIsGuestPagingEnabledEx(pCtx) + && !(pCtx->msrEFER & MSR_K6_EFER_LMA)); } #endif /* VBOX_WITHOUT_UNNAMED_UNIONS */ @@ -341,7 +613,7 @@ VMMDECL(void) CPUMSetHyperDR3(PVMCPU pVCpu, RTGCUINTREG uDr3); VMMDECL(void) CPUMSetHyperDR6(PVMCPU pVCpu, RTGCUINTREG uDr6); VMMDECL(void) CPUMSetHyperDR7(PVMCPU pVCpu, RTGCUINTREG uDr7); VMMDECL(void) CPUMSetHyperCtx(PVMCPU pVCpu, const PCPUMCTX pCtx); -VMMDECL(int) CPUMRecalcHyperDRx(PVMCPU pVCpu); +VMMDECL(int) CPUMRecalcHyperDRx(PVMCPU pVCpu, uint8_t iGstReg, bool fForceHyper); /** @} */ VMMDECL(void) CPUMPushHyper(PVMCPU pVCpu, uint32_t u32); @@ -350,11 +622,10 @@ VMMDECL(PCPUMCTX) CPUMGetHyperCtxPtr(PVMCPU pVCpu); VMMDECL(PCCPUMCTXCORE) CPUMGetHyperCtxCore(PVMCPU pVCpu); VMMDECL(PCPUMCTX) CPUMQueryGuestCtxPtr(PVMCPU pVCpu); VMMDECL(PCCPUMCTXCORE) CPUMGetGuestCtxCore(PVMCPU pVCpu); -VMMR3DECL(int) CPUMR3RawEnter(PVMCPU pVCpu, PCPUMCTXCORE pCtxCore); -VMMR3DECL(int) CPUMR3RawLeave(PVMCPU pVCpu, PCPUMCTXCORE pCtxCore, int rc); +VMM_INT_DECL(int) CPUMRawEnter(PVMCPU pVCpu, PCPUMCTXCORE pCtxCore); +VMM_INT_DECL(int) CPUMRawLeave(PVMCPU pVCpu, PCPUMCTXCORE pCtxCore, int rc); VMMDECL(uint32_t) CPUMRawGetEFlags(PVMCPU pVCpu); VMMDECL(void) CPUMRawSetEFlags(PVMCPU pVCpu, uint32_t fEfl); -VMMDECL(int) CPUMHandleLazyFPU(PVMCPU pVCpu); /** @name Changed flags. * These flags are used to keep track of which important register that @@ -394,16 +665,32 @@ VMMR3DECL(void) CPUMR3RemLeave(PVMCPU pVCpu, bool fNoOutOfSyncSels); VMMDECL(bool) CPUMSupportsFXSR(PVM pVM); VMMDECL(bool) CPUMIsHostUsingSysEnter(PVM pVM); VMMDECL(bool) CPUMIsHostUsingSysCall(PVM pVM); -VMMDECL(bool) CPUMIsGuestFPUStateActive(PVMCPU pVCPU); +VMMDECL(bool) CPUMIsGuestFPUStateActive(PVMCPU pVCpu); VMMDECL(void) CPUMDeactivateGuestFPUState(PVMCPU pVCpu); VMMDECL(bool) CPUMIsGuestDebugStateActive(PVMCPU pVCpu); +VMMDECL(bool) CPUMIsGuestDebugStateActivePending(PVMCPU pVCpu); VMMDECL(void) CPUMDeactivateGuestDebugState(PVMCPU pVCpu); VMMDECL(bool) CPUMIsHyperDebugStateActive(PVMCPU pVCpu); -VMMDECL(void) CPUMDeactivateHyperDebugState(PVMCPU pVCpu); +VMMDECL(bool) CPUMIsHyperDebugStateActivePending(PVMCPU pVCpu); VMMDECL(uint32_t) CPUMGetGuestCPL(PVMCPU pVCpu); VMMDECL(CPUMMODE) CPUMGetGuestMode(PVMCPU pVCpu); VMMDECL(uint32_t) CPUMGetGuestCodeBits(PVMCPU pVCpu); VMMDECL(DISCPUMODE) CPUMGetGuestDisMode(PVMCPU pVCpu); +VMMDECL(uint64_t) CPUMGetGuestScalableBusFrequency(PVM pVM); + +/** @name Typical scalable bus frequency values. + * @{ */ +/** Special internal value indicating that we don't know the frequency. + * @internal */ +#define CPUM_SBUSFREQ_UNKNOWN UINT64_C(1) +#define CPUM_SBUSFREQ_100MHZ UINT64_C(100000000) +#define CPUM_SBUSFREQ_133MHZ UINT64_C(133333333) +#define CPUM_SBUSFREQ_167MHZ UINT64_C(166666666) +#define CPUM_SBUSFREQ_200MHZ UINT64_C(200000000) +#define CPUM_SBUSFREQ_267MHZ UINT64_C(266666666) +#define CPUM_SBUSFREQ_333MHZ UINT64_C(333333333) +#define CPUM_SBUSFREQ_400MHZ UINT64_C(400000000) +/** @} */ #ifdef IN_RING3 @@ -413,10 +700,12 @@ VMMDECL(DISCPUMODE) CPUMGetGuestDisMode(PVMCPU pVCpu); */ VMMR3DECL(int) CPUMR3Init(PVM pVM); +VMMR3DECL(int) CPUMR3InitCompleted(PVM pVM); +VMMR3DECL(void) CPUMR3LogCpuIds(PVM pVM); VMMR3DECL(void) CPUMR3Relocate(PVM pVM); VMMR3DECL(int) CPUMR3Term(PVM pVM); VMMR3DECL(void) CPUMR3Reset(PVM pVM); -VMMR3DECL(void) CPUMR3ResetCpu(PVMCPU pVCpu); +VMMR3DECL(void) CPUMR3ResetCpu(PVM pVM, PVMCPU pVCpu); VMMDECL(bool) CPUMR3IsStateRestorePending(PVM pVM); VMMR3DECL(void) CPUMR3SetHWVirtEx(PVM pVM, bool fHWVirtExEnabled); VMMR3DECL(int) CPUMR3SetCR4Feature(PVM pVM, RTHCUINTREG fOr, RTHCUINTREG fAnd); @@ -425,6 +714,15 @@ VMMR3DECL(RCPTRTYPE(PCCPUMCPUID)) CPUMR3GetGuestCpuIdExtRCPtr(PVM pVM); VMMR3DECL(RCPTRTYPE(PCCPUMCPUID)) CPUMR3GetGuestCpuIdCentaurRCPtr(PVM pVM); VMMR3DECL(RCPTRTYPE(PCCPUMCPUID)) CPUMR3GetGuestCpuIdDefRCPtr(PVM pVM); +VMMR3DECL(CPUMMICROARCH) CPUMR3CpuIdDetermineMicroarchEx(CPUMCPUVENDOR enmVendor, uint8_t bFamily, + uint8_t bModel, uint8_t bStepping); +VMMR3DECL(const char *) CPUMR3MicroarchName(CPUMMICROARCH enmMicroarch); +VMMR3DECL(int) CPUMR3CpuIdCollectLeaves(PCPUMCPUIDLEAF *ppaLeaves, uint32_t *pcLeaves); +VMMR3DECL(int) CPUMR3CpuIdDetectUnknownLeafMethod(PCPUMUKNOWNCPUID penmUnknownMethod, PCPUMCPUID pDefUnknown); +VMMR3DECL(const char *) CPUMR3CpuIdUnknownLeafMethodName(CPUMUKNOWNCPUID enmUnknownMethod); +VMMR3DECL(CPUMCPUVENDOR) CPUMR3CpuIdDetectVendorEx(uint32_t uEAX, uint32_t uEBX, uint32_t uECX, uint32_t uEDX); +VMMR3DECL(const char *) CPUMR3CpuVendorName(CPUMCPUVENDOR enmVendor); + /** @} */ #endif /* IN_RING3 */ @@ -459,6 +757,12 @@ DECLASM(void) CPUMGCCallGuestTrapHandler(PCPUMCTXCORE pRegFrame, uint3 */ DECLASM(void) CPUMGCCallV86Code(PCPUMCTXCORE pRegFrame); +VMMDECL(int) CPUMHandleLazyFPU(PVMCPU pVCpu); +VMMDECL(uint32_t) CPUMRCGetGuestCPL(PVMCPU pVCpu, PCPUMCTXCORE pRegFrame); +#ifdef VBOX_WITH_RAW_RING1 +VMMDECL(void) CPUMRCRecheckRawState(PVMCPU pVCpu, PCPUMCTXCORE pCtxCore); +#endif + /** @} */ #endif /* IN_RC */ @@ -467,18 +771,20 @@ DECLASM(void) CPUMGCCallV86Code(PCPUMCTXCORE pRegFrame); * @ingroup grp_cpum * @{ */ -VMMR0DECL(int) CPUMR0ModuleInit(void); -VMMR0DECL(int) CPUMR0ModuleTerm(void); -VMMR0DECL(int) CPUMR0Init(PVM pVM); -VMMR0DECL(int) CPUMR0LoadGuestFPU(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx); -VMMR0DECL(int) CPUMR0SaveGuestFPU(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx); -VMMR0DECL(int) CPUMR0SaveGuestDebugState(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, bool fDR6); -VMMR0DECL(int) CPUMR0LoadGuestDebugState(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, bool fDR6); -VMMR0DECL(int) CPUMR0LoadHostDebugState(PVM pVM, PVMCPU pVCpu); -VMMR0DECL(int) CPUMR0SaveHostDebugState(PVM pVM, PVMCPU pVCpu); -VMMR0DECL(int) CPUMR0LoadHyperDebugState(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, bool fDR6); +VMMR0_INT_DECL(int) CPUMR0ModuleInit(void); +VMMR0_INT_DECL(int) CPUMR0ModuleTerm(void); +VMMR0_INT_DECL(int) CPUMR0InitVM(PVM pVM); +VMMR0_INT_DECL(int) CPUMR0Trap07Handler(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx); +VMMR0_INT_DECL(int) CPUMR0LoadGuestFPU(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx); +VMMR0_INT_DECL(int) CPUMR0SaveGuestFPU(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx); +VMMR0_INT_DECL(int) CPUMR0SaveHostDebugState(PVM pVM, PVMCPU pVCpu); +VMMR0_INT_DECL(bool) CPUMR0DebugStateMaybeSaveGuestAndRestoreHost(PVMCPU pVCpu, bool fDr6); +VMMR0_INT_DECL(bool) CPUMR0DebugStateMaybeSaveGuest(PVMCPU pVCpu, bool fDr6); + +VMMR0_INT_DECL(void) CPUMR0LoadGuestDebugState(PVMCPU pVCpu, bool fDr6); +VMMR0_INT_DECL(void) CPUMR0LoadHyperDebugState(PVMCPU pVCpu, bool fDr6); #ifdef VBOX_WITH_VMMR0_DISABLE_LAPIC_NMI -VMMR0DECL(void) CPUMR0SetLApic(PVM pVM, RTCPUID idHostCpu); +VMMR0_INT_DECL(void) CPUMR0SetLApic(PVMCPU pVCpu, RTCPUID idHostCpu); #endif /** @} */ diff --git a/include/VBox/vmm/cpum.mac b/include/VBox/vmm/cpum.mac index 8f906d06..48d3eb70 100644 --- a/include/VBox/vmm/cpum.mac +++ b/include/VBox/vmm/cpum.mac @@ -3,7 +3,7 @@ ; ; -; Copyright (C) 2006-2010 Oracle Corporation +; Copyright (C) 2006-2012 Oracle Corporation ; ; This file is part of VirtualBox Open Source Edition (OSE), as ; available from http://www.virtualbox.org. This file is free software; @@ -193,7 +193,8 @@ struc CPUMCTX .msrCSTAR resb 8 .msrSFMASK resb 8 .msrKERNELGSBASE resb 8 - .au32SizePadding resb 32 + .msrApicBase resb 8 + .au32SizePadding resb 24 endstruc @@ -205,3 +206,4 @@ endstruc %endif + diff --git a/include/VBox/vmm/cpumctx.h b/include/VBox/vmm/cpumctx.h index 35861823..c4c9df3b 100644 --- a/include/VBox/vmm/cpumctx.h +++ b/include/VBox/vmm/cpumctx.h @@ -135,7 +135,8 @@ typedef struct CPUMSYSENTER /** * CPU context core. * - * @todo eliminate this structure! + * @todo Eliminate this structure! + * @deprecated We don't push any context cores any more in TRPM. */ #pragma pack(1) typedef struct CPUMCTXCORE @@ -399,10 +400,11 @@ typedef struct CPUMCTX uint64_t msrCSTAR; /**< Compatibility mode syscall rip. */ uint64_t msrSFMASK; /**< syscall flag mask. */ uint64_t msrKERNELGSBASE; /**< swapgs exchange value. */ + uint64_t msrApicBase; /**< The local APIC base (IA32_APIC_BASE MSR). */ /** @} */ /** Size padding. */ - uint32_t au32SizePadding[8]; + uint32_t au32SizePadding[6]; } CPUMCTX; #pragma pack() @@ -414,6 +416,11 @@ typedef struct CPUMCTX # define CPUMCTX2CORE(pCtx) ((PCPUMCTXCORE)(void *)&(pCtx)->rax) /** + * Gets the CPUMCTXCORE part of a CPUMCTX. + */ +# define CPUMCTX_FROM_CORE(a_pCtxCore) RT_FROM_MEMBER(a_pCtxCore, CPUMCTX, rax) + +/** * Gets the first selector register of a CPUMCTX. * * Use this with X86_SREG_COUNT to loop thru the selector registers. @@ -446,6 +453,7 @@ typedef union CPUMCTXMSRS uint64_t MtrrFix4K_E8000; /**< IA32_MTRR_FIX4K_E8000 */ uint64_t MtrrFix4K_F0000; /**< IA32_MTRR_FIX4K_F0000 */ uint64_t MtrrFix4K_F8000; /**< IA32_MTRR_FIX4K_F8000 */ + uint64_t PkgCStateCfgCtrl; /**< MSR_PKG_CST_CONFIG_CONTROL */ } msr; uint64_t au64[64]; } CPUMCTXMSRS; diff --git a/include/VBox/vmm/cpumdis.h b/include/VBox/vmm/cpumdis.h index 9aa509a3..dab556a8 100644 --- a/include/VBox/vmm/cpumdis.h +++ b/include/VBox/vmm/cpumdis.h @@ -3,7 +3,7 @@ */ /* - * Copyright (C) 2006-2010 Oracle Corporation + * Copyright (C) 2006-2012 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; diff --git a/include/VBox/vmm/csam.h b/include/VBox/vmm/csam.h index 675cac7f..99a68563 100644 --- a/include/VBox/vmm/csam.h +++ b/include/VBox/vmm/csam.h @@ -3,7 +3,7 @@ */ /* - * Copyright (C) 2006-2010 Oracle Corporation + * Copyright (C) 2006-2013 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -28,13 +28,14 @@ #include <VBox/types.h> +#if defined(VBOX_WITH_RAW_MODE) || defined(DOXYGEN_RUNNING) /** @defgroup grp_csam The Code Scanning and Analysis API * @{ */ /** - * CSAM monitoring tag + * CSAM monitoring tag. * For use with CSAMR3MonitorPage */ typedef enum CSAMTAG @@ -51,98 +52,22 @@ RT_C_DECLS_BEGIN /** - * Check if this page needs to be analysed by CSAM. - * - * This function should only be called for supervisor pages and - * only when CSAM is enabled. Leaving these selection criteria - * to the caller simplifies the interface (PTE passing). - * - * Note the the page has not yet been synced, so the TLB trick - * (which wasn't ever active anyway) cannot be applied. - * - * @returns true if the page should be marked not present because - * CSAM want need to scan it. - * @returns false if the page was already scanned. - * @param pVM The VM to operate on. - * @param GCPtr GC pointer of page table entry - */ -VMMDECL(bool) CSAMDoesPageNeedScanning(PVM pVM, RTRCUINTPTR GCPtr); - -/** - * Check if this page was previously scanned by CSAM - * - * @returns true -> scanned, false -> not scanned - * @param pVM The VM to operate on. - * @param pPage GC page address - */ -VMMDECL(bool) CSAMIsPageScanned(PVM pVM, RTRCPTR pPage); - -/** - * Mark a page as scanned/not scanned - * - * @note: we always mark it as scanned, even if we haven't completely done so - * - * @returns VBox status code. - * @param pVM The VM to operate on. - * @param pPage GC page address (not necessarily aligned) - * @param fScanned Mark as scanned or not scanned - * - */ -VMMDECL(int) CSAMMarkPage(PVM pVM, RTRCUINTPTR pPage, bool fScanned); - - -/** - * Remember a possible code page for later inspection - * - * @returns VBox status code. - * @param pVM The VM to operate on. - * @param GCPtr GC pointer of page - */ -VMMDECL(void) CSAMMarkPossibleCodePage(PVM pVM, RTRCPTR GCPtr); - -/** * Query CSAM state (enabled/disabled) * - * @returns 0 - disabled, 1 - enabled - * @param pVM The VM to operate on. - */ -#define CSAMIsEnabled(pVM) (pVM->fCSAMEnabled && EMIsRawRing0Enabled(pVM)) - -/** - * Turn on code scanning - * - * @returns VBox status code. (trap handled or not) - * @param pVM The VM to operate on. + * @returns true / false. + * @param a_pVM The shared VM handle. + * @internal */ -VMMDECL(int) CSAMEnableScanning(PVM pVM); - -/** - * Turn off code scanning - * - * @returns VBox status code. (trap handled or not) - * @param pVM The VM to operate on. - */ -VMMDECL(int) CSAMDisableScanning(PVM pVM); +#define CSAMIsEnabled(a_pVM) ((a_pVM)->fCSAMEnabled && EMIsRawRing0Enabled(a_pVM)) - -/** - * Check if this page needs to be analysed by CSAM - * - * @returns 0 - disabled, 1 - enabled - * @param pVM The VM to operate on. - * @param pvFault Fault address - */ -VMMDECL(int) CSAMExecFault(PVM pVM, RTRCPTR pvFault); - -/** - * Check if we've scanned this instruction before. If true, then we can emulate - * it instead of returning to ring 3. - * - * @returns boolean - * @param pVM The VM to operate on. - * @param GCPtr GC pointer of page table entry - */ -VMMDECL(bool) CSAMIsKnownDangerousInstr(PVM pVM, RTRCUINTPTR GCPtr); +VMM_INT_DECL(bool) CSAMDoesPageNeedScanning(PVM pVM, RTRCUINTPTR GCPtr); +VMM_INT_DECL(bool) CSAMIsPageScanned(PVM pVM, RTRCPTR pPage); +VMM_INT_DECL(int) CSAMMarkPage(PVM pVM, RTRCUINTPTR pPage, bool fScanned); +VMM_INT_DECL(void) CSAMMarkPossibleCodePage(PVM pVM, RTRCPTR GCPtr); +VMM_INT_DECL(int) CSAMEnableScanning(PVM pVM); +VMM_INT_DECL(int) CSAMDisableScanning(PVM pVM); +VMM_INT_DECL(int) CSAMExecFault(PVM pVM, RTRCPTR pvFault); +VMM_INT_DECL(bool) CSAMIsKnownDangerousInstr(PVM pVM, RTRCUINTPTR GCPtr); #ifdef IN_RING3 @@ -151,149 +76,25 @@ VMMDECL(bool) CSAMIsKnownDangerousInstr(PVM pVM, RTRCUINTPTR GCPtr); * @{ */ -/** - * Query CSAM state (enabled/disabled) - * - * @returns 0 - disabled, 1 - enabled - * @param pVM The VM to operate on. - */ -VMMR3DECL(int) CSAMR3IsEnabled(PVM pVM); +VMMR3DECL(bool) CSAMR3IsEnabled(PUVM pUVM); +VMMR3DECL(int) CSAMR3SetScanningEnabled(PUVM pUVM, bool fEnabled); -/** - * Initializes the csam. - * - * @returns VBox status code. - * @param pVM The VM to operate on. - */ -VMMR3DECL(int) CSAMR3Init(PVM pVM); +VMMR3_INT_DECL(int) CSAMR3Init(PVM pVM); +VMMR3_INT_DECL(void) CSAMR3Relocate(PVM pVM, RTGCINTPTR offDelta); +VMMR3_INT_DECL(int) CSAMR3Term(PVM pVM); +VMMR3_INT_DECL(int) CSAMR3Reset(PVM pVM); -/** - * Applies relocations to data and code managed by this - * component. This function will be called at init and - * whenever the VMM need to relocate it self inside the GC. - * - * The csam will update the addresses used by the switcher. - * - * @param pVM The VM. - * @param offDelta Relocation delta. - */ -VMMR3DECL(void) CSAMR3Relocate(PVM pVM, RTGCINTPTR offDelta); - -/** - * Terminates the csam. - * - * Termination means cleaning up and freeing all resources, - * the VM it self is at this point powered off or suspended. - * - * @returns VBox status code. - * @param pVM The VM to operate on. - */ -VMMR3DECL(int) CSAMR3Term(PVM pVM); - -/** - * CSAM reset callback. - * - * @returns VBox status code. - * @param pVM The VM which is reset. - */ -VMMR3DECL(int) CSAMR3Reset(PVM pVM); +VMMR3_INT_DECL(int) CSAMR3FlushPage(PVM pVM, RTRCPTR addr); +VMMR3_INT_DECL(int) CSAMR3RemovePage(PVM pVM, RTRCPTR addr); +VMMR3_INT_DECL(int) CSAMR3CheckCode(PVM pVM, RTRCPTR pInstrGC); +VMMR3_INT_DECL(int) CSAMR3CheckCodeEx(PVM pVM, PCPUMCTXCORE pCtxCore, RTRCPTR pInstrGC); +VMMR3_INT_DECL(int) CSAMR3MarkCode(PVM pVM, RTRCPTR pInstr, uint32_t cbInstr, bool fScanned); +VMMR3_INT_DECL(int) CSAMR3DoPendingAction(PVM pVM, PVMCPU pVCpu); +VMMR3_INT_DECL(int) CSAMR3CheckGates(PVM pVM, uint32_t iGate, uint32_t cGates); - -/** - * Notify CSAM of a page flush - * - * @returns VBox status code - * @param pVM The VM to operate on. - * @param addr GC address of the page to flush - */ -VMMR3DECL(int) CSAMR3FlushPage(PVM pVM, RTRCPTR addr); - -/** - * Remove a CSAM monitored page. Use with care! - * - * @returns VBox status code - * @param pVM The VM to operate on. - * @param addr GC address of the page to flush - */ -VMMR3DECL(int) CSAMR3RemovePage(PVM pVM, RTRCPTR addr); - -/** - * Scan and analyse code - * - * @returns VBox status code. - * @param pVM The VM to operate on. - * @param pCtxCore CPU context - * @param pInstrGC Instruction pointer - */ -VMMR3DECL(int) CSAMR3CheckCodeEx(PVM pVM, PCPUMCTXCORE pCtxCore, RTRCPTR pInstrGC); - -/** - * Scan and analyse code - * - * @returns VBox status code. - * @param pVM The VM to operate on. - * @param pInstrGC Instruction pointer (0:32 virtual address) - */ -VMMR3DECL(int) CSAMR3CheckCode(PVM pVM, RTRCPTR pInstrGC); - -/** - * Mark an instruction in a page as scanned/not scanned - * - * @returns VBox status code. - * @param pVM The VM to operate on. - * @param pInstr Instruction pointer - * @param cbInstr Instruction size - * @param fScanned Mark as scanned or not - */ -VMMR3DECL(int) CSAMR3MarkCode(PVM pVM, RTRCPTR pInstr, uint32_t cbInstr, bool fScanned); - -/** - * Perform any pending actions - * - * @returns VBox status code. - * @param pVM The VM to operate on. - * @param pVCpu The VMCPU to operate on. - */ -VMMR3DECL(int) CSAMR3DoPendingAction(PVM pVM, PVMCPU pVCpu); - -/** - * Monitors a code page (if not already monitored) - * - * @returns VBox status code - * @param pVM The VM to operate on. - * @param pPageAddrGC The page to monitor - * @param enmTag Monitor tag - */ -VMMR3DECL(int) CSAMR3MonitorPage(PVM pVM, RTRCPTR pPageAddrGC, CSAMTAG enmTag); - -/** - * Unmonitors a code page - * - * @returns VBox status code - * @param pVM The VM to operate on. - * @param pPageAddrGC The page to monitor - * @param enmTag Monitor tag - */ -VMMR3DECL(int) CSAMR3UnmonitorPage(PVM pVM, RTRCPTR pPageAddrGC, CSAMTAG enmTag); - -/** - * Analyse interrupt and trap gates - * - * @returns VBox status code. - * @param pVM The VM to operate on. - * @param iGate Start gate - * @param cGates Number of gates to check - */ -VMMR3DECL(int) CSAMR3CheckGates(PVM pVM, uint32_t iGate, uint32_t cGates); - -/** - * Record previous call instruction addresses - * - * @returns VBox status code. - * @param pVM The VM to operate on. - * @param GCPtrCall Call address - */ -VMMR3DECL(int) CSAMR3RecordCallAddress(PVM pVM, RTRCPTR GCPtrCall); +VMMR3DECL(int) CSAMR3MonitorPage(PVM pVM, RTRCPTR pPageAddrGC, CSAMTAG enmTag); +VMMR3DECL(int) CSAMR3UnmonitorPage(PVM pVM, RTRCPTR pPageAddrGC, CSAMTAG enmTag); +VMMR3DECL(int) CSAMR3RecordCallAddress(PVM pVM, RTRCPTR GCPtrCall); /** @} */ #endif @@ -302,4 +103,7 @@ VMMR3DECL(int) CSAMR3RecordCallAddress(PVM pVM, RTRCPTR GCPtrCall); /** @} */ RT_C_DECLS_END +#endif /* VBOX_WITH_RAW_MODE */ + #endif + diff --git a/include/VBox/vmm/dbgf.h b/include/VBox/vmm/dbgf.h index 65bb94c7..9aa4be5b 100644 --- a/include/VBox/vmm/dbgf.h +++ b/include/VBox/vmm/dbgf.h @@ -3,7 +3,7 @@ */ /* - * Copyright (C) 2006-2010 Oracle Corporation + * Copyright (C) 2006-2013 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -46,8 +46,8 @@ RT_C_DECLS_BEGIN * @ingroup grp_dbgf * @{ */ -VMMRZDECL(int) DBGFRZTrap01Handler(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, RTGCUINTREG uDr6); -VMMRZDECL(int) DBGFRZTrap03Handler(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame); +VMMRZ_INT_DECL(int) DBGFRZTrap01Handler(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, RTGCUINTREG uDr6, bool fAltStepping); +VMMRZ_INT_DECL(int) DBGFRZTrap03Handler(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame); /** @} */ #endif @@ -114,14 +114,14 @@ typedef const DBGFADDRESS *PCDBGFADDRESS; #define DBGFADDRESS_IS_HMA(pAddress) ( !!((pAddress)->fFlags & DBGFADDRESS_FLAGS_HMA) ) /** @} */ -VMMR3DECL(int) DBGFR3AddrFromSelOff(PVM pVM, VMCPUID idCpu, PDBGFADDRESS pAddress, RTSEL Sel, RTUINTPTR off); -VMMR3DECL(int) DBGFR3AddrFromSelInfoOff(PVM pVM, PDBGFADDRESS pAddress, PCDBGFSELINFO pSelInfo, RTUINTPTR off); -VMMR3DECL(PDBGFADDRESS) DBGFR3AddrFromFlat(PVM pVM, PDBGFADDRESS pAddress, RTGCUINTPTR FlatPtr); -VMMR3DECL(PDBGFADDRESS) DBGFR3AddrFromPhys(PVM pVM, PDBGFADDRESS pAddress, RTGCPHYS PhysAddr); -VMMR3DECL(bool) DBGFR3AddrIsValid(PVM pVM, PCDBGFADDRESS pAddress); -VMMR3DECL(int) DBGFR3AddrToPhys(PVM pVM, VMCPUID idCpu, PDBGFADDRESS pAddress, PRTGCPHYS pGCPhys); -VMMR3DECL(int) DBGFR3AddrToHostPhys(PVM pVM, VMCPUID idCpu, PDBGFADDRESS pAddress, PRTHCPHYS pHCPhys); -VMMR3DECL(int) DBGFR3AddrToVolatileR3Ptr(PVM pVM, VMCPUID idCpu, PDBGFADDRESS pAddress, bool fReadOnly, void **ppvR3Ptr); +VMMR3DECL(int) DBGFR3AddrFromSelOff(PUVM pUVM, VMCPUID idCpu, PDBGFADDRESS pAddress, RTSEL Sel, RTUINTPTR off); +VMMR3DECL(int) DBGFR3AddrFromSelInfoOff(PUVM pUVM, PDBGFADDRESS pAddress, PCDBGFSELINFO pSelInfo, RTUINTPTR off); +VMMR3DECL(PDBGFADDRESS) DBGFR3AddrFromFlat(PUVM pUVM, PDBGFADDRESS pAddress, RTGCUINTPTR FlatPtr); +VMMR3DECL(PDBGFADDRESS) DBGFR3AddrFromPhys(PUVM pUVM, PDBGFADDRESS pAddress, RTGCPHYS PhysAddr); +VMMR3DECL(bool) DBGFR3AddrIsValid(PUVM pUVM, PCDBGFADDRESS pAddress); +VMMR3DECL(int) DBGFR3AddrToPhys(PUVM pUVM, VMCPUID idCpu, PDBGFADDRESS pAddress, PRTGCPHYS pGCPhys); +VMMR3DECL(int) DBGFR3AddrToHostPhys(PUVM pUVM, VMCPUID idCpu, PDBGFADDRESS pAddress, PRTHCPHYS pHCPhys); +VMMR3DECL(int) DBGFR3AddrToVolatileR3Ptr(PUVM pUVM, VMCPUID idCpu, PDBGFADDRESS pAddress, bool fReadOnly, void **ppvR3Ptr); VMMR3DECL(PDBGFADDRESS) DBGFR3AddrAdd(PDBGFADDRESS pAddress, RTGCUINTPTR uAddend); VMMR3DECL(PDBGFADDRESS) DBGFR3AddrSub(PDBGFADDRESS pAddress, RTGCUINTPTR uSubtrahend); @@ -179,10 +179,10 @@ typedef enum DBGFEVENTTYPE * to bring up the debugger at a specific place. */ DBGFEVENT_DEV_STOP, - /** The VM is terminating. + /** The VM is powering off. * When this notification is received, the debugger thread should detach ASAP. */ - DBGFEVENT_TERMINATING, + DBGFEVENT_POWERING_OFF, /** The usual 32-bit hack. */ DBGFEVENT_32BIT_HACK = 0x7fffffff @@ -201,7 +201,7 @@ typedef enum DBGFEVENTCTX /** Recompiled mode. */ DBGFEVENTCTX_REM, /** VMX / AVT mode. */ - DBGFEVENTCTX_HWACCL, + DBGFEVENTCTX_HM, /** Hypervisor context. */ DBGFEVENTCTX_HYPER, /** Other mode */ @@ -281,24 +281,29 @@ typedef const DBGFEVENT *PCDBGFEVENT; # define DBGFSTOP(pVM) VINF_SUCCESS # endif -VMMR3DECL(int) DBGFR3Init(PVM pVM); -VMMR3DECL(int) DBGFR3Term(PVM pVM); -VMMR3DECL(void) DBGFR3Relocate(PVM pVM, RTGCINTPTR offDelta); -VMMR3DECL(int) DBGFR3VMMForcedAction(PVM pVM); -VMMR3DECL(int) DBGFR3Event(PVM pVM, DBGFEVENTTYPE enmEvent); -VMMR3DECL(int) DBGFR3EventSrc(PVM pVM, DBGFEVENTTYPE enmEvent, const char *pszFile, unsigned uLine, const char *pszFunction, const char *pszFormat, ...); -VMMR3DECL(int) DBGFR3EventSrcV(PVM pVM, DBGFEVENTTYPE enmEvent, const char *pszFile, unsigned uLine, const char *pszFunction, const char *pszFormat, va_list args); -VMMR3DECL(int) DBGFR3EventAssertion(PVM pVM, DBGFEVENTTYPE enmEvent, const char *pszMsg1, const char *pszMsg2); -VMMR3DECL(int) DBGFR3EventBreakpoint(PVM pVM, DBGFEVENTTYPE enmEvent); -VMMR3DECL(int) DBGFR3Attach(PVM pVM); -VMMR3DECL(int) DBGFR3Detach(PVM pVM); -VMMR3DECL(int) DBGFR3EventWait(PVM pVM, RTMSINTERVAL cMillies, PCDBGFEVENT *ppEvent); -VMMR3DECL(int) DBGFR3Halt(PVM pVM); -VMMR3DECL(bool) DBGFR3IsHalted(PVM pVM); -VMMR3DECL(bool) DBGFR3CanWait(PVM pVM); -VMMR3DECL(int) DBGFR3Resume(PVM pVM); -VMMR3DECL(int) DBGFR3Step(PVM pVM, VMCPUID idCpu); -VMMR3DECL(int) DBGFR3PrgStep(PVMCPU pVCpu); +VMMR3_INT_DECL(int) DBGFR3Init(PVM pVM); +VMMR3_INT_DECL(int) DBGFR3Term(PVM pVM); +VMMR3_INT_DECL(void) DBGFR3PowerOff(PVM pVM); +VMMR3_INT_DECL(void) DBGFR3Relocate(PVM pVM, RTGCINTPTR offDelta); +VMMR3_INT_DECL(int) DBGFR3VMMForcedAction(PVM pVM); +VMMR3DECL(int) DBGFR3Event(PVM pVM, DBGFEVENTTYPE enmEvent); +VMMR3DECL(int) DBGFR3EventSrc(PVM pVM, DBGFEVENTTYPE enmEvent, const char *pszFile, unsigned uLine, + const char *pszFunction, const char *pszFormat, ...); +VMMR3DECL(int) DBGFR3EventSrcV(PVM pVM, DBGFEVENTTYPE enmEvent, const char *pszFile, unsigned uLine, + const char *pszFunction, const char *pszFormat, va_list args); +VMMR3_INT_DECL(int) DBGFR3EventAssertion(PVM pVM, DBGFEVENTTYPE enmEvent, const char *pszMsg1, const char *pszMsg2); +VMMR3_INT_DECL(int) DBGFR3EventBreakpoint(PVM pVM, DBGFEVENTTYPE enmEvent); +VMMR3_INT_DECL(int) DBGFR3PrgStep(PVMCPU pVCpu); + +VMMR3DECL(int) DBGFR3Attach(PUVM pUVM); +VMMR3DECL(int) DBGFR3Detach(PUVM pUVM); +VMMR3DECL(int) DBGFR3EventWait(PUVM pUVM, RTMSINTERVAL cMillies, PCDBGFEVENT *ppEvent); +VMMR3DECL(int) DBGFR3Halt(PUVM pUVM); +VMMR3DECL(bool) DBGFR3IsHalted(PUVM pUVM); +VMMR3DECL(int) DBGFR3QueryWaitable(PUVM pUVM); +VMMR3DECL(int) DBGFR3Resume(PUVM pUVM); +VMMR3DECL(int) DBGFR3Step(PUVM pUVM, VMCPUID idCpu); +VMMR3DECL(int) DBGFR3InjectNMI(PUVM pUVM, VMCPUID idCpu); #endif /* IN_RING3 */ @@ -384,39 +389,44 @@ typedef DBGFBP *PDBGFBP; typedef const DBGFBP *PCDBGFBP; #ifdef IN_RING3 /* The breakpoint management API is only available in ring-3. */ -VMMR3DECL(int) DBGFR3BpSet(PVM pVM, PCDBGFADDRESS pAddress, uint64_t iHitTrigger, uint64_t iHitDisable, uint32_t *piBp); -VMMR3DECL(int) DBGFR3BpSetReg(PVM pVM, PCDBGFADDRESS pAddress, uint64_t iHitTrigger, uint64_t iHitDisable, +VMMR3DECL(int) DBGFR3BpSet(PUVM pUVM, PCDBGFADDRESS pAddress, uint64_t iHitTrigger, uint64_t iHitDisable, uint32_t *piBp); +VMMR3DECL(int) DBGFR3BpSetReg(PUVM pUVM, PCDBGFADDRESS pAddress, uint64_t iHitTrigger, uint64_t iHitDisable, uint8_t fType, uint8_t cb, uint32_t *piBp); -VMMR3DECL(int) DBGFR3BpSetREM(PVM pVM, PCDBGFADDRESS pAddress, uint64_t iHitTrigger, uint64_t iHitDisable, uint32_t *piBp); -VMMR3DECL(int) DBGFR3BpClear(PVM pVM, uint32_t iBp); -VMMR3DECL(int) DBGFR3BpEnable(PVM pVM, uint32_t iBp); -VMMR3DECL(int) DBGFR3BpDisable(PVM pVM, uint32_t iBp); +VMMR3DECL(int) DBGFR3BpSetREM(PUVM pUVM, PCDBGFADDRESS pAddress, uint64_t iHitTrigger, uint64_t iHitDisable, uint32_t *piBp); +VMMR3DECL(int) DBGFR3BpClear(PUVM pUVM, uint32_t iBp); +VMMR3DECL(int) DBGFR3BpEnable(PUVM pUVM, uint32_t iBp); +VMMR3DECL(int) DBGFR3BpDisable(PUVM pUVM, uint32_t iBp); /** * Breakpoint enumeration callback function. * * @returns VBox status code. Any failure will stop the enumeration. - * @param pVM The VM handle. + * @param pUVM The user mode VM handle. * @param pvUser The user argument. * @param pBp Pointer to the breakpoint information. (readonly) */ -typedef DECLCALLBACK(int) FNDBGFBPENUM(PVM pVM, void *pvUser, PCDBGFBP pBp); +typedef DECLCALLBACK(int) FNDBGFBPENUM(PUVM pUVM, void *pvUser, PCDBGFBP pBp); /** Pointer to a breakpoint enumeration callback function. */ typedef FNDBGFBPENUM *PFNDBGFBPENUM; -VMMR3DECL(int) DBGFR3BpEnum(PVM pVM, PFNDBGFBPENUM pfnCallback, void *pvUser); +VMMR3DECL(int) DBGFR3BpEnum(PUVM pUVM, PFNDBGFBPENUM pfnCallback, void *pvUser); #endif /* IN_RING3 */ -VMMDECL(RTGCUINTREG) DBGFBpGetDR7(PVM pVM); -VMMDECL(RTGCUINTREG) DBGFBpGetDR0(PVM pVM); -VMMDECL(RTGCUINTREG) DBGFBpGetDR1(PVM pVM); -VMMDECL(RTGCUINTREG) DBGFBpGetDR2(PVM pVM); -VMMDECL(RTGCUINTREG) DBGFBpGetDR3(PVM pVM); -VMMDECL(bool) DBGFIsStepping(PVMCPU pVCpu); +VMM_INT_DECL(RTGCUINTREG) DBGFBpGetDR7(PVM pVM); +VMM_INT_DECL(RTGCUINTREG) DBGFBpGetDR0(PVM pVM); +VMM_INT_DECL(RTGCUINTREG) DBGFBpGetDR1(PVM pVM); +VMM_INT_DECL(RTGCUINTREG) DBGFBpGetDR2(PVM pVM); +VMM_INT_DECL(RTGCUINTREG) DBGFBpGetDR3(PVM pVM); +VMM_INT_DECL(bool) DBGFBpIsHwArmed(PVM pVM); +VMM_INT_DECL(bool) DBGFBpIsHwIoArmed(PVM pVM); +VMM_INT_DECL(bool) DBGFIsStepping(PVMCPU pVCpu); +VMM_INT_DECL(VBOXSTRICTRC) DBGFBpCheckIo(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, RTIOPORT uIoPort, uint8_t cbValue); #ifdef IN_RING3 /* The CPU mode API only works in ring-3. */ -VMMR3DECL(CPUMMODE) DBGFR3CpuGetMode(PVM pVM, VMCPUID idCpu); +VMMR3DECL(CPUMMODE) DBGFR3CpuGetMode(PUVM pUVM, VMCPUID idCpu); +VMMR3DECL(VMCPUID) DBGFR3CpuGetCount(PUVM pUVM); +VMMR3DECL(bool) DBGFR3CpuIsIn64BitCode(PUVM pUVM, VMCPUID idCpu); #endif @@ -510,37 +520,37 @@ typedef FNDBGFHANDLEREXT *PFNDBGFHANDLEREXT; #define DBGFINFO_FLAGS_RUN_ON_EMT RT_BIT(0) /** @} */ -VMMR3DECL(int) DBGFR3InfoRegisterDevice(PVM pVM, const char *pszName, const char *pszDesc, PFNDBGFHANDLERDEV pfnHandler, PPDMDEVINS pDevIns); -VMMR3DECL(int) DBGFR3InfoRegisterDriver(PVM pVM, const char *pszName, const char *pszDesc, PFNDBGFHANDLERDRV pfnHandler, PPDMDRVINS pDrvIns); -VMMR3DECL(int) DBGFR3InfoRegisterInternal(PVM pVM, const char *pszName, const char *pszDesc, PFNDBGFHANDLERINT pfnHandler); -VMMR3DECL(int) DBGFR3InfoRegisterInternalEx(PVM pVM, const char *pszName, const char *pszDesc, PFNDBGFHANDLERINT pfnHandler, uint32_t fFlags); -VMMR3DECL(int) DBGFR3InfoRegisterExternal(PVM pVM, const char *pszName, const char *pszDesc, PFNDBGFHANDLEREXT pfnHandler, void *pvUser); -VMMR3DECL(int) DBGFR3InfoDeregisterDevice(PVM pVM, PPDMDEVINS pDevIns, const char *pszName); -VMMR3DECL(int) DBGFR3InfoDeregisterDriver(PVM pVM, PPDMDRVINS pDrvIns, const char *pszName); -VMMR3DECL(int) DBGFR3InfoDeregisterInternal(PVM pVM, const char *pszName); -VMMR3DECL(int) DBGFR3InfoDeregisterExternal(PVM pVM, const char *pszName); -VMMR3DECL(int) DBGFR3Info(PVM pVM, const char *pszName, const char *pszArgs, PCDBGFINFOHLP pHlp); -VMMR3DECL(int) DBGFR3InfoEx(PVM pVM, VMCPUID idCpu, const char *pszName, const char *pszArgs, PCDBGFINFOHLP pHlp); -VMMR3DECL(int) DBGFR3InfoLogRel(PVM pVM, const char *pszName, const char *pszArgs); -VMMR3DECL(int) DBGFR3InfoStdErr(PVM pVM, const char *pszName, const char *pszArgs); -VMMR3DECL(int) DBGFR3InfoMulti(PVM pVM, const char *pszIncludePat, const char *pszExcludePat, - const char *pszSepFmt, PCDBGFINFOHLP pHlp); +VMMR3_INT_DECL(int) DBGFR3InfoRegisterDevice(PVM pVM, const char *pszName, const char *pszDesc, PFNDBGFHANDLERDEV pfnHandler, PPDMDEVINS pDevIns); +VMMR3_INT_DECL(int) DBGFR3InfoRegisterDriver(PVM pVM, const char *pszName, const char *pszDesc, PFNDBGFHANDLERDRV pfnHandler, PPDMDRVINS pDrvIns); +VMMR3_INT_DECL(int) DBGFR3InfoRegisterInternal(PVM pVM, const char *pszName, const char *pszDesc, PFNDBGFHANDLERINT pfnHandler); +VMMR3_INT_DECL(int) DBGFR3InfoRegisterInternalEx(PVM pVM, const char *pszName, const char *pszDesc, PFNDBGFHANDLERINT pfnHandler, uint32_t fFlags); +VMMR3DECL(int) DBGFR3InfoRegisterExternal(PUVM pUVM, const char *pszName, const char *pszDesc, PFNDBGFHANDLEREXT pfnHandler, void *pvUser); +VMMR3_INT_DECL(int) DBGFR3InfoDeregisterDevice(PVM pVM, PPDMDEVINS pDevIns, const char *pszName); +VMMR3_INT_DECL(int) DBGFR3InfoDeregisterDriver(PVM pVM, PPDMDRVINS pDrvIns, const char *pszName); +VMMR3_INT_DECL(int) DBGFR3InfoDeregisterInternal(PVM pVM, const char *pszName); +VMMR3DECL(int) DBGFR3InfoDeregisterExternal(PUVM pUVM, const char *pszName); +VMMR3DECL(int) DBGFR3Info(PUVM pUVM, const char *pszName, const char *pszArgs, PCDBGFINFOHLP pHlp); +VMMR3DECL(int) DBGFR3InfoEx(PUVM pUVM, VMCPUID idCpu, const char *pszName, const char *pszArgs, PCDBGFINFOHLP pHlp); +VMMR3DECL(int) DBGFR3InfoLogRel(PUVM pUVM, const char *pszName, const char *pszArgs); +VMMR3DECL(int) DBGFR3InfoStdErr(PUVM pUVM, const char *pszName, const char *pszArgs); +VMMR3_INT_DECL(int) DBGFR3InfoMulti(PVM pVM, const char *pszIncludePat, const char *pszExcludePat, + const char *pszSepFmt, PCDBGFINFOHLP pHlp); /** @def DBGFR3InfoLog * Display a piece of info writing to the log if enabled. * - * @param pVM VM handle. - * @param pszName The identifier of the info to display. - * @param pszArgs Arguments to the info handler. + * @param a_pVM The shared VM handle. + * @param a_pszName The identifier of the info to display. + * @param a_pszArgs Arguments to the info handler. */ #ifdef LOG_ENABLED -#define DBGFR3InfoLog(pVM, pszName, pszArgs) \ +# define DBGFR3_INFO_LOG(a_pVM, a_pszName, a_pszArgs) \ do { \ if (LogIsEnabled()) \ - DBGFR3Info(pVM, pszName, pszArgs, NULL); \ + DBGFR3Info((a_pVM)->pUVM, a_pszName, a_pszArgs, NULL); \ } while (0) #else -#define DBGFR3InfoLog(pVM, pszName, pszArgs) do { } while (0) +# define DBGFR3_INFO_LOG(a_pVM, a_pszName, a_pszArgs) do { } while (0) #endif /** @@ -549,15 +559,15 @@ VMMR3DECL(int) DBGFR3InfoMulti(PVM pVM, const char *pszIncludePat, const char *p * @returns VBox status code. * A status code indicating failure will end the enumeration * and DBGFR3InfoEnum will return with that status code. - * @param pVM VM handle. + * @param pUVM The user mode VM handle. * @param pszName Info identifier name. * @param pszDesc The description. */ -typedef DECLCALLBACK(int) FNDBGFINFOENUM(PVM pVM, const char *pszName, const char *pszDesc, void *pvUser); +typedef DECLCALLBACK(int) FNDBGFINFOENUM(PUVM pUVM, const char *pszName, const char *pszDesc, void *pvUser); /** Pointer to a FNDBGFINFOENUM function. */ typedef FNDBGFINFOENUM *PFNDBGFINFOENUM; -VMMR3DECL(int) DBGFR3InfoEnum(PVM pVM, PFNDBGFINFOENUM pfnCallback, void *pvUser); +VMMR3DECL(int) DBGFR3InfoEnum(PUVM pUVM, PFNDBGFINFOENUM pfnCallback, void *pvUser); VMMR3DECL(PCDBGFINFOHLP) DBGFR3InfoLogHlp(void); VMMR3DECL(PCDBGFINFOHLP) DBGFR3InfoLogRelHlp(void); @@ -565,9 +575,9 @@ VMMR3DECL(PCDBGFINFOHLP) DBGFR3InfoLogRelHlp(void); #ifdef IN_RING3 /* The log contrl API only works in ring-3. */ -VMMR3DECL(int) DBGFR3LogModifyGroups(PVM pVM, const char *pszGroupSettings); -VMMR3DECL(int) DBGFR3LogModifyFlags(PVM pVM, const char *pszFlagSettings); -VMMR3DECL(int) DBGFR3LogModifyDestinations(PVM pVM, const char *pszDestSettings); +VMMR3DECL(int) DBGFR3LogModifyGroups(PUVM pUVM, const char *pszGroupSettings); +VMMR3DECL(int) DBGFR3LogModifyFlags(PUVM pUVM, const char *pszFlagSettings); +VMMR3DECL(int) DBGFR3LogModifyDestinations(PUVM pUVM, const char *pszDestSettings); #endif /* IN_RING3 */ #ifdef IN_RING3 /* The debug information management APIs only works in ring-3. */ @@ -650,33 +660,32 @@ typedef const DBGFLINE *PCDBGFLINE; /** @} */ -VMMR3DECL(int) DBGFR3AsAdd(PVM pVM, RTDBGAS hDbgAs, RTPROCESS ProcId); -VMMR3DECL(int) DBGFR3AsDelete(PVM pVM, RTDBGAS hDbgAs); -VMMR3DECL(int) DBGFR3AsSetAlias(PVM pVM, RTDBGAS hAlias, RTDBGAS hAliasFor); -VMMR3DECL(RTDBGAS) DBGFR3AsResolve(PVM pVM, RTDBGAS hAlias); -VMMR3DECL(RTDBGAS) DBGFR3AsResolveAndRetain(PVM pVM, RTDBGAS hAlias); -VMMR3DECL(RTDBGAS) DBGFR3AsQueryByName(PVM pVM, const char *pszName); -VMMR3DECL(RTDBGAS) DBGFR3AsQueryByPid(PVM pVM, RTPROCESS ProcId); - -VMMR3DECL(int) DBGFR3AsLoadImage(PVM pVM, RTDBGAS hDbgAs, const char *pszFilename, const char *pszModName, PCDBGFADDRESS pModAddress, RTDBGSEGIDX iModSeg, uint32_t fFlags); -VMMR3DECL(int) DBGFR3AsLoadMap(PVM pVM, RTDBGAS hDbgAs, const char *pszFilename, const char *pszModName, PCDBGFADDRESS pModAddress, RTDBGSEGIDX iModSeg, RTGCUINTPTR uSubtrahend, uint32_t fFlags); -VMMR3DECL(int) DBGFR3AsLinkModule(PVM pVM, RTDBGAS hDbgAs, RTDBGMOD hMod, PCDBGFADDRESS pModAddress, RTDBGSEGIDX iModSeg, uint32_t fFlags); - -VMMR3DECL(int) DBGFR3AsSymbolByAddr(PVM pVM, RTDBGAS hDbgAs, PCDBGFADDRESS pAddress, PRTGCINTPTR poffDisp, PRTDBGSYMBOL pSymbol, PRTDBGMOD phMod); -VMMR3DECL(PRTDBGSYMBOL) DBGFR3AsSymbolByAddrA(PVM pVM, RTDBGAS hDbgAs, PCDBGFADDRESS pAddress, PRTGCINTPTR poffDisp, PRTDBGMOD phMod); -VMMR3DECL(int) DBGFR3AsSymbolByName(PVM pVM, RTDBGAS hDbgAs, const char *pszSymbol, PRTDBGSYMBOL pSymbol, PRTDBGMOD phMod); - -/* The following are soon to be obsoleted: */ -VMMR3DECL(int) DBGFR3ModuleLoad(PVM pVM, const char *pszFilename, RTGCUINTPTR AddressDelta, const char *pszName, RTGCUINTPTR ModuleAddress, unsigned cbImage); -VMMR3DECL(void) DBGFR3ModuleRelocate(PVM pVM, RTGCUINTPTR OldImageBase, RTGCUINTPTR NewImageBase, RTGCUINTPTR cbImage, - const char *pszFilename, const char *pszName); -VMMR3DECL(int) DBGFR3SymbolAdd(PVM pVM, RTGCUINTPTR ModuleAddress, RTGCUINTPTR SymbolAddress, RTUINT cbSymbol, const char *pszSymbol); -VMMR3DECL(int) DBGFR3SymbolByAddr(PVM pVM, RTGCUINTPTR Address, PRTGCINTPTR poffDisplacement, PDBGFSYMBOL pSymbol); -VMMR3DECL(int) DBGFR3SymbolByName(PVM pVM, const char *pszSymbol, PDBGFSYMBOL pSymbol); - -VMMR3DECL(int) DBGFR3LineByAddr(PVM pVM, RTGCUINTPTR Address, PRTGCINTPTR poffDisplacement, PDBGFLINE pLine); -VMMR3DECL(PDBGFLINE) DBGFR3LineByAddrAlloc(PVM pVM, RTGCUINTPTR Address, PRTGCINTPTR poffDisplacement); -VMMR3DECL(void) DBGFR3LineFree(PDBGFLINE pLine); +VMMR3DECL(RTDBGCFG) DBGFR3AsGetConfig(PUVM pUVM); + +VMMR3DECL(int) DBGFR3AsAdd(PUVM pUVM, RTDBGAS hDbgAs, RTPROCESS ProcId); +VMMR3DECL(int) DBGFR3AsDelete(PUVM pUVM, RTDBGAS hDbgAs); +VMMR3DECL(int) DBGFR3AsSetAlias(PUVM pUVM, RTDBGAS hAlias, RTDBGAS hAliasFor); +VMMR3DECL(RTDBGAS) DBGFR3AsResolve(PUVM pUVM, RTDBGAS hAlias); +VMMR3DECL(RTDBGAS) DBGFR3AsResolveAndRetain(PUVM pUVM, RTDBGAS hAlias); +VMMR3DECL(RTDBGAS) DBGFR3AsQueryByName(PUVM pUVM, const char *pszName); +VMMR3DECL(RTDBGAS) DBGFR3AsQueryByPid(PUVM pUVM, RTPROCESS ProcId); + +VMMR3DECL(int) DBGFR3AsLoadImage(PUVM pUVM, RTDBGAS hDbgAs, const char *pszFilename, const char *pszModName, + RTLDRARCH enmArch, PCDBGFADDRESS pModAddress, RTDBGSEGIDX iModSeg, uint32_t fFlags); +VMMR3DECL(int) DBGFR3AsLoadMap(PUVM pUVM, RTDBGAS hDbgAs, const char *pszFilename, const char *pszModName, PCDBGFADDRESS pModAddress, RTDBGSEGIDX iModSeg, RTGCUINTPTR uSubtrahend, uint32_t fFlags); +VMMR3DECL(int) DBGFR3AsLinkModule(PUVM pUVM, RTDBGAS hDbgAs, RTDBGMOD hMod, PCDBGFADDRESS pModAddress, RTDBGSEGIDX iModSeg, uint32_t fFlags); +VMMR3DECL(int) DBGFR3AsUnlinkModuleByName(PUVM pUVM, RTDBGAS hDbgAs, const char *pszModName); + +VMMR3DECL(int) DBGFR3AsSymbolByAddr(PUVM pUVM, RTDBGAS hDbgAs, PCDBGFADDRESS pAddress, uint32_t fFlags, + PRTGCINTPTR poffDisp, PRTDBGSYMBOL pSymbol, PRTDBGMOD phMod); +VMMR3DECL(PRTDBGSYMBOL) DBGFR3AsSymbolByAddrA(PUVM pUVM, RTDBGAS hDbgAs, PCDBGFADDRESS pAddress, uint32_t Flags, + PRTGCINTPTR poffDisp, PRTDBGMOD phMod); +VMMR3DECL(int) DBGFR3AsSymbolByName(PUVM pUVM, RTDBGAS hDbgAs, const char *pszSymbol, PRTDBGSYMBOL pSymbol, PRTDBGMOD phMod); + +VMMR3DECL(int) DBGFR3AsLineByAddr(PUVM pUVM, RTDBGAS hDbgAs, PCDBGFADDRESS pAddress, + PRTGCINTPTR poffDisp, PRTDBGLINE pLine, PRTDBGMOD phMod); +VMMR3DECL(PRTDBGLINE) DBGFR3AsLineByAddrA(PUVM pUVM, RTDBGAS hDbgAs, PCDBGFADDRESS pAddress, + PRTGCINTPTR poffDisp, PRTDBGMOD phMod); #endif /* IN_RING3 */ @@ -769,7 +778,7 @@ typedef struct DBGFSTACKFRAME /** Pointer to the symbol nearest the program counter (PC). NULL if not found. */ PRTDBGSYMBOL pSymPC; /** Pointer to the linnumber nearest the program counter (PC). NULL if not found. */ - PDBGFLINE pLinePC; + PRTDBGLINE pLinePC; /** The return frame address. * The off member is [e|r]bp and the Sel member is ss. */ @@ -786,7 +795,7 @@ typedef struct DBGFSTACKFRAME /** Pointer to the symbol nearest the return PC. NULL if not found. */ PRTDBGSYMBOL pSymReturnPC; /** Pointer to the linnumber nearest the return PC. NULL if not found. */ - PDBGFLINE pLineReturnPC; + PRTDBGLINE pLineReturnPC; /** 32-bytes of stack arguments. */ union @@ -846,8 +855,9 @@ typedef enum DBGFCODETYPE } DBGFCODETYPE; /** @} */ -VMMR3DECL(int) DBGFR3StackWalkBegin(PVM pVM, VMCPUID idCpu, DBGFCODETYPE enmCodeType, PCDBGFSTACKFRAME *ppFirstFrame); -VMMR3DECL(int) DBGFR3StackWalkBeginEx(PVM pVM, VMCPUID idCpu, DBGFCODETYPE enmCodeType, PCDBGFADDRESS pAddrFrame, +VMMR3DECL(int) DBGFR3StackWalkBegin(PUVM pUVM, VMCPUID idCpu, DBGFCODETYPE enmCodeType, + PCDBGFSTACKFRAME *ppFirstFrame); +VMMR3DECL(int) DBGFR3StackWalkBeginEx(PUVM pUVM, VMCPUID idCpu, DBGFCODETYPE enmCodeType, PCDBGFADDRESS pAddrFrame, PCDBGFADDRESS pAddrStack,PCDBGFADDRESS pAddrPC, DBGFRETURNTYPE enmReturnType, PCDBGFSTACKFRAME *ppFirstFrame); VMMR3DECL(PCDBGFSTACKFRAME) DBGFR3StackWalkNext(PCDBGFSTACKFRAME pCurrent); @@ -872,6 +882,12 @@ VMMR3DECL(void) DBGFR3StackWalkEnd(PCDBGFSTACKFRAME pFirstFrame); #define DBGF_DISAS_FLAGS_NO_BYTES RT_BIT(4) /** No address in the output. */ #define DBGF_DISAS_FLAGS_NO_ADDRESS RT_BIT(5) +/** Probably a hypervisor instruction. */ +#define DBGF_DISAS_FLAGS_HYPER RT_BIT(6) +/** Disassemble original unpatched bytes (PATM). */ +#define DBGF_DISAS_FLAGS_UNPATCHED_BYTES RT_BIT(7) +/** Annotate patched instructions. */ +#define DBGF_DISAS_FLAGS_ANNOTATE_PATCHED RT_BIT(8) /** Disassemble in the default mode of the specific context. */ #define DBGF_DISAS_FLAGS_DEFAULT_MODE UINT32_C(0x00000000) /** Disassemble in 16-bit mode. */ @@ -885,29 +901,29 @@ VMMR3DECL(void) DBGFR3StackWalkEnd(PCDBGFSTACKFRAME pFirstFrame); /** The disassembly mode mask. */ #define DBGF_DISAS_FLAGS_MODE_MASK UINT32_C(0x70000000) /** Mask containing the valid flags. */ -#define DBGF_DISAS_FLAGS_VALID_MASK UINT32_C(0x7000007f) +#define DBGF_DISAS_FLAGS_VALID_MASK UINT32_C(0x700001ff) /** @} */ /** Special flat selector. */ #define DBGF_SEL_FLAT 1 -VMMR3DECL(int) DBGFR3DisasInstrEx(PVM pVM, VMCPUID idCpu, RTSEL Sel, RTGCPTR GCPtr, uint32_t fFlags, - char *pszOutput, uint32_t cbOutput, uint32_t *pcbInstr); -VMMR3DECL(int) DBGFR3DisasInstrCurrent(PVMCPU pVCpu, char *pszOutput, uint32_t cbOutput); -VMMR3DECL(int) DBGFR3DisasInstrCurrentLogInternal(PVMCPU pVCpu, const char *pszPrefix); +VMMR3DECL(int) DBGFR3DisasInstrEx(PUVM pUVM, VMCPUID idCpu, RTSEL Sel, RTGCPTR GCPtr, uint32_t fFlags, + char *pszOutput, uint32_t cbOutput, uint32_t *pcbInstr); +VMMR3_INT_DECL(int) DBGFR3DisasInstrCurrent(PVMCPU pVCpu, char *pszOutput, uint32_t cbOutput); +VMMR3DECL(int) DBGFR3DisasInstrCurrentLogInternal(PVMCPU pVCpu, const char *pszPrefix); /** @def DBGFR3DisasInstrCurrentLog * Disassembles the current guest context instruction and writes it to the log. * All registers and data will be displayed. Addresses will be attempted resolved to symbols. */ #ifdef LOG_ENABLED -# define DBGFR3DisasInstrCurrentLog(pVCpu, pszPrefix) \ +# define DBGFR3_DISAS_INSTR_CUR_LOG(pVCpu, pszPrefix) \ do { \ if (LogIsEnabled()) \ DBGFR3DisasInstrCurrentLogInternal(pVCpu, pszPrefix); \ } while (0) #else -# define DBGFR3DisasInstrCurrentLog(pVCpu, pszPrefix) do { } while (0) +# define DBGFR3_DISAS_INSTR_CUR_LOG(pVCpu, pszPrefix) do { } while (0) #endif VMMR3DECL(int) DBGFR3DisasInstrLogInternal(PVMCPU pVCpu, RTSEL Sel, RTGCPTR GCPtr, const char *pszPrefix); @@ -918,23 +934,23 @@ VMMR3DECL(int) DBGFR3DisasInstrLogInternal(PVMCPU pVCpu, RTSEL Sel, RTGCPTR GCPt * @thread Any EMT. */ # ifdef LOG_ENABLED -# define DBGFR3DisasInstrLog(pVCpu, Sel, GCPtr, pszPrefix) \ +# define DBGFR3_DISAS_INSTR_LOG(pVCpu, Sel, GCPtr, pszPrefix) \ do { \ if (LogIsEnabled()) \ DBGFR3DisasInstrLogInternal(pVCpu, Sel, GCPtr, pszPrefix); \ } while (0) # else -# define DBGFR3DisasInstrLog(pVCpu, Sel, GCPtr, pszPrefix) do { } while (0) +# define DBGFR3_DISAS_INSTR_LOG(pVCpu, Sel, GCPtr, pszPrefix) do { } while (0) # endif #endif #ifdef IN_RING3 -VMMR3DECL(int) DBGFR3MemScan(PVM pVM, VMCPUID idCpu, PCDBGFADDRESS pAddress, RTGCUINTPTR cbRange, RTGCUINTPTR uAlign, +VMMR3DECL(int) DBGFR3MemScan(PUVM pUVM, VMCPUID idCpu, PCDBGFADDRESS pAddress, RTGCUINTPTR cbRange, RTGCUINTPTR uAlign, const void *pvNeedle, size_t cbNeedle, PDBGFADDRESS pHitAddress); -VMMR3DECL(int) DBGFR3MemRead(PVM pVM, VMCPUID idCpu, PCDBGFADDRESS pAddress, void *pvBuf, size_t cbRead); -VMMR3DECL(int) DBGFR3MemReadString(PVM pVM, VMCPUID idCpu, PCDBGFADDRESS pAddress, char *pszBuf, size_t cbBuf); -VMMR3DECL(int) DBGFR3MemWrite(PVM pVM, VMCPUID idCpu, PCDBGFADDRESS pAddress, void const *pvBuf, size_t cbRead); +VMMR3DECL(int) DBGFR3MemRead(PUVM pUVM, VMCPUID idCpu, PCDBGFADDRESS pAddress, void *pvBuf, size_t cbRead); +VMMR3DECL(int) DBGFR3MemReadString(PUVM pUVM, VMCPUID idCpu, PCDBGFADDRESS pAddress, char *pszBuf, size_t cbBuf); +VMMR3DECL(int) DBGFR3MemWrite(PUVM pUVM, VMCPUID idCpu, PCDBGFADDRESS pAddress, void const *pvBuf, size_t cbRead); #endif @@ -979,7 +995,7 @@ VMMR3DECL(int) DBGFR3MemWrite(PVM pVM, VMCPUID idCpu, PCDBGFADDRESS pAddress, vo /** The mask of bits controlling the paging mode. */ #define DBGFPGDMP_FLAGS_MODE_MASK UINT32_C(0x00000f32) /** @} */ -VMMDECL(int) DBGFR3PagingDumpEx(PVM pVM, VMCPUID idCpu, uint32_t fFlags, uint64_t cr3, uint64_t u64FirstAddr, +VMMDECL(int) DBGFR3PagingDumpEx(PUVM pUVM, VMCPUID idCpu, uint32_t fFlags, uint64_t cr3, uint64_t u64FirstAddr, uint64_t u64LastAddr, uint32_t cMaxDepth, PCDBGFINFOHLP pHlp); @@ -993,7 +1009,7 @@ VMMDECL(int) DBGFR3PagingDumpEx(PVM pVM, VMCPUID idCpu, uint32_t fFlags, uint64_ /** If currently executing in in 64-bit mode, blow up data selectors. */ #define DBGFSELQI_FLAGS_DT_ADJ_64BIT_MODE UINT32_C(2) /** @} */ -VMMR3DECL(int) DBGFR3SelQueryInfo(PVM pVM, VMCPUID idCpu, RTSEL Sel, uint32_t fFlags, PDBGFSELINFO pSelInfo); +VMMR3DECL(int) DBGFR3SelQueryInfo(PUVM pUVM, VMCPUID idCpu, RTSEL Sel, uint32_t fFlags, PDBGFSELINFO pSelInfo); /** @@ -1269,6 +1285,11 @@ typedef DBGFREGVALTYPE *PDBGFREGVALTYPE; */ typedef union DBGFREGVAL { + uint64_t au64[2]; /**< The 64-bit array view. First because of the initializer. */ + uint32_t au32[4]; /**< The 32-bit array view. */ + uint16_t au16[8]; /**< The 16-bit array view. */ + uint8_t au8[16]; /**< The 8-bit array view. */ + uint8_t u8; /**< The 8-bit view. */ uint16_t u16; /**< The 16-bit view. */ uint32_t u32; /**< The 32-bit view. */ @@ -1285,10 +1306,6 @@ typedef union DBGFREGVAL uint32_t u32Limit; } dtr; - uint8_t au8[16]; /**< The 8-bit array view. */ - uint16_t au16[8]; /**< The 16-bit array view. */ - uint32_t au32[4]; /**< The 32-bit array view. */ - uint64_t au64[2]; /**< The 64-bit array view. */ RTUINT128U u; } DBGFREGVAL; /** Pointer to a generic register value type. */ @@ -1296,6 +1313,12 @@ typedef DBGFREGVAL *PDBGFREGVAL; /** Pointer to a const generic register value type. */ typedef DBGFREGVAL const *PCDBGFREGVAL; +/** Initialize a DBGFREGVAL variable to all zeros. */ +#define DBGFREGVAL_INITIALIZE_ZERO { { 0, 0 } } +/** Initialize a DBGFREGVAL variable to all bits set . */ +#define DBGFREGVAL_INITIALIZE_FFFF { { UINT64_MAX, UINT64_MAX } } + + VMMDECL(ssize_t) DBGFR3RegFormatValue(char *pszBuf, size_t cbBuf, PCDBGFREGVAL pValue, DBGFREGVALTYPE enmType, bool fSpecial); VMMDECL(ssize_t) DBGFR3RegFormatValueEx(char *pszBuf, size_t cbBuf, PCDBGFREGVAL pValue, DBGFREGVALTYPE enmType, unsigned uBase, signed int cchWidth, signed int cchPrecision, uint32_t fFlags); @@ -1316,9 +1339,13 @@ typedef struct DBGFREGSUBFIELD int8_t cShift; /** Sub-field flags, DBGFREGSUBFIELD_FLAGS_XXX. */ uint8_t fFlags; - /** Getter (optional). */ + /** Getter (optional). + * @remarks Does not take the device lock or anything like that. + */ DECLCALLBACKMEMBER(int, pfnGet)(void *pvUser, struct DBGFREGSUBFIELD const *pSubField, PRTUINT128U puValue); - /** Setter (optional). */ + /** Setter (optional). + * @remarks Does not take the device lock or anything like that. + */ DECLCALLBACKMEMBER(int, pfnSet)(void *pvUser, struct DBGFREGSUBFIELD const *pSubField, RTUINT128U uValue, RTUINT128U fMask); } DBGFREGSUBFIELD; /** Pointer to a const register sub-field descriptor. */ @@ -1336,6 +1363,9 @@ typedef DBGFREGSUBFIELD const *PCDBGFREGSUBFIELD; /** Macro for creating a read-write sub-field entry with getters. */ #define DBGFREGSUBFIELD_RW_SG(a_szName, a_cBits, a_cShift, a_pfnGet, a_pfnSet) \ { a_szName, 0 /*iFirstBit*/, a_cBits, a_cShift, 0 /*fFlags*/, a_pfnGet, a_pfnSet } +/** Macro for creating a read-only sub-field entry without getters. */ +#define DBGFREGSUBFIELD_RO(a_szName, a_iFirstBit, a_cBits, a_cShift) \ + { a_szName, a_iFirstBit, a_cBits, a_cShift, DBGFREGSUBFIELD_FLAGS_READ_ONLY, NULL /*pfnGet*/, NULL /*pfnSet*/ } /** Macro for creating a terminator sub-field entry. */ #define DBGFREGSUBFIELD_TERMINATOR() \ { NULL, 0, 0, 0, 0, NULL, NULL } @@ -1370,9 +1400,13 @@ typedef struct DBGFREGDESC * For CPU registers this is the offset into the CPUMCTX structure, * thuse the 'off' prefix. */ uint32_t offRegister; - /** Getter. */ + /** Getter. + * @remarks Does not take the device lock or anything like that. + */ DECLCALLBACKMEMBER(int, pfnGet)(void *pvUser, struct DBGFREGDESC const *pDesc, PDBGFREGVAL pValue); - /** Setter. */ + /** Setter. + * @remarks Does not take the device lock or anything like that. + */ DECLCALLBACKMEMBER(int, pfnSet)(void *pvUser, struct DBGFREGDESC const *pDesc, PCDBGFREGVAL pValue, PCDBGFREGVAL pfMask); /** Aliases (optional). */ PCDBGFREGALIAS paAliases; @@ -1430,30 +1464,31 @@ typedef DBGFREGENTRY const *PCDBGFREGENTRY; * guest. */ #define DBGFREG_HYPER_VMCPUID UINT32_C(0x01000000) -VMMR3DECL(int) DBGFR3RegCpuQueryU8( PVM pVM, VMCPUID idCpu, DBGFREG enmReg, uint8_t *pu8); -VMMR3DECL(int) DBGFR3RegCpuQueryU16( PVM pVM, VMCPUID idCpu, DBGFREG enmReg, uint16_t *pu16); -VMMR3DECL(int) DBGFR3RegCpuQueryU32( PVM pVM, VMCPUID idCpu, DBGFREG enmReg, uint32_t *pu32); -VMMR3DECL(int) DBGFR3RegCpuQueryU64( PVM pVM, VMCPUID idCpu, DBGFREG enmReg, uint64_t *pu64); -VMMR3DECL(int) DBGFR3RegCpuQueryU128(PVM pVM, VMCPUID idCpu, DBGFREG enmReg, uint128_t *pu128); -VMMR3DECL(int) DBGFR3RegCpuQueryLrd( PVM pVM, VMCPUID idCpu, DBGFREG enmReg, long double *plrd); -VMMR3DECL(int) DBGFR3RegCpuQueryXdtr(PVM pVM, VMCPUID idCpu, DBGFREG enmReg, uint64_t *pu64Base, uint16_t *pu16Limit); +VMMR3DECL(int) DBGFR3RegCpuQueryU8( PUVM pUVM, VMCPUID idCpu, DBGFREG enmReg, uint8_t *pu8); +VMMR3DECL(int) DBGFR3RegCpuQueryU16( PUVM pUVM, VMCPUID idCpu, DBGFREG enmReg, uint16_t *pu16); +VMMR3DECL(int) DBGFR3RegCpuQueryU32( PUVM pUVM, VMCPUID idCpu, DBGFREG enmReg, uint32_t *pu32); +VMMR3DECL(int) DBGFR3RegCpuQueryU64( PUVM pUVM, VMCPUID idCpu, DBGFREG enmReg, uint64_t *pu64); +VMMR3DECL(int) DBGFR3RegCpuQueryU128(PUVM pUVM, VMCPUID idCpu, DBGFREG enmReg, uint128_t *pu128); +VMMR3DECL(int) DBGFR3RegCpuQueryLrd( PUVM pUVM, VMCPUID idCpu, DBGFREG enmReg, long double *plrd); +VMMR3DECL(int) DBGFR3RegCpuQueryXdtr(PUVM pUVM, VMCPUID idCpu, DBGFREG enmReg, uint64_t *pu64Base, uint16_t *pu16Limit); #if 0 -VMMR3DECL(int) DBGFR3RegCpuQueryBatch(PVM pVM,VMCPUID idCpu, PDBGFREGENTRY paRegs, size_t cRegs); -VMMR3DECL(int) DBGFR3RegCpuQueryAll( PVM pVM, VMCPUID idCpu, PDBGFREGENTRY paRegs, size_t cRegs); - -VMMR3DECL(int) DBGFR3RegCpuSetU8( PVM pVM, VMCPUID idCpu, DBGFREG enmReg, uint8_t u8); -VMMR3DECL(int) DBGFR3RegCpuSetU16( PVM pVM, VMCPUID idCpu, DBGFREG enmReg, uint16_t u16); -VMMR3DECL(int) DBGFR3RegCpuSetU32( PVM pVM, VMCPUID idCpu, DBGFREG enmReg, uint32_t u32); -VMMR3DECL(int) DBGFR3RegCpuSetU64( PVM pVM, VMCPUID idCpu, DBGFREG enmReg, uint64_t u64); -VMMR3DECL(int) DBGFR3RegCpuSetU128( PVM pVM, VMCPUID idCpu, DBGFREG enmReg, uint128_t u128); -VMMR3DECL(int) DBGFR3RegCpuSetLrd( PVM pVM, VMCPUID idCpu, DBGFREG enmReg, long double lrd); -VMMR3DECL(int) DBGFR3RegCpuSetBatch( PVM pVM, VMCPUID idCpu, PCDBGFREGENTRY paRegs, size_t cRegs); +VMMR3DECL(int) DBGFR3RegCpuQueryBatch(PUVM pUVM,VMCPUID idCpu, PDBGFREGENTRY paRegs, size_t cRegs); +VMMR3DECL(int) DBGFR3RegCpuQueryAll( PUVM pUVM, VMCPUID idCpu, PDBGFREGENTRY paRegs, size_t cRegs); + +VMMR3DECL(int) DBGFR3RegCpuSetU8( PUVM pUVM, VMCPUID idCpu, DBGFREG enmReg, uint8_t u8); +VMMR3DECL(int) DBGFR3RegCpuSetU16( PUVM pUVM, VMCPUID idCpu, DBGFREG enmReg, uint16_t u16); +VMMR3DECL(int) DBGFR3RegCpuSetU32( PUVM pUVM, VMCPUID idCpu, DBGFREG enmReg, uint32_t u32); +VMMR3DECL(int) DBGFR3RegCpuSetU64( PUVM pUVM, VMCPUID idCpu, DBGFREG enmReg, uint64_t u64); +VMMR3DECL(int) DBGFR3RegCpuSetU128( PUVM pUVM, VMCPUID idCpu, DBGFREG enmReg, uint128_t u128); +VMMR3DECL(int) DBGFR3RegCpuSetLrd( PUVM pUVM, VMCPUID idCpu, DBGFREG enmReg, long double lrd); +VMMR3DECL(int) DBGFR3RegCpuSetBatch( PUVM pUVM, VMCPUID idCpu, PCDBGFREGENTRY paRegs, size_t cRegs); #endif -VMMR3DECL(const char *) DBGFR3RegCpuName(PVM pVM, DBGFREG enmReg, DBGFREGVALTYPE enmType); +VMMR3DECL(const char *) DBGFR3RegCpuName(PUVM pUVM, DBGFREG enmReg, DBGFREGVALTYPE enmType); VMMR3_INT_DECL(int) DBGFR3RegRegisterCpu(PVM pVM, PVMCPU pVCpu, PCDBGFREGDESC paRegisters, bool fGuestRegs); -VMMR3DECL(int) DBGFR3RegRegisterDevice(PVM pVM, PCDBGFREGDESC paRegisters, PPDMDEVINS pDevIns, const char *pszPrefix, uint32_t iInstance); +VMMR3_INT_DECL(int) DBGFR3RegRegisterDevice(PVM pVM, PCDBGFREGDESC paRegisters, PPDMDEVINS pDevIns, + const char *pszPrefix, uint32_t iInstance); /** * Entry in a named batch query or set operation. @@ -1472,33 +1507,33 @@ typedef DBGFREGENTRYNM *PDBGFREGENTRYNM; /** Pointer to a const named register entry in a batch operation. */ typedef DBGFREGENTRYNM const *PCDBGFREGENTRYNM; -VMMR3DECL(int) DBGFR3RegNmValidate( PVM pVM, VMCPUID idDefCpu, const char *pszReg); - -VMMR3DECL(int) DBGFR3RegNmQuery( PVM pVM, VMCPUID idDefCpu, const char *pszReg, PDBGFREGVAL pValue, PDBGFREGVALTYPE penmType); -VMMR3DECL(int) DBGFR3RegNmQueryU8( PVM pVM, VMCPUID idDefCpu, const char *pszReg, uint8_t *pu8); -VMMR3DECL(int) DBGFR3RegNmQueryU16( PVM pVM, VMCPUID idDefCpu, const char *pszReg, uint16_t *pu16); -VMMR3DECL(int) DBGFR3RegNmQueryU32( PVM pVM, VMCPUID idDefCpu, const char *pszReg, uint32_t *pu32); -VMMR3DECL(int) DBGFR3RegNmQueryU64( PVM pVM, VMCPUID idDefCpu, const char *pszReg, uint64_t *pu64); -VMMR3DECL(int) DBGFR3RegNmQueryU128(PVM pVM, VMCPUID idDefCpu, const char *pszReg, PRTUINT128U pu128); -/*VMMR3DECL(int) DBGFR3RegNmQueryLrd( PVM pVM, VMCPUID idDefCpu, const char *pszReg, long double *plrd);*/ -VMMR3DECL(int) DBGFR3RegNmQueryXdtr(PVM pVM, VMCPUID idDefCpu, const char *pszReg, uint64_t *pu64Base, uint16_t *pu16Limit); -VMMR3DECL(int) DBGFR3RegNmQueryBatch(PVM pVM,VMCPUID idDefCpu, PDBGFREGENTRYNM paRegs, size_t cRegs); -VMMR3DECL(int) DBGFR3RegNmQueryAllCount(PVM pVM, size_t *pcRegs); -VMMR3DECL(int) DBGFR3RegNmQueryAll( PVM pVM, PDBGFREGENTRYNM paRegs, size_t cRegs); - -VMMR3DECL(int) DBGFR3RegNmSet( PVM pVM, VMCPUID idDefCpu, const char *pszReg, PCDBGFREGVAL pValue, DBGFREGVALTYPE enmType); -VMMR3DECL(int) DBGFR3RegNmSetU8( PVM pVM, VMCPUID idDefCpu, const char *pszReg, uint8_t u8); -VMMR3DECL(int) DBGFR3RegNmSetU16( PVM pVM, VMCPUID idDefCpu, const char *pszReg, uint16_t u16); -VMMR3DECL(int) DBGFR3RegNmSetU32( PVM pVM, VMCPUID idDefCpu, const char *pszReg, uint32_t u32); -VMMR3DECL(int) DBGFR3RegNmSetU64( PVM pVM, VMCPUID idDefCpu, const char *pszReg, uint64_t u64); -VMMR3DECL(int) DBGFR3RegNmSetU128( PVM pVM, VMCPUID idDefCpu, const char *pszReg, RTUINT128U u128); -VMMR3DECL(int) DBGFR3RegNmSetLrd( PVM pVM, VMCPUID idDefCpu, const char *pszReg, long double lrd); -VMMR3DECL(int) DBGFR3RegNmSetBatch( PVM pVM, VMCPUID idDefCpu, PCDBGFREGENTRYNM paRegs, size_t cRegs); +VMMR3DECL(int) DBGFR3RegNmValidate( PUVM pUVM, VMCPUID idDefCpu, const char *pszReg); + +VMMR3DECL(int) DBGFR3RegNmQuery( PUVM pUVM, VMCPUID idDefCpu, const char *pszReg, PDBGFREGVAL pValue, PDBGFREGVALTYPE penmType); +VMMR3DECL(int) DBGFR3RegNmQueryU8( PUVM pUVM, VMCPUID idDefCpu, const char *pszReg, uint8_t *pu8); +VMMR3DECL(int) DBGFR3RegNmQueryU16( PUVM pUVM, VMCPUID idDefCpu, const char *pszReg, uint16_t *pu16); +VMMR3DECL(int) DBGFR3RegNmQueryU32( PUVM pUVM, VMCPUID idDefCpu, const char *pszReg, uint32_t *pu32); +VMMR3DECL(int) DBGFR3RegNmQueryU64( PUVM pUVM, VMCPUID idDefCpu, const char *pszReg, uint64_t *pu64); +VMMR3DECL(int) DBGFR3RegNmQueryU128(PUVM pUVM, VMCPUID idDefCpu, const char *pszReg, PRTUINT128U pu128); +/*VMMR3DECL(int) DBGFR3RegNmQueryLrd( PUVM pUVM, VMCPUID idDefCpu, const char *pszReg, long double *plrd);*/ +VMMR3DECL(int) DBGFR3RegNmQueryXdtr(PUVM pUVM, VMCPUID idDefCpu, const char *pszReg, uint64_t *pu64Base, uint16_t *pu16Limit); +VMMR3DECL(int) DBGFR3RegNmQueryBatch(PUVM pUVM,VMCPUID idDefCpu, PDBGFREGENTRYNM paRegs, size_t cRegs); +VMMR3DECL(int) DBGFR3RegNmQueryAllCount(PUVM pUVM, size_t *pcRegs); +VMMR3DECL(int) DBGFR3RegNmQueryAll( PUVM pUVM, PDBGFREGENTRYNM paRegs, size_t cRegs); + +VMMR3DECL(int) DBGFR3RegNmSet( PUVM pUVM, VMCPUID idDefCpu, const char *pszReg, PCDBGFREGVAL pValue, DBGFREGVALTYPE enmType); +VMMR3DECL(int) DBGFR3RegNmSetU8( PUVM pUVM, VMCPUID idDefCpu, const char *pszReg, uint8_t u8); +VMMR3DECL(int) DBGFR3RegNmSetU16( PUVM pUVM, VMCPUID idDefCpu, const char *pszReg, uint16_t u16); +VMMR3DECL(int) DBGFR3RegNmSetU32( PUVM pUVM, VMCPUID idDefCpu, const char *pszReg, uint32_t u32); +VMMR3DECL(int) DBGFR3RegNmSetU64( PUVM pUVM, VMCPUID idDefCpu, const char *pszReg, uint64_t u64); +VMMR3DECL(int) DBGFR3RegNmSetU128( PUVM pUVM, VMCPUID idDefCpu, const char *pszReg, RTUINT128U u128); +VMMR3DECL(int) DBGFR3RegNmSetLrd( PUVM pUVM, VMCPUID idDefCpu, const char *pszReg, long double lrd); +VMMR3DECL(int) DBGFR3RegNmSetBatch( PUVM pUVM, VMCPUID idDefCpu, PCDBGFREGENTRYNM paRegs, size_t cRegs); /** @todo add enumeration methods. */ -VMMR3DECL(int) DBGFR3RegPrintf( PVM pVM, VMCPUID idDefCpu, char *pszBuf, size_t cbBuf, const char *pszFormat, ...); -VMMR3DECL(int) DBGFR3RegPrintfV(PVM pVM, VMCPUID idDefCpu, char *pszBuf, size_t cbBuf, const char *pszFormat, va_list va); +VMMR3DECL(int) DBGFR3RegPrintf( PUVM pUVM, VMCPUID idDefCpu, char *pszBuf, size_t cbBuf, const char *pszFormat, ...); +VMMR3DECL(int) DBGFR3RegPrintfV(PUVM pUVM, VMCPUID idDefCpu, char *pszBuf, size_t cbBuf, const char *pszFormat, va_list va); /** @@ -1546,18 +1581,18 @@ typedef struct DBGFOSREG * Constructs the instance. * * @returns VBox status code. - * @param pVM Pointer to the shared VM structure. + * @param pUVM The user mode VM handle. * @param pvData Pointer to the instance data. */ - DECLCALLBACKMEMBER(int, pfnConstruct)(PVM pVM, void *pvData); + DECLCALLBACKMEMBER(int, pfnConstruct)(PUVM pUVM, void *pvData); /** * Destroys the instance. * - * @param pVM Pointer to the shared VM structure. + * @param pUVM The user mode VM handle. * @param pvData Pointer to the instance data. */ - DECLCALLBACKMEMBER(void, pfnDestruct)(PVM pVM, void *pvData); + DECLCALLBACKMEMBER(void, pfnDestruct)(PUVM pUVM, void *pvData); /** * Probes the guest memory for OS finger prints. @@ -1566,10 +1601,10 @@ typedef struct DBGFOSREG * or pfnRefresh that should take care of that. * * @returns true if is an OS handled by this module, otherwise false. - * @param pVM Pointer to the shared VM structure. + * @param pUVM The user mode VM handle. * @param pvData Pointer to the instance data. */ - DECLCALLBACKMEMBER(bool, pfnProbe)(PVM pVM, void *pvData); + DECLCALLBACKMEMBER(bool, pfnProbe)(PUVM pUVM, void *pvData); /** * Initializes a fresly detected guest, loading symbols and such useful stuff. @@ -1577,10 +1612,10 @@ typedef struct DBGFOSREG * This is called after pfnProbe. * * @returns VBox status code. - * @param pVM Pointer to the shared VM structure. + * @param pUVM The user mode VM handle. * @param pvData Pointer to the instance data. */ - DECLCALLBACKMEMBER(int, pfnInit)(PVM pVM, void *pvData); + DECLCALLBACKMEMBER(int, pfnInit)(PUVM pUVM, void *pvData); /** * Refreshes symbols and stuff following a redetection of the same OS. @@ -1588,10 +1623,10 @@ typedef struct DBGFOSREG * This is called after pfnProbe. * * @returns VBox status code. - * @param pVM Pointer to the shared VM structure. + * @param pUVM The user mode VM handle. * @param pvData Pointer to the instance data. */ - DECLCALLBACKMEMBER(int, pfnRefresh)(PVM pVM, void *pvData); + DECLCALLBACKMEMBER(int, pfnRefresh)(PUVM pUVM, void *pvData); /** * Terminates an OS when a new (or none) OS has been detected, @@ -1599,10 +1634,10 @@ typedef struct DBGFOSREG * * This is called after pfnProbe and if needed before pfnDestruct. * - * @param pVM Pointer to the shared VM structure. + * @param pUVM The user mode VM handle. * @param pvData Pointer to the instance data. */ - DECLCALLBACKMEMBER(void, pfnTerm)(PVM pVM, void *pvData); + DECLCALLBACKMEMBER(void, pfnTerm)(PUVM pUVM, void *pvData); /** * Queries the version of the running OS. @@ -1610,12 +1645,12 @@ typedef struct DBGFOSREG * This is only called after pfnInit(). * * @returns VBox status code. - * @param pVM Pointer to the shared VM structure. + * @param pUVM The user mode VM handle. * @param pvData Pointer to the instance data. * @param pszVersion Where to store the version string. * @param cchVersion The size of the version string buffer. */ - DECLCALLBACKMEMBER(int, pfnQueryVersion)(PVM pVM, void *pvData, char *pszVersion, size_t cchVersion); + DECLCALLBACKMEMBER(int, pfnQueryVersion)(PUVM pUVM, void *pvData, char *pszVersion, size_t cchVersion); /** * Queries the pointer to a interface. @@ -1623,11 +1658,11 @@ typedef struct DBGFOSREG * This is called after pfnProbe. * * @returns Pointer to the interface if available, NULL if not available. - * @param pVM Pointer to the shared VM structure. + * @param pUVM The user mode VM handle. * @param pvData Pointer to the instance data. * @param enmIf The interface identifier. */ - DECLCALLBACKMEMBER(void *, pfnQueryInterface)(PVM pVM, void *pvData, DBGFOSINTERFACE enmIf); + DECLCALLBACKMEMBER(void *, pfnQueryInterface)(PUVM pUVM, void *pvData, DBGFOSINTERFACE enmIf); /** Trailing magic (DBGFOSREG_MAGIC). */ uint32_t u32EndMagic; @@ -1640,14 +1675,14 @@ typedef DBGFOSREG const *PCDBGFOSREG; /** Magic value for DBGFOSREG::u32Magic and DBGFOSREG::u32EndMagic. (Hitomi Kanehara) */ #define DBGFOSREG_MAGIC 0x19830808 -VMMR3DECL(int) DBGFR3OSRegister(PVM pVM, PCDBGFOSREG pReg); -VMMR3DECL(int) DBGFR3OSDeregister(PVM pVM, PCDBGFOSREG pReg); -VMMR3DECL(int) DBGFR3OSDetect(PVM pVM, char *pszName, size_t cchName); -VMMR3DECL(int) DBGFR3OSQueryNameAndVersion(PVM pVM, char *pszName, size_t cchName, char *pszVersion, size_t cchVersion); -VMMR3DECL(void *) DBGFR3OSQueryInterface(PVM pVM, DBGFOSINTERFACE enmIf); +VMMR3DECL(int) DBGFR3OSRegister(PUVM pUVM, PCDBGFOSREG pReg); +VMMR3DECL(int) DBGFR3OSDeregister(PUVM pUVM, PCDBGFOSREG pReg); +VMMR3DECL(int) DBGFR3OSDetect(PUVM pUVM, char *pszName, size_t cchName); +VMMR3DECL(int) DBGFR3OSQueryNameAndVersion(PUVM pUVM, char *pszName, size_t cchName, char *pszVersion, size_t cchVersion); +VMMR3DECL(void *) DBGFR3OSQueryInterface(PUVM pUVM, DBGFOSINTERFACE enmIf); -VMMR3DECL(int) DBGFR3CoreWrite(PVM pVM, const char *pszFilename, bool fReplaceFile); +VMMR3DECL(int) DBGFR3CoreWrite(PUVM pUVM, const char *pszFilename, bool fReplaceFile); /** @} */ diff --git a/include/VBox/vmm/dbgfsel.h b/include/VBox/vmm/dbgfsel.h index 708666bf..2be4ee84 100644 --- a/include/VBox/vmm/dbgfsel.h +++ b/include/VBox/vmm/dbgfsel.h @@ -3,7 +3,7 @@ */ /* - * Copyright (C) 2006-2010 Oracle Corporation + * Copyright (C) 2006-2011 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; diff --git a/include/VBox/vmm/em.h b/include/VBox/vmm/em.h index a0efe5fc..d492ecf4 100644 --- a/include/VBox/vmm/em.h +++ b/include/VBox/vmm/em.h @@ -3,7 +3,7 @@ */ /* - * Copyright (C) 2006-2010 Oracle Corporation + * Copyright (C) 2006-2013 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -51,9 +51,9 @@ typedef enum EMSTATE /** Raw-mode execution. */ EMSTATE_RAW, /** Hardware accelerated raw-mode execution. */ - EMSTATE_HWACC, - /** Value reserved for future use (used to be PARAV). */ - EMSTATE_RESERVED, + EMSTATE_HM, + /** Executing in IEM. */ + EMSTATE_IEM, /** Recompiled mode execution. */ EMSTATE_REM, /** Execution is halted. (waiting for interrupt) */ @@ -67,13 +67,18 @@ typedef enum EMSTATE /** Guest debug event from raw-mode is being processed. */ EMSTATE_DEBUG_GUEST_RAW, /** Guest debug event from hardware accelerated mode is being processed. */ - EMSTATE_DEBUG_GUEST_HWACC, + EMSTATE_DEBUG_GUEST_HM, + /** Guest debug event from interpreted execution mode is being processed. */ + EMSTATE_DEBUG_GUEST_IEM, /** Guest debug event from recompiled-mode is being processed. */ EMSTATE_DEBUG_GUEST_REM, /** Hypervisor debug event being processed. */ EMSTATE_DEBUG_HYPER, /** The VM has encountered a fatal error. (And everyone is panicing....) */ EMSTATE_GURU_MEDITATION, + /** Executing in IEM, falling back on REM if we cannot switch back to HM or + * RAW after a short while. */ + EMSTATE_IEM_THEN_REM, /** Just a hack to ensure that we get a 32-bit integer. */ EMSTATE_MAKE_32BIT_HACK = 0x7fffffff } EMSTATE; @@ -94,8 +99,8 @@ typedef enum EMCODETYPE_32BIT_HACK = 0x7fffffff } EMCODETYPE; -VMMDECL(EMSTATE) EMGetState(PVMCPU pVCpu); -VMMDECL(void) EMSetState(PVMCPU pVCpu, EMSTATE enmNewState); +VMM_INT_DECL(EMSTATE) EMGetState(PVMCPU pVCpu); +VMM_INT_DECL(void) EMSetState(PVMCPU pVCpu, EMSTATE enmNewState); /** @name Callback handlers for instruction emulation functions. * These are placed here because IOM wants to use them as well. @@ -121,7 +126,7 @@ typedef FNEMULATELOCKPARAM3 *PFNEMULATELOCKPARAM3; * @returns false if disabled. * @param pVM The VM to operate on. */ -#define EMIsRawRing3Enabled(pVM) (!(pVM)->fRecompileUser) +#define EMIsRawRing3Enabled(pVM) (!(pVM)->fRecompileUser) /** * Checks if raw ring-0 execute mode is enabled. @@ -130,7 +135,20 @@ typedef FNEMULATELOCKPARAM3 *PFNEMULATELOCKPARAM3; * @returns false if disabled. * @param pVM The VM to operate on. */ -#define EMIsRawRing0Enabled(pVM) (!(pVM)->fRecompileSupervisor) +#define EMIsRawRing0Enabled(pVM) (!(pVM)->fRecompileSupervisor) + +#ifdef VBOX_WITH_RAW_RING1 +/** + * Checks if raw ring-1 execute mode is enabled. + * + * @returns true if enabled. + * @returns false if disabled. + * @param pVM The VM to operate on. + */ +# define EMIsRawRing1Enabled(pVM) ((pVM)->fRawRing1Enabled) +#else +# define EMIsRawRing1Enabled(pVM) false +#endif /** * Checks if execution with hardware assisted virtualization is enabled. @@ -139,7 +157,7 @@ typedef FNEMULATELOCKPARAM3 *PFNEMULATELOCKPARAM3; * @returns false if disabled. * @param pVM The VM to operate on. */ -#define EMIsHwVirtExecutionEnabled(pVM) (!(pVM)->fRecompileSupervisor && !(pVM)->fRecompileUser) +#define EMIsHwVirtExecutionEnabled(pVM) (!(pVM)->fRecompileSupervisor && !(pVM)->fRecompileUser) /** * Checks if execution of supervisor code should be done in the @@ -151,39 +169,39 @@ typedef FNEMULATELOCKPARAM3 *PFNEMULATELOCKPARAM3; */ #define EMIsSupervisorCodeRecompiled(pVM) ((pVM)->fRecompileSupervisor) -VMMDECL(void) EMSetInhibitInterruptsPC(PVMCPU pVCpu, RTGCUINTPTR PC); -VMMDECL(RTGCUINTPTR) EMGetInhibitInterruptsPC(PVMCPU pVCpu); -VMMDECL(int) EMInterpretDisasCurrent(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pCpu, unsigned *pcbInstr); -VMMDECL(int) EMInterpretDisasOneEx(PVM pVM, PVMCPU pVCpu, RTGCUINTPTR GCPtrInstr, PCCPUMCTXCORE pCtxCore, - PDISCPUSTATE pDISState, unsigned *pcbInstr); -VMMDECL(VBOXSTRICTRC) EMInterpretInstruction(PVMCPU pVCpu, PCPUMCTXCORE pCoreCtx, RTGCPTR pvFault); -VMMDECL(VBOXSTRICTRC) EMInterpretInstructionEx(PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbWritten); -VMMDECL(VBOXSTRICTRC) EMInterpretInstructionDisasState(PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pCoreCtx, RTGCPTR pvFault, EMCODETYPE enmCodeType); +VMMDECL(void) EMSetInhibitInterruptsPC(PVMCPU pVCpu, RTGCUINTPTR PC); +VMMDECL(RTGCUINTPTR) EMGetInhibitInterruptsPC(PVMCPU pVCpu); +VMM_INT_DECL(int) EMInterpretDisasCurrent(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pCpu, unsigned *pcbInstr); +VMM_INT_DECL(int) EMInterpretDisasOneEx(PVM pVM, PVMCPU pVCpu, RTGCUINTPTR GCPtrInstr, PCCPUMCTXCORE pCtxCore, + PDISCPUSTATE pDISState, unsigned *pcbInstr); +VMM_INT_DECL(VBOXSTRICTRC) EMInterpretInstruction(PVMCPU pVCpu, PCPUMCTXCORE pCoreCtx, RTGCPTR pvFault); +VMM_INT_DECL(VBOXSTRICTRC) EMInterpretInstructionEx(PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbWritten); +VMM_INT_DECL(VBOXSTRICTRC) EMInterpretInstructionDisasState(PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pCoreCtx, + RTGCPTR pvFault, EMCODETYPE enmCodeType); #ifdef IN_RC -VMMDECL(int) EMInterpretIretV86ForPatm(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame); +VMM_INT_DECL(int) EMInterpretIretV86ForPatm(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame); #endif -VMMDECL(int) EMInterpretCpuId(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame); -VMMDECL(int) EMInterpretRdtsc(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame); -VMMDECL(int) EMInterpretRdpmc(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame); -VMMDECL(int) EMInterpretRdtscp(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx); -VMMDECL(VBOXSTRICTRC) EMInterpretInvlpg(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pAddrGC); -VMMDECL(VBOXSTRICTRC) EMInterpretMWait(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame); -VMMDECL(int) EMInterpretMonitor(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame); -VMMDECL(int) EMInterpretDRxWrite(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t DestRegDrx, uint32_t SrcRegGen); -VMMDECL(int) EMInterpretDRxRead(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t DestRegGen, uint32_t SrcRegDrx); -VMMDECL(int) EMInterpretCRxWrite(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t DestRegCrx, uint32_t SrcRegGen); -VMMDECL(int) EMInterpretCRxRead(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t DestRegGen, uint32_t SrcRegCrx); -VMMDECL(int) EMInterpretLMSW(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint16_t u16Data); -VMMDECL(int) EMInterpretCLTS(PVM pVM, PVMCPU pVCpu); -#ifndef VBOX_WITH_IEM -VMMDECL(int) EMInterpretRdmsr(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame); -VMMDECL(int) EMInterpretWrmsr(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame); -#endif /* !VBOX_WITH_IEM */ -VMM_INT_DECL(bool) EMShouldContinueAfterHalt(PVMCPU pVCpu, PCPUMCTX pCtx); -VMM_INT_DECL(int) EMMonitorWaitPrepare(PVMCPU pVCpu, uint64_t rax, uint64_t rcx, uint64_t rdx); -VMM_INT_DECL(int) EMMonitorWaitPerform(PVMCPU pVCpu, uint64_t rax, uint64_t rcx); +VMM_INT_DECL(int) EMInterpretCpuId(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame); +VMM_INT_DECL(int) EMInterpretRdtsc(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame); +VMM_INT_DECL(int) EMInterpretRdpmc(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame); +VMM_INT_DECL(int) EMInterpretRdtscp(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx); +VMM_INT_DECL(VBOXSTRICTRC) EMInterpretInvlpg(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pAddrGC); +VMM_INT_DECL(VBOXSTRICTRC) EMInterpretMWait(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame); +VMM_INT_DECL(int) EMInterpretMonitor(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame); +VMM_INT_DECL(int) EMInterpretDRxWrite(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t DestRegDrx, uint32_t SrcRegGen); +VMM_INT_DECL(int) EMInterpretDRxRead(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t DestRegGen, uint32_t SrcRegDrx); +VMM_INT_DECL(int) EMInterpretCRxWrite(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t DestRegCrx, uint32_t SrcRegGen); +VMM_INT_DECL(int) EMInterpretCRxRead(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t DestRegGen, uint32_t SrcRegCrx); +VMM_INT_DECL(int) EMInterpretLMSW(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint16_t u16Data); +VMM_INT_DECL(int) EMInterpretCLTS(PVM pVM, PVMCPU pVCpu); +VMM_INT_DECL(int) EMInterpretRdmsr(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame); +VMM_INT_DECL(int) EMInterpretWrmsr(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame); +VMM_INT_DECL(bool) EMShouldContinueAfterHalt(PVMCPU pVCpu, PCPUMCTX pCtx); +VMM_INT_DECL(bool) EMMonitorWaitShouldContinue(PVMCPU pVCpu, PCPUMCTX pCtx); +VMM_INT_DECL(int) EMMonitorWaitPrepare(PVMCPU pVCpu, uint64_t rax, uint64_t rcx, uint64_t rdx, RTGCPHYS GCPhys); +VMM_INT_DECL(int) EMMonitorWaitPerform(PVMCPU pVCpu, uint64_t rax, uint64_t rcx); /** @name Assembly routines * @{ */ @@ -213,26 +231,28 @@ VMMDECL(uint32_t) EMEmulateLockXAdd(void *pvParam1, void *pvParam2, size_t cbO /** @name REM locking routines * @{ */ -VMMDECL(void) EMRemUnlock(PVM pVM); -VMMDECL(void) EMRemLock(PVM pVM); -VMMDECL(bool) EMRemIsLockOwner(PVM pVM); -VMMDECL(int) EMRemTryLock(PVM pVM); +VMMDECL(void) EMRemUnlock(PVM pVM); +VMMDECL(void) EMRemLock(PVM pVM); +VMMDECL(bool) EMRemIsLockOwner(PVM pVM); +VMM_INT_DECL(int) EMRemTryLock(PVM pVM); /** @} */ + +/** @name EM_ONE_INS_FLAGS_XXX - flags for EMR3HmSingleInstruction (et al). + * @{ */ +/** Return when CS:RIP changes or some other important event happens. + * This means running whole REP and LOOP $ sequences for instance. */ +#define EM_ONE_INS_FLAGS_RIP_CHANGE RT_BIT_32(0) +/** Mask of valid flags. */ +#define EM_ONE_INS_FLAGS_MASK UINT32_C(0x00000001) +/** @} */ + + #ifdef IN_RING3 /** @defgroup grp_em_r3 The EM Host Context Ring-3 API * @ingroup grp_em * @{ */ -VMMR3DECL(int) EMR3Init(PVM pVM); -VMMR3DECL(void) EMR3Relocate(PVM pVM); -VMMR3DECL(void) EMR3ResetCpu(PVMCPU pVCpu); -VMMR3DECL(void) EMR3Reset(PVM pVM); -VMMR3DECL(int) EMR3Term(PVM pVM); -VMMR3DECL(DECLNORETURN(void)) EMR3FatalError(PVMCPU pVCpu, int rc); -VMMR3DECL(int) EMR3ExecuteVM(PVM pVM, PVMCPU pVCpu); -VMMR3DECL(int) EMR3CheckRawForcedActions(PVM pVM, PVMCPU pVCpu); -VMMR3DECL(int) EMR3Interpret(PVM pVM); /** * Command argument for EMR3RawSetMode(). @@ -248,25 +268,30 @@ typedef enum EMEXECPOLICY EMEXECPOLICY_RECOMPILE_RING0, /** Whether to recompile ring-3 code or execute it in raw/hm. */ EMEXECPOLICY_RECOMPILE_RING3, + /** Whether to only use IEM for execution. */ + EMEXECPOLICY_IEM_ALL, /** End of valid value (not included). */ EMEXECPOLICY_END, /** The customary 32-bit type blowup. */ EMEXECPOLICY_32BIT_HACK = 0x7fffffff } EMEXECPOLICY; +VMMR3DECL(int) EMR3SetExecutionPolicy(PUVM pUVM, EMEXECPOLICY enmPolicy, bool fEnforce); +VMMR3DECL(int) EMR3QueryExecutionPolicy(PUVM pUVM, EMEXECPOLICY enmPolicy, bool *pfEnforced); -VMMR3DECL(int) EMR3SetExecutionPolicy(PVM pVM, EMEXECPOLICY enmPolicy, bool fEnforce); -/** @} */ -#endif /* IN_RING3 */ - +VMMR3_INT_DECL(int) EMR3Init(PVM pVM); +VMMR3_INT_DECL(void) EMR3Relocate(PVM pVM); +VMMR3_INT_DECL(void) EMR3ResetCpu(PVMCPU pVCpu); +VMMR3_INT_DECL(void) EMR3Reset(PVM pVM); +VMMR3_INT_DECL(int) EMR3Term(PVM pVM); +VMMR3DECL(DECLNORETURN(void)) EMR3FatalError(PVMCPU pVCpu, int rc); +VMMR3_INT_DECL(int) EMR3ExecuteVM(PVM pVM, PVMCPU pVCpu); +VMMR3_INT_DECL(int) EMR3CheckRawForcedActions(PVM pVM, PVMCPU pVCpu); +VMMR3_INT_DECL(int) EMR3NotifyResume(PVM pVM); +VMMR3_INT_DECL(int) EMR3NotifySuspend(PVM pVM); +VMMR3_INT_DECL(VBOXSTRICTRC) EMR3HmSingleInstruction(PVM pVM, PVMCPU pVCpu, uint32_t fFlags); -#ifdef IN_RC -/** @defgroup grp_em_gc The EM Guest Context API - * @ingroup grp_em - * @{ - */ -VMMRCDECL(int) EMGCTrap(PVM pVM, unsigned uTrap, PCPUMCTXCORE pRegFrame); /** @} */ -#endif /* IN_RC */ +#endif /* IN_RING3 */ /** @} */ diff --git a/include/VBox/vmm/ftm.h b/include/VBox/vmm/ftm.h index 2fc1ccfe..e8702d67 100644 --- a/include/VBox/vmm/ftm.h +++ b/include/VBox/vmm/ftm.h @@ -3,7 +3,7 @@ */ /* - * Copyright (C) 2010 Oracle Corporation + * Copyright (C) 2010-2013 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -40,24 +40,27 @@ RT_C_DECLS_BEGIN */ typedef enum FTMCHECKPOINTTYPE { + FTMCHECKPOINTTYPE_INVALID = 0, FTMCHECKPOINTTYPE_NETWORK, FTMCHECKPOINTTYPE_STORAGE, + FTMCHECKPOINTTYPE_END, FTMCHECKPOINTTYPE_32BIT_HACK = 0x7fffffff } FTMCHECKPOINTTYPE; -VMMDECL(bool) FTMIsDeltaLoadSaveActive(PVM pVM); -VMMDECL(int) FTMSetCheckpoint(PVM pVM, FTMCHECKPOINTTYPE enmType); +VMM_INT_DECL(bool) FTMIsDeltaLoadSaveActive(PVM pVM); +VMM_INT_DECL(int) FTMSetCheckpoint(PVM pVM, FTMCHECKPOINTTYPE enmType); #ifdef IN_RING3 /** @defgroup grp_ftm_r3 The FTM Host Context Ring-3 API * @ingroup grp_ftm * @{ */ -VMMR3DECL(int) FTMR3PowerOn(PVM pVM, bool fMaster, unsigned uInterval, const char *pszAddress, unsigned uPort, const char *pszPassword); -VMMR3DECL(int) FTMR3Init(PVM pVM); -VMMR3DECL(int) FTMR3Term(PVM pVM); -VMMR3DECL(int) FTMR3CancelStandby(PVM pVM); -VMMR3DECL(int) FTMR3SetCheckpoint(PVM pVM, FTMCHECKPOINTTYPE enmType); +VMMR3DECL(int) FTMR3PowerOn(PUVM pUVM, bool fMaster, unsigned uInterval, const char *pszAddress, unsigned uPort, const char *pszPassword); +VMMR3DECL(int) FTMR3CancelStandby(PUVM pUVM); + +VMMR3_INT_DECL(int) FTMR3Init(PVM pVM); +VMMR3_INT_DECL(int) FTMR3Term(PVM pVM); +VMMR3_INT_DECL(int) FTMR3SetCheckpoint(PVM pVM, FTMCHECKPOINTTYPE enmType); #endif /* IN_RING3 */ diff --git a/include/VBox/vmm/gmm.h b/include/VBox/vmm/gmm.h index 0f93c94a..e5db104c 100644 --- a/include/VBox/vmm/gmm.h +++ b/include/VBox/vmm/gmm.h @@ -3,7 +3,7 @@ */ /* - * Copyright (C) 2007-2010 Oracle Corporation + * Copyright (C) 2007-2012 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; diff --git a/include/VBox/vmm/gvm.h b/include/VBox/vmm/gvm.h index b0d607de..0fe406b0 100644 --- a/include/VBox/vmm/gvm.h +++ b/include/VBox/vmm/gvm.h @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2007-2010 Oracle Corporation + * Copyright (C) 2007-2011 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; diff --git a/include/VBox/vmm/gvmm.h b/include/VBox/vmm/gvmm.h index e78d181b..eb86f9b2 100644 --- a/include/VBox/vmm/gvmm.h +++ b/include/VBox/vmm/gvmm.h @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2007-2010 Oracle Corporation + * Copyright (C) 2007-2012 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; diff --git a/include/VBox/vmm/hm.h b/include/VBox/vmm/hm.h new file mode 100644 index 00000000..12b94167 --- /dev/null +++ b/include/VBox/vmm/hm.h @@ -0,0 +1,265 @@ +/** @file + * HM - Intel/AMD VM Hardware Assisted Virtualization Manager (VMM) + */ + +/* + * Copyright (C) 2006-2013 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL) only, as it comes in the "COPYING.CDDL" file of the + * VirtualBox OSE distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + */ + +#ifndef ___VBox_vmm_hm_h +#define ___VBox_vmm_hm_h + +#include <VBox/vmm/pgm.h> +#include <VBox/vmm/cpum.h> +#include <VBox/vmm/vmm.h> +#include <iprt/mp.h> + + +/** @defgroup grp_hm The VM Hardware Manager API + * @{ + */ + +RT_C_DECLS_BEGIN + +/** + * Checks whether HM (VT-x/AMD-V) is being used by this VM. + * + * @retval @c true if used. + * @retval @c false if software virtualization (raw-mode) is used. + * + * @param a_pVM The cross context VM structure. + * @sa HMIsEnabledNotMacro, HMR3IsEnabled + * @internal + */ +#if defined(VBOX_STRICT) && defined(IN_RING3) +# define HMIsEnabled(a_pVM) HMIsEnabledNotMacro(a_pVM) +#else +# define HMIsEnabled(a_pVM) ((a_pVM)->fHMEnabled) +#endif + +/** + * Checks whether raw-mode context is required for any purpose. + * + * @retval @c true if required either by raw-mode itself or by HM for doing + * switching the cpu to 64-bit mode. + * @retval @c false if not required. + * + * @param a_pVM The cross context VM structure. + * @internal + */ +#if HC_ARCH_BITS == 64 +# define HMIsRawModeCtxNeeded(a_pVM) (!HMIsEnabled(a_pVM)) +#else +# define HMIsRawModeCtxNeeded(a_pVM) (!HMIsEnabled(a_pVM) || (a_pVM)->fHMNeedRawModeCtx) +#endif + + /** + * Check if the current CPU state is valid for emulating IO blocks in the recompiler + * + * @returns boolean + * @param a_pVCpu Pointer to the shared virtual CPU structure. + * @internal + */ +#define HMCanEmulateIoBlock(a_pVCpu) (!CPUMIsGuestInPagedProtectedMode(a_pVCpu)) + + /** + * Check if the current CPU state is valid for emulating IO blocks in the recompiler + * + * @returns boolean + * @param a_pCtx Pointer to the CPU context (within PVM). + * @internal + */ +#define HMCanEmulateIoBlockEx(a_pCtx) (!CPUMIsGuestInPagedProtectedModeEx(a_pCtx)) + +/** + * Checks whether we're in the special hardware virtualization context. + * @returns true / false. + * @param a_pVCpu The caller's cross context virtual CPU structure. + * @thread EMT + */ +#ifdef IN_RING0 +# define HMIsInHwVirtCtx(a_pVCpu) (VMCPU_GET_STATE(a_pVCpu) == VMCPUSTATE_STARTED_HM) +#else +# define HMIsInHwVirtCtx(a_pVCpu) (false) +#endif + +/** + * Checks whether we're in the special hardware virtualization context and we + * cannot perform long jump without guru meditating and possibly messing up the + * host and/or guest state. + * + * This is after we've turned interrupts off and such. + * + * @returns true / false. + * @param a_pVCpu The caller's cross context virtual CPU structure. + * @thread EMT + */ +#ifdef IN_RING0 +# define HMIsInHwVirtNoLongJmpCtx(a_pVCpu) (VMCPU_GET_STATE(a_pVCpu) == VMCPUSTATE_STARTED_EXEC) +#else +# define HMIsInHwVirtNoLongJmpCtx(a_pVCpu) (false) +#endif + +/** + * 64-bit raw-mode (intermediate memory context) operations. + * + * These are special hypervisor eip values used when running 64-bit guests on + * 32-bit hosts. Each operation corresponds to a routine. + * + * @note Duplicated in the assembly code! + */ +typedef enum HM64ON32OP +{ + HM64ON32OP_INVALID = 0, + HM64ON32OP_VMXRCStartVM64, + HM64ON32OP_SVMRCVMRun64, + HM64ON32OP_HMRCSaveGuestFPU64, + HM64ON32OP_HMRCSaveGuestDebug64, + HM64ON32OP_HMRCTestSwitcher64, + HM64ON32OP_END, + HM64ON32OP_32BIT_HACK = 0x7fffffff +} HM64ON32OP; + +VMMDECL(bool) HMIsEnabledNotMacro(PVM pVM); +VMM_INT_DECL(int) HMInvalidatePage(PVMCPU pVCpu, RTGCPTR GCVirt); +VMM_INT_DECL(bool) HMHasPendingIrq(PVM pVM); +VMM_INT_DECL(PX86PDPE) HMGetPaePdpes(PVMCPU pVCpu); +VMM_INT_DECL(int) HMAmdIsSubjectToErratum170(uint32_t *pu32Family, uint32_t *pu32Model, uint32_t *pu32Stepping); +VMM_INT_DECL(bool) HMSetSingleInstruction(PVMCPU pVCpu, bool fEnable); + +#ifndef IN_RC +VMM_INT_DECL(int) HMFlushTLB(PVMCPU pVCpu); +VMM_INT_DECL(int) HMFlushTLBOnAllVCpus(PVM pVM); +VMM_INT_DECL(int) HMInvalidatePageOnAllVCpus(PVM pVM, RTGCPTR GCVirt); +VMM_INT_DECL(int) HMInvalidatePhysPage(PVM pVM, RTGCPHYS GCPhys); +VMM_INT_DECL(bool) HMIsNestedPagingActive(PVM pVM); +VMM_INT_DECL(PGMMODE) HMGetShwPagingMode(PVM pVM); +#else /* Nops in RC: */ +# define HMFlushTLB(pVCpu) do { } while (0) +# define HMIsNestedPagingActive(pVM) false +# define HMFlushTLBOnAllVCpus(pVM) do { } while (0) +#endif + +#ifdef IN_RING0 +/** @defgroup grp_hm_r0 The VM Hardware Manager API + * @ingroup grp_hm + * @{ + */ +VMMR0_INT_DECL(int) HMR0Init(void); +VMMR0_INT_DECL(int) HMR0Term(void); +VMMR0_INT_DECL(int) HMR0InitVM(PVM pVM); +VMMR0_INT_DECL(int) HMR0TermVM(PVM pVM); +VMMR0_INT_DECL(int) HMR0EnableAllCpus(PVM pVM); +VMMR0_INT_DECL(int) HMR0EnterSwitcher(PVM pVM, VMMSWITCHER enmSwitcher, bool *pfVTxDisabled); +VMMR0_INT_DECL(void) HMR0LeaveSwitcher(PVM pVM, bool fVTxDisabled); + +VMMR0_INT_DECL(void) HMR0SavePendingIOPortWrite(PVMCPU pVCpu, RTGCPTR GCPtrRip, RTGCPTR GCPtrRipNext, + unsigned uPort, unsigned uAndVal, unsigned cbSize); +VMMR0_INT_DECL(void) HMR0SavePendingIOPortRead(PVMCPU pVCpu, RTGCPTR GCPtrRip, RTGCPTR GCPtrRipNext, + unsigned uPort, unsigned uAndVal, unsigned cbSize); + +/** @} */ +#endif /* IN_RING0 */ + + +#ifdef IN_RING3 +/** @defgroup grp_hm_r3 The VM Hardware Manager API + * @ingroup grp_hm + * @{ + */ +VMMR3DECL(bool) HMR3IsEnabled(PUVM pUVM); +VMMR3DECL(bool) HMR3IsNestedPagingActive(PUVM pUVM); +VMMR3DECL(bool) HMR3IsVpidActive(PUVM pVUM); +VMMR3DECL(bool) HMR3IsUXActive(PUVM pVUM); +VMMR3DECL(bool) HMR3IsSvmEnabled(PUVM pUVM); +VMMR3DECL(bool) HMR3IsVmxEnabled(PUVM pUVM); + +VMMR3_INT_DECL(bool) HMR3IsEventPending(PVMCPU pVCpu); +VMMR3_INT_DECL(int) HMR3Init(PVM pVM); +VMMR3_INT_DECL(int) HMR3InitCompleted(PVM pVM, VMINITCOMPLETED enmWhat); +VMMR3_INT_DECL(void) HMR3Relocate(PVM pVM); +VMMR3_INT_DECL(int) HMR3Term(PVM pVM); +VMMR3_INT_DECL(void) HMR3Reset(PVM pVM); +VMMR3_INT_DECL(void) HMR3ResetCpu(PVMCPU pVCpu); +VMMR3_INT_DECL(void) HMR3CheckError(PVM pVM, int iStatusCode); +VMMR3DECL(bool) HMR3CanExecuteGuest(PVM pVM, PCPUMCTX pCtx); +VMMR3_INT_DECL(void) HMR3NotifyScheduled(PVMCPU pVCpu); +VMMR3_INT_DECL(void) HMR3NotifyEmulated(PVMCPU pVCpu); +VMMR3_INT_DECL(bool) HMR3IsActive(PVMCPU pVCpu); +VMMR3_INT_DECL(void) HMR3PagingModeChanged(PVM pVM, PVMCPU pVCpu, PGMMODE enmShadowMode, PGMMODE enmGuestMode); +VMMR3_INT_DECL(int) HMR3EmulateIoBlock(PVM pVM, PCPUMCTX pCtx); +VMMR3_INT_DECL(VBOXSTRICTRC) HMR3RestartPendingIOInstr(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx); +VMMR3_INT_DECL(int) HMR3EnablePatching(PVM pVM, RTGCPTR pPatchMem, unsigned cbPatchMem); +VMMR3_INT_DECL(int) HMR3DisablePatching(PVM pVM, RTGCPTR pPatchMem, unsigned cbPatchMem); +VMMR3_INT_DECL(int) HMR3PatchTprInstr(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx); +VMMR3_INT_DECL(bool) HMR3IsRescheduleRequired(PVM pVM, PCPUMCTX pCtx); +VMMR3_INT_DECL(bool) HMR3IsVmxPreemptionTimerUsed(PVM pVM); + +/** @} */ +#endif /* IN_RING3 */ + +#ifdef IN_RING0 +/** @addtogroup grp_hm_r0 + * @{ + */ +/** Disables preemption if required. */ +# define HM_DISABLE_PREEMPT_IF_NEEDED() \ + RTTHREADPREEMPTSTATE PreemptStateInternal = RTTHREADPREEMPTSTATE_INITIALIZER; \ + bool fPreemptDisabledInternal = false; \ + if (RTThreadPreemptIsEnabled(NIL_RTTHREAD)) \ + { \ + Assert(VMMR0ThreadCtxHooksAreRegistered(pVCpu)); \ + RTThreadPreemptDisable(&PreemptStateInternal); \ + fPreemptDisabledInternal = true; \ + } + +/** Restores preemption if previously disabled by HM_DISABLE_PREEMPT(). */ +# define HM_RESTORE_PREEMPT_IF_NEEDED() \ + do \ + { \ + if (fPreemptDisabledInternal) \ + RTThreadPreemptRestore(&PreemptStateInternal); \ + } while (0) + +VMMR0_INT_DECL(int) HMR0SetupVM(PVM pVM); +VMMR0_INT_DECL(int) HMR0RunGuestCode(PVM pVM, PVMCPU pVCpu); +VMMR0_INT_DECL(int) HMR0Enter(PVM pVM, PVMCPU pVCpu); +VMMR0_INT_DECL(int) HMR0Leave(PVM pVM, PVMCPU pVCpu); +VMMR0_INT_DECL(int) HMR0EnterCpu(PVMCPU pVCpu); +VMMR0_INT_DECL(int) HMR0LeaveCpu(PVMCPU pVCpu); +VMMR0_INT_DECL(void) HMR0ThreadCtxCallback(RTTHREADCTXEVENT enmEvent, void *pvUser); +VMMR0_INT_DECL(bool) HMR0SuspendPending(void); + +# if HC_ARCH_BITS == 32 && defined(VBOX_WITH_64_BITS_GUESTS) +VMMR0_INT_DECL(int) HMR0SaveFPUState(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx); +VMMR0_INT_DECL(int) HMR0SaveDebugState(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx); +VMMR0_INT_DECL(int) HMR0TestSwitcher3264(PVM pVM); +# endif + +/** @} */ +#endif /* IN_RING0 */ + + +/** @} */ +RT_C_DECLS_END + + +#endif + diff --git a/include/VBox/vmm/hwacc_svm.h b/include/VBox/vmm/hm_svm.h index 8912e378..7a67c387 100644 --- a/include/VBox/vmm/hwacc_svm.h +++ b/include/VBox/vmm/hm_svm.h @@ -1,9 +1,9 @@ /** @file - * HWACCM - SVM Structures and Definitions. (VMM) + * HM - SVM Structures and Definitions. (VMM) */ /* - * Copyright (C) 2006-2007 Oracle Corporation + * Copyright (C) 2006-2013 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -32,7 +32,7 @@ #include <iprt/asm.h> /** @defgroup grp_svm svm Types and Definitions - * @ingroup grp_hwaccm + * @ingroup grp_hm * @{ */ @@ -56,13 +56,13 @@ #define AMD_CPUID_SVM_FEATURE_EDX_FLUSH_BY_ASID RT_BIT(6) /** Bit 7 - DecodeAssist - Indicate decode assist is supported. */ #define AMD_CPUID_SVM_FEATURE_EDX_DECODE_ASSIST RT_BIT(7) -/** Where did we get this from? */ -#define AMD_CPUID_SVM_FEATURE_EDX_SSE_3_5_DISABLE RT_BIT(9) /** Bit 10 - PauseFilter - Indicates support for the PAUSE intercept filter. */ #define AMD_CPUID_SVM_FEATURE_EDX_PAUSE_FILTER RT_BIT(10) /** Bit 12 - PauseFilterThreshold - Indicates support for the PAUSE * intercept filter cycle count threshold. */ #define AMD_CPUID_SVM_FEATURE_EDX_PAUSE_FILTER_THRESHOLD RT_BIT(12) +/** Bit 13 - AVIC - Advanced Virtual Interrupt Controller. */ +#define AMD_CPUID_SVM_FEATURE_EDX_AVIC RT_BIT(13) /** @} */ @@ -70,7 +70,7 @@ * @{ */ /** Invalid guest state in VMCB. */ -#define SVM_EXIT_INVALID -1 +#define SVM_EXIT_INVALID (-1) /** Read from CR0-CR15. */ #define SVM_EXIT_READ_CR0 0x0 #define SVM_EXIT_READ_CR1 0x1 @@ -258,17 +258,24 @@ #define SVM_EXIT_WBINVD 0x89 /** MONITOR instruction. */ #define SVM_EXIT_MONITOR 0x8A -/** MWAIT instruction uncond. */ -#define SVM_EXIT_MWAIT_UNCOND 0x8B -/** MWAIT instruction when armed. */ +/** MWAIT instruction. */ +#define SVM_EXIT_MWAIT 0x8B +/** MWAIT instruction, when armed. */ #define SVM_EXIT_MWAIT_ARMED 0x8C /** Nested paging: host-level page fault occurred (EXITINFO1 contains fault errorcode; EXITINFO2 contains the guest physical address causing the fault). */ #define SVM_EXIT_NPF 0x400 - +/** AVIC: Virtual IPI delivery not completed. */ +#define SVM_EXIT_AVIC_INCOMPLETE_IPI 0x401 +/** AVIC: Attempted access by guest to a vAPIC register not handled by AVIC + * hardware. */ +#define SVM_EXIT_AVIC_NOACCEL 0x402 + +/** The maximum possible exit value. */ +#define SVM_EXIT_MAX (SVM_EXIT_AVIC_NOACCEL) /** @} */ -/** @name SVM_VMCB.u64ExitInfo2 +/** @name SVMVMCB.u64ExitInfo2 for task switches * @{ */ /** Set to 1 if the task switch was caused by an IRET; else cleared to 0. */ @@ -281,7 +288,16 @@ #define SVM_EXIT2_TASK_SWITCH_EFLAGS_RF RT_BIT_64(48) /** @} */ -/** @name SVM_VMCB.ctrl.u32InterceptCtrl1 +/** @name SVMVMCB.u64ExitInfo1 for MSR accesses + * @{ + */ +/** The access was a read MSR. */ +#define SVM_EXIT1_MSR_READ 0x0 +/** The access was a write MSR. */ +#define SVM_EXIT1_MSR_WRITE 0x1 +/** @} */ + +/** @name SVMVMCB.ctrl.u32InterceptCtrl1 * @{ */ /** 0 Intercept INTR (physical maskable interrupt). */ @@ -351,7 +367,7 @@ /** @} */ -/** @name SVM_VMCB.ctrl.u32InterceptCtrl2 +/** @name SVMVMCB.ctrl.u32InterceptCtrl2 * @{ */ /** 0 Intercept VMRUN instruction. */ @@ -377,27 +393,27 @@ /** 10 Intercept MONITOR instruction. */ #define SVM_CTRL2_INTERCEPT_MONITOR RT_BIT(10) /** 11 Intercept MWAIT instruction unconditionally. */ -#define SVM_CTRL2_INTERCEPT_MWAIT_UNCOND RT_BIT(11) +#define SVM_CTRL2_INTERCEPT_MWAIT RT_BIT(11) /** 12 Intercept MWAIT instruction when armed. */ #define SVM_CTRL2_INTERCEPT_MWAIT_ARMED RT_BIT(12) /** 13 Intercept XSETBV instruction. */ #define SVM_CTRL2_INTERCEPT_XSETBV RT_BIT(13) /** @} */ -/** @name SVM_VMCB.ctrl.u64NestedPaging +/** @name SVMVMCB.ctrl.u64NestedPaging * @{ */ #define SVM_NESTED_PAGING_ENABLE RT_BIT(0) /** @} */ -/** @name SVM_VMCB.ctrl.u64IntShadow +/** @name SVMVMCB.ctrl.u64IntShadow * @{ */ #define SVM_INTERRUPT_SHADOW_ACTIVE RT_BIT(0) /** @} */ -/** @name SVM_INTCTRL.u3Type +/** @name SVMINTCTRL.u3Type * @{ */ /** External or virtual interrupt. */ @@ -411,7 +427,7 @@ /** @} */ -/** @name SVM_VMCB.ctrl.TLBCtrl.n.u8TLBFlush +/** @name SVMVMCB.ctrl.TLBCtrl.n.u8TLBFlush * @{ */ /** Flush nothing. */ @@ -450,13 +466,11 @@ typedef struct uint64_t u64Base; } SVMGDTR; #pragma pack() - typedef SVMGDTR SVMIDTR; /** - * SVM Event injection structure. + * SVM Event injection structure (EVENTINJ and EXITINTINFO). */ -#pragma pack(1) typedef union { struct @@ -468,15 +482,14 @@ typedef union uint32_t u1Valid : 1; uint32_t u32ErrorCode : 32; } n; - uint64_t au64[1]; -} SVM_EVENT; -#pragma pack() - + uint64_t u; +} SVMEVENT; +/** Pointer to the SVMEVENT union. */ +typedef SVMEVENT *PSVMEVENT; /** - * SVM Interrupt control structure. + * SVM Interrupt control structure (Virtual Interrupt Control). */ -#pragma pack(1) typedef union { struct @@ -488,19 +501,17 @@ typedef union uint32_t u1IgnoreTPR : 1; uint32_t u3Reserved : 3; uint32_t u1VIrqMasking : 1; - uint32_t u7Reserved2 : 7; + uint32_t u6Reserved : 6; + uint32_t u1AvicEnable : 1; uint32_t u8VIrqVector : 8; uint32_t u24Reserved : 24; } n; - uint64_t au64[1]; -} SVM_INTCTRL; -#pragma pack() - + uint64_t u; +} SVMINTCTRL; /** * SVM TLB control structure. */ -#pragma pack(1) typedef union { struct @@ -509,15 +520,12 @@ typedef union uint32_t u8TLBFlush : 8; uint32_t u24Reserved : 24; } n; - uint64_t au64[1]; -} SVM_TLBCTRL; -#pragma pack() - + uint64_t u; +} SVMTLBCTRL; /** - * SVM IOIO exit structure. + * SVM IOIO exit structure (EXITINFO1 for IOIO intercepts). */ -#pragma pack(1) typedef union { struct @@ -535,29 +543,65 @@ typedef union uint32_t u6Reserved : 6; uint32_t u16Port : 16; } n; - uint32_t au32[1]; -} SVM_IOIO_EXIT; -#pragma pack() + uint32_t u; +} SVMIOIOEXIT; + +/** @name SVMIOIOEXIT.u1Type + * @{ */ +/** IO write. */ +#define SVM_IOIO_WRITE 0 +/** IO read. */ +#define SVM_IOIO_READ 1 +/** @}*/ /** * SVM nested paging structure. */ -#pragma pack(1) typedef union { struct { - uint32_t u1NestedPaging : 1; /**< enabled/disabled */ + uint32_t u1NestedPaging : 1; /**< enabled/disabled */ } n; - uint64_t au64[1]; -} SVM_NPCTRL; -#pragma pack() + uint64_t u; +} SVMNPCTRL; + +/** + * SVM AVIC. + */ +typedef union +{ + struct + { + uint64_t u12Reserved1 : 12; + uint64_t u40Addr : 40; + uint64_t u12Reserved2 : 12; + } n; + uint64_t u; +} SVMAVIC; +AssertCompileSize(SVMAVIC, 8); + +/** + * SVM AVIC PHYSICAL_TABLE pointer. + */ +typedef union +{ + struct + { + uint64_t u8LastGuestCoreId : 8; + uint64_t u4Reserved : 4; + uint64_t u40Addr : 40; + uint64_t u12Reserved : 12; + } n; + uint64_t u; +} SVMAVICPHYS; +AssertCompileSize(SVMAVICPHYS, 8); /** * SVM VM Control Block. (VMCB) */ #pragma pack(1) -typedef struct _SVM_VMCB +typedef struct SVMVMCB { /** Control Area. */ struct @@ -577,7 +621,9 @@ typedef struct _SVM_VMCB /** Offset 0x0C - Intercept control field 2. */ uint32_t u32InterceptCtrl2; /** Offset 0x14-0x3F - Reserved. */ - uint8_t u8Reserved[0x3e - 0x14]; + uint8_t u8Reserved[0x3c - 0x14]; + /** Offset 0x3c - PAUSE filter threshold. */ + uint16_t u16PauseFilterThreshold; /** Offset 0x3e - PAUSE intercept filter count. */ uint16_t u16PauseFilterCount; /** Offset 0x40 - Physical address of IOPM. */ @@ -587,9 +633,9 @@ typedef struct _SVM_VMCB /** Offset 0x50 - TSC Offset. */ uint64_t u64TSCOffset; /** Offset 0x58 - TLB control field. */ - SVM_TLBCTRL TLBCtrl; + SVMTLBCTRL TLBCtrl; /** Offset 0x60 - Interrupt control field. */ - SVM_INTCTRL IntCtrl; + SVMINTCTRL IntCtrl; /** Offset 0x68 - Interrupt shadow. */ uint64_t u64IntShadow; /** Offset 0x70 - Exit code. */ @@ -599,29 +645,39 @@ typedef struct _SVM_VMCB /** Offset 0x80 - Exit info 2. */ uint64_t u64ExitInfo2; /** Offset 0x88 - Exit Interrupt info. */ - SVM_EVENT ExitIntInfo; + SVMEVENT ExitIntInfo; /** Offset 0x90 - Nested Paging. */ - SVM_NPCTRL NestedPaging; - /** Offset 0x98-0xA7 - Reserved. */ - uint8_t u8Reserved2[0xA8-0x98]; + SVMNPCTRL NestedPaging; + /** Offset 0x98 - AVIC APIC BAR. */ + SVMAVIC AvicBar; + /** Offset 0xA0-0xA7 - Reserved. */ + uint8_t u8Reserved2[0xA8-0xA0]; /** Offset 0xA8 - Event injection. */ - SVM_EVENT EventInject; + SVMEVENT EventInject; /** Offset 0xB0 - Host CR3 for nested paging. */ uint64_t u64NestedPagingCR3; /** Offset 0xB8 - LBR Virtualization. */ uint64_t u64LBRVirt; /** Offset 0xC0 - VMCB Clean Bits. */ - uint64_t u64VMCBCleanBits; + uint64_t u64VmcbCleanBits; /** Offset 0xC8 - Next sequential instruction pointer. */ uint64_t u64NextRIP; /** Offset 0xD0 - Number of bytes fetched. */ uint8_t cbInstrFetched; /** Offset 0xD1 - Number of bytes fetched. */ uint8_t abInstr[15]; + /** Offset 0xE0 - AVIC APIC_BACKING_PAGE pointer. */ + SVMAVIC AvicBackingPagePtr; + /** Offset 0xE8-0xEF - Reserved. */ + uint8_t u8Reserved3[0xF0 - 0xE8]; + /** Offset 0xF0 - AVIC LOGICAL_TABLE pointer. */ + SVMAVIC AvicLogicalTablePtr; + /** Offset 0xF8 - AVIC PHYSICAL_TABLE pointer. */ + SVMAVICPHYS AvicPhysicalTablePtr; } ctrl; - /** Offset 0xC0-0x3FF - Reserved. */ - uint8_t u8Reserved3[0x400-0xE0]; + /** Offset 0x100-0x3FF - Reserved. */ + uint8_t u8Reserved3[0x400-0x100]; /** State Save Area. Starts at offset 0x400. */ struct @@ -714,25 +770,36 @@ typedef struct _SVM_VMCB /** Offset 0x698-0xFFF- Reserved. */ uint8_t u8Reserved10[0x1000-0x698]; -} SVM_VMCB; +} SVMVMCB; #pragma pack() -AssertCompileSize(SVM_VMCB, 0x1000); -AssertCompileMemberOffset(SVM_VMCB, ctrl.u16InterceptRdCRx, 0x000); -AssertCompileMemberOffset(SVM_VMCB, ctrl.u16PauseFilterCount,0x03e); -AssertCompileMemberOffset(SVM_VMCB, ctrl.TLBCtrl, 0x058); -AssertCompileMemberOffset(SVM_VMCB, ctrl.ExitIntInfo, 0x088); -AssertCompileMemberOffset(SVM_VMCB, ctrl.EventInject, 0x0A8); -AssertCompileMemberOffset(SVM_VMCB, ctrl.abInstr, 0x0D1); -AssertCompileMemberOffset(SVM_VMCB, guest, 0x400); -AssertCompileMemberOffset(SVM_VMCB, guest.ES, 0x400); -AssertCompileMemberOffset(SVM_VMCB, guest.u8Reserved4, 0x4A0); -AssertCompileMemberOffset(SVM_VMCB, guest.u8CPL, 0x4CB); -AssertCompileMemberOffset(SVM_VMCB, guest.u8Reserved6, 0x4D8); -AssertCompileMemberOffset(SVM_VMCB, guest.u8Reserved7, 0x580); -AssertCompileMemberOffset(SVM_VMCB, guest.u8Reserved9, 0x648); -AssertCompileMemberOffset(SVM_VMCB, guest.u64GPAT, 0x668); -AssertCompileMemberOffset(SVM_VMCB, guest.u64LASTEXCPTO, 0x690); -AssertCompileMemberOffset(SVM_VMCB, u8Reserved10, 0x698); +/** Pointer to the SVMVMCB structure. */ +typedef SVMVMCB *PSVMVMCB; +AssertCompileMemberOffset(SVMVMCB, ctrl.u16InterceptRdCRx, 0x000); +AssertCompileMemberOffset(SVMVMCB, ctrl.u16PauseFilterCount, 0x03e); +AssertCompileMemberOffset(SVMVMCB, ctrl.TLBCtrl, 0x058); +AssertCompileMemberOffset(SVMVMCB, ctrl.ExitIntInfo, 0x088); +AssertCompileMemberOffset(SVMVMCB, ctrl.EventInject, 0x0A8); +AssertCompileMemberOffset(SVMVMCB, ctrl.abInstr, 0x0D1); +AssertCompileMemberOffset(SVMVMCB, ctrl.AvicBackingPagePtr, 0x0E0); +AssertCompileMemberOffset(SVMVMCB, ctrl.AvicLogicalTablePtr, 0x0F0); +AssertCompileMemberOffset(SVMVMCB, ctrl.AvicPhysicalTablePtr, 0x0F8); +AssertCompileMemberOffset(SVMVMCB, guest, 0x400); +AssertCompileMemberOffset(SVMVMCB, guest.ES, 0x400); +AssertCompileMemberOffset(SVMVMCB, guest.TR, 0x490); +AssertCompileMemberOffset(SVMVMCB, guest.u64EFER, 0x4D0); +AssertCompileMemberOffset(SVMVMCB, guest.u64CR4, 0x548); +AssertCompileMemberOffset(SVMVMCB, guest.u64RIP, 0x578); +AssertCompileMemberOffset(SVMVMCB, guest.u64RSP, 0x5D8); +AssertCompileMemberOffset(SVMVMCB, guest.u64CR2, 0x640); +AssertCompileMemberOffset(SVMVMCB, guest.u8Reserved4, 0x4A0); +AssertCompileMemberOffset(SVMVMCB, guest.u8CPL, 0x4CB); +AssertCompileMemberOffset(SVMVMCB, guest.u8Reserved6, 0x4D8); +AssertCompileMemberOffset(SVMVMCB, guest.u8Reserved7, 0x580); +AssertCompileMemberOffset(SVMVMCB, guest.u8Reserved9, 0x648); +AssertCompileMemberOffset(SVMVMCB, guest.u64GPAT, 0x668); +AssertCompileMemberOffset(SVMVMCB, guest.u64LASTEXCPTO, 0x690); +AssertCompileMemberOffset(SVMVMCB, u8Reserved10, 0x698); +AssertCompileSize(SVMVMCB, 0x1000); #ifdef IN_RING0 VMMR0DECL(int) SVMR0InvalidatePage(PVM pVM, PVMCPU pVCpu, RTGCPTR GCVirt); diff --git a/include/VBox/vmm/hm_vmx.h b/include/VBox/vmm/hm_vmx.h new file mode 100644 index 00000000..a84b01ca --- /dev/null +++ b/include/VBox/vmm/hm_vmx.h @@ -0,0 +1,2343 @@ +/** @file + * HM - VMX Structures and Definitions. (VMM) + */ + +/* + * Copyright (C) 2006-2013 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL) only, as it comes in the "COPYING.CDDL" file of the + * VirtualBox OSE distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + */ + +#ifndef ___VBox_vmm_vmx_h +#define ___VBox_vmm_vmx_h + +#include <VBox/types.h> +#include <VBox/err.h> +#include <iprt/x86.h> +#include <iprt/assert.h> + +/* In Visual C++ versions prior to 2012, the vmx intrinsics are only available + when targeting AMD64. */ +#if RT_INLINE_ASM_USES_INTRIN >= 16 && defined(RT_ARCH_AMD64) +# include <intrin.h> +/* We always want them as intrinsics, no functions. */ +# pragma intrinsic(__vmx_on) +# pragma intrinsic(__vmx_off) +# pragma intrinsic(__vmx_vmclear) +# pragma intrinsic(__vmx_vmptrld) +# pragma intrinsic(__vmx_vmread) +# pragma intrinsic(__vmx_vmwrite) +# define VMX_USE_MSC_INTRINSICS 1 +#else +# define VMX_USE_MSC_INTRINSICS 0 +#endif + + +/** @defgroup grp_vmx vmx Types and Definitions + * @ingroup grp_hm + * @{ + */ + +/** @def HMVMXCPU_GST_SET_UPDATED + * Sets a guest-state-updated flag. + * + * @param pVCpu Pointer to the VMCPU. + * @param fFlag The flag to set. + */ +#define HMVMXCPU_GST_SET_UPDATED(pVCpu, fFlag) (ASMAtomicUoOrU32(&(pVCpu)->hm.s.vmx.fUpdatedGuestState, (fFlag))) + +/** @def HMVMXCPU_GST_IS_SET + * Checks if all the flags in the specified guest-state-updated set is pending. + * + * @param pVCpu Pointer to the VMCPU. + * @param fFlag The flag to check. + */ +#define HMVMXCPU_GST_IS_SET(pVCpu, fFlag) ((ASMAtomicUoReadU32(&(pVCpu)->hm.s.vmx.fUpdatedGuestState) & (fFlag)) == (fFlag)) + +/** @def HMVMXCPU_GST_IS_UPDATED + * Checks if one or more of the flags in the specified guest-state-updated set + * is updated. + * + * @param pVCpu Pointer to the VMCPU. + * @param fFlags The flags to check for. + */ +#define HMVMXCPU_GST_IS_UPDATED(pVCpu, fFlags) RT_BOOL(ASMAtomicUoReadU32(&(pVCpu)->hm.s.vmx.fUpdatedGuestState) & (fFlags)) + +/** @def HMVMXCPU_GST_RESET_TO + * Resets the guest-state-updated flags to the specified value. + * + * @param pVCpu Pointer to the VMCPU. + * @param fFlags The new value. + */ +#define HMVMXCPU_GST_RESET_TO(pVCpu, fFlags) (ASMAtomicUoWriteU32(&(pVCpu)->hm.s.vmx.fUpdatedGuestState, (fFlags))) + +/** @def HMVMXCPU_GST_VALUE + * Returns the current guest-state-updated flags value. + * + * @param pVCpu Pointer to the VMCPU. + */ +#define HMVMXCPU_GST_VALUE(pVCpu) (ASMAtomicUoReadU32(&(pVCpu)->hm.s.vmx.fUpdatedGuestState)) + +/** @name Host-state restoration flags. + * @{ + */ +/* If you change these values don't forget to update the assembly defines as well! */ +#define VMX_RESTORE_HOST_SEL_DS RT_BIT(0) +#define VMX_RESTORE_HOST_SEL_ES RT_BIT(1) +#define VMX_RESTORE_HOST_SEL_FS RT_BIT(2) +#define VMX_RESTORE_HOST_SEL_GS RT_BIT(3) +#define VMX_RESTORE_HOST_SEL_TR RT_BIT(4) +#define VMX_RESTORE_HOST_GDTR RT_BIT(5) +#define VMX_RESTORE_HOST_IDTR RT_BIT(6) +#define VMX_RESTORE_HOST_REQUIRED RT_BIT(7) +/** @} */ + +/** + * Host-state restoration structure. + * This holds host-state fields that require manual restoration. + * Assembly version found in hm_vmx.mac (should be automatically verified). + */ +typedef struct VMXRESTOREHOST +{ + RTSEL uHostSelDS; /* 0x00 */ + RTSEL uHostSelES; /* 0x02 */ + RTSEL uHostSelFS; /* 0x04 */ + RTSEL uHostSelGS; /* 0x06 */ + RTSEL uHostSelTR; /* 0x08 */ + uint8_t abPadding0[4]; + X86XDTR64 HostGdtr; /**< 0x0e - should be aligned by it's 64-bit member. */ + uint8_t abPadding1[6]; + X86XDTR64 HostIdtr; /**< 0x1e - should be aligned by it's 64-bit member. */ + uint64_t uHostFSBase; /* 0x28 */ + uint64_t uHostGSBase; /* 0x30 */ +} VMXRESTOREHOST; +/** Pointer to VMXRESTOREHOST. */ +typedef VMXRESTOREHOST *PVMXRESTOREHOST; +AssertCompileSize(X86XDTR64, 10); +AssertCompileMemberOffset(VMXRESTOREHOST, HostGdtr.uAddr, 16); +AssertCompileMemberOffset(VMXRESTOREHOST, HostIdtr.uAddr, 32); +AssertCompileMemberOffset(VMXRESTOREHOST, uHostFSBase, 40); +AssertCompileSize(VMXRESTOREHOST, 56); + +/** @name VMX HM-error codes for VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO. + * UFC = Unsupported Feature Combination. + * @{ + */ +/** Unsupported pin-based VM-execution controls combo. */ +#define VMX_UFC_CTRL_PIN_EXEC 0 +/** Unsupported processor-based VM-execution controls combo. */ +#define VMX_UFC_CTRL_PROC_EXEC 1 +/** Unsupported pin-based VM-execution controls combo. */ +#define VMX_UFC_CTRL_PROC_MOV_DRX_EXIT 2 +/** Unsupported VM-entry controls combo. */ +#define VMX_UFC_CTRL_ENTRY 3 +/** Unsupported VM-exit controls combo. */ +#define VMX_UFC_CTRL_EXIT 4 +/** MSR storage capacity of the VMCS autoload/store area is not sufficient + * for storing host MSRs. */ +#define VMX_UFC_INSUFFICIENT_HOST_MSR_STORAGE 5 +/** MSR storage capacity of the VMCS autoload/store area is not sufficient + * for storing guest MSRs. */ +#define VMX_UFC_INSUFFICIENT_GUEST_MSR_STORAGE 6 +/** Invalid VMCS size. */ +#define VMX_UFC_INVALID_VMCS_SIZE 7 +/** @} */ + +/** @name VMX HM-error codes for VERR_VMX_INVALID_GUEST_STATE. + * IGS = Invalid Guest State. + * @{ + */ +/** An error occurred while checking invalid-guest-state. */ +#define VMX_IGS_ERROR 0 +/** The invalid guest-state checks did not find any reason why. */ +#define VMX_IGS_REASON_NOT_FOUND 1 +/** CR0 fixed1 bits invalid. */ +#define VMX_IGS_CR0_FIXED1 2 +/** CR0 fixed0 bits invalid. */ +#define VMX_IGS_CR0_FIXED0 3 +/** CR0.PE and CR0.PE invalid VT-x/host combination. */ +#define VMX_IGS_CR0_PG_PE_COMBO 4 +/** CR4 fixed1 bits invalid. */ +#define VMX_IGS_CR4_FIXED1 5 +/** CR4 fixed0 bits invalid. */ +#define VMX_IGS_CR4_FIXED0 6 +/** Reserved bits in VMCS' DEBUGCTL MSR field not set to 0 when + * VMX_VMCS_CTRL_ENTRY_LOAD_DEBUG is used. */ +#define VMX_IGS_DEBUGCTL_MSR_RESERVED 7 +/** CR0.PG not set for long-mode when not using unrestricted guest. */ +#define VMX_IGS_CR0_PG_LONGMODE 8 +/** CR4.PAE not set for long-mode guest when not using unrestricted guest. */ +#define VMX_IGS_CR4_PAE_LONGMODE 9 +/** CR4.PCIDE set for 32-bit guest. */ +#define VMX_IGS_CR4_PCIDE 10 +/** VMCS' DR7 reserved bits not set to 0. */ +#define VMX_IGS_DR7_RESERVED 11 +/** VMCS' PERF_GLOBAL MSR reserved bits not set to 0. */ +#define VMX_IGS_PERF_GLOBAL_MSR_RESERVED 12 +/** VMCS' EFER MSR reserved bits not set to 0. */ +#define VMX_IGS_EFER_MSR_RESERVED 13 +/** VMCS' EFER MSR.LMA does not match the IA32e mode guest control. */ +#define VMX_IGS_EFER_LMA_GUEST_MODE_MISMATCH 14 +/** VMCS' EFER MSR.LMA does not match CR0.PG of the guest when not using + * unrestricted guest. */ +#define VMX_IGS_EFER_LMA_PG_MISMATCH 15 +/** CS.Attr.P bit invalid. */ +#define VMX_IGS_CS_ATTR_P_INVALID 16 +/** CS.Attr reserved bits not set to 0. */ +#define VMX_IGS_CS_ATTR_RESERVED 17 +/** CS.Attr.G bit invalid. */ +#define VMX_IGS_CS_ATTR_G_INVALID 18 +/** CS is unusable. */ +#define VMX_IGS_CS_ATTR_UNUSABLE 19 +/** CS and SS DPL unequal. */ +#define VMX_IGS_CS_SS_ATTR_DPL_UNEQUAL 20 +/** CS and SS DPL mismatch. */ +#define VMX_IGS_CS_SS_ATTR_DPL_MISMATCH 21 +/** CS Attr.Type invalid. */ +#define VMX_IGS_CS_ATTR_TYPE_INVALID 22 +/** CS and SS RPL unequal. */ +#define VMX_IGS_SS_CS_RPL_UNEQUAL 23 +/** SS.Attr.DPL and SS RPL unequal. */ +#define VMX_IGS_SS_ATTR_DPL_RPL_UNEQUAL 24 +/** SS.Attr.DPL invalid for segment type. */ +#define VMX_IGS_SS_ATTR_DPL_INVALID 25 +/** SS.Attr.Type invalid. */ +#define VMX_IGS_SS_ATTR_TYPE_INVALID 26 +/** SS.Attr.P bit invalid. */ +#define VMX_IGS_SS_ATTR_P_INVALID 27 +/** SS.Attr reserved bits not set to 0. */ +#define VMX_IGS_SS_ATTR_RESERVED 28 +/** SS.Attr.G bit invalid. */ +#define VMX_IGS_SS_ATTR_G_INVALID 29 +/** DS.Attr.A bit invalid. */ +#define VMX_IGS_DS_ATTR_A_INVALID 30 +/** DS.Attr.P bit invalid. */ +#define VMX_IGS_DS_ATTR_P_INVALID 31 +/** DS.Attr.DPL and DS RPL unequal. */ +#define VMX_IGS_DS_ATTR_DPL_RPL_UNEQUAL 32 +/** DS.Attr reserved bits not set to 0. */ +#define VMX_IGS_DS_ATTR_RESERVED 33 +/** DS.Attr.G bit invalid. */ +#define VMX_IGS_DS_ATTR_G_INVALID 34 +/** DS.Attr.Type invalid. */ +#define VMX_IGS_DS_ATTR_TYPE_INVALID 35 +/** ES.Attr.A bit invalid. */ +#define VMX_IGS_ES_ATTR_A_INVALID 36 +/** ES.Attr.P bit invalid. */ +#define VMX_IGS_ES_ATTR_P_INVALID 37 +/** ES.Attr.DPL and DS RPL unequal. */ +#define VMX_IGS_ES_ATTR_DPL_RPL_UNEQUAL 38 +/** ES.Attr reserved bits not set to 0. */ +#define VMX_IGS_ES_ATTR_RESERVED 39 +/** ES.Attr.G bit invalid. */ +#define VMX_IGS_ES_ATTR_G_INVALID 40 +/** ES.Attr.Type invalid. */ +#define VMX_IGS_ES_ATTR_TYPE_INVALID 41 +/** FS.Attr.A bit invalid. */ +#define VMX_IGS_FS_ATTR_A_INVALID 42 +/** FS.Attr.P bit invalid. */ +#define VMX_IGS_FS_ATTR_P_INVALID 43 +/** FS.Attr.DPL and DS RPL unequal. */ +#define VMX_IGS_FS_ATTR_DPL_RPL_UNEQUAL 44 +/** FS.Attr reserved bits not set to 0. */ +#define VMX_IGS_FS_ATTR_RESERVED 45 +/** FS.Attr.G bit invalid. */ +#define VMX_IGS_FS_ATTR_G_INVALID 46 +/** FS.Attr.Type invalid. */ +#define VMX_IGS_FS_ATTR_TYPE_INVALID 47 +/** GS.Attr.A bit invalid. */ +#define VMX_IGS_GS_ATTR_A_INVALID 48 +/** GS.Attr.P bit invalid. */ +#define VMX_IGS_GS_ATTR_P_INVALID 49 +/** GS.Attr.DPL and DS RPL unequal. */ +#define VMX_IGS_GS_ATTR_DPL_RPL_UNEQUAL 50 +/** GS.Attr reserved bits not set to 0. */ +#define VMX_IGS_GS_ATTR_RESERVED 51 +/** GS.Attr.G bit invalid. */ +#define VMX_IGS_GS_ATTR_G_INVALID 52 +/** GS.Attr.Type invalid. */ +#define VMX_IGS_GS_ATTR_TYPE_INVALID 53 +/** V86 mode CS.Base invalid. */ +#define VMX_IGS_V86_CS_BASE_INVALID 54 +/** V86 mode CS.Limit invalid. */ +#define VMX_IGS_V86_CS_LIMIT_INVALID 55 +/** V86 mode CS.Attr invalid. */ +#define VMX_IGS_V86_CS_ATTR_INVALID 56 +/** V86 mode SS.Base invalid. */ +#define VMX_IGS_V86_SS_BASE_INVALID 57 +/** V86 mode SS.Limit invalid. */ +#define VMX_IGS_V86_SS_LIMIT_INVALID 59 +/** V86 mode SS.Attr invalid. */ +#define VMX_IGS_V86_SS_ATTR_INVALID 59 +/** V86 mode DS.Base invalid. */ +#define VMX_IGS_V86_DS_BASE_INVALID 60 +/** V86 mode DS.Limit invalid. */ +#define VMX_IGS_V86_DS_LIMIT_INVALID 61 +/** V86 mode DS.Attr invalid. */ +#define VMX_IGS_V86_DS_ATTR_INVALID 62 +/** V86 mode ES.Base invalid. */ +#define VMX_IGS_V86_ES_BASE_INVALID 63 +/** V86 mode ES.Limit invalid. */ +#define VMX_IGS_V86_ES_LIMIT_INVALID 64 +/** V86 mode ES.Attr invalid. */ +#define VMX_IGS_V86_ES_ATTR_INVALID 65 +/** V86 mode FS.Base invalid. */ +#define VMX_IGS_V86_FS_BASE_INVALID 66 +/** V86 mode FS.Limit invalid. */ +#define VMX_IGS_V86_FS_LIMIT_INVALID 67 +/** V86 mode FS.Attr invalid. */ +#define VMX_IGS_V86_FS_ATTR_INVALID 68 +/** V86 mode GS.Base invalid. */ +#define VMX_IGS_V86_GS_BASE_INVALID 69 +/** V86 mode GS.Limit invalid. */ +#define VMX_IGS_V86_GS_LIMIT_INVALID 70 +/** V86 mode GS.Attr invalid. */ +#define VMX_IGS_V86_GS_ATTR_INVALID 71 +/** Longmode CS.Base invalid. */ +#define VMX_IGS_LONGMODE_CS_BASE_INVALID 72 +/** Longmode SS.Base invalid. */ +#define VMX_IGS_LONGMODE_SS_BASE_INVALID 73 +/** Longmode DS.Base invalid. */ +#define VMX_IGS_LONGMODE_DS_BASE_INVALID 74 +/** Longmode ES.Base invalid. */ +#define VMX_IGS_LONGMODE_ES_BASE_INVALID 75 +/** SYSENTER ESP is not canonical. */ +#define VMX_IGS_SYSENTER_ESP_NOT_CANONICAL 76 +/** SYSENTER EIP is not canonical. */ +#define VMX_IGS_SYSENTER_EIP_NOT_CANONICAL 77 +/** PAT MSR invalid. */ +#define VMX_IGS_PAT_MSR_INVALID 78 +/** PAT MSR reserved bits not set to 0. */ +#define VMX_IGS_PAT_MSR_RESERVED 79 +/** GDTR.Base is not canonical. */ +#define VMX_IGS_GDTR_BASE_NOT_CANONICAL 80 +/** IDTR.Base is not canonical. */ +#define VMX_IGS_IDTR_BASE_NOT_CANONICAL 81 +/** GDTR.Limit invalid. */ +#define VMX_IGS_GDTR_LIMIT_INVALID 82 +/** IDTR.Limit invalid. */ +#define VMX_IGS_IDTR_LIMIT_INVALID 83 +/** Longmode RIP is invalid. */ +#define VMX_IGS_LONGMODE_RIP_INVALID 84 +/** RFLAGS reserved bits not set to 0. */ +#define VMX_IGS_RFLAGS_RESERVED 85 +/** RFLAGS RA1 reserved bits not set to 1. */ +#define VMX_IGS_RFLAGS_RESERVED1 86 +/** RFLAGS.VM (V86 mode) invalid. */ +#define VMX_IGS_RFLAGS_VM_INVALID 87 +/** RFLAGS.IF invalid. */ +#define VMX_IGS_RFLAGS_IF_INVALID 88 +/** Activity state invalid. */ +#define VMX_IGS_ACTIVITY_STATE_INVALID 89 +/** Activity state HLT invalid when SS.Attr.DPL is not zero. */ +#define VMX_IGS_ACTIVITY_STATE_HLT_INVALID 90 +/** Activity state ACTIVE invalid when block-by-STI or MOV SS. */ +#define VMX_IGS_ACTIVITY_STATE_ACTIVE_INVALID 91 +/** Activity state SIPI WAIT invalid. */ +#define VMX_IGS_ACTIVITY_STATE_SIPI_WAIT_INVALID 92 +/** Interruptibility state reserved bits not set to 0. */ +#define VMX_IGS_INTERRUPTIBILITY_STATE_RESERVED 93 +/** Interruptibility state cannot be block-by-STI -and- MOV SS. */ +#define VMX_IGS_INTERRUPTIBILITY_STATE_STI_MOVSS_INVALID 94 +/** Interruptibility state block-by-STI invalid for EFLAGS. */ +#define VMX_IGS_INTERRUPTIBILITY_STATE_STI_EFL_INVALID 95 +/** Interruptibility state invalid while trying to deliver external + * interrupt. */ +#define VMX_IGS_INTERRUPTIBILITY_STATE_EXT_INT_INVALID 96 +/** Interruptibility state block-by-MOVSS invalid while trying to deliver an + * NMI. */ +#define VMX_IGS_INTERRUPTIBILITY_STATE_MOVSS_INVALID 97 +/** Interruptibility state block-by-SMI invalid when CPU is not in SMM. */ +#define VMX_IGS_INTERRUPTIBILITY_STATE_SMI_INVALID 98 +/** Interruptibility state block-by-SMI invalid when trying to enter SMM. */ +#define VMX_IGS_INTERRUPTIBILITY_STATE_SMI_SMM_INVALID 99 +/** Interruptibilty state block-by-STI (maybe) invalid when trying to deliver + * an NMI. */ +#define VMX_IGS_INTERRUPTIBILITY_STATE_STI_INVALID 100 +/** Interruptibility state block-by-NMI invalid when virtual-NMIs control is + * active. */ +#define VMX_IGS_INTERRUPTIBILITY_STATE_NMI_INVALID 101 +/** Pending debug exceptions reserved bits not set to 0. */ +#define VMX_IGS_PENDING_DEBUG_RESERVED 102 +/** Longmode pending debug exceptions reserved bits not set to 0. */ +#define VMX_IGS_LONGMODE_PENDING_DEBUG_RESERVED 103 +/** Pending debug exceptions.BS bit is not set when it should be. */ +#define VMX_IGS_PENDING_DEBUG_XCPT_BS_NOT_SET 104 +/** Pending debug exceptions.BS bit is not clear when it should be. */ +#define VMX_IGS_PENDING_DEBUG_XCPT_BS_NOT_CLEAR 105 +/** VMCS link pointer reserved bits not set to 0. */ +#define VMX_IGS_VMCS_LINK_PTR_RESERVED 106 +/** TR cannot index into LDT, TI bit MBZ. */ +#define VMX_IGS_TR_TI_INVALID 107 +/** LDTR cannot index into LDT. TI bit MBZ. */ +#define VMX_IGS_LDTR_TI_INVALID 108 +/** TR.Base is not canonical. */ +#define VMX_IGS_TR_BASE_NOT_CANONICAL 109 +/** FS.Base is not canonical. */ +#define VMX_IGS_FS_BASE_NOT_CANONICAL 110 +/** GS.Base is not canonical. */ +#define VMX_IGS_GS_BASE_NOT_CANONICAL 111 +/** LDTR.Base is not canonical. */ +#define VMX_IGS_LDTR_BASE_NOT_CANONICAL 112 +/** TR is unusable. */ +#define VMX_IGS_TR_ATTR_UNUSABLE 113 +/** TR.Attr.S bit invalid. */ +#define VMX_IGS_TR_ATTR_S_INVALID 114 +/** TR is not present. */ +#define VMX_IGS_TR_ATTR_P_INVALID 115 +/** TR.Attr reserved bits not set to 0. */ +#define VMX_IGS_TR_ATTR_RESERVED 116 +/** TR.Attr.G bit invalid. */ +#define VMX_IGS_TR_ATTR_G_INVALID 117 +/** Longmode TR.Attr.Type invalid. */ +#define VMX_IGS_LONGMODE_TR_ATTR_TYPE_INVALID 118 +/** TR.Attr.Type invalid. */ +#define VMX_IGS_TR_ATTR_TYPE_INVALID 119 +/** CS.Attr.S invalid. */ +#define VMX_IGS_CS_ATTR_S_INVALID 120 +/** CS.Attr.DPL invalid. */ +#define VMX_IGS_CS_ATTR_DPL_INVALID 121 +/** PAE PDPTE reserved bits not set to 0. */ +#define VMX_IGS_PAE_PDPTE_RESERVED 123 +/** @} */ + +/** @name VMX VMCS-Read cache indices. + * @{ + */ +# define VMX_VMCS_GUEST_ES_BASE_CACHE_IDX 0 +# define VMX_VMCS_GUEST_CS_BASE_CACHE_IDX 1 +# define VMX_VMCS_GUEST_SS_BASE_CACHE_IDX 2 +# define VMX_VMCS_GUEST_DS_BASE_CACHE_IDX 3 +# define VMX_VMCS_GUEST_FS_BASE_CACHE_IDX 4 +# define VMX_VMCS_GUEST_GS_BASE_CACHE_IDX 5 +# define VMX_VMCS_GUEST_LDTR_BASE_CACHE_IDX 6 +# define VMX_VMCS_GUEST_TR_BASE_CACHE_IDX 7 +# define VMX_VMCS_GUEST_GDTR_BASE_CACHE_IDX 8 +# define VMX_VMCS_GUEST_IDTR_BASE_CACHE_IDX 9 +# define VMX_VMCS_GUEST_RSP_CACHE_IDX 10 +# define VMX_VMCS_GUEST_RIP_CACHE_IDX 11 +# define VMX_VMCS_GUEST_SYSENTER_ESP_CACHE_IDX 12 +# define VMX_VMCS_GUEST_SYSENTER_EIP_CACHE_IDX 13 +# define VMX_VMCS_RO_EXIT_QUALIFICATION_CACHE_IDX 14 +# define VMX_VMCS_MAX_CACHE_IDX (VMX_VMCS_RO_EXIT_QUALIFICATION_CACHE_IDX + 1) +# define VMX_VMCS_GUEST_CR3_CACHE_IDX 15 +# define VMX_VMCS_MAX_NESTED_PAGING_CACHE_IDX (VMX_VMCS_GUEST_CR3_CACHE_IDX + 1) +/** @} */ + +/** @name VMX EPT paging structures + * @{ + */ + +/** + * Number of page table entries in the EPT. (PDPTE/PDE/PTE) + */ +#define EPT_PG_ENTRIES X86_PG_PAE_ENTRIES + +/** + * EPT Page Directory Pointer Entry. Bit view. + * @todo uint64_t isn't safe for bitfields (gcc pedantic warnings, and IIRC, + * this did cause trouble with one compiler/version). + */ +#pragma pack(1) +typedef struct EPTPML4EBITS +{ + /** Present bit. */ + uint64_t u1Present : 1; + /** Writable bit. */ + uint64_t u1Write : 1; + /** Executable bit. */ + uint64_t u1Execute : 1; + /** Reserved (must be 0). */ + uint64_t u5Reserved : 5; + /** Available for software. */ + uint64_t u4Available : 4; + /** Physical address of the next level (PD). Restricted by maximum physical address width of the cpu. */ + uint64_t u40PhysAddr : 40; + /** Availabe for software. */ + uint64_t u12Available : 12; +} EPTPML4EBITS; +#pragma pack() +AssertCompileSize(EPTPML4EBITS, 8); + +/** Bits 12-51 - - EPT - Physical Page number of the next level. */ +#define EPT_PML4E_PG_MASK X86_PML4E_PG_MASK +/** The page shift to get the PML4 index. */ +#define EPT_PML4_SHIFT X86_PML4_SHIFT +/** The PML4 index mask (apply to a shifted page address). */ +#define EPT_PML4_MASK X86_PML4_MASK + +/** + * EPT PML4E. + */ +#pragma pack(1) +typedef union EPTPML4E +{ + /** Normal view. */ + EPTPML4EBITS n; + /** Unsigned integer view. */ + X86PGPAEUINT u; + /** 64 bit unsigned integer view. */ + uint64_t au64[1]; + /** 32 bit unsigned integer view. */ + uint32_t au32[2]; +} EPTPML4E; +#pragma pack() +/** Pointer to a PML4 table entry. */ +typedef EPTPML4E *PEPTPML4E; +/** Pointer to a const PML4 table entry. */ +typedef const EPTPML4E *PCEPTPML4E; +AssertCompileSize(EPTPML4E, 8); + +/** + * EPT PML4 Table. + */ +#pragma pack(1) +typedef struct EPTPML4 +{ + EPTPML4E a[EPT_PG_ENTRIES]; +} EPTPML4; +#pragma pack() +/** Pointer to an EPT PML4 Table. */ +typedef EPTPML4 *PEPTPML4; +/** Pointer to a const EPT PML4 Table. */ +typedef const EPTPML4 *PCEPTPML4; + +/** + * EPT Page Directory Pointer Entry. Bit view. + */ +#pragma pack(1) +typedef struct EPTPDPTEBITS +{ + /** Present bit. */ + uint64_t u1Present : 1; + /** Writable bit. */ + uint64_t u1Write : 1; + /** Executable bit. */ + uint64_t u1Execute : 1; + /** Reserved (must be 0). */ + uint64_t u5Reserved : 5; + /** Available for software. */ + uint64_t u4Available : 4; + /** Physical address of the next level (PD). Restricted by maximum physical address width of the cpu. */ + uint64_t u40PhysAddr : 40; + /** Availabe for software. */ + uint64_t u12Available : 12; +} EPTPDPTEBITS; +#pragma pack() +AssertCompileSize(EPTPDPTEBITS, 8); + +/** Bits 12-51 - - EPT - Physical Page number of the next level. */ +#define EPT_PDPTE_PG_MASK X86_PDPE_PG_MASK +/** The page shift to get the PDPT index. */ +#define EPT_PDPT_SHIFT X86_PDPT_SHIFT +/** The PDPT index mask (apply to a shifted page address). */ +#define EPT_PDPT_MASK X86_PDPT_MASK_AMD64 + +/** + * EPT Page Directory Pointer. + */ +#pragma pack(1) +typedef union EPTPDPTE +{ + /** Normal view. */ + EPTPDPTEBITS n; + /** Unsigned integer view. */ + X86PGPAEUINT u; + /** 64 bit unsigned integer view. */ + uint64_t au64[1]; + /** 32 bit unsigned integer view. */ + uint32_t au32[2]; +} EPTPDPTE; +#pragma pack() +/** Pointer to an EPT Page Directory Pointer Entry. */ +typedef EPTPDPTE *PEPTPDPTE; +/** Pointer to a const EPT Page Directory Pointer Entry. */ +typedef const EPTPDPTE *PCEPTPDPTE; +AssertCompileSize(EPTPDPTE, 8); + +/** + * EPT Page Directory Pointer Table. + */ +#pragma pack(1) +typedef struct EPTPDPT +{ + EPTPDPTE a[EPT_PG_ENTRIES]; +} EPTPDPT; +#pragma pack() +/** Pointer to an EPT Page Directory Pointer Table. */ +typedef EPTPDPT *PEPTPDPT; +/** Pointer to a const EPT Page Directory Pointer Table. */ +typedef const EPTPDPT *PCEPTPDPT; + + +/** + * EPT Page Directory Table Entry. Bit view. + */ +#pragma pack(1) +typedef struct EPTPDEBITS +{ + /** Present bit. */ + uint64_t u1Present : 1; + /** Writable bit. */ + uint64_t u1Write : 1; + /** Executable bit. */ + uint64_t u1Execute : 1; + /** Reserved (must be 0). */ + uint64_t u4Reserved : 4; + /** Big page (must be 0 here). */ + uint64_t u1Size : 1; + /** Available for software. */ + uint64_t u4Available : 4; + /** Physical address of page table. Restricted by maximum physical address width of the cpu. */ + uint64_t u40PhysAddr : 40; + /** Availabe for software. */ + uint64_t u12Available : 12; +} EPTPDEBITS; +#pragma pack() +AssertCompileSize(EPTPDEBITS, 8); + +/** Bits 12-51 - - EPT - Physical Page number of the next level. */ +#define EPT_PDE_PG_MASK X86_PDE_PAE_PG_MASK +/** The page shift to get the PD index. */ +#define EPT_PD_SHIFT X86_PD_PAE_SHIFT +/** The PD index mask (apply to a shifted page address). */ +#define EPT_PD_MASK X86_PD_PAE_MASK + +/** + * EPT 2MB Page Directory Table Entry. Bit view. + */ +#pragma pack(1) +typedef struct EPTPDE2MBITS +{ + /** Present bit. */ + uint64_t u1Present : 1; + /** Writable bit. */ + uint64_t u1Write : 1; + /** Executable bit. */ + uint64_t u1Execute : 1; + /** EPT Table Memory Type. MBZ for non-leaf nodes. */ + uint64_t u3EMT : 3; + /** Ignore PAT memory type */ + uint64_t u1IgnorePAT : 1; + /** Big page (must be 1 here). */ + uint64_t u1Size : 1; + /** Available for software. */ + uint64_t u4Available : 4; + /** Reserved (must be 0). */ + uint64_t u9Reserved : 9; + /** Physical address of the 2MB page. Restricted by maximum physical address width of the cpu. */ + uint64_t u31PhysAddr : 31; + /** Availabe for software. */ + uint64_t u12Available : 12; +} EPTPDE2MBITS; +#pragma pack() +AssertCompileSize(EPTPDE2MBITS, 8); + +/** Bits 21-51 - - EPT - Physical Page number of the next level. */ +#define EPT_PDE2M_PG_MASK X86_PDE2M_PAE_PG_MASK + +/** + * EPT Page Directory Table Entry. + */ +#pragma pack(1) +typedef union EPTPDE +{ + /** Normal view. */ + EPTPDEBITS n; + /** 2MB view (big). */ + EPTPDE2MBITS b; + /** Unsigned integer view. */ + X86PGPAEUINT u; + /** 64 bit unsigned integer view. */ + uint64_t au64[1]; + /** 32 bit unsigned integer view. */ + uint32_t au32[2]; +} EPTPDE; +#pragma pack() +/** Pointer to an EPT Page Directory Table Entry. */ +typedef EPTPDE *PEPTPDE; +/** Pointer to a const EPT Page Directory Table Entry. */ +typedef const EPTPDE *PCEPTPDE; +AssertCompileSize(EPTPDE, 8); + +/** + * EPT Page Directory Table. + */ +#pragma pack(1) +typedef struct EPTPD +{ + EPTPDE a[EPT_PG_ENTRIES]; +} EPTPD; +#pragma pack() +/** Pointer to an EPT Page Directory Table. */ +typedef EPTPD *PEPTPD; +/** Pointer to a const EPT Page Directory Table. */ +typedef const EPTPD *PCEPTPD; + + +/** + * EPT Page Table Entry. Bit view. + */ +#pragma pack(1) +typedef struct EPTPTEBITS +{ + /** 0 - Present bit. + * @remark This is a convenience "misnomer". The bit actually indicates + * read access and the CPU will consider an entry with any of the + * first three bits set as present. Since all our valid entries + * will have this bit set, it can be used as a present indicator + * and allow some code sharing. */ + uint64_t u1Present : 1; + /** 1 - Writable bit. */ + uint64_t u1Write : 1; + /** 2 - Executable bit. */ + uint64_t u1Execute : 1; + /** 5:3 - EPT Memory Type. MBZ for non-leaf nodes. */ + uint64_t u3EMT : 3; + /** 6 - Ignore PAT memory type */ + uint64_t u1IgnorePAT : 1; + /** 11:7 - Available for software. */ + uint64_t u5Available : 5; + /** 51:12 - Physical address of page. Restricted by maximum physical + * address width of the cpu. */ + uint64_t u40PhysAddr : 40; + /** 63:52 - Available for software. */ + uint64_t u12Available : 12; +} EPTPTEBITS; +#pragma pack() +AssertCompileSize(EPTPTEBITS, 8); + +/** Bits 12-51 - - EPT - Physical Page number of the next level. */ +#define EPT_PTE_PG_MASK X86_PTE_PAE_PG_MASK +/** The page shift to get the EPT PTE index. */ +#define EPT_PT_SHIFT X86_PT_PAE_SHIFT +/** The EPT PT index mask (apply to a shifted page address). */ +#define EPT_PT_MASK X86_PT_PAE_MASK + +/** + * EPT Page Table Entry. + */ +#pragma pack(1) +typedef union EPTPTE +{ + /** Normal view. */ + EPTPTEBITS n; + /** Unsigned integer view. */ + X86PGPAEUINT u; + /** 64 bit unsigned integer view. */ + uint64_t au64[1]; + /** 32 bit unsigned integer view. */ + uint32_t au32[2]; +} EPTPTE; +#pragma pack() +/** Pointer to an EPT Page Directory Table Entry. */ +typedef EPTPTE *PEPTPTE; +/** Pointer to a const EPT Page Directory Table Entry. */ +typedef const EPTPTE *PCEPTPTE; +AssertCompileSize(EPTPTE, 8); + +/** + * EPT Page Table. + */ +#pragma pack(1) +typedef struct EPTPT +{ + EPTPTE a[EPT_PG_ENTRIES]; +} EPTPT; +#pragma pack() +/** Pointer to an extended page table. */ +typedef EPTPT *PEPTPT; +/** Pointer to a const extended table. */ +typedef const EPTPT *PCEPTPT; + +/** + * VPID flush types. + */ +typedef enum +{ + /** Invalidate a specific page. */ + VMX_FLUSH_VPID_INDIV_ADDR = 0, + /** Invalidate one context (specific VPID). */ + VMX_FLUSH_VPID_SINGLE_CONTEXT = 1, + /** Invalidate all contexts (all VPIDs). */ + VMX_FLUSH_VPID_ALL_CONTEXTS = 2, + /** Invalidate a single VPID context retaining global mappings. */ + VMX_FLUSH_VPID_SINGLE_CONTEXT_RETAIN_GLOBALS = 3, + /** Unsupported by VirtualBox. */ + VMX_FLUSH_VPID_NOT_SUPPORTED = 0xbad, + /** Unsupported by CPU. */ + VMX_FLUSH_VPID_NONE = 0xb00, + /** 32bit hackishness. */ + VMX_FLUSH_VPID_32BIT_HACK = 0x7fffffff +} VMX_FLUSH_VPID; + +/** + * EPT flush types. + */ +typedef enum +{ + /** Invalidate one context (specific EPT). */ + VMX_FLUSH_EPT_SINGLE_CONTEXT = 1, + /* Invalidate all contexts (all EPTs) */ + VMX_FLUSH_EPT_ALL_CONTEXTS = 2, + /** Unsupported by VirtualBox. */ + VMX_FLUSH_EPT_NOT_SUPPORTED = 0xbad, + /** Unsupported by CPU. */ + VMX_FLUSH_EPT_NONE = 0xb00, + /** 32bit hackishness. */ + VMX_FLUSH_EPT_32BIT_HACK = 0x7fffffff +} VMX_FLUSH_EPT; +/** @} */ + +/** @name MSR autoload/store elements + * @{ + */ +#pragma pack(1) +typedef struct +{ + uint32_t u32Msr; + uint32_t u32Reserved; + uint64_t u64Value; +} VMXAUTOMSR; +#pragma pack() +/** Pointer to an MSR load/store element. */ +typedef VMXAUTOMSR *PVMXAUTOMSR; +/** Pointer to a const MSR load/store element. */ +typedef const VMXAUTOMSR *PCVMXAUTOMSR; +/** @} */ + +/** @name VMX-capability qword + * @{ + */ +#pragma pack(1) +typedef union +{ + struct + { + /** Bits set here -must- be set in the correpsonding VM-execution controls. */ + uint32_t disallowed0; + /** Bits cleared here -must- be cleared in the corresponding VM-execution + * controls. */ + uint32_t allowed1; + } n; + uint64_t u; +} VMX_CAPABILITY; +#pragma pack() +/** @} */ + +/** @name VMX MSRs. + * @{ + */ +typedef struct VMXMSRS +{ + uint64_t u64FeatureCtrl; + uint64_t u64BasicInfo; + VMX_CAPABILITY VmxPinCtls; + VMX_CAPABILITY VmxProcCtls; + VMX_CAPABILITY VmxProcCtls2; + VMX_CAPABILITY VmxExit; + VMX_CAPABILITY VmxEntry; + uint64_t u64Misc; + uint64_t u64Cr0Fixed0; + uint64_t u64Cr0Fixed1; + uint64_t u64Cr4Fixed0; + uint64_t u64Cr4Fixed1; + uint64_t u64VmcsEnum; + uint64_t u64Vmfunc; + uint64_t u64EptVpidCaps; +} VMXMSRS; +/** Pointer to a VMXMSRS struct. */ +typedef VMXMSRS *PVMXMSRS; +/** @} */ + +/** @name VMX EFLAGS reserved bits. + * @{ + */ +/** And-mask for setting reserved bits to zero */ +#define VMX_EFLAGS_RESERVED_0 (~0xffc08028) +/** Or-mask for setting reserved bits to 1 */ +#define VMX_EFLAGS_RESERVED_1 0x00000002 +/** @} */ + +/** @name VMX Basic Exit Reasons. + * @{ + */ +/** -1 Invalid exit code */ +#define VMX_EXIT_INVALID -1 +/** 0 Exception or non-maskable interrupt (NMI). */ +#define VMX_EXIT_XCPT_OR_NMI 0 +/** 1 External interrupt. */ +#define VMX_EXIT_EXT_INT 1 +/** 2 Triple fault. */ +#define VMX_EXIT_TRIPLE_FAULT 2 +/** 3 INIT signal. */ +#define VMX_EXIT_INIT_SIGNAL 3 +/** 4 Start-up IPI (SIPI). */ +#define VMX_EXIT_SIPI 4 +/** 5 I/O system-management interrupt (SMI). */ +#define VMX_EXIT_IO_SMI 5 +/** 6 Other SMI. */ +#define VMX_EXIT_SMI 6 +/** 7 Interrupt window exiting. */ +#define VMX_EXIT_INT_WINDOW 7 +/** 8 NMI window exiting. */ +#define VMX_EXIT_NMI_WINDOW 8 +/** 9 Task switch. */ +#define VMX_EXIT_TASK_SWITCH 9 +/** 10 Guest software attempted to execute CPUID. */ +#define VMX_EXIT_CPUID 10 +/** 10 Guest software attempted to execute GETSEC. */ +#define VMX_EXIT_GETSEC 11 +/** 12 Guest software attempted to execute HLT. */ +#define VMX_EXIT_HLT 12 +/** 13 Guest software attempted to execute INVD. */ +#define VMX_EXIT_INVD 13 +/** 14 Guest software attempted to execute INVLPG. */ +#define VMX_EXIT_INVLPG 14 +/** 15 Guest software attempted to execute RDPMC. */ +#define VMX_EXIT_RDPMC 15 +/** 16 Guest software attempted to execute RDTSC. */ +#define VMX_EXIT_RDTSC 16 +/** 17 Guest software attempted to execute RSM in SMM. */ +#define VMX_EXIT_RSM 17 +/** 18 Guest software executed VMCALL. */ +#define VMX_EXIT_VMCALL 18 +/** 19 Guest software executed VMCLEAR. */ +#define VMX_EXIT_VMCLEAR 19 +/** 20 Guest software executed VMLAUNCH. */ +#define VMX_EXIT_VMLAUNCH 20 +/** 21 Guest software executed VMPTRLD. */ +#define VMX_EXIT_VMPTRLD 21 +/** 22 Guest software executed VMPTRST. */ +#define VMX_EXIT_VMPTRST 22 +/** 23 Guest software executed VMREAD. */ +#define VMX_EXIT_VMREAD 23 +/** 24 Guest software executed VMRESUME. */ +#define VMX_EXIT_VMRESUME 24 +/** 25 Guest software executed VMWRITE. */ +#define VMX_EXIT_VMWRITE 25 +/** 26 Guest software executed VMXOFF. */ +#define VMX_EXIT_VMXOFF 26 +/** 27 Guest software executed VMXON. */ +#define VMX_EXIT_VMXON 27 +/** 28 Control-register accesses. */ +#define VMX_EXIT_MOV_CRX 28 +/** 29 Debug-register accesses. */ +#define VMX_EXIT_MOV_DRX 29 +/** 30 I/O instruction. */ +#define VMX_EXIT_IO_INSTR 30 +/** 31 RDMSR. Guest software attempted to execute RDMSR. */ +#define VMX_EXIT_RDMSR 31 +/** 32 WRMSR. Guest software attempted to execute WRMSR. */ +#define VMX_EXIT_WRMSR 32 +/** 33 VM-entry failure due to invalid guest state. */ +#define VMX_EXIT_ERR_INVALID_GUEST_STATE 33 +/** 34 VM-entry failure due to MSR loading. */ +#define VMX_EXIT_ERR_MSR_LOAD 34 +/** 36 Guest software executed MWAIT. */ +#define VMX_EXIT_MWAIT 36 +/** 37 VM exit due to monitor trap flag. */ +#define VMX_EXIT_MTF 37 +/** 39 Guest software attempted to execute MONITOR. */ +#define VMX_EXIT_MONITOR 39 +/** 40 Guest software attempted to execute PAUSE. */ +#define VMX_EXIT_PAUSE 40 +/** 41 VM-entry failure due to machine-check. */ +#define VMX_EXIT_ERR_MACHINE_CHECK 41 +/** 43 TPR below threshold. Guest software executed MOV to CR8. */ +#define VMX_EXIT_TPR_BELOW_THRESHOLD 43 +/** 44 APIC access. Guest software attempted to access memory at a physical address on the APIC-access page. */ +#define VMX_EXIT_APIC_ACCESS 44 +/** 46 Access to GDTR or IDTR. Guest software attempted to execute LGDT, LIDT, SGDT, or SIDT. */ +#define VMX_EXIT_XDTR_ACCESS 46 +/** 47 Access to LDTR or TR. Guest software attempted to execute LLDT, LTR, SLDT, or STR. */ +#define VMX_EXIT_TR_ACCESS 47 +/** 48 EPT violation. An attempt to access memory with a guest-physical address was disallowed by the configuration of the EPT paging structures. */ +#define VMX_EXIT_EPT_VIOLATION 48 +/** 49 EPT misconfiguration. An attempt to access memory with a guest-physical address encountered a misconfigured EPT paging-structure entry. */ +#define VMX_EXIT_EPT_MISCONFIG 49 +/** 50 INVEPT. Guest software attempted to execute INVEPT. */ +#define VMX_EXIT_INVEPT 50 +/** 51 RDTSCP. Guest software attempted to execute RDTSCP. */ +#define VMX_EXIT_RDTSCP 51 +/** 52 VMX-preemption timer expired. The preemption timer counted down to zero. */ +#define VMX_EXIT_PREEMPT_TIMER 52 +/** 53 INVVPID. Guest software attempted to execute INVVPID. */ +#define VMX_EXIT_INVVPID 53 +/** 54 WBINVD. Guest software attempted to execute WBINVD. */ +#define VMX_EXIT_WBINVD 54 +/** 55 XSETBV. Guest software attempted to execute XSETBV. */ +#define VMX_EXIT_XSETBV 55 +/** 57 RDRAND. Guest software attempted to execute RDRAND. */ +#define VMX_EXIT_RDRAND 57 +/** 58 INVPCID. Guest software attempted to execute INVPCID. */ +#define VMX_EXIT_INVPCID 58 +/** 59 VMFUNC. Guest software attempted to execute VMFUNC. */ +#define VMX_EXIT_VMFUNC 59 +/** The maximum exit value (inclusive). */ +#define VMX_EXIT_MAX (VMX_EXIT_VMFUNC) +/** @} */ + + +/** @name VM Instruction Errors + * @{ + */ +/** VMCALL executed in VMX root operation. */ +#define VMX_ERROR_VMCALL 1 +/** VMCLEAR with invalid physical address. */ +#define VMX_ERROR_VMCLEAR_INVALID_PHYS_ADDR 2 +/** VMCLEAR with VMXON pointer. */ +#define VMX_ERROR_VMCLEAR_INVALID_VMXON_PTR 3 +/** VMLAUNCH with non-clear VMCS. */ +#define VMX_ERROR_VMLAUCH_NON_CLEAR_VMCS 4 +/** VMRESUME with non-launched VMCS. */ +#define VMX_ERROR_VMRESUME_NON_LAUNCHED_VMCS 5 +/** VMRESUME with a corrupted VMCS (indicates corruption of the current VMCS). */ +#define VMX_ERROR_VMRESUME_CORRUPTED_VMCS 6 +/** VM-entry with invalid control field(s). */ +#define VMX_ERROR_VMENTRY_INVALID_CONTROL_FIELDS 7 +/** VM-entry with invalid host-state field(s). */ +#define VMX_ERROR_VMENTRY_INVALID_HOST_STATE 8 +/** VMPTRLD with invalid physical address. */ +#define VMX_ERROR_VMPTRLD_INVALID_PHYS_ADDR 9 +/** VMPTRLD with VMXON pointer. */ +#define VMX_ERROR_VMPTRLD_VMXON_PTR 10 +/** VMPTRLD with incorrect VMCS revision identifier. */ +#define VMX_ERROR_VMPTRLD_WRONG_VMCS_REVISION 11 +/** VMREAD/VMWRITE from/to unsupported VMCS component. */ +#define VMX_ERROR_VMREAD_INVALID_COMPONENT 12 +#define VMX_ERROR_VMWRITE_INVALID_COMPONENT VMX_ERROR_VMREAD_INVALID_COMPONENT +/** VMWRITE to read-only VMCS component. */ +#define VMX_ERROR_VMWRITE_READONLY_COMPONENT 13 +/** VMXON executed in VMX root operation. */ +#define VMX_ERROR_VMXON_IN_VMX_ROOT_OP 15 +/** VM entry with invalid executive-VMCS pointer. */ +#define VMX_ERROR_VMENTRY_INVALID_VMCS_EXEC_PTR 16 +/** VM entry with non-launched executive VMCS. */ +#define VMX_ERROR_VMENTRY_NON_LAUNCHED_EXEC_VMCS 17 +/** VM entry with executive-VMCS pointer not VMXON pointer. */ +#define VMX_ERROR_VMENTRY_EXEC_VMCS_PTR 18 +/** VMCALL with non-clear VMCS. */ +#define VMX_ERROR_VMCALL_NON_CLEAR_VMCS 19 +/** VMCALL with invalid VM-exit control fields. */ +#define VMX_ERROR_VMCALL_INVALID_VMEXIT_FIELDS 20 +/** VMCALL with incorrect MSEG revision identifier. */ +#define VMX_ERROR_VMCALL_INVALID_MSEG_REVISION 22 +/** VMXOFF under dual-monitor treatment of SMIs and SMM. */ +#define VMX_ERROR_VMXOFF_DUAL_MONITOR 23 +/** VMCALL with invalid SMM-monitor features. */ +#define VMX_ERROR_VMCALL_INVALID_SMM_MONITOR 24 +/** VM entry with invalid VM-execution control fields in executive VMCS. */ +#define VMX_ERROR_VMENTRY_INVALID_VM_EXEC_CTRL 25 +/** VM entry with events blocked by MOV SS. */ +#define VMX_ERROR_VMENTRY_MOV_SS 26 +/** Invalid operand to INVEPT/INVVPID. */ +#define VMX_ERROR_INVEPTVPID_INVALID_OPERAND 28 + +/** @} */ + + +/** @name VMX MSRs - Basic VMX information. + * @{ + */ +/** VMCS revision identifier used by the processor. */ +#define MSR_IA32_VMX_BASIC_INFO_VMCS_ID(a) ((a) & 0x7FFFFFFF) +/** Size of the VMCS. */ +#define MSR_IA32_VMX_BASIC_INFO_VMCS_SIZE(a) (((a) >> 32) & 0x1FFF) +/** Width of physical address used for the VMCS. + * 0 -> limited to the available amount of physical ram + * 1 -> within the first 4 GB + */ +#define MSR_IA32_VMX_BASIC_INFO_VMCS_PHYS_WIDTH(a) (((a) >> 48) & 1) +/** Whether the processor supports the dual-monitor treatment of system-management interrupts and system-management code. (always 1) */ +#define MSR_IA32_VMX_BASIC_INFO_VMCS_DUAL_MON(a) (((a) >> 49) & 1) +/** Memory type that must be used for the VMCS. */ +#define MSR_IA32_VMX_BASIC_INFO_VMCS_MEM_TYPE(a) (((a) >> 50) & 0xF) +/** Whether the processor provides additional information for exits due to INS/OUTS. */ +#define MSR_IA32_VMX_BASIC_INFO_VMCS_INS_OUTS(a) RT_BOOL((a) & RT_BIT_64(54)) +/** @} */ + + +/** @name VMX MSRs - Misc VMX info. + * @{ + */ +/** Relationship between the preemption timer and tsc; count down every time bit x of the tsc changes. */ +#define MSR_IA32_VMX_MISC_PREEMPT_TSC_BIT(a) ((a) & 0x1f) +/** Whether VM-exit stores EFER.LMA into the "IA32e mode guest" field. */ +#define MSR_IA32_VMX_MISC_STORE_EFERLMA_VMEXIT(a) (((a) >> 5) & 1) +/** Activity states supported by the implementation. */ +#define MSR_IA32_VMX_MISC_ACTIVITY_STATES(a) (((a) >> 6) & 0x7) +/** Number of CR3 target values supported by the processor. (0-256) */ +#define MSR_IA32_VMX_MISC_CR3_TARGET(a) (((a) >> 16) & 0x1FF) +/** Maximum nr of MSRs in the VMCS. (N+1)*512. */ +#define MSR_IA32_VMX_MISC_MAX_MSR(a) (((((a) >> 25) & 0x7) + 1) * 512) +/** Whether RDMSR can be used to read IA32_SMBASE_MSR in SMM. */ +#define MSR_IA32_VMX_MISC_RDMSR_SMBASE_MSR_SMM(a) (((a) >> 15) & 1) +/** Whether bit 2 of IA32_SMM_MONITOR_CTL can be set to 1. */ +#define MSR_IA32_VMX_MISC_SMM_MONITOR_CTL_B2(a) (((a) >> 28) & 1) +/** Whether VMWRITE can be used to write VM-exit information fields. */ +#define MSR_IA32_VMX_MISC_VMWRITE_VMEXIT_INFO(a) (((a) >> 29) & 1) +/** MSEG revision identifier used by the processor. */ +#define MSR_IA32_VMX_MISC_MSEG_ID(a) ((a) >> 32) +/** @} */ + + +/** @name VMX MSRs - VMCS enumeration field info + * @{ + */ +/** Highest field index. */ +#define MSR_IA32_VMX_VMCS_ENUM_HIGHEST_INDEX(a) (((a) >> 1) & 0x1FF) +/** @} */ + + +/** @name MSR_IA32_VMX_EPT_VPID_CAPS; EPT capabilities MSR + * @{ + */ +#define MSR_IA32_VMX_EPT_VPID_CAP_RWX_X_ONLY RT_BIT_64(0) +#define MSR_IA32_VMX_EPT_VPID_CAP_RWX_W_ONLY RT_BIT_64(1) +#define MSR_IA32_VMX_EPT_VPID_CAP_RWX_WX_ONLY RT_BIT_64(2) +#define MSR_IA32_VMX_EPT_VPID_CAP_GAW_21_BITS RT_BIT_64(3) +#define MSR_IA32_VMX_EPT_VPID_CAP_GAW_30_BITS RT_BIT_64(4) +#define MSR_IA32_VMX_EPT_VPID_CAP_GAW_39_BITS RT_BIT_64(5) +#define MSR_IA32_VMX_EPT_VPID_CAP_GAW_48_BITS RT_BIT_64(6) +#define MSR_IA32_VMX_EPT_VPID_CAP_GAW_57_BITS RT_BIT_64(7) +#define MSR_IA32_VMX_EPT_VPID_CAP_EMT_UC RT_BIT_64(8) +#define MSR_IA32_VMX_EPT_VPID_CAP_EMT_WC RT_BIT_64(9) +#define MSR_IA32_VMX_EPT_VPID_CAP_EMT_WT RT_BIT_64(12) +#define MSR_IA32_VMX_EPT_VPID_CAP_EMT_WP RT_BIT_64(13) +#define MSR_IA32_VMX_EPT_VPID_CAP_EMT_WB RT_BIT_64(14) +#define MSR_IA32_VMX_EPT_VPID_CAP_SP_21_BITS RT_BIT_64(16) +#define MSR_IA32_VMX_EPT_VPID_CAP_SP_30_BITS RT_BIT_64(17) +#define MSR_IA32_VMX_EPT_VPID_CAP_SP_39_BITS RT_BIT_64(18) +#define MSR_IA32_VMX_EPT_VPID_CAP_SP_48_BITS RT_BIT_64(19) +#define MSR_IA32_VMX_EPT_VPID_CAP_INVEPT RT_BIT_64(20) +#define MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_SINGLE_CONTEXT RT_BIT_64(25) +#define MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS RT_BIT_64(26) +#define MSR_IA32_VMX_EPT_VPID_CAP_INVVPID RT_BIT_64(32) +#define MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_INDIV_ADDR RT_BIT_64(40) +#define MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT RT_BIT_64(41) +#define MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_ALL_CONTEXTS RT_BIT_64(42) +#define MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT_RETAIN_GLOBALS RT_BIT_64(43) + +/** @} */ + +/** @name Extended Page Table Pointer (EPTP) + * @{ + */ +/** Uncachable EPT paging structure memory type. */ +#define VMX_EPT_MEMTYPE_UC 0 +/** Write-back EPT paging structure memory type. */ +#define VMX_EPT_MEMTYPE_WB 6 +/** Shift value to get the EPT page walk length (bits 5-3) */ +#define VMX_EPT_PAGE_WALK_LENGTH_SHIFT 3 +/** Mask value to get the EPT page walk length (bits 5-3) */ +#define VMX_EPT_PAGE_WALK_LENGTH_MASK 7 +/** Default EPT page-walk length (1 less than the actual EPT page-walk + * length) */ +#define VMX_EPT_PAGE_WALK_LENGTH_DEFAULT 3 +/** @} */ + + +/** @name VMCS field encoding - 16 bits guest fields + * @{ + */ +#define VMX_VMCS16_GUEST_FIELD_VPID 0x0 +#define VMX_VMCS16_GUEST_FIELD_ES 0x800 +#define VMX_VMCS16_GUEST_FIELD_CS 0x802 +#define VMX_VMCS16_GUEST_FIELD_SS 0x804 +#define VMX_VMCS16_GUEST_FIELD_DS 0x806 +#define VMX_VMCS16_GUEST_FIELD_FS 0x808 +#define VMX_VMCS16_GUEST_FIELD_GS 0x80A +#define VMX_VMCS16_GUEST_FIELD_LDTR 0x80C +#define VMX_VMCS16_GUEST_FIELD_TR 0x80E +/** @} */ + +/** @name VMCS field encoding - 16 bits host fields + * @{ + */ +#define VMX_VMCS16_HOST_FIELD_ES 0xC00 +#define VMX_VMCS16_HOST_FIELD_CS 0xC02 +#define VMX_VMCS16_HOST_FIELD_SS 0xC04 +#define VMX_VMCS16_HOST_FIELD_DS 0xC06 +#define VMX_VMCS16_HOST_FIELD_FS 0xC08 +#define VMX_VMCS16_HOST_FIELD_GS 0xC0A +#define VMX_VMCS16_HOST_FIELD_TR 0xC0C +/** @} */ + +/** @name VMCS field encoding - 64 bits host fields + * @{ + */ +#define VMX_VMCS64_HOST_FIELD_PAT_FULL 0x2C00 +#define VMX_VMCS64_HOST_FIELD_PAT_HIGH 0x2C01 +#define VMX_VMCS64_HOST_FIELD_EFER_FULL 0x2C02 +#define VMX_VMCS64_HOST_FIELD_EFER_HIGH 0x2C03 +#define VMX_VMCS64_HOST_PERF_GLOBAL_CTRL_FULL 0x2C04 /**< MSR IA32_PERF_GLOBAL_CTRL */ +#define VMX_VMCS64_HOST_PERF_GLOBAL_CTRL_HIGH 0x2C05 /**< MSR IA32_PERF_GLOBAL_CTRL */ +/** @} */ + + +/** @name VMCS field encoding - 64 Bits control fields + * @{ + */ +#define VMX_VMCS64_CTRL_IO_BITMAP_A_FULL 0x2000 +#define VMX_VMCS64_CTRL_IO_BITMAP_A_HIGH 0x2001 +#define VMX_VMCS64_CTRL_IO_BITMAP_B_FULL 0x2002 +#define VMX_VMCS64_CTRL_IO_BITMAP_B_HIGH 0x2003 + +/* Optional */ +#define VMX_VMCS64_CTRL_MSR_BITMAP_FULL 0x2004 +#define VMX_VMCS64_CTRL_MSR_BITMAP_HIGH 0x2005 + +#define VMX_VMCS64_CTRL_EXIT_MSR_STORE_FULL 0x2006 +#define VMX_VMCS64_CTRL_EXIT_MSR_STORE_HIGH 0x2007 +#define VMX_VMCS64_CTRL_EXIT_MSR_LOAD_FULL 0x2008 +#define VMX_VMCS64_CTRL_EXIT_MSR_LOAD_HIGH 0x2009 + +#define VMX_VMCS64_CTRL_ENTRY_MSR_LOAD_FULL 0x200A +#define VMX_VMCS64_CTRL_ENTRY_MSR_LOAD_HIGH 0x200B + +#define VMX_VMCS64_CTRL_EXEC_VMCS_PTR_FULL 0x200C +#define VMX_VMCS64_CTRL_EXEC_VMCS_PTR_HIGH 0x200D + +#define VMX_VMCS64_CTRL_TSC_OFFSET_FULL 0x2010 +#define VMX_VMCS64_CTRL_TSC_OFFSET_HIGH 0x2011 + +/** Optional (VMX_VMCS_CTRL_PROC_EXEC_USE_TPR_SHADOW) */ +#define VMX_VMCS64_CTRL_VAPIC_PAGEADDR_FULL 0x2012 +#define VMX_VMCS64_CTRL_VAPIC_PAGEADDR_HIGH 0x2013 + +/** Optional (VMX_VMCS_CTRL_PROC_EXEC2_VIRT_APIC) */ +#define VMX_VMCS64_CTRL_APIC_ACCESSADDR_FULL 0x2014 +#define VMX_VMCS64_CTRL_APIC_ACCESSADDR_HIGH 0x2015 + +/** Optional (VMX_VMCS_CTRL_PROC_EXEC2_VMFUNC) */ +#define VMX_VMCS64_CTRL_VMFUNC_CTRLS_FULL 0x2018 +#define VMX_VMCS64_CTRL_VMFUNC_CTRLS_HIGH 0x2019 + +/** Extended page table pointer. */ +#define VMX_VMCS64_CTRL_EPTP_FULL 0x201a +#define VMX_VMCS64_CTRL_EPTP_HIGH 0x201b + +/** Extended page table pointer lists. */ +#define VMX_VMCS64_CTRL_EPTP_LIST_FULL 0x2024 +#define VMX_VMCS64_CTRL_EPTP_LIST_HIGH 0x2025 + +/** VM-exit guest phyiscal address. */ +#define VMX_VMCS64_EXIT_GUEST_PHYS_ADDR_FULL 0x2400 +#define VMX_VMCS64_EXIT_GUEST_PHYS_ADDR_HIGH 0x2401 +/** @} */ + + +/** @name VMCS field encoding - 64 Bits guest fields + * @{ + */ +#define VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL 0x2800 +#define VMX_VMCS64_GUEST_VMCS_LINK_PTR_HIGH 0x2801 +#define VMX_VMCS64_GUEST_DEBUGCTL_FULL 0x2802 /**< MSR IA32_DEBUGCTL */ +#define VMX_VMCS64_GUEST_DEBUGCTL_HIGH 0x2803 /**< MSR IA32_DEBUGCTL */ +#define VMX_VMCS64_GUEST_PAT_FULL 0x2804 +#define VMX_VMCS64_GUEST_PAT_HIGH 0x2805 +#define VMX_VMCS64_GUEST_EFER_FULL 0x2806 +#define VMX_VMCS64_GUEST_EFER_HIGH 0x2807 +#define VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_FULL 0x2808 /**< MSR IA32_PERF_GLOBAL_CTRL */ +#define VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_HIGH 0x2809 /**< MSR IA32_PERF_GLOBAL_CTRL */ +#define VMX_VMCS64_GUEST_PDPTE0_FULL 0x280A +#define VMX_VMCS64_GUEST_PDPTE0_HIGH 0x280B +#define VMX_VMCS64_GUEST_PDPTE1_FULL 0x280C +#define VMX_VMCS64_GUEST_PDPTE1_HIGH 0x280D +#define VMX_VMCS64_GUEST_PDPTE2_FULL 0x280E +#define VMX_VMCS64_GUEST_PDPTE2_HIGH 0x280F +#define VMX_VMCS64_GUEST_PDPTE3_FULL 0x2810 +#define VMX_VMCS64_GUEST_PDPTE3_HIGH 0x2811 +/** @} */ + + +/** @name VMCS field encoding - 32 Bits control fields + * @{ + */ +#define VMX_VMCS32_CTRL_PIN_EXEC 0x4000 +#define VMX_VMCS32_CTRL_PROC_EXEC 0x4002 +#define VMX_VMCS32_CTRL_EXCEPTION_BITMAP 0x4004 +#define VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK 0x4006 +#define VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH 0x4008 +#define VMX_VMCS32_CTRL_CR3_TARGET_COUNT 0x400A +#define VMX_VMCS32_CTRL_EXIT 0x400C +#define VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT 0x400E +#define VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT 0x4010 +#define VMX_VMCS32_CTRL_ENTRY 0x4012 +#define VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT 0x4014 +#define VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO 0x4016 +#define VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE 0x4018 +#define VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH 0x401A +#define VMX_VMCS32_CTRL_TPR_THRESHOLD 0x401C +#define VMX_VMCS32_CTRL_PROC_EXEC2 0x401E +/** @} */ + + +/** @name VMX_VMCS_CTRL_PIN_EXEC + * @{ + */ +/** External interrupts cause VM exits if set; otherwise dispatched through the guest's IDT. */ +#define VMX_VMCS_CTRL_PIN_EXEC_EXT_INT_EXIT RT_BIT(0) +/** Non-maskable interrupts cause VM exits if set; otherwise dispatched through the guest's IDT. */ +#define VMX_VMCS_CTRL_PIN_EXEC_NMI_EXIT RT_BIT(3) +/** Virtual NMIs. */ +#define VMX_VMCS_CTRL_PIN_EXEC_VIRTUAL_NMI RT_BIT(5) +/** Activate VMX preemption timer. */ +#define VMX_VMCS_CTRL_PIN_EXEC_PREEMPT_TIMER RT_BIT(6) +/* All other bits are reserved and must be set according to MSR IA32_VMX_PROCBASED_CTLS. */ +/** @} */ + +/** @name VMX_VMCS_CTRL_PROC_EXEC + * @{ + */ +/** VM Exit as soon as RFLAGS.IF=1 and no blocking is active. */ +#define VMX_VMCS_CTRL_PROC_EXEC_INT_WINDOW_EXIT RT_BIT(2) +/** Use timestamp counter offset. */ +#define VMX_VMCS_CTRL_PROC_EXEC_USE_TSC_OFFSETTING RT_BIT(3) +/** VM Exit when executing the HLT instruction. */ +#define VMX_VMCS_CTRL_PROC_EXEC_HLT_EXIT RT_BIT(7) +/** VM Exit when executing the INVLPG instruction. */ +#define VMX_VMCS_CTRL_PROC_EXEC_INVLPG_EXIT RT_BIT(9) +/** VM Exit when executing the MWAIT instruction. */ +#define VMX_VMCS_CTRL_PROC_EXEC_MWAIT_EXIT RT_BIT(10) +/** VM Exit when executing the RDPMC instruction. */ +#define VMX_VMCS_CTRL_PROC_EXEC_RDPMC_EXIT RT_BIT(11) +/** VM Exit when executing the RDTSC/RDTSCP instruction. */ +#define VMX_VMCS_CTRL_PROC_EXEC_RDTSC_EXIT RT_BIT(12) +/** VM Exit when executing the MOV to CR3 instruction. (forced to 1 on the 'first' VT-x capable CPUs; this actually includes the newest Nehalem CPUs) */ +#define VMX_VMCS_CTRL_PROC_EXEC_CR3_LOAD_EXIT RT_BIT(15) +/** VM Exit when executing the MOV from CR3 instruction. (forced to 1 on the 'first' VT-x capable CPUs; this actually includes the newest Nehalem CPUs) */ +#define VMX_VMCS_CTRL_PROC_EXEC_CR3_STORE_EXIT RT_BIT(16) +/** VM Exit on CR8 loads. */ +#define VMX_VMCS_CTRL_PROC_EXEC_CR8_LOAD_EXIT RT_BIT(19) +/** VM Exit on CR8 stores. */ +#define VMX_VMCS_CTRL_PROC_EXEC_CR8_STORE_EXIT RT_BIT(20) +/** Use TPR shadow. */ +#define VMX_VMCS_CTRL_PROC_EXEC_USE_TPR_SHADOW RT_BIT(21) +/** VM Exit when virtual nmi blocking is disabled. */ +#define VMX_VMCS_CTRL_PROC_EXEC_NMI_WINDOW_EXIT RT_BIT(22) +/** VM Exit when executing a MOV DRx instruction. */ +#define VMX_VMCS_CTRL_PROC_EXEC_MOV_DR_EXIT RT_BIT(23) +/** VM Exit when executing IO instructions. */ +#define VMX_VMCS_CTRL_PROC_EXEC_UNCOND_IO_EXIT RT_BIT(24) +/** Use IO bitmaps. */ +#define VMX_VMCS_CTRL_PROC_EXEC_USE_IO_BITMAPS RT_BIT(25) +/** Monitor trap flag. */ +#define VMX_VMCS_CTRL_PROC_EXEC_MONITOR_TRAP_FLAG RT_BIT(27) +/** Use MSR bitmaps. */ +#define VMX_VMCS_CTRL_PROC_EXEC_USE_MSR_BITMAPS RT_BIT(28) +/** VM Exit when executing the MONITOR instruction. */ +#define VMX_VMCS_CTRL_PROC_EXEC_MONITOR_EXIT RT_BIT(29) +/** VM Exit when executing the PAUSE instruction. */ +#define VMX_VMCS_CTRL_PROC_EXEC_PAUSE_EXIT RT_BIT(30) +/** Determines whether the secondary processor based VM-execution controls are used. */ +#define VMX_VMCS_CTRL_PROC_EXEC_USE_SECONDARY_EXEC_CTRL RT_BIT(31) +/** @} */ + +/** @name VMX_VMCS_CTRL_PROC_EXEC2 + * @{ + */ +/** Virtualize APIC access. */ +#define VMX_VMCS_CTRL_PROC_EXEC2_VIRT_APIC RT_BIT(0) +/** EPT supported/enabled. */ +#define VMX_VMCS_CTRL_PROC_EXEC2_EPT RT_BIT(1) +/** Descriptor table instructions cause VM-exits. */ +#define VMX_VMCS_CTRL_PROC_EXEC2_DESCRIPTOR_TABLE_EXIT RT_BIT(2) +/** RDTSCP supported/enabled. */ +#define VMX_VMCS_CTRL_PROC_EXEC2_RDTSCP RT_BIT(3) +/** Virtualize x2APIC mode. */ +#define VMX_VMCS_CTRL_PROC_EXEC2_VIRT_X2APIC RT_BIT(4) +/** VPID supported/enabled. */ +#define VMX_VMCS_CTRL_PROC_EXEC2_VPID RT_BIT(5) +/** VM Exit when executing the WBINVD instruction. */ +#define VMX_VMCS_CTRL_PROC_EXEC2_WBINVD_EXIT RT_BIT(6) +/** Unrestricted guest execution. */ +#define VMX_VMCS_CTRL_PROC_EXEC2_UNRESTRICTED_GUEST RT_BIT(7) +/** A specified nr of pause loops cause a VM-exit. */ +#define VMX_VMCS_CTRL_PROC_EXEC2_PAUSE_LOOP_EXIT RT_BIT(10) +/** VM Exit when executing RDRAND instructions. */ +#define VMX_VMCS_CTRL_PROC_EXEC2_RDRAND_EXIT RT_BIT(11) +/** Enables INVPCID instructions. */ +#define VMX_VMCS_CTRL_PROC_EXEC2_INVPCID RT_BIT(12) +/** Enables VMFUNC instructions. */ +#define VMX_VMCS_CTRL_PROC_EXEC2_VMFUNC RT_BIT(13) +/** @} */ + + +/** @name VMX_VMCS_CTRL_ENTRY + * @{ + */ +/** Load guest debug controls (dr7 & IA32_DEBUGCTL_MSR) (forced to 1 on the 'first' VT-x capable CPUs; this actually includes the newest Nehalem CPUs) */ +#define VMX_VMCS_CTRL_ENTRY_LOAD_DEBUG RT_BIT(2) +/** 64 bits guest mode. Must be 0 for CPUs that don't support AMD64. */ +#define VMX_VMCS_CTRL_ENTRY_IA32E_MODE_GUEST RT_BIT(9) +/** In SMM mode after VM-entry. */ +#define VMX_VMCS_CTRL_ENTRY_ENTRY_SMM RT_BIT(10) +/** Disable dual treatment of SMI and SMM; must be zero for VM-entry outside of SMM. */ +#define VMX_VMCS_CTRL_ENTRY_DEACTIVATE_DUALMON RT_BIT(11) +/** Whether the guest IA32_PERF_GLOBAL_CTRL MSR is loaded on VM entry. */ +#define VMX_VMCS_CTRL_ENTRY_LOAD_GUEST_PERF_MSR RT_BIT(13) +/** Whether the guest IA32_PAT MSR is loaded on VM entry. */ +#define VMX_VMCS_CTRL_ENTRY_LOAD_GUEST_PAT_MSR RT_BIT(14) +/** Whether the guest IA32_EFER MSR is loaded on VM entry. */ +#define VMX_VMCS_CTRL_ENTRY_LOAD_GUEST_EFER_MSR RT_BIT(15) +/** @} */ + + +/** @name VMX_VMCS_CTRL_EXIT + * @{ + */ +/** Save guest debug controls (dr7 & IA32_DEBUGCTL_MSR) (forced to 1 on the 'first' VT-x capable CPUs; this actually includes the newest Nehalem CPUs) */ +#define VMX_VMCS_CTRL_EXIT_SAVE_DEBUG RT_BIT(2) +/** Return to long mode after a VM-exit. */ +#define VMX_VMCS_CTRL_EXIT_HOST_ADDR_SPACE_SIZE RT_BIT(9) +/** Whether the IA32_PERF_GLOBAL_CTRL MSR is loaded on VM exit. */ +#define VMX_VMCS_CTRL_EXIT_LOAD_PERF_MSR RT_BIT(12) +/** Acknowledge external interrupts with the irq controller if one caused a VM-exit. */ +#define VMX_VMCS_CTRL_EXIT_ACK_EXT_INT RT_BIT(15) +/** Whether the guest IA32_PAT MSR is saved on VM exit. */ +#define VMX_VMCS_CTRL_EXIT_SAVE_GUEST_PAT_MSR RT_BIT(18) +/** Whether the host IA32_PAT MSR is loaded on VM exit. */ +#define VMX_VMCS_CTRL_EXIT_LOAD_HOST_PAT_MSR RT_BIT(19) +/** Whether the guest IA32_EFER MSR is saved on VM exit. */ +#define VMX_VMCS_CTRL_EXIT_SAVE_GUEST_EFER_MSR RT_BIT(20) +/** Whether the host IA32_EFER MSR is loaded on VM exit. */ +#define VMX_VMCS_CTRL_EXIT_LOAD_HOST_EFER_MSR RT_BIT(21) +/** Whether the value of the VMX preemption timer is saved on every VM exit. */ +#define VMX_VMCS_CTRL_EXIT_SAVE_VMX_PREEMPT_TIMER RT_BIT(22) +/** @} */ + + +/** @name VMX_VMCS_CTRL_VMFUNC + * @{ + */ +/** EPTP-switching function changes the value of the EPTP to one chosen from the EPTP list. */ +#define VMX_VMCS_CTRL_VMFUNC_EPTP_SWITCHING RT_BIT_64(0) +/** @} */ + + +/** @name VMCS field encoding - 32 Bits read-only fields + * @{ + */ +#define VMX_VMCS32_RO_VM_INSTR_ERROR 0x4400 +#define VMX_VMCS32_RO_EXIT_REASON 0x4402 +#define VMX_VMCS32_RO_EXIT_INTERRUPTION_INFO 0x4404 +#define VMX_VMCS32_RO_EXIT_INTERRUPTION_ERROR_CODE 0x4406 +#define VMX_VMCS32_RO_IDT_INFO 0x4408 +#define VMX_VMCS32_RO_IDT_ERROR_CODE 0x440A +#define VMX_VMCS32_RO_EXIT_INSTR_LENGTH 0x440C +#define VMX_VMCS32_RO_EXIT_INSTR_INFO 0x440E +/** @} */ + +/** @name VMX_VMCS32_RO_EXIT_REASON + * @{ + */ +#define VMX_EXIT_REASON_BASIC(a) ((a) & 0xffff) +/** @} */ + +/** @name VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO + * @{ + */ +#define VMX_ENTRY_INTERRUPTION_INFO_IS_VALID(a) RT_BOOL((a) & RT_BIT(31)) +#define VMX_ENTRY_INTERRUPTION_INFO_TYPE_SHIFT 8 +#define VMX_ENTRY_INTERRUPTION_INFO_TYPE(a) ((a >> VMX_ENTRY_INTERRUPTION_INFO_TYPE_SHIFT) & 7) +/** @} */ + + +/** @name VMX_VMCS32_RO_EXIT_INTERRUPTION_INFO + * @{ + */ +#define VMX_EXIT_INTERRUPTION_INFO_VECTOR(a) ((a) & 0xff) +#define VMX_EXIT_INTERRUPTION_INFO_TYPE_SHIFT 8 +#define VMX_EXIT_INTERRUPTION_INFO_TYPE(a) (((a) >> VMX_EXIT_INTERRUPTION_INFO_TYPE_SHIFT) & 7) +#define VMX_EXIT_INTERRUPTION_INFO_ERROR_CODE_VALID RT_BIT(11) +#define VMX_EXIT_INTERRUPTION_INFO_ERROR_CODE_IS_VALID(a) RT_BOOL((a) & VMX_EXIT_INTERRUPTION_INFO_ERROR_CODE_VALID) +#define VMX_EXIT_INTERRUPTION_INFO_NMI_UNBLOCK(a) ((a) & RT_BIT(12)) +#define VMX_EXIT_INTERRUPTION_INFO_VALID RT_BIT(31) +#define VMX_EXIT_INTERRUPTION_INFO_IS_VALID(a) RT_BOOL((a) & RT_BIT(31)) +/** Construct an irq event injection value from the exit interruption info value (same except that bit 12 is reserved). */ +#define VMX_VMCS_CTRL_ENTRY_IRQ_INFO_FROM_EXIT_INT_INFO(a) ((a) & ~RT_BIT(12)) +/** @} */ + +/** @name VMX_VMCS_RO_EXIT_INTERRUPTION_INFO_TYPE + * @{ + */ +#define VMX_EXIT_INTERRUPTION_INFO_TYPE_EXT_INT 0 +#define VMX_EXIT_INTERRUPTION_INFO_TYPE_NMI 2 +#define VMX_EXIT_INTERRUPTION_INFO_TYPE_HW_XCPT 3 +#define VMX_EXIT_INTERRUPTION_INFO_TYPE_SW_INT 4 +#define VMX_EXIT_INTERRUPTION_INFO_TYPE_PRIV_SW_XCPT 5 +#define VMX_EXIT_INTERRUPTION_INFO_TYPE_SW_XCPT 6 +/** @} */ + +/** @name VMX_VMCS32_RO_IDT_VECTORING_INFO + * @{ + */ +#define VMX_IDT_VECTORING_INFO_VECTOR(a) ((a) & 0xff) +#define VMX_IDT_VECTORING_INFO_TYPE_SHIFT 8 +#define VMX_IDT_VECTORING_INFO_TYPE(a) (((a) >> VMX_IDT_VECTORING_INFO_TYPE_SHIFT) & 7) +#define VMX_IDT_VECTORING_INFO_ERROR_CODE_VALID RT_BIT(11) +#define VMX_IDT_VECTORING_INFO_ERROR_CODE_IS_VALID(a) RT_BOOL((a) & VMX_IDT_VECTORING_INFO_ERROR_CODE_VALID) +#define VMX_IDT_VECTORING_INFO_VALID(a) ((a) & RT_BIT(31)) +#define VMX_ENTRY_INT_INFO_FROM_EXIT_IDT_INFO(a) ((a) & ~RT_BIT(12)) +/** @} */ + +/** @name VMX_VMCS_RO_IDT_VECTORING_INFO_TYPE + * @{ + */ +#define VMX_IDT_VECTORING_INFO_TYPE_EXT_INT 0 +#define VMX_IDT_VECTORING_INFO_TYPE_NMI 2 +#define VMX_IDT_VECTORING_INFO_TYPE_HW_XCPT 3 +#define VMX_IDT_VECTORING_INFO_TYPE_SW_INT 4 +#define VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT 5 +#define VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT 6 +/** @} */ + + +/** @name VMCS field encoding - 32 Bits guest state fields + * @{ + */ +#define VMX_VMCS32_GUEST_ES_LIMIT 0x4800 +#define VMX_VMCS32_GUEST_CS_LIMIT 0x4802 +#define VMX_VMCS32_GUEST_SS_LIMIT 0x4804 +#define VMX_VMCS32_GUEST_DS_LIMIT 0x4806 +#define VMX_VMCS32_GUEST_FS_LIMIT 0x4808 +#define VMX_VMCS32_GUEST_GS_LIMIT 0x480A +#define VMX_VMCS32_GUEST_LDTR_LIMIT 0x480C +#define VMX_VMCS32_GUEST_TR_LIMIT 0x480E +#define VMX_VMCS32_GUEST_GDTR_LIMIT 0x4810 +#define VMX_VMCS32_GUEST_IDTR_LIMIT 0x4812 +#define VMX_VMCS32_GUEST_ES_ACCESS_RIGHTS 0x4814 +#define VMX_VMCS32_GUEST_CS_ACCESS_RIGHTS 0x4816 +#define VMX_VMCS32_GUEST_SS_ACCESS_RIGHTS 0x4818 +#define VMX_VMCS32_GUEST_DS_ACCESS_RIGHTS 0x481A +#define VMX_VMCS32_GUEST_FS_ACCESS_RIGHTS 0x481C +#define VMX_VMCS32_GUEST_GS_ACCESS_RIGHTS 0x481E +#define VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS 0x4820 +#define VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS 0x4822 +#define VMX_VMCS32_GUEST_INTERRUPTIBILITY_STATE 0x4824 +#define VMX_VMCS32_GUEST_ACTIVITY_STATE 0x4826 +#define VMX_VMCS32_GUEST_SYSENTER_CS 0x482A /**< MSR IA32_SYSENTER_CS */ +#define VMX_VMCS32_GUEST_PREEMPT_TIMER_VALUE 0x482E +/** @} */ + + +/** @name VMX_VMCS_GUEST_ACTIVITY_STATE + * @{ + */ +/** The logical processor is active. */ +#define VMX_VMCS_GUEST_ACTIVITY_ACTIVE 0x0 +/** The logical processor is inactive, because executed a HLT instruction. */ +#define VMX_VMCS_GUEST_ACTIVITY_HLT 0x1 +/** The logical processor is inactive, because of a triple fault or other serious error. */ +#define VMX_VMCS_GUEST_ACTIVITY_SHUTDOWN 0x2 +/** The logical processor is inactive, because it's waiting for a startup-IPI */ +#define VMX_VMCS_GUEST_ACTIVITY_SIPI_WAIT 0x3 +/** @} */ + + +/** @name VMX_VMCS_GUEST_INTERRUPTIBILITY_STATE + * @{ + */ +#define VMX_VMCS_GUEST_INTERRUPTIBILITY_STATE_BLOCK_STI RT_BIT(0) +#define VMX_VMCS_GUEST_INTERRUPTIBILITY_STATE_BLOCK_MOVSS RT_BIT(1) +#define VMX_VMCS_GUEST_INTERRUPTIBILITY_STATE_BLOCK_SMI RT_BIT(2) +#define VMX_VMCS_GUEST_INTERRUPTIBILITY_STATE_BLOCK_NMI RT_BIT(3) +/** @} */ + + +/** @name VMCS field encoding - 32 Bits host state fields + * @{ + */ +#define VMX_VMCS32_HOST_SYSENTER_CS 0x4C00 +/** @} */ + +/** @name Natural width control fields + * @{ + */ +#define VMX_VMCS_CTRL_CR0_MASK 0x6000 +#define VMX_VMCS_CTRL_CR4_MASK 0x6002 +#define VMX_VMCS_CTRL_CR0_READ_SHADOW 0x6004 +#define VMX_VMCS_CTRL_CR4_READ_SHADOW 0x6006 +#define VMX_VMCS_CTRL_CR3_TARGET_VAL0 0x6008 +#define VMX_VMCS_CTRL_CR3_TARGET_VAL1 0x600A +#define VMX_VMCS_CTRL_CR3_TARGET_VAL2 0x600C +#define VMX_VMCS_CTRL_CR3_TARGET_VAL31 0x600E +/** @} */ + + +/** @name Natural width read-only data fields + * @{ + */ +#define VMX_VMCS_RO_EXIT_QUALIFICATION 0x6400 +#define VMX_VMCS_RO_IO_RCX 0x6402 +#define VMX_VMCS_RO_IO_RSX 0x6404 +#define VMX_VMCS_RO_IO_RDI 0x6406 +#define VMX_VMCS_RO_IO_RIP 0x6408 +#define VMX_VMCS_RO_EXIT_GUEST_LINEAR_ADDR 0x640A +/** @} */ + + +/** @name VMX_VMCS_RO_EXIT_QUALIFICATION + * @{ + */ +/** 0-2: Debug register number */ +#define VMX_EXIT_QUALIFICATION_DRX_REGISTER(a) ((a) & 7) +/** 3: Reserved; cleared to 0. */ +#define VMX_EXIT_QUALIFICATION_DRX_RES1(a) (((a) >> 3) & 1) +/** 4: Direction of move (0 = write, 1 = read) */ +#define VMX_EXIT_QUALIFICATION_DRX_DIRECTION(a) (((a) >> 4) & 1) +/** 5-7: Reserved; cleared to 0. */ +#define VMX_EXIT_QUALIFICATION_DRX_RES2(a) (((a) >> 5) & 7) +/** 8-11: General purpose register number. */ +#define VMX_EXIT_QUALIFICATION_DRX_GENREG(a) (((a) >> 8) & 0xF) +/** Rest: reserved. */ +/** @} */ + +/** @name VMX_EXIT_QUALIFICATION_DRX_DIRECTION values + * @{ + */ +#define VMX_EXIT_QUALIFICATION_DRX_DIRECTION_WRITE 0 +#define VMX_EXIT_QUALIFICATION_DRX_DIRECTION_READ 1 +/** @} */ + + + +/** @name CRx accesses + * @{ + */ +/** 0-3: Control register number (0 for CLTS & LMSW) */ +#define VMX_EXIT_QUALIFICATION_CRX_REGISTER(a) ((a) & 0xF) +/** 4-5: Access type. */ +#define VMX_EXIT_QUALIFICATION_CRX_ACCESS(a) (((a) >> 4) & 3) +/** 6: LMSW operand type */ +#define VMX_EXIT_QUALIFICATION_CRX_LMSW_OP(a) (((a) >> 6) & 1) +/** 7: Reserved; cleared to 0. */ +#define VMX_EXIT_QUALIFICATION_CRX_RES1(a) (((a) >> 7) & 1) +/** 8-11: General purpose register number (0 for CLTS & LMSW). */ +#define VMX_EXIT_QUALIFICATION_CRX_GENREG(a) (((a) >> 8) & 0xF) +/** 12-15: Reserved; cleared to 0. */ +#define VMX_EXIT_QUALIFICATION_CRX_RES2(a) (((a) >> 12) & 0xF) +/** 16-31: LMSW source data (else 0). */ +#define VMX_EXIT_QUALIFICATION_CRX_LMSW_DATA(a) (((a) >> 16) & 0xFFFF) +/** Rest: reserved. */ +/** @} */ + +/** @name VMX_EXIT_QUALIFICATION_CRX_ACCESS + * @{ + */ +#define VMX_EXIT_QUALIFICATION_CRX_ACCESS_WRITE 0 +#define VMX_EXIT_QUALIFICATION_CRX_ACCESS_READ 1 +#define VMX_EXIT_QUALIFICATION_CRX_ACCESS_CLTS 2 +#define VMX_EXIT_QUALIFICATION_CRX_ACCESS_LMSW 3 +/** @} */ + +/** @name VMX_EXIT_QUALIFICATION_TASK_SWITCH + * @{ + */ +#define VMX_EXIT_QUALIFICATION_TASK_SWITCH_SELECTOR(a) ((a) & 0xffff) +#define VMX_EXIT_QUALIFICATION_TASK_SWITCH_TYPE(a) (((a) >> 30) & 0x3) +/** Task switch caused by a call instruction. */ +#define VMX_EXIT_QUALIFICATION_TASK_SWITCH_TYPE_CALL 0 +/** Task switch caused by an iret instruction. */ +#define VMX_EXIT_QUALIFICATION_TASK_SWITCH_TYPE_IRET 1 +/** Task switch caused by a jmp instruction. */ +#define VMX_EXIT_QUALIFICATION_TASK_SWITCH_TYPE_JMP 2 +/** Task switch caused by an interrupt gate. */ +#define VMX_EXIT_QUALIFICATION_TASK_SWITCH_TYPE_IDT 3 +/** @} */ + + +/** @name VMX_EXIT_EPT_VIOLATION + * @{ + */ +/** Set if the violation was caused by a data read. */ +#define VMX_EXIT_QUALIFICATION_EPT_DATA_READ RT_BIT(0) +/** Set if the violation was caused by a data write. */ +#define VMX_EXIT_QUALIFICATION_EPT_DATA_WRITE RT_BIT(1) +/** Set if the violation was caused by an insruction fetch. */ +#define VMX_EXIT_QUALIFICATION_EPT_INSTR_FETCH RT_BIT(2) +/** AND of the present bit of all EPT structures. */ +#define VMX_EXIT_QUALIFICATION_EPT_ENTRY_PRESENT RT_BIT(3) +/** AND of the write bit of all EPT structures. */ +#define VMX_EXIT_QUALIFICATION_EPT_ENTRY_WRITE RT_BIT(4) +/** AND of the execute bit of all EPT structures. */ +#define VMX_EXIT_QUALIFICATION_EPT_ENTRY_EXECUTE RT_BIT(5) +/** Set if the guest linear address field contains the faulting address. */ +#define VMX_EXIT_QUALIFICATION_EPT_GUEST_ADDR_VALID RT_BIT(7) +/** If bit 7 is one: (reserved otherwise) + * 1 - violation due to physical address access. + * 0 - violation caused by page walk or access/dirty bit updates + */ +#define VMX_EXIT_QUALIFICATION_EPT_TRANSLATED_ACCESS RT_BIT(8) +/** @} */ + + +/** @name VMX_EXIT_PORT_IO + * @{ + */ +/** 0-2: IO operation width. */ +#define VMX_EXIT_QUALIFICATION_IO_WIDTH(a) ((a) & 7) +/** 3: IO operation direction. */ +#define VMX_EXIT_QUALIFICATION_IO_DIRECTION(a) (((a) >> 3) & 1) +/** 4: String IO operation (INS / OUTS). */ +#define VMX_EXIT_QUALIFICATION_IO_IS_STRING(a) RT_BOOL((a) & RT_BIT_64(4)) +/** 5: Repeated IO operation. */ +#define VMX_EXIT_QUALIFICATION_IO_IS_REP(a) RT_BOOL((a) & RT_BIT_64(5)) +/** 6: Operand encoding. */ +#define VMX_EXIT_QUALIFICATION_IO_ENCODING(a) (((a) >> 6) & 1) +/** 16-31: IO Port (0-0xffff). */ +#define VMX_EXIT_QUALIFICATION_IO_PORT(a) (((a) >> 16) & 0xffff) +/* Rest reserved. */ +/** @} */ + +/** @name VMX_EXIT_QUALIFICATION_IO_DIRECTION + * @{ + */ +#define VMX_EXIT_QUALIFICATION_IO_DIRECTION_OUT 0 +#define VMX_EXIT_QUALIFICATION_IO_DIRECTION_IN 1 +/** @} */ + + +/** @name VMX_EXIT_QUALIFICATION_IO_ENCODING + * @{ + */ +#define VMX_EXIT_QUALIFICATION_IO_ENCODING_DX 0 +#define VMX_EXIT_QUALIFICATION_IO_ENCODING_IMM 1 +/** @} */ + +/** @name VMX_EXIT_APIC_ACCESS + * @{ + */ +/** 0-11: If the APIC-access VM exit is due to a linear access, the offset of access within the APIC page. */ +#define VMX_EXIT_QUALIFICATION_APIC_ACCESS_OFFSET(a) ((a) & 0xfff) +/** 12-15: Access type. */ +#define VMX_EXIT_QUALIFICATION_APIC_ACCESS_TYPE(a) ((a) & 0xf000) +/* Rest reserved. */ +/** @} */ + + +/** @name VMX_EXIT_QUALIFICATION_APIC_ACCESS_TYPE; access types + * @{ + */ +/** Linear read access. */ +#define VMX_APIC_ACCESS_TYPE_LINEAR_READ 0 +/** Linear write access. */ +#define VMX_APIC_ACCESS_TYPE_LINEAR_WRITE 1 +/** Linear instruction fetch access. */ +#define VMX_APIC_ACCESS_TYPE_LINEAR_INSTR_FETCH 2 +/** Linear read/write access during event delivery. */ +#define VMX_APIC_ACCESS_TYPE_LINEAR_EVENT_DELIVERY 3 +/** Physical read/write access during event delivery. */ +#define VMX_APIC_ACCESS_TYPE_PHYSICAL_EVENT_DELIVERY 10 +/** Physical access for an instruction fetch or during instruction execution. */ +#define VMX_APIC_ACCESS_TYPE_PHYSICAL_INSTR 15 +/** @} */ + +/** @} */ + +/** @name VMCS field encoding - Natural width guest state fields + * @{ + */ +#define VMX_VMCS_GUEST_CR0 0x6800 +#define VMX_VMCS_GUEST_CR3 0x6802 +#define VMX_VMCS_GUEST_CR4 0x6804 +#define VMX_VMCS_GUEST_ES_BASE 0x6806 +#define VMX_VMCS_GUEST_CS_BASE 0x6808 +#define VMX_VMCS_GUEST_SS_BASE 0x680A +#define VMX_VMCS_GUEST_DS_BASE 0x680C +#define VMX_VMCS_GUEST_FS_BASE 0x680E +#define VMX_VMCS_GUEST_GS_BASE 0x6810 +#define VMX_VMCS_GUEST_LDTR_BASE 0x6812 +#define VMX_VMCS_GUEST_TR_BASE 0x6814 +#define VMX_VMCS_GUEST_GDTR_BASE 0x6816 +#define VMX_VMCS_GUEST_IDTR_BASE 0x6818 +#define VMX_VMCS_GUEST_DR7 0x681A +#define VMX_VMCS_GUEST_RSP 0x681C +#define VMX_VMCS_GUEST_RIP 0x681E +#define VMX_VMCS_GUEST_RFLAGS 0x6820 +#define VMX_VMCS_GUEST_PENDING_DEBUG_EXCEPTIONS 0x6822 +#define VMX_VMCS_GUEST_SYSENTER_ESP 0x6824 /**< MSR IA32_SYSENTER_ESP */ +#define VMX_VMCS_GUEST_SYSENTER_EIP 0x6826 /**< MSR IA32_SYSENTER_EIP */ +/** @} */ + + +/** @name VMX_VMCS_GUEST_DEBUG_EXCEPTIONS + * @{ + */ +/** Hardware breakpoint 0 was met. */ +#define VMX_VMCS_GUEST_DEBUG_EXCEPTIONS_B0 RT_BIT(0) +/** Hardware breakpoint 1 was met. */ +#define VMX_VMCS_GUEST_DEBUG_EXCEPTIONS_B1 RT_BIT(1) +/** Hardware breakpoint 2 was met. */ +#define VMX_VMCS_GUEST_DEBUG_EXCEPTIONS_B2 RT_BIT(2) +/** Hardware breakpoint 3 was met. */ +#define VMX_VMCS_GUEST_DEBUG_EXCEPTIONS_B3 RT_BIT(3) +/** At least one data or IO breakpoint was hit. */ +#define VMX_VMCS_GUEST_DEBUG_EXCEPTIONS_BREAKPOINT_ENABLED RT_BIT(12) +/** A debug exception would have been triggered by single-step execution mode. */ +#define VMX_VMCS_GUEST_DEBUG_EXCEPTIONS_BS RT_BIT(14) +/** Bits 4-11, 13 and 15-63 are reserved. */ + +/** @} */ + +/** @name VMCS field encoding - Natural width host state fields + * @{ + */ +#define VMX_VMCS_HOST_CR0 0x6C00 +#define VMX_VMCS_HOST_CR3 0x6C02 +#define VMX_VMCS_HOST_CR4 0x6C04 +#define VMX_VMCS_HOST_FS_BASE 0x6C06 +#define VMX_VMCS_HOST_GS_BASE 0x6C08 +#define VMX_VMCS_HOST_TR_BASE 0x6C0A +#define VMX_VMCS_HOST_GDTR_BASE 0x6C0C +#define VMX_VMCS_HOST_IDTR_BASE 0x6C0E +#define VMX_VMCS_HOST_SYSENTER_ESP 0x6C10 +#define VMX_VMCS_HOST_SYSENTER_EIP 0x6C12 +#define VMX_VMCS_HOST_RSP 0x6C14 +#define VMX_VMCS_HOST_RIP 0x6C16 +/** @} */ + +/** @} */ + + +/** @defgroup grp_vmx_asm vmx assembly helpers + * @ingroup grp_vmx + * @{ + */ + +/** + * Restores some host-state fields that need not be done on every VM-exit. + * + * @returns VBox status code. + * @param fRestoreHostFlags Flags of which host registers needs to be + * restored. + * @param pRestoreHost Pointer to the host-restore structure. + */ +DECLASM(int) VMXRestoreHostState(uint32_t fRestoreHostFlags, PVMXRESTOREHOST pRestoreHost); + + +/** + * Dispatches an NMI to the host. + */ +DECLASM(int) VMXDispatchHostNmi(void); + + +/** + * Executes VMXON + * + * @returns VBox status code + * @param pVMXOn Physical address of VMXON structure + */ +#if ((RT_INLINE_ASM_EXTERNAL || !defined(RT_ARCH_X86)) && !VMX_USE_MSC_INTRINSICS) || defined(VBOX_WITH_HYBRID_32BIT_KERNEL) +DECLASM(int) VMXEnable(RTHCPHYS pVMXOn); +#else +DECLINLINE(int) VMXEnable(RTHCPHYS pVMXOn) +{ +# if RT_INLINE_ASM_GNU_STYLE + int rc = VINF_SUCCESS; + __asm__ __volatile__ ( + "push %3 \n\t" + "push %2 \n\t" + ".byte 0xF3, 0x0F, 0xC7, 0x34, 0x24 # VMXON [esp] \n\t" + "ja 2f \n\t" + "je 1f \n\t" + "movl $"RT_XSTR(VERR_VMX_INVALID_VMXON_PTR)", %0 \n\t" + "jmp 2f \n\t" + "1: \n\t" + "movl $"RT_XSTR(VERR_VMX_VMXON_FAILED)", %0 \n\t" + "2: \n\t" + "add $8, %%esp \n\t" + :"=rm"(rc) + :"0"(VINF_SUCCESS), + "ir"((uint32_t)pVMXOn), /* don't allow direct memory reference here, */ + "ir"((uint32_t)(pVMXOn >> 32)) /* this would not work with -fomit-frame-pointer */ + :"memory" + ); + return rc; + +# elif VMX_USE_MSC_INTRINSICS + unsigned char rcMsc = __vmx_on(&pVMXOn); + if (RT_LIKELY(rcMsc == 0)) + return VINF_SUCCESS; + return rcMsc == 2 ? VERR_VMX_INVALID_VMXON_PTR : VERR_VMX_VMXON_FAILED; + +# else + int rc = VINF_SUCCESS; + __asm + { + push dword ptr [pVMXOn+4] + push dword ptr [pVMXOn] + _emit 0xF3 + _emit 0x0F + _emit 0xC7 + _emit 0x34 + _emit 0x24 /* VMXON [esp] */ + jnc vmxon_good + mov dword ptr [rc], VERR_VMX_INVALID_VMXON_PTR + jmp the_end + +vmxon_good: + jnz the_end + mov dword ptr [rc], VERR_VMX_VMXON_FAILED +the_end: + add esp, 8 + } + return rc; +# endif +} +#endif + + +/** + * Executes VMXOFF + */ +#if ((RT_INLINE_ASM_EXTERNAL || !defined(RT_ARCH_X86)) && !VMX_USE_MSC_INTRINSICS) || defined(VBOX_WITH_HYBRID_32BIT_KERNEL) +DECLASM(void) VMXDisable(void); +#else +DECLINLINE(void) VMXDisable(void) +{ +# if RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__ ( + ".byte 0x0F, 0x01, 0xC4 # VMXOFF \n\t" + ); + +# elif VMX_USE_MSC_INTRINSICS + __vmx_off(); + +# else + __asm + { + _emit 0x0F + _emit 0x01 + _emit 0xC4 /* VMXOFF */ + } +# endif +} +#endif + + +/** + * Executes VMCLEAR + * + * @returns VBox status code + * @param pVMCS Physical address of VM control structure + */ +#if ((RT_INLINE_ASM_EXTERNAL || !defined(RT_ARCH_X86)) && !VMX_USE_MSC_INTRINSICS) || defined(VBOX_WITH_HYBRID_32BIT_KERNEL) +DECLASM(int) VMXClearVmcs(RTHCPHYS pVMCS); +#else +DECLINLINE(int) VMXClearVmcs(RTHCPHYS pVMCS) +{ +# if RT_INLINE_ASM_GNU_STYLE + int rc = VINF_SUCCESS; + __asm__ __volatile__ ( + "push %3 \n\t" + "push %2 \n\t" + ".byte 0x66, 0x0F, 0xC7, 0x34, 0x24 # VMCLEAR [esp] \n\t" + "jnc 1f \n\t" + "movl $"RT_XSTR(VERR_VMX_INVALID_VMCS_PTR)", %0 \n\t" + "1: \n\t" + "add $8, %%esp \n\t" + :"=rm"(rc) + :"0"(VINF_SUCCESS), + "ir"((uint32_t)pVMCS), /* don't allow direct memory reference here, */ + "ir"((uint32_t)(pVMCS >> 32)) /* this would not work with -fomit-frame-pointer */ + :"memory" + ); + return rc; + +# elif VMX_USE_MSC_INTRINSICS + unsigned char rcMsc = __vmx_vmclear(&pVMCS); + if (RT_LIKELY(rcMsc == 0)) + return VINF_SUCCESS; + return VERR_VMX_INVALID_VMCS_PTR; + +# else + int rc = VINF_SUCCESS; + __asm + { + push dword ptr [pVMCS+4] + push dword ptr [pVMCS] + _emit 0x66 + _emit 0x0F + _emit 0xC7 + _emit 0x34 + _emit 0x24 /* VMCLEAR [esp] */ + jnc success + mov dword ptr [rc], VERR_VMX_INVALID_VMCS_PTR +success: + add esp, 8 + } + return rc; +# endif +} +#endif + + +/** + * Executes VMPTRLD + * + * @returns VBox status code + * @param pVMCS Physical address of VMCS structure + */ +#if ((RT_INLINE_ASM_EXTERNAL || !defined(RT_ARCH_X86)) && !VMX_USE_MSC_INTRINSICS) || defined(VBOX_WITH_HYBRID_32BIT_KERNEL) +DECLASM(int) VMXActivateVmcs(RTHCPHYS pVMCS); +#else +DECLINLINE(int) VMXActivateVmcs(RTHCPHYS pVMCS) +{ +# if RT_INLINE_ASM_GNU_STYLE + int rc = VINF_SUCCESS; + __asm__ __volatile__ ( + "push %3 \n\t" + "push %2 \n\t" + ".byte 0x0F, 0xC7, 0x34, 0x24 # VMPTRLD [esp] \n\t" + "jnc 1f \n\t" + "movl $"RT_XSTR(VERR_VMX_INVALID_VMCS_PTR)", %0 \n\t" + "1: \n\t" + "add $8, %%esp \n\t" + :"=rm"(rc) + :"0"(VINF_SUCCESS), + "ir"((uint32_t)pVMCS), /* don't allow direct memory reference here, */ + "ir"((uint32_t)(pVMCS >> 32)) /* this will not work with -fomit-frame-pointer */ + ); + return rc; + +# elif VMX_USE_MSC_INTRINSICS + unsigned char rcMsc = __vmx_vmptrld(&pVMCS); + if (RT_LIKELY(rcMsc == 0)) + return VINF_SUCCESS; + return VERR_VMX_INVALID_VMCS_PTR; + +# else + int rc = VINF_SUCCESS; + __asm + { + push dword ptr [pVMCS+4] + push dword ptr [pVMCS] + _emit 0x0F + _emit 0xC7 + _emit 0x34 + _emit 0x24 /* VMPTRLD [esp] */ + jnc success + mov dword ptr [rc], VERR_VMX_INVALID_VMCS_PTR + +success: + add esp, 8 + } + return rc; +# endif +} +#endif + +/** + * Executes VMPTRST + * + * @returns VBox status code + * @param pVMCS Address that will receive the current pointer + */ +DECLASM(int) VMXGetActivatedVmcs(RTHCPHYS *pVMCS); + +/** + * Executes VMWRITE + * + * @returns VBox status code + * @retval VINF_SUCCESS + * @retval VERR_VMX_INVALID_VMCS_PTR + * @retval VERR_VMX_INVALID_VMCS_FIELD + * + * @param idxField VMCS index + * @param u32Val 32 bits value + * + * @remarks The values of the two status codes can be ORed together, the result + * will be VERR_VMX_INVALID_VMCS_PTR. + */ +#if ((RT_INLINE_ASM_EXTERNAL || !defined(RT_ARCH_X86)) && !VMX_USE_MSC_INTRINSICS) || defined(VBOX_WITH_HYBRID_32BIT_KERNEL) +DECLASM(int) VMXWriteVmcs32(uint32_t idxField, uint32_t u32Val); +#else +DECLINLINE(int) VMXWriteVmcs32(uint32_t idxField, uint32_t u32Val) +{ +# if RT_INLINE_ASM_GNU_STYLE + int rc = VINF_SUCCESS; + __asm__ __volatile__ ( + ".byte 0x0F, 0x79, 0xC2 # VMWRITE eax, edx \n\t" + "ja 2f \n\t" + "je 1f \n\t" + "movl $"RT_XSTR(VERR_VMX_INVALID_VMCS_PTR)", %0 \n\t" + "jmp 2f \n\t" + "1: \n\t" + "movl $"RT_XSTR(VERR_VMX_INVALID_VMCS_FIELD)", %0 \n\t" + "2: \n\t" + :"=rm"(rc) + :"0"(VINF_SUCCESS), + "a"(idxField), + "d"(u32Val) + ); + return rc; + +# elif VMX_USE_MSC_INTRINSICS + unsigned char rcMsc = __vmx_vmwrite(idxField, u32Val); + if (RT_LIKELY(rcMsc == 0)) + return VINF_SUCCESS; + return rcMsc == 2 ? VERR_VMX_INVALID_VMCS_PTR : VERR_VMX_INVALID_VMCS_FIELD; + +#else + int rc = VINF_SUCCESS; + __asm + { + push dword ptr [u32Val] + mov eax, [idxField] + _emit 0x0F + _emit 0x79 + _emit 0x04 + _emit 0x24 /* VMWRITE eax, [esp] */ + jnc valid_vmcs + mov dword ptr [rc], VERR_VMX_INVALID_VMCS_PTR + jmp the_end + +valid_vmcs: + jnz the_end + mov dword ptr [rc], VERR_VMX_INVALID_VMCS_FIELD +the_end: + add esp, 4 + } + return rc; +# endif +} +#endif + +/** + * Executes VMWRITE + * + * @returns VBox status code + * @retval VINF_SUCCESS + * @retval VERR_VMX_INVALID_VMCS_PTR + * @retval VERR_VMX_INVALID_VMCS_FIELD + * + * @param idxField VMCS index + * @param u64Val 16, 32 or 64 bits value + * + * @remarks The values of the two status codes can be ORed together, the result + * will be VERR_VMX_INVALID_VMCS_PTR. + */ +#if !defined(RT_ARCH_X86) || defined(VBOX_WITH_HYBRID_32BIT_KERNEL) +# if !VMX_USE_MSC_INTRINSICS || ARCH_BITS != 64 +DECLASM(int) VMXWriteVmcs64(uint32_t idxField, uint64_t u64Val); +# else /* VMX_USE_MSC_INTRINSICS */ +DECLINLINE(int) VMXWriteVmcs64(uint32_t idxField, uint64_t u64Val) +{ + unsigned char rcMsc = __vmx_vmwrite(idxField, u64Val); + if (RT_LIKELY(rcMsc == 0)) + return VINF_SUCCESS; + return rcMsc == 2 ? VERR_VMX_INVALID_VMCS_PTR : VERR_VMX_INVALID_VMCS_FIELD; +} +# endif /* VMX_USE_MSC_INTRINSICS */ +#else +# define VMXWriteVmcs64(idxField, u64Val) VMXWriteVmcs64Ex(pVCpu, idxField, u64Val) /** @todo dead ugly, picking up pVCpu like this */ +VMMR0DECL(int) VMXWriteVmcs64Ex(PVMCPU pVCpu, uint32_t idxField, uint64_t u64Val); +#endif + +#ifdef VBOX_WITH_HYBRID_32BIT_KERNEL +# define VMXWriteVmcsHstN(idxField, uVal) HMVMX_IS_64BIT_HOST_MODE() ? \ + VMXWriteVmcs64(idxField, uVal) \ + : VMXWriteVmcs32(idxField, uVal) +# define VMXWriteVmcsGstN(idxField, u64Val) (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests) ? \ + VMXWriteVmcs64(idxField, u64Val) \ + : VMXWriteVmcs32(idxField, u64Val) +#elif ARCH_BITS == 32 +# define VMXWriteVmcsHstN VMXWriteVmcs32 +# define VMXWriteVmcsGstN(idxField, u64Val) VMXWriteVmcs64Ex(pVCpu, idxField, u64Val) +# else /* ARCH_BITS == 64 */ +# define VMXWriteVmcsHstN VMXWriteVmcs64 +# define VMXWriteVmcsGstN VMXWriteVmcs64 +# endif + + +/** + * Invalidate a page using invept + * @returns VBox status code + * @param enmFlush Type of flush + * @param pDescriptor Descriptor + */ +DECLASM(int) VMXR0InvEPT(VMX_FLUSH_EPT enmFlush, uint64_t *pDescriptor); + +/** + * Invalidate a page using invvpid + * @returns VBox status code + * @param enmFlush Type of flush + * @param pDescriptor Descriptor + */ +DECLASM(int) VMXR0InvVPID(VMX_FLUSH_VPID enmFlush, uint64_t *pDescriptor); + +/** + * Executes VMREAD + * + * @returns VBox status code + * @retval VINF_SUCCESS + * @retval VERR_VMX_INVALID_VMCS_PTR + * @retval VERR_VMX_INVALID_VMCS_FIELD + * + * @param idxField VMCS index + * @param pData Ptr to store VM field value + * + * @remarks The values of the two status codes can be ORed together, the result + * will be VERR_VMX_INVALID_VMCS_PTR. + */ +#if ((RT_INLINE_ASM_EXTERNAL || !defined(RT_ARCH_X86)) && !VMX_USE_MSC_INTRINSICS) || defined(VBOX_WITH_HYBRID_32BIT_KERNEL) +DECLASM(int) VMXReadVmcs32(uint32_t idxField, uint32_t *pData); +#else +DECLINLINE(int) VMXReadVmcs32(uint32_t idxField, uint32_t *pData) +{ +# if RT_INLINE_ASM_GNU_STYLE + int rc = VINF_SUCCESS; + __asm__ __volatile__ ( + "movl $"RT_XSTR(VINF_SUCCESS)", %0 \n\t" + ".byte 0x0F, 0x78, 0xc2 # VMREAD eax, edx \n\t" + "ja 2f \n\t" + "je 1f \n\t" + "movl $"RT_XSTR(VERR_VMX_INVALID_VMCS_PTR)", %0 \n\t" + "jmp 2f \n\t" + "1: \n\t" + "movl $"RT_XSTR(VERR_VMX_INVALID_VMCS_FIELD)", %0 \n\t" + "2: \n\t" + :"=&r"(rc), + "=d"(*pData) + :"a"(idxField), + "d"(0) + ); + return rc; + +# elif VMX_USE_MSC_INTRINSICS + unsigned char rcMsc; +# if ARCH_BITS == 32 + rcMsc = __vmx_vmread(idxField, pData); +# else + uint64_t u64Tmp; + rcMsc = __vmx_vmread(idxField, &u64Tmp); + *pData = (uint32_t)u64Tmp; +# endif + if (RT_LIKELY(rcMsc == 0)) + return VINF_SUCCESS; + return rcMsc == 2 ? VERR_VMX_INVALID_VMCS_PTR : VERR_VMX_INVALID_VMCS_FIELD; + +#else + int rc = VINF_SUCCESS; + __asm + { + sub esp, 4 + mov dword ptr [esp], 0 + mov eax, [idxField] + _emit 0x0F + _emit 0x78 + _emit 0x04 + _emit 0x24 /* VMREAD eax, [esp] */ + mov edx, pData + pop dword ptr [edx] + jnc valid_vmcs + mov dword ptr [rc], VERR_VMX_INVALID_VMCS_PTR + jmp the_end + +valid_vmcs: + jnz the_end + mov dword ptr [rc], VERR_VMX_INVALID_VMCS_FIELD +the_end: + } + return rc; +# endif +} +#endif + +/** + * Executes VMREAD + * + * @returns VBox status code + * @retval VINF_SUCCESS + * @retval VERR_VMX_INVALID_VMCS_PTR + * @retval VERR_VMX_INVALID_VMCS_FIELD + * + * @param idxField VMCS index + * @param pData Ptr to store VM field value + * + * @remarks The values of the two status codes can be ORed together, the result + * will be VERR_VMX_INVALID_VMCS_PTR. + */ +#if (!defined(RT_ARCH_X86) && !VMX_USE_MSC_INTRINSICS) || defined(VBOX_WITH_HYBRID_32BIT_KERNEL) +DECLASM(int) VMXReadVmcs64(uint32_t idxField, uint64_t *pData); +#else +DECLINLINE(int) VMXReadVmcs64(uint32_t idxField, uint64_t *pData) +{ +# if VMX_USE_MSC_INTRINSICS + unsigned char rcMsc; +# if ARCH_BITS == 32 + size_t uLow; + size_t uHigh; + rcMsc = __vmx_vmread(idxField, &uLow); + rcMsc |= __vmx_vmread(idxField + 1, &uHigh); + *pData = RT_MAKE_U64(uLow, uHigh); +# else + rcMsc = __vmx_vmread(idxField, pData); +# endif + if (RT_LIKELY(rcMsc == 0)) + return VINF_SUCCESS; + return rcMsc == 2 ? VERR_VMX_INVALID_VMCS_PTR : VERR_VMX_INVALID_VMCS_FIELD; + +# elif ARCH_BITS == 32 + int rc; + uint32_t val_hi, val; + rc = VMXReadVmcs32(idxField, &val); + rc |= VMXReadVmcs32(idxField + 1, &val_hi); + AssertRC(rc); + *pData = RT_MAKE_U64(val, val_hi); + return rc; + +# else +# error "Shouldn't be here..." +# endif +} +#endif + +/** + * Gets the last instruction error value from the current VMCS + * + * @returns error value + */ +DECLINLINE(uint32_t) VMXGetLastError(void) +{ +#if ARCH_BITS == 64 + uint64_t uLastError = 0; + int rc = VMXReadVmcs64(VMX_VMCS32_RO_VM_INSTR_ERROR, &uLastError); + AssertRC(rc); + return (uint32_t)uLastError; + +#else /* 32-bit host: */ + uint32_t uLastError = 0; + int rc = VMXReadVmcs32(VMX_VMCS32_RO_VM_INSTR_ERROR, &uLastError); + AssertRC(rc); + return uLastError; +#endif +} + +#ifdef IN_RING0 +VMMR0DECL(int) VMXR0InvalidatePage(PVM pVM, PVMCPU pVCpu, RTGCPTR GCVirt); +VMMR0DECL(int) VMXR0InvalidatePhysPage(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys); +#endif /* IN_RING0 */ + +/** @} */ + +#endif + diff --git a/include/VBox/vmm/hwacc_vmx.mac b/include/VBox/vmm/hm_vmx.mac index 3fc11b43..3a3a1c7b 100644 --- a/include/VBox/vmm/hwacc_vmx.mac +++ b/include/VBox/vmm/hm_vmx.mac @@ -1,9 +1,9 @@ ;; @file -; HWACCM - VMX Structures and Definitions. +; HM - VMX Structures and Definitions. ; ; -; Copyright (C) 2006-2010 Oracle Corporation +; Copyright (C) 2006-2013 Oracle Corporation ; ; This file is part of VirtualBox Open Source Edition (OSE), as ; available from http://www.virtualbox.org. This file is free software; @@ -60,16 +60,16 @@ %define VMX_VMCS_GUEST_LINK_PTR_HIGH 02801h %define VMX_VMCS_GUEST_DEBUGCTL_FULL 02802h %define VMX_VMCS_GUEST_DEBUGCTL_HIGH 02803h -%define VMX_VMCS_CTRL_PIN_EXEC_CONTROLS 04000h -%define VMX_VMCS_CTRL_PROC_EXEC_CONTROLS 04002h +%define VMX_VMCS_CTRL_PIN_EXEC 04000h +%define VMX_VMCS_CTRL_PROC_EXEC 04002h %define VMX_VMCS_CTRL_EXCEPTION_BITMAP 04004h %define VMX_VMCS_CTRL_PAGEFAULT_ERROR_MASK 04006h %define VMX_VMCS_CTRL_PAGEFAULT_ERROR_MATCH 04008h %define VMX_VMCS_CTRL_CR3_TARGET_COUNT 0400Ah -%define VMX_VMCS_CTRL_EXIT_CONTROLS 0400Ch +%define VMX_VMCS_CTRL_EXIT 0400Ch %define VMX_VMCS_CTRL_EXIT_MSR_STORE_COUNT 0400Eh %define VMX_VMCS_CTRL_EXIT_MSR_LOAD_COUNT 04010h -%define VMX_VMCS_CTRL_ENTRY_CONTROLS 04012h +%define VMX_VMCS_CTRL_ENTRY 04012h %define VMX_VMCS_CTRL_ENTRY_MSR_LOAD_COUNT 04014h %define VMX_VMCS_CTRL_ENTRY_IRQ_INFO 04016h %define VMX_VMCS_CTRL_ENTRY_EXCEPTION_ERRCODE 04018h @@ -118,26 +118,26 @@ %define VMX_VMCS_RO_IO_RDI 06406h %define VMX_VMCS_RO_IO_RIP 06408h %define VMX_VMCS_GUEST_LINEAR_ADDR 0640Ah -%define VMX_VMCS64_GUEST_CR0 06800h -%define VMX_VMCS64_GUEST_CR3 06802h -%define VMX_VMCS64_GUEST_CR4 06804h -%define VMX_VMCS64_GUEST_ES_BASE 06806h -%define VMX_VMCS64_GUEST_CS_BASE 06808h -%define VMX_VMCS64_GUEST_SS_BASE 0680Ah -%define VMX_VMCS64_GUEST_DS_BASE 0680Ch -%define VMX_VMCS64_GUEST_FS_BASE 0680Eh -%define VMX_VMCS64_GUEST_GS_BASE 06810h -%define VMX_VMCS64_GUEST_LDTR_BASE 06812h -%define VMX_VMCS64_GUEST_TR_BASE 06814h -%define VMX_VMCS64_GUEST_GDTR_BASE 06816h -%define VMX_VMCS64_GUEST_IDTR_BASE 06818h -%define VMX_VMCS64_GUEST_DR7 0681Ah -%define VMX_VMCS64_GUEST_RSP 0681Ch -%define VMX_VMCS64_GUEST_RIP 0681Eh -%define VMX_VMCS64_GUEST_RFLAGS 06820h +%define VMX_VMCS64_GUEST_CR0 06800h +%define VMX_VMCS64_GUEST_CR3 06802h +%define VMX_VMCS64_GUEST_CR4 06804h +%define VMX_VMCS64_GUEST_ES_BASE 06806h +%define VMX_VMCS64_GUEST_CS_BASE 06808h +%define VMX_VMCS64_GUEST_SS_BASE 0680Ah +%define VMX_VMCS64_GUEST_DS_BASE 0680Ch +%define VMX_VMCS64_GUEST_FS_BASE 0680Eh +%define VMX_VMCS64_GUEST_GS_BASE 06810h +%define VMX_VMCS64_GUEST_LDTR_BASE 06812h +%define VMX_VMCS64_GUEST_TR_BASE 06814h +%define VMX_VMCS64_GUEST_GDTR_BASE 06816h +%define VMX_VMCS64_GUEST_IDTR_BASE 06818h +%define VMX_VMCS64_GUEST_DR7 0681Ah +%define VMX_VMCS64_GUEST_RSP 0681Ch +%define VMX_VMCS64_GUEST_RIP 0681Eh +%define VMX_VMCS64_GUEST_RFLAGS 06820h %define VMX_VMCS_GUEST_DEBUG_EXCEPTIONS 06822h -%define VMX_VMCS64_GUEST_SYSENTER_ESP 06824h -%define VMX_VMCS64_GUEST_SYSENTER_EIP 06826h +%define VMX_VMCS64_GUEST_SYSENTER_ESP 06824h +%define VMX_VMCS64_GUEST_SYSENTER_EIP 06826h %define VMX_VMCS_HOST_CR0 06C00h %define VMX_VMCS_HOST_CR3 06C02h %define VMX_VMCS_HOST_CR4 06C04h @@ -151,4 +151,31 @@ %define VMX_VMCS_HOST_RSP 06C14h %define VMX_VMCS_HOST_RIP 06C16h -%define VMX_VMCS_CTRL_EXIT_CONTROLS_HOST_AMD64 RT_BIT(9) +%define VMX_RESTORE_HOST_SEL_DS 1h ;RT_BIT(0) +%define VMX_RESTORE_HOST_SEL_ES 2h ;RT_BIT(1) +%define VMX_RESTORE_HOST_SEL_FS 4h ;RT_BIT(2) +%define VMX_RESTORE_HOST_SEL_GS 8h ;RT_BIT(3) +%define VMX_RESTORE_HOST_SEL_TR 10h ;RT_BIT(4) +%define VMX_RESTORE_HOST_GDTR 20h ;RT_BIT(5) +%define VMX_RESTORE_HOST_IDTR 40h ;RT_BIT(6) +%define VMX_RESTORE_HOST_REQUIRED 80h ;RT_BIT(7) + +;; C version hm_vmx.h. +struc VMXRESTOREHOST + .uHostSelDS resw 1 + .uHostSelES resw 1 + .uHostSelFS resw 1 + .uHostSelGS resw 1 + .uHostSelTR resw 1 + .abPadding0 resb 4 + .HostGdtr resb 10 + .abPadding1 resb 6 + .HostIdtr resb 10 + .uHostFSBase resq 1 + .uHostGSBase resq 1 +endstruc +AssertCompileMemberOffset(VMXRESTOREHOST, HostGdtr, 16-2) +AssertCompileMemberOffset(VMXRESTOREHOST, HostIdtr, 32-2) +AssertCompileMemberOffset(VMXRESTOREHOST, uHostFSBase, 40) +AssertCompileSize(VMXRESTOREHOST, 56) + diff --git a/include/VBox/vmm/hwacc_vmx.h b/include/VBox/vmm/hwacc_vmx.h deleted file mode 100644 index a96f587e..00000000 --- a/include/VBox/vmm/hwacc_vmx.h +++ /dev/null @@ -1,1708 +0,0 @@ -/** @file - * HWACCM - VMX Structures and Definitions. (VMM) - */ - -/* - * Copyright (C) 2006-2010 Oracle Corporation - * - * This file is part of VirtualBox Open Source Edition (OSE), as - * available from http://www.virtualbox.org. This file is free software; - * you can redistribute it and/or modify it under the terms of the GNU - * General Public License (GPL) as published by the Free Software - * Foundation, in version 2 as it comes in the "COPYING" file of the - * VirtualBox OSE distribution. VirtualBox OSE is distributed in the - * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. - * - * The contents of this file may alternatively be used under the terms - * of the Common Development and Distribution License Version 1.0 - * (CDDL) only, as it comes in the "COPYING.CDDL" file of the - * VirtualBox OSE distribution, in which case the provisions of the - * CDDL are applicable instead of those of the GPL. - * - * You may elect to license modified versions of this file under the - * terms and conditions of either the GPL or the CDDL or both. - */ - -#ifndef ___VBox_vmm_vmx_h -#define ___VBox_vmm_vmx_h - -#include <VBox/types.h> -#include <VBox/err.h> -#include <iprt/x86.h> -#include <iprt/assert.h> - -/** @defgroup grp_vmx vmx Types and Definitions - * @ingroup grp_hwaccm - * @{ - */ - -/** @name VMX EPT paging structures - * @{ - */ - -/** - * Number of page table entries in the EPT. (PDPTE/PDE/PTE) - */ -#define EPT_PG_ENTRIES X86_PG_PAE_ENTRIES - -/** - * EPT Page Directory Pointer Entry. Bit view. - * @todo uint64_t isn't safe for bitfields (gcc pedantic warnings, and IIRC, - * this did cause trouble with one compiler/version). - */ -#pragma pack(1) -typedef struct EPTPML4EBITS -{ - /** Present bit. */ - uint64_t u1Present : 1; - /** Writable bit. */ - uint64_t u1Write : 1; - /** Executable bit. */ - uint64_t u1Execute : 1; - /** Reserved (must be 0). */ - uint64_t u5Reserved : 5; - /** Available for software. */ - uint64_t u4Available : 4; - /** Physical address of the next level (PD). Restricted by maximum physical address width of the cpu. */ - uint64_t u40PhysAddr : 40; - /** Availabe for software. */ - uint64_t u12Available : 12; -} EPTPML4EBITS; -#pragma pack() -AssertCompileSize(EPTPML4EBITS, 8); - -/** Bits 12-51 - - EPT - Physical Page number of the next level. */ -#define EPT_PML4E_PG_MASK X86_PML4E_PG_MASK -/** The page shift to get the PML4 index. */ -#define EPT_PML4_SHIFT X86_PML4_SHIFT -/** The PML4 index mask (apply to a shifted page address). */ -#define EPT_PML4_MASK X86_PML4_MASK - -/** - * EPT PML4E. - */ -#pragma pack(1) -typedef union EPTPML4E -{ - /** Normal view. */ - EPTPML4EBITS n; - /** Unsigned integer view. */ - X86PGPAEUINT u; - /** 64 bit unsigned integer view. */ - uint64_t au64[1]; - /** 32 bit unsigned integer view. */ - uint32_t au32[2]; -} EPTPML4E; -#pragma pack() -/** Pointer to a PML4 table entry. */ -typedef EPTPML4E *PEPTPML4E; -/** Pointer to a const PML4 table entry. */ -typedef const EPTPML4E *PCEPTPML4E; -AssertCompileSize(EPTPML4E, 8); - -/** - * EPT PML4 Table. - */ -#pragma pack(1) -typedef struct EPTPML4 -{ - EPTPML4E a[EPT_PG_ENTRIES]; -} EPTPML4; -#pragma pack() -/** Pointer to an EPT PML4 Table. */ -typedef EPTPML4 *PEPTPML4; -/** Pointer to a const EPT PML4 Table. */ -typedef const EPTPML4 *PCEPTPML4; - -/** - * EPT Page Directory Pointer Entry. Bit view. - */ -#pragma pack(1) -typedef struct EPTPDPTEBITS -{ - /** Present bit. */ - uint64_t u1Present : 1; - /** Writable bit. */ - uint64_t u1Write : 1; - /** Executable bit. */ - uint64_t u1Execute : 1; - /** Reserved (must be 0). */ - uint64_t u5Reserved : 5; - /** Available for software. */ - uint64_t u4Available : 4; - /** Physical address of the next level (PD). Restricted by maximum physical address width of the cpu. */ - uint64_t u40PhysAddr : 40; - /** Availabe for software. */ - uint64_t u12Available : 12; -} EPTPDPTEBITS; -#pragma pack() -AssertCompileSize(EPTPDPTEBITS, 8); - -/** Bits 12-51 - - EPT - Physical Page number of the next level. */ -#define EPT_PDPTE_PG_MASK X86_PDPE_PG_MASK -/** The page shift to get the PDPT index. */ -#define EPT_PDPT_SHIFT X86_PDPT_SHIFT -/** The PDPT index mask (apply to a shifted page address). */ -#define EPT_PDPT_MASK X86_PDPT_MASK_AMD64 - -/** - * EPT Page Directory Pointer. - */ -#pragma pack(1) -typedef union EPTPDPTE -{ - /** Normal view. */ - EPTPDPTEBITS n; - /** Unsigned integer view. */ - X86PGPAEUINT u; - /** 64 bit unsigned integer view. */ - uint64_t au64[1]; - /** 32 bit unsigned integer view. */ - uint32_t au32[2]; -} EPTPDPTE; -#pragma pack() -/** Pointer to an EPT Page Directory Pointer Entry. */ -typedef EPTPDPTE *PEPTPDPTE; -/** Pointer to a const EPT Page Directory Pointer Entry. */ -typedef const EPTPDPTE *PCEPTPDPTE; -AssertCompileSize(EPTPDPTE, 8); - -/** - * EPT Page Directory Pointer Table. - */ -#pragma pack(1) -typedef struct EPTPDPT -{ - EPTPDPTE a[EPT_PG_ENTRIES]; -} EPTPDPT; -#pragma pack() -/** Pointer to an EPT Page Directory Pointer Table. */ -typedef EPTPDPT *PEPTPDPT; -/** Pointer to a const EPT Page Directory Pointer Table. */ -typedef const EPTPDPT *PCEPTPDPT; - - -/** - * EPT Page Directory Table Entry. Bit view. - */ -#pragma pack(1) -typedef struct EPTPDEBITS -{ - /** Present bit. */ - uint64_t u1Present : 1; - /** Writable bit. */ - uint64_t u1Write : 1; - /** Executable bit. */ - uint64_t u1Execute : 1; - /** Reserved (must be 0). */ - uint64_t u4Reserved : 4; - /** Big page (must be 0 here). */ - uint64_t u1Size : 1; - /** Available for software. */ - uint64_t u4Available : 4; - /** Physical address of page table. Restricted by maximum physical address width of the cpu. */ - uint64_t u40PhysAddr : 40; - /** Availabe for software. */ - uint64_t u12Available : 12; -} EPTPDEBITS; -#pragma pack() -AssertCompileSize(EPTPDEBITS, 8); - -/** Bits 12-51 - - EPT - Physical Page number of the next level. */ -#define EPT_PDE_PG_MASK X86_PDE_PAE_PG_MASK -/** The page shift to get the PD index. */ -#define EPT_PD_SHIFT X86_PD_PAE_SHIFT -/** The PD index mask (apply to a shifted page address). */ -#define EPT_PD_MASK X86_PD_PAE_MASK - -/** - * EPT 2MB Page Directory Table Entry. Bit view. - */ -#pragma pack(1) -typedef struct EPTPDE2MBITS -{ - /** Present bit. */ - uint64_t u1Present : 1; - /** Writable bit. */ - uint64_t u1Write : 1; - /** Executable bit. */ - uint64_t u1Execute : 1; - /** EPT Table Memory Type. MBZ for non-leaf nodes. */ - uint64_t u3EMT : 3; - /** Ignore PAT memory type */ - uint64_t u1IgnorePAT : 1; - /** Big page (must be 1 here). */ - uint64_t u1Size : 1; - /** Available for software. */ - uint64_t u4Available : 4; - /** Reserved (must be 0). */ - uint64_t u9Reserved : 9; - /** Physical address of the 2MB page. Restricted by maximum physical address width of the cpu. */ - uint64_t u31PhysAddr : 31; - /** Availabe for software. */ - uint64_t u12Available : 12; -} EPTPDE2MBITS; -#pragma pack() -AssertCompileSize(EPTPDE2MBITS, 8); - -/** Bits 21-51 - - EPT - Physical Page number of the next level. */ -#define EPT_PDE2M_PG_MASK X86_PDE2M_PAE_PG_MASK - -/** - * EPT Page Directory Table Entry. - */ -#pragma pack(1) -typedef union EPTPDE -{ - /** Normal view. */ - EPTPDEBITS n; - /** 2MB view (big). */ - EPTPDE2MBITS b; - /** Unsigned integer view. */ - X86PGPAEUINT u; - /** 64 bit unsigned integer view. */ - uint64_t au64[1]; - /** 32 bit unsigned integer view. */ - uint32_t au32[2]; -} EPTPDE; -#pragma pack() -/** Pointer to an EPT Page Directory Table Entry. */ -typedef EPTPDE *PEPTPDE; -/** Pointer to a const EPT Page Directory Table Entry. */ -typedef const EPTPDE *PCEPTPDE; -AssertCompileSize(EPTPDE, 8); - -/** - * EPT Page Directory Table. - */ -#pragma pack(1) -typedef struct EPTPD -{ - EPTPDE a[EPT_PG_ENTRIES]; -} EPTPD; -#pragma pack() -/** Pointer to an EPT Page Directory Table. */ -typedef EPTPD *PEPTPD; -/** Pointer to a const EPT Page Directory Table. */ -typedef const EPTPD *PCEPTPD; - - -/** - * EPT Page Table Entry. Bit view. - */ -#pragma pack(1) -typedef struct EPTPTEBITS -{ - /** 0 - Present bit. - * @remark This is a convenience "misnomer". The bit actually indicates - * read access and the CPU will consider an entry with any of the - * first three bits set as present. Since all our valid entries - * will have this bit set, it can be used as a present indicator - * and allow some code sharing. */ - uint64_t u1Present : 1; - /** 1 - Writable bit. */ - uint64_t u1Write : 1; - /** 2 - Executable bit. */ - uint64_t u1Execute : 1; - /** 5:3 - EPT Memory Type. MBZ for non-leaf nodes. */ - uint64_t u3EMT : 3; - /** 6 - Ignore PAT memory type */ - uint64_t u1IgnorePAT : 1; - /** 11:7 - Available for software. */ - uint64_t u5Available : 5; - /** 51:12 - Physical address of page. Restricted by maximum physical - * address width of the cpu. */ - uint64_t u40PhysAddr : 40; - /** 63:52 - Available for software. */ - uint64_t u12Available : 12; -} EPTPTEBITS; -#pragma pack() -AssertCompileSize(EPTPTEBITS, 8); - -/** Bits 12-51 - - EPT - Physical Page number of the next level. */ -#define EPT_PTE_PG_MASK X86_PTE_PAE_PG_MASK -/** The page shift to get the EPT PTE index. */ -#define EPT_PT_SHIFT X86_PT_PAE_SHIFT -/** The EPT PT index mask (apply to a shifted page address). */ -#define EPT_PT_MASK X86_PT_PAE_MASK - -/** - * EPT Page Table Entry. - */ -#pragma pack(1) -typedef union EPTPTE -{ - /** Normal view. */ - EPTPTEBITS n; - /** Unsigned integer view. */ - X86PGPAEUINT u; - /** 64 bit unsigned integer view. */ - uint64_t au64[1]; - /** 32 bit unsigned integer view. */ - uint32_t au32[2]; -} EPTPTE; -#pragma pack() -/** Pointer to an EPT Page Directory Table Entry. */ -typedef EPTPTE *PEPTPTE; -/** Pointer to a const EPT Page Directory Table Entry. */ -typedef const EPTPTE *PCEPTPTE; -AssertCompileSize(EPTPTE, 8); - -/** - * EPT Page Table. - */ -#pragma pack(1) -typedef struct EPTPT -{ - EPTPTE a[EPT_PG_ENTRIES]; -} EPTPT; -#pragma pack() -/** Pointer to an extended page table. */ -typedef EPTPT *PEPTPT; -/** Pointer to a const extended table. */ -typedef const EPTPT *PCEPTPT; - -/** - * VPID flush types. - */ -typedef enum -{ - /** Invalidate a specific page. */ - VMX_FLUSH_VPID_INDIV_ADDR = 0, - /** Invalidate one context (specific VPID). */ - VMX_FLUSH_VPID_SINGLE_CONTEXT = 1, - /** Invalidate all contexts (all VPIDs). */ - VMX_FLUSH_VPID_ALL_CONTEXTS = 2, - /** Invalidate a single VPID context retaining global mappings. */ - VMX_FLUSH_VPID_SINGLE_CONTEXT_RETAIN_GLOBALS = 3, - /** Unsupported by VirtualBox. */ - VMX_FLUSH_VPID_NOT_SUPPORTED = 0xbad, - /** Unsupported by CPU. */ - VMX_FLUSH_VPID_NONE = 0xb00, - /** 32bit hackishness. */ - VMX_FLUSH_VPID_32BIT_HACK = 0x7fffffff -} VMX_FLUSH_VPID; - -/** - * EPT flush types. - */ -typedef enum -{ - /** Invalidate one context (specific EPT). */ - VMX_FLUSH_EPT_SINGLE_CONTEXT = 1, - /* Invalidate all contexts (all EPTs) */ - VMX_FLUSH_EPT_ALL_CONTEXTS = 2, - /** Unsupported by VirtualBox. */ - VMX_FLUSH_EPT_NOT_SUPPORTED = 0xbad, - /** Unsupported by CPU. */ - VMX_FLUSH_EPT_NONE = 0xb00, - /** 32bit hackishness. */ - VMX_FLUSH_EPT_32BIT_HACK = 0x7fffffff -} VMX_FLUSH_EPT; -/** @} */ - -/** @name MSR load/store elements - * @{ - */ -#pragma pack(1) -typedef struct -{ - uint32_t u32IndexMSR; - uint32_t u32Reserved; - uint64_t u64Value; -} VMXMSR; -#pragma pack() -/** Pointer to an MSR load/store element. */ -typedef VMXMSR *PVMXMSR; -/** Pointer to a const MSR load/store element. */ -typedef const VMXMSR *PCVMXMSR; - -/** @} */ - - -/** @name VT-x capability qword - * @{ - */ -#pragma pack(1) -typedef union -{ - struct - { - uint32_t disallowed0; - uint32_t allowed1; - } n; - uint64_t u; -} VMX_CAPABILITY; -#pragma pack() -/** @} */ - -/** @name VMX Basic Exit Reasons. - * @{ - */ -/** And-mask for setting reserved bits to zero */ -#define VMX_EFLAGS_RESERVED_0 (~0xffc08028) -/** Or-mask for setting reserved bits to 1 */ -#define VMX_EFLAGS_RESERVED_1 0x00000002 -/** @} */ - -/** @name VMX Basic Exit Reasons. - * @{ - */ -/** -1 Invalid exit code */ -#define VMX_EXIT_INVALID -1 -/** 0 Exception or non-maskable interrupt (NMI). */ -#define VMX_EXIT_EXCEPTION 0 -/** 1 External interrupt. */ -#define VMX_EXIT_EXTERNAL_IRQ 1 -/** 2 Triple fault. */ -#define VMX_EXIT_TRIPLE_FAULT 2 -/** 3 INIT signal. */ -#define VMX_EXIT_INIT_SIGNAL 3 -/** 4 Start-up IPI (SIPI). */ -#define VMX_EXIT_SIPI 4 -/** 5 I/O system-management interrupt (SMI). */ -#define VMX_EXIT_IO_SMI_IRQ 5 -/** 6 Other SMI. */ -#define VMX_EXIT_SMI_IRQ 6 -/** 7 Interrupt window. */ -#define VMX_EXIT_IRQ_WINDOW 7 -/** 9 Task switch. */ -#define VMX_EXIT_TASK_SWITCH 9 -/** 10 Guest software attempted to execute CPUID. */ -#define VMX_EXIT_CPUID 10 -/** 12 Guest software attempted to execute HLT. */ -#define VMX_EXIT_HLT 12 -/** 13 Guest software attempted to execute INVD. */ -#define VMX_EXIT_INVD 13 -/** 14 Guest software attempted to execute INVLPG. */ -#define VMX_EXIT_INVLPG 14 -/** 15 Guest software attempted to execute RDPMC. */ -#define VMX_EXIT_RDPMC 15 -/** 16 Guest software attempted to execute RDTSC. */ -#define VMX_EXIT_RDTSC 16 -/** 17 Guest software attempted to execute RSM in SMM. */ -#define VMX_EXIT_RSM 17 -/** 18 Guest software executed VMCALL. */ -#define VMX_EXIT_VMCALL 18 -/** 19 Guest software executed VMCLEAR. */ -#define VMX_EXIT_VMCLEAR 19 -/** 20 Guest software executed VMLAUNCH. */ -#define VMX_EXIT_VMLAUNCH 20 -/** 21 Guest software executed VMPTRLD. */ -#define VMX_EXIT_VMPTRLD 21 -/** 22 Guest software executed VMPTRST. */ -#define VMX_EXIT_VMPTRST 22 -/** 23 Guest software executed VMREAD. */ -#define VMX_EXIT_VMREAD 23 -/** 24 Guest software executed VMRESUME. */ -#define VMX_EXIT_VMRESUME 24 -/** 25 Guest software executed VMWRITE. */ -#define VMX_EXIT_VMWRITE 25 -/** 26 Guest software executed VMXOFF. */ -#define VMX_EXIT_VMXOFF 26 -/** 27 Guest software executed VMXON. */ -#define VMX_EXIT_VMXON 27 -/** 28 Control-register accesses. */ -#define VMX_EXIT_CRX_MOVE 28 -/** 29 Debug-register accesses. */ -#define VMX_EXIT_DRX_MOVE 29 -/** 30 I/O instruction. */ -#define VMX_EXIT_PORT_IO 30 -/** 31 RDMSR. Guest software attempted to execute RDMSR. */ -#define VMX_EXIT_RDMSR 31 -/** 32 WRMSR. Guest software attempted to execute WRMSR. */ -#define VMX_EXIT_WRMSR 32 -/** 33 VM-entry failure due to invalid guest state. */ -#define VMX_EXIT_ERR_INVALID_GUEST_STATE 33 -/** 34 VM-entry failure due to MSR loading. */ -#define VMX_EXIT_ERR_MSR_LOAD 34 -/** 36 Guest software executed MWAIT. */ -#define VMX_EXIT_MWAIT 36 -/** 37 VM exit due to monitor trap flag. */ -#define VMX_EXIT_MTF 37 -/** 39 Guest software attempted to execute MONITOR. */ -#define VMX_EXIT_MONITOR 39 -/** 40 Guest software attempted to execute PAUSE. */ -#define VMX_EXIT_PAUSE 40 -/** 41 VM-entry failure due to machine-check. */ -#define VMX_EXIT_ERR_MACHINE_CHECK 41 -/** 43 TPR below threshold. Guest software executed MOV to CR8. */ -#define VMX_EXIT_TPR 43 -/** 44 APIC access. Guest software attempted to access memory at a physical address on the APIC-access page. */ -#define VMX_EXIT_APIC_ACCESS 44 -/** 46 Access to GDTR or IDTR. Guest software attempted to execute LGDT, LIDT, SGDT, or SIDT. */ -#define VMX_EXIT_XDTR_ACCESS 46 -/** 47 Access to LDTR or TR. Guest software attempted to execute LLDT, LTR, SLDT, or STR. */ -#define VMX_EXIT_TR_ACCESS 47 -/** 48 EPT violation. An attempt to access memory with a guest-physical address was disallowed by the configuration of the EPT paging structures. */ -#define VMX_EXIT_EPT_VIOLATION 48 -/** 49 EPT misconfiguration. An attempt to access memory with a guest-physical address encountered a misconfigured EPT paging-structure entry. */ -#define VMX_EXIT_EPT_MISCONFIG 49 -/** 50 INVEPT. Guest software attempted to execute INVEPT. */ -#define VMX_EXIT_INVEPT 50 -/** 51 RDTSCP. Guest software attempted to execute RDTSCP. */ -#define VMX_EXIT_RDTSCP 51 -/** 52 VMX-preemption timer expired. The preemption timer counted down to zero. */ -#define VMX_EXIT_PREEMPTION_TIMER 52 -/** 53 INVVPID. Guest software attempted to execute INVVPID. */ -#define VMX_EXIT_INVVPID 53 -/** 54 WBINVD. Guest software attempted to execute WBINVD. */ -#define VMX_EXIT_WBINVD 54 -/** 55 XSETBV. Guest software attempted to execute XSETBV. */ -#define VMX_EXIT_XSETBV 55 -/** @} */ - - -/** @name VM Instruction Errors - * @{ - */ -/** 1 VMCALL executed in VMX root operation. */ -#define VMX_ERROR_VMCALL 1 -/** 2 VMCLEAR with invalid physical address. */ -#define VMX_ERROR_VMCLEAR_INVALID_PHYS_ADDR 2 -/** 3 VMCLEAR with VMXON pointer. */ -#define VMX_ERROR_VMCLEAR_INVALID_VMXON_PTR 3 -/** 4 VMLAUNCH with non-clear VMCS. */ -#define VMX_ERROR_VMLAUCH_NON_CLEAR_VMCS 4 -/** 5 VMRESUME with non-launched VMCS. */ -#define VMX_ERROR_VMRESUME_NON_LAUNCHED_VMCS 5 -/** 6 VMRESUME with a corrupted VMCS (indicates corruption of the current VMCS). */ -#define VMX_ERROR_VMRESUME_CORRUPTED_VMCS 6 -/** 7 VM entry with invalid control field(s). */ -#define VMX_ERROR_VMENTRY_INVALID_CONTROL_FIELDS 7 -/** 8 VM entry with invalid host-state field(s). */ -#define VMX_ERROR_VMENTRY_INVALID_HOST_STATE 8 -/** 9 VMPTRLD with invalid physical address. */ -#define VMX_ERROR_VMPTRLD_INVALID_PHYS_ADDR 9 -/** 10 VMPTRLD with VMXON pointer. */ -#define VMX_ERROR_VMPTRLD_VMXON_PTR 10 -/** 11 VMPTRLD with incorrect VMCS revision identifier. */ -#define VMX_ERROR_VMPTRLD_WRONG_VMCS_REVISION 11 -/** 12 VMREAD/VMWRITE from/to unsupported VMCS component. */ -#define VMX_ERROR_VMREAD_INVALID_COMPONENT 12 -#define VMX_ERROR_VMWRITE_INVALID_COMPONENT VMX_ERROR_VMREAD_INVALID_COMPONENT -/** 13 VMWRITE to read-only VMCS component. */ -#define VMX_ERROR_VMWRITE_READONLY_COMPONENT 13 -/** 15 VMXON executed in VMX root operation. */ -#define VMX_ERROR_VMXON_IN_VMX_ROOT_OP 15 -/** 16 VM entry with invalid executive-VMCS pointer. */ -#define VMX_ERROR_VMENTRY_INVALID_VMCS_EXEC_PTR 16 -/** 17 VM entry with non-launched executive VMCS. */ -#define VMX_ERROR_VMENTRY_NON_LAUNCHED_EXEC_VMCS 17 -/** 18 VM entry with executive-VMCS pointer not VMXON pointer. */ -#define VMX_ERROR_VMENTRY_EXEC_VMCS_PTR 18 -/** 19 VMCALL with non-clear VMCS. */ -#define VMX_ERROR_VMCALL_NON_CLEAR_VMCS 19 -/** 20 VMCALL with invalid VM-exit control fields. */ -#define VMX_ERROR_VMCALL_INVALID_VMEXIT_FIELDS 20 -/** 22 VMCALL with incorrect MSEG revision identifier. */ -#define VMX_ERROR_VMCALL_INVALID_MSEG_REVISION 22 -/** 23 VMXOFF under dual-monitor treatment of SMIs and SMM. */ -#define VMX_ERROR_VMXOFF_DUAL_MONITOR 23 -/** 24 VMCALL with invalid SMM-monitor features. */ -#define VMX_ERROR_VMCALL_INVALID_SMM_MONITOR 24 -/** 25 VM entry with invalid VM-execution control fields in executive VMCS. */ -#define VMX_ERROR_VMENTRY_INVALID_VM_EXEC_CTRL 25 -/** 26 VM entry with events blocked by MOV SS. */ -#define VMX_ERROR_VMENTRY_MOV_SS 26 -/** 26 Invalid operand to INVEPT/INVVPID. */ -#define VMX_ERROR_INVEPTVPID_INVALID_OPERAND 28 - -/** @} */ - - -/** @name VMX MSRs - Basic VMX information. - * @{ - */ -/** VMCS revision identifier used by the processor. */ -#define MSR_IA32_VMX_BASIC_INFO_VMCS_ID(a) (a & 0x7FFFFFFF) -/** Size of the VMCS. */ -#define MSR_IA32_VMX_BASIC_INFO_VMCS_SIZE(a) (((a) >> 32) & 0xFFF) -/** Width of physical address used for the VMCS. - * 0 -> limited to the available amount of physical ram - * 1 -> within the first 4 GB - */ -#define MSR_IA32_VMX_BASIC_INFO_VMCS_PHYS_WIDTH(a) (((a) >> 48) & 1) -/** Whether the processor supports the dual-monitor treatment of system-management interrupts and system-management code. (always 1) */ -#define MSR_IA32_VMX_BASIC_INFO_VMCS_DUAL_MON(a) (((a) >> 49) & 1) -/** Memory type that must be used for the VMCS. */ -#define MSR_IA32_VMX_BASIC_INFO_VMCS_MEM_TYPE(a) (((a) >> 50) & 0xF) -/** @} */ - - -/** @name VMX MSRs - Misc VMX info. - * @{ - */ -/** Relationship between the preemption timer and tsc; count down every time bit x of the tsc changes. */ -#define MSR_IA32_VMX_MISC_PREEMPT_TSC_BIT(a) ((a) & 0x1f) -/** Activity states supported by the implementation. */ -#define MSR_IA32_VMX_MISC_ACTIVITY_STATES(a) (((a) >> 6) & 0x7) -/** Number of CR3 target values supported by the processor. (0-256) */ -#define MSR_IA32_VMX_MISC_CR3_TARGET(a) (((a) >> 16) & 0x1FF) -/** Maximum nr of MSRs in the VMCS. (N+1)*512. */ -#define MSR_IA32_VMX_MISC_MAX_MSR(a) (((((a) >> 25) & 0x7) + 1) * 512) -/** MSEG revision identifier used by the processor. */ -#define MSR_IA32_VMX_MISC_MSEG_ID(a) ((a) >> 32) -/** @} */ - - -/** @name VMX MSRs - VMCS enumeration field info - * @{ - */ -/** Highest field index. */ -#define MSR_IA32_VMX_VMCS_ENUM_HIGHEST_INDEX(a) (((a) >> 1) & 0x1FF) - -/** @} */ - - -/** @name MSR_IA32_VMX_EPT_CAPS; EPT capabilities MSR - * @{ - */ -#define MSR_IA32_VMX_EPT_CAPS_RWX_X_ONLY RT_BIT_64(0) -#define MSR_IA32_VMX_EPT_CAPS_RWX_W_ONLY RT_BIT_64(1) -#define MSR_IA32_VMX_EPT_CAPS_RWX_WX_ONLY RT_BIT_64(2) -#define MSR_IA32_VMX_EPT_CAPS_GAW_21_BITS RT_BIT_64(3) -#define MSR_IA32_VMX_EPT_CAPS_GAW_30_BITS RT_BIT_64(4) -#define MSR_IA32_VMX_EPT_CAPS_GAW_39_BITS RT_BIT_64(5) -#define MSR_IA32_VMX_EPT_CAPS_GAW_48_BITS RT_BIT_64(6) -#define MSR_IA32_VMX_EPT_CAPS_GAW_57_BITS RT_BIT_64(7) -#define MSR_IA32_VMX_EPT_CAPS_EMT_UC RT_BIT_64(8) -#define MSR_IA32_VMX_EPT_CAPS_EMT_WC RT_BIT_64(9) -#define MSR_IA32_VMX_EPT_CAPS_EMT_WT RT_BIT_64(12) -#define MSR_IA32_VMX_EPT_CAPS_EMT_WP RT_BIT_64(13) -#define MSR_IA32_VMX_EPT_CAPS_EMT_WB RT_BIT_64(14) -#define MSR_IA32_VMX_EPT_CAPS_SP_21_BITS RT_BIT_64(16) -#define MSR_IA32_VMX_EPT_CAPS_SP_30_BITS RT_BIT_64(17) -#define MSR_IA32_VMX_EPT_CAPS_SP_39_BITS RT_BIT_64(18) -#define MSR_IA32_VMX_EPT_CAPS_SP_48_BITS RT_BIT_64(19) -#define MSR_IA32_VMX_EPT_CAPS_INVEPT RT_BIT_64(20) -#define MSR_IA32_VMX_EPT_CAPS_INVEPT_CAPS_SINGLE_CONTEXT RT_BIT_64(25) -#define MSR_IA32_VMX_EPT_CAPS_INVEPT_CAPS_ALL_CONTEXTS RT_BIT_64(26) -#define MSR_IA32_VMX_EPT_CAPS_INVVPID RT_BIT_64(32) -#define MSR_IA32_VMX_EPT_CAPS_INVVPID_CAPS_INDIV_ADDR RT_BIT_64(40) -#define MSR_IA32_VMX_EPT_CAPS_INVVPID_CAPS_SINGLE_CONTEXT RT_BIT_64(41) -#define MSR_IA32_VMX_EPT_CAPS_INVVPID_CAPS_ALL_CONTEXTS RT_BIT_64(42) -#define MSR_IA32_VMX_EPT_CAPS_INVVPID_CAPS_SINGLE_CONTEXT_RETAIN_GLOBALS RT_BIT_64(43) - -/** @} */ - -/** @name Extended Page Table Pointer (EPTP) - * @{ - */ -/** Uncachable EPT paging structure memory type. */ -#define VMX_EPT_MEMTYPE_UC 0 -/** Write-back EPT paging structure memory type. */ -#define VMX_EPT_MEMTYPE_WB 6 -/** Shift value to get the EPT page walk length (bits 5-3) */ -#define VMX_EPT_PAGE_WALK_LENGTH_SHIFT 3 -/** Mask value to get the EPT page walk length (bits 5-3) */ -#define VMX_EPT_PAGE_WALK_LENGTH_MASK 7 -/** Default EPT page walk length */ -#define VMX_EPT_PAGE_WALK_LENGTH_DEFAULT 3 -/** @} */ - - -/** @name VMCS field encoding - 16 bits guest fields - * @{ - */ -#define VMX_VMCS16_GUEST_FIELD_VPID 0x0 -#define VMX_VMCS16_GUEST_FIELD_ES 0x800 -#define VMX_VMCS16_GUEST_FIELD_CS 0x802 -#define VMX_VMCS16_GUEST_FIELD_SS 0x804 -#define VMX_VMCS16_GUEST_FIELD_DS 0x806 -#define VMX_VMCS16_GUEST_FIELD_FS 0x808 -#define VMX_VMCS16_GUEST_FIELD_GS 0x80A -#define VMX_VMCS16_GUEST_FIELD_LDTR 0x80C -#define VMX_VMCS16_GUEST_FIELD_TR 0x80E -/** @} */ - -/** @name VMCS field encoding - 16 bits host fields - * @{ - */ -#define VMX_VMCS16_HOST_FIELD_ES 0xC00 -#define VMX_VMCS16_HOST_FIELD_CS 0xC02 -#define VMX_VMCS16_HOST_FIELD_SS 0xC04 -#define VMX_VMCS16_HOST_FIELD_DS 0xC06 -#define VMX_VMCS16_HOST_FIELD_FS 0xC08 -#define VMX_VMCS16_HOST_FIELD_GS 0xC0A -#define VMX_VMCS16_HOST_FIELD_TR 0xC0C -/** @} */ - -/** @name VMCS field encoding - 64 bits host fields - * @{ - */ -#define VMX_VMCS_HOST_FIELD_PAT_FULL 0x2C00 -#define VMX_VMCS_HOST_FIELD_PAT_HIGH 0x2C01 -#define VMX_VMCS_HOST_FIELD_EFER_FULL 0x2C02 -#define VMX_VMCS_HOST_FIELD_EFER_HIGH 0x2C03 -#define VMX_VMCS_HOST_PERF_GLOBAL_CTRL_FULL 0x2C04 /**< MSR IA32_PERF_GLOBAL_CTRL */ -#define VMX_VMCS_HOST_PERF_GLOBAL_CTRL_HIGH 0x2C05 /**< MSR IA32_PERF_GLOBAL_CTRL */ -/** @} */ - - -/** @name VMCS field encoding - 64 Bits control fields - * @{ - */ -#define VMX_VMCS_CTRL_IO_BITMAP_A_FULL 0x2000 -#define VMX_VMCS_CTRL_IO_BITMAP_A_HIGH 0x2001 -#define VMX_VMCS_CTRL_IO_BITMAP_B_FULL 0x2002 -#define VMX_VMCS_CTRL_IO_BITMAP_B_HIGH 0x2003 - -/* Optional */ -#define VMX_VMCS_CTRL_MSR_BITMAP_FULL 0x2004 -#define VMX_VMCS_CTRL_MSR_BITMAP_HIGH 0x2005 - -#define VMX_VMCS_CTRL_VMEXIT_MSR_STORE_FULL 0x2006 -#define VMX_VMCS_CTRL_VMEXIT_MSR_STORE_HIGH 0x2007 -#define VMX_VMCS_CTRL_VMEXIT_MSR_LOAD_FULL 0x2008 -#define VMX_VMCS_CTRL_VMEXIT_MSR_LOAD_HIGH 0x2009 - -#define VMX_VMCS_CTRL_VMENTRY_MSR_LOAD_FULL 0x200A -#define VMX_VMCS_CTRL_VMENTRY_MSR_LOAD_HIGH 0x200B - -#define VMX_VMCS_CTRL_EXEC_VMCS_PTR_FULL 0x200C -#define VMX_VMCS_CTRL_EXEC_VMCS_PTR_HIGH 0x200D - -#define VMX_VMCS_CTRL_TSC_OFFSET_FULL 0x2010 -#define VMX_VMCS_CTRL_TSC_OFFSET_HIGH 0x2011 - -/** Optional (VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_USE_TPR_SHADOW) */ -#define VMX_VMCS_CTRL_VAPIC_PAGEADDR_FULL 0x2012 -#define VMX_VMCS_CTRL_VAPIC_PAGEADDR_HIGH 0x2013 - -/** Optional (VMX_VMCS_CTRL_PROC_EXEC2_VIRT_APIC) */ -#define VMX_VMCS_CTRL_APIC_ACCESSADDR_FULL 0x2014 -#define VMX_VMCS_CTRL_APIC_ACCESSADDR_HIGH 0x2015 - -/** Extended page table pointer. */ -#define VMX_VMCS_CTRL_EPTP_FULL 0x201a -#define VMX_VMCS_CTRL_EPTP_HIGH 0x201b - -/** VM-exit phyiscal address. */ -#define VMX_VMCS_EXIT_PHYS_ADDR_FULL 0x2400 -#define VMX_VMCS_EXIT_PHYS_ADDR_HIGH 0x2401 -/** @} */ - - -/** @name VMCS field encoding - 64 Bits guest fields - * @{ - */ -#define VMX_VMCS_GUEST_LINK_PTR_FULL 0x2800 -#define VMX_VMCS_GUEST_LINK_PTR_HIGH 0x2801 -#define VMX_VMCS_GUEST_DEBUGCTL_FULL 0x2802 /**< MSR IA32_DEBUGCTL */ -#define VMX_VMCS_GUEST_DEBUGCTL_HIGH 0x2803 /**< MSR IA32_DEBUGCTL */ -#define VMX_VMCS_GUEST_PAT_FULL 0x2804 -#define VMX_VMCS_GUEST_PAT_HIGH 0x2805 -#define VMX_VMCS_GUEST_EFER_FULL 0x2806 -#define VMX_VMCS_GUEST_EFER_HIGH 0x2807 -#define VMX_VMCS_GUEST_PERF_GLOBAL_CTRL_FULL 0x2808 /**< MSR IA32_PERF_GLOBAL_CTRL */ -#define VMX_VMCS_GUEST_PERF_GLOBAL_CTRL_HIGH 0x2809 /**< MSR IA32_PERF_GLOBAL_CTRL */ -#define VMX_VMCS_GUEST_PDPTR0_FULL 0x280A -#define VMX_VMCS_GUEST_PDPTR0_HIGH 0x280B -#define VMX_VMCS_GUEST_PDPTR1_FULL 0x280C -#define VMX_VMCS_GUEST_PDPTR1_HIGH 0x280D -#define VMX_VMCS_GUEST_PDPTR2_FULL 0x280E -#define VMX_VMCS_GUEST_PDPTR2_HIGH 0x280F -#define VMX_VMCS_GUEST_PDPTR3_FULL 0x2810 -#define VMX_VMCS_GUEST_PDPTR3_HIGH 0x2811 -/** @} */ - - -/** @name VMCS field encoding - 32 Bits control fields - * @{ - */ -#define VMX_VMCS_CTRL_PIN_EXEC_CONTROLS 0x4000 -#define VMX_VMCS_CTRL_PROC_EXEC_CONTROLS 0x4002 -#define VMX_VMCS_CTRL_EXCEPTION_BITMAP 0x4004 -#define VMX_VMCS_CTRL_PAGEFAULT_ERROR_MASK 0x4006 -#define VMX_VMCS_CTRL_PAGEFAULT_ERROR_MATCH 0x4008 -#define VMX_VMCS_CTRL_CR3_TARGET_COUNT 0x400A -#define VMX_VMCS_CTRL_EXIT_CONTROLS 0x400C -#define VMX_VMCS_CTRL_EXIT_MSR_STORE_COUNT 0x400E -#define VMX_VMCS_CTRL_EXIT_MSR_LOAD_COUNT 0x4010 -#define VMX_VMCS_CTRL_ENTRY_CONTROLS 0x4012 -#define VMX_VMCS_CTRL_ENTRY_MSR_LOAD_COUNT 0x4014 -#define VMX_VMCS_CTRL_ENTRY_IRQ_INFO 0x4016 -#define VMX_VMCS_CTRL_ENTRY_EXCEPTION_ERRCODE 0x4018 -#define VMX_VMCS_CTRL_ENTRY_INSTR_LENGTH 0x401A -/** This field exists only on processors that support the 1-setting of the “use TPR shadow” VM-execution control. */ -#define VMX_VMCS_CTRL_TPR_THRESHOLD 0x401C -/** This field exists only on processors that support the 1-setting of the “activate secondary controls” VM-execution control. */ -#define VMX_VMCS_CTRL_PROC_EXEC_CONTROLS2 0x401E -/** @} */ - - -/** @name VMX_VMCS_CTRL_PIN_EXEC_CONTROLS - * @{ - */ -/** External interrupts cause VM exits if set; otherwise dispatched through the guest's IDT. */ -#define VMX_VMCS_CTRL_PIN_EXEC_CONTROLS_EXT_INT_EXIT RT_BIT(0) -/** Non-maskable interrupts cause VM exits if set; otherwise dispatched through the guest's IDT. */ -#define VMX_VMCS_CTRL_PIN_EXEC_CONTROLS_NMI_EXIT RT_BIT(3) -/** Virtual NMIs. */ -#define VMX_VMCS_CTRL_PIN_EXEC_CONTROLS_VIRTUAL_NMI RT_BIT(5) -/** Activate VMX preemption timer. */ -#define VMX_VMCS_CTRL_PIN_EXEC_CONTROLS_PREEMPT_TIMER RT_BIT(6) -/* All other bits are reserved and must be set according to MSR IA32_VMX_PROCBASED_CTLS. */ -/** @} */ - -/** @name VMX_VMCS_CTRL_PROC_EXEC_CONTROLS - * @{ - */ -/** VM Exit as soon as RFLAGS.IF=1 and no blocking is active. */ -#define VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_IRQ_WINDOW_EXIT RT_BIT(2) -/** Use timestamp counter offset. */ -#define VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_TSC_OFFSET RT_BIT(3) -/** VM Exit when executing the HLT instruction. */ -#define VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_HLT_EXIT RT_BIT(7) -/** VM Exit when executing the INVLPG instruction. */ -#define VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_INVLPG_EXIT RT_BIT(9) -/** VM Exit when executing the MWAIT instruction. */ -#define VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_MWAIT_EXIT RT_BIT(10) -/** VM Exit when executing the RDPMC instruction. */ -#define VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_RDPMC_EXIT RT_BIT(11) -/** VM Exit when executing the RDTSC/RDTSCP instruction. */ -#define VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_RDTSC_EXIT RT_BIT(12) -/** VM Exit when executing the MOV to CR3 instruction. (forced to 1 on the 'first' VT-x capable CPUs; this actually includes the newest Nehalem CPUs) */ -#define VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_CR3_LOAD_EXIT RT_BIT(15) -/** VM Exit when executing the MOV from CR3 instruction. (forced to 1 on the 'first' VT-x capable CPUs; this actually includes the newest Nehalem CPUs) */ -#define VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_CR3_STORE_EXIT RT_BIT(16) -/** VM Exit on CR8 loads. */ -#define VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_CR8_LOAD_EXIT RT_BIT(19) -/** VM Exit on CR8 stores. */ -#define VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_CR8_STORE_EXIT RT_BIT(20) -/** Use TPR shadow. */ -#define VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_USE_TPR_SHADOW RT_BIT(21) -/** VM Exit when virtual nmi blocking is disabled. */ -#define VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_NMI_WINDOW_EXIT RT_BIT(22) -/** VM Exit when executing a MOV DRx instruction. */ -#define VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_MOV_DR_EXIT RT_BIT(23) -/** VM Exit when executing IO instructions. */ -#define VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_UNCOND_IO_EXIT RT_BIT(24) -/** Use IO bitmaps. */ -#define VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_USE_IO_BITMAPS RT_BIT(25) -/** Monitor trap flag. */ -#define VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_MONITOR_TRAP_FLAG RT_BIT(27) -/** Use MSR bitmaps. */ -#define VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_USE_MSR_BITMAPS RT_BIT(28) -/** VM Exit when executing the MONITOR instruction. */ -#define VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_MONITOR_EXIT RT_BIT(29) -/** VM Exit when executing the PAUSE instruction. */ -#define VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_PAUSE_EXIT RT_BIT(30) -/** Determines whether the secondary processor based VM-execution controls are used. */ -#define VMX_VMCS_CTRL_PROC_EXEC_USE_SECONDARY_EXEC_CTRL RT_BIT(31) -/** @} */ - -/** @name VMX_VMCS_CTRL_PROC_EXEC_CONTROLS2 - * @{ - */ -/** Virtualize APIC access. */ -#define VMX_VMCS_CTRL_PROC_EXEC2_VIRT_APIC RT_BIT(0) -/** EPT supported/enabled. */ -#define VMX_VMCS_CTRL_PROC_EXEC2_EPT RT_BIT(1) -/** Descriptor table instructions cause VM-exits. */ -#define VMX_VMCS_CTRL_PROC_EXEC2_DESCRIPTOR_INSTR_EXIT RT_BIT(2) -/** RDTSCP supported/enabled. */ -#define VMX_VMCS_CTRL_PROC_EXEC2_RDTSCP RT_BIT(3) -/** Virtualize x2APIC mode. */ -#define VMX_VMCS_CTRL_PROC_EXEC2_X2APIC RT_BIT(4) -/** VPID supported/enabled. */ -#define VMX_VMCS_CTRL_PROC_EXEC2_VPID RT_BIT(5) -/** VM Exit when executing the WBINVD instruction. */ -#define VMX_VMCS_CTRL_PROC_EXEC2_WBINVD_EXIT RT_BIT(6) -/** Unrestricted guest execution. */ -#define VMX_VMCS_CTRL_PROC_EXEC2_REAL_MODE RT_BIT(7) -/** A specified nr of pause loops cause a VM-exit. */ -#define VMX_VMCS_CTRL_PROC_EXEC2_PAUSE_LOOP_EXIT RT_BIT(10) -/** @} */ - - -/** @name VMX_VMCS_CTRL_ENTRY_CONTROLS - * @{ - */ -/** Load guest debug controls (dr7 & IA32_DEBUGCTL_MSR) (forced to 1 on the 'first' VT-x capable CPUs; this actually includes the newest Nehalem CPUs) */ -#define VMX_VMCS_CTRL_ENTRY_CONTROLS_LOAD_DEBUG RT_BIT(2) -/** 64 bits guest mode. Must be 0 for CPUs that don't support AMD64. */ -#define VMX_VMCS_CTRL_ENTRY_CONTROLS_IA64_MODE RT_BIT(9) -/** In SMM mode after VM-entry. */ -#define VMX_VMCS_CTRL_ENTRY_CONTROLS_ENTRY_SMM RT_BIT(10) -/** Disable dual treatment of SMI and SMM; must be zero for VM-entry outside of SMM. */ -#define VMX_VMCS_CTRL_ENTRY_CONTROLS_DEACTIVATE_DUALMON RT_BIT(11) -/** This control determines whether the guest IA32_PERF_GLOBAL_CTRL MSR is loaded on VM entry. */ -#define VMX_VMCS_CTRL_ENTRY_CONTROLS_LOAD_GUEST_PERF_MSR RT_BIT(13) -/** This control determines whether the guest IA32_PAT MSR is loaded on VM entry. */ -#define VMX_VMCS_CTRL_ENTRY_CONTROLS_LOAD_GUEST_PAT_MSR RT_BIT(14) -/** This control determines whether the guest IA32_EFER MSR is loaded on VM entry. */ -#define VMX_VMCS_CTRL_ENTRY_CONTROLS_LOAD_GUEST_EFER_MSR RT_BIT(15) -/** @} */ - - -/** @name VMX_VMCS_CTRL_EXIT_CONTROLS - * @{ - */ -/** Save guest debug controls (dr7 & IA32_DEBUGCTL_MSR) (forced to 1 on the 'first' VT-x capable CPUs; this actually includes the newest Nehalem CPUs) */ -#define VMX_VMCS_CTRL_EXIT_CONTROLS_SAVE_DEBUG RT_BIT(2) -/** Return to long mode after a VM-exit. */ -#define VMX_VMCS_CTRL_EXIT_CONTROLS_HOST_AMD64 RT_BIT(9) -/** This control determines whether the IA32_PERF_GLOBAL_CTRL MSR is loaded on VM exit. */ -#define VMX_VMCS_CTRL_EXIT_CONTROLS_LOAD_PERF_MSR RT_BIT(12) -/** Acknowledge external interrupts with the irq controller if one caused a VM-exit. */ -#define VMX_VMCS_CTRL_EXIT_CONTROLS_ACK_EXTERNAL_IRQ RT_BIT(15) -/** This control determines whether the guest IA32_PAT MSR is saved on VM exit. */ -#define VMX_VMCS_CTRL_EXIT_CONTROLS_SAVE_GUEST_PAT_MSR RT_BIT(18) -/** This control determines whether the host IA32_PAT MSR is loaded on VM exit. */ -#define VMX_VMCS_CTRL_EXIT_CONTROLS_LOAD_HOST_PAT_MSR RT_BIT(19) -/** This control determines whether the guest IA32_EFER MSR is saved on VM exit. */ -#define VMX_VMCS_CTRL_EXIT_CONTROLS_SAVE_GUEST_EFER_MSR RT_BIT(20) -/** This control determines whether the host IA32_EFER MSR is loaded on VM exit. */ -#define VMX_VMCS_CTRL_EXIT_CONTROLS_LOAD_HOST_EFER_MSR RT_BIT(21) -/** This control determines whether the value of the VMX preemption timer is saved on VM exit. */ -#define VMX_VMCS_CTRL_EXIT_CONTROLS_SAVE_VMX_PREEMPT_TIMER RT_BIT(22) -/** @} */ - -/** @name VMCS field encoding - 32 Bits read-only fields - * @{ - */ -#define VMX_VMCS32_RO_VM_INSTR_ERROR 0x4400 -#define VMX_VMCS32_RO_EXIT_REASON 0x4402 -#define VMX_VMCS32_RO_EXIT_INTERRUPTION_INFO 0x4404 -#define VMX_VMCS32_RO_EXIT_INTERRUPTION_ERRCODE 0x4406 -#define VMX_VMCS32_RO_IDT_INFO 0x4408 -#define VMX_VMCS32_RO_IDT_ERRCODE 0x440A -#define VMX_VMCS32_RO_EXIT_INSTR_LENGTH 0x440C -#define VMX_VMCS32_RO_EXIT_INSTR_INFO 0x440E -/** @} */ - -/** @name VMX_VMCS_RO_EXIT_INTERRUPTION_INFO - * @{ - */ -#define VMX_EXIT_INTERRUPTION_INFO_VECTOR(a) (a & 0xff) -#define VMX_EXIT_INTERRUPTION_INFO_TYPE_SHIFT 8 -#define VMX_EXIT_INTERRUPTION_INFO_TYPE(a) ((a >> VMX_EXIT_INTERRUPTION_INFO_TYPE_SHIFT) & 7) -#define VMX_EXIT_INTERRUPTION_INFO_ERROR_CODE_VALID RT_BIT(11) -#define VMX_EXIT_INTERRUPTION_INFO_ERROR_CODE_IS_VALID(a) (a & VMX_EXIT_INTERRUPTION_INFO_ERROR_CODE_VALID) -#define VMX_EXIT_INTERRUPTION_INFO_NMI_UNBLOCK(a) (a & RT_BIT(12)) -#define VMX_EXIT_INTERRUPTION_INFO_VALID_SHIFT 31 -#define VMX_EXIT_INTERRUPTION_INFO_VALID(a) (a & RT_BIT(31)) -/** Construct an irq event injection value from the exit interruption info value (same except that bit 12 is reserved). */ -#define VMX_VMCS_CTRL_ENTRY_IRQ_INFO_FROM_EXIT_INT_INFO(a) (a & ~RT_BIT(12)) -/** @} */ - -/** @name VMX_VMCS_RO_EXIT_INTERRUPTION_INFO_TYPE - * @{ - */ -#define VMX_EXIT_INTERRUPTION_INFO_TYPE_EXT 0 -#define VMX_EXIT_INTERRUPTION_INFO_TYPE_NMI 2 -#define VMX_EXIT_INTERRUPTION_INFO_TYPE_HWEXCPT 3 -#define VMX_EXIT_INTERRUPTION_INFO_TYPE_SW 4 /**< int xx */ -#define VMX_EXIT_INTERRUPTION_INFO_TYPE_DBEXCPT 5 /**< Why are we getting this one?? */ -#define VMX_EXIT_INTERRUPTION_INFO_TYPE_SWEXCPT 6 -/** @} */ - - -/** @name VMCS field encoding - 32 Bits guest state fields - * @{ - */ -#define VMX_VMCS32_GUEST_ES_LIMIT 0x4800 -#define VMX_VMCS32_GUEST_CS_LIMIT 0x4802 -#define VMX_VMCS32_GUEST_SS_LIMIT 0x4804 -#define VMX_VMCS32_GUEST_DS_LIMIT 0x4806 -#define VMX_VMCS32_GUEST_FS_LIMIT 0x4808 -#define VMX_VMCS32_GUEST_GS_LIMIT 0x480A -#define VMX_VMCS32_GUEST_LDTR_LIMIT 0x480C -#define VMX_VMCS32_GUEST_TR_LIMIT 0x480E -#define VMX_VMCS32_GUEST_GDTR_LIMIT 0x4810 -#define VMX_VMCS32_GUEST_IDTR_LIMIT 0x4812 -#define VMX_VMCS32_GUEST_ES_ACCESS_RIGHTS 0x4814 -#define VMX_VMCS32_GUEST_CS_ACCESS_RIGHTS 0x4816 -#define VMX_VMCS32_GUEST_SS_ACCESS_RIGHTS 0x4818 -#define VMX_VMCS32_GUEST_DS_ACCESS_RIGHTS 0x481A -#define VMX_VMCS32_GUEST_FS_ACCESS_RIGHTS 0x481C -#define VMX_VMCS32_GUEST_GS_ACCESS_RIGHTS 0x481E -#define VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS 0x4820 -#define VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS 0x4822 -#define VMX_VMCS32_GUEST_INTERRUPTIBILITY_STATE 0x4824 -#define VMX_VMCS32_GUEST_ACTIVITY_STATE 0x4826 -#define VMX_VMCS32_GUEST_SYSENTER_CS 0x482A /**< MSR IA32_SYSENTER_CS */ -#define VMX_VMCS32_GUEST_PREEMPTION_TIMER_VALUE 0x482E -/** @} */ - - -/** @name VMX_VMCS_GUEST_ACTIVITY_STATE - * @{ - */ -/** The logical processor is active. */ -#define VMX_CMS_GUEST_ACTIVITY_ACTIVE 0x0 -/** The logical processor is inactive, because executed a HLT instruction. */ -#define VMX_CMS_GUEST_ACTIVITY_HLT 0x1 -/** The logical processor is inactive, because of a triple fault or other serious error. */ -#define VMX_CMS_GUEST_ACTIVITY_SHUTDOWN 0x2 -/** The logical processor is inactive, because it's waiting for a startup-IPI */ -#define VMX_CMS_GUEST_ACTIVITY_SIPI_WAIT 0x3 -/** @} */ - - -/** @name VMX_VMCS_GUEST_INTERRUPTIBILITY_STATE - * @{ - */ -#define VMX_VMCS_GUEST_INTERRUPTIBILITY_STATE_BLOCK_STI RT_BIT(0) -#define VMX_VMCS_GUEST_INTERRUPTIBILITY_STATE_BLOCK_MOVSS RT_BIT(1) -#define VMX_VMCS_GUEST_INTERRUPTIBILITY_STATE_BLOCK_SMI RT_BIT(2) -#define VMX_VMCS_GUEST_INTERRUPTIBILITY_STATE_BLOCK_NMI RT_BIT(3) -/** @} */ - - -/** @name VMCS field encoding - 32 Bits host state fields - * @{ - */ -#define VMX_VMCS32_HOST_SYSENTER_CS 0x4C00 -/** @} */ - -/** @name Natural width control fields - * @{ - */ -#define VMX_VMCS_CTRL_CR0_MASK 0x6000 -#define VMX_VMCS_CTRL_CR4_MASK 0x6002 -#define VMX_VMCS_CTRL_CR0_READ_SHADOW 0x6004 -#define VMX_VMCS_CTRL_CR4_READ_SHADOW 0x6006 -#define VMX_VMCS_CTRL_CR3_TARGET_VAL0 0x6008 -#define VMX_VMCS_CTRL_CR3_TARGET_VAL1 0x600A -#define VMX_VMCS_CTRL_CR3_TARGET_VAL2 0x600C -#define VMX_VMCS_CTRL_CR3_TARGET_VAL31 0x600E -/** @} */ - - -/** @name Natural width read-only data fields - * @{ - */ -#define VMX_VMCS_RO_EXIT_QUALIFICATION 0x6400 -#define VMX_VMCS_RO_IO_RCX 0x6402 -#define VMX_VMCS_RO_IO_RSX 0x6404 -#define VMX_VMCS_RO_IO_RDI 0x6406 -#define VMX_VMCS_RO_IO_RIP 0x6408 -#define VMX_VMCS_EXIT_GUEST_LINEAR_ADDR 0x640A -/** @} */ - - -/** @name VMX_VMCS_RO_EXIT_QUALIFICATION - * @{ - */ -/** 0-2: Debug register number */ -#define VMX_EXIT_QUALIFICATION_DRX_REGISTER(a) (a & 7) -/** 3: Reserved; cleared to 0. */ -#define VMX_EXIT_QUALIFICATION_DRX_RES1(a) ((a >> 3) & 1) -/** 4: Direction of move (0 = write, 1 = read) */ -#define VMX_EXIT_QUALIFICATION_DRX_DIRECTION(a) ((a >> 4) & 1) -/** 5-7: Reserved; cleared to 0. */ -#define VMX_EXIT_QUALIFICATION_DRX_RES2(a) ((a >> 5) & 7) -/** 8-11: General purpose register number. */ -#define VMX_EXIT_QUALIFICATION_DRX_GENREG(a) ((a >> 8) & 0xF) -/** Rest: reserved. */ -/** @} */ - -/** @name VMX_EXIT_QUALIFICATION_DRX_DIRECTION values - * @{ - */ -#define VMX_EXIT_QUALIFICATION_DRX_DIRECTION_WRITE 0 -#define VMX_EXIT_QUALIFICATION_DRX_DIRECTION_READ 1 -/** @} */ - - - -/** @name CRx accesses - * @{ - */ -/** 0-3: Control register number (0 for CLTS & LMSW) */ -#define VMX_EXIT_QUALIFICATION_CRX_REGISTER(a) (a & 0xF) -/** 4-5: Access type. */ -#define VMX_EXIT_QUALIFICATION_CRX_ACCESS(a) ((a >> 4) & 3) -/** 6: LMSW operand type */ -#define VMX_EXIT_QUALIFICATION_CRX_LMSW_OP(a) ((a >> 6) & 1) -/** 7: Reserved; cleared to 0. */ -#define VMX_EXIT_QUALIFICATION_CRX_RES1(a) ((a >> 7) & 1) -/** 8-11: General purpose register number (0 for CLTS & LMSW). */ -#define VMX_EXIT_QUALIFICATION_CRX_GENREG(a) ((a >> 8) & 0xF) -/** 12-15: Reserved; cleared to 0. */ -#define VMX_EXIT_QUALIFICATION_CRX_RES2(a) ((a >> 12) & 0xF) -/** 16-31: LMSW source data (else 0). */ -#define VMX_EXIT_QUALIFICATION_CRX_LMSW_DATA(a) ((a >> 16) & 0xFFFF) -/** Rest: reserved. */ -/** @} */ - -/** @name VMX_EXIT_QUALIFICATION_CRX_ACCESS - * @{ - */ -#define VMX_EXIT_QUALIFICATION_CRX_ACCESS_WRITE 0 -#define VMX_EXIT_QUALIFICATION_CRX_ACCESS_READ 1 -#define VMX_EXIT_QUALIFICATION_CRX_ACCESS_CLTS 2 -#define VMX_EXIT_QUALIFICATION_CRX_ACCESS_LMSW 3 -/** @} */ - -/** @name VMX_EXIT_QUALIFICATION_TASK_SWITCH - * @{ - */ -#define VMX_EXIT_QUALIFICATION_TASK_SWITCH_SELECTOR(a) (a & 0xffff) -#define VMX_EXIT_QUALIFICATION_TASK_SWITCH_TYPE(a) ((a >> 30)& 0x3) -/** Task switch caused by a call instruction. */ -#define VMX_EXIT_QUALIFICATION_TASK_SWITCH_TYPE_CALL 0 -/** Task switch caused by an iret instruction. */ -#define VMX_EXIT_QUALIFICATION_TASK_SWITCH_TYPE_IRET 1 -/** Task switch caused by a jmp instruction. */ -#define VMX_EXIT_QUALIFICATION_TASK_SWITCH_TYPE_JMP 2 -/** Task switch caused by an interrupt gate. */ -#define VMX_EXIT_QUALIFICATION_TASK_SWITCH_TYPE_IDT 3 - -/** @} */ - - -/** @name VMX_EXIT_EPT_VIOLATION - * @{ - */ -/** Set if the violation was caused by a data read. */ -#define VMX_EXIT_QUALIFICATION_EPT_DATA_READ RT_BIT(0) -/** Set if the violation was caused by a data write. */ -#define VMX_EXIT_QUALIFICATION_EPT_DATA_WRITE RT_BIT(1) -/** Set if the violation was caused by an insruction fetch. */ -#define VMX_EXIT_QUALIFICATION_EPT_INSTR_FETCH RT_BIT(2) -/** AND of the present bit of all EPT structures. */ -#define VMX_EXIT_QUALIFICATION_EPT_ENTRY_PRESENT RT_BIT(3) -/** AND of the write bit of all EPT structures. */ -#define VMX_EXIT_QUALIFICATION_EPT_ENTRY_WRITE RT_BIT(4) -/** AND of the execute bit of all EPT structures. */ -#define VMX_EXIT_QUALIFICATION_EPT_ENTRY_EXECUTE RT_BIT(5) -/** Set if the guest linear address field contains the faulting address. */ -#define VMX_EXIT_QUALIFICATION_EPT_GUEST_ADDR_VALID RT_BIT(7) -/** If bit 7 is one: (reserved otherwise) - * 1 - violation due to physical address access. - * 0 - violation caused by page walk or access/dirty bit updates - */ -#define VMX_EXIT_QUALIFICATION_EPT_TRANSLATED_ACCESS RT_BIT(8) -/** @} */ - - -/** @name VMX_EXIT_PORT_IO - * @{ - */ -/** 0-2: IO operation width. */ -#define VMX_EXIT_QUALIFICATION_IO_WIDTH(a) (a & 7) -/** 3: IO operation direction. */ -#define VMX_EXIT_QUALIFICATION_IO_DIRECTION(a) ((a >> 3) & 1) -/** 4: String IO operation. */ -#define VMX_EXIT_QUALIFICATION_IO_STRING(a) ((a >> 4) & 1) -/** 5: Repeated IO operation. */ -#define VMX_EXIT_QUALIFICATION_IO_REP(a) ((a >> 5) & 1) -/** 6: Operand encoding. */ -#define VMX_EXIT_QUALIFICATION_IO_ENCODING(a) ((a >> 6) & 1) -/** 16-31: IO Port (0-0xffff). */ -#define VMX_EXIT_QUALIFICATION_IO_PORT(a) ((a >> 16) & 0xffff) -/* Rest reserved. */ -/** @} */ - -/** @name VMX_EXIT_QUALIFICATION_IO_DIRECTION - * @{ - */ -#define VMX_EXIT_QUALIFICATION_IO_DIRECTION_OUT 0 -#define VMX_EXIT_QUALIFICATION_IO_DIRECTION_IN 1 -/** @} */ - - -/** @name VMX_EXIT_QUALIFICATION_IO_ENCODING - * @{ - */ -#define VMX_EXIT_QUALIFICATION_IO_ENCODING_DX 0 -#define VMX_EXIT_QUALIFICATION_IO_ENCODING_IMM 1 -/** @} */ - -/** @name VMX_EXIT_APIC_ACCESS - * @{ - */ -/** 0-11: If the APIC-access VM exit is due to a linear access, the offset of access within the APIC page. */ -#define VMX_EXIT_QUALIFICATION_APIC_ACCESS_OFFSET(a) (a & 0xfff) -/** 12-15: Access type. */ -#define VMX_EXIT_QUALIFICATION_APIC_ACCESS_TYPE(a) ((a >> 12) & 0xf) -/* Rest reserved. */ -/** @} */ - - -/** @name VMX_EXIT_QUALIFICATION_APIC_ACCESS_TYPE; access types - * @{ - */ -/** Linear read access. */ -#define VMX_APIC_ACCESS_TYPE_LINEAR_READ 0 -/** Linear write access. */ -#define VMX_APIC_ACCESS_TYPE_LINEAR_WRITE 1 -/** Linear instruction fetch access. */ -#define VMX_APIC_ACCESS_TYPE_LINEAR_INSTR_FETCH 2 -/** Linear read/write access during event delivery. */ -#define VMX_APIC_ACCESS_TYPE_LINEAR_EVENT_DELIVERY 3 -/** Physical read/write access during event delivery. */ -#define VMX_APIC_ACCESS_TYPE_PHYSICAL_EVENT_DELIVERY 10 -/** Physical access for an instruction fetch or during instruction execution. */ -#define VMX_APIC_ACCESS_TYPE_PHYSICAL_INSTR 15 -/** @} */ - -/** @} */ - -/** @name VMCS field encoding - Natural width guest state fields - * @{ - */ -#define VMX_VMCS64_GUEST_CR0 0x6800 -#define VMX_VMCS64_GUEST_CR3 0x6802 -#define VMX_VMCS64_GUEST_CR4 0x6804 -#define VMX_VMCS64_GUEST_ES_BASE 0x6806 -#define VMX_VMCS64_GUEST_CS_BASE 0x6808 -#define VMX_VMCS64_GUEST_SS_BASE 0x680A -#define VMX_VMCS64_GUEST_DS_BASE 0x680C -#define VMX_VMCS64_GUEST_FS_BASE 0x680E -#define VMX_VMCS64_GUEST_GS_BASE 0x6810 -#define VMX_VMCS64_GUEST_LDTR_BASE 0x6812 -#define VMX_VMCS64_GUEST_TR_BASE 0x6814 -#define VMX_VMCS64_GUEST_GDTR_BASE 0x6816 -#define VMX_VMCS64_GUEST_IDTR_BASE 0x6818 -#define VMX_VMCS64_GUEST_DR7 0x681A -#define VMX_VMCS64_GUEST_RSP 0x681C -#define VMX_VMCS64_GUEST_RIP 0x681E -#define VMX_VMCS_GUEST_RFLAGS 0x6820 -#define VMX_VMCS_GUEST_DEBUG_EXCEPTIONS 0x6822 -#define VMX_VMCS64_GUEST_SYSENTER_ESP 0x6824 /**< MSR IA32_SYSENTER_ESP */ -#define VMX_VMCS64_GUEST_SYSENTER_EIP 0x6826 /**< MSR IA32_SYSENTER_EIP */ -/** @} */ - - -/** @name VMX_VMCS_GUEST_DEBUG_EXCEPTIONS - * @{ - */ -/** Hardware breakpoint 0 was met. */ -#define VMX_VMCS_GUEST_DEBUG_EXCEPTIONS_B0 RT_BIT(0) -/** Hardware breakpoint 1 was met. */ -#define VMX_VMCS_GUEST_DEBUG_EXCEPTIONS_B1 RT_BIT(1) -/** Hardware breakpoint 2 was met. */ -#define VMX_VMCS_GUEST_DEBUG_EXCEPTIONS_B2 RT_BIT(2) -/** Hardware breakpoint 3 was met. */ -#define VMX_VMCS_GUEST_DEBUG_EXCEPTIONS_B3 RT_BIT(3) -/** At least one data or IO breakpoint was hit. */ -#define VMX_VMCS_GUEST_DEBUG_EXCEPTIONS_BREAKPOINT_ENABLED RT_BIT(12) -/** A debug exception would have been triggered by single-step execution mode. */ -#define VMX_VMCS_GUEST_DEBUG_EXCEPTIONS_BS RT_BIT(14) -/** Bits 4-11, 13 and 15-63 are reserved. */ - -/** @} */ - -/** @name VMCS field encoding - Natural width host state fields - * @{ - */ -#define VMX_VMCS_HOST_CR0 0x6C00 -#define VMX_VMCS_HOST_CR3 0x6C02 -#define VMX_VMCS_HOST_CR4 0x6C04 -#define VMX_VMCS_HOST_FS_BASE 0x6C06 -#define VMX_VMCS_HOST_GS_BASE 0x6C08 -#define VMX_VMCS_HOST_TR_BASE 0x6C0A -#define VMX_VMCS_HOST_GDTR_BASE 0x6C0C -#define VMX_VMCS_HOST_IDTR_BASE 0x6C0E -#define VMX_VMCS_HOST_SYSENTER_ESP 0x6C10 -#define VMX_VMCS_HOST_SYSENTER_EIP 0x6C12 -#define VMX_VMCS_HOST_RSP 0x6C14 -#define VMX_VMCS_HOST_RIP 0x6C16 -/** @} */ - -/** @} */ - - -#if RT_INLINE_ASM_GNU_STYLE -# define __STR(x) #x -# define STR(x) __STR(x) -#endif - - -/** @defgroup grp_vmx_asm vmx assembly helpers - * @ingroup grp_vmx - * @{ - */ - -/** - * Executes VMXON - * - * @returns VBox status code - * @param pVMXOn Physical address of VMXON structure - */ -#if RT_INLINE_ASM_EXTERNAL || HC_ARCH_BITS == 64 || defined(VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0) -DECLASM(int) VMXEnable(RTHCPHYS pVMXOn); -#else -DECLINLINE(int) VMXEnable(RTHCPHYS pVMXOn) -{ - int rc = VINF_SUCCESS; -# if RT_INLINE_ASM_GNU_STYLE - __asm__ __volatile__ ( - "push %3 \n\t" - "push %2 \n\t" - ".byte 0xF3, 0x0F, 0xC7, 0x34, 0x24 # VMXON [esp] \n\t" - "ja 2f \n\t" - "je 1f \n\t" - "movl $"STR(VERR_VMX_INVALID_VMXON_PTR)", %0 \n\t" - "jmp 2f \n\t" - "1: \n\t" - "movl $"STR(VERR_VMX_GENERIC)", %0 \n\t" - "2: \n\t" - "add $8, %%esp \n\t" - :"=rm"(rc) - :"0"(VINF_SUCCESS), - "ir"((uint32_t)pVMXOn), /* don't allow direct memory reference here, */ - "ir"((uint32_t)(pVMXOn >> 32)) /* this would not work with -fomit-frame-pointer */ - :"memory" - ); -# else - __asm - { - push dword ptr [pVMXOn+4] - push dword ptr [pVMXOn] - _emit 0xF3 - _emit 0x0F - _emit 0xC7 - _emit 0x34 - _emit 0x24 /* VMXON [esp] */ - jnc vmxon_good - mov dword ptr [rc], VERR_VMX_INVALID_VMXON_PTR - jmp the_end - -vmxon_good: - jnz the_end - mov dword ptr [rc], VERR_VMX_GENERIC -the_end: - add esp, 8 - } -# endif - return rc; -} -#endif - - -/** - * Executes VMXOFF - */ -#if RT_INLINE_ASM_EXTERNAL || HC_ARCH_BITS == 64 || defined(VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0) -DECLASM(void) VMXDisable(void); -#else -DECLINLINE(void) VMXDisable(void) -{ -# if RT_INLINE_ASM_GNU_STYLE - __asm__ __volatile__ ( - ".byte 0x0F, 0x01, 0xC4 # VMXOFF \n\t" - ); -# else - __asm - { - _emit 0x0F - _emit 0x01 - _emit 0xC4 /* VMXOFF */ - } -# endif -} -#endif - - -/** - * Executes VMCLEAR - * - * @returns VBox status code - * @param pVMCS Physical address of VM control structure - */ -#if RT_INLINE_ASM_EXTERNAL || HC_ARCH_BITS == 64 || defined(VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0) -DECLASM(int) VMXClearVMCS(RTHCPHYS pVMCS); -#else -DECLINLINE(int) VMXClearVMCS(RTHCPHYS pVMCS) -{ - int rc = VINF_SUCCESS; -# if RT_INLINE_ASM_GNU_STYLE - __asm__ __volatile__ ( - "push %3 \n\t" - "push %2 \n\t" - ".byte 0x66, 0x0F, 0xC7, 0x34, 0x24 # VMCLEAR [esp] \n\t" - "jnc 1f \n\t" - "movl $"STR(VERR_VMX_INVALID_VMCS_PTR)", %0 \n\t" - "1: \n\t" - "add $8, %%esp \n\t" - :"=rm"(rc) - :"0"(VINF_SUCCESS), - "ir"((uint32_t)pVMCS), /* don't allow direct memory reference here, */ - "ir"((uint32_t)(pVMCS >> 32)) /* this would not work with -fomit-frame-pointer */ - :"memory" - ); -# else - __asm - { - push dword ptr [pVMCS+4] - push dword ptr [pVMCS] - _emit 0x66 - _emit 0x0F - _emit 0xC7 - _emit 0x34 - _emit 0x24 /* VMCLEAR [esp] */ - jnc success - mov dword ptr [rc], VERR_VMX_INVALID_VMCS_PTR -success: - add esp, 8 - } -# endif - return rc; -} -#endif - - -/** - * Executes VMPTRLD - * - * @returns VBox status code - * @param pVMCS Physical address of VMCS structure - */ -#if RT_INLINE_ASM_EXTERNAL || HC_ARCH_BITS == 64 || defined(VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0) -DECLASM(int) VMXActivateVMCS(RTHCPHYS pVMCS); -#else -DECLINLINE(int) VMXActivateVMCS(RTHCPHYS pVMCS) -{ - int rc = VINF_SUCCESS; -# if RT_INLINE_ASM_GNU_STYLE - __asm__ __volatile__ ( - "push %3 \n\t" - "push %2 \n\t" - ".byte 0x0F, 0xC7, 0x34, 0x24 # VMPTRLD [esp] \n\t" - "jnc 1f \n\t" - "movl $"STR(VERR_VMX_INVALID_VMCS_PTR)", %0 \n\t" - "1: \n\t" - "add $8, %%esp \n\t" - :"=rm"(rc) - :"0"(VINF_SUCCESS), - "ir"((uint32_t)pVMCS), /* don't allow direct memory reference here, */ - "ir"((uint32_t)(pVMCS >> 32)) /* this will not work with -fomit-frame-pointer */ - ); -# else - __asm - { - push dword ptr [pVMCS+4] - push dword ptr [pVMCS] - _emit 0x0F - _emit 0xC7 - _emit 0x34 - _emit 0x24 /* VMPTRLD [esp] */ - jnc success - mov dword ptr [rc], VERR_VMX_INVALID_VMCS_PTR - -success: - add esp, 8 - } -# endif - return rc; -} -#endif - -/** - * Executes VMPTRST - * - * @returns VBox status code - * @param pVMCS Address that will receive the current pointer - */ -DECLASM(int) VMXGetActivateVMCS(RTHCPHYS *pVMCS); - -/** - * Executes VMWRITE - * - * @returns VBox status code - * @param idxField VMCS index - * @param u32Val 32 bits value - */ -#if RT_INLINE_ASM_EXTERNAL || HC_ARCH_BITS == 64 || defined(VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0) -DECLASM(int) VMXWriteVMCS32(uint32_t idxField, uint32_t u32Val); -#else -DECLINLINE(int) VMXWriteVMCS32(uint32_t idxField, uint32_t u32Val) -{ - int rc = VINF_SUCCESS; -# if RT_INLINE_ASM_GNU_STYLE - __asm__ __volatile__ ( - ".byte 0x0F, 0x79, 0xC2 # VMWRITE eax, edx \n\t" - "ja 2f \n\t" - "je 1f \n\t" - "movl $"STR(VERR_VMX_INVALID_VMCS_PTR)", %0 \n\t" - "jmp 2f \n\t" - "1: \n\t" - "movl $"STR(VERR_VMX_INVALID_VMCS_FIELD)", %0 \n\t" - "2: \n\t" - :"=rm"(rc) - :"0"(VINF_SUCCESS), - "a"(idxField), - "d"(u32Val) - ); -# else - __asm - { - push dword ptr [u32Val] - mov eax, [idxField] - _emit 0x0F - _emit 0x79 - _emit 0x04 - _emit 0x24 /* VMWRITE eax, [esp] */ - jnc valid_vmcs - mov dword ptr [rc], VERR_VMX_INVALID_VMCS_PTR - jmp the_end - -valid_vmcs: - jnz the_end - mov dword ptr [rc], VERR_VMX_INVALID_VMCS_FIELD -the_end: - add esp, 4 - } -# endif - return rc; -} -#endif - -/** - * Executes VMWRITE - * - * @returns VBox status code - * @param idxField VMCS index - * @param u64Val 16, 32 or 64 bits value - */ -#if HC_ARCH_BITS == 64 || defined(VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0) -DECLASM(int) VMXWriteVMCS64(uint32_t idxField, uint64_t u64Val); -#else -VMMR0DECL(int) VMXWriteVMCS64Ex(PVMCPU pVCpu, uint32_t idxField, uint64_t u64Val); - -#define VMXWriteVMCS64(idxField, u64Val) VMXWriteVMCS64Ex(pVCpu, idxField, u64Val) -#endif - -#if HC_ARCH_BITS == 64 -#define VMXWriteVMCS VMXWriteVMCS64 -#else -#define VMXWriteVMCS VMXWriteVMCS32 -#endif /* HC_ARCH_BITS == 64 */ - - -/** - * Invalidate a page using invept - * @returns VBox status code - * @param enmFlush Type of flush - * @param pDescriptor Descriptor - */ -DECLASM(int) VMXR0InvEPT(VMX_FLUSH_EPT enmFlush, uint64_t *pDescriptor); - -/** - * Invalidate a page using invvpid - * @returns VBox status code - * @param enmFlush Type of flush - * @param pDescriptor Descriptor - */ -DECLASM(int) VMXR0InvVPID(VMX_FLUSH_VPID enmFlush, uint64_t *pDescriptor); - -/** - * Executes VMREAD - * - * @returns VBox status code - * @param idxField VMCS index - * @param pData Ptr to store VM field value - */ -#if RT_INLINE_ASM_EXTERNAL || HC_ARCH_BITS == 64 || defined(VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0) -DECLASM(int) VMXReadVMCS32(uint32_t idxField, uint32_t *pData); -#else -DECLINLINE(int) VMXReadVMCS32(uint32_t idxField, uint32_t *pData) -{ - int rc = VINF_SUCCESS; -# if RT_INLINE_ASM_GNU_STYLE - __asm__ __volatile__ ( - "movl $"STR(VINF_SUCCESS)", %0 \n\t" - ".byte 0x0F, 0x78, 0xc2 # VMREAD eax, edx \n\t" - "ja 2f \n\t" - "je 1f \n\t" - "movl $"STR(VERR_VMX_INVALID_VMCS_PTR)", %0 \n\t" - "jmp 2f \n\t" - "1: \n\t" - "movl $"STR(VERR_VMX_INVALID_VMCS_FIELD)", %0 \n\t" - "2: \n\t" - :"=&r"(rc), - "=d"(*pData) - :"a"(idxField), - "d"(0) - ); -# else - __asm - { - sub esp, 4 - mov dword ptr [esp], 0 - mov eax, [idxField] - _emit 0x0F - _emit 0x78 - _emit 0x04 - _emit 0x24 /* VMREAD eax, [esp] */ - mov edx, pData - pop dword ptr [edx] - jnc valid_vmcs - mov dword ptr [rc], VERR_VMX_INVALID_VMCS_PTR - jmp the_end - -valid_vmcs: - jnz the_end - mov dword ptr [rc], VERR_VMX_INVALID_VMCS_FIELD -the_end: - } -# endif - return rc; -} -#endif - -/** - * Executes VMREAD - * - * @returns VBox status code - * @param idxField VMCS index - * @param pData Ptr to store VM field value - */ -#if HC_ARCH_BITS == 64 || defined(VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0) -DECLASM(int) VMXReadVMCS64(uint32_t idxField, uint64_t *pData); -#else -DECLINLINE(int) VMXReadVMCS64(uint32_t idxField, uint64_t *pData) -{ - int rc; - - uint32_t val_hi, val; - rc = VMXReadVMCS32(idxField, &val); - rc |= VMXReadVMCS32(idxField + 1, &val_hi); - AssertRC(rc); - *pData = RT_MAKE_U64(val, val_hi); - return rc; -} -#endif - -#if HC_ARCH_BITS == 64 -# define VMXReadVMCS VMXReadVMCS64 -#else -# define VMXReadVMCS VMXReadVMCS32 -#endif /* HC_ARCH_BITS == 64 */ - -/** - * Gets the last instruction error value from the current VMCS - * - * @returns error value - */ -DECLINLINE(uint32_t) VMXGetLastError(void) -{ -#if HC_ARCH_BITS == 64 - uint64_t uLastError = 0; - int rc = VMXReadVMCS(VMX_VMCS32_RO_VM_INSTR_ERROR, &uLastError); - AssertRC(rc); - return (uint32_t)uLastError; - -#else /* 32-bit host: */ - uint32_t uLastError = 0; - int rc = VMXReadVMCS32(VMX_VMCS32_RO_VM_INSTR_ERROR, &uLastError); - AssertRC(rc); - return uLastError; -#endif -} - -#ifdef IN_RING0 -VMMR0DECL(int) VMXR0InvalidatePage(PVM pVM, PVMCPU pVCpu, RTGCPTR GCVirt); -VMMR0DECL(int) VMXR0InvalidatePhysPage(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys); -#endif /* IN_RING0 */ - -/** @} */ - -#endif - diff --git a/include/VBox/vmm/hwaccm.h b/include/VBox/vmm/hwaccm.h deleted file mode 100644 index 98a7d02e..00000000 --- a/include/VBox/vmm/hwaccm.h +++ /dev/null @@ -1,154 +0,0 @@ -/** @file - * HWACCM - Intel/AMD VM Hardware Support Manager (VMM) - */ - -/* - * Copyright (C) 2006-2010 Oracle Corporation - * - * This file is part of VirtualBox Open Source Edition (OSE), as - * available from http://www.virtualbox.org. This file is free software; - * you can redistribute it and/or modify it under the terms of the GNU - * General Public License (GPL) as published by the Free Software - * Foundation, in version 2 as it comes in the "COPYING" file of the - * VirtualBox OSE distribution. VirtualBox OSE is distributed in the - * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. - * - * The contents of this file may alternatively be used under the terms - * of the Common Development and Distribution License Version 1.0 - * (CDDL) only, as it comes in the "COPYING.CDDL" file of the - * VirtualBox OSE distribution, in which case the provisions of the - * CDDL are applicable instead of those of the GPL. - * - * You may elect to license modified versions of this file under the - * terms and conditions of either the GPL or the CDDL or both. - */ - -#ifndef ___VBox_vmm_hwaccm_h -#define ___VBox_vmm_hwaccm_h - -#include <VBox/vmm/pgm.h> -#include <VBox/vmm/cpum.h> -#include <iprt/mp.h> - - -/** @defgroup grp_hwaccm The VM Hardware Manager API - * @{ - */ - -RT_C_DECLS_BEGIN - -/** - * Query HWACCM state (enabled/disabled) - * - * @returns 0 - disabled, 1 - enabled - * @param pVM The VM to operate on. - */ -#define HWACCMIsEnabled(pVM) ((pVM)->fHWACCMEnabled) - - /** - * Check if the current CPU state is valid for emulating IO blocks in the recompiler - * - * @returns boolean - * @param pCtx CPU context - */ -#define HWACCMCanEmulateIoBlock(pVCpu) (!CPUMIsGuestInPagedProtectedMode(pVCpu)) -#define HWACCMCanEmulateIoBlockEx(pCtx) (!CPUMIsGuestInPagedProtectedModeEx(pCtx)) - -VMMDECL(int) HWACCMInvalidatePage(PVMCPU pVCpu, RTGCPTR GCVirt); -VMMDECL(bool) HWACCMHasPendingIrq(PVM pVM); - -#ifndef IN_RC -VMMDECL(int) HWACCMFlushTLB(PVMCPU pVCpu); -VMMDECL(int) HWACCMFlushTLBOnAllVCpus(PVM pVM); -VMMDECL(int) HWACCMInvalidatePageOnAllVCpus(PVM pVM, RTGCPTR GCVirt); -VMMDECL(int) HWACCMInvalidatePhysPage(PVM pVM, RTGCPHYS GCPhys); -VMMDECL(bool) HWACCMIsNestedPagingActive(PVM pVM); -VMMDECL(PGMMODE) HWACCMGetShwPagingMode(PVM pVM); -#else -/* Nop in GC */ -# define HWACCMFlushTLB(pVCpu) do { } while (0) -# define HWACCMIsNestedPagingActive(pVM) false -# define HWACCMFlushTLBOnAllVCpus(pVM) do { } while (0) -#endif - -#ifdef IN_RING0 -/** @defgroup grp_hwaccm_r0 The VM Hardware Manager API - * @ingroup grp_hwaccm - * @{ - */ -VMMR0DECL(int) HWACCMR0Init(void); -VMMR0DECL(int) HWACCMR0Term(void); -VMMR0DECL(int) HWACCMR0InitVM(PVM pVM); -VMMR0DECL(int) HWACCMR0TermVM(PVM pVM); -VMMR0DECL(int) HWACCMR0EnableAllCpus(PVM pVM); -VMMR0DECL(int) HWACCMR0EnterSwitcher(PVM pVM, bool *pfVTxDisabled); -VMMR0DECL(int) HWACCMR0LeaveSwitcher(PVM pVM, bool fVTxDisabled); - -VMMR0DECL(void) HWACCMR0SavePendingIOPortWrite(PVMCPU pVCpu, RTGCPTR GCPtrRip, RTGCPTR GCPtrRipNext, unsigned uPort, unsigned uAndVal, unsigned cbSize); -VMMR0DECL(void) HWACCMR0SavePendingIOPortRead(PVMCPU pVCpu, RTGCPTR GCPtrRip, RTGCPTR GCPtrRipNext, unsigned uPort, unsigned uAndVal, unsigned cbSize); - -/** @} */ -#endif /* IN_RING0 */ - - -#ifdef IN_RING3 -/** @defgroup grp_hwaccm_r3 The VM Hardware Manager API - * @ingroup grp_hwaccm - * @{ - */ -VMMR3DECL(bool) HWACCMR3IsEventPending(PVMCPU pVCpu); -VMMR3DECL(int) HWACCMR3Init(PVM pVM); -VMMR3_INT_DECL(int) HWACCMR3InitCompleted(PVM pVM, VMINITCOMPLETED enmWhat); -VMMR3DECL(void) HWACCMR3Relocate(PVM pVM); -VMMR3DECL(int) HWACCMR3Term(PVM pVM); -VMMR3DECL(void) HWACCMR3Reset(PVM pVM); -VMMR3DECL(void) HWACCMR3ResetCpu(PVMCPU pVCpu); -VMMR3DECL(void) HWACCMR3CheckError(PVM pVM, int iStatusCode); -VMMR3DECL(bool) HWACCMR3CanExecuteGuest(PVM pVM, PCPUMCTX pCtx); -VMMR3DECL(void) HWACCMR3NotifyScheduled(PVMCPU pVCpu); -VMMR3DECL(void) HWACCMR3NotifyEmulated(PVMCPU pVCpu); -VMMR3DECL(bool) HWACCMR3IsActive(PVMCPU pVCpu); -VMMR3DECL(bool) HWACCMR3IsNestedPagingActive(PVM pVM); -VMMR3DECL(bool) HWACCMR3IsAllowed(PVM pVM); -VMMR3DECL(void) HWACCMR3PagingModeChanged(PVM pVM, PVMCPU pVCpu, PGMMODE enmShadowMode, PGMMODE enmGuestMode); -VMMR3DECL(bool) HWACCMR3IsVPIDActive(PVM pVM); -VMMR3DECL(int) HWACCMR3InjectNMI(PVM pVM); -VMMR3DECL(int) HWACCMR3EmulateIoBlock(PVM pVM, PCPUMCTX pCtx); -VMMR3DECL(VBOXSTRICTRC) HWACCMR3RestartPendingIOInstr(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx); -VMMR3DECL(int) HWACMMR3EnablePatching(PVM pVM, RTGCPTR pPatchMem, unsigned cbPatchMem); -VMMR3DECL(int) HWACMMR3DisablePatching(PVM pVM, RTGCPTR pPatchMem, unsigned cbPatchMem); -VMMR3DECL(int) HWACCMR3PatchTprInstr(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx); -VMMR3DECL(bool) HWACCMR3IsRescheduleRequired(PVM pVM, PCPUMCTX pCtx); -VMMR3DECL(bool) HWACCMR3IsVmxPreemptionTimerUsed(PVM pVM); - -/** @} */ -#endif /* IN_RING3 */ - -#ifdef IN_RING0 -/** @addtogroup grp_hwaccm_r0 - * @{ - */ -VMMR0DECL(int) HWACCMR0SetupVM(PVM pVM); -VMMR0DECL(int) HWACCMR0RunGuestCode(PVM pVM, PVMCPU pVCpu); -VMMR0DECL(int) HWACCMR0Enter(PVM pVM, PVMCPU pVCpu); -VMMR0DECL(int) HWACCMR0Leave(PVM pVM, PVMCPU pVCpu); -VMMR0DECL(int) HWACCMR0InvalidatePage(PVM pVM, PVMCPU pVCpu); -VMMR0DECL(int) HWACCMR0FlushTLB(PVM pVM); -VMMR0DECL(bool) HWACCMR0SuspendPending(void); - -# if HC_ARCH_BITS == 32 && defined(VBOX_WITH_64_BITS_GUESTS) -VMMR0DECL(int) HWACCMR0SaveFPUState(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx); -VMMR0DECL(int) HWACCMR0SaveDebugState(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx); -VMMR0DECL(int) HWACCMR0TestSwitcher3264(PVM pVM); -# endif - -/** @} */ -#endif /* IN_RING0 */ - - -/** @} */ -RT_C_DECLS_END - - -#endif - diff --git a/include/VBox/vmm/iem.h b/include/VBox/vmm/iem.h index 617a05a6..32168660 100644 --- a/include/VBox/vmm/iem.h +++ b/include/VBox/vmm/iem.h @@ -3,7 +3,7 @@ */ /* - * Copyright (C) 2011 Oracle Corporation + * Copyright (C) 2011-2012 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -28,6 +28,7 @@ #include <VBox/types.h> #include <VBox/vmm/trpm.h> +#include <iprt/assert.h> RT_C_DECLS_BEGIN @@ -37,6 +38,17 @@ RT_C_DECLS_BEGIN */ +/** + * Operand or addressing mode. + */ +typedef enum IEMMODE +{ + IEMMODE_16BIT = 0, + IEMMODE_32BIT, + IEMMODE_64BIT +} IEMMODE; +AssertCompileSize(IEMMODE, 4); + VMMDECL(VBOXSTRICTRC) IEMExecOne(PVMCPU pVCpu); VMMDECL(VBOXSTRICTRC) IEMExecOneEx(PVMCPU pVCpu, PCPUMCTXCORE pCtxCore, uint32_t *pcbWritten); @@ -53,7 +65,10 @@ VMM_INT_DECL(int) IEMBreakpointClear(PVM pVM, RTGCPTR GCPtrBp); /** @name Given Instruction Interpreters * @{ */ - +VMM_INT_DECL(VBOXSTRICTRC) IEMExecStringIoWrite(PVMCPU pVCpu, uint8_t cbValue, IEMMODE enmAddrMode, + bool fRepPrefix, uint8_t cbInstr, uint8_t iEffSeg); +VMM_INT_DECL(VBOXSTRICTRC) IEMExecStringIoRead(PVMCPU pVCpu, uint8_t cbValue, IEMMODE enmAddrMode, + bool fRepPrefix, uint8_t cbInstr); /** @} */ #if defined(IEM_VERIFICATION_MODE) && defined(IN_RING3) diff --git a/include/VBox/vmm/iom.h b/include/VBox/vmm/iom.h index a7e552c9..a69ac4cd 100644 --- a/include/VBox/vmm/iom.h +++ b/include/VBox/vmm/iom.h @@ -3,7 +3,7 @@ */ /* - * Copyright (C) 2006-2010 Oracle Corporation + * Copyright (C) 2006-2013 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -57,13 +57,11 @@ RT_C_DECLS_BEGIN * more than once! * * @remark To avoid making assumptions about the layout of the - * VINF_EM_FIRST...VINF_EM_LAST range we're checking - * explicitly for each for exach the exceptions. - * However, for efficieny we ASSUME that the - * VINF_EM_LAST is smaller than most of the relevant - * status codes. We also ASSUME that the - * VINF_EM_RESCHEDULE_REM status code is the most - * frequent status code we'll enounter in this range. + * VINF_EM_FIRST...VINF_EM_LAST range we're checking explicitly for + * each exact exception. However, for efficiency we ASSUME that the + * VINF_EM_LAST is smaller than most of the relevant status codes. We + * also ASSUME that the VINF_EM_RESCHEDULE_REM status code is the + * most frequent status code we'll enounter in this range. * * @todo Will have to add VINF_EM_DBG_HYPER_BREAKPOINT if the * I/O port and MMIO breakpoints should trigger before @@ -75,7 +73,7 @@ RT_C_DECLS_BEGIN && (rc) != VINF_EM_RESCHEDULE_REM \ && (rc) >= VINF_EM_FIRST \ && (rc) != VINF_EM_RESCHEDULE_RAW \ - && (rc) != VINF_EM_RESCHEDULE_HWACC \ + && (rc) != VINF_EM_RESCHEDULE_HM \ ) \ ) @@ -116,6 +114,16 @@ RT_C_DECLS_BEGIN * simplifications of devices where reads doesn't change the device * state in any way. */ #define IOMMMIO_FLAGS_WRITE_DWORD_QWORD_READ_MISSING UINT32_C(0x00000040) +/** All write accesses are DWORD (32-bit) sized and aligned, attempts at other + * accesses are ignored. + * @remarks E1000, APIC */ +#define IOMMMIO_FLAGS_WRITE_ONLY_DWORD UINT32_C(0x00000050) +/** All write accesses are DWORD (32-bit) or QWORD (64-bit) sized and aligned, + * attempts at other accesses are ignored. + * @remarks Seemingly required by AHCI (although I doubt it's _really_ + * required as EM/REM doesn't do the right thing in ring-3 anyway, + * esp. not in raw-mode). */ +#define IOMMMIO_FLAGS_WRITE_ONLY_DWORD_QWORD UINT32_C(0x00000060) /** The read access mode mask. */ #define IOMMMIO_FLAGS_WRITE_MODE UINT32_C(0x00000070) @@ -132,6 +140,14 @@ RT_C_DECLS_BEGIN #define IOMMMIO_FLAGS_VALID_MASK UINT32_C(0x00000373) /** @} */ +/** + * Checks whether the write mode allows aligned QWORD accesses to be passed + * thru to the device handler. + * @param a_fFlags The MMIO handler flags. + * @remarks The current implementation makes ASSUMPTIONS about the mode values! + */ +#define IOMMMIO_DOES_WRITE_MODE_ALLOW_QWORD(a_fFlags) RT_BOOL((a_fFlags) & UINT32_C(0x00000020)) + /** * Port I/O Handler for IN operations. @@ -145,6 +161,7 @@ RT_C_DECLS_BEGIN * @param pu32 Where to store the result. This is always a 32-bit * variable regardless of what @a cb might say. * @param cb Number of bytes read. + * @remarks Caller enters the device critical section. */ typedef DECLCALLBACK(int) FNIOMIOPORTIN(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb); /** Pointer to a FNIOMIOPORTIN(). */ @@ -162,6 +179,7 @@ typedef FNIOMIOPORTIN *PFNIOMIOPORTIN; * @param pGCPtrDst Pointer to the destination buffer (GC, incremented appropriately). * @param pcTransfers Pointer to the number of transfer units to read, on return remaining transfer units. * @param cb Size of the transfer unit (1, 2 or 4 bytes). + * @remarks Caller enters the device critical section. */ typedef DECLCALLBACK(int) FNIOMIOPORTINSTRING(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, RTGCPTR *pGCPtrDst, PRTGCUINTREG pcTransfers, unsigned cb); /** Pointer to a FNIOMIOPORTINSTRING(). */ @@ -177,6 +195,7 @@ typedef FNIOMIOPORTINSTRING *PFNIOMIOPORTINSTRING; * @param uPort Port number used for the OUT operation. * @param u32 The value to output. * @param cb The value size in bytes. + * @remarks Caller enters the device critical section. */ typedef DECLCALLBACK(int) FNIOMIOPORTOUT(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb); /** Pointer to a FNIOMIOPORTOUT(). */ @@ -193,6 +212,7 @@ typedef FNIOMIOPORTOUT *PFNIOMIOPORTOUT; * @param pGCPtrSrc Pointer to the source buffer (GC, incremented appropriately). * @param pcTransfers Pointer to the number of transfer units to write, on return remaining transfer units. * @param cb Size of the transfer unit (1, 2 or 4 bytes). + * @remarks Caller enters the device critical section. */ typedef DECLCALLBACK(int) FNIOMIOPORTOUTSTRING(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, RTGCPTR *pGCPtrSrc, PRTGCUINTREG pcTransfers, unsigned cb); /** Pointer to a FNIOMIOPORTOUTSTRING(). */ @@ -209,6 +229,7 @@ typedef FNIOMIOPORTOUTSTRING *PFNIOMIOPORTOUTSTRING; * @param GCPhysAddr Physical address (in GC) where the read starts. * @param pv Where to store the result. * @param cb Number of bytes read. + * @remarks Caller enters the device critical section. */ typedef DECLCALLBACK(int) FNIOMMMIOREAD(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb); /** Pointer to a FNIOMMMIOREAD(). */ @@ -224,6 +245,7 @@ typedef FNIOMMMIOREAD *PFNIOMMMIOREAD; * @param GCPhysAddr Physical address (in GC) where the read starts. * @param pv Where to fetch the result. * @param cb Number of bytes to write. + * @remarks Caller enters the device critical section. */ typedef DECLCALLBACK(int) FNIOMMMIOWRITE(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void const *pv, unsigned cb); /** Pointer to a FNIOMMMIOWRITE(). */ @@ -240,36 +262,37 @@ typedef FNIOMMMIOWRITE *PFNIOMMMIOWRITE; * @param u32Item Byte/Word/Dword data to fill. * @param cbItem Size of data in u32Item parameter, restricted to 1/2/4 bytes. * @param cItems Number of iterations. + * @remarks Caller enters the device critical section. */ typedef DECLCALLBACK(int) FNIOMMMIOFILL(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, uint32_t u32Item, unsigned cbItem, unsigned cItems); /** Pointer to a FNIOMMMIOFILL(). */ typedef FNIOMMMIOFILL *PFNIOMMMIOFILL; -VMMDECL(VBOXSTRICTRC) IOMIOPortRead(PVM pVM, RTIOPORT Port, uint32_t *pu32Value, size_t cbValue); -VMMDECL(VBOXSTRICTRC) IOMIOPortWrite(PVM pVM, RTIOPORT Port, uint32_t u32Value, size_t cbValue); -VMMDECL(VBOXSTRICTRC) IOMInterpretOUT(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu); -VMMDECL(VBOXSTRICTRC) IOMInterpretIN(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu); -VMMDECL(VBOXSTRICTRC) IOMIOPortReadString(PVM pVM, RTIOPORT Port, PRTGCPTR pGCPtrDst, PRTGCUINTREG pcTransfers, unsigned cb); -VMMDECL(VBOXSTRICTRC) IOMIOPortWriteString(PVM pVM, RTIOPORT Port, PRTGCPTR pGCPtrSrc, PRTGCUINTREG pcTransfers, unsigned cb); -VMMDECL(VBOXSTRICTRC) IOMInterpretINS(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu); -VMMDECL(VBOXSTRICTRC) IOMInterpretINSEx(PVM pVM, PCPUMCTXCORE pRegFrame, uint32_t uPort, uint32_t uPrefix, DISCPUMODE enmAddrMode, uint32_t cbTransfer); -VMMDECL(VBOXSTRICTRC) IOMInterpretOUTS(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu); -VMMDECL(VBOXSTRICTRC) IOMInterpretOUTSEx(PVM pVM, PCPUMCTXCORE pRegFrame, uint32_t uPort, uint32_t uPrefix, DISCPUMODE enmAddrMode, uint32_t cbTransfer); -VMMDECL(VBOXSTRICTRC) IOMMMIORead(PVM pVM, RTGCPHYS GCPhys, uint32_t *pu32Value, size_t cbValue); -VMMDECL(VBOXSTRICTRC) IOMMMIOWrite(PVM pVM, RTGCPHYS GCPhys, uint32_t u32Value, size_t cbValue); -VMMDECL(VBOXSTRICTRC) IOMMMIOPhysHandler(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pCtxCore, RTGCPHYS GCPhysFault); +VMMDECL(VBOXSTRICTRC) IOMIOPortRead(PVM pVM, PVMCPU pVCpu, RTIOPORT Port, uint32_t *pu32Value, size_t cbValue); +VMMDECL(VBOXSTRICTRC) IOMIOPortWrite(PVM pVM, PVMCPU pVCpu, RTIOPORT Port, uint32_t u32Value, size_t cbValue); +VMMDECL(VBOXSTRICTRC) IOMInterpretOUT(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu); +VMMDECL(VBOXSTRICTRC) IOMInterpretIN(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu); +VMMDECL(VBOXSTRICTRC) IOMIOPortReadString(PVM pVM, PVMCPU pVCpu, RTIOPORT Port, PRTGCPTR pGCPtrDst, PRTGCUINTREG pcTransfers, unsigned cb); +VMMDECL(VBOXSTRICTRC) IOMIOPortWriteString(PVM pVM, PVMCPU pVCpu, RTIOPORT Port, PRTGCPTR pGCPtrSrc, PRTGCUINTREG pcTransfers, unsigned cb); +VMMDECL(VBOXSTRICTRC) IOMInterpretINS(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu); +VMMDECL(VBOXSTRICTRC) IOMInterpretINSEx(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t uPort, uint32_t uPrefix, DISCPUMODE enmAddrMode, uint32_t cbTransfer); +VMMDECL(VBOXSTRICTRC) IOMInterpretOUTS(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu); +VMMDECL(VBOXSTRICTRC) IOMInterpretOUTSEx(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t uPort, uint32_t uPrefix, DISCPUMODE enmAddrMode, uint32_t cbTransfer); +VMMDECL(VBOXSTRICTRC) IOMMMIORead(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys, uint32_t *pu32Value, size_t cbValue); +VMMDECL(VBOXSTRICTRC) IOMMMIOWrite(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys, uint32_t u32Value, size_t cbValue); +VMMDECL(VBOXSTRICTRC) IOMMMIOPhysHandler(PVM pVM, PVMCPU pVCpu, RTGCUINT uErrorCode, PCPUMCTXCORE pCtxCore, RTGCPHYS GCPhysFault); VMMDECL(VBOXSTRICTRC) IOMInterpretCheckPortIOAccess(PVM pVM, PCPUMCTXCORE pCtxCore, RTIOPORT Port, unsigned cb); VMMDECL(int) IOMMMIOMapMMIO2Page(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS GCPhysRemapped, uint64_t fPageFlags); -VMMDECL(int) IOMMMIOMapMMIOHCPage(PVM pVM, RTGCPHYS GCPhys, RTHCPHYS HCPhys, uint64_t fPageFlags); +VMMDECL(int) IOMMMIOMapMMIOHCPage(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys, RTHCPHYS HCPhys, uint64_t fPageFlags); VMMDECL(int) IOMMMIOResetRegion(PVM pVM, RTGCPHYS GCPhys); -VMMDECL(bool) IOMIsLockOwner(PVM pVM); +VMMDECL(bool) IOMIsLockWriteOwner(PVM pVM); #ifdef IN_RC /** @defgroup grp_iom_rc The IOM Raw-Mode Context API * @ingroup grp_iom * @{ */ -VMMRCDECL(VBOXSTRICTRC) IOMRCIOPortHandler(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu); +VMMRCDECL(VBOXSTRICTRC) IOMRCIOPortHandler(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu); /** @} */ #endif /* IN_RC */ diff --git a/include/VBox/vmm/mm.h b/include/VBox/vmm/mm.h index 66490fce..bcb55c14 100644 --- a/include/VBox/vmm/mm.h +++ b/include/VBox/vmm/mm.h @@ -3,7 +3,7 @@ */ /* - * Copyright (C) 2006-2010 Oracle Corporation + * Copyright (C) 2006-2012 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -58,6 +58,8 @@ typedef enum MMTAG MM_TAG_CSAM_PATCH, MM_TAG_CPUM_CTX, + MM_TAG_CPUM_CPUID, + MM_TAG_CPUM_MSRS, MM_TAG_DBGF, MM_TAG_DBGF_AS, @@ -130,7 +132,7 @@ typedef enum MMTAG MM_TAG_VMM, - MM_TAG_HWACCM, + MM_TAG_HM, MM_TAG_32BIT_HACK = 0x7fffffff } MMTAG; @@ -205,6 +207,7 @@ DECLINLINE(RTRCPTR) MMHyperCCToRC(PVM pVM, void *pv) VMMDECL(int) MMHyperAlloc(PVM pVM, size_t cb, uint32_t uAlignment, MMTAG enmTag, void **ppv); +VMMDECL(int) MMHyperDupMem(PVM pVM, const void *pvSrc, size_t cb, unsigned uAlignment, MMTAG enmTag, void **ppv); VMMDECL(int) MMHyperFree(PVM pVM, void *pv); VMMDECL(void) MMHyperHeapCheck(PVM pVM); VMMDECL(int) MMR3LockCall(PVM pVM); diff --git a/include/VBox/vmm/patm.h b/include/VBox/vmm/patm.h index 70b7fa55..6f9adca0 100644 --- a/include/VBox/vmm/patm.h +++ b/include/VBox/vmm/patm.h @@ -3,7 +3,7 @@ */ /* - * Copyright (C) 2006-2010 Oracle Corporation + * Copyright (C) 2006-2013 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -29,6 +29,7 @@ #include <VBox/types.h> #include <VBox/dis.h> +#if defined(VBOX_WITH_RAW_MODE) || defined(DOXYGEN_RUNNING) RT_C_DECLS_BEGIN @@ -41,18 +42,18 @@ RT_C_DECLS_BEGIN * Flags for specifying the type of patch to install with PATMR3InstallPatch * @{ */ -#define PATMFL_CODE32 RT_BIT_64(0) -#define PATMFL_INTHANDLER RT_BIT_64(1) -#define PATMFL_SYSENTER RT_BIT_64(2) -#define PATMFL_GUEST_SPECIFIC RT_BIT_64(3) -#define PATMFL_USER_MODE RT_BIT_64(4) -#define PATMFL_IDTHANDLER RT_BIT_64(5) -#define PATMFL_TRAPHANDLER RT_BIT_64(6) -#define PATMFL_DUPLICATE_FUNCTION RT_BIT_64(7) -#define PATMFL_REPLACE_FUNCTION_CALL RT_BIT_64(8) +#define PATMFL_CODE32 RT_BIT_64(0) +#define PATMFL_INTHANDLER RT_BIT_64(1) +#define PATMFL_SYSENTER RT_BIT_64(2) +#define PATMFL_GUEST_SPECIFIC RT_BIT_64(3) +#define PATMFL_USER_MODE RT_BIT_64(4) +#define PATMFL_IDTHANDLER RT_BIT_64(5) +#define PATMFL_TRAPHANDLER RT_BIT_64(6) +#define PATMFL_DUPLICATE_FUNCTION RT_BIT_64(7) +#define PATMFL_REPLACE_FUNCTION_CALL RT_BIT_64(8) #define PATMFL_TRAPHANDLER_WITH_ERRORCODE RT_BIT_64(9) #define PATMFL_INTHANDLER_WITH_ERRORCODE (PATMFL_TRAPHANDLER_WITH_ERRORCODE) -#define PATMFL_MMIO_ACCESS RT_BIT_64(10) +#define PATMFL_MMIO_ACCESS RT_BIT_64(10) /* no more room -> change PATMInternal.h if more is needed!! */ /* @@ -70,32 +71,32 @@ RT_C_DECLS_BEGIN typedef struct PATMGCSTATE { - /* Virtual Flags register (IF + more later on) */ + /** Virtual Flags register (IF + more later on) */ uint32_t uVMFlags; - /* Pending PATM actions (internal use only) */ + /** Pending PATM actions (internal use only) */ uint32_t uPendingAction; - /* Records the number of times all patches are called (indicating how many exceptions we managed to avoid) */ + /** Records the number of times all patches are called (indicating how many exceptions we managed to avoid) */ uint32_t uPatchCalls; - /* Scratchpad dword */ + /** Scratchpad dword */ uint32_t uScratch; - /* Debugging info */ + /** Debugging info */ uint32_t uIretEFlags, uIretCS, uIretEIP; - /* PATM stack pointer */ + /** PATM stack pointer */ uint32_t Psp; - /* PATM interrupt flag */ + /** PATM interrupt flag */ uint32_t fPIF; - /* PATM inhibit irq address (used by sti) */ + /** PATM inhibit irq address (used by sti) */ RTRCPTR GCPtrInhibitInterrupts; - /* Scratch room for call patch */ + /** Scratch room for call patch */ RTRCPTR GCCallPatchTargetAddr; RTRCPTR GCCallReturnAddr; - /* Temporary storage for guest registers. */ + /** Temporary storage for guest registers. */ struct { uint32_t uEAX; @@ -108,11 +109,11 @@ typedef struct PATMGCSTATE typedef struct PATMTRAPREC { - /* pointer to original guest code instruction (for emulation) */ + /** pointer to original guest code instruction (for emulation) */ RTRCPTR pNewEIP; - /* pointer to the next guest code instruction */ + /** pointer to the next guest code instruction */ RTRCPTR pNextInstr; - /* pointer to the corresponding next instruction in the patch block */ + /** pointer to the corresponding next instruction in the patch block */ RTRCPTR pNextPatchInstr; } PATMTRAPREC, *PPATMTRAPREC; @@ -122,198 +123,50 @@ typedef struct PATMTRAPREC */ typedef enum { - PATMTRANS_FAILED, - PATMTRANS_SAFE, /* Safe translation */ - PATMTRANS_PATCHSTART, /* Instruction starts a patch block */ - PATMTRANS_OVERWRITTEN, /* Instruction overwritten by patchjump */ - PATMTRANS_INHIBITIRQ /* Instruction must be executed due to instruction fusing */ + PATMTRANS_FAILED, + PATMTRANS_SAFE, /**< Safe translation */ + PATMTRANS_PATCHSTART, /**< Instruction starts a patch block */ + PATMTRANS_OVERWRITTEN, /**< Instruction overwritten by patchjump */ + PATMTRANS_INHIBITIRQ /**< Instruction must be executed due to instruction fusing */ } PATMTRANSSTATE; -/** - * Load virtualized flags. - * - * This function is called from CPUMRawEnter(). It doesn't have to update the - * IF and IOPL eflags bits, the caller will enforce those to set and 0 respectively. - * - * @param pVM VM handle. - * @param pCtxCore The cpu context core. - * @see pg_raw - */ -VMMDECL(void) PATMRawEnter(PVM pVM, PCPUMCTXCORE pCtxCore); - -/** - * Restores virtualized flags. - * - * This function is called from CPUMRawLeave(). It will update the eflags register. - * - * @param pVM VM handle. - * @param pCtxCore The cpu context core. - * @param rawRC Raw mode return code - * @see @ref pg_raw - */ -VMMDECL(void) PATMRawLeave(PVM pVM, PCPUMCTXCORE pCtxCore, int rawRC); - -/** - * Get the EFLAGS. - * This is a worker for CPUMRawGetEFlags(). - * - * @returns The eflags. - * @param pVM The VM handle. - * @param pCtxCore The context core. - */ -VMMDECL(uint32_t) PATMRawGetEFlags(PVM pVM, PCCPUMCTXCORE pCtxCore); - -/** - * Updates the EFLAGS. - * This is a worker for CPUMRawSetEFlags(). - * - * @param pVM The VM handle. - * @param pCtxCore The context core. - * @param efl The new EFLAGS value. - */ -VMMDECL(void) PATMRawSetEFlags(PVM pVM, PCPUMCTXCORE pCtxCore, uint32_t efl); - -/** - * Returns the guest context pointer of the GC context structure - * - * @returns VBox status code. - * @param pVM The VM to operate on. - */ -VMMDECL(RCPTRTYPE(PPATMGCSTATE)) PATMQueryGCState(PVM pVM); - -/** - * Checks whether the GC address is part of our patch region - * - * @returns true -> yes, false -> no - * @param pVM The VM to operate on. - * @param pAddr Guest context address - */ -VMMDECL(bool) PATMIsPatchGCAddr(PVM pVM, RTRCUINTPTR pAddr); - -/** - * Check if we must use raw mode (patch code being executed or marked safe for IF=0) - * - * @param pVM VM handle. - * @param pAddrGC Guest context address - */ -VMMDECL(bool) PATMShouldUseRawMode(PVM pVM, RTRCPTR pAddrGC); /** * Query PATM state (enabled/disabled) * * @returns 0 - disabled, 1 - enabled * @param pVM The VM to operate on. + * @internal */ -#define PATMIsEnabled(pVM) (pVM->fPATMEnabled) +#define PATMIsEnabled(a_pVM) ((a_pVM)->fPATMEnabled) -/** - * Set parameters for pending MMIO patch operation - * - * @returns VBox status code. - * @param pDevIns Device instance. - * @param GCPhys MMIO physical address - * @param pCachedData GC pointer to cached data - */ -VMMDECL(int) PATMSetMMIOPatchInfo(PVM pVM, RTGCPHYS GCPhys, RTRCPTR pCachedData); - - -/** - * Adds branch pair to the lookup cache of the particular branch instruction - * - * @returns VBox status - * @param pVM The VM to operate on. - * @param pJumpTableGC Pointer to branch instruction lookup cache - * @param pBranchTarget Original branch target - * @param pRelBranchPatch Relative duplicated function address - */ -VMMDECL(int) PATMAddBranchToLookupCache(PVM pVM, RTRCPTR pJumpTableGC, RTRCPTR pBranchTarget, RTRCUINTPTR pRelBranchPatch); - - -/** - * Checks if the int 3 was caused by a patched instruction - * - * @returns VBox status - * - * @param pVM The VM handle. - * @param pCtxCore The relevant core context. - */ -VMMRCDECL(int) PATMRCHandleInt3PatchTrap(PVM pVM, PCPUMCTXCORE pRegFrame); - -/** - * Checks if the int 3 was caused by a patched instruction - * - * @returns VBox status - * - * @param pVM The VM handle. - * @param pInstrGC Instruction pointer - * @param pOpcode Original instruction opcode (out, optional) - * @param pSize Original instruction size (out, optional) - */ -VMMDECL(bool) PATMIsInt3Patch(PVM pVM, RTRCPTR pInstrGC, uint32_t *pOpcode, uint32_t *pSize); - - -/** - * Checks if the interrupt flag is enabled or not. - * - * @returns true if it's enabled. - * @returns false if it's disabled. - * - * @param pVM The VM handle. - */ -VMMDECL(bool) PATMAreInterruptsEnabled(PVM pVM); +VMMDECL(bool) PATMIsPatchGCAddr(PVM pVM, RTRCUINTPTR pAddr); +VMM_INT_DECL(int) PATMReadPatchCode(PVM pVM, RTGCPTR GCPtrPatchCode, void *pvDst, size_t cbToRead, size_t *pcbRead); -/** - * Checks if the interrupt flag is enabled or not. - * - * @returns true if it's enabled. - * @returns false if it's disabled. - * - * @param pVM The VM handle. - * @param pCtxCore CPU context - */ -VMMDECL(bool) PATMAreInterruptsEnabledByCtxCore(PVM pVM, PCPUMCTXCORE pCtxCore); +VMM_INT_DECL(void) PATMRawEnter(PVM pVM, PCPUMCTXCORE pCtxCore); +VMM_INT_DECL(void) PATMRawLeave(PVM pVM, PCPUMCTXCORE pCtxCore, int rawRC); +VMM_INT_DECL(uint32_t) PATMRawGetEFlags(PVM pVM, PCCPUMCTXCORE pCtxCore); +VMM_INT_DECL(void) PATMRawSetEFlags(PVM pVM, PCPUMCTXCORE pCtxCore, uint32_t efl); +VMM_INT_DECL(RCPTRTYPE(PPATMGCSTATE)) PATMGetGCState(PVM pVM); +VMM_INT_DECL(bool) PATMShouldUseRawMode(PVM pVM, RTRCPTR pAddrGC); +VMM_INT_DECL(int) PATMSetMMIOPatchInfo(PVM pVM, RTGCPHYS GCPhys, RTRCPTR pCachedData); +VMM_INT_DECL(bool) PATMIsInt3Patch(PVM pVM, RTRCPTR pInstrGC, uint32_t *pOpcode, uint32_t *pSize); +VMM_INT_DECL(bool) PATMAreInterruptsEnabled(PVM pVM); +VMM_INT_DECL(bool) PATMAreInterruptsEnabledByCtxCore(PVM pVM, PCPUMCTXCORE pCtxCore); #ifdef PATM_EMULATE_SYSENTER -/** - * Emulate sysenter, sysexit and syscall instructions - * - * @returns VBox status - * - * @param pVM The VM handle. - * @param pCtxCore The relevant core context. - * @param pCpu Disassembly context - */ -VMMDECL(int) PATMSysCall(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu); +VMM_INT_DECL(int) PATMSysCall(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu); #endif #ifdef IN_RC -/** @defgroup grp_patm_gc The Patch Manager API +/** @defgroup grp_patm_rc The Patch Manager RC API * @ingroup grp_patm * @{ */ -/** - * Checks if the write is located on a page with was patched before. - * (if so, then we are not allowed to turn on r/w) - * - * @returns VBox status - * @param pVM The VM to operate on. - * @param pRegFrame CPU context - * @param GCPtr GC pointer to write address - * @param cbWrite Nr of bytes to write - * - */ -VMMRCDECL(int) PATMGCHandleWriteToPatchPage(PVM pVM, PCPUMCTXCORE pRegFrame, RTRCPTR GCPtr, uint32_t cbWrite); - -/** - * Checks if the illegal instruction was caused by a patched instruction - * - * @returns VBox status - * - * @param pVM The VM handle. - * @param pCtxCore The relevant core context. - */ -VMMDECL(int) PATMRCHandleIllegalInstrTrap(PVM pVM, PCPUMCTXCORE pRegFrame); +VMMRC_INT_DECL(int) PATMRCHandleInt3PatchTrap(PVM pVM, PCPUMCTXCORE pRegFrame); +VMMRC_INT_DECL(int) PATMRCHandleWriteToPatchPage(PVM pVM, PCPUMCTXCORE pRegFrame, RTRCPTR GCPtr, uint32_t cbWrite); +VMMRC_INT_DECL(int) PATMRCHandleIllegalInstrTrap(PVM pVM, PCPUMCTXCORE pRegFrame); /** @} */ @@ -325,341 +178,41 @@ VMMDECL(int) PATMRCHandleIllegalInstrTrap(PVM pVM, PCPUMCTXCORE pRegFrame); * @{ */ -/** - * Query PATM state (enabled/disabled) - * - * @returns 0 - disabled, 1 - enabled - * @param pVM The VM to operate on. - */ -VMMR3DECL(int) PATMR3IsEnabled(PVM pVM); - -/** - * Initializes the PATM. - * - * @returns VBox status code. - * @param pVM The VM to operate on. - */ -VMMR3DECL(int) PATMR3Init(PVM pVM); - -/** - * Finalizes HMA page attributes. - * - * @returns VBox status code. - * @param pVM The VM handle. - */ -VMMR3DECL(int) PATMR3InitFinalize(PVM pVM); - -/** - * Applies relocations to data and code managed by this - * component. This function will be called at init and - * whenever the VMM need to relocate it self inside the GC. - * - * The PATM will update the addresses used by the switcher. - * - * @param pVM The VM. - */ -VMMR3DECL(void) PATMR3Relocate(PVM pVM); - -/** - * Terminates the PATM. - * - * Termination means cleaning up and freeing all resources, - * the VM it self is at this point powered off or suspended. - * - * @returns VBox status code. - * @param pVM The VM to operate on. - */ -VMMR3DECL(int) PATMR3Term(PVM pVM); - -/** - * PATM reset callback. - * - * @returns VBox status code. - * @param pVM The VM which is reset. - */ -VMMR3DECL(int) PATMR3Reset(PVM pVM); - -/** - * Returns the host context pointer and size of the patch memory block - * - * @returns VBox status code. - * @param pVM The VM to operate on. - * @param pcb Size of the patch memory block - */ -VMMR3DECL(void *) PATMR3QueryPatchMemHC(PVM pVM, uint32_t *pcb); - -/** - * Returns the guest context pointer and size of the patch memory block - * - * @returns VBox status code. - * @param pVM The VM to operate on. - * @param pcb Size of the patch memory block - */ -VMMR3DECL(RTRCPTR) PATMR3QueryPatchMemGC(PVM pVM, uint32_t *pcb); - -/** - * Checks whether the GC address is inside a generated patch jump - * - * @returns true -> yes, false -> no - * @param pVM The VM to operate on. - * @param pAddr Guest context address - * @param pPatchAddr Guest context patch address (if true) - */ -VMMR3DECL(bool) PATMR3IsInsidePatchJump(PVM pVM, RTRCPTR pAddr, PRTGCPTR32 pPatchAddr); - - -/** - * Returns the GC pointer of the patch for the specified GC address - * - * @returns VBox status code. - * @param pVM The VM to operate on. - * @param pAddrGC Guest context address - */ -VMMR3DECL(RTRCPTR) PATMR3QueryPatchGCPtr(PVM pVM, RTRCPTR pAddrGC); - -/** - * Checks whether the HC address is part of our patch region - * - * @returns VBox status code. - * @param pVM The VM to operate on. - * @param pAddrGC Guest context address - */ -VMMR3DECL(bool) PATMR3IsPatchHCAddr(PVM pVM, R3PTRTYPE(uint8_t *) pAddrHC); - -/** - * Convert a GC patch block pointer to a HC patch pointer - * - * @returns HC pointer or NULL if it's not a GC patch pointer - * @param pVM The VM to operate on. - * @param pAddrGC GC pointer - */ -VMMR3DECL(R3PTRTYPE(void *)) PATMR3GCPtrToHCPtr(PVM pVM, RTRCPTR pAddrGC); - - -/** - * Returns the host context pointer and size of the GC context structure - * - * @returns VBox status code. - * @param pVM The VM to operate on. - */ -VMMR3DECL(PPATMGCSTATE) PATMR3QueryGCStateHC(PVM pVM); - -/** - * Handle trap inside patch code - * - * @returns VBox status code. - * @param pVM The VM to operate on. - * @param pCtx CPU context - * @param pEip GC pointer of trapping instruction - * @param pNewEip GC pointer to new instruction - */ -VMMR3DECL(int) PATMR3HandleTrap(PVM pVM, PCPUMCTX pCtx, RTRCPTR pEip, RTGCPTR *ppNewEip); - -/** - * Handle page-fault in monitored page - * - * @returns VBox status code. - * @param pVM The VM to operate on. - */ -VMMR3DECL(int) PATMR3HandleMonitoredPage(PVM pVM); - -/** - * Notifies PATM about a (potential) write to code that has been patched. - * - * @returns VBox status code. - * @param pVM The VM to operate on. - * @param GCPtr GC pointer to write address - * @param cbWrite Nr of bytes to write - * - */ -VMMR3DECL(int) PATMR3PatchWrite(PVM pVM, RTRCPTR GCPtr, uint32_t cbWrite); - -/** - * Notify PATM of a page flush - * - * @returns VBox status code - * @param pVM The VM to operate on. - * @param addr GC address of the page to flush - */ -VMMR3DECL(int) PATMR3FlushPage(PVM pVM, RTRCPTR addr); - -/** - * Allows or disallow patching of privileged instructions executed by the guest OS - * - * @returns VBox status code. - * @param pVM The VM to operate on. - * @param fAllowPatching Allow/disallow patching - */ -VMMR3DECL(int) PATMR3AllowPatching(PVM pVM, uint32_t fAllowPatching); - -/** - * Patch privileged instruction at specified location - * - * @returns VBox status code. - * @param pVM The VM to operate on. - * @param pInstr Guest context point to privileged instruction (0:32 flat address) - * @param flags Patch flags - * - * @note returns failure if patching is not allowed or possible - */ -VMMR3DECL(int) PATMR3InstallPatch(PVM pVM, RTRCPTR pInstrGC, uint64_t flags); - -/** - * Gives hint to PATM about supervisor guest instructions - * - * @returns VBox status code. - * @param pVM The VM to operate on. - * @param pInstr Guest context point to privileged instruction - * @param flags Patch flags - */ -VMMR3DECL(int) PATMR3AddHint(PVM pVM, RTRCPTR pInstrGC, uint32_t flags); - -/** - * Patch branch target function for call/jump at specified location. - * (in responds to a VINF_PATM_DUPLICATE_FUNCTION GC exit reason) - * - * @returns VBox status code. - * @param pVM The VM to operate on. - * @param pCtx Guest context - * - */ -VMMR3DECL(int) PATMR3DuplicateFunctionRequest(PVM pVM, PCPUMCTX pCtx); - -/** - * Query the corresponding GC instruction pointer from a pointer inside the patch block itself - * - * @returns original GC instruction pointer or 0 if not found - * @param pVM The VM to operate on. - * @param pPatchGC GC address in patch block - * @param pEnmState State of the translated address (out) - * - */ -VMMR3DECL(RTRCPTR) PATMR3PatchToGCPtr(PVM pVM, RTRCPTR pPatchGC, PATMTRANSSTATE *pEnmState); - -/** - * Converts Guest code GC ptr to Patch code GC ptr (if found) - * - * @returns corresponding GC pointer in patch block - * @param pVM The VM to operate on. - * @param pInstrGC Guest context pointer to privileged instruction - * - */ -VMMR3DECL(RTRCPTR) PATMR3GuestGCPtrToPatchGCPtr(PVM pVM, RCPTRTYPE(uint8_t*) pInstrGC); - -/** - * Query the opcode of the original code that was overwritten by the 5 bytes patch jump - * - * @returns VBox status code. - * @param pVM The VM to operate on. - * @param pInstrGC GC address of instr - * @param pByte opcode byte pointer (OUT) - * @returns VBOX error code - * - */ -VMMR3DECL(int) PATMR3QueryOpcode(PVM pVM, RTRCPTR pInstrGC, uint8_t *pByte); -VMMR3DECL(int) PATMR3ReadOrgInstr(PVM pVM, RTGCPTR32 GCPtrInstr, uint8_t *pbDst, size_t cbToRead, size_t *pcbRead); - -/** - * Disable patch for privileged instruction at specified location - * - * @returns VBox status code. - * @param pVM The VM to operate on. - * @param pInstr Guest context point to privileged instruction - * - * @note returns failure if patching is not allowed or possible - * - */ -VMMR3DECL(int) PATMR3DisablePatch(PVM pVM, RTRCPTR pInstrGC); - - -/** - * Enable patch for privileged instruction at specified location - * - * @returns VBox status code. - * @param pVM The VM to operate on. - * @param pInstr Guest context point to privileged instruction - * - * @note returns failure if patching is not allowed or possible - * - */ -VMMR3DECL(int) PATMR3EnablePatch(PVM pVM, RTRCPTR pInstrGC); - - -/** - * Remove patch for privileged instruction at specified location - * - * @returns VBox status code. - * @param pVM The VM to operate on. - * @param pInstr Guest context point to privileged instruction - * - * @note returns failure if patching is not allowed or possible - * - */ -VMMR3DECL(int) PATMR3RemovePatch(PVM pVM, RTRCPTR pInstrGC); - - -/** - * Detects it the specified address falls within a 5 byte jump generated for an active patch. - * If so, this patch is permanently disabled. - * - * @param pVM The VM to operate on. - * @param pInstrGC Guest context pointer to instruction - * @param pConflictGC Guest context pointer to check - */ -VMMR3DECL(int) PATMR3DetectConflict(PVM pVM, RTRCPTR pInstrGC, RTRCPTR pConflictGC); - - -/** - * Checks if the instructions at the specified address has been patched already. - * - * @returns boolean, patched or not - * @param pVM The VM to operate on. - * @param pInstrGC Guest context pointer to instruction - */ -VMMR3DECL(bool) PATMR3HasBeenPatched(PVM pVM, RTRCPTR pInstrGC); - - -/** - * Install Linux 2.6 spinlock patch - * - * @returns VBox status code. - * @param pVM The VM to operate on - * @param pCallAcquireSpinlockGC GC pointer of call instruction - * @param cbAcquireSpinlockCall Instruction size - * - */ -VMMR3DECL(int) PATMInstallSpinlockPatch(PVM pVM, RTRCPTR pCallAcquireSpinlockGC, uint32_t cbAcquireSpinlockCall); - - -/** - * Check if supplied call target is the Linux 2.6 spinlock acquire function - * - * @returns boolean - * @param pVM The VM to operate on - * @param pCallAcquireSpinlockGC Call target GC address - * - */ -VMMR3DECL(bool) PATMIsSpinlockAcquire(PVM pVM, RTRCPTR pCallTargetGC); - -/** - * Check if supplied call target is the Linux 2.6 spinlock release function - * - * @returns boolean - * @param pVM The VM to operate on - * @param pCallTargetGC Call target GC address - * - */ -VMMR3DECL(bool) PATMIsSpinlockRelease(PVM pVM, RTRCPTR pCallTargetGC); - -/** - * Check if supplied call target is the Linux 2.6 spinlock release function (patched equivalent) - * - * @returns boolean - * @param pVM The VM to operate on - * @param pCallTargetGC Call target GC address - * - */ -VMMR3DECL(bool) PATMIsSpinlockReleasePatch(PVM pVM, RTRCPTR pCallTargetGC); +VMMR3DECL(int) PATMR3AllowPatching(PUVM pUVM, bool fAllowPatching); +VMMR3DECL(bool) PATMR3IsEnabled(PUVM pUVM); + +VMMR3_INT_DECL(int) PATMR3Init(PVM pVM); +VMMR3_INT_DECL(int) PATMR3InitFinalize(PVM pVM); +VMMR3_INT_DECL(void) PATMR3Relocate(PVM pVM); +VMMR3_INT_DECL(int) PATMR3Term(PVM pVM); +VMMR3_INT_DECL(int) PATMR3Reset(PVM pVM); + +VMMR3_INT_DECL(void *) PATMR3QueryPatchMemHC(PVM pVM, uint32_t *pcb); +VMMR3_INT_DECL(RTRCPTR) PATMR3QueryPatchMemGC(PVM pVM, uint32_t *pcb); +VMMR3_INT_DECL(bool) PATMR3IsInsidePatchJump(PVM pVM, RTRCPTR pAddr, PRTGCPTR32 pPatchAddr); +VMMR3_INT_DECL(RTRCPTR) PATMR3QueryPatchGCPtr(PVM pVM, RTRCPTR pAddrGC); +VMMR3_INT_DECL(bool) PATMR3IsPatchHCAddr(PVM pVM, void *pAddrHC); +VMMR3_INT_DECL(void *) PATMR3GCPtrToHCPtr(PVM pVM, RTRCPTR pAddrGC); +VMMR3_INT_DECL(PPATMGCSTATE) PATMR3QueryGCStateHC(PVM pVM); +VMMR3_INT_DECL(int) PATMR3HandleTrap(PVM pVM, PCPUMCTX pCtx, RTRCPTR pEip, RTGCPTR *ppNewEip); +VMMR3_INT_DECL(int) PATMR3HandleMonitoredPage(PVM pVM); +VMMR3_INT_DECL(int) PATMR3PatchWrite(PVM pVM, RTRCPTR GCPtr, uint32_t cbWrite); +VMMR3_INT_DECL(int) PATMR3FlushPage(PVM pVM, RTRCPTR addr); +VMMR3_INT_DECL(int) PATMR3InstallPatch(PVM pVM, RTRCPTR pInstrGC, uint64_t flags); +VMMR3_INT_DECL(int) PATMR3AddHint(PVM pVM, RTRCPTR pInstrGC, uint32_t flags); +VMMR3_INT_DECL(int) PATMR3DuplicateFunctionRequest(PVM pVM, PCPUMCTX pCtx); +VMMR3_INT_DECL(RTRCPTR) PATMR3PatchToGCPtr(PVM pVM, RTRCPTR pPatchGC, PATMTRANSSTATE *pEnmState); +VMMR3DECL(int) PATMR3QueryOpcode(PVM pVM, RTRCPTR pInstrGC, uint8_t *pByte); +VMMR3_INT_DECL(int) PATMR3ReadOrgInstr(PVM pVM, RTGCPTR32 GCPtrInstr, uint8_t *pbDst, size_t cbToRead, size_t *pcbRead); +VMMR3_INT_DECL(int) PATMR3DisablePatch(PVM pVM, RTRCPTR pInstrGC); +VMMR3_INT_DECL(int) PATMR3EnablePatch(PVM pVM, RTRCPTR pInstrGC); +VMMR3_INT_DECL(int) PATMR3RemovePatch(PVM pVM, RTRCPTR pInstrGC); +VMMR3_INT_DECL(int) PATMR3DetectConflict(PVM pVM, RTRCPTR pInstrGC, RTRCPTR pConflictGC); +VMMR3_INT_DECL(bool) PATMR3HasBeenPatched(PVM pVM, RTRCPTR pInstrGC); + +VMMR3_INT_DECL(void) PATMR3DbgPopulateAddrSpace(PVM pVM, RTDBGAS hDbgAs); +VMMR3_INT_DECL(void) PATMR3DbgAnnotatePatchedInstruction(PVM pVM, RTRCPTR RCPtr, uint8_t cbInstr, + char *pszBuf, size_t cbBuf); /** @} */ #endif @@ -668,5 +221,6 @@ VMMR3DECL(bool) PATMIsSpinlockReleasePatch(PVM pVM, RTRCPTR pCallTargetGC); /** @} */ RT_C_DECLS_END +#endif /* VBOX_WITH_RAW_MODE */ #endif diff --git a/include/VBox/vmm/pdm.h b/include/VBox/vmm/pdm.h index ff95ea82..527d3d14 100644 --- a/include/VBox/vmm/pdm.h +++ b/include/VBox/vmm/pdm.h @@ -3,7 +3,7 @@ */ /* - * Copyright (C) 2006-2010 Oracle Corporation + * Copyright (C) 2006-2013 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -29,6 +29,7 @@ #include <VBox/vmm/pdmapi.h> #include <VBox/vmm/pdmqueue.h> #include <VBox/vmm/pdmcritsect.h> +#include <VBox/vmm/pdmcritsectrw.h> #include <VBox/vmm/pdmthread.h> #include <VBox/vmm/pdmifs.h> #include <VBox/vmm/pdmdrv.h> diff --git a/include/VBox/vmm/pdmapi.h b/include/VBox/vmm/pdmapi.h index 1fb8aef6..321865a1 100644 --- a/include/VBox/vmm/pdmapi.h +++ b/include/VBox/vmm/pdmapi.h @@ -7,7 +7,7 @@ */ /* - * Copyright (C) 2006-2010 Oracle Corporation + * Copyright (C) 2006-2013 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -40,20 +40,21 @@ RT_C_DECLS_BEGIN * @{ */ -VMMDECL(int) PDMGetInterrupt(PVMCPU pVCpu, uint8_t *pu8Interrupt); -VMMDECL(int) PDMIsaSetIrq(PVM pVM, uint8_t u8Irq, uint8_t u8Level, uint32_t uTagSrc); -VMM_INT_DECL(int) PDMIoApicSetIrq(PVM pVM, uint8_t u8Irq, uint8_t u8Level, uint32_t uTagSrc); -VMM_INT_DECL(int) PDMIoApicSendMsi(PVM pVM, RTGCPHYS GCAddr, uint32_t uValue, uint32_t uTagSrc); -VMMDECL(bool) PDMHasIoApic(PVM pVM); -VMMDECL(int) PDMApicHasPendingIrq(PVM pVM, bool *pfPending); -VMMDECL(int) PDMApicSetBase(PVM pVM, uint64_t u64Base); -VMMDECL(int) PDMApicGetBase(PVM pVM, uint64_t *pu64Base); -VMMDECL(int) PDMApicSetTPR(PVMCPU pVCpu, uint8_t u8TPR); -VMMDECL(int) PDMApicGetTPR(PVMCPU pVCpu, uint8_t *pu8TPR, bool *pfPending); -VMMDECL(int) PDMApicWriteMSR(PVM pVM, VMCPUID iCpu, uint32_t u32Reg, uint64_t u64Value); -VMMDECL(int) PDMApicReadMSR(PVM pVM, VMCPUID iCpu, uint32_t u32Reg, uint64_t *pu64Value); -VMMDECL(int) PDMVMMDevHeapR3ToGCPhys(PVM pVM, RTR3PTR pv, RTGCPHYS *pGCPhys); -VMMDECL(bool) PDMVMMDevHeapIsEnabled(PVM pVM); +VMMDECL(int) PDMGetInterrupt(PVMCPU pVCpu, uint8_t *pu8Interrupt); +VMMDECL(int) PDMIsaSetIrq(PVM pVM, uint8_t u8Irq, uint8_t u8Level, uint32_t uTagSrc); +VMM_INT_DECL(bool) PDMHasIoApic(PVM pVM); +VMM_INT_DECL(int) PDMIoApicSetIrq(PVM pVM, uint8_t u8Irq, uint8_t u8Level, uint32_t uTagSrc); +VMM_INT_DECL(int) PDMIoApicSendMsi(PVM pVM, RTGCPHYS GCAddr, uint32_t uValue, uint32_t uTagSrc); +VMM_INT_DECL(bool) PDMHasApic(PVM pVM); +VMM_INT_DECL(int) PDMApicHasPendingIrq(PVM pVM, bool *pfPending); +VMMDECL(int) PDMApicSetBase(PVMCPU pVCpu, uint64_t u64Base); +VMMDECL(int) PDMApicGetBase(PVMCPU pVCpu, uint64_t *pu64Base); +VMMDECL(int) PDMApicSetTPR(PVMCPU pVCpu, uint8_t u8TPR); +VMMDECL(int) PDMApicGetTPR(PVMCPU pVCpu, uint8_t *pu8TPR, bool *pfPending, uint8_t *pu8PendingIrq); +VMM_INT_DECL(int) PDMApicWriteMSR(PVM pVM, VMCPUID iCpu, uint32_t u32Reg, uint64_t u64Value); +VMM_INT_DECL(int) PDMApicReadMSR(PVM pVM, VMCPUID iCpu, uint32_t u32Reg, uint64_t *pu64Value); +VMM_INT_DECL(int) PDMVmmDevHeapR3ToGCPhys(PVM pVM, RTR3PTR pv, RTGCPHYS *pGCPhys); +VMM_INT_DECL(bool) PDMVmmDevHeapIsEnabled(PVM pVM); /** @defgroup grp_pdm_r3 The PDM Host Context Ring-3 API @@ -61,18 +62,36 @@ VMMDECL(bool) PDMVMMDevHeapIsEnabled(PVM pVM); * @{ */ -VMMR3DECL(int) PDMR3InitUVM(PUVM pUVM); -VMMR3DECL(int) PDMR3LdrLoadVMMR0U(PUVM pUVM); -VMMR3DECL(int) PDMR3Init(PVM pVM); -VMMR3DECL(void) PDMR3PowerOn(PVM pVM); -VMMR3DECL(void) PDMR3ResetCpu(PVMCPU pVCpu); -VMMR3DECL(void) PDMR3Reset(PVM pVM); -VMMR3DECL(void) PDMR3Suspend(PVM pVM); -VMMR3DECL(void) PDMR3Resume(PVM pVM); -VMMR3DECL(void) PDMR3PowerOff(PVM pVM); -VMMR3DECL(void) PDMR3Relocate(PVM pVM, RTGCINTPTR offDelta); -VMMR3DECL(int) PDMR3Term(PVM pVM); -VMMR3DECL(void) PDMR3TermUVM(PUVM pUVM); +VMMR3_INT_DECL(int) PDMR3InitUVM(PUVM pUVM); +VMMR3_INT_DECL(int) PDMR3LdrLoadVMMR0U(PUVM pUVM); +VMMR3_INT_DECL(int) PDMR3Init(PVM pVM); +VMMR3DECL(void) PDMR3PowerOn(PVM pVM); +VMMR3_INT_DECL(void) PDMR3ResetCpu(PVMCPU pVCpu); +VMMR3_INT_DECL(void) PDMR3Reset(PVM pVM); +VMMR3_INT_DECL(void) PDMR3MemSetup(PVM pVM, bool fAtReset); +VMMR3_INT_DECL(void) PDMR3Suspend(PVM pVM); +VMMR3_INT_DECL(void) PDMR3Resume(PVM pVM); +VMMR3DECL(void) PDMR3PowerOff(PVM pVM); +VMMR3_INT_DECL(void) PDMR3Relocate(PVM pVM, RTGCINTPTR offDelta); +VMMR3_INT_DECL(int) PDMR3Term(PVM pVM); +VMMR3_INT_DECL(void) PDMR3TermUVM(PUVM pUVM); + +/** PDM loader context indicator. */ +typedef enum PDMLDRCTX +{ + /** Invalid zero value. */ + PDMLDRCTX_INVALID = 0, + /** Ring-0 context. */ + PDMLDRCTX_RING_0, + /** Ring-3 context. */ + PDMLDRCTX_RING_3, + /** Raw-mode context. */ + PDMLDRCTX_RAW_MODE, + /** End of valid context values. */ + PDMLDRCTX_END, + /** 32-bit type hack. */ + PDMLDRCTX_32BIT_HACK = 0x7fffffff +} PDMLDRCTX; /** * Module enumeration callback function. @@ -85,54 +104,57 @@ VMMR3DECL(void) PDMR3TermUVM(PUVM pUVM); * @param pszName Module name. (short and unique) * @param ImageBase Address where to executable image is loaded. * @param cbImage Size of the executable image. - * @param fRC Set if raw-mode context, clear if host context. + * @param enmCtx The context the module is loaded into. * @param pvArg User argument. */ typedef DECLCALLBACK(int) FNPDMR3ENUM(PVM pVM, const char *pszFilename, const char *pszName, - RTUINTPTR ImageBase, size_t cbImage, bool fRC, void *pvArg); + RTUINTPTR ImageBase, size_t cbImage, PDMLDRCTX enmCtx, void *pvArg); /** Pointer to a FNPDMR3ENUM() function. */ typedef FNPDMR3ENUM *PFNPDMR3ENUM; -VMMR3DECL(int) PDMR3LdrEnumModules(PVM pVM, PFNPDMR3ENUM pfnCallback, void *pvArg); -VMMR3DECL(void) PDMR3LdrRelocateU(PUVM pUVM, RTGCINTPTR offDelta); -VMMR3DECL(int) PDMR3LdrGetSymbolR3(PVM pVM, const char *pszModule, const char *pszSymbol, void **ppvValue); -VMMR3DECL(int) PDMR3LdrGetSymbolR0(PVM pVM, const char *pszModule, const char *pszSymbol, PRTR0PTR ppvValue); -VMMR3DECL(int) PDMR3LdrGetSymbolR0Lazy(PVM pVM, const char *pszModule, const char *pszSearchPath, const char *pszSymbol, PRTR0PTR ppvValue); -VMMR3DECL(int) PDMR3LdrLoadRC(PVM pVM, const char *pszFilename, const char *pszName); -VMMR3DECL(int) PDMR3LdrGetSymbolRC(PVM pVM, const char *pszModule, const char *pszSymbol, PRTRCPTR pRCPtrValue); -VMMR3DECL(int) PDMR3LdrGetSymbolRCLazy(PVM pVM, const char *pszModule, const char *pszSearchPath, const char *pszSymbol, PRTRCPTR pRCPtrValue); -VMMR3DECL(int) PDMR3LdrQueryRCModFromPC(PVM pVM, RTRCPTR uPC, - char *pszModName, size_t cchModName, PRTRCPTR pMod, - char *pszNearSym1, size_t cchNearSym1, PRTRCPTR pNearSym1, - char *pszNearSym2, size_t cchNearSym2, PRTRCPTR pNearSym2); -VMMR3DECL(int) PDMR3LdrQueryR0ModFromPC(PVM pVM, RTR0PTR uPC, - char *pszModName, size_t cchModName, PRTR0PTR pMod, - char *pszNearSym1, size_t cchNearSym1, PRTR0PTR pNearSym1, - char *pszNearSym2, size_t cchNearSym2, PRTR0PTR pNearSym2); -VMMR3DECL(int) PDMR3LdrGetInterfaceSymbols(PVM pVM, - void *pvInterface, size_t cbInterface, - const char *pszModule, const char *pszSearchPath, - const char *pszSymPrefix, const char *pszSymList, - bool fRing0OrRC); - -VMMR3DECL(int) PDMR3QueryDevice(PVM pVM, const char *pszDevice, unsigned iInstance, PPPDMIBASE ppBase); -VMMR3DECL(int) PDMR3QueryDeviceLun(PVM pVM, const char *pszDevice, unsigned iInstance, unsigned iLun, PPPDMIBASE ppBase); -VMMR3DECL(int) PDMR3QueryLun(PVM pVM, const char *pszDevice, unsigned iInstance, unsigned iLun, PPPDMIBASE ppBase); -VMMR3DECL(int) PDMR3QueryDriverOnLun(PVM pVM, const char *pszDevice, unsigned iInstance, unsigned iLun, const char *pszDriver, - PPPDMIBASE ppBase); -VMMR3DECL(int) PDMR3DeviceAttach(PVM pVM, const char *pszDevice, unsigned iInstance, unsigned iLun, uint32_t fFlags, PPDMIBASE *ppBase); -VMMR3DECL(int) PDMR3DeviceDetach(PVM pVM, const char *pszDevice, unsigned iInstance, unsigned iLun, uint32_t fFlags); +VMMR3DECL(int) PDMR3LdrEnumModules(PVM pVM, PFNPDMR3ENUM pfnCallback, void *pvArg); +VMMR3_INT_DECL(void) PDMR3LdrRelocateU(PUVM pUVM, RTGCINTPTR offDelta); +VMMR3_INT_DECL(int) PDMR3LdrGetSymbolR3(PVM pVM, const char *pszModule, const char *pszSymbol, void **ppvValue); +VMMR3DECL(int) PDMR3LdrGetSymbolR0(PVM pVM, const char *pszModule, const char *pszSymbol, PRTR0PTR ppvValue); +VMMR3DECL(int) PDMR3LdrGetSymbolR0Lazy(PVM pVM, const char *pszModule, const char *pszSearchPath, const char *pszSymbol, PRTR0PTR ppvValue); +VMMR3DECL(int) PDMR3LdrLoadRC(PVM pVM, const char *pszFilename, const char *pszName); +VMMR3DECL(int) PDMR3LdrGetSymbolRC(PVM pVM, const char *pszModule, const char *pszSymbol, PRTRCPTR pRCPtrValue); +VMMR3DECL(int) PDMR3LdrGetSymbolRCLazy(PVM pVM, const char *pszModule, const char *pszSearchPath, const char *pszSymbol, + PRTRCPTR pRCPtrValue); +VMMR3_INT_DECL(int) PDMR3LdrQueryRCModFromPC(PVM pVM, RTRCPTR uPC, + char *pszModName, size_t cchModName, PRTRCPTR pMod, + char *pszNearSym1, size_t cchNearSym1, PRTRCPTR pNearSym1, + char *pszNearSym2, size_t cchNearSym2, PRTRCPTR pNearSym2); +VMMR3_INT_DECL(int) PDMR3LdrQueryR0ModFromPC(PVM pVM, RTR0PTR uPC, + char *pszModName, size_t cchModName, PRTR0PTR pMod, + char *pszNearSym1, size_t cchNearSym1, PRTR0PTR pNearSym1, + char *pszNearSym2, size_t cchNearSym2, PRTR0PTR pNearSym2); +VMMR3_INT_DECL(int) PDMR3LdrGetInterfaceSymbols(PVM pVM, void *pvInterface, size_t cbInterface, + const char *pszModule, const char *pszSearchPath, + const char *pszSymPrefix, const char *pszSymList, + bool fRing0OrRC); + +VMMR3DECL(int) PDMR3QueryDevice(PUVM pUVM, const char *pszDevice, unsigned iInstance, PPPDMIBASE ppBase); +VMMR3DECL(int) PDMR3QueryDeviceLun(PUVM pUVM, const char *pszDevice, unsigned iInstance, unsigned iLun, PPPDMIBASE ppBase); +VMMR3DECL(int) PDMR3QueryLun(PUVM pUVM, const char *pszDevice, unsigned iInstance, unsigned iLun, PPPDMIBASE ppBase); +VMMR3DECL(int) PDMR3QueryDriverOnLun(PUVM pUVM, const char *pszDevice, unsigned iInstance, unsigned iLun, + const char *pszDriver, PPPDMIBASE ppBase); +VMMR3DECL(int) PDMR3DeviceAttach(PUVM pUVM, const char *pszDevice, unsigned iInstance, unsigned iLun, uint32_t fFlags, + PPDMIBASE *ppBase); +VMMR3DECL(int) PDMR3DeviceDetach(PUVM pUVM, const char *pszDevice, unsigned iInstance, unsigned iLun, uint32_t fFlags); VMMR3_INT_DECL(PPDMCRITSECT) PDMR3DevGetCritSect(PVM pVM, PPDMDEVINS pDevIns); -VMMR3DECL(int) PDMR3DriverAttach(PVM pVM, const char *pszDevice, unsigned iDevIns, unsigned iLun, uint32_t fFlags, PPPDMIBASE ppBase); -VMMR3DECL(int) PDMR3DriverDetach(PVM pVM, const char *pszDevice, unsigned iDevIns, unsigned iLun, - const char *pszDriver, unsigned iOccurance, uint32_t fFlags); -VMMR3DECL(int) PDMR3DriverReattach(PVM pVM, const char *pszDevice, unsigned iDevIns, unsigned iLun, - const char *pszDriver, unsigned iOccurance, uint32_t fFlags, PCFGMNODE pCfg, PPPDMIBASE ppBase); -VMMR3DECL(void) PDMR3DmaRun(PVM pVM); -VMMR3DECL(int) PDMR3LockCall(PVM pVM); -VMMR3DECL(int) PDMR3RegisterVMMDevHeap(PVM pVM, RTGCPHYS GCPhys, RTR3PTR pvHeap, unsigned cbSize); -VMMR3DECL(int) PDMR3VMMDevHeapAlloc(PVM pVM, unsigned cbSize, RTR3PTR *ppv); -VMMR3DECL(int) PDMR3VMMDevHeapFree(PVM pVM, RTR3PTR pv); -VMMR3DECL(int) PDMR3UnregisterVMMDevHeap(PVM pVM, RTGCPHYS GCPhys); +VMMR3DECL(int) PDMR3DriverAttach(PUVM pUVM, const char *pszDevice, unsigned iDevIns, unsigned iLun, uint32_t fFlags, + PPPDMIBASE ppBase); +VMMR3DECL(int) PDMR3DriverDetach(PUVM pUVM, const char *pszDevice, unsigned iDevIns, unsigned iLun, + const char *pszDriver, unsigned iOccurance, uint32_t fFlags); +VMMR3DECL(int) PDMR3DriverReattach(PUVM pVM, const char *pszDevice, unsigned iDevIns, unsigned iLun, + const char *pszDriver, unsigned iOccurance, uint32_t fFlags, PCFGMNODE pCfg, + PPPDMIBASE ppBase); +VMMR3DECL(void) PDMR3DmaRun(PVM pVM); +VMMR3_INT_DECL(int) PDMR3LockCall(PVM pVM); +VMMR3_INT_DECL(int) PDMR3VmmDevHeapRegister(PVM pVM, RTGCPHYS GCPhys, RTR3PTR pvHeap, unsigned cbSize); +VMMR3_INT_DECL(int) PDMR3VmmDevHeapUnregister(PVM pVM, RTGCPHYS GCPhys); +VMMR3_INT_DECL(int) PDMR3VmmDevHeapAlloc(PVM pVM, size_t cbSize, RTR3PTR *ppv); +VMMR3_INT_DECL(int) PDMR3VmmDevHeapFree(PVM pVM, RTR3PTR pv); VMMR3_INT_DECL(int) PDMR3TracingConfig(PVM pVM, const char *pszName, size_t cchName, bool fEnable, bool fApply); VMMR3_INT_DECL(bool) PDMR3TracingAreAll(PVM pVM, bool fEnabled); VMMR3_INT_DECL(int) PDMR3TracingQueryConfig(PVM pVM, char *pszConfig, size_t cbConfig); diff --git a/include/VBox/vmm/pdmasynccompletion.h b/include/VBox/vmm/pdmasynccompletion.h index 1d1af265..74285945 100644 --- a/include/VBox/vmm/pdmasynccompletion.h +++ b/include/VBox/vmm/pdmasynccompletion.h @@ -3,7 +3,7 @@ */ /* - * Copyright (C) 2007-2010 Oracle Corporation + * Copyright (C) 2007-2013 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -104,122 +104,8 @@ typedef DECLCALLBACK(void) FNPDMASYNCCOMPLETEINT(PVM pVM, void *pvUser, void *pv /** Pointer to a FNPDMASYNCCOMPLETEINT(). */ typedef FNPDMASYNCCOMPLETEINT *PFNPDMASYNCCOMPLETEINT; - -/** - * Creates an async completion template for a device instance. - * - * The template is used when creating new completion tasks. - * - * @returns VBox status code. - * @param pVM Pointer to the shared VM structure. - * @param pDevIns The device instance. - * @param ppTemplate Where to store the template pointer on success. - * @param pfnCompleted The completion callback routine. - * @param pszDesc Description. - */ -VMMR3DECL(int) PDMR3AsyncCompletionTemplateCreateDevice(PVM pVM, PPDMDEVINS pDevIns, PPPDMASYNCCOMPLETIONTEMPLATE ppTemplate, PFNPDMASYNCCOMPLETEDEV pfnCompleted, const char *pszDesc); - -/** - * Creates an async completion template for a driver instance. - * - * The template is used when creating new completion tasks. - * - * @returns VBox status code. - * @param pVM Pointer to the shared VM structure. - * @param pDrvIns The driver instance. - * @param ppTemplate Where to store the template pointer on success. - * @param pfnCompleted The completion callback routine. - * @param pvTemplateUser Template user argument. - * @param pszDesc Description. - */ -VMMR3DECL(int) PDMR3AsyncCompletionTemplateCreateDriver(PVM pVM, PPDMDRVINS pDrvIns, PPPDMASYNCCOMPLETIONTEMPLATE ppTemplate, PFNPDMASYNCCOMPLETEDRV pfnCompleted, void *pvTemplateUser, const char *pszDesc); - -/** - * Creates an async completion template for a USB device instance. - * - * The template is used when creating new completion tasks. - * - * @returns VBox status code. - * @param pVM Pointer to the shared VM structure. - * @param pUsbIns The USB device instance. - * @param ppTemplate Where to store the template pointer on success. - * @param pfnCompleted The completion callback routine. - * @param pszDesc Description. - */ -VMMR3DECL(int) PDMR3AsyncCompletionTemplateCreateUsb(PVM pVM, PPDMUSBINS pUsbIns, PPPDMASYNCCOMPLETIONTEMPLATE ppTemplate, PFNPDMASYNCCOMPLETEUSB pfnCompleted, const char *pszDesc); - -/** - * Creates an async completion template for internally by the VMM. - * - * The template is used when creating new completion tasks. - * - * @returns VBox status code. - * @param pVM Pointer to the shared VM structure. - * @param ppTemplate Where to store the template pointer on success. - * @param pfnCompleted The completion callback routine. - * @param pvUser2 The 2nd user argument for the callback. - * @param pszDesc Description. - */ VMMR3DECL(int) PDMR3AsyncCompletionTemplateCreateInternal(PVM pVM, PPPDMASYNCCOMPLETIONTEMPLATE ppTemplate, PFNPDMASYNCCOMPLETEINT pfnCompleted, void *pvUser2, const char *pszDesc); - -/** - * Destroys the specified async completion template. - * - * @returns VBox status codes: - * @retval VINF_SUCCESS on success. - * @retval VERR_PDM_ASYNC_TEMPLATE_BUSY if the template is still in use. - * - * @param pTemplate The template in question. - */ VMMR3DECL(int) PDMR3AsyncCompletionTemplateDestroy(PPDMASYNCCOMPLETIONTEMPLATE pTemplate); - -/** - * Destroys all the specified async completion templates for the given device instance. - * - * @returns VBox status codes: - * @retval VINF_SUCCESS on success. - * @retval VERR_PDM_ASYNC_TEMPLATE_BUSY if one or more of the templates are still in use. - * - * @param pVM Pointer to the shared VM structure. - * @param pDevIns The device instance. - */ -VMMR3DECL(int) PDMR3AsyncCompletionTemplateDestroyDevice(PVM pVM, PPDMDEVINS pDevIns); - -/** - * Destroys all the specified async completion templates for the given driver instance. - * - * @returns VBox status codes: - * @retval VINF_SUCCESS on success. - * @retval VERR_PDM_ASYNC_TEMPLATE_BUSY if one or more of the templates are still in use. - * - * @param pVM Pointer to the shared VM structure. - * @param pDrvIns The driver instance. - */ -VMMR3DECL(int) PDMR3AsyncCompletionTemplateDestroyDriver(PVM pVM, PPDMDRVINS pDrvIns); - -/** - * Destroys all the specified async completion templates for the given USB device instance. - * - * @returns VBox status codes: - * @retval VINF_SUCCESS on success. - * @retval VERR_PDM_ASYNC_TEMPLATE_BUSY if one or more of the templates are still in use. - * - * @param pVM Pointer to the shared VM structure. - * @param pUsbIns The USB device instance. - */ -VMMR3DECL(int) PDMR3AsyncCompletionTemplateDestroyUsb(PVM pVM, PPDMUSBINS pUsbIns); - - -/** - * Opens a file as an async completion endpoint. - * - * @returns VBox status code. - * @param ppEndpoint Where to store the opaque endpoint handle on success. - * @param pszFilename Path to the file which is to be opened. (UTF-8) - * @param fFlags Open flags, see grp_pdmacep_file_flags. - * @param pTemplate Handle to the completion callback template to use - * for this end point. - */ VMMR3DECL(int) PDMR3AsyncCompletionEpCreateForFile(PPPDMASYNCCOMPLETIONENDPOINT ppEndpoint, const char *pszFilename, uint32_t fFlags, PPDMASYNCCOMPLETIONTEMPLATE pTemplate); @@ -238,127 +124,21 @@ VMMR3DECL(int) PDMR3AsyncCompletionEpCreateForFile(PPPDMASYNCCOMPLETIONENDPOINT #define PDMACEP_FILE_FLAGS_HOST_CACHE_ENABLED RT_BIT_32(3) /** @} */ -/** - * Closes a endpoint waiting for any pending tasks to finish. - * - * @returns nothing. - * @param pEndpoint Handle of the endpoint. - */ VMMR3DECL(void) PDMR3AsyncCompletionEpClose(PPDMASYNCCOMPLETIONENDPOINT pEndpoint); - -/** - * Creates a read task on the given endpoint. - * - * @returns VBox status code. - * @param pEndpoint The file endpoint to read from. - * @param off Where to start reading from. - * @param paSegments Scatter gather list to store the data in. - * @param cSegments Number of segments in the list. - * @param cbRead The overall number of bytes to read. - * @param pvUser Opaque user data returned in the completion callback - * upon completion of the task. - * @param ppTask Where to store the task handle on success. - */ VMMR3DECL(int) PDMR3AsyncCompletionEpRead(PPDMASYNCCOMPLETIONENDPOINT pEndpoint, RTFOFF off, PCRTSGSEG paSegments, unsigned cSegments, size_t cbRead, void *pvUser, PPPDMASYNCCOMPLETIONTASK ppTask); - -/** - * Creates a write task on the given endpoint. - * - * @returns VBox status code. - * @param pEndpoint The file endpoint to write to. - * @param off Where to start writing at. - * @param paSegments Scatter gather list of the data to write. - * @param cSegments Number of segments in the list. - * @param cbWrite The overall number of bytes to write. - * @param pvUser Opaque user data returned in the completion callback - * upon completion of the task. - * @param ppTask Where to store the task handle on success. - */ VMMR3DECL(int) PDMR3AsyncCompletionEpWrite(PPDMASYNCCOMPLETIONENDPOINT pEndpoint, RTFOFF off, PCRTSGSEG paSegments, unsigned cSegments, size_t cbWrite, void *pvUser, PPPDMASYNCCOMPLETIONTASK ppTask); - -/** - * Creates a flush task on the given endpoint. - * - * Every read and write task initiated before the flush task is - * finished upon completion of this task. - * - * @returns VBox status code. - * @param pEndpoint The file endpoint to flush. - * @param pvUser Opaque user data returned in the completion callback - * upon completion of the task. - * @param ppTask Where to store the task handle on success. - */ -VMMR3DECL(int) PDMR3AsyncCompletionEpFlush(PPDMASYNCCOMPLETIONENDPOINT pEndpoint, - void *pvUser, - PPPDMASYNCCOMPLETIONTASK ppTask); - -/** - * Queries the size of an endpoint. - * Not that some endpoints may not support this and will return an error - * (sockets for example). - * - * @returns VBox status code. - * @retval VERR_NOT_SUPPORTED if the endpoint does not support this operation. - * @param pEndpoint The file endpoint. - * @param pcbSize Where to store the size of the endpoint. - */ -VMMR3DECL(int) PDMR3AsyncCompletionEpGetSize(PPDMASYNCCOMPLETIONENDPOINT pEndpoint, - uint64_t *pcbSize); - -/** - * Sets the size of an endpoint. - * Not that some endpoints may not support this and will return an error - * (sockets for example). - * - * @returns VBox status code. - * @retval VERR_NOT_SUPPORTED if the endpoint does not support this operation. - * @param pEndpoint The file endpoint. - * @param cbSize The size to set. - * - * @note PDMR3AsyncCompletionEpFlush should be called before this operation is executed. - */ -VMMR3DECL(int) PDMR3AsyncCompletionEpSetSize(PPDMASYNCCOMPLETIONENDPOINT pEndpoint, - uint64_t cbSize); - -/** - * Assigns or removes a bandwidth control manager to/from the endpoint. - * - * @returns VBox status code. - * @param pEndpoint The endpoint. - * @param pcszBwMgr The identifer of the new bandwidth manager to assign - * or NULL to remove the current one. - */ -VMMR3DECL(int) PDMR3AsyncCompletionEpSetBwMgr(PPDMASYNCCOMPLETIONENDPOINT pEndpoint, - const char *pcszBwMgr); - -/** - * Cancels an async completion task. - * - * If you want to use this method, you have to take great create to make sure - * you will never attempt cancel a task which has been completed. Since there is - * no reference counting or anything on the task it self, you have to serialize - * the cancelation and completion paths such that the aren't racing one another. - * - * @returns VBox status code - * @param pTask The Task to cancel. - */ +VMMR3DECL(int) PDMR3AsyncCompletionEpFlush(PPDMASYNCCOMPLETIONENDPOINT pEndpoint, void *pvUser, PPPDMASYNCCOMPLETIONTASK ppTask); +VMMR3DECL(int) PDMR3AsyncCompletionEpGetSize(PPDMASYNCCOMPLETIONENDPOINT pEndpoint, uint64_t *pcbSize); +VMMR3DECL(int) PDMR3AsyncCompletionEpSetSize(PPDMASYNCCOMPLETIONENDPOINT pEndpoint, uint64_t cbSize); +VMMR3DECL(int) PDMR3AsyncCompletionEpSetBwMgr(PPDMASYNCCOMPLETIONENDPOINT pEndpoint, const char *pszBwMgr); VMMR3DECL(int) PDMR3AsyncCompletionTaskCancel(PPDMASYNCCOMPLETIONTASK pTask); - -/** - * Changes the limit of a bandwidth manager for file endpoints to the given value. - * - * @returns VBox status code. - * @param pVM Pointer to the shared VM structure. - * @param pcszBwMgr The identifer of the bandwidth manager to change. - * @param cbMaxNew The new maximum for the bandwidth manager in bytes/sec. - */ -VMMR3DECL(int) PDMR3AsyncCompletionBwMgrSetMaxForFile(PVM pVM, const char *pcszBwMgr, uint32_t cbMaxNew); +VMMR3DECL(int) PDMR3AsyncCompletionBwMgrSetMaxForFile(PUVM pUVM, const char *pszBwMgr, uint32_t cbMaxNew); /** @} */ diff --git a/include/VBox/vmm/pdmblkcache.h b/include/VBox/vmm/pdmblkcache.h index fc92bc4f..14d85f67 100644 --- a/include/VBox/vmm/pdmblkcache.h +++ b/include/VBox/vmm/pdmblkcache.h @@ -3,7 +3,7 @@ */ /* - * Copyright (C) 2007-2010 Oracle Corporation + * Copyright (C) 2007-2011 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; diff --git a/include/VBox/vmm/pdmcardreaderinfs.h b/include/VBox/vmm/pdmcardreaderinfs.h index e1ad5a2d..7cb3ca75 100644 --- a/include/VBox/vmm/pdmcardreaderinfs.h +++ b/include/VBox/vmm/pdmcardreaderinfs.h @@ -1,5 +1,4 @@ /* $Id: pdmcardreaderinfs.h $ */ - /** @file * cardreaderinfs - interface between Usb Card Reader device and its driver. */ @@ -26,11 +25,10 @@ */ #ifndef ___VBox_vmm_pdmcardreaderinfs_h -# define ___VBox_vmm_pdmcardreaderinfs_h +#define ___VBox_vmm_pdmcardreaderinfs_h #include <VBox/types.h> -#define PDMICARDREADERDOWN_IID "78d65378-889c-4418-8bc2-7a89a5af2817" typedef struct PDMICARDREADER_IO_REQUEST { @@ -49,41 +47,41 @@ typedef struct PDMICARDREADER_READERSTATE } PDMICARDREADER_READERSTATE; +#define PDMICARDREADERDOWN_IID "78d65378-889c-4418-8bc2-7a89a5af2817" typedef struct PDMICARDREADERDOWN PDMICARDREADERDOWN; typedef PDMICARDREADERDOWN *PPDMICARDREADERDOWN; struct PDMICARDREADERDOWN { - DECLR3CALLBACKMEMBER(int, pfnCardReaderDownEstablishContext,(PPDMICARDREADERDOWN pInterface)); - DECLR3CALLBACKMEMBER(int, pfnCardReaderDownConnect,(PPDMICARDREADERDOWN pInterface, void *pvUser, const char *pszCardReaderName, - uint32_t u32ShareMode, uint32_t u32PreferredProtocols)); - DECLR3CALLBACKMEMBER(int, pfnCardReaderDownDisconnect,(PPDMICARDREADERDOWN pInterface, void *pvUser, - uint32_t u32Disposition)); - DECLR3CALLBACKMEMBER(int, pfnCardReaderDownStatus,(PPDMICARDREADERDOWN pInterface, void *pvUser, - uint32_t cchReaderName, uint32_t cbAtrLen)); - DECLR3CALLBACKMEMBER(int, pfnCardReaderDownReleaseContext,(PPDMICARDREADERDOWN pInterface, void *pvUser)); - DECLR3CALLBACKMEMBER(int, pfnCardReaderDownGetStatusChange,(PPDMICARDREADERDOWN pInterface, void *pvUser, - uint32_t u32Timeout, PDMICARDREADER_READERSTATE *paReaderStats, uint32_t cReaderStats)); - DECLR3CALLBACKMEMBER(int, pfnCardReaderDownBeginTransaction,(PPDMICARDREADERDOWN pInterface, void *pvUser)); - DECLR3CALLBACKMEMBER(int, pfnCardReaderDownEndTransaction,(PPDMICARDREADERDOWN pInterface, void *pvUser, - uint32_t u32Disposition)); - DECLR3CALLBACKMEMBER(int, pfnCardReaderDownTransmit,(PPDMICARDREADERDOWN pInterface, void *pvUser, - const PDMICARDREADER_IO_REQUEST *pioSendRequest, - const uint8_t *pu8SendBuffer, uint32_t cbSendBuffer, uint32_t cbRecvBuffer)); + DECLR3CALLBACKMEMBER(int, pfnEstablishContext,(PPDMICARDREADERDOWN pInterface)); + DECLR3CALLBACKMEMBER(int, pfnConnect,(PPDMICARDREADERDOWN pInterface, void *pvUser, const char *pszCardReaderName, + uint32_t u32ShareMode, uint32_t u32PreferredProtocols)); + DECLR3CALLBACKMEMBER(int, pfnDisconnect,(PPDMICARDREADERDOWN pInterface, void *pvUser, uint32_t u32Disposition)); + DECLR3CALLBACKMEMBER(int, pfnStatus,(PPDMICARDREADERDOWN pInterface, void *pvUser, uint32_t cchReaderName, uint32_t cbAtrLen)); + DECLR3CALLBACKMEMBER(int, pfnReleaseContext,(PPDMICARDREADERDOWN pInterface, void *pvUser)); + DECLR3CALLBACKMEMBER(int, pfnGetStatusChange,(PPDMICARDREADERDOWN pInterface, void *pvUser, uint32_t u32Timeout, + PDMICARDREADER_READERSTATE *paReaderStats, uint32_t cReaderStats)); + DECLR3CALLBACKMEMBER(int, pfnBeginTransaction,(PPDMICARDREADERDOWN pInterface, void *pvUser)); + DECLR3CALLBACKMEMBER(int, pfnEndTransaction,(PPDMICARDREADERDOWN pInterface, void *pvUser, uint32_t u32Disposition)); + DECLR3CALLBACKMEMBER(int, pfnTransmit,(PPDMICARDREADERDOWN pInterface, void *pvUser, + const PDMICARDREADER_IO_REQUEST *pioSendRequest, + const uint8_t *pu8SendBuffer, uint32_t cbSendBuffer, uint32_t cbRecvBuffer)); /** * Up level provides pvInBuffer of cbInBuffer bytes to call SCardControl, also it specify bytes it expects to receive - * @note: device/driver implementation should copy buffers before execution in async mode, and both layers shouldn't - * expect permanent storage for the buffer. + * @note Device/driver implementation should copy buffers before execution in + * async mode, and both layers shouldn't expect permanent storage for the + * buffer. */ - DECLR3CALLBACKMEMBER(int, pfnCardReaderDownControl,(PPDMICARDREADERDOWN pInterface, void *pvUser, - uint32_t u32ControlCode, const void *pvInBuffer, uint32_t cbInBuffer, uint32_t cbOutBuffer)); + DECLR3CALLBACKMEMBER(int, pfnControl,(PPDMICARDREADERDOWN pInterface, void *pvUser, + uint32_t u32ControlCode, const void *pvInBuffer, + uint32_t cbInBuffer, uint32_t cbOutBuffer)); /** * This function ask driver to provide attribute (dwAttribId) and provide limit (cbAttrib) of buffer size for attribute value, * Callback UpGetAttrib returns buffer containing the value and altered size of the buffer. */ - DECLR3CALLBACKMEMBER(int, pfnCardReaderDownGetAttr,(PPDMICARDREADERDOWN pInterface, void *pvUser, - uint32_t u32AttribId, uint32_t cbAttrib)); - DECLR3CALLBACKMEMBER(int, pfnCardReaderDownSetAttr,(PPDMICARDREADERDOWN pInterface, void *pvUser, - uint32_t u32AttribId, const void *pvAttrib, uint32_t cbAttrib)); + DECLR3CALLBACKMEMBER(int, pfnGetAttr,(PPDMICARDREADERDOWN pInterface, void *pvUser, + uint32_t u32AttribId, uint32_t cbAttrib)); + DECLR3CALLBACKMEMBER(int, pfnSetAttr,(PPDMICARDREADERDOWN pInterface, void *pvUser, + uint32_t u32AttribId, const void *pvAttrib, uint32_t cbAttrib)); }; #define PDMICARDREADERUP_IID "c0d7498e-0635-48ca-aab1-b11b6a55cf7d" @@ -91,26 +89,27 @@ typedef struct PDMICARDREADERUP PDMICARDREADERUP; typedef PDMICARDREADERUP *PPDMICARDREADERUP; struct PDMICARDREADERUP { - DECLR3CALLBACKMEMBER(int, pfnCardReaderUpEstablishContext,(PPDMICARDREADERUP pInterface, int32_t lSCardRc)); - DECLR3CALLBACKMEMBER(int, pfnCardReaderUpStatus,(PPDMICARDREADERUP pInterface, void *pvUser, int32_t lSCardRc, - char *pszReaderName, uint32_t cchReaderName, uint32_t u32CardState, - uint32_t u32Protocol, uint8_t *pu8Atr, uint32_t cbAtr)); - DECLR3CALLBACKMEMBER(int, pfnCardReaderUpConnect,(PPDMICARDREADERUP pInterface, void *pvUser, int32_t lSCardRc, - uint32_t u32ActiveProtocol)); - DECLR3CALLBACKMEMBER(int, pfnCardReaderUpDisconnect,(PPDMICARDREADERUP pInterface, void *pvUser, int32_t lSCardRc)); - DECLR3CALLBACKMEMBER(int, pfnCardReaderUpSetStatusChange,(PPDMICARDREADERUP pInterface, void *pvUser, int32_t lSCardRc, - PDMICARDREADER_READERSTATE *paReaderStats, uint32_t cReaderStats)); - DECLR3CALLBACKMEMBER(int, pfnCardReaderUpBeginTransaction,(PPDMICARDREADERUP pInterface, void *pvUser, int32_t lSCardRc)); - DECLR3CALLBACKMEMBER(int, pfnCardReaderUpEndTransaction,(PPDMICARDREADERUP pInterface, void *pvUser, int32_t lSCardRc)); + DECLR3CALLBACKMEMBER(int, pfnEstablishContext,(PPDMICARDREADERUP pInterface, int32_t lSCardRc)); + DECLR3CALLBACKMEMBER(int, pfnStatus,(PPDMICARDREADERUP pInterface, void *pvUser, int32_t lSCardRc, + char *pszReaderName, uint32_t cchReaderName, uint32_t u32CardState, + uint32_t u32Protocol, uint8_t *pu8Atr, uint32_t cbAtr)); + DECLR3CALLBACKMEMBER(int, pfnConnect,(PPDMICARDREADERUP pInterface, void *pvUser, int32_t lSCardRc, + uint32_t u32ActiveProtocol)); + DECLR3CALLBACKMEMBER(int, pfnDisconnect,(PPDMICARDREADERUP pInterface, void *pvUser, int32_t lSCardRc)); + DECLR3CALLBACKMEMBER(int, pfnSetStatusChange,(PPDMICARDREADERUP pInterface, void *pvUser, int32_t lSCardRc, + PDMICARDREADER_READERSTATE *paReaderStats, uint32_t cReaderStats)); + DECLR3CALLBACKMEMBER(int, pfnBeginTransaction,(PPDMICARDREADERUP pInterface, void *pvUser, int32_t lSCardRc)); + DECLR3CALLBACKMEMBER(int, pfnEndTransaction,(PPDMICARDREADERUP pInterface, void *pvUser, int32_t lSCardRc)); /* Note: pioRecvPci stack variable */ - DECLR3CALLBACKMEMBER(int, pfnCardReaderUpTransmit,(PPDMICARDREADERUP pInterface, void *pvUser, int32_t lSCardRc, - const PDMICARDREADER_IO_REQUEST *pioRecvPci, uint8_t *pu8RecvBuffer, uint32_t cbRecvBuffer)); - DECLR3CALLBACKMEMBER(int, pfnCardReaderUpControl,(PPDMICARDREADERUP pInterface, void *pvUser, int32_t lSCardRc, - uint32_t u32ControlCode, void *pvOutBuffer, uint32_t cbOutBuffer)); - DECLR3CALLBACKMEMBER(int, pfnCardReaderUpGetAttrib,(PPDMICARDREADERUP pInterface, void *pvUser, int32_t lSCardRc, - uint32_t u32AttribId, void *pvAttrib, uint32_t cbAttrib)); - DECLR3CALLBACKMEMBER(int, pfnCardReaderUpSetAttrib,(PPDMICARDREADERUP pInterface, void *pvUser, int32_t lSCardRc, - uint32_t u32AttribId)); + DECLR3CALLBACKMEMBER(int, pfnTransmit,(PPDMICARDREADERUP pInterface, void *pvUser, int32_t lSCardRc, + const PDMICARDREADER_IO_REQUEST *pioRecvPci, + uint8_t *pu8RecvBuffer, uint32_t cbRecvBuffer)); + DECLR3CALLBACKMEMBER(int, pfnControl,(PPDMICARDREADERUP pInterface, void *pvUser, int32_t lSCardRc, + uint32_t u32ControlCode, void *pvOutBuffer, uint32_t cbOutBuffer)); + DECLR3CALLBACKMEMBER(int, pfnGetAttrib,(PPDMICARDREADERUP pInterface, void *pvUser, int32_t lSCardRc, + uint32_t u32AttribId, void *pvAttrib, uint32_t cbAttrib)); + DECLR3CALLBACKMEMBER(int, pfnSetAttrib,(PPDMICARDREADERUP pInterface, void *pvUser, int32_t lSCardRc, uint32_t u32AttribId)); }; #endif + diff --git a/include/VBox/vmm/pdmcommon.h b/include/VBox/vmm/pdmcommon.h index c4e1be26..d62210a0 100644 --- a/include/VBox/vmm/pdmcommon.h +++ b/include/VBox/vmm/pdmcommon.h @@ -3,7 +3,7 @@ */ /* - * Copyright (C) 2006-2010 Oracle Corporation + * Copyright (C) 2006-2013 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -109,7 +109,7 @@ typedef FNPDMUSBASYNCNOTIFY *PFNPDMUSBASYNCNOTIFY; * @returns true if done, false if more work to be done. * * @param pDevIns The device instance. - * + * @remarks The caller will enter the device critical section. * @thread EMT(0) */ typedef DECLCALLBACK(bool) FNPDMDEVASYNCNOTIFY(PPDMDEVINS pDevIns); diff --git a/include/VBox/vmm/pdmcritsect.h b/include/VBox/vmm/pdmcritsect.h index 02d7924d..0895b52b 100644 --- a/include/VBox/vmm/pdmcritsect.h +++ b/include/VBox/vmm/pdmcritsect.h @@ -3,7 +3,7 @@ */ /* - * Copyright (C) 2006-2010 Oracle Corporation + * Copyright (C) 2006-2011 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -51,26 +51,31 @@ typedef union PDMCRITSECT #endif } PDMCRITSECT; +VMMR3_INT_DECL(int) PDMR3CritSectBothTerm(PVM pVM); +VMMR3_INT_DECL(void) PDMR3CritSectLeaveAll(PVM pVM); +VMM_INT_DECL(void) PDMCritSectBothFF(PVMCPU pVCpu); + + +VMMR3DECL(uint32_t) PDMR3CritSectCountOwned(PVM pVM, char *pszNames, size_t cbNames); + VMMR3DECL(int) PDMR3CritSectInit(PVM pVM, PPDMCRITSECT pCritSect, RT_SRC_POS_DECL, const char *pszNameFmt, ...); +VMMR3DECL(int) PDMR3CritSectEnterEx(PPDMCRITSECT pCritSect, bool fCallRing3); +VMMR3DECL(bool) PDMR3CritSectYield(PPDMCRITSECT pCritSect); +VMMR3DECL(const char *) PDMR3CritSectName(PCPDMCRITSECT pCritSect); +VMMR3DECL(int) PDMR3CritSectScheduleExitEvent(PPDMCRITSECT pCritSect, RTSEMEVENT EventToSignal); +VMMR3DECL(int) PDMR3CritSectDelete(PPDMCRITSECT pCritSect); + VMMDECL(int) PDMCritSectEnter(PPDMCRITSECT pCritSect, int rcBusy); VMMDECL(int) PDMCritSectEnterDebug(PPDMCRITSECT pCritSect, int rcBusy, RTHCUINTPTR uId, RT_SRC_POS_DECL); VMMDECL(int) PDMCritSectTryEnter(PPDMCRITSECT pCritSect); VMMDECL(int) PDMCritSectTryEnterDebug(PPDMCRITSECT pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL); -VMMR3DECL(int) PDMR3CritSectEnterEx(PPDMCRITSECT pCritSect, bool fCallRing3); VMMDECL(int) PDMCritSectLeave(PPDMCRITSECT pCritSect); + VMMDECL(bool) PDMCritSectIsOwner(PCPDMCRITSECT pCritSect); VMMDECL(bool) PDMCritSectIsOwnerEx(PCPDMCRITSECT pCritSect, PVMCPU pVCpu); VMMDECL(bool) PDMCritSectIsInitialized(PCPDMCRITSECT pCritSect); VMMDECL(bool) PDMCritSectHasWaiters(PCPDMCRITSECT pCritSect); VMMDECL(uint32_t) PDMCritSectGetRecursion(PCPDMCRITSECT pCritSect); -VMMR3DECL(bool) PDMR3CritSectYield(PPDMCRITSECT pCritSect); -VMMR3DECL(const char *) PDMR3CritSectName(PCPDMCRITSECT pCritSect); -VMMR3DECL(int) PDMR3CritSectScheduleExitEvent(PPDMCRITSECT pCritSect, RTSEMEVENT EventToSignal); -VMMR3DECL(int) PDMR3CritSectDelete(PPDMCRITSECT pCritSect); -VMMDECL(int) PDMR3CritSectTerm(PVM pVM); -VMMDECL(void) PDMCritSectFF(PVMCPU pVCpu); -VMMR3DECL(uint32_t) PDMR3CritSectCountOwned(PVM pVM, char *pszNames, size_t cbNames); -VMMR3DECL(void) PDMR3CritSectLeaveAll(PVM pVM); VMMR3DECL(PPDMCRITSECT) PDMR3CritSectGetNop(PVM pVM); VMMR3DECL(R0PTRTYPE(PPDMCRITSECT)) PDMR3CritSectGetNopR0(PVM pVM); diff --git a/include/VBox/vmm/pdmcritsectrw.h b/include/VBox/vmm/pdmcritsectrw.h new file mode 100644 index 00000000..9c922017 --- /dev/null +++ b/include/VBox/vmm/pdmcritsectrw.h @@ -0,0 +1,97 @@ +/** @file + * PDM - Pluggable Device Manager, Read/Write Critical Section. + */ + +/* + * Copyright (C) 2006-2013 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL) only, as it comes in the "COPYING.CDDL" file of the + * VirtualBox OSE distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + */ + +#ifndef ___VBox_vmm_pdmcritsectrw_h +#define ___VBox_vmm_pdmcritsectrw_h + +#include <VBox/types.h> + + +RT_C_DECLS_BEGIN + +/** @defgroup grp_pdm_critsectrw The PDM Read/Write Critical Section API + * @ingroup grp_pdm + * @{ + */ + +/** + * A PDM read/write critical section. + * Initialize using PDMDRVHLP::pfnCritSectRwInit(). + */ +typedef union PDMCRITSECTRW +{ + /** Padding. */ + uint8_t padding[HC_ARCH_BITS == 32 ? 0xc0 : 0x100]; +#ifdef PDMCRITSECTRWINT_DECLARED + /** The internal structure (not normally visible). */ + struct PDMCRITSECTRWINT s; +#endif +} PDMCRITSECTRW; + +VMMR3DECL(int) PDMR3CritSectRwInit(PVM pVM, PPDMCRITSECTRW pCritSect, RT_SRC_POS_DECL, const char *pszNameFmt, ...); +VMMR3DECL(int) PDMR3CritSectRwDelete(PPDMCRITSECTRW pCritSect); +VMMR3DECL(const char *) PDMR3CritSectRwName(PCPDMCRITSECTRW pCritSect); +VMMR3DECL(int) PDMR3CritSectRwEnterSharedEx(PPDMCRITSECTRW pThis, bool fCallRing3); +VMMR3DECL(int) PDMR3CritSectRwEnterExclEx(PPDMCRITSECTRW pThis, bool fCallRing3); + +VMMDECL(int) PDMCritSectRwEnterShared(PPDMCRITSECTRW pCritSect, int rcBusy); +VMMDECL(int) PDMCritSectRwEnterSharedDebug(PPDMCRITSECTRW pCritSect, int rcBusy, RTHCUINTPTR uId, RT_SRC_POS_DECL); +VMMDECL(int) PDMCritSectRwTryEnterShared(PPDMCRITSECTRW pCritSect); +VMMDECL(int) PDMCritSectRwTryEnterSharedDebug(PPDMCRITSECTRW pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL); +VMMDECL(int) PDMCritSectRwLeaveShared(PPDMCRITSECTRW pCritSect); +VMMDECL(int) PDMCritSectRwEnterExcl(PPDMCRITSECTRW pCritSect, int rcBusy); +VMMDECL(int) PDMCritSectRwEnterExclDebug(PPDMCRITSECTRW pCritSect, int rcBusy, RTHCUINTPTR uId, RT_SRC_POS_DECL); +VMMDECL(int) PDMCritSectRwTryEnterExcl(PPDMCRITSECTRW pCritSect); +VMMDECL(int) PDMCritSectRwTryEnterExclDebug(PPDMCRITSECTRW pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL); +VMMDECL(int) PDMCritSectRwLeaveExcl(PPDMCRITSECTRW pCritSect); + +VMMDECL(bool) PDMCritSectRwIsWriteOwner(PPDMCRITSECTRW pCritSect); +VMMDECL(bool) PDMCritSectRwIsReadOwner(PPDMCRITSECTRW pCritSect, bool fWannaHear); +VMMDECL(uint32_t) PDMCritSectRwGetWriteRecursion(PPDMCRITSECTRW pCritSect); +VMMDECL(uint32_t) PDMCritSectRwGetWriterReadRecursion(PPDMCRITSECTRW pCritSect); +VMMDECL(uint32_t) PDMCritSectRwGetReadCount(PPDMCRITSECTRW pCritSect); +VMMDECL(bool) PDMCritSectRwIsInitialized(PCPDMCRITSECTRW pCritSect); + +/* Lock strict build: Remap the three enter calls to the debug versions. */ +#ifdef VBOX_STRICT +# ifdef ___iprt_asm_h +# define PDMCritSectRwEnterExcl(pCritSect, rcBusy) PDMCritSectRwEnterExclDebug(pCritSect, rcBusy, (uintptr_t)ASMReturnAddress(), RT_SRC_POS) +# define PDMCritSectRwTryEnterExcl(pCritSect) PDMCritSectRwTryEnterExclDebug(pCritSect, (uintptr_t)ASMReturnAddress(), RT_SRC_POS) +# define PDMCritSectRwEnterShared(pCritSect, rcBusy) PDMCritSectRwEnterSharedDebug(pCritSect, rcBusy, (uintptr_t)ASMReturnAddress(), RT_SRC_POS) +# define PDMCritSectRwTryEnterShared(pCritSect) PDMCritSectRwTryEnterSharedDebug(pCritSect, (uintptr_t)ASMReturnAddress(), RT_SRC_POS) +# else +# define PDMCritSectRwEnterExcl(pCritSect, rcBusy) PDMCritSectRwEnterExclDebug(pCritSect, rcBusy, 0, RT_SRC_POS) +# define PDMCritSectRwTryEnterExcl(pCritSect) PDMCritSectRwTryEnterExclDebug(pCritSect, 0, RT_SRC_POS) +# define PDMCritSectRwEnterShared(pCritSect, rcBusy) PDMCritSectRwEnterSharedDebug(pCritSect, rcBusy, 0, RT_SRC_POS) +# define PDMCritSectRwTryEnterShared(pCritSect) PDMCritSectRwTryEnterSharedDebug(pCritSect, 0, RT_SRC_POS) +# endif +#endif + +/** @} */ + +RT_C_DECLS_END + +#endif + diff --git a/include/VBox/vmm/pdmdev.h b/include/VBox/vmm/pdmdev.h index 892ed590..7a964b74 100644 --- a/include/VBox/vmm/pdmdev.h +++ b/include/VBox/vmm/pdmdev.h @@ -3,7 +3,7 @@ */ /* - * Copyright (C) 2006-2011 Oracle Corporation + * Copyright (C) 2006-2013 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -39,6 +39,7 @@ #include <VBox/vmm/dbgf.h> #include <VBox/err.h> #include <VBox/pci.h> +#include <VBox/sup.h> #include <iprt/stdarg.h> @@ -108,30 +109,6 @@ typedef DECLCALLBACK(void) FNPDMDEVRELOCATE(PPDMDEVINS pDevIns, RTGCINTPTR offDe typedef FNPDMDEVRELOCATE *PFNPDMDEVRELOCATE; /** - * Device I/O Control interface. - * - * This is used by external components, such as the COM interface, to - * communicate with devices using a class wide interface or a device - * specific interface. - * - * @returns VBox status code. - * @param pDevIns Pointer to the device instance. - * @param uFunction Function to perform. - * @param pvIn Pointer to input data. - * @param cbIn Size of input data. - * @param pvOut Pointer to output data. - * @param cbOut Size of output data. - * @param pcbOut Where to store the actual size of the output data. - * - * @remarks Not used. - */ -typedef DECLCALLBACK(int) FNPDMDEVIOCTL(PPDMDEVINS pDevIns, uint32_t uFunction, - void *pvIn, uint32_t cbIn, - void *pvOut, uint32_t cbOut, PRTUINT pcbOut); -/** Pointer to a FNPDMDEVIOCTL() function. */ -typedef FNPDMDEVIOCTL *PFNPDMDEVIOCTL; - -/** * Power On notification. * * @returns VBox status. @@ -185,7 +162,7 @@ typedef FNPDMDEVRESUME *PFNPDMDEVRESUME; * * This is only called when the VMR3PowerOff call is made on a running VM. This * means that there is no notification if the VM was suspended before being - * powered of. There will also be no callback when hot plugging devices. + * powered off. There will also be no callback when hot plugging devices. * * @param pDevIns The device instance data. * @thread EMT(0) @@ -264,6 +241,21 @@ typedef DECLCALLBACK(int) FNPDMDEVINITCOMPLETE(PPDMDEVINS pDevIns); typedef FNPDMDEVINITCOMPLETE *PFNPDMDEVINITCOMPLETE; +/** + * The context of a pfnMemSetup call. + */ +typedef enum PDMDEVMEMSETUPCTX +{ + /** Invalid zero value. */ + PDMDEVMEMSETUPCTX_INVALID = 0, + /** After construction. */ + PDMDEVMEMSETUPCTX_AFTER_CONSTRUCTION, + /** After reset. */ + PDMDEVMEMSETUPCTX_AFTER_RESET, + /** Type size hack. */ + PDMDEVMEMSETUPCTX_32BIT_HACK = 0x7fffffff +} PDMDEVMEMSETUPCTX; + /** * PDM Device Registration Structure. @@ -304,9 +296,16 @@ typedef struct PDMDEVREG /** Relocation command - optional. * Critical section NOT entered. */ PFNPDMDEVRELOCATE pfnRelocate; - /** I/O Control interface - optional. - * Not used. */ - PFNPDMDEVIOCTL pfnIOCtl; + + /** + * Memory setup callback. + * + * @param pDevIns The device instance data. + * @param enmCtx Indicates the context of the call. + * @remarks The critical section is entered prior to calling this method. + */ + DECLR3CALLBACKMEMBER(void, pfnMemSetup, (PPDMDEVINS pDevIns, PDMDEVMEMSETUPCTX enmCtx)); + /** Power on notification - optional. * Critical section is entered. */ PFNPDMDEVPOWERON pfnPowerOn; @@ -345,7 +344,7 @@ typedef PDMDEVREG *PPDMDEVREG; typedef PDMDEVREG const *PCPDMDEVREG; /** Current DEVREG version number. */ -#define PDM_DEVREG_VERSION PDM_VERSION_MAKE(0xffff, 1, 0) +#define PDM_DEVREG_VERSION PDM_VERSION_MAKE(0xffff, 2, 0) /** PDM Device Flags. * @{ */ @@ -503,6 +502,7 @@ typedef struct PDMPCIBUSREG * @param pszName Pointer to device name (permanent, readonly). For debugging, not unique. * @param iDev The device number ((dev << 3) | function) the device should have on the bus. * If negative, the pci bus device will assign one. + * @remarks Caller enters the PDM critical section. */ DECLR3CALLBACKMEMBER(int, pfnRegisterR3,(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, const char *pszName, int iDev)); @@ -513,6 +513,7 @@ typedef struct PDMPCIBUSREG * @param pDevIns Device instance of the PCI Bus. * @param pPciDev The PCI device structure. * @param pMsiReg MSI registration structure + * @remarks Caller enters the PDM critical section. */ DECLR3CALLBACKMEMBER(int, pfnRegisterMsiR3,(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, PPDMMSIREG pMsiReg)); @@ -526,6 +527,7 @@ typedef struct PDMPCIBUSREG * @param cbRegion Size of the region. * @param iType PCI_ADDRESS_SPACE_MEM, PCI_ADDRESS_SPACE_IO or PCI_ADDRESS_SPACE_MEM_PREFETCH. * @param pfnCallback Callback for doing the mapping. + * @remarks Caller enters the PDM critical section. */ DECLR3CALLBACKMEMBER(int, pfnIORegionRegisterR3,(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, int iRegion, uint32_t cbRegion, PCIADDRESSSPACE enmType, PFNPCIIOREGIONMAP pfnCallback)); @@ -542,6 +544,7 @@ typedef struct PDMPCIBUSREG * @param pfnWriteOld Pointer to function pointer which will receive the old (default) * PCI config write function. This way, user can decide when (and if) * to call default PCI config write function. Can be NULL. + * @remarks Caller enters the PDM critical section. * @thread EMT */ DECLR3CALLBACKMEMBER(void, pfnSetConfigCallbacksR3,(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, PFNPCICONFIGREAD pfnRead, PPFNPCICONFIGREAD ppfnReadOld, @@ -555,36 +558,18 @@ typedef struct PDMPCIBUSREG * @param iIrq IRQ number to set. * @param iLevel IRQ level. See the PDM_IRQ_LEVEL_* \#defines. * @param uTagSrc The IRQ tag and source (for tracing). + * @remarks Caller enters the PDM critical section. */ DECLR3CALLBACKMEMBER(void, pfnSetIrqR3,(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, int iIrq, int iLevel, uint32_t uTagSrc)); /** - * Saves a state of the PCI device. - * - * @returns VBox status code. - * @param pDevIns Device instance of the PCI Bus. - * @param pPciDev Pointer to PCI device. - * @param pSSMHandle The handle to save the state to. - */ - DECLR3CALLBACKMEMBER(int, pfnSaveExecR3,(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, PSSMHANDLE pSSMHandle)); - - /** - * Loads a saved PCI device state. - * - * @returns VBox status code. - * @param pDevIns Device instance of the PCI Bus. - * @param pPciDev Pointer to PCI device. - * @param pSSMHandle The handle to the saved state. - */ - DECLR3CALLBACKMEMBER(int, pfnLoadExecR3,(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, PSSMHANDLE pSSMHandle)); - - /** * Called to perform the job of the bios. * This is only called for the first PCI Bus - it is expected to * service all the PCI buses. * * @returns VBox status. * @param pDevIns Device instance of the first bus. + * @remarks Caller enters the PDM critical section. */ DECLR3CALLBACKMEMBER(int, pfnFakePCIBIOSR3,(PPDMDEVINS pDevIns)); @@ -599,7 +584,7 @@ typedef struct PDMPCIBUSREG typedef PDMPCIBUSREG *PPDMPCIBUSREG; /** Current PDMPCIBUSREG version number. */ -#define PDM_PCIBUSREG_VERSION PDM_VERSION_MAKE(0xfffe, 3, 0) +#define PDM_PCIBUSREG_VERSION PDM_VERSION_MAKE(0xfffe, 4, 0) /** * PCI Bus RC helpers. @@ -858,6 +843,7 @@ typedef struct PDMPICREG * @param iIrq IRQ number to set. * @param iLevel IRQ level. See the PDM_IRQ_LEVEL_* \#defines. * @param uTagSrc The IRQ tag and source (for tracing). + * @remarks Caller enters the PDM critical section. */ DECLR3CALLBACKMEMBER(void, pfnSetIrqR3,(PPDMDEVINS pDevIns, int iIrq, int iLevel, uint32_t uTagSrc)); @@ -867,6 +853,7 @@ typedef struct PDMPICREG * @returns Pending interrupt number. * @param pDevIns Device instance of the PIC. * @param puTagSrc Where to return the IRQ tag and source. + * @remarks Caller enters the PDM critical section. */ DECLR3CALLBACKMEMBER(int, pfnGetInterruptR3,(PPDMDEVINS pDevIns, uint32_t *puTagSrc)); @@ -1077,40 +1064,52 @@ typedef struct PDMAPICREG * * @returns Pending interrupt number. * @param pDevIns Device instance of the APIC. + * @param idCpu The VCPU Id. * @param puTagSrc Where to return the tag source. + * @remarks Caller enters the PDM critical section */ - DECLR3CALLBACKMEMBER(int, pfnGetInterruptR3,(PPDMDEVINS pDevIns, uint32_t *puTagSrc)); + DECLR3CALLBACKMEMBER(int, pfnGetInterruptR3,(PPDMDEVINS pDevIns, VMCPUID idCpu, uint32_t *puTagSrc)); /** * Check if the APIC has a pending interrupt/if a TPR change would active one * * @returns Pending interrupt yes/no * @param pDevIns Device instance of the APIC. + * @param idCpu The VCPU Id. + * @param pu8PendingIrq Where to store the highest priority pending IRQ + * (optional, can be NULL). + * @remarks Unlike the other callbacks, the PDM lock may not always be entered + * prior to calling this method. */ - DECLR3CALLBACKMEMBER(bool, pfnHasPendingIrqR3,(PPDMDEVINS pDevIns)); + DECLR3CALLBACKMEMBER(bool, pfnHasPendingIrqR3,(PPDMDEVINS pDevIns, VMCPUID idCpu, uint8_t *pu8PendingIrq)); /** * Set the APIC base. * * @param pDevIns Device instance of the APIC. + * @param idCpu The VCPU Id. * @param u64Base The new base. + * @remarks Caller enters the PDM critical section. */ - DECLR3CALLBACKMEMBER(void, pfnSetBaseR3,(PPDMDEVINS pDevIns, uint64_t u64Base)); + DECLR3CALLBACKMEMBER(void, pfnSetBaseR3,(PPDMDEVINS pDevIns, VMCPUID idCpu, uint64_t u64Base)); /** * Get the APIC base. * * @returns Current base. * @param pDevIns Device instance of the APIC. + * @param idCpu The VCPU Id. + * @remarks Caller enters the PDM critical section. */ - DECLR3CALLBACKMEMBER(uint64_t, pfnGetBaseR3,(PPDMDEVINS pDevIns)); + DECLR3CALLBACKMEMBER(uint64_t, pfnGetBaseR3,(PPDMDEVINS pDevIns, VMCPUID idCpu)); /** * Set the TPR (task priority register). * * @param pDevIns Device instance of the APIC. - * @param idCpu VCPU id + * @param idCpu The VCPU id. * @param u8TPR The new TPR. + * @remarks Caller enters the PDM critical section. */ DECLR3CALLBACKMEMBER(void, pfnSetTPRR3,(PPDMDEVINS pDevIns, VMCPUID idCpu, uint8_t u8TPR)); @@ -1120,6 +1119,7 @@ typedef struct PDMAPICREG * @returns The current TPR. * @param pDevIns Device instance of the APIC. * @param idCpu VCPU id + * @remarks Caller enters the PDM critical section. */ DECLR3CALLBACKMEMBER(uint8_t, pfnGetTPRR3,(PPDMDEVINS pDevIns, VMCPUID idCpu)); @@ -1169,6 +1169,7 @@ typedef struct PDMAPICREG * @param u8Polarity See APIC implementation. * @param u8TriggerMode See APIC implementation. * @param uTagSrc The IRQ tag and source (for tracing). + * @remarks Caller enters the PDM critical section */ DECLR3CALLBACKMEMBER(int, pfnBusDeliverR3,(PPDMDEVINS pDevIns, uint8_t u8Dest, uint8_t u8DestMode, uint8_t u8DeliveryMode, uint8_t iVector, uint8_t u8Polarity, uint8_t u8TriggerMode, uint32_t uTagSrc)); @@ -1184,6 +1185,7 @@ typedef struct PDMAPICREG * @param u8Pin Local pin number (0 or 1 for current CPUs). * @param u8Level The level. * @param uTagSrc The IRQ tag and source (for tracing). + * @remarks Caller enters the PDM critical section */ DECLR3CALLBACKMEMBER(int, pfnLocalInterruptR3,(PPDMDEVINS pDevIns, uint8_t u8Pin, uint8_t u8Level)); @@ -1572,6 +1574,7 @@ typedef struct PDMIOAPICREG * @param iIrq IRQ number to set. * @param iLevel IRQ level. See the PDM_IRQ_LEVEL_* \#defines. * @param uTagSrc The IRQ tag and source (for tracing). + * @remarks Caller enters the PDM critical section */ DECLR3CALLBACKMEMBER(void, pfnSetIrqR3,(PPDMDEVINS pDevIns, int iIrq, int iLevel, uint32_t uTagSrc)); @@ -1588,6 +1591,7 @@ typedef struct PDMIOAPICREG * @param GCPhys Request address. * @param uValue Request value. * @param uTagSrc The IRQ tag and source (for tracing). + * @remarks Caller enters the PDM critical section */ DECLR3CALLBACKMEMBER(void, pfnSendMsiR3,(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, uint32_t uValue, uint32_t uTagSrc)); @@ -2017,11 +2021,12 @@ typedef R3PTRTYPE(const PDMPCIRAWHLPR3 *) PCPDMPCIRAWHLPR3; * DMA Transfer Handler. * * @returns Number of bytes transferred. - * @param pDevIns Device instance of the DMA. - * @param pvUser User pointer. - * @param uChannel Channel number. - * @param off DMA position. - * @param cb Block size. + * @param pDevIns Device instance of the DMA. + * @param pvUser User pointer. + * @param uChannel Channel number. + * @param off DMA position. + * @param cb Block size. + * @remarks The device lock is not taken, however, the DMA device lock is held. */ typedef DECLCALLBACK(uint32_t) FNDMATRANSFERHANDLER(PPDMDEVINS pDevIns, void *pvUser, unsigned uChannel, uint32_t off, uint32_t cb); /** Pointer to a FNDMATRANSFERHANDLER(). */ @@ -2040,6 +2045,7 @@ typedef struct PDMDMAREG * * @returns A more work indiciator. I.e. 'true' if there is more to be done, and 'false' if all is done. * @param pDevIns Device instance of the DMAC. + * @remarks No locks held, called on EMT(0) as a form of serialization. */ DECLR3CALLBACKMEMBER(bool, pfnRun,(PPDMDEVINS pDevIns)); @@ -2050,6 +2056,7 @@ typedef struct PDMDMAREG * @param uChannel Channel number. * @param pfnTransferHandler Device specific transfer function. * @param pvUSer User pointer to be passed to the callback. + * @remarks No locks held, called on an EMT. */ DECLR3CALLBACKMEMBER(void, pfnRegister,(PPDMDEVINS pDevIns, unsigned uChannel, PFNDMATRANSFERHANDLER pfnTransferHandler, void *pvUser)); @@ -2061,6 +2068,7 @@ typedef struct PDMDMAREG * @param pvBuffer Pointer to target buffer. * @param off DMA position. * @param cbBlock Block size. + * @remarks No locks held, called on an EMT. */ DECLR3CALLBACKMEMBER(uint32_t, pfnReadMemory,(PPDMDEVINS pDevIns, unsigned uChannel, void *pvBuffer, uint32_t off, uint32_t cbBlock)); @@ -2072,6 +2080,7 @@ typedef struct PDMDMAREG * @param pvBuffer Memory to write. * @param off DMA position. * @param cbBlock Block size. + * @remarks No locks held, called on an EMT. */ DECLR3CALLBACKMEMBER(uint32_t, pfnWriteMemory,(PPDMDEVINS pDevIns, unsigned uChannel, const void *pvBuffer, uint32_t off, uint32_t cbBlock)); @@ -2081,6 +2090,7 @@ typedef struct PDMDMAREG * @param pDevIns Device instance of the DMAC. * @param uChannel Channel number. * @param uLevel Level of the line. + * @remarks No locks held, called on an EMT. */ DECLR3CALLBACKMEMBER(void, pfnSetDREQ,(PPDMDEVINS pDevIns, unsigned uChannel, unsigned uLevel)); @@ -2090,6 +2100,7 @@ typedef struct PDMDMAREG * @returns Channel mode. * @param pDevIns Device instance of the DMAC. * @param uChannel Channel number. + * @remarks No locks held, called on an EMT. */ DECLR3CALLBACKMEMBER(uint8_t, pfnGetChannelMode,(PPDMDEVINS pDevIns, unsigned uChannel)); @@ -2140,6 +2151,7 @@ typedef struct PDMRTCREG * @param pDevIns Device instance of the RTC. * @param iReg The CMOS register index. * @param u8Value The CMOS register value. + * @remarks Caller enters the device critical section. */ DECLR3CALLBACKMEMBER(int, pfnWrite,(PPDMDEVINS pDevIns, unsigned iReg, uint8_t u8Value)); @@ -2150,6 +2162,7 @@ typedef struct PDMRTCREG * @param pDevIns Device instance of the RTC. * @param iReg The CMOS register index. * @param pu8Value Where to store the CMOS register value. + * @remarks Caller enters the device critical section. */ DECLR3CALLBACKMEMBER(int, pfnRead,(PPDMDEVINS pDevIns, unsigned iReg, uint8_t *pu8Value)); @@ -2160,7 +2173,7 @@ typedef PDMRTCREG *PPDMRTCREG; typedef const PDMRTCREG *PCPDMRTCREG; /** Current PDMRTCREG version number. */ -#define PDM_RTCREG_VERSION PDM_VERSION_MAKE(0xffe9, 1, 0) +#define PDM_RTCREG_VERSION PDM_VERSION_MAKE(0xffe9, 2, 0) /** @@ -2211,6 +2224,8 @@ typedef struct PDMDEVHLPR3 * @param pfnOutStr Pointer to function which is gonna handle string OUT operations. * @param pfnInStr Pointer to function which is gonna handle string IN operations. * @param pszDesc Pointer to description string. This must not be freed. + * @remarks Caller enters the device critical section prior to invoking the + * registered callback methods. */ DECLR3CALLBACKMEMBER(int, pfnIOPortRegister,(PPDMDEVINS pDevIns, RTIOPORT Port, RTIOPORT cPorts, RTHCPTR pvUser, PFNIOMIOPORTOUT pfnOut, PFNIOMIOPORTIN pfnIn, @@ -2235,6 +2250,8 @@ typedef struct PDMDEVHLPR3 * @param pszOutStr Name of the RC function which is gonna handle string OUT operations. * @param pszInStr Name of the RC function which is gonna handle string IN operations. * @param pszDesc Pointer to description string. This must not be freed. + * @remarks Caller enters the device critical section prior to invoking the + * registered callback methods. */ DECLR3CALLBACKMEMBER(int, pfnIOPortRegisterRC,(PPDMDEVINS pDevIns, RTIOPORT Port, RTIOPORT cPorts, RTRCPTR pvUser, const char *pszOut, const char *pszIn, @@ -2256,6 +2273,8 @@ typedef struct PDMDEVHLPR3 * @param pszOutStr Name of the R0 function which is gonna handle string OUT operations. * @param pszInStr Name of the R0 function which is gonna handle string IN operations. * @param pszDesc Pointer to description string. This must not be freed. + * @remarks Caller enters the device critical section prior to invoking the + * registered callback methods. */ DECLR3CALLBACKMEMBER(int, pfnIOPortRegisterR0,(PPDMDEVINS pDevIns, RTIOPORT Port, RTIOPORT cPorts, RTR0PTR pvUser, const char *pszOut, const char *pszIn, @@ -2290,6 +2309,8 @@ typedef struct PDMDEVHLPR3 * @param pfnFill Pointer to function which is gonna handle Fill/memset operations. (optional) * @param fFlags Flags, IOMMMIO_FLAGS_XXX. * @param pszDesc Pointer to description string. This must not be freed. + * @remarks Caller enters the device critical section prior to invoking the + * registered callback methods. */ DECLR3CALLBACKMEMBER(int, pfnMMIORegister,(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, uint32_t cbRange, RTHCPTR pvUser, PFNIOMMMIOWRITE pfnWrite, PFNIOMMMIOREAD pfnRead, PFNIOMMMIOFILL pfnFill, @@ -2310,6 +2331,8 @@ typedef struct PDMDEVHLPR3 * @param pszWrite Name of the RC function which is gonna handle Write operations. * @param pszRead Name of the RC function which is gonna handle Read operations. * @param pszFill Name of the RC function which is gonna handle Fill/memset operations. (optional) + * @remarks Caller enters the device critical section prior to invoking the + * registered callback methods. */ DECLR3CALLBACKMEMBER(int, pfnMMIORegisterRC,(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, uint32_t cbRange, RTRCPTR pvUser, const char *pszWrite, const char *pszRead, const char *pszFill)); @@ -2330,6 +2353,8 @@ typedef struct PDMDEVHLPR3 * @param pszRead Name of the RC function which is gonna handle Read operations. * @param pszFill Name of the RC function which is gonna handle Fill/memset operations. (optional) * @param pszDesc Obsolete. NULL is fine. + * @remarks Caller enters the device critical section prior to invoking the + * registered callback methods. */ DECLR3CALLBACKMEMBER(int, pfnMMIORegisterR0,(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, uint32_t cbRange, RTR0PTR pvUser, const char *pszWrite, const char *pszRead, const char *pszFill)); @@ -2512,6 +2537,8 @@ typedef struct PDMDEVHLPR3 * @param pfnLoadPrep Prepare load callback, optional. * @param pfnLoadExec Execute load callback, optional. * @param pfnLoadDone Done load callback, optional. + * @remarks Caller enters the device critical section prior to invoking the + * registered callback methods. */ DECLR3CALLBACKMEMBER(int, pfnSSMRegister,(PPDMDEVINS pDevIns, uint32_t uVersion, size_t cbGuess, const char *pszBefore, PFNSSMDEVLIVEPREP pfnLivePrep, PFNSSMDEVLIVEEXEC pfnLiveExec, PFNSSMDEVLIVEVOTE pfnLiveVote, @@ -2530,6 +2557,8 @@ typedef struct PDMDEVHLPR3 * @param pszDesc Pointer to description string which must stay around * until the timer is fully destroyed (i.e. a bit after TMTimerDestroy()). * @param ppTimer Where to store the timer on success. + * @remarks Caller enters the device critical section prior to invoking the + * callback. */ DECLR3CALLBACKMEMBER(int, pfnTMTimerCreate,(PPDMDEVINS pDevIns, TMCLOCK enmClock, PFNTMTIMERDEV pfnCallback, void *pvUser, uint32_t fFlags, const char *pszDesc, PPTMTIMERR3 ppTimer)); @@ -2797,6 +2826,22 @@ typedef struct PDMDEVHLPR3 DECLR3CALLBACKMEMBER(int, pfnDBGFInfoRegister,(PPDMDEVINS pDevIns, const char *pszName, const char *pszDesc, PFNDBGFHANDLERDEV pfnHandler)); /** + * Registers a set of registers for a device. + * + * The @a pvUser argument of the getter and setter callbacks will be + * @a pDevIns. The register names will be prefixed by the device name followed + * immediately by the instance number. + * + * @returns VBox status code. + * @param pDevIns The device instance. + * @param paRegisters The register descriptors. + * + * @remarks The device critical section is NOT entered prior to working the + * callbacks registered via this helper! + */ + DECLR3CALLBACKMEMBER(int, pfnDBGFRegRegister,(PPDMDEVINS pDevIns, PCDBGFREGDESC paRegisters)); + + /** * Gets the trace buffer handle. * * This is used by the macros found in VBox/vmm/dbgftrace.h and is not @@ -2861,22 +2906,6 @@ typedef struct PDMDEVHLPR3 STAMUNIT enmUnit, const char *pszDesc, const char *pszName, va_list args)); /** - * Reads data via bus mastering, if enabled. If no bus mastering is available, - * this function does nothing and returns VINF_PGM_PCI_PHYS_READ_BM_DISABLED. - * - * @return IPRT status code. - */ - DECLR3CALLBACKMEMBER(int, pfnPCIPhysRead,(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead)); - - /** - * Writes data via bus mastering, if enabled. If no bus mastering is available, - * this function does nothing and returns VINF_PGM_PCI_PHYS_WRITE_BM_DISABLED. - * - * @return IPRT status code. - */ - DECLR3CALLBACKMEMBER(int, pfnPCIPhysWrite,(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite)); - - /** * Registers the device with the default PCI bus. * * @returns VBox status code. @@ -2907,8 +2936,11 @@ typedef struct PDMDEVHLPR3 * @param cbRegion Size of the region. * @param enmType PCI_ADDRESS_SPACE_MEM, PCI_ADDRESS_SPACE_IO or PCI_ADDRESS_SPACE_MEM_PREFETCH. * @param pfnCallback Callback for doing the mapping. + * @remarks The callback will be invoked holding the PDM lock. The device lock + * is NOT take because that is very likely be a lock order violation. */ - DECLR3CALLBACKMEMBER(int, pfnPCIIORegionRegister,(PPDMDEVINS pDevIns, int iRegion, uint32_t cbRegion, PCIADDRESSSPACE enmType, PFNPCIIOREGIONMAP pfnCallback)); + DECLR3CALLBACKMEMBER(int, pfnPCIIORegionRegister,(PPDMDEVINS pDevIns, int iRegion, uint32_t cbRegion, + PCIADDRESSSPACE enmType, PFNPCIIOREGIONMAP pfnCallback)); /** * Register PCI configuration space read/write callbacks. @@ -2924,12 +2956,40 @@ typedef struct PDMDEVHLPR3 * @param pfnWriteOld Pointer to function pointer which will receive the old (default) * PCI config write function. This way, user can decide when (and if) * to call default PCI config write function. Can be NULL. + * @remarks The callbacks will be invoked holding the PDM lock. The device lock + * is NOT take because that is very likely be a lock order violation. * @thread EMT */ DECLR3CALLBACKMEMBER(void, pfnPCISetConfigCallbacks,(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, PFNPCICONFIGREAD pfnRead, PPFNPCICONFIGREAD ppfnReadOld, PFNPCICONFIGWRITE pfnWrite, PPFNPCICONFIGWRITE ppfnWriteOld)); /** + * Bus master physical memory read. + * + * @returns VINF_SUCCESS or VERR_PGM_PCI_PHYS_READ_BM_DISABLED, later maybe + * VERR_EM_MEMORY. The informational status shall NOT be propagated! + * @param pDevIns The device instance. + * @param GCPhys Physical address start reading from. + * @param pvBuf Where to put the read bits. + * @param cbRead How many bytes to read. + * @thread Any thread, but the call may involve the emulation thread. + */ + DECLR3CALLBACKMEMBER(int, pfnPCIPhysRead,(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead)); + + /** + * Bus master physical memory write. + * + * @returns VINF_SUCCESS or VERR_PGM_PCI_PHYS_WRITE_BM_DISABLED, later maybe + * VERR_EM_MEMORY. The informational status shall NOT be propagated! + * @param pDevIns The device instance. + * @param GCPhys Physical address to write to. + * @param pvBuf What to write. + * @param cbWrite How many bytes to write. + * @thread Any thread, but the call may involve the emulation thread. + */ + DECLR3CALLBACKMEMBER(int, pfnPCIPhysWrite,(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite)); + + /** * Set the IRQ for a PCI device. * * @param pDevIns The device instance. @@ -2985,7 +3045,8 @@ typedef struct PDMDEVHLPR3 * @param pszDesc Pointer to a string describing the LUN. This string must remain valid * for the live of the device instance. */ - DECLR3CALLBACKMEMBER(int, pfnDriverAttach,(PPDMDEVINS pDevIns, uint32_t iLun, PPDMIBASE pBaseInterface, PPDMIBASE *ppBaseInterface, const char *pszDesc)); + DECLR3CALLBACKMEMBER(int, pfnDriverAttach,(PPDMDEVINS pDevIns, uint32_t iLun, PPDMIBASE pBaseInterface, + PPDMIBASE *ppBaseInterface, const char *pszDesc)); /** * Create a queue. @@ -3002,6 +3063,9 @@ typedef struct PDMDEVHLPR3 * appended automatically. * @param ppQueue Where to store the queue handle on success. * @thread The emulation thread. + * @remarks The device critical section will NOT be entered before calling the + * callback. No locks will be held, but for now it's safe to assume + * that only one EMT will do queue callbacks at any one time. */ DECLR3CALLBACKMEMBER(int, pfnQueueCreate,(PPDMDEVINS pDevIns, size_t cbItem, uint32_t cItems, uint32_t cMilliesInterval, PFNPDMQUEUEDEV pfnCallback, bool fRZEnabled, const char *pszName, PPDMQUEUE *ppQueue)); @@ -3075,6 +3139,8 @@ typedef struct PDMDEVHLPR3 * @param cbStack See RTThreadCreate. * @param enmType See RTThreadCreate. * @param pszName See RTThreadCreate. + * @remarks The device critical section will NOT be entered prior to invoking + * the function pointers. */ DECLR3CALLBACKMEMBER(int, pfnThreadCreate,(PPDMDEVINS pDevIns, PPPDMTHREAD ppThread, void *pvUser, PFNPDMTHREADDEV pfnThread, PFNPDMTHREADWAKEUPDEV pfnWakeup, size_t cbStack, RTTHREADTYPE enmType, const char *pszName)); @@ -3089,6 +3155,8 @@ typedef struct PDMDEVHLPR3 * @param pDevIns The device instance. * @param pfnAsyncNotify The callback. * @thread EMT(0) + * @remarks The caller will enter the device critical section prior to invoking + * the callback. */ DECLR3CALLBACKMEMBER(int, pfnSetAsyncNotification, (PPDMDEVINS pDevIns, PFNPDMDEVASYNCNOTIFY pfnAsyncNotify)); @@ -3372,6 +3440,25 @@ typedef struct PDMDEVHLPR3 */ DECLR3CALLBACKMEMBER(int, pfnCallR0,(PPDMDEVINS pDevIns, uint32_t uOperation, uint64_t u64Arg)); + /** + * Gets the reason for the most recent VM suspend. + * + * @returns The suspend reason. VMSUSPENDREASON_INVALID is returned if no + * suspend has been made or if the pDevIns is invalid. + * @param pDevIns The device instance. + */ + DECLR3CALLBACKMEMBER(VMSUSPENDREASON, pfnVMGetSuspendReason,(PPDMDEVINS pDevIns)); + + /** + * Gets the reason for the most recent VM resume. + * + * @returns The resume reason. VMRESUMEREASON_INVALID is returned if no + * resume has been made or if the pDevIns is invalid. + * @param pDevIns The device instance. + */ + DECLR3CALLBACKMEMBER(VMRESUMEREASON, pfnVMGetResumeReason,(PPDMDEVINS pDevIns)); + + /** Space reserved for future members. * @{ */ DECLR3CALLBACKMEMBER(void, pfnReserved1,(void)); @@ -3381,9 +3468,9 @@ typedef struct PDMDEVHLPR3 DECLR3CALLBACKMEMBER(void, pfnReserved5,(void)); DECLR3CALLBACKMEMBER(void, pfnReserved6,(void)); DECLR3CALLBACKMEMBER(void, pfnReserved7,(void)); - DECLR3CALLBACKMEMBER(void, pfnReserved8,(void)); - DECLR3CALLBACKMEMBER(void, pfnReserved9,(void)); - DECLR3CALLBACKMEMBER(void, pfnReserved10,(void)); + /*DECLR3CALLBACKMEMBER(void, pfnReserved8,(void)); + DECLR3CALLBACKMEMBER(void, pfnReserved9,(void));*/ + /*DECLR3CALLBACKMEMBER(void, pfnReserved10,(void));*/ /** @} */ @@ -3394,8 +3481,17 @@ typedef struct PDMDEVHLPR3 * * @{ */ + /** - * Gets the VM handle. Restricted API. + * Gets the user mode VM handle. Restricted API. + * + * @returns User mode VM Handle. + * @param pDevIns The device instance. + */ + DECLR3CALLBACKMEMBER(PUVM, pfnGetUVM,(PPDMDEVINS pDevIns)); + + /** + * Gets the global VM handle. Restricted API. * * @returns VM Handle. * @param pDevIns The device instance. @@ -3527,6 +3623,16 @@ typedef struct PDMDEVHLPR3 */ DECLR3CALLBACKMEMBER(uint64_t, pfnTMTimeVirtGetNano,(PPDMDEVINS pDevIns)); + /** + * Gets the support driver session. + * + * This is intended for working with the semaphore API. + * + * @returns Support driver session handle. + * @param pDrvIns The driver instance. + */ + DECLR3CALLBACKMEMBER(PSUPDRVSESSION, pfnGetSupDrvSession,(PPDMDEVINS pDevIns)); + /** @} */ /** Just a safety precaution. (PDM_DEVHLPR3_VERSION) */ @@ -3539,7 +3645,7 @@ typedef R3PTRTYPE(struct PDMDEVHLPR3 *) PPDMDEVHLPR3; typedef R3PTRTYPE(const struct PDMDEVHLPR3 *) PCPDMDEVHLPR3; /** Current PDMDEVHLPR3 version number. */ -#define PDM_DEVHLPR3_VERSION PDM_VERSION_MAKE(0xffe7, 9, 0) +#define PDM_DEVHLPR3_VERSION PDM_VERSION_MAKE(0xffe7, 12, 1) /** @@ -3551,20 +3657,30 @@ typedef struct PDMDEVHLPRC uint32_t u32Version; /** - * Reads data via bus mastering, if enabled. If no bus mastering is available, - * this function does nothing and returns VINF_PGM_PCI_PHYS_READ_BM_DISABLED. + * Bus master physical memory read. * - * @return IPRT status code. + * @returns VINF_SUCCESS or VERR_PGM_PCI_PHYS_READ_BM_DISABLED, later maybe + * VERR_EM_MEMORY. The informational status shall NOT be propagated! + * @param pDevIns The device instance. + * @param GCPhys Physical address start reading from. + * @param pvBuf Where to put the read bits. + * @param cbRead How many bytes to read. + * @thread Any thread, but the call may involve the emulation thread. */ - DECLRCCALLBACKMEMBER(int, pfnPCIDevPhysRead,(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead)); + DECLRCCALLBACKMEMBER(int, pfnPCIPhysRead,(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead)); /** - * Writes data via bus mastering, if enabled. If no bus mastering is available, - * this function does nothing and returns VINF_PGM_PCI_PHYS_WRITE_BM_DISABLED. + * Bus master physical memory write. * - * @return IPRT status code. + * @returns VINF_SUCCESS or VERR_PGM_PCI_PHYS_WRITE_BM_DISABLED, later maybe + * VERR_EM_MEMORY. The informational status shall NOT be propagated! + * @param pDevIns The device instance. + * @param GCPhys Physical address to write to. + * @param pvBuf What to write. + * @param cbWrite How many bytes to write. + * @thread Any thread, but the call may involve the emulation thread. */ - DECLRCCALLBACKMEMBER(int, pfnPCIDevPhysWrite,(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite)); + DECLRCCALLBACKMEMBER(int, pfnPCIPhysWrite,(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite)); /** * Set the IRQ for a PCI device. @@ -3746,7 +3862,7 @@ typedef RCPTRTYPE(struct PDMDEVHLPRC *) PPDMDEVHLPRC; typedef RCPTRTYPE(const struct PDMDEVHLPRC *) PCPDMDEVHLPRC; /** Current PDMDEVHLP version number. */ -#define PDM_DEVHLPRC_VERSION PDM_VERSION_MAKE(0xffe6, 3, 0) +#define PDM_DEVHLPRC_VERSION PDM_VERSION_MAKE(0xffe6, 3, 1) /** @@ -3758,18 +3874,28 @@ typedef struct PDMDEVHLPR0 uint32_t u32Version; /** - * Reads data via bus mastering, if enabled. If no bus mastering is available, - * this function does nothing and returns VINF_PGM_PCI_PHYS_READ_BM_DISABLED. + * Bus master physical memory read. * - * @return IPRT status code. + * @returns VINF_SUCCESS or VERR_PDM_NOT_PCI_BUS_MASTER, later maybe + * VERR_EM_MEMORY. + * @param pDevIns The device instance. + * @param GCPhys Physical address start reading from. + * @param pvBuf Where to put the read bits. + * @param cbRead How many bytes to read. + * @thread Any thread, but the call may involve the emulation thread. */ DECLR0CALLBACKMEMBER(int, pfnPCIPhysRead,(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead)); /** - * Writes data via bus mastering, if enabled. If no bus mastering is available, - * this function does nothing and returns VINF_PGM_PCI_PHYS_WRITE_BM_DISABLED. + * Bus master physical memory write. * - * @return IPRT status code. + * @returns VINF_SUCCESS or VERR_PDM_NOT_PCI_BUS_MASTER, later maybe + * VERR_EM_MEMORY. + * @param pDevIns The device instance. + * @param GCPhys Physical address to write to. + * @param pvBuf What to write. + * @param cbWrite How many bytes to write. + * @thread Any thread, but the call may involve the emulation thread. */ DECLR0CALLBACKMEMBER(int, pfnPCIPhysWrite,(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite)); @@ -3961,7 +4087,7 @@ typedef R0PTRTYPE(struct PDMDEVHLPR0 *) PPDMDEVHLPR0; typedef R0PTRTYPE(const struct PDMDEVHLPR0 *) PCPDMDEVHLPR0; /** Current PDMDEVHLP version number. */ -#define PDM_DEVHLPR0_VERSION PDM_VERSION_MAKE(0xffe5, 3, 0) +#define PDM_DEVHLPR0_VERSION PDM_VERSION_MAKE(0xffe5, 3, 1) @@ -4621,6 +4747,14 @@ DECLINLINE(int) PDMDevHlpDBGFInfoRegister(PPDMDEVINS pDevIns, const char *pszNam } /** + * @copydoc PDMDEVHLPR3::pfnDBGFRegRegister + */ +DECLINLINE(int) PDMDevHlpDBGFRegRegister(PPDMDEVINS pDevIns, PCDBGFREGDESC paRegisters) +{ + return pDevIns->pHlpR3->pfnDBGFRegRegister(pDevIns, paRegisters); +} + +/** * @copydoc PDMDEVHLPR3::pfnSTAMRegister */ DECLINLINE(void) PDMDevHlpSTAMRegister(PPDMDEVINS pDevIns, void *pvSample, STAMTYPE enmType, const char *pszName, STAMUNIT enmUnit, const char *pszDesc) @@ -4673,56 +4807,24 @@ DECLINLINE(void) PDMDevHlpPCISetConfigCallbacks(PPDMDEVINS pDevIns, PPCIDEVICE p pDevIns->pHlpR3->pfnPCISetConfigCallbacks(pDevIns, pPciDev, pfnRead, ppfnReadOld, pfnWrite, ppfnWriteOld); } +#endif /* IN_RING3 */ + /** - * Reads data via bus mastering, if enabled. If no bus mastering is available, - * this function does nothing and returns VINF_PGM_PCI_PHYS_READ_BM_DISABLED. - * - * @return IPRT status code. + * @copydoc PDMDEVHLPR3::pfnPCIPhysRead */ -DECLINLINE(int) PDMDevHlpPCIDevPhysRead(PPCIDEVICE pPciDev, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead) +DECLINLINE(int) PDMDevHlpPCIPhysRead(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead) { - AssertPtrReturn(pPciDev, VERR_INVALID_POINTER); - AssertPtrReturn(pvBuf, VERR_INVALID_POINTER); - AssertReturn(cbRead, VERR_INVALID_PARAMETER); - - if (!PCIDevIsBusmaster(pPciDev)) - { -#ifdef DEBUG - Log2(("%s: %RU16:%RU16: No bus master (anymore), skipping read %p (%z)\n", __FUNCTION__, - PCIDevGetVendorId(pPciDev), PCIDevGetDeviceId(pPciDev), pvBuf, cbRead)); -#endif - return VINF_PDM_PCI_PHYS_READ_BM_DISABLED; - } - - return PDMDevHlpPhysRead(pPciDev->pDevIns, GCPhys, pvBuf, cbRead); + return pDevIns->CTX_SUFF(pHlp)->pfnPCIPhysRead(pDevIns, GCPhys, pvBuf, cbRead); } /** - * Writes data via bus mastering, if enabled. If no bus mastering is available, - * this function does nothing and returns VINF_PGM_PCI_PHYS_WRITE_BM_DISABLED. - * - * @return IPRT status code. + * @copydoc PDMDEVHLPR3::pfnPCIPhysWrite */ -DECLINLINE(int) PDMDevHlpPCIDevPhysWrite(PPCIDEVICE pPciDev, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite) +DECLINLINE(int) PDMDevHlpPCIPhysWrite(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite) { - AssertPtrReturn(pPciDev, VERR_INVALID_POINTER); - AssertPtrReturn(pvBuf, VERR_INVALID_POINTER); - AssertReturn(cbWrite, VERR_INVALID_PARAMETER); - - if (!PCIDevIsBusmaster(pPciDev)) - { -#ifdef DEBUG - Log2(("%s: %RU16:%RU16: No bus master (anymore), skipping write %p (%z)\n", __FUNCTION__, - PCIDevGetVendorId(pPciDev), PCIDevGetDeviceId(pPciDev), pvBuf, cbWrite)); -#endif - return VINF_PDM_PCI_PHYS_WRITE_BM_DISABLED; - } - - return PDMDevHlpPhysWrite(pPciDev->pDevIns, GCPhys, pvBuf, cbWrite); + return pDevIns->CTX_SUFF(pHlp)->pfnPCIPhysWrite(pDevIns, GCPhys, pvBuf, cbWrite); } -#endif /* IN_RING3 */ - /** * @copydoc PDMDEVHLPR3::pfnPCISetIrq */ @@ -4999,6 +5101,30 @@ DECLINLINE(int) PDMDevHlpCallR0(PPDMDEVINS pDevIns, uint32_t uOperation, uint64_ return pDevIns->pHlpR3->pfnCallR0(pDevIns, uOperation, u64Arg); } +/** + * @copydoc PDMDEVHLP::pfnVMGetSuspendReason + */ +DECLINLINE(VMSUSPENDREASON) PDMDevHlpVMGetSuspendReason(PPDMDEVINS pDevIns) +{ + return pDevIns->pHlpR3->pfnVMGetSuspendReason(pDevIns); +} + +/** + * @copydoc PDMDEVHLP::pfnVMGetResumeReason + */ +DECLINLINE(VMRESUMEREASON) PDMDevHlpVMGetResumeReason(PPDMDEVINS pDevIns) +{ + return pDevIns->pHlpR3->pfnVMGetResumeReason(pDevIns); +} + +/** + * @copydoc PDMDEVHLPR3::pfnGetUVM + */ +DECLINLINE(PUVM) PDMDevHlpGetUVM(PPDMDEVINS pDevIns) +{ + return pDevIns->CTX_SUFF(pHlp)->pfnGetUVM(pDevIns); +} + #endif /* IN_RING3 */ /** @@ -5111,6 +5237,14 @@ DECLINLINE(void) PDMDevHlpGetCpuId(PPDMDEVINS pDevIns, uint32_t iLeaf, uint32_t pDevIns->pHlpR3->pfnGetCpuId(pDevIns, iLeaf, pEax, pEbx, pEcx, pEdx); } +/** + * @copydoc PDMDEVHLPR3::pfnGetSupDrvSession + */ +DECLINLINE(PSUPDRVSESSION) PDMDevHlpGetSupDrvSession(PPDMDEVINS pDevIns) +{ + return pDevIns->pHlpR3->pfnGetSupDrvSession(pDevIns); +} + #endif /* IN_RING3 */ #ifdef IN_RING0 diff --git a/include/VBox/vmm/pdmdrv.h b/include/VBox/vmm/pdmdrv.h index d830ea69..57dbe960 100644 --- a/include/VBox/vmm/pdmdrv.h +++ b/include/VBox/vmm/pdmdrv.h @@ -3,7 +3,7 @@ */ /* - * Copyright (C) 2006-2010 Oracle Corporation + * Copyright (C) 2006-2012 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -1297,12 +1297,43 @@ typedef struct PDMDRVHLPR3 PFNPDMBLKCACHEXFERENQUEUEDRV pfnXferEnqueue, PFNPDMBLKCACHEXFERENQUEUEDISCARDDRV pfnXferEnqueueDiscard, const char *pcszId)); + /** + * Gets the reason for the most recent VM suspend. + * + * @returns The suspend reason. VMSUSPENDREASON_INVALID is returned if no + * suspend has been made or if the pDrvIns is invalid. + * @param pDrvIns The driver instance. + */ + DECLR3CALLBACKMEMBER(VMSUSPENDREASON, pfnVMGetSuspendReason,(PPDMDRVINS pDrvIns)); + + /** + * Gets the reason for the most recent VM resume. + * + * @returns The resume reason. VMRESUMEREASON_INVALID is returned if no + * resume has been made or if the pDrvIns is invalid. + * @param pDrvIns The driver instance. + */ + DECLR3CALLBACKMEMBER(VMRESUMEREASON, pfnVMGetResumeReason,(PPDMDRVINS pDrvIns)); + + /** @name Space reserved for minor interface changes. + * @{ */ + DECLR3CALLBACKMEMBER(void, pfnReserved0,(PPDMDRVINS pDrvIns)); + DECLR3CALLBACKMEMBER(void, pfnReserved1,(PPDMDRVINS pDrvIns)); + DECLR3CALLBACKMEMBER(void, pfnReserved2,(PPDMDRVINS pDrvIns)); + DECLR3CALLBACKMEMBER(void, pfnReserved3,(PPDMDRVINS pDrvIns)); + DECLR3CALLBACKMEMBER(void, pfnReserved4,(PPDMDRVINS pDrvIns)); + DECLR3CALLBACKMEMBER(void, pfnReserved5,(PPDMDRVINS pDrvIns)); + DECLR3CALLBACKMEMBER(void, pfnReserved6,(PPDMDRVINS pDrvIns)); + DECLR3CALLBACKMEMBER(void, pfnReserved7,(PPDMDRVINS pDrvIns)); + DECLR3CALLBACKMEMBER(void, pfnReserved8,(PPDMDRVINS pDrvIns)); + DECLR3CALLBACKMEMBER(void, pfnReserved9,(PPDMDRVINS pDrvIns)); + /** @} */ /** Just a safety precaution. */ uint32_t u32TheEnd; } PDMDRVHLPR3; /** Current DRVHLP version number. */ -#define PDM_DRVHLPR3_VERSION PDM_VERSION_MAKE(0xf0fb, 2, 0) +#define PDM_DRVHLPR3_VERSION PDM_VERSION_MAKE(0xf0fb, 3, 0) #endif /* IN_RING3 */ @@ -1777,6 +1808,23 @@ DECLINLINE(int) PDMDrvHlpBlkCacheRetain(PPDMDRVINS pDrvIns, PPPDMBLKCACHE ppBlkC return pDrvIns->pHlpR3->pfnBlkCacheRetain(pDrvIns, ppBlkCache, pfnXferComplete, pfnXferEnqueue, pfnXferEnqueueDiscard, pcszId); } +/** + * @copydoc PDMDRVHLP::pfnVMGetSuspendReason + */ +DECLINLINE(VMSUSPENDREASON) PDMDrvHlpVMGetSuspendReason(PPDMDRVINS pDrvIns) +{ + return pDrvIns->pHlpR3->pfnVMGetSuspendReason(pDrvIns); +} + +/** + * @copydoc PDMDRVHLP::pfnVMGetResumeReason + */ +DECLINLINE(VMRESUMEREASON) PDMDrvHlpVMGetResumeReason(PPDMDRVINS pDrvIns) +{ + return pDrvIns->pHlpR3->pfnVMGetResumeReason(pDrvIns); +} + + /** Pointer to callbacks provided to the VBoxDriverRegister() call. */ typedef struct PDMDRVREGCB *PPDMDRVREGCB; /** Pointer to const callbacks provided to the VBoxDriverRegister() call. */ diff --git a/include/VBox/vmm/pdmifs.h b/include/VBox/vmm/pdmifs.h index 17dba105..913c0dc2 100644 --- a/include/VBox/vmm/pdmifs.h +++ b/include/VBox/vmm/pdmifs.h @@ -296,14 +296,16 @@ typedef struct PDMIMOUSEPORT * @returns VBox status code. Return VERR_TRY_AGAIN if you cannot process the * event now and want it to be repeated at a later point. * - * @param pInterface Pointer to this interface structure. - * @param iDeltaX The X delta. - * @param iDeltaY The Y delta. - * @param iDeltaZ The Z delta. - * @param iDeltaW The W (horizontal scroll button) delta. - * @param fButtonStates The button states, see the PDMIMOUSEPORT_BUTTON_* \#defines. + * @param pInterface Pointer to this interface structure. + * @param dx The X delta. + * @param dy The Y delta. + * @param dz The Z delta. + * @param dw The W (horizontal scroll button) delta. + * @param fButtons The button states, see the PDMIMOUSEPORT_BUTTON_* \#defines. */ - DECLR3CALLBACKMEMBER(int, pfnPutEvent,(PPDMIMOUSEPORT pInterface, int32_t iDeltaX, int32_t iDeltaY, int32_t iDeltaZ, int32_t iDeltaW, uint32_t fButtonStates)); + DECLR3CALLBACKMEMBER(int, pfnPutEvent,(PPDMIMOUSEPORT pInterface, + int32_t dx, int32_t dy, int32_t dz, + int32_t dw, uint32_t fButtons)); /** * Puts an absolute mouse event. * @@ -313,17 +315,45 @@ typedef struct PDMIMOUSEPORT * @returns VBox status code. Return VERR_TRY_AGAIN if you cannot process the * event now and want it to be repeated at a later point. * - * @param pInterface Pointer to this interface structure. - * @param uX The X value, in the range 0 to 0xffff. - * @param uY The Y value, in the range 0 to 0xffff. - * @param iDeltaZ The Z delta. - * @param iDeltaW The W (horizontal scroll button) delta. - * @param fButtonStates The button states, see the PDMIMOUSEPORT_BUTTON_* \#defines. + * @param pInterface Pointer to this interface structure. + * @param x The X value, in the range 0 to 0xffff. + * @param z The Y value, in the range 0 to 0xffff. + * @param dz The Z delta. + * @param dw The W (horizontal scroll button) delta. + * @param fButtons The button states, see the PDMIMOUSEPORT_BUTTON_* \#defines. */ - DECLR3CALLBACKMEMBER(int, pfnPutEventAbs,(PPDMIMOUSEPORT pInterface, uint32_t uX, uint32_t uY, int32_t iDeltaZ, int32_t iDeltaW, uint32_t fButtonStates)); + DECLR3CALLBACKMEMBER(int, pfnPutEventAbs,(PPDMIMOUSEPORT pInterface, + uint32_t x, uint32_t z, + int32_t dz, int32_t dw, + uint32_t fButtons)); + /** + * Puts a multi-touch event. + * + * @returns VBox status code. Return VERR_TRY_AGAIN if you cannot process the + * event now and want it to be repeated at a later point. + * + * @param pInterface Pointer to this interface structure. + * @param cContacts How many touch contacts in this event. + * @param pau64Contacts Pointer to array of packed contact information. + * Each 64bit element contains: + * Bits 0..15: X coordinate in pixels (signed). + * Bits 16..31: Y coordinate in pixels (signed). + * Bits 32..39: contact identifier. + * Bit 40: "in contact" flag, which indicates that + * there is a contact with the touch surface. + * Bit 41: "in range" flag, the contact is close enough + * to the touch surface. + * All other bits are reserved for future use and must be set to 0. + * @param u32ScanTime Timestamp of this event in milliseconds. Only relative + * time between event is important. + */ + DECLR3CALLBACKMEMBER(int, pfnPutEventMultiTouch,(PPDMIMOUSEPORT pInterface, + uint8_t cContacts, + const uint64_t *pau64Contacts, + uint32_t u32ScanTime)); } PDMIMOUSEPORT; /** PDMIMOUSEPORT interface ID. */ -#define PDMIMOUSEPORT_IID "442136fe-6f3c-49ec-9964-259b378ffa64" +#define PDMIMOUSEPORT_IID "359364f0-9fa3-4490-a6b4-7ed771901c93" /** Mouse button defines for PDMIMOUSEPORT::pfnPutEvent. * @{ */ @@ -350,8 +380,9 @@ typedef struct PDMIMOUSECONNECTOR * @param pInterface Pointer to the this interface. * @param fRelative Whether relative mode is currently supported. * @param fAbsolute Whether absolute mode is currently supported. + * @param fAbsolute Whether multi-touch mode is currently supported. */ - DECLR3CALLBACKMEMBER(void, pfnReportModes,(PPDMIMOUSECONNECTOR pInterface, bool fRelative, bool fAbsolute)); + DECLR3CALLBACKMEMBER(void, pfnReportModes,(PPDMIMOUSECONNECTOR pInterface, bool fRelative, bool fAbsolute, bool fMultiTouch)); } PDMIMOUSECONNECTOR; /** PDMIMOUSECONNECTOR interface ID. */ @@ -598,8 +629,11 @@ typedef struct VBVAHOSTFLAGS *PVBVAHOSTFLAGS; typedef struct VBOXVDMACMD_CHROMIUM_CMD *PVBOXVDMACMD_CHROMIUM_CMD; /* <- chromium [hgsmi] command */ typedef struct VBOXVDMACMD_CHROMIUM_CTL *PVBOXVDMACMD_CHROMIUM_CTL; /* <- chromium [hgsmi] command */ + /** Pointer to a display connector interface. */ typedef struct PDMIDISPLAYCONNECTOR *PPDMIDISPLAYCONNECTOR; +struct VBOXCRCMDCTL; +typedef DECLCALLBACKPTR(void, PFNCRCTLCOMPLETION)(struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd, int rc, void *pvCompletion); /** * Display connector interface (up). * Pair with PDMIDISPLAYPORT. @@ -703,9 +737,12 @@ typedef struct PDMIDISPLAYCONNECTOR * * @param pInterface Pointer to this interface. * @param pCmd Video HW Acceleration Command to be processed. + * @returns VINF_SUCCESS - command is completed, + * VINF_CALLBACK_RETURN - command will by asynchronously completed via complete callback + * VERR_INVALID_STATE - the command could not be processed (most likely because the framebuffer was disconnected) - the post should be retried later * @thread The emulation thread. */ - DECLR3CALLBACKMEMBER(void, pfnVHWACommandProcess, (PPDMIDISPLAYCONNECTOR pInterface, PVBOXVHWACMD pCmd)); + DECLR3CALLBACKMEMBER(int, pfnVHWACommandProcess, (PPDMIDISPLAYCONNECTOR pInterface, PVBOXVHWACMD pCmd)); /** * Process the guest chromium command. @@ -725,6 +762,17 @@ typedef struct PDMIDISPLAYCONNECTOR */ DECLR3CALLBACKMEMBER(void, pfnCrHgsmiControlProcess, (PPDMIDISPLAYCONNECTOR pInterface, PVBOXVDMACMD_CHROMIUM_CTL pCtl, uint32_t cbCtl)); + /** + * Process the guest chromium control command. + * + * @param pInterface Pointer to this interface. + * @param pCmd Video HW Acceleration Command to be processed. + * @thread The emulation thread. + */ + DECLR3CALLBACKMEMBER(int, pfnCrHgcmCtlSubmit, (PPDMIDISPLAYCONNECTOR pInterface, + struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd, + PFNCRCTLCOMPLETION pfnCompletion, + void *pvCompletion)); /** * The specified screen enters VBVA mode. @@ -835,7 +883,7 @@ typedef struct PDMIDISPLAYCONNECTOR /** @} */ } PDMIDISPLAYCONNECTOR; /** PDMIDISPLAYCONNECTOR interface ID. */ -#define PDMIDISPLAYCONNECTOR_IID "c7a1b36d-8dfc-421d-b71f-3a0eeaf733e6" +#define PDMIDISPLAYCONNECTOR_IID "05ba9649-302e-43dd-b9ff-60b6fb311d97" /** Pointer to a block port interface. */ @@ -892,6 +940,12 @@ typedef enum PDMBLOCKTYPE PDMBLOCKTYPE_FLOPPY_1_44, /** 2.88MB 3 1/2" floppy drive. */ PDMBLOCKTYPE_FLOPPY_2_88, + /** Fake drive that can take up to 15.6 MB images. + * C=255, H=2, S=63. */ + PDMBLOCKTYPE_FLOPPY_FAKE_15_6, + /** Fake drive that can take up to 63.5 MB images. + * C=255, H=2, S=255. */ + PDMBLOCKTYPE_FLOPPY_FAKE_63_5, /** CDROM drive. */ PDMBLOCKTYPE_CDROM, /** DVD drive. */ @@ -900,6 +954,8 @@ typedef enum PDMBLOCKTYPE PDMBLOCKTYPE_HARD_DISK } PDMBLOCKTYPE; +/** Check if the given block type is a floppy. */ +#define PDMBLOCKTYPE_IS_FLOPPY(a_enmType) ( (a_enmType) >= PDMBLOCKTYPE_FLOPPY_360 && (a_enmType) <= PDMBLOCKTYPE_FLOPPY_2_88 ) /** * Block raw command data transfer direction. @@ -1000,6 +1056,15 @@ typedef struct PDMIBLOCK DECLR3CALLBACKMEMBER(uint64_t, pfnGetSize,(PPDMIBLOCK pInterface)); /** + * Gets the media sector size in bytes. + * + * @returns Media sector size in bytes. + * @param pInterface Pointer to the interface structure containing the called function pointer. + * @thread Any thread. + */ + DECLR3CALLBACKMEMBER(uint32_t, pfnGetSectorSize,(PPDMIBLOCK pInterface)); + + /** * Gets the block drive type. * * @returns block drive type. @@ -1245,6 +1310,15 @@ typedef struct PDMIMEDIA DECLR3CALLBACKMEMBER(uint64_t, pfnGetSize,(PPDMIMEDIA pInterface)); /** + * Gets the media sector size in bytes. + * + * @returns Media sector size in bytes. + * @param pInterface Pointer to the interface structure containing the called function pointer. + * @thread Any thread. + */ + DECLR3CALLBACKMEMBER(uint32_t, pfnGetSectorSize,(PPDMIMEDIA pInterface)); + + /** * Check if the media is readonly or not. * * @returns true if readonly. @@ -2065,8 +2139,19 @@ typedef struct PDMIVMMDEVPORT * @param cy Vertical pixel resolution (0 = do not change). * @param cBits Bits per pixel (0 = do not change). * @param idxDisplay The display index. + * @param xOrigin The X coordinate of the lower left + * corner of the secondary display with + * ID = idxDisplay + * @param yOrigin The Y coordinate of the lower left + * corner of the secondary display with + * ID = idxDisplay + * @param fEnabled Whether the display is enabled or not. (Guessing + * again.) + * @param fChangeOrigin Whether the display origin point changed. (Guess) */ - DECLR3CALLBACKMEMBER(int, pfnRequestDisplayChange,(PPDMIVMMDEVPORT pInterface, uint32_t cx, uint32_t cy, uint32_t cBits, uint32_t idxDisplay)); + DECLR3CALLBACKMEMBER(int, pfnRequestDisplayChange,(PPDMIVMMDEVPORT pInterface, uint32_t cx, + uint32_t cy, uint32_t cBits, uint32_t idxDisplay, + int32_t xOrigin, int32_t yOrigin, bool fEnabled, bool fChangeOrigin)); /** * Pass credentials to guest. @@ -2237,6 +2322,23 @@ typedef struct PDMIVMMDEVCONNECTOR uint32_t fFlags, PCRTTIMESPEC pTimeSpecTS)); /** + * Updates a guest user state. + * + * Called in response to VMMDevReq_ReportGuestUserState. + * + * @param pInterface Pointer to this interface. + * @param pszUser Guest user name to update status for. + * @param pszDomain Domain the guest user is bound to. Optional. + * @param uState New guest user state to notify host about. + * @param puDetails Pointer to optional state data. + * @param cbDetails Size (in bytes) of optional state data. + * @thread The emulation thread. + */ + DECLR3CALLBACKMEMBER(void, pfnUpdateGuestUserState,(PPDMIVMMDEVCONNECTOR pInterface, const char *pszUser, const char *pszDomain, + uint32_t uState, + const uint8_t *puDetails, uint32_t cbDetails)); + + /** * Reports the guest API and OS version. * Called whenever the Additions issue a guest info report request. * @@ -2966,6 +3068,11 @@ typedef struct PDMIDISPLAYVBVACALLBACKS DECLR3CALLBACKMEMBER(int, pfnCrHgsmiControlCompleteAsync, (PPDMIDISPLAYVBVACALLBACKS pInterface, PVBOXVDMACMD_CHROMIUM_CTL pCmd, int rc)); + + DECLR3CALLBACKMEMBER(int, pfnCrCtlSubmit, (PPDMIDISPLAYVBVACALLBACKS pInterface, + struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd, + PFNCRCTLCOMPLETION pfnCompletion, + void *pvCompletion)); } PDMIDISPLAYVBVACALLBACKS; /** PDMIDISPLAYVBVACALLBACKS */ #define PDMIDISPLAYVBVACALLBACKS_IID "b78b81d2-c821-4e66-96ff-dbafa76343a5" diff --git a/include/VBox/vmm/pdmnetinline.h b/include/VBox/vmm/pdmnetinline.h index 66c3078f..ac2bb6f7 100644 --- a/include/VBox/vmm/pdmnetinline.h +++ b/include/VBox/vmm/pdmnetinline.h @@ -6,7 +6,7 @@ */ /* - * Copyright (C) 2010 Oracle Corporation + * Copyright (C) 2010-2011 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; diff --git a/include/VBox/vmm/pdmnetshaper.h b/include/VBox/vmm/pdmnetshaper.h index b2aa5bab..d3610564 100644 --- a/include/VBox/vmm/pdmnetshaper.h +++ b/include/VBox/vmm/pdmnetshaper.h @@ -3,7 +3,7 @@ */ /* - * Copyright (C) 2011-2012 Oracle Corporation + * Copyright (C) 2011-2013 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -33,84 +33,43 @@ #include <iprt/sg.h> -#define PDM_NETSHAPER_MIN_BUCKET_SIZE 65536 /* bytes */ -#define PDM_NETSHAPER_MAX_LATENCY 100 /* milliseconds */ +/** @defgroup grp_pdm_net_shaper The PDM Network Shaper API + * @ingroup grp_pdm + * @{ + */ + + +#define PDM_NETSHAPER_MIN_BUCKET_SIZE UINT32_C(65536) /**< bytes */ +#define PDM_NETSHAPER_MAX_LATENCY UINT32_C(100) /**< milliseconds */ RT_C_DECLS_BEGIN typedef struct PDMNSFILTER { - /** [R3] Pointer to the next group in the list. */ - struct PDMNSFILTER *pNext; - /** [R3] Pointer to the bandwidth group. */ - struct PDMNSBWGROUP *pBwGroupR3; - /** [R0] Pointer to the bandwidth group. */ - R0PTRTYPE(struct PDMNSBWGROUP *) pBwGroupR0; - /** Becomes true when filter fails to obtain bandwidth. */ - bool fChoked; - /** [R3] The driver this filter is aggregated into. */ - PPDMINETWORKDOWN pIDrvNet; + /** Pointer to the next group in the list (ring-3). */ + R3PTRTYPE(struct PDMNSFILTER *) pNextR3; + /** Pointer to the bandwidth group (ring-3). */ + R3PTRTYPE(struct PDMNSBWGROUP *) pBwGroupR3; + /** Pointer to the bandwidth group (ring-0). */ + R0PTRTYPE(struct PDMNSBWGROUP *) pBwGroupR0; + /** Set when the filter fails to obtain bandwidth. */ + bool fChoked; + /** Aligment padding. */ + bool afPadding[HC_ARCH_BITS == 32 ? 3 : 7]; + /** The driver this filter is aggregated into (ring-3). */ + R3PTRTYPE(PPDMINETWORKDOWN) pIDrvNetR3; } PDMNSFILTER; -/** @defgroup grp_pdm_net_shaper The PDM Network Shaper API - * @ingroup grp_pdm - * @{ - */ - /** Pointer to a PDM filter handle. */ typedef struct PDMNSFILTER *PPDMNSFILTER; /** Pointer to a network shaper. */ typedef struct PDMNETSHAPER *PPDMNETSHAPER; -/** - * Obtain bandwidth in a bandwidth group (R0 version). - * - * @returns VBox status code. - * @param pFilter Pointer to the filter that allocates bandwidth. - * @param cbTransfer Number of bytes to allocate. - */ -VMMR0DECL(bool) PDMR0NsAllocateBandwidth(PPDMNSFILTER pFilter, size_t cbTransfer); - -/** - * Obtain bandwidth in a bandwidth group. - * - * @returns VBox status code. - * @param pFilter Pointer to the filter that allocates bandwidth. - * @param cbTransfer Number of bytes to allocate. - */ -VMMR3DECL(bool) PDMR3NsAllocateBandwidth(PPDMNSFILTER pFilter, size_t cbTransfer); - -/** - * Attach network filter driver from bandwidth group. - * - * @returns VBox status code. - * @param pVM Handle of VM. - * @param pDrvIns The driver instance. - * @param pcszBwGroup Name of the bandwidth group to attach to. - * @param pFilter Pointer to the filter we attach. - */ -VMMR3DECL(int) PDMR3NsAttach(PVM pVM, PPDMDRVINS pDrvIns, const char *pcszBwGroup, PPDMNSFILTER pFilter); - -/** - * Detach network filter driver from bandwidth group. - * - * @returns VBox status code. - * @param pVM Handle of VM. - * @param pDrvIns The driver instance. - * @param pFilter Pointer to the filter we detach. - */ -VMMR3DECL(int) PDMR3NsDetach(PVM pVM, PPDMDRVINS pDrvIns, PPDMNSFILTER pFilter); - -/** - * Adjusts the maximum rate for the bandwidth group. - * - * @returns VBox status code. - * @param pVM Handle of VM. - * @param pcszBwGroup Name of the bandwidth group to attach to. - * @param cbTransferPerSecMax Maximum number of bytes per second to be transmitted. - */ -VMMR3DECL(int) PDMR3NsBwGroupSetLimit(PVM pVM, const char *pcszBwGroup, uint64_t cbTransferPerSecMax); +VMMDECL(bool) PDMNsAllocateBandwidth(PPDMNSFILTER pFilter, size_t cbTransfer); +VMMR3_INT_DECL(int) PDMR3NsAttach(PUVM pUVM, PPDMDRVINS pDrvIns, const char *pcszBwGroup, PPDMNSFILTER pFilter); +VMMR3_INT_DECL(int) PDMR3NsDetach(PUVM pUVM, PPDMDRVINS pDrvIns, PPDMNSFILTER pFilter); +VMMR3DECL(int) PDMR3NsBwGroupSetLimit(PUVM pUVM, const char *pszBwGroup, uint64_t cbPerSecMax); /** @} */ diff --git a/include/VBox/vmm/pdmnetshaperint.h b/include/VBox/vmm/pdmnetshaperint.h deleted file mode 100644 index 3bbfcda7..00000000 --- a/include/VBox/vmm/pdmnetshaperint.h +++ /dev/null @@ -1,94 +0,0 @@ -/* $Id: pdmnetshaperint.h $ */ -/** @file - * PDM Network Shaper - Internal data structures and functions common for both - * R0 and R3 parts. - */ - -/* - * Copyright (C) 2011-2012 Oracle Corporation - * - * This file is part of VirtualBox Open Source Edition (OSE), as - * available from http://www.virtualbox.org. This file is free software; - * you can redistribute it and/or modify it under the terms of the GNU - * General Public License (GPL) as published by the Free Software - * Foundation, in version 2 as it comes in the "COPYING" file of the - * VirtualBox OSE distribution. VirtualBox OSE is distributed in the - * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. - * - * The contents of this file may alternatively be used under the terms - * of the Common Development and Distribution License Version 1.0 - * (CDDL) only, as it comes in the "COPYING.CDDL" file of the - * VirtualBox OSE distribution, in which case the provisions of the - * CDDL are applicable instead of those of the GPL. - * - * You may elect to license modified versions of this file under the - * terms and conditions of either the GPL or the CDDL or both. - */ - -/** - * Bandwidth group instance data - */ -typedef struct PDMNSBWGROUP -{ - /** Pointer to the next group in the list. */ - struct PDMNSBWGROUP *pNext; - /** Pointer to the shared UVM structure. */ - struct PDMNETSHAPER *pShaper; - /** Critical section protecting all members below. */ - PDMCRITSECT cs; - /** Pointer to the first filter attached to this group. */ - struct PDMNSFILTER *pFiltersHead; - /** Bandwidth group name. */ - char *pszName; - /** Maximum number of bytes filters are allowed to transfer. */ - volatile uint64_t cbTransferPerSecMax; - /** Number of bytes we are allowed to transfer in one burst. */ - volatile uint32_t cbBucketSize; - /** Number of bytes we were allowed to transfer at the last update. */ - volatile uint32_t cbTokensLast; - /** Timestamp of the last update */ - volatile uint64_t tsUpdatedLast; - /** Reference counter - How many filters are associated with this group. */ - volatile uint32_t cRefs; -} PDMNSBWGROUP; -/** Pointer to a bandwidth group. */ -typedef PDMNSBWGROUP *PPDMNSBWGROUP; - -DECLINLINE(bool) pdmNsAllocateBandwidth(PPDMNSFILTER pFilter, size_t cbTransfer) -{ - AssertPtrReturn(pFilter, true); - if (!VALID_PTR(pFilter->CTX_SUFF(pBwGroup))) - return true; - - PPDMNSBWGROUP pBwGroup = ASMAtomicReadPtrT(&pFilter->CTX_SUFF(pBwGroup), PPDMNSBWGROUP); - int rc = PDMCritSectEnter(&pBwGroup->cs, VERR_SEM_BUSY); AssertRC(rc); - if (RT_UNLIKELY(rc == VERR_SEM_BUSY)) - return true; - bool fAllowed = true; - if (pBwGroup->cbTransferPerSecMax) - { - /* Re-fill the bucket first */ - uint64_t tsNow = RTTimeSystemNanoTS(); - uint32_t uTokensAdded = (tsNow - pBwGroup->tsUpdatedLast)*pBwGroup->cbTransferPerSecMax/(1000*1000*1000); - uint32_t uTokens = RT_MIN(pBwGroup->cbBucketSize, uTokensAdded + pBwGroup->cbTokensLast); - - if (cbTransfer > uTokens) - { - fAllowed = false; - ASMAtomicWriteBool(&pFilter->fChoked, true); - } - else - { - pBwGroup->tsUpdatedLast = tsNow; - pBwGroup->cbTokensLast = uTokens - (uint32_t)cbTransfer; - } - Log2((LOG_FN_FMT "BwGroup=%#p{%s} cbTransfer=%u uTokens=%u uTokensAdded=%u fAllowed=%RTbool\n", - __PRETTY_FUNCTION__, pBwGroup, pBwGroup->pszName, cbTransfer, uTokens, uTokensAdded, fAllowed)); - } - else - Log2((LOG_FN_FMT "BwGroup=%#p{%s} disabled fAllowed=%RTbool\n", - __PRETTY_FUNCTION__, pBwGroup, pBwGroup->pszName, fAllowed)); - - rc = PDMCritSectLeave(&pBwGroup->cs); AssertRC(rc); - return fAllowed; -} diff --git a/include/VBox/vmm/pdmnvram.h b/include/VBox/vmm/pdmnvram.h index 10c1abc4..03967dff 100644 --- a/include/VBox/vmm/pdmnvram.h +++ b/include/VBox/vmm/pdmnvram.h @@ -3,7 +3,7 @@ */ /* - * Copyright (C) 2012 Oracle Corporation + * Copyright (C) 2012-2013 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -36,35 +36,85 @@ RT_C_DECLS_BEGIN * @{ */ -typedef struct PDMINVRAM *PPDMINVRAM; +/** Pointer to NVRAM interface provided by the driver. */ +typedef struct PDMINVRAMCONNECTOR *PPDMINVRAMCONNECTOR; -typedef struct PDMINVRAM +/** + * Non-volatile RAM storage interface provided by the driver (up). + * + * @note The variable indexes used here 0-based, sequential and without gaps. + */ +typedef struct PDMINVRAMCONNECTOR { /** - * This method flushes all values in the storage. + * Query a variable by variable index. + * + * @returns VBox status code. + * @retval VERR_NOT_FOUND if the variable was not found. This indicates that + * there are not variables with a higher index. + * + * @param idxVariable The variable index. By starting @a idxVariable at 0 + * and increasing it with each call, this can be used + * to enumerate all available variables. + * @param pVendorUuid The vendor UUID of the variable. + * @param pszName The variable name buffer. + * @param pcchName On input this hold the name buffer size (including + * the space for the terminator char). On successful + * return it holds the strlen() value for @a pszName. + * @param pfAttributes Where to return the value attributes. + * @param pbValue The value buffer. + * @param pcbValue On input the size of the value buffer, on output the + * actual number of bytes returned. */ - DECLR3CALLBACKMEMBER(int, pfnFlushNvramStorage, (PPDMINVRAM pInterface)); + DECLR3CALLBACKMEMBER(int, pfnVarQueryByIndex,(PPDMINVRAMCONNECTOR pInterface, uint32_t idxVariable, + PRTUUID pVendorUuid, char *pszName, uint32_t *pcchName, + uint32_t *pfAttributes, uint8_t *pbValue, uint32_t *pcbValue)); /** - * This method store NVRAM variable to storage + * Begins variable store sequence. + * + * @returns VBox status code. + * @param pInterance Pointer to this interface structure. + * @param cVariables The number of variables. */ - DECLR3CALLBACKMEMBER(int, pfnStoreNvramValue, (PPDMINVRAM pInterface, int idxVariable, RTUUID *pVendorUuid, const char *pcszVariableName, size_t cbVariableName, uint8_t *pu8Value, size_t cbValue)); + DECLR3CALLBACKMEMBER(int, pfnVarStoreSeqBegin,(PPDMINVRAMCONNECTOR pInterface, uint32_t cVariables)); /** - * This method load NVRAM variable to storage + * Puts the next variable in the store sequence. + * + * @returns VBox status code. + * @param idxVariable The variable index. This will start at 0 and advance + * up to @a cVariables - 1. + * @param pVendorUuid The vendor UUID of the variable. + * @param pszName The variable name buffer. + * @param pcchName On input this hold the name buffer size (including + * the space for the terminator char). On successful + * return it holds the strlen() value for @a pszName. + * @param fAttributes The value attributes. + * @param pbValue The value buffer. + * @param pcbValue On input the size of the value buffer, on output the + * actual number of bytes returned. */ - DECLR3CALLBACKMEMBER(int, pfnLoadNvramValue, (PPDMINVRAM pInterface, int idxVariable, RTUUID *pVendorUuid, char *pcszVariableName, size_t *pcbVariableName, uint8_t *pu8Value, size_t *pcbValue)); - -} PDMINVRAM; + DECLR3CALLBACKMEMBER(int, pfnVarStoreSeqPut,(PPDMINVRAMCONNECTOR pInterface, int idxVariable, + PCRTUUID pVendorUuid, const char *pszName, size_t cchName, + uint32_t fAttributes, uint8_t const *pbValue, size_t cbValue)); + /** + * Ends a variable store sequence. + * + * @returns VBox status code, @a rc on success. + * @param pInterance Pointer to this interface structure. + * @param rc The VBox status code for the whole store operation. + */ + DECLR3CALLBACKMEMBER(int, pfnVarStoreSeqEnd,(PPDMINVRAMCONNECTOR pInterface, int rc)); -#define PDMINVRAM_IID "11226408-CB4C-4369-9218-1EE0092FB9F8" +} PDMINVRAMCONNECTOR; +/** PDMINVRAMCONNECTOR interface ID. */ +#define PDMINVRAMCONNECTOR_IID "057bc5c9-8022-43a8-9a41-0b106f97a89f" /** @} */ RT_C_DECLS_END - #endif - diff --git a/include/VBox/vmm/pdmqueue.h b/include/VBox/vmm/pdmqueue.h index 3445c85a..4edf16c3 100644 --- a/include/VBox/vmm/pdmqueue.h +++ b/include/VBox/vmm/pdmqueue.h @@ -3,7 +3,7 @@ */ /* - * Copyright (C) 2006-2011 Oracle Corporation + * Copyright (C) 2006-2013 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -65,6 +65,9 @@ typedef struct PDMQUEUEITEMCORE * If false the item will not be removed and the flushing will stop. * @param pDevIns The device instance. * @param pItem The item to consume. Upon return this item will be freed. + * @remarks The device critical section will NOT be entered before calling the + * callback. No locks will be held, but for now it's safe to assume + * that only one EMT will do queue callbacks at any one time. */ typedef DECLCALLBACK(bool) FNPDMQUEUEDEV(PPDMDEVINS pDevIns, PPDMQUEUEITEMCORE pItem); /** Pointer to a FNPDMQUEUEDEV(). */ @@ -77,6 +80,8 @@ typedef FNPDMQUEUEDEV *PFNPDMQUEUEDEV; * If false the item will not be removed and the flushing will stop. * @param pDevIns The USB device instance. * @param pItem The item to consume. Upon return this item will be freed. + * @remarks No locks will be held, but for now it's safe to assume that only one + * EMT will do queue callbacks at any one time. */ typedef DECLCALLBACK(bool) FNPDMQUEUEUSB(PPDMUSBINS pUsbIns, PPDMQUEUEITEMCORE pItem); /** Pointer to a FNPDMQUEUEUSB(). */ @@ -89,6 +94,8 @@ typedef FNPDMQUEUEUSB *PFNPDMQUEUEUSB; * If false the item will not be removed and the flushing will stop. * @param pDrvIns The driver instance. * @param pItem The item to consume. Upon return this item will be freed. + * @remarks No locks will be held, but for now it's safe to assume that only one + * EMT will do queue callbacks at any one time. */ typedef DECLCALLBACK(bool) FNPDMQUEUEDRV(PPDMDRVINS pDrvIns, PPDMQUEUEITEMCORE pItem); /** Pointer to a FNPDMQUEUEDRV(). */ @@ -101,6 +108,8 @@ typedef FNPDMQUEUEDRV *PFNPDMQUEUEDRV; * If false the item will not be removed and the flushing will stop. * @param pVM The VM handle. * @param pItem The item to consume. Upon return this item will be freed. + * @remarks No locks will be held, but for now it's safe to assume that only one + * EMT will do queue callbacks at any one time. */ typedef DECLCALLBACK(bool) FNPDMQUEUEINT(PVM pVM, PPDMQUEUEITEMCORE pItem); /** Pointer to a FNPDMQUEUEINT(). */ @@ -113,6 +122,8 @@ typedef FNPDMQUEUEINT *PFNPDMQUEUEINT; * If false the item will not be removed and the flushing will stop. * @param pvUser User argument. * @param pItem The item to consume. Upon return this item will be freed. + * @remarks No locks will be held, but for now it's safe to assume that only one + * EMT will do queue callbacks at any one time. */ typedef DECLCALLBACK(bool) FNPDMQUEUEEXT(void *pvUser, PPDMQUEUEITEMCORE pItem); /** Pointer to a FNPDMQUEUEEXT(). */ diff --git a/include/VBox/vmm/pdmusb.h b/include/VBox/vmm/pdmusb.h index ae3f5cfb..6abe2a14 100644 --- a/include/VBox/vmm/pdmusb.h +++ b/include/VBox/vmm/pdmusb.h @@ -3,7 +3,7 @@ */ /* - * Copyright (C) 2006-2010 Oracle Corporation + * Copyright (C) 2006-2013 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -113,6 +113,11 @@ typedef PDMUSBDESCCACHE *PPDMUSBDESCCACHE; typedef const PDMUSBDESCCACHE *PCPDMUSBDESCCACHE; +/** PDM Device Flags. + * @{ */ +/** A high-speed capable USB 2.0 device (also required to support full-speed). */ +#define PDM_USBREG_HIGHSPEED_CAPABLE RT_BIT(0) +/** @} */ /** PDM USB Device Registration Structure, * @@ -164,7 +169,7 @@ typedef struct PDMUSBREG * Most VM resources are freed by the VM. This callback is provided so that any non-VM * resources can be freed correctly. * - * This method will be called regardless of the pfnConstruc result to avoid + * This method will be called regardless of the pfnConstruct result to avoid * complicated failure paths. * * @param pUsbIns The USB device instance data. @@ -672,6 +677,38 @@ typedef struct PDMUSBHLP */ DECLR3CALLBACKMEMBER(void, pfnAsyncNotificationCompleted, (PPDMUSBINS pUsbIns)); + /** + * Gets the reason for the most recent VM suspend. + * + * @returns The suspend reason. VMSUSPENDREASON_INVALID is returned if no + * suspend has been made or if the pUsbIns is invalid. + * @param pUsbIns The driver instance. + */ + DECLR3CALLBACKMEMBER(VMSUSPENDREASON, pfnVMGetSuspendReason,(PPDMUSBINS pUsbIns)); + + /** + * Gets the reason for the most recent VM resume. + * + * @returns The resume reason. VMRESUMEREASON_INVALID is returned if no + * resume has been made or if the pUsbIns is invalid. + * @param pUsbIns The driver instance. + */ + DECLR3CALLBACKMEMBER(VMRESUMEREASON, pfnVMGetResumeReason,(PPDMUSBINS pUsbIns)); + + /** @name Space reserved for minor interface changes. + * @{ */ + DECLR3CALLBACKMEMBER(void, pfnReserved0,(PPDMUSBINS pUsbIns)); + DECLR3CALLBACKMEMBER(void, pfnReserved1,(PPDMUSBINS pUsbIns)); + DECLR3CALLBACKMEMBER(void, pfnReserved2,(PPDMUSBINS pUsbIns)); + DECLR3CALLBACKMEMBER(void, pfnReserved3,(PPDMUSBINS pUsbIns)); + DECLR3CALLBACKMEMBER(void, pfnReserved4,(PPDMUSBINS pUsbIns)); + DECLR3CALLBACKMEMBER(void, pfnReserved5,(PPDMUSBINS pUsbIns)); + DECLR3CALLBACKMEMBER(void, pfnReserved6,(PPDMUSBINS pUsbIns)); + DECLR3CALLBACKMEMBER(void, pfnReserved7,(PPDMUSBINS pUsbIns)); + DECLR3CALLBACKMEMBER(void, pfnReserved8,(PPDMUSBINS pUsbIns)); + DECLR3CALLBACKMEMBER(void, pfnReserved9,(PPDMUSBINS pUsbIns)); + /** @} */ + /** Just a safety precaution. */ uint32_t u32TheEnd; } PDMUSBHLP; @@ -681,7 +718,7 @@ typedef PDMUSBHLP *PPDMUSBHLP; typedef const PDMUSBHLP *PCPDMUSBHLP; /** Current USBHLP version number. */ -#define PDM_USBHLP_VERSION PDM_VERSION_MAKE(0xeefe, 2, 0) +#define PDM_USBHLP_VERSION PDM_VERSION_MAKE(0xeefe, 3, 0) #endif /* IN_RING3 */ @@ -732,9 +769,12 @@ typedef struct PDMUSBINS uint32_t fTracing; /** The tracing ID of this device. */ uint32_t idTracing; + /** The USB version of the hub this device is attached to. Used to + * determine whether the device communicates at high-speed or full-/low-speed. */ + uint32_t iUsbHubVersion; /** Padding to make achInstanceData aligned at 32 byte boundary. */ - uint32_t au32Padding[HC_ARCH_BITS == 32 ? 3 : 4]; + uint32_t au32Padding[HC_ARCH_BITS == 32 ? 2 : 3]; /** Device instance data. The size of this area is defined * in the PDMUSBREG::cbInstanceData field. */ @@ -991,10 +1031,11 @@ typedef struct PDMUSBREGCB */ typedef DECLCALLBACK(int) FNPDMVBOXUSBREGISTER(PCPDMUSBREGCB pCallbacks, uint32_t u32Version); -VMMR3DECL(int) PDMR3USBCreateProxyDevice(PVM pVM, PCRTUUID pUuid, bool fRemote, const char *pszAddress, void *pvBackend, +VMMR3DECL(int) PDMR3UsbCreateEmulatedDevice(PUVM pUVM, const char *pszDeviceName, PCFGMNODE pDeviceNode, PCRTUUID pUuid); +VMMR3DECL(int) PDMR3UsbCreateProxyDevice(PUVM pUVM, PCRTUUID pUuid, bool fRemote, const char *pszAddress, void *pvBackend, uint32_t iUsbVersion, uint32_t fMaskedIfs); -VMMR3DECL(int) PDMR3USBDetachDevice(PVM pVM, PCRTUUID pUuid); -VMMR3DECL(bool) PDMR3USBHasHub(PVM pVM); +VMMR3DECL(int) PDMR3UsbDetachDevice(PUVM pUVM, PCRTUUID pUuid); +VMMR3DECL(bool) PDMR3UsbHasHub(PUVM pUVM); /** @} */ diff --git a/include/VBox/vmm/pdmwebcaminfs.h b/include/VBox/vmm/pdmwebcaminfs.h new file mode 100644 index 00000000..40b01614 --- /dev/null +++ b/include/VBox/vmm/pdmwebcaminfs.h @@ -0,0 +1,133 @@ +/* $Id: pdmwebcaminfs.h $ */ + +/** @file + * webcaminfs - interfaces between dev and driver. + */ + +/* + * Copyright (C) 2011-2013 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL) only, as it comes in the "COPYING.CDDL" file of the + * VirtualBox OSE distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + */ + +#ifndef ___VBox_vmm_pdmwebcaminfs_h +#define ___VBox_vmm_pdmwebcaminfs_h + + +typedef struct PDMIWEBCAM_DEVICEDESC PDMIWEBCAM_DEVICEDESC; +typedef struct PDMIWEBCAM_CTRLHDR PDMIWEBCAM_CTRLHDR; +typedef struct PDMIWEBCAM_FRAMEHDR PDMIWEBCAM_FRAMEHDR; + + +#define PDMIWEBCAMDOWN_IID "0d29b9a1-f4cd-4719-a564-38d5634ba9f8" +typedef struct PDMIWEBCAMDOWN *PPDMIWEBCAMDOWN; +typedef struct PDMIWEBCAMDOWN +{ + /* + * The PDM device is ready to get webcam notifications. + * + * @param pInterface Pointer to the interface. + * @param fReady Whether the device is ready. + */ + DECLR3CALLBACKMEMBER(void, pfnWebcamDownReady, (PPDMIWEBCAMDOWN pInterface, + bool fReady)); + + /* + * Send a control request to the webcam. + * Async response will be returned by pfnWebcamUpControl callback. + * + * @param pInterface Pointer to the interface. + * @param pvUser The callers context. + * @param u64DeviceId Unique id for the reported webcam assigned by the driver. + * @param pCtrl The control data. + * @param cbCtrl The size of the control data. + */ + DECLR3CALLBACKMEMBER(int, pfnWebcamDownControl, (PPDMIWEBCAMDOWN pInterface, + void *pvUser, + uint64_t u64DeviceId, + const PDMIWEBCAM_CTRLHDR *pCtrl, + uint32_t cbCtrl)); +} PDMIWEBCAMDOWN; + + +#define PDMIWEBCAMUP_IID "6ac03e3c-f56c-4a35-80af-c13ce47a9dd7" +typedef struct PDMIWEBCAMUP *PPDMIWEBCAMUP; +typedef struct PDMIWEBCAMUP +{ + /* + * A webcam is available. + * + * @param pInterface Pointer to the interface. + * @param u64DeviceId Unique id for the reported webcam assigned by the driver. + * @param pDeviceDesc The device description. + * @param cbDeviceDesc The size of the device description. + * @param u32Version The remote video input protocol version. + * @param fu32Capabilities The remote video input protocol capabilities. + */ + DECLR3CALLBACKMEMBER(int, pfnWebcamUpAttached,(PPDMIWEBCAMUP pInterface, + uint64_t u64DeviceId, + const PDMIWEBCAM_DEVICEDESC *pDeviceDesc, + uint32_t cbDeviceDesc, + uint32_t u32Version, + uint32_t fu32Capabilities)); + + /* + * The webcam is not available anymore. + * + * @param pInterface Pointer to the interface. + * @param u64DeviceId Unique id for the reported webcam assigned by the driver. + */ + DECLR3CALLBACKMEMBER(void, pfnWebcamUpDetached,(PPDMIWEBCAMUP pInterface, + uint64_t u64DeviceId)); + + /* + * There is a control response or a control change for the webcam. + * + * @param pInterface Pointer to the interface. + * @param fResponse True if this is a response for a previous pfnWebcamDownControl call. + * @param pvUser The pvUser parameter of the pfnWebcamDownControl call. Undefined if fResponse == false. + * @param u64DeviceId Unique id for the reported webcam assigned by the driver. + * @param pCtrl The control data. + * @param cbCtrl The size of the control data. + */ + DECLR3CALLBACKMEMBER(void, pfnWebcamUpControl,(PPDMIWEBCAMUP pInterface, + bool fResponse, + void *pvUser, + uint64_t u64DeviceId, + const PDMIWEBCAM_CTRLHDR *pCtrl, + uint32_t cbCtrl)); + + /* + * A new frame. + * + * @param pInterface Pointer to the interface. + * @param u64DeviceId Unique id for the reported webcam assigned by the driver. + * @param pHeader Payload header. + * @param cbHeader Size of the payload header. + * @param pvFrame Frame (image) data. + * @param cbFrame Size of the image data. + */ + DECLR3CALLBACKMEMBER(void, pfnWebcamUpFrame,(PPDMIWEBCAMUP pInterface, + uint64_t u64DeviceId, + PDMIWEBCAM_FRAMEHDR *pHeader, + uint32_t cbHeader, + const void *pvFrame, + uint32_t cbFrame)); +} PDMIWEBCAMUP; + +#endif diff --git a/include/VBox/vmm/pgm.h b/include/VBox/vmm/pgm.h index 5d8b5f0d..7e397b2a 100644 --- a/include/VBox/vmm/pgm.h +++ b/include/VBox/vmm/pgm.h @@ -3,7 +3,7 @@ */ /* - * Copyright (C) 2006-2010 Oracle Corporation + * Copyright (C) 2006-2013 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -333,13 +333,14 @@ VMMDECL(bool) PGMGstIsPagePresent(PVMCPU pVCpu, RTGCPTR GCPtr); VMMDECL(int) PGMGstSetPage(PVMCPU pVCpu, RTGCPTR GCPtr, size_t cb, uint64_t fFlags); VMMDECL(int) PGMGstModifyPage(PVMCPU pVCpu, RTGCPTR GCPtr, size_t cb, uint64_t fFlags, uint64_t fMask); VMM_INT_DECL(int) PGMGstGetPaePdpes(PVMCPU pVCpu, PX86PDPE paPdpes); -VMM_INT_DECL(int) PGMGstUpdatePaePdpes(PVMCPU pVCpu, PCX86PDPE paPdpes); +VMM_INT_DECL(void) PGMGstUpdatePaePdpes(PVMCPU pVCpu, PCX86PDPE paPdpes); VMMDECL(int) PGMInvalidatePage(PVMCPU pVCpu, RTGCPTR GCPtrPage); VMMDECL(int) PGMFlushTLB(PVMCPU pVCpu, uint64_t cr3, bool fGlobal); VMMDECL(int) PGMSyncCR3(PVMCPU pVCpu, uint64_t cr0, uint64_t cr3, uint64_t cr4, bool fGlobal); VMMDECL(int) PGMUpdateCR3(PVMCPU pVCpu, uint64_t cr3); VMMDECL(int) PGMChangeMode(PVMCPU pVCpu, uint64_t cr0, uint64_t cr4, uint64_t efer); +VMMDECL(void) PGMCr0WpEnabled(PVMCPU pVCpu); VMMDECL(PGMMODE) PGMGetGuestMode(PVMCPU pVCpu); VMMDECL(PGMMODE) PGMGetShadowMode(PVMCPU pVCpu); VMMDECL(PGMMODE) PGMGetHostMode(PVM pVM); @@ -383,7 +384,9 @@ VMMDECL(int) PGMPhysSimpleDirtyWriteGCPtr(PVMCPU pVCpu, RTGCPTR GCPtrDst, VMMDECL(int) PGMPhysInterpretedRead(PVMCPU pVCpu, PCPUMCTXCORE pCtxCore, void *pvDst, RTGCPTR GCPtrSrc, size_t cb); VMMDECL(int) PGMPhysInterpretedReadNoHandlers(PVMCPU pVCpu, PCPUMCTXCORE pCtxCore, void *pvDst, RTGCUINTPTR GCPtrSrc, size_t cb, bool fRaiseTrap); VMMDECL(int) PGMPhysInterpretedWriteNoHandlers(PVMCPU pVCpu, PCPUMCTXCORE pCtxCore, RTGCPTR GCPtrDst, void const *pvSrc, size_t cb, bool fRaiseTrap); -VMM_INT_DECL(int) PGMPhysIemGCPhys2Ptr(PVM pVM, RTGCPHYS GCPhys, bool fWritable, bool fByPassHandlers, void **ppv, PPGMPAGEMAPLOCK pLock); +VMM_INT_DECL(int) PGMPhysIemGCPhys2Ptr(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys, bool fWritable, bool fByPassHandlers, void **ppv, PPGMPAGEMAPLOCK pLock); +VMM_INT_DECL(int) PGMPhysIemQueryAccess(PVM pVM, RTGCPHYS GCPhys, bool fWritable, bool fByPassHandlers); + #ifdef VBOX_STRICT VMMDECL(unsigned) PGMAssertHandlerAndFlagsInSync(PVM pVM); VMMDECL(unsigned) PGMAssertNoMappingConflicts(PVM pVM); @@ -455,8 +458,9 @@ VMMR3DECL(int) PGMR3InitDynMap(PVM pVM); VMMR3DECL(int) PGMR3InitFinalize(PVM pVM); VMMR3_INT_DECL(int) PGMR3InitCompleted(PVM pVM, VMINITCOMPLETED enmWhat); VMMR3DECL(void) PGMR3Relocate(PVM pVM, RTGCINTPTR offDelta); -VMMR3DECL(void) PGMR3ResetUnpluggedCpu(PVM pVM, PVMCPU pVCpu); -VMMR3DECL(void) PGMR3Reset(PVM pVM); +VMMR3DECL(void) PGMR3ResetCpu(PVM pVM, PVMCPU pVCpu); +VMMR3_INT_DECL(void) PGMR3Reset(PVM pVM); +VMMR3_INT_DECL(void) PGMR3MemSetup(PVM pVM, bool fReset); VMMR3DECL(int) PGMR3Term(PVM pVM); VMMR3DECL(int) PGMR3LockCall(PVM pVM); VMMR3DECL(int) PGMR3ChangeMode(PVM pVM, PVMCPU pVCpu, PGMMODE enmGuestMode); @@ -468,8 +472,8 @@ VMMR3DECL(int) PGMR3PhysEnumDirtyFTPages(PVM pVM, PFNPGMENUMDIRTYFTPAGES pf VMMR3DECL(uint32_t) PGMR3PhysGetRamRangeCount(PVM pVM); VMMR3DECL(int) PGMR3PhysGetRange(PVM pVM, uint32_t iRange, PRTGCPHYS pGCPhysStart, PRTGCPHYS pGCPhysLast, const char **ppszDesc, bool *pfIsMmio); -VMMR3DECL(int) PGMR3QueryMemoryStats(PVM pVM, uint64_t *pcbTotalMem, uint64_t *pcbPrivateMem, uint64_t *pcbSharedMem, uint64_t *pcbZeroMem); -VMMR3DECL(int) PGMR3QueryGlobalMemoryStats(PVM pVM, uint64_t *pcbAllocMem, uint64_t *pcbFreeMem, uint64_t *pcbBallonedMem, uint64_t *pcbSharedMem); +VMMR3DECL(int) PGMR3QueryMemoryStats(PUVM pUVM, uint64_t *pcbTotalMem, uint64_t *pcbPrivateMem, uint64_t *pcbSharedMem, uint64_t *pcbZeroMem); +VMMR3DECL(int) PGMR3QueryGlobalMemoryStats(PUVM pUVM, uint64_t *pcbAllocMem, uint64_t *pcbFreeMem, uint64_t *pcbBallonedMem, uint64_t *pcbSharedMem); VMMR3DECL(int) PGMR3PhysMMIORegister(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, R3PTRTYPE(PFNPGMR3PHYSHANDLER) pfnHandlerR3, RTR3PTR pvUserR3, @@ -507,12 +511,13 @@ VMMDECL(void) PGMR3PhysSetA20(PVMCPU pVCpu, bool fEnable); VMMR3DECL(int) PGMR3MapPT(PVM pVM, RTGCPTR GCPtr, uint32_t cb, uint32_t fFlags, PFNPGMRELOCATE pfnRelocate, void *pvUser, const char *pszDesc); VMMR3DECL(int) PGMR3UnmapPT(PVM pVM, RTGCPTR GCPtr); VMMR3DECL(int) PGMR3FinalizeMappings(PVM pVM); -VMMR3DECL(int) PGMR3MappingsDisable(PVM pVM); VMMR3DECL(int) PGMR3MappingsSize(PVM pVM, uint32_t *pcb); VMMR3DECL(int) PGMR3MappingsFix(PVM pVM, RTGCPTR GCPtrBase, uint32_t cb); VMMR3DECL(int) PGMR3MappingsUnfix(PVM pVM); VMMR3DECL(bool) PGMR3MappingsNeedReFixing(PVM pVM); +#if defined(VBOX_WITH_RAW_MODE) || (HC_ARCH_BITS != 64 && !defined(VBOX_WITH_HYBRID_32BIT_KERNEL)) VMMR3DECL(int) PGMR3MapIntermediate(PVM pVM, RTUINTPTR Addr, RTHCPHYS HCPhys, unsigned cbPages); +#endif VMMR3DECL(int) PGMR3MapRead(PVM pVM, void *pvDst, RTGCPTR GCPtrSrc, size_t cb); VMMR3DECL(int) PGMR3HandlerPhysicalRegister(PVM pVM, PGMPHYSHANDLERTYPE enmType, RTGCPHYS GCPhys, RTGCPHYS GCPhysLast, @@ -552,15 +557,15 @@ VMMR3DECL(int) PGMR3PhysAllocateLargeHandyPage(PVM pVM, RTGCPHYS GCPhys); VMMR3DECL(int) PGMR3CheckIntegrity(PVM pVM); -VMMR3DECL(int) PGMR3DbgR3Ptr2GCPhys(PVM pVM, RTR3PTR R3Ptr, PRTGCPHYS pGCPhys); -VMMR3DECL(int) PGMR3DbgR3Ptr2HCPhys(PVM pVM, RTR3PTR R3Ptr, PRTHCPHYS pHCPhys); -VMMR3DECL(int) PGMR3DbgHCPhys2GCPhys(PVM pVM, RTHCPHYS HCPhys, PRTGCPHYS pGCPhys); -VMMR3DECL(int) PGMR3DbgReadGCPhys(PVM pVM, void *pvDst, RTGCPHYS GCPhysSrc, size_t cb, uint32_t fFlags, size_t *pcbRead); -VMMR3DECL(int) PGMR3DbgWriteGCPhys(PVM pVM, RTGCPHYS GCPhysDst, const void *pvSrc, size_t cb, uint32_t fFlags, size_t *pcbWritten); -VMMR3DECL(int) PGMR3DbgReadGCPtr(PVM pVM, void *pvDst, RTGCPTR GCPtrSrc, size_t cb, uint32_t fFlags, size_t *pcbRead); -VMMR3DECL(int) PGMR3DbgWriteGCPtr(PVM pVM, RTGCPTR GCPtrDst, void const *pvSrc, size_t cb, uint32_t fFlags, size_t *pcbWritten); -VMMR3DECL(int) PGMR3DbgScanPhysical(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cbRange, RTGCPHYS GCPhysAlign, const uint8_t *pabNeedle, size_t cbNeedle, PRTGCPHYS pGCPhysHit); -VMMR3DECL(int) PGMR3DbgScanVirtual(PVM pVM, PVMCPU pVCpu, RTGCPTR GCPtr, RTGCPTR cbRange, RTGCPTR GCPtrAlign, const uint8_t *pabNeedle, size_t cbNeedle, PRTGCUINTPTR pGCPhysHit); +VMMR3DECL(int) PGMR3DbgR3Ptr2GCPhys(PUVM pUVM, RTR3PTR R3Ptr, PRTGCPHYS pGCPhys); +VMMR3DECL(int) PGMR3DbgR3Ptr2HCPhys(PUVM pUVM, RTR3PTR R3Ptr, PRTHCPHYS pHCPhys); +VMMR3DECL(int) PGMR3DbgHCPhys2GCPhys(PUVM pUVM, RTHCPHYS HCPhys, PRTGCPHYS pGCPhys); +VMMR3_INT_DECL(int) PGMR3DbgReadGCPhys(PVM pVM, void *pvDst, RTGCPHYS GCPhysSrc, size_t cb, uint32_t fFlags, size_t *pcbRead); +VMMR3_INT_DECL(int) PGMR3DbgWriteGCPhys(PVM pVM, RTGCPHYS GCPhysDst, const void *pvSrc, size_t cb, uint32_t fFlags, size_t *pcbWritten); +VMMR3_INT_DECL(int) PGMR3DbgReadGCPtr(PVM pVM, void *pvDst, RTGCPTR GCPtrSrc, size_t cb, uint32_t fFlags, size_t *pcbRead); +VMMR3_INT_DECL(int) PGMR3DbgWriteGCPtr(PVM pVM, RTGCPTR GCPtrDst, void const *pvSrc, size_t cb, uint32_t fFlags, size_t *pcbWritten); +VMMR3_INT_DECL(int) PGMR3DbgScanPhysical(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cbRange, RTGCPHYS GCPhysAlign, const uint8_t *pabNeedle, size_t cbNeedle, PRTGCPHYS pGCPhysHit); +VMMR3_INT_DECL(int) PGMR3DbgScanVirtual(PVM pVM, PVMCPU pVCpu, RTGCPTR GCPtr, RTGCPTR cbRange, RTGCPTR GCPtrAlign, const uint8_t *pabNeedle, size_t cbNeedle, PRTGCUINTPTR pGCPhysHit); VMMR3_INT_DECL(int) PGMR3DumpHierarchyShw(PVM pVM, uint64_t cr3, uint32_t fFlags, uint64_t u64FirstAddr, uint64_t u64LastAddr, uint32_t cMaxDepth, PCDBGFINFOHLP pHlp); VMMR3_INT_DECL(int) PGMR3DumpHierarchyGst(PVM pVM, uint64_t cr3, uint32_t fFlags, RTGCPTR FirstAddr, RTGCPTR LastAddr, uint32_t cMaxDepth, PCDBGFINFOHLP pHlp); diff --git a/include/VBox/vmm/rem.h b/include/VBox/vmm/rem.h index 79a18810..bda6e29a 100644 --- a/include/VBox/vmm/rem.h +++ b/include/VBox/vmm/rem.h @@ -3,7 +3,7 @@ */ /* - * Copyright (C) 2006-2010 Oracle Corporation + * Copyright (C) 2006-2011 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; diff --git a/include/VBox/vmm/selm.h b/include/VBox/vmm/selm.h index 763d0acf..7503e734 100644 --- a/include/VBox/vmm/selm.h +++ b/include/VBox/vmm/selm.h @@ -41,7 +41,6 @@ RT_C_DECLS_BEGIN VMMDECL(RTSEL) SELMGetTrap8Selector(PVM pVM); VMMDECL(void) SELMSetTrap8EIP(PVM pVM, uint32_t u32EIP); VMMDECL(int) SELMGetRing1Stack(PVM pVM, uint32_t *pSS, PRTGCPTR32 pEsp); -VMMDECL(RTGCPTR) SELMGetGuestTSS(PVM pVM); VMMDECL(RTSEL) SELMGetHyperCS(PVM pVM); VMMDECL(RTSEL) SELMGetHyperCS64(PVM pVM); VMMDECL(RTSEL) SELMGetHyperDS(PVM pVM); @@ -94,11 +93,12 @@ VMMR3DECL(int) SELMR3InitFinalize(PVM pVM); VMMR3DECL(void) SELMR3Relocate(PVM pVM); VMMR3DECL(int) SELMR3Term(PVM pVM); VMMR3DECL(void) SELMR3Reset(PVM pVM); +# ifdef VBOX_WITH_RAW_MODE VMMR3DECL(VBOXSTRICTRC) SELMR3UpdateFromCPUM(PVM pVM, PVMCPU pVCpu); VMMR3DECL(int) SELMR3SyncTSS(PVM pVM, PVMCPU pVCpu); +# endif VMMR3DECL(int) SELMR3GetSelectorInfo(PVM pVM, PVMCPU pVCpu, RTSEL Sel, PDBGFSELINFO pSelInfo); VMMR3DECL(int) SELMR3GetShadowSelectorInfo(PVM pVM, RTSEL Sel, PDBGFSELINFO pSelInfo); -VMMR3DECL(void) SELMR3DisableMonitoring(PVM pVM); VMMR3DECL(void) SELMR3DumpDescriptor(X86DESC Desc, RTSEL Sel, const char *pszMsg); VMMR3DECL(void) SELMR3DumpHyperGDT(PVM pVM); VMMR3DECL(void) SELMR3DumpHyperLDT(PVM pVM); @@ -106,6 +106,10 @@ VMMR3DECL(void) SELMR3DumpGuestGDT(PVM pVM); VMMR3DECL(void) SELMR3DumpGuestLDT(PVM pVM); VMMR3DECL(bool) SELMR3CheckTSS(PVM pVM); VMMR3DECL(int) SELMR3DebugCheck(PVM pVM); +# ifdef VBOX_WITH_SAFE_STR +VMMR3DECL(bool) SELMR3CheckShadowTR(PVM pVM); +# endif + /** @def SELMR3_DEBUG_CHECK * Invokes SELMR3DebugCheck in stricts builds. */ # ifdef VBOX_STRICT diff --git a/include/VBox/vmm/ssm.h b/include/VBox/vmm/ssm.h index 427e0796..8218930f 100644 --- a/include/VBox/vmm/ssm.h +++ b/include/VBox/vmm/ssm.h @@ -3,7 +3,7 @@ */ /* - * Copyright (C) 2006-2010 Oracle Corporation + * Copyright (C) 2006-2013 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -377,7 +377,11 @@ typedef struct SSMFIELD #define SSMSTRUCT_FLAGS_DONT_IGNORE RT_BIT_32(2) /** Saved using SSMR3PutMem, don't be too strict. */ #define SSMSTRUCT_FLAGS_SAVED_AS_MEM RT_BIT_32(3) -/** Band-aid for old SSMR3PutMem/SSMR3GetMem of structurs with host pointers. */ +/** Band-aid for old SSMR3PutMem/SSMR3GetMem of structurs with host pointers. + * @remarks This type is normally only used up to the first changes to the + * structures take place in order to make sure the conversion from + * SSMR3PutMem to field descriptors went smoothly. Replace with + * SSMSTRUCT_FLAGS_MEM_BAND_AID_RELAXED when changing the structure. */ #define SSMSTRUCT_FLAGS_MEM_BAND_AID ( SSMSTRUCT_FLAGS_DONT_IGNORE | SSMSTRUCT_FLAGS_FULL_STRUCT \ | SSMSTRUCT_FLAGS_NO_MARKERS | SSMSTRUCT_FLAGS_SAVED_AS_MEM) /** Band-aid for old SSMR3PutMem/SSMR3GetMem of structurs with host @@ -399,6 +403,7 @@ typedef struct SSMFIELD * @returns VBox status code. * @param pDevIns Device instance of the device which registered the data unit. * @param pSSM SSM operation handle. + * @remarks The caller enters the device critical section prior to the call. * @thread Any. */ typedef DECLCALLBACK(int) FNSSMDEVLIVEPREP(PPDMDEVINS pDevIns, PSSMHANDLE pSSM); @@ -415,6 +420,7 @@ typedef FNSSMDEVLIVEPREP *PFNSSMDEVLIVEPREP; * @param pDevIns Device instance of the device which registered the data unit. * @param pSSM SSM operation handle. * @param uPass The pass. + * @remarks The caller enters the device critical section prior to the call. * @thread Any. */ typedef DECLCALLBACK(int) FNSSMDEVLIVEEXEC(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uPass); @@ -437,6 +443,7 @@ typedef FNSSMDEVLIVEEXEC *PFNSSMDEVLIVEEXEC; * @param pDevIns Device instance of the device which registered the data unit. * @param pSSM SSM operation handle. * @param uPass The data pass. + * @remarks The caller enters the device critical section prior to the call. * @thread Any. */ typedef DECLCALLBACK(int) FNSSMDEVLIVEVOTE(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uPass); @@ -449,6 +456,7 @@ typedef FNSSMDEVLIVEVOTE *PFNSSMDEVLIVEVOTE; * @returns VBox status code. * @param pDevIns Device instance of the device which registered the data unit. * @param pSSM SSM operation handle. + * @remarks The caller enters the device critical section prior to the call. */ typedef DECLCALLBACK(int) FNSSMDEVSAVEPREP(PPDMDEVINS pDevIns, PSSMHANDLE pSSM); /** Pointer to a FNSSMDEVSAVEPREP() function. */ @@ -460,6 +468,7 @@ typedef FNSSMDEVSAVEPREP *PFNSSMDEVSAVEPREP; * @returns VBox status code. * @param pDevIns Device instance of the device which registered the data unit. * @param pSSM SSM operation handle. + * @remarks The caller enters the device critical section prior to the call. */ typedef DECLCALLBACK(int) FNSSMDEVSAVEEXEC(PPDMDEVINS pDevIns, PSSMHANDLE pSSM); /** Pointer to a FNSSMDEVSAVEEXEC() function. */ @@ -471,6 +480,7 @@ typedef FNSSMDEVSAVEEXEC *PFNSSMDEVSAVEEXEC; * @returns VBox status code. * @param pDevIns Device instance of the device which registered the data unit. * @param pSSM SSM operation handle. + * @remarks The caller enters the device critical section prior to the call. */ typedef DECLCALLBACK(int) FNSSMDEVSAVEDONE(PPDMDEVINS pDevIns, PSSMHANDLE pSSM); /** Pointer to a FNSSMDEVSAVEDONE() function. */ @@ -482,6 +492,7 @@ typedef FNSSMDEVSAVEDONE *PFNSSMDEVSAVEDONE; * @returns VBox status code. * @param pDevIns Device instance of the device which registered the data unit. * @param pSSM SSM operation handle. + * @remarks The caller enters the device critical section prior to the call. */ typedef DECLCALLBACK(int) FNSSMDEVLOADPREP(PPDMDEVINS pDevIns, PSSMHANDLE pSSM); /** Pointer to a FNSSMDEVLOADPREP() function. */ @@ -496,6 +507,7 @@ typedef FNSSMDEVLOADPREP *PFNSSMDEVLOADPREP; * @param uVersion Data layout version. * @param uPass The pass. This is always SSM_PASS_FINAL for units * that doesn't specify a pfnSaveLive callback. + * @remarks The caller enters the device critical section prior to the call. */ typedef DECLCALLBACK(int) FNSSMDEVLOADEXEC(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass); /** Pointer to a FNSSMDEVLOADEXEC() function. */ @@ -507,6 +519,7 @@ typedef FNSSMDEVLOADEXEC *PFNSSMDEVLOADEXEC; * @returns VBox load code. * @param pDevIns Device instance of the device which registered the data unit. * @param pSSM SSM operation handle. + * @remarks The caller enters the device critical section prior to the call. */ typedef DECLCALLBACK(int) FNSSMDEVLOADDONE(PPDMDEVINS pDevIns, PSSMHANDLE pSSM); /** Pointer to a FNSSMDEVLOADDONE() function. */ @@ -1131,22 +1144,28 @@ typedef struct SSMSTRMOPS VMMR3_INT_DECL(void) SSMR3Term(PVM pVM); -VMMR3DECL(int) SSMR3RegisterDevice(PVM pVM, PPDMDEVINS pDevIns, const char *pszName, uint32_t uInstance, uint32_t uVersion, size_t cbGuess, const char *pszBefore, - PFNSSMDEVLIVEPREP pfnLivePrep, PFNSSMDEVLIVEEXEC pfnLiveExec, PFNSSMDEVLIVEVOTE pfnLiveVote, - PFNSSMDEVSAVEPREP pfnSavePrep, PFNSSMDEVSAVEEXEC pfnSaveExec, PFNSSMDEVSAVEDONE pfnSaveDone, - PFNSSMDEVLOADPREP pfnLoadPrep, PFNSSMDEVLOADEXEC pfnLoadExec, PFNSSMDEVLOADDONE pfnLoadDone); -VMMR3DECL(int) SSMR3RegisterDriver(PVM pVM, PPDMDRVINS pDrvIns, const char *pszName, uint32_t uInstance, uint32_t uVersion, size_t cbGuess, - PFNSSMDRVLIVEPREP pfnLivePrep, PFNSSMDRVLIVEEXEC pfnLiveExec, PFNSSMDRVLIVEVOTE pfnLiveVote, - PFNSSMDRVSAVEPREP pfnSavePrep, PFNSSMDRVSAVEEXEC pfnSaveExec, PFNSSMDRVSAVEDONE pfnSaveDone, - PFNSSMDRVLOADPREP pfnLoadPrep, PFNSSMDRVLOADEXEC pfnLoadExec, PFNSSMDRVLOADDONE pfnLoadDone); -VMMR3DECL(int) SSMR3RegisterInternal(PVM pVM, const char *pszName, uint32_t uInstance, uint32_t uVersion, size_t cbGuess, - PFNSSMINTLIVEPREP pfnLivePrep, PFNSSMINTLIVEEXEC pfnLiveExec, PFNSSMINTLIVEVOTE pfnLiveVote, - PFNSSMINTSAVEPREP pfnSavePrep, PFNSSMINTSAVEEXEC pfnSaveExec, PFNSSMINTSAVEDONE pfnSaveDone, - PFNSSMINTLOADPREP pfnLoadPrep, PFNSSMINTLOADEXEC pfnLoadExec, PFNSSMINTLOADDONE pfnLoadDone); -VMMR3DECL(int) SSMR3RegisterExternal(PVM pVM, const char *pszName, uint32_t uInstance, uint32_t uVersion, size_t cbGuess, - PFNSSMEXTLIVEPREP pfnLivePrep, PFNSSMEXTLIVEEXEC pfnLiveExec, PFNSSMEXTLIVEVOTE pfnLiveVote, - PFNSSMEXTSAVEPREP pfnSavePrep, PFNSSMEXTSAVEEXEC pfnSaveExec, PFNSSMEXTSAVEDONE pfnSaveDone, - PFNSSMEXTLOADPREP pfnLoadPrep, PFNSSMEXTLOADEXEC pfnLoadExec, PFNSSMEXTLOADDONE pfnLoadDone, void *pvUser); +VMMR3_INT_DECL(int) +SSMR3RegisterDevice(PVM pVM, PPDMDEVINS pDevIns, const char *pszName, uint32_t uInstance, uint32_t uVersion, + size_t cbGuess, const char *pszBefore, + PFNSSMDEVLIVEPREP pfnLivePrep, PFNSSMDEVLIVEEXEC pfnLiveExec, PFNSSMDEVLIVEVOTE pfnLiveVote, + PFNSSMDEVSAVEPREP pfnSavePrep, PFNSSMDEVSAVEEXEC pfnSaveExec, PFNSSMDEVSAVEDONE pfnSaveDone, + PFNSSMDEVLOADPREP pfnLoadPrep, PFNSSMDEVLOADEXEC pfnLoadExec, PFNSSMDEVLOADDONE pfnLoadDone); +VMMR3_INT_DECL(int) +SSMR3RegisterDriver(PVM pVM, PPDMDRVINS pDrvIns, const char *pszName, uint32_t uInstance, uint32_t uVersion, size_t cbGuess, + PFNSSMDRVLIVEPREP pfnLivePrep, PFNSSMDRVLIVEEXEC pfnLiveExec, PFNSSMDRVLIVEVOTE pfnLiveVote, + PFNSSMDRVSAVEPREP pfnSavePrep, PFNSSMDRVSAVEEXEC pfnSaveExec, PFNSSMDRVSAVEDONE pfnSaveDone, + PFNSSMDRVLOADPREP pfnLoadPrep, PFNSSMDRVLOADEXEC pfnLoadExec, PFNSSMDRVLOADDONE pfnLoadDone); +VMMR3DECL(int) +SSMR3RegisterInternal(PVM pVM, const char *pszName, uint32_t uInstance, uint32_t uVersion, size_t cbGuess, + PFNSSMINTLIVEPREP pfnLivePrep, PFNSSMINTLIVEEXEC pfnLiveExec, PFNSSMINTLIVEVOTE pfnLiveVote, + PFNSSMINTSAVEPREP pfnSavePrep, PFNSSMINTSAVEEXEC pfnSaveExec, PFNSSMINTSAVEDONE pfnSaveDone, + PFNSSMINTLOADPREP pfnLoadPrep, PFNSSMINTLOADEXEC pfnLoadExec, PFNSSMINTLOADDONE pfnLoadDone); +VMMR3DECL(int) +SSMR3RegisterExternal(PUVM pUVM, const char *pszName, uint32_t uInstance, uint32_t uVersion, size_t cbGuess, + PFNSSMEXTLIVEPREP pfnLivePrep, PFNSSMEXTLIVEEXEC pfnLiveExec, PFNSSMEXTLIVEVOTE pfnLiveVote, + PFNSSMEXTSAVEPREP pfnSavePrep, PFNSSMEXTSAVEEXEC pfnSaveExec, PFNSSMEXTSAVEDONE pfnSaveDone, + PFNSSMEXTLOADPREP pfnLoadPrep, PFNSSMEXTLOADEXEC pfnLoadExec, PFNSSMEXTLOADDONE pfnLoadDone, void *pvUser); +VMMR3DECL(int) SSMR3RegisterStub(PVM pVM, const char *pszName, uint32_t uInstance); VMMR3_INT_DECL(int) SSMR3DeregisterDevice(PVM pVM, PPDMDEVINS pDevIns, const char *pszName, uint32_t uInstance); VMMR3_INT_DECL(int) SSMR3DeregisterDriver(PVM pVM, PPDMDRVINS pDrvIns, const char *pszName, uint32_t uInstance); VMMR3DECL(int) SSMR3DeregisterInternal(PVM pVM, const char *pszName); @@ -1176,7 +1195,7 @@ VMMR3DECL(uint32_t) SSMR3HandleVersion(PSSMHANDLE pSSM); VMMR3DECL(const char *) SSMR3HandleHostOSAndArch(PSSMHANDLE pSSM); VMMR3_INT_DECL(int) SSMR3HandleSetGCPtrSize(PSSMHANDLE pSSM, unsigned cbGCPtr); VMMR3DECL(void) SSMR3HandleReportLivePercent(PSSMHANDLE pSSM, unsigned uPercent); -VMMR3DECL(int) SSMR3Cancel(PVM pVM); +VMMR3DECL(int) SSMR3Cancel(PUVM pUVM); /** Save operations. diff --git a/include/VBox/vmm/stam.h b/include/VBox/vmm/stam.h index c25c606f..e7f2c556 100644 --- a/include/VBox/vmm/stam.h +++ b/include/VBox/vmm/stam.h @@ -3,7 +3,7 @@ */ /* - * Copyright (C) 2006-2010 Oracle Corporation + * Copyright (C) 2006-2013 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -1200,38 +1200,17 @@ VMMR3DECL(int) STAMR3RegisterCallback(PVM pVM, void *pvSample, STAMVISIBILITY e VMMR3DECL(int) STAMR3RegisterCallbackV(PVM pVM, void *pvSample, STAMVISIBILITY enmVisibility, STAMUNIT enmUnit, PFNSTAMR3CALLBACKRESET pfnReset, PFNSTAMR3CALLBACKPRINT pfnPrint, const char *pszDesc, const char *pszName, va_list args); -VMMR3DECL(int) STAMR3DeregisterU(PUVM pUVM, void *pvSample); -VMMR3DECL(int) STAMR3Deregister(PVM pVM, void *pvSample); - -/** @def STAM_REL_DEREG - * Deregisters a statistics sample if statistics are enabled. - * - * @param pVM VM Handle. - * @param pvSample Pointer to the sample. - */ -#define STAM_REL_DEREG(pVM, pvSample) \ - STAM_REL_STATS({ int rcStam = STAMR3Deregister(pVM, pvSample); AssertRC(rcStam); }) -/** @def STAM_DEREG - * Deregisters a statistics sample if statistics are enabled. - * - * @param pVM VM Handle. - * @param pvSample Pointer to the sample. - */ -#define STAM_DEREG(pVM, pvSample) \ - STAM_STATS({ STAM_REL_DEREG(pVM, pvSample); }) - -VMMR3DECL(int) STAMR3ResetU(PUVM pUVM, const char *pszPat); -VMMR3DECL(int) STAMR3Reset(PVM pVM, const char *pszPat); -VMMR3DECL(int) STAMR3SnapshotU(PUVM pUVM, const char *pszPat, char **ppszSnapshot, size_t *pcchSnapshot, bool fWithDesc); -VMMR3DECL(int) STAMR3Snapshot(PVM pVM, const char *pszPat, char **ppszSnapshot, size_t *pcchSnapshot, bool fWithDesc); -VMMR3DECL(int) STAMR3SnapshotFreeU(PUVM pUVM, char *pszSnapshot); -VMMR3DECL(int) STAMR3SnapshotFree(PVM pVM, char *pszSnapshot); -VMMR3DECL(int) STAMR3DumpU(PUVM pUVM, const char *pszPat); -VMMR3DECL(int) STAMR3Dump(PVM pVM, const char *pszPat); -VMMR3DECL(int) STAMR3DumpToReleaseLogU(PUVM pUVM, const char *pszPat); -VMMR3DECL(int) STAMR3DumpToReleaseLog(PVM pVM, const char *pszPat); -VMMR3DECL(int) STAMR3PrintU(PUVM pUVM, const char *pszPat); -VMMR3DECL(int) STAMR3Print(PVM pVM, const char *pszPat); +VMMR3DECL(int) STAMR3Deregister(PUVM pUVM, const char *pszPat); +VMMR3DECL(int) STAMR3DeregisterF(PUVM pUVM, const char *pszPatFmt, ...); +VMMR3DECL(int) STAMR3DeregisterV(PUVM pUVM, const char *pszPatFmt, va_list va); +VMMR3DECL(int) STAMR3DeregisterByAddr(PUVM pUVM, void *pvSample); + +VMMR3DECL(int) STAMR3Reset(PUVM pUVM, const char *pszPat); +VMMR3DECL(int) STAMR3Snapshot(PUVM pUVM, const char *pszPat, char **ppszSnapshot, size_t *pcchSnapshot, bool fWithDesc); +VMMR3DECL(int) STAMR3SnapshotFree(PUVM pUVM, char *pszSnapshot); +VMMR3DECL(int) STAMR3Dump(PUVM pUVM, const char *pszPat); +VMMR3DECL(int) STAMR3DumpToReleaseLog(PUVM pUVM, const char *pszPat); +VMMR3DECL(int) STAMR3Print(PUVM pUVM, const char *pszPat); /** * Callback function for STAMR3Enum(). @@ -1251,8 +1230,7 @@ typedef DECLCALLBACK(int) FNSTAMR3ENUM(const char *pszName, STAMTYPE enmType, vo /** Pointer to a FNSTAMR3ENUM(). */ typedef FNSTAMR3ENUM *PFNSTAMR3ENUM; -VMMR3DECL(int) STAMR3EnumU(PUVM pUVM, const char *pszPat, PFNSTAMR3ENUM pfnEnum, void *pvUser); -VMMR3DECL(int) STAMR3Enum(PVM pVM, const char *pszPat, PFNSTAMR3ENUM pfnEnum, void *pvUser); +VMMR3DECL(int) STAMR3Enum(PUVM pUVM, const char *pszPat, PFNSTAMR3ENUM pfnEnum, void *pvUser); VMMR3DECL(const char *) STAMR3GetUnit(STAMUNIT enmUnit); /** @} */ diff --git a/include/VBox/vmm/tm.h b/include/VBox/vmm/tm.h index be328b1c..8f857a4c 100644 --- a/include/VBox/vmm/tm.h +++ b/include/VBox/vmm/tm.h @@ -3,7 +3,7 @@ */ /* - * Copyright (C) 2006-2010 Oracle Corporation + * Copyright (C) 2006-2013 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -87,9 +87,9 @@ VMM_INT_DECL(void) TMNotifyEndOfHalt(PVMCPU pVCpu); #ifdef IN_RING3 VMMR3DECL(int) TMR3NotifySuspend(PVM pVM, PVMCPU pVCpu); VMMR3DECL(int) TMR3NotifyResume(PVM pVM, PVMCPU pVCpu); -VMMR3DECL(int) TMR3SetWarpDrive(PVM pVM, uint32_t u32Percent); +VMMR3DECL(int) TMR3SetWarpDrive(PUVM pUVM, uint32_t u32Percent); +VMMR3DECL(uint32_t) TMR3GetWarpDrive(PUVM pUVM); #endif -VMMDECL(uint32_t) TMGetWarpDrive(PVM pVM); VMM_INT_DECL(uint32_t) TMCalcHostTimerFrequency(PVM pVM, PVMCPU pVCpu); #ifdef IN_RING3 VMMR3DECL(int) TMR3GetCpuLoadTimes(PVM pVM, VMCPUID idCpu, uint64_t *pcNsTotal, uint64_t *pcNsExecuting, diff --git a/include/VBox/vmm/trpm.h b/include/VBox/vmm/trpm.h index 0cdfc153..7dc436c6 100644 --- a/include/VBox/vmm/trpm.h +++ b/include/VBox/vmm/trpm.h @@ -3,7 +3,7 @@ */ /* - * Copyright (C) 2006-2010 Oracle Corporation + * Copyright (C) 2006-2012 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -68,17 +68,20 @@ typedef TRPMEVENT const *PCTRPMEVENT; */ #define TRPM_INVALID_HANDLER 0 -VMMDECL(int) TRPMQueryTrap(PVMCPU pVCpu, uint8_t *pu8TrapNo, PTRPMEVENT pEnmType); +VMMDECL(int) TRPMQueryTrap(PVMCPU pVCpu, uint8_t *pu8TrapNo, PTRPMEVENT penmType); VMMDECL(uint8_t) TRPMGetTrapNo(PVMCPU pVCpu); VMMDECL(RTGCUINT) TRPMGetErrorCode(PVMCPU pVCpu); VMMDECL(RTGCUINTPTR) TRPMGetFaultAddress(PVMCPU pVCpu); +VMMDECL(uint8_t) TRPMGetInstrLength(PVMCPU pVCpu); VMMDECL(int) TRPMResetTrap(PVMCPU pVCpu); VMMDECL(int) TRPMAssertTrap(PVMCPU pVCpu, uint8_t u8TrapNo, TRPMEVENT enmType); +VMMDECL(int) TRPMAssertXcptPF(PVMCPU pVCpu, RTGCUINTPTR uCR2, RTGCUINT uErrorCode); VMMDECL(void) TRPMSetErrorCode(PVMCPU pVCpu, RTGCUINT uErrorCode); VMMDECL(void) TRPMSetFaultAddress(PVMCPU pVCpu, RTGCUINTPTR uCR2); +VMMDECL(void) TRPMSetInstrLength(PVMCPU pVCpu, uint8_t cbInstr); VMMDECL(bool) TRPMIsSoftwareInterrupt(PVMCPU pVCpu); VMMDECL(bool) TRPMHasTrap(PVMCPU pVCpu); -VMMDECL(int) TRPMQueryTrapAll(PVMCPU pVCpu, uint8_t *pu8TrapNo, PTRPMEVENT pEnmType, PRTGCUINT puErrorCode, PRTGCUINTPTR puCR2); +VMMDECL(int) TRPMQueryTrapAll(PVMCPU pVCpu, uint8_t *pu8TrapNo, PTRPMEVENT pEnmType, PRTGCUINT puErrorCode, PRTGCUINTPTR puCR2, uint8_t *pcbInstr); VMMDECL(void) TRPMSaveTrap(PVMCPU pVCpu); VMMDECL(void) TRPMRestoreTrap(PVMCPU pVCpu); VMMDECL(int) TRPMForwardTrap(PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t iGate, uint32_t cbInstr, TRPMERRORCODE enmError, TRPMEVENT enmType, int32_t iOrgTrap); @@ -96,16 +99,17 @@ VMMR3DECL(int) TRPMR3Init(PVM pVM); VMMR3DECL(void) TRPMR3Relocate(PVM pVM, RTGCINTPTR offDelta); VMMR3DECL(void) TRPMR3ResetCpu(PVMCPU pVCpu); VMMR3DECL(void) TRPMR3Reset(PVM pVM); -VMMR3_INT_DECL(int) TRPMR3GetImportRC(PVM pVM, const char *pszSymbol, PRTRCPTR pRCPtrValue); VMMR3DECL(int) TRPMR3Term(PVM pVM); -VMMR3DECL(int) TRPMR3EnableGuestTrapHandler(PVM pVM, unsigned iTrap); -VMMR3DECL(int) TRPMR3SetGuestTrapHandler(PVM pVM, unsigned iTrap, RTRCPTR pHandler); -VMMR3DECL(RTRCPTR) TRPMR3GetGuestTrapHandler(PVM pVM, unsigned iTrap); -VMMR3DECL(void) TRPMR3DisableMonitoring(PVM pVM); +VMMR3DECL(int) TRPMR3InjectEvent(PVM pVM, PVMCPU pVCpu, TRPMEVENT enmEvent); +# ifdef VBOX_WITH_RAW_MODE +VMMR3_INT_DECL(int) TRPMR3GetImportRC(PVM pVM, const char *pszSymbol, PRTRCPTR pRCPtrValue); VMMR3DECL(int) TRPMR3SyncIDT(PVM pVM, PVMCPU pVCpu); VMMR3DECL(bool) TRPMR3IsGateHandler(PVM pVM, RTRCPTR GCPtr); VMMR3DECL(uint32_t) TRPMR3QueryGateByHandler(PVM pVM, RTRCPTR GCPtr); -VMMR3DECL(int) TRPMR3InjectEvent(PVM pVM, PVMCPU pVCpu, TRPMEVENT enmEvent); +VMMR3DECL(int) TRPMR3EnableGuestTrapHandler(PVM pVM, unsigned iTrap); +VMMR3DECL(int) TRPMR3SetGuestTrapHandler(PVM pVM, unsigned iTrap, RTRCPTR pHandler); +VMMR3DECL(RTRCPTR) TRPMR3GetGuestTrapHandler(PVM pVM, unsigned iTrap); +# endif /** @} */ #endif diff --git a/include/VBox/vmm/uvm.h b/include/VBox/vmm/uvm.h index 10b8e49b..37087752 100644 --- a/include/VBox/vmm/uvm.h +++ b/include/VBox/vmm/uvm.h @@ -3,7 +3,7 @@ */ /* - * Copyright (C) 2007-2010 Oracle Corporation + * Copyright (C) 2007-2013 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -55,6 +55,16 @@ typedef struct UVMCPU #endif uint8_t padding[512]; } vm; + + /** The DBGF data. */ + union + { +#ifdef ___DBGFInternal_h + struct DBGFUSERPERVMCPU s; +#endif + uint8_t padding[64]; + } dbgf; + } UVMCPU; AssertCompileMemberAlignment(UVMCPU, vm, 32); @@ -114,7 +124,7 @@ typedef struct UVM #ifdef ___PDMInternal_h struct PDMUSERPERVM s; #endif - uint8_t padding[128]; + uint8_t padding[256]; } pdm; /** The STAM data. */ @@ -123,9 +133,18 @@ typedef struct UVM #ifdef ___STAMInternal_h struct STAMUSERPERVM s; #endif - uint8_t padding[6624]; + uint8_t padding[6880]; } stam; + /** The DBGF data. */ + union + { +#ifdef ___DBGFInternal_h + struct DBGFUSERPERVM s; +#endif + uint8_t padding[256]; + } dbgf; + /** Per virtual CPU data. */ UVMCPU aCpus[1]; } UVM; diff --git a/include/VBox/vmm/vm.h b/include/VBox/vmm/vm.h index ef713127..bebb9836 100644 --- a/include/VBox/vmm/vm.h +++ b/include/VBox/vmm/vm.h @@ -3,7 +3,7 @@ */ /* - * Copyright (C) 2006-2012 Oracle Corporation + * Copyright (C) 2006-2013 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -68,7 +68,9 @@ typedef enum VMCPUSTATE /** CPU started. */ VMCPUSTATE_STARTED, - /** Executing guest code and can be poked. */ + /** CPU started in HM context. */ + VMCPUSTATE_STARTED_HM, + /** Executing guest code and can be poked (RC or STI bits of HM). */ VMCPUSTATE_STARTED_EXEC, /** Executing guest code in the recompiler. */ VMCPUSTATE_STARTED_EXEC_REM, @@ -84,7 +86,9 @@ typedef enum VMCPUSTATE /** - * Per virtual CPU data. + * The cross context virtual CPU structure. + * + * Run 'kmk run-struct-tests' (from src/VBox/VMM if you like) after updating! */ typedef struct VMCPU { @@ -110,7 +114,7 @@ typedef struct VMCPU /** The native R0 thread handle. (different from the R3 handle!) */ RTNATIVETHREAD hNativeThreadR0; /* 48 / 32 */ /** Which host CPU ID is this EMT running on. - * Only valid when in RC or HWACCMR0 with scheduling disabled. */ + * Only valid when in RC or HMR0 with scheduling disabled. */ RTCPUID volatile idHostCpu; /* 56 / 36 */ /** Trace groups enable flags. */ @@ -138,14 +142,14 @@ typedef struct VMCPU uint8_t padding[3584]; /* multiple of 64 */ } cpum; - /** HWACCM part. */ + /** HM part. */ union { -#ifdef ___HWACCMInternal_h - struct HWACCMCPU s; +#ifdef ___HMInternal_h + struct HMCPU s; #endif - uint8_t padding[5376]; /* multiple of 64 */ - } hwaccm; + uint8_t padding[5568]; /* multiple of 64 */ + } hm; /** EM part. */ union @@ -189,7 +193,7 @@ typedef struct VMCPU #ifdef ___VMMInternal_h struct VMMCPU s; #endif - uint8_t padding[640]; /* multiple of 64 */ + uint8_t padding[704]; /* multiple of 64 */ } vmm; /** PDM part. */ @@ -198,7 +202,7 @@ typedef struct VMCPU #ifdef ___PDMInternal_h struct PDMCPU s; #endif - uint8_t padding[128]; /* multiple of 64 */ + uint8_t padding[256]; /* multiple of 64 */ } pdm; /** IOM part. */ @@ -221,7 +225,7 @@ typedef struct VMCPU } dbgf; /** Align the following members on page boundary. */ - uint8_t abAlignment2[1024 - 320 - 128]; + uint8_t abAlignment2[192]; /** PGM part. */ union @@ -271,6 +275,16 @@ typedef struct VMCPU /** The name of the Ring 0 Context VMM Core module. */ #define VMMR0_MAIN_MODULE_NAME "VMMR0.r0" +/** + * Wrapper macro for avoiding too much \#ifdef VBOX_WITH_RAW_MODE. + */ +#ifdef VBOX_WITH_RAW_MODE +# define VM_WHEN_RAW_MODE(a_WithExpr, a_WithoutExpr) a_WithExpr +#else +# define VM_WHEN_RAW_MODE(a_WithExpr, a_WithoutExpr) a_WithoutExpr +#endif + + /** VM Forced Action Flags. * * Use the VM_FF_SET() and VM_FF_CLEAR() macros to change the force @@ -347,6 +361,12 @@ typedef struct VMCPU /** This action forces the VM to service pending requests from other * thread or requests which must be executed in another context. */ #define VMCPU_FF_REQUEST RT_BIT_32(9) +/** This action forces the VM to service any pending updates to CR3 (used only + * by HM). */ +#define VMCPU_FF_HM_UPDATE_CR3 RT_BIT_32(12) +/** This action forces the VM to service any pending updates to PAE PDPEs (used + * only by HM). */ +#define VMCPU_FF_HM_UPDATE_PAE_PDPES RT_BIT_32(13) /** This action forces the VM to resync the page tables before going * back to execute guest code. (GLOBAL FLUSH) */ #define VMCPU_FF_PGM_SYNC_CR3 RT_BIT_32(16) @@ -354,29 +374,33 @@ typedef struct VMCPU * (NON-GLOBAL FLUSH) */ #define VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL RT_BIT_32(17) /** Check for pending TLB shootdown actions. - * Consumer: HWACCM - * @todo rename to VMCPU_FF_HWACCM_TLB_SHOOTDOWN */ + * Consumer: HM + * @todo rename to VMCPU_FF_HM_TLB_SHOOTDOWN */ #define VMCPU_FF_TLB_SHOOTDOWN RT_BIT_32(18) /** Check for pending TLB flush action. - * Consumer: HWACCM - * @todo rename to VMCPU_FF_HWACCM_TLB_FLUSH */ + * Consumer: HM + * @todo rename to VMCPU_FF_HM_TLB_FLUSH */ #define VMCPU_FF_TLB_FLUSH RT_BIT_32(VMCPU_FF_TLB_FLUSH_BIT) /** The bit number for VMCPU_FF_TLB_FLUSH. */ #define VMCPU_FF_TLB_FLUSH_BIT 19 +#ifdef VBOX_WITH_RAW_MODE /** Check the interrupt and trap gates */ -#define VMCPU_FF_TRPM_SYNC_IDT RT_BIT_32(20) +# define VMCPU_FF_TRPM_SYNC_IDT RT_BIT_32(20) /** Check Guest's TSS ring 0 stack */ -#define VMCPU_FF_SELM_SYNC_TSS RT_BIT_32(21) +# define VMCPU_FF_SELM_SYNC_TSS RT_BIT_32(21) /** Check Guest's GDT table */ -#define VMCPU_FF_SELM_SYNC_GDT RT_BIT_32(22) +# define VMCPU_FF_SELM_SYNC_GDT RT_BIT_32(22) /** Check Guest's LDT table */ -#define VMCPU_FF_SELM_SYNC_LDT RT_BIT_32(23) +# define VMCPU_FF_SELM_SYNC_LDT RT_BIT_32(23) +#endif /* VBOX_WITH_RAW_MODE */ /** Inhibit interrupts pending. See EMGetInhibitInterruptsPC(). */ #define VMCPU_FF_INHIBIT_INTERRUPTS RT_BIT_32(24) +#ifdef VBOX_WITH_RAW_MODE /** CSAM needs to scan the page that's being executed */ -#define VMCPU_FF_CSAM_SCAN_PAGE RT_BIT_32(26) +# define VMCPU_FF_CSAM_SCAN_PAGE RT_BIT_32(26) /** CSAM needs to do some homework. */ -#define VMCPU_FF_CSAM_PENDING_ACTION RT_BIT_32(27) +# define VMCPU_FF_CSAM_PENDING_ACTION RT_BIT_32(27) +#endif /* VBOX_WITH_RAW_MODE */ /** Force return to Ring-3. */ #define VMCPU_FF_TO_R3 RT_BIT_32(28) @@ -389,45 +413,67 @@ typedef struct VMCPU #define VM_FF_EXTERNAL_HALTED_MASK ( VM_FF_CHECK_VM_STATE | VM_FF_DBGF | VM_FF_REQUEST \ | VM_FF_PDM_QUEUES | VM_FF_PDM_DMA | VM_FF_EMT_RENDEZVOUS) /** Externally forced VMCPU actions. Used to quit the idle/wait loop. */ -#define VMCPU_FF_EXTERNAL_HALTED_MASK (VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC | VMCPU_FF_REQUEST | VMCPU_FF_TIMER) +#define VMCPU_FF_EXTERNAL_HALTED_MASK ( VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC | VMCPU_FF_REQUEST \ + | VMCPU_FF_TIMER) /** High priority VM pre-execution actions. */ #define VM_FF_HIGH_PRIORITY_PRE_MASK ( VM_FF_CHECK_VM_STATE | VM_FF_DBGF | VM_FF_TM_VIRTUAL_SYNC \ - | VM_FF_DEBUG_SUSPEND | VM_FF_PGM_NEED_HANDY_PAGES | VM_FF_PGM_NO_MEMORY | VM_FF_EMT_RENDEZVOUS) + | VM_FF_DEBUG_SUSPEND | VM_FF_PGM_NEED_HANDY_PAGES | VM_FF_PGM_NO_MEMORY \ + | VM_FF_EMT_RENDEZVOUS) /** High priority VMCPU pre-execution actions. */ -#define VMCPU_FF_HIGH_PRIORITY_PRE_MASK ( VMCPU_FF_TIMER | VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC | VMCPU_FF_PGM_SYNC_CR3 \ - | VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL | VMCPU_FF_SELM_SYNC_TSS | VMCPU_FF_TRPM_SYNC_IDT \ - | VMCPU_FF_SELM_SYNC_GDT | VMCPU_FF_SELM_SYNC_LDT | VMCPU_FF_INHIBIT_INTERRUPTS) +#define VMCPU_FF_HIGH_PRIORITY_PRE_MASK ( VMCPU_FF_TIMER | VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC \ + | VMCPU_FF_PGM_SYNC_CR3 | VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL \ + | VMCPU_FF_INHIBIT_INTERRUPTS \ + | VM_WHEN_RAW_MODE( VMCPU_FF_SELM_SYNC_TSS | VMCPU_FF_TRPM_SYNC_IDT \ + | VMCPU_FF_SELM_SYNC_GDT | VMCPU_FF_SELM_SYNC_LDT, 0 ) ) /** High priority VM pre raw-mode execution mask. */ #define VM_FF_HIGH_PRIORITY_PRE_RAW_MASK (VM_FF_PGM_NEED_HANDY_PAGES | VM_FF_PGM_NO_MEMORY) /** High priority VMCPU pre raw-mode execution mask. */ -#define VMCPU_FF_HIGH_PRIORITY_PRE_RAW_MASK ( VMCPU_FF_PGM_SYNC_CR3 | VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL | VMCPU_FF_SELM_SYNC_TSS | VMCPU_FF_TRPM_SYNC_IDT \ - | VMCPU_FF_SELM_SYNC_GDT | VMCPU_FF_SELM_SYNC_LDT | VMCPU_FF_INHIBIT_INTERRUPTS) +#define VMCPU_FF_HIGH_PRIORITY_PRE_RAW_MASK ( VMCPU_FF_PGM_SYNC_CR3 | VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL \ + | VMCPU_FF_INHIBIT_INTERRUPTS \ + | VM_WHEN_RAW_MODE( VMCPU_FF_SELM_SYNC_TSS | VMCPU_FF_TRPM_SYNC_IDT \ + | VMCPU_FF_SELM_SYNC_GDT | VMCPU_FF_SELM_SYNC_LDT, 0) ) /** High priority post-execution actions. */ #define VM_FF_HIGH_PRIORITY_POST_MASK (VM_FF_PGM_NO_MEMORY) /** High priority post-execution actions. */ -#define VMCPU_FF_HIGH_PRIORITY_POST_MASK (VMCPU_FF_PDM_CRITSECT|VMCPU_FF_CSAM_PENDING_ACTION) +#define VMCPU_FF_HIGH_PRIORITY_POST_MASK ( VMCPU_FF_PDM_CRITSECT | VM_WHEN_RAW_MODE(VMCPU_FF_CSAM_PENDING_ACTION, 0) \ + | VMCPU_FF_HM_UPDATE_CR3 | VMCPU_FF_HM_UPDATE_PAE_PDPES) /** Normal priority VM post-execution actions. */ #define VM_FF_NORMAL_PRIORITY_POST_MASK ( VM_FF_CHECK_VM_STATE | VM_FF_DBGF | VM_FF_RESET \ | VM_FF_PGM_NO_MEMORY | VM_FF_EMT_RENDEZVOUS) /** Normal priority VMCPU post-execution actions. */ -#define VMCPU_FF_NORMAL_PRIORITY_POST_MASK (VMCPU_FF_CSAM_SCAN_PAGE) +#define VMCPU_FF_NORMAL_PRIORITY_POST_MASK VM_WHEN_RAW_MODE(VMCPU_FF_CSAM_SCAN_PAGE, 0) /** Normal priority VM actions. */ -#define VM_FF_NORMAL_PRIORITY_MASK (VM_FF_REQUEST | VM_FF_PDM_QUEUES | VM_FF_PDM_DMA | VM_FF_REM_HANDLER_NOTIFY | VM_FF_EMT_RENDEZVOUS) +#define VM_FF_NORMAL_PRIORITY_MASK ( VM_FF_REQUEST | VM_FF_PDM_QUEUES | VM_FF_PDM_DMA | VM_FF_REM_HANDLER_NOTIFY \ + | VM_FF_EMT_RENDEZVOUS) /** Normal priority VMCPU actions. */ #define VMCPU_FF_NORMAL_PRIORITY_MASK (VMCPU_FF_REQUEST) /** Flags to clear before resuming guest execution. */ #define VMCPU_FF_RESUME_GUEST_MASK (VMCPU_FF_TO_R3) -/** VM Flags that cause the HWACCM loops to go back to ring-3. */ -#define VM_FF_HWACCM_TO_R3_MASK (VM_FF_TM_VIRTUAL_SYNC | VM_FF_PGM_NEED_HANDY_PAGES | VM_FF_PGM_NO_MEMORY | VM_FF_PDM_QUEUES | VM_FF_EMT_RENDEZVOUS) -/** VMCPU Flags that cause the HWACCM loops to go back to ring-3. */ -#define VMCPU_FF_HWACCM_TO_R3_MASK (VMCPU_FF_TO_R3 | VMCPU_FF_TIMER | VMCPU_FF_PDM_CRITSECT) +/** VM Flags that cause the HM loops to go back to ring-3. */ +#define VM_FF_HM_TO_R3_MASK ( VM_FF_TM_VIRTUAL_SYNC | VM_FF_PGM_NEED_HANDY_PAGES | VM_FF_PGM_NO_MEMORY \ + | VM_FF_PDM_QUEUES | VM_FF_EMT_RENDEZVOUS) +/** VMCPU Flags that cause the HM loops to go back to ring-3. */ +#define VMCPU_FF_HM_TO_R3_MASK (VMCPU_FF_TO_R3 | VMCPU_FF_TIMER | VMCPU_FF_PDM_CRITSECT) + +/** High priority ring-0 VM pre HM-mode execution mask. */ +#define VM_FF_HP_R0_PRE_HM_MASK (VM_FF_HM_TO_R3_MASK | VM_FF_REQUEST | VM_FF_PGM_POOL_FLUSH_PENDING | VM_FF_PDM_DMA) +/** High priority ring-0 VMCPU pre HM-mode execution mask. */ +#define VMCPU_FF_HP_R0_PRE_HM_MASK ( VMCPU_FF_HM_TO_R3_MASK | VMCPU_FF_PGM_SYNC_CR3 \ + | VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL | VMCPU_FF_REQUEST) +/** High priority ring-0 VM pre HM-mode execution mask, single stepping. */ +#define VM_FF_HP_R0_PRE_HM_STEP_MASK (VM_FF_HP_R0_PRE_HM_MASK & ~( VM_FF_TM_VIRTUAL_SYNC | VM_FF_PDM_QUEUES \ + | VM_FF_EMT_RENDEZVOUS | VM_FF_REQUEST \ + | VM_FF_PDM_DMA) ) +/** High priority ring-0 VMCPU pre HM-mode execution mask, single stepping. */ +#define VMCPU_FF_HP_R0_PRE_HM_STEP_MASK (VMCPU_FF_HP_R0_PRE_HM_MASK & ~( VMCPU_FF_TO_R3 | VMCPU_FF_TIMER \ + | VMCPU_FF_PDM_CRITSECT | VMCPU_FF_REQUEST) ) /** All the forced VM flags. */ #define VM_FF_ALL_MASK (~0U) @@ -439,14 +485,15 @@ typedef struct VMCPU #define VM_FF_ALL_REM_MASK (~(VM_FF_HIGH_PRIORITY_PRE_RAW_MASK) | VM_FF_PGM_NO_MEMORY) /** All the forced VMCPU flags except those related to raw-mode and hardware * assisted execution. */ -#define VMCPU_FF_ALL_REM_MASK (~(VMCPU_FF_HIGH_PRIORITY_PRE_RAW_MASK | VMCPU_FF_CSAM_PENDING_ACTION | VMCPU_FF_PDM_CRITSECT | VMCPU_FF_TLB_FLUSH | VMCPU_FF_TLB_SHOOTDOWN)) - +#define VMCPU_FF_ALL_REM_MASK (~( VMCPU_FF_HIGH_PRIORITY_PRE_RAW_MASK | VMCPU_FF_PDM_CRITSECT \ + | VMCPU_FF_TLB_FLUSH | VMCPU_FF_TLB_SHOOTDOWN \ + | VM_WHEN_RAW_MODE(VMCPU_FF_CSAM_PENDING_ACTION, 0) )) /** @} */ /** @def VM_FF_SET * Sets a force action flag. * - * @param pVM VM Handle. + * @param pVM Pointer to the VM. * @param fFlag The flag to set. */ #if 1 @@ -461,15 +508,15 @@ typedef struct VMCPU /** @def VMCPU_FF_SET * Sets a force action flag for the given VCPU. * - * @param pVCpu VMCPU Handle. + * @param pVCpu Pointer to the VMCPU. * @param fFlag The flag to set. */ -#define VMCPU_FF_SET(pVCpu, fFlag) ASMAtomicOrU32(&(pVCpu)->fLocalForcedActions, (fFlag)) +#define VMCPU_FF_SET(pVCpu, fFlag) ASMAtomicOrU32(&(pVCpu)->fLocalForcedActions, (fFlag)) /** @def VM_FF_CLEAR * Clears a force action flag. * - * @param pVM VM Handle. + * @param pVM Pointer to the VM. * @param fFlag The flag to clear. */ #if 1 @@ -484,80 +531,68 @@ typedef struct VMCPU /** @def VMCPU_FF_CLEAR * Clears a force action flag for the given VCPU. * - * @param pVCpu VMCPU Handle. + * @param pVCpu Pointer to the VMCPU. * @param fFlag The flag to clear. */ -#define VMCPU_FF_CLEAR(pVCpu, fFlag) ASMAtomicAndU32(&(pVCpu)->fLocalForcedActions, ~(fFlag)) +#define VMCPU_FF_CLEAR(pVCpu, fFlag) ASMAtomicAndU32(&(pVCpu)->fLocalForcedActions, ~(fFlag)) -/** @def VM_FF_ISSET +/** @def VM_FF_IS_SET * Checks if a force action flag is set. * - * @param pVM VM Handle. + * @param pVM Pointer to the VM. * @param fFlag The flag to check. */ #define VM_FF_IS_SET(pVM, fFlag) (((pVM)->fGlobalForcedActions & (fFlag)) == (fFlag)) -/** @deprecated */ -#define VM_FF_ISSET(pVM, fFlag) VM_FF_IS_SET(pVM, fFlag) -/** @def VMCPU_FF_ISSET +/** @def VMCPU_FF_IS_SET * Checks if a force action flag is set for the given VCPU. * - * @param pVCpu VMCPU Handle. + * @param pVCpu Pointer to the VMCPU. * @param fFlag The flag to check. */ #define VMCPU_FF_IS_SET(pVCpu, fFlag) (((pVCpu)->fLocalForcedActions & (fFlag)) == (fFlag)) -/** @deprecated */ -#define VMCPU_FF_ISSET(pVCpu, fFlag) VMCPU_FF_IS_SET(pVCpu, fFlag) -/** @def VM_FF_ISPENDING +/** @def VM_FF_IS_PENDING * Checks if one or more force action in the specified set is pending. * - * @param pVM VM Handle. + * @param pVM Pointer to the VM. * @param fFlags The flags to check for. */ -#define VM_FF_IS_PENDING(pVM, fFlags) ((pVM)->fGlobalForcedActions & (fFlags)) -/** @deprecated */ -#define VM_FF_ISPENDING(pVM, fFlags) VM_FF_IS_PENDING(pVM, fFlags) +#define VM_FF_IS_PENDING(pVM, fFlags) RT_BOOL((pVM)->fGlobalForcedActions & (fFlags)) /** @def VM_FF_TESTANDCLEAR * Checks if one (!) force action in the specified set is pending and clears it atomically * * @returns true if the bit was set. * @returns false if the bit was clear. - * @param pVM VM Handle. + * @param pVM Pointer to the VM. * @param iBit Bit position to check and clear */ #define VM_FF_TEST_AND_CLEAR(pVM, iBit) (ASMAtomicBitTestAndClear(&(pVM)->fGlobalForcedActions, iBit##_BIT)) -/** @deprecated */ -#define VM_FF_TESTANDCLEAR(pVM, iBit) (ASMAtomicBitTestAndClear(&(pVM)->fGlobalForcedActions, iBit##_BIT)) /** @def VMCPU_FF_TESTANDCLEAR * Checks if one (!) force action in the specified set is pending and clears it atomically * * @returns true if the bit was set. * @returns false if the bit was clear. - * @param pVCpu VMCPU Handle. + * @param pVCpu Pointer to the VMCPU. * @param iBit Bit position to check and clear */ #define VMCPU_FF_TEST_AND_CLEAR(pVCpu, iBit) (ASMAtomicBitTestAndClear(&(pVCpu)->fLocalForcedActions, iBit##_BIT)) -/** @deprecated */ -#define VMCPU_FF_TESTANDCLEAR(pVCpu, iBit) (ASMAtomicBitTestAndClear(&(pVCpu)->fLocalForcedActions, iBit##_BIT)) -/** @def VMCPU_FF_ISPENDING +/** @def VMCPU_FF_IS_PENDING * Checks if one or more force action in the specified set is pending for the given VCPU. * - * @param pVCpu VMCPU Handle. + * @param pVCpu Pointer to the VMCPU. * @param fFlags The flags to check for. */ -#define VMCPU_FF_IS_PENDING(pVCpu, fFlags) ((pVCpu)->fLocalForcedActions & (fFlags)) -/** @deprecated */ -#define VMCPU_FF_ISPENDING(pVCpu, fFlags) VMCPU_FF_IS_PENDING(pVCpu, fFlags) +#define VMCPU_FF_IS_PENDING(pVCpu, fFlags) RT_BOOL((pVCpu)->fLocalForcedActions & (fFlags)) -/** @def VM_FF_ISPENDING +/** @def VM_FF_IS_PENDING_EXCEPT * Checks if one or more force action in the specified set is pending while one * or more other ones are not. * - * @param pVM VM Handle. + * @param pVM Pointer to the VM. * @param fFlags The flags to check for. * @param fExcpt The flags that should not be set. */ @@ -567,7 +602,7 @@ typedef struct VMCPU * Checks if one or more force action in the specified set is pending for the given * VCPU while one or more other ones are not. * - * @param pVCpu VMCPU Handle. + * @param pVCpu Pointer to the VMCPU. * @param fFlags The flags to check for. * @param fExcpt The flags that should not be set. */ @@ -615,7 +650,10 @@ typedef struct VMCPU #ifdef IN_RC # define VMCPU_ASSERT_EMT(pVCpu) Assert(VMCPU_IS_EMT(pVCpu)) #elif defined(IN_RING0) -# define VMCPU_ASSERT_EMT(pVCpu) Assert(VMCPU_IS_EMT(pVCpu)) +# define VMCPU_ASSERT_EMT(pVCpu) AssertMsg(VMCPU_IS_EMT(pVCpu), \ + ("Not emulation thread! Thread=%RTnthrd ThreadEMT=%RTnthrd idCpu=%u\n", \ + RTThreadNativeSelf(), (pVCpu) ? (pVCpu)->hNativeThreadR0 : 0, \ + (pVCpu) ? (pVCpu)->idCpu : 0)) #else # define VMCPU_ASSERT_EMT(pVCpu) \ AssertMsg(VMCPU_IS_EMT(pVCpu), \ @@ -723,15 +761,21 @@ typedef struct VMCPU ("state %s, expected %s\n", VMGetStateName((pVM)->enmVMState), VMGetStateName(_enmState)), \ (rc)) +/** @def VM_IS_VALID_EXT + * Asserts a the VM handle is valid for external access, i.e. not being destroy + * or terminated. */ +#define VM_IS_VALID_EXT(pVM) \ + ( RT_VALID_ALIGNED_PTR(pVM, PAGE_SIZE) \ + && ( (unsigned)(pVM)->enmVMState < (unsigned)VMSTATE_DESTROYING \ + || ( (unsigned)(pVM)->enmVMState == (unsigned)VMSTATE_DESTROYING \ + && VM_IS_EMT(pVM))) ) + /** @def VM_ASSERT_VALID_EXT_RETURN * Asserts a the VM handle is valid for external access, i.e. not being * destroy or terminated. */ #define VM_ASSERT_VALID_EXT_RETURN(pVM, rc) \ - AssertMsgReturn( RT_VALID_ALIGNED_PTR(pVM, PAGE_SIZE) \ - && ( (unsigned)(pVM)->enmVMState < (unsigned)VMSTATE_DESTROYING \ - || ( (unsigned)(pVM)->enmVMState == (unsigned)VMSTATE_DESTROYING \ - && VM_IS_EMT(pVM))), \ + AssertMsgReturn(VM_IS_VALID_EXT(pVM), \ ("pVM=%p state %s\n", (pVM), RT_VALID_ALIGNED_PTR(pVM, PAGE_SIZE) \ ? VMGetStateName(pVM->enmVMState) : ""), \ (rc)) @@ -753,17 +797,17 @@ typedef struct VMCPU -/** This is the VM structure. +/** + * The cross context VM structure. * - * It contains (nearly?) all the VM data which have to be available in all - * contexts. Even if it contains all the data the idea is to use APIs not - * to modify all the members all around the place. Therefore we make use of - * unions to hide everything which isn't local to the current source module. - * This means we'll have to pay a little bit of attention when adding new - * members to structures in the unions and make sure to keep the padding sizes - * up to date. + * It contains all the VM data which have to be available in all contexts. + * Even if it contains all the data the idea is to use APIs not to modify all + * the members all around the place. Therefore we make use of unions to hide + * everything which isn't local to the current source module. This means we'll + * have to pay a little bit of attention when adding new members to structures + * in the unions and make sure to keep the padding sizes up to date. * - * Run tstVMStructSize after update! + * Run 'kmk run-struct-tests' (from src/VBox/VMM if you like) after updating! */ typedef struct VM { @@ -835,6 +879,8 @@ typedef struct VM bool fRecompileUser; /** Whether to recompile supervisor mode code or run it raw/hm. */ bool fRecompileSupervisor; + /** Whether raw mode supports ring-1 code or not. */ + bool fRawRing1Enabled; /** PATM enabled flag. * This is placed here for performance reasons. */ bool fPATMEnabled; @@ -842,19 +888,26 @@ typedef struct VM * This is placed here for performance reasons. */ bool fCSAMEnabled; /** Hardware VM support is available and enabled. + * Determined very early during init. * This is placed here for performance reasons. */ - bool fHWACCMEnabled; - /** Hardware VM support is required and non-optional. - * This is initialized together with the rest of the VM structure. */ - bool fHwVirtExtForced; - /** Set when this VM is the master FT node. */ + bool fHMEnabled; + /** For asserting on fHMEnable usage. */ + bool fHMEnabledFixed; + /** Hardware VM support requires a minimal raw-mode context. + * This is never set on 64-bit hosts, only 32-bit hosts requires it. */ + bool fHMNeedRawModeCtx; + /** Set when this VM is the master FT node. + * @todo This doesn't need to be here, FTM should store it in it's own + * structures instead. */ bool fFaultTolerantMaster; - /** Large page enabled flag. */ + /** Large page enabled flag. + * @todo This doesn't need to be here, PGM should store it in it's own + * structures instead. */ bool fUseLargePages; /** @} */ /** Alignment padding.. */ - uint32_t uPadding1; + uint8_t uPadding1[2]; /** @name Debugging * @{ */ @@ -929,14 +982,14 @@ typedef struct VM uint8_t padding[4096*2+6080]; /* multiple of 64 */ } pgm; - /** HWACCM part. */ + /** HM part. */ union { -#ifdef ___HWACCMInternal_h - struct HWACCM s; +#ifdef ___HMInternal_h + struct HM s; #endif - uint8_t padding[5376]; /* multiple of 64 */ - } hwaccm; + uint8_t padding[5440]; /* multiple of 64 */ + } hm; /** TRPM part. */ union @@ -980,7 +1033,7 @@ typedef struct VM #ifdef ___IOMInternal_h struct IOM s; #endif - uint8_t padding[832]; /* multiple of 64 */ + uint8_t padding[896]; /* multiple of 64 */ } iom; /** PATM part. */ @@ -1077,7 +1130,7 @@ typedef struct VM /** Padding for aligning the cpu array on a page boundary. */ - uint8_t abAlignment2[542]; + uint8_t abAlignment2[414]; /* ---- end small stuff ---- */ diff --git a/include/VBox/vmm/vm.mac b/include/VBox/vmm/vm.mac index 6d65b0c9..2a1be76b 100644 --- a/include/VBox/vmm/vm.mac +++ b/include/VBox/vmm/vm.mac @@ -3,7 +3,7 @@ ; ; -; Copyright (C) 2006-2012 Oracle Corporation +; Copyright (C) 2006-2013 Oracle Corporation ; ; This file is part of VirtualBox Open Source Edition (OSE), as ; available from http://www.virtualbox.org. This file is free software; @@ -58,14 +58,16 @@ struc VM .pfnVMMRCToHostAsmNoReturn resd 1 .fRecompileUser resb 1 .fRecompileSupervisor resb 1 + .fRawRing1Enabled resb 1 .fPATMEnabled resb 1 .fCSAMEnabled resb 1 - .fHWACCMEnabled resb 1 - .fHwVirtExtForced resb 1 + .fHMEnabled resb 1 + .fHMEnabledFixed resb 1 + .fHMNeedRawModeCtx resb 1 .fFaultTolerantMaster resb 1 .fUseLargePages resb 1 - .uPadding1 resd 1 + .uPadding1 resb 2 .hTraceBufRC RTRCPTR_RES 1 .hTraceBufR3 RTR3PTR_RES 1 @@ -132,13 +134,13 @@ struc VMCPU alignb 64 .cpum resb 3584 - .hwaccm resb 5376 + .hm resb 5568 .em resb 1472 .iem resb 3072 .trpm resb 128 .tm resb 384 - .vmm resb 640 - .pdm resb 128 + .vmm resb 704 + .pdm resb 256 .iom resb 512 .dbgf resb 64 alignb 4096 diff --git a/include/VBox/vmm/vmapi.h b/include/VBox/vmm/vmapi.h index b15fc7f6..d19ac645 100644 --- a/include/VBox/vmm/vmapi.h +++ b/include/VBox/vmm/vmapi.h @@ -3,7 +3,7 @@ */ /* - * Copyright (C) 2006-2010 Oracle Corporation + * Copyright (C) 2006-2013 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -92,20 +92,20 @@ RT_C_DECLS_BEGIN /** * VM error callback function. * - * @param pVM The VM handle. Can be NULL if an error occurred before - * successfully creating a VM. + * @param pUVM The user mode VM handle. Can be NULL if an error + * occurred before successfully creating a VM. * @param pvUser The user argument. * @param rc VBox status code. * @param RT_SRC_POS_DECL The source position arguments. See RT_SRC_POS and RT_SRC_POS_ARGS. * @param pszFormat Error message format string. * @param args Error message arguments. */ -typedef DECLCALLBACK(void) FNVMATERROR(PVM pVM, void *pvUser, int rc, RT_SRC_POS_DECL, const char *pszError, va_list args); +typedef DECLCALLBACK(void) FNVMATERROR(PUVM pUVM, void *pvUser, int rc, RT_SRC_POS_DECL, const char *pszError, va_list args); /** Pointer to a VM error callback. */ typedef FNVMATERROR *PFNVMATERROR; -VMMDECL(int) VMSetError(PVM pVM, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...); -VMMDECL(int) VMSetErrorV(PVM pVM, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list args); +VMMDECL(int) VMSetError(PVM pVM, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...); +VMMDECL(int) VMSetErrorV(PVM pVM, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list args); /** @def VM_SET_ERROR * Macro for setting a simple VM error message. @@ -122,20 +122,35 @@ VMMDECL(int) VMSetErrorV(PVM pVM, int rc, RT_SRC_POS_DECL, const char *pszFormat */ #define VM_SET_ERROR(pVM, rc, pszMessage) (VMSetError(pVM, rc, RT_SRC_POS, pszMessage)) +/** @def VM_SET_ERROR + * Macro for setting a simple VM error message. + * Don't use '%' in the message! + * + * @returns rc. Meaning you can do: + * @code + * return VM_SET_ERROR(pVM, VERR_OF_YOUR_CHOICE, "descriptive message"); + * @endcode + * @param pVM VM handle. + * @param rc VBox status code. + * @param pszMessage Error message string. + * @thread Any + */ +#define VM_SET_ERROR_U(a_pUVM, a_rc, a_pszMessage) (VMR3SetError(a_pUVM, a_rc, RT_SRC_POS, a_pszMessage)) + /** * VM runtime error callback function. * * See VMSetRuntimeError for the detailed description of parameters. * - * @param pVM The VM handle. + * @param pUVM The user mode VM handle. * @param pvUser The user argument. * @param fFlags The error flags. * @param pszErrorId Error ID string. * @param pszFormat Error message format string. * @param va Error message arguments. */ -typedef DECLCALLBACK(void) FNVMATRUNTIMEERROR(PVM pVM, void *pvUser, uint32_t fFlags, const char *pszErrorId, +typedef DECLCALLBACK(void) FNVMATRUNTIMEERROR(PUVM pUVM, void *pvUser, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, va_list va); /** Pointer to a VM runtime error callback. */ typedef FNVMATRUNTIMEERROR *PFNVMATRUNTIMEERROR; @@ -163,17 +178,17 @@ VMMDECL(int) VMSetRuntimeErrorV(PVM pVM, uint32_t fFlags, const char *pszErrorId /** @} */ /** - * VM state callback function. + * VM state change callback function. * * You are not allowed to call any function which changes the VM state from a * state callback, except VMR3Destroy(). * - * @param pVM The VM handle. + * @param pUVM The user mode VM handle. * @param enmState The new state. * @param enmOldState The old state. * @param pvUser The user argument. */ -typedef DECLCALLBACK(void) FNVMATSTATE(PVM pVM, VMSTATE enmState, VMSTATE enmOldState, void *pvUser); +typedef DECLCALLBACK(void) FNVMATSTATE(PUVM pUVM, VMSTATE enmState, VMSTATE enmOldState, void *pvUser); /** Pointer to a VM state callback. */ typedef FNVMATSTATE *PFNVMATSTATE; @@ -309,45 +324,102 @@ typedef enum VMINITCOMPLETED /** The ring-0 init is completed. */ VMINITCOMPLETED_RING0, /** The hardware accelerated virtualization init is completed. - * Used to make decisision depending on whether HWACCMIsEnabled(). */ - VMINITCOMPLETED_HWACCM, - /** The GC init is completed. */ - VMINITCOMPLETED_GC + * Used to make decisision depending on HM* bits being completely + * initialized. */ + VMINITCOMPLETED_HM, + /** The RC init is completed. */ + VMINITCOMPLETED_RC } VMINITCOMPLETED; -VMMR3DECL(int) VMR3Create(uint32_t cCpus, PCVMM2USERMETHODS pVm2UserCbs, - PFNVMATERROR pfnVMAtError, void *pvUserVM, - PFNCFGMCONSTRUCTOR pfnCFGMConstructor, void *pvUserCFGM, - PVM *ppVM); -VMMR3DECL(int) VMR3PowerOn(PVM pVM); -VMMR3DECL(int) VMR3Suspend(PVM pVM); -VMMR3DECL(int) VMR3Resume(PVM pVM); -VMMR3DECL(int) VMR3Reset(PVM pVM); +/** Reason for VM resume. */ +typedef enum VMRESUMEREASON +{ + VMRESUMEREASON_INVALID = 0, + /** User decided to do so. */ + VMRESUMEREASON_USER, + /** VM reconfiguration (like changing DVD). */ + VMRESUMEREASON_RECONFIG, + /** The host resumed. */ + VMRESUMEREASON_HOST_RESUME, + /** Restored state. */ + VMRESUMEREASON_STATE_RESTORED, + /** Snapshot / saved state. */ + VMRESUMEREASON_STATE_SAVED, + /** Teleported to a new box / instance. */ + VMRESUMEREASON_TELEPORTED, + /** Teleportation failed. */ + VMRESUMEREASON_TELEPORT_FAILED, + /** FTM temporarily suspended the VM. */ + VMRESUMEREASON_FTM_SYNC, + /** End of valid reasons. */ + VMRESUMEREASON_END, + /** Blow the type up to 32-bits. */ + VMRESUMEREASON_32BIT_HACK = 0x7fffffff +} VMRESUMEREASON; + +/** Reason for VM suspend. */ +typedef enum VMSUSPENDREASON +{ + VMSUSPENDREASON_INVALID = 0, + /** User decided to do so. */ + VMSUSPENDREASON_USER, + /** VM reconfiguration (like changing DVD). */ + VMSUSPENDREASON_RECONFIG, + /** The VM is suspending itself. */ + VMSUSPENDREASON_VM, + /** The Vm is suspending because of a runtime error. */ + VMSUSPENDREASON_RUNTIME_ERROR, + /** The host was suspended. */ + VMSUSPENDREASON_HOST_SUSPEND, + /** The host is running low on battery power. */ + VMSUSPENDREASON_HOST_BATTERY_LOW, + /** FTM is temporarily suspending the VM. */ + VMSUSPENDREASON_FTM_SYNC, + /** End of valid reasons. */ + VMSUSPENDREASON_END, + /** Blow the type up to 32-bits. */ + VMSUSPENDREASON_32BIT_HACK = 0x7fffffff +} VMSUSPENDREASON; + /** * Progress callback. + * * This will report the completion percentage of an operation. * * @returns VINF_SUCCESS. * @returns Error code to cancel the operation with. - * @param pVM The VM handle. + * @param pUVM The user mode VM handle. * @param uPercent Completion percentage (0-100). * @param pvUser User specified argument. */ -typedef DECLCALLBACK(int) FNVMPROGRESS(PVM pVM, unsigned uPercent, void *pvUser); +typedef DECLCALLBACK(int) FNVMPROGRESS(PUVM pUVM, unsigned uPercent, void *pvUser); /** Pointer to a FNVMPROGRESS function. */ typedef FNVMPROGRESS *PFNVMPROGRESS; -VMMR3DECL(int) VMR3Save(PVM pVM, const char *pszFilename, bool fContinueAfterwards, PFNVMPROGRESS pfnProgress, void *pvUser, bool *pfSuspended); -VMMR3DECL(int) VMR3Teleport(PVM pVM, uint32_t cMsDowntime, PCSSMSTRMOPS pStreamOps, void *pvStreamOpsUser, PFNVMPROGRESS pfnProgress, void *pvProgressUser, bool *pfSuspended); -VMMR3DECL(int) VMR3LoadFromFile(PVM pVM, const char *pszFilename, PFNVMPROGRESS pfnProgress, void *pvUser); -VMMR3DECL(int) VMR3LoadFromStream(PVM pVM, PCSSMSTRMOPS pStreamOps, void *pvStreamOpsUser, - PFNVMPROGRESS pfnProgress, void *pvProgressUser); -VMMR3DECL(int) VMR3PowerOff(PVM pVM); -VMMR3DECL(int) VMR3Destroy(PVM pVM); -VMMR3DECL(void) VMR3Relocate(PVM pVM, RTGCINTPTR offDelta); -VMMR3DECL(PVM) VMR3EnumVMs(PVM pVMPrev); + +VMMR3DECL(int) VMR3Create(uint32_t cCpus, PCVMM2USERMETHODS pVm2UserCbs, + PFNVMATERROR pfnVMAtError, void *pvUserVM, + PFNCFGMCONSTRUCTOR pfnCFGMConstructor, void *pvUserCFGM, + PVM *ppVM, PUVM *ppUVM); +VMMR3DECL(int) VMR3PowerOn(PUVM pUVM); +VMMR3DECL(int) VMR3Suspend(PUVM pUVM, VMSUSPENDREASON enmReason); +VMMR3DECL(VMSUSPENDREASON) VMR3GetSuspendReason(PUVM); +VMMR3DECL(int) VMR3Resume(PUVM pUVM, VMRESUMEREASON enmReason); +VMMR3DECL(VMRESUMEREASON) VMR3GetResumeReason(PUVM); +VMMR3DECL(int) VMR3Reset(PUVM pUVM); +VMMR3DECL(int) VMR3Save(PUVM pUVM, const char *pszFilename, bool fContinueAfterwards, PFNVMPROGRESS pfnProgress, void *pvUser, bool *pfSuspended); +VMMR3_INT_DECL(int) VMR3SaveFT(PUVM pUVM, PCSSMSTRMOPS pStreamOps, void *pvStreamOpsUser, bool *pfSuspended, bool fSkipStateChanges); +VMMR3DECL(int) VMR3Teleport(PUVM pUVM, uint32_t cMsDowntime, PCSSMSTRMOPS pStreamOps, void *pvStreamOpsUser, PFNVMPROGRESS pfnProgress, void *pvProgressUser, bool *pfSuspended); +VMMR3DECL(int) VMR3LoadFromFile(PUVM pUVM, const char *pszFilename, PFNVMPROGRESS pfnProgress, void *pvUser); +VMMR3DECL(int) VMR3LoadFromStream(PUVM pUVM, PCSSMSTRMOPS pStreamOps, void *pvStreamOpsUser, + PFNVMPROGRESS pfnProgress, void *pvProgressUser); +VMMR3_INT_DECL(int) VMR3LoadFromStreamFT(PUVM pUVM, PCSSMSTRMOPS pStreamOps, void *pvStreamOpsUser); + +VMMR3DECL(int) VMR3PowerOff(PUVM pUVM); +VMMR3DECL(int) VMR3Destroy(PUVM pUVM); +VMMR3_INT_DECL(void) VMR3Relocate(PVM pVM, RTGCINTPTR offDelta); VMMR3DECL(PVM) VMR3GetVM(PUVM pUVM); VMMR3DECL(PUVM) VMR3GetUVM(PVM pVM); @@ -358,48 +430,38 @@ VMMR3DECL(PRTUUID) VMR3GetUuid(PUVM pUVM, PRTUUID pUuid); VMMR3DECL(VMSTATE) VMR3GetState(PVM pVM); VMMR3DECL(VMSTATE) VMR3GetStateU(PUVM pUVM); VMMR3DECL(const char *) VMR3GetStateName(VMSTATE enmState); +VMMR3DECL(int) VMR3AtStateRegister(PUVM pUVM, PFNVMATSTATE pfnAtState, void *pvUser); +VMMR3DECL(int) VMR3AtStateDeregister(PUVM pUVM, PFNVMATSTATE pfnAtState, void *pvUser); +VMMR3_INT_DECL(bool) VMR3TeleportedAndNotFullyResumedYet(PVM pVM); +VMMR3DECL(int) VMR3AtErrorRegister(PUVM pUVM, PFNVMATERROR pfnAtError, void *pvUser); +VMMR3DECL(int) VMR3AtErrorDeregister(PUVM pUVM, PFNVMATERROR pfnAtError, void *pvUser); +VMMR3DECL(int) VMR3SetError(PUVM pUVM, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...); +VMMR3DECL(int) VMR3SetErrorV(PUVM pUVM, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va); +VMMR3_INT_DECL(void) VMR3SetErrorWorker(PVM pVM); +VMMR3_INT_DECL(uint32_t) VMR3GetErrorCount(PUVM pUVM); +VMMR3DECL(int) VMR3AtRuntimeErrorRegister(PUVM pUVM, PFNVMATRUNTIMEERROR pfnAtRuntimeError, void *pvUser); +VMMR3DECL(int) VMR3AtRuntimeErrorDeregister(PUVM pUVM, PFNVMATRUNTIMEERROR pfnAtRuntimeError, void *pvUser); +VMMR3_INT_DECL(int) VMR3SetRuntimeErrorWorker(PVM pVM); +VMMR3_INT_DECL(uint32_t) VMR3GetRuntimeErrorCount(PUVM pUVM); + +VMMR3DECL(int) VMR3ReqCallU(PUVM pUVM, VMCPUID idDstCpu, PVMREQ *ppReq, RTMSINTERVAL cMillies, uint32_t fFlags, PFNRT pfnFunction, unsigned cArgs, ...); +VMMR3DECL(int) VMR3ReqCallVU(PUVM pUVM, VMCPUID idDstCpu, PVMREQ *ppReq, RTMSINTERVAL cMillies, uint32_t fFlags, PFNRT pfnFunction, unsigned cArgs, va_list Args); +VMMR3_INT_DECL(int) VMR3ReqCallWait(PVM pVM, VMCPUID idDstCpu, PFNRT pfnFunction, unsigned cArgs, ...); +VMMR3DECL(int) VMR3ReqCallWaitU(PUVM pUVM, VMCPUID idDstCpu, PFNRT pfnFunction, unsigned cArgs, ...); +VMMR3DECL(int) VMR3ReqCallNoWait(PVM pVM, VMCPUID idDstCpu, PFNRT pfnFunction, unsigned cArgs, ...); +VMMR3DECL(int) VMR3ReqCallNoWaitU(PUVM pUVM, VMCPUID idDstCpu, PFNRT pfnFunction, unsigned cArgs, ...); +VMMR3_INT_DECL(int) VMR3ReqCallVoidWait(PVM pVM, VMCPUID idDstCpu, PFNRT pfnFunction, unsigned cArgs, ...); +VMMR3DECL(int) VMR3ReqCallVoidWaitU(PUVM pUVM, VMCPUID idDstCpu, PFNRT pfnFunction, unsigned cArgs, ...); +VMMR3DECL(int) VMR3ReqCallVoidNoWait(PVM pVM, VMCPUID idDstCpu, PFNRT pfnFunction, unsigned cArgs, ...); +VMMR3DECL(int) VMR3ReqPriorityCallWait(PVM pVM, VMCPUID idDstCpu, PFNRT pfnFunction, unsigned cArgs, ...); +VMMR3DECL(int) VMR3ReqPriorityCallWaitU(PUVM pUVM, VMCPUID idDstCpu, PFNRT pfnFunction, unsigned cArgs, ...); +VMMR3DECL(int) VMR3ReqPriorityCallVoidWaitU(PUVM pUVM, VMCPUID idDstCpu, PFNRT pfnFunction, unsigned cArgs, ...); +VMMR3DECL(int) VMR3ReqAlloc(PUVM pUVM, PVMREQ *ppReq, VMREQTYPE enmType, VMCPUID idDstCpu); +VMMR3DECL(int) VMR3ReqFree(PVMREQ pReq); +VMMR3DECL(int) VMR3ReqQueue(PVMREQ pReq, RTMSINTERVAL cMillies); +VMMR3DECL(int) VMR3ReqWait(PVMREQ pReq, RTMSINTERVAL cMillies); +VMMR3_INT_DECL(int) VMR3ReqProcessU(PUVM pUVM, VMCPUID idDstCpu, bool fPriorityOnly); -/** - * VM destruction callback. - * @param pVM The VM which is about to be destroyed. - * @param pvUser The user parameter specified at registration. - */ -typedef DECLCALLBACK(void) FNVMATDTOR(PVM pVM, void *pvUser); -/** Pointer to a VM destruction callback. */ -typedef FNVMATDTOR *PFNVMATDTOR; - -VMMR3DECL(int) VMR3AtDtorRegister(PFNVMATDTOR pfnAtDtor, void *pvUser); -VMMR3DECL(int) VMR3AtDtorDeregister(PFNVMATDTOR pfnAtDtor); -VMMR3DECL(int) VMR3AtStateRegister(PVM pVM, PFNVMATSTATE pfnAtState, void *pvUser); -VMMR3DECL(int) VMR3AtStateDeregister(PVM pVM, PFNVMATSTATE pfnAtState, void *pvUser); -VMMR3DECL(bool) VMR3TeleportedAndNotFullyResumedYet(PVM pVM); -VMMR3DECL(int) VMR3AtErrorRegister(PVM pVM, PFNVMATERROR pfnAtError, void *pvUser); -VMMR3DECL(int) VMR3AtErrorRegisterU(PUVM pVM, PFNVMATERROR pfnAtError, void *pvUser); -VMMR3DECL(int) VMR3AtErrorDeregister(PVM pVM, PFNVMATERROR pfnAtError, void *pvUser); -VMMR3DECL(void) VMR3SetErrorWorker(PVM pVM); -VMMR3DECL(uint32_t) VMR3GetErrorCount(PVM pVM); -VMMR3DECL(uint32_t) VMR3GetErrorCountU(PUVM pUVM); -VMMR3DECL(int) VMR3AtRuntimeErrorRegister(PVM pVM, PFNVMATRUNTIMEERROR pfnAtRuntimeError, void *pvUser); -VMMR3DECL(int) VMR3AtRuntimeErrorDeregister(PVM pVM, PFNVMATRUNTIMEERROR pfnAtRuntimeError, void *pvUser); -VMMR3DECL(int) VMR3SetRuntimeErrorWorker(PVM pVM); -VMMR3DECL(uint32_t) VMR3GetRuntimeErrorCount(PVM pVM); -VMMR3DECL(int) VMR3ReqCall(PVM pVM, VMCPUID idDstCpu, PVMREQ *ppReq, RTMSINTERVAL cMillies, uint32_t fFlags, PFNRT pfnFunction, unsigned cArgs, ...); -VMMR3DECL(int) VMR3ReqCallU(PUVM pUVM, VMCPUID idDstCpu, PVMREQ *ppReq, RTMSINTERVAL cMillies, uint32_t fFlags, PFNRT pfnFunction, unsigned cArgs, ...); -VMMR3DECL(int) VMR3ReqCallVU(PUVM pUVM, VMCPUID idDstCpu, PVMREQ *ppReq, RTMSINTERVAL cMillies, uint32_t fFlags, PFNRT pfnFunction, unsigned cArgs, va_list Args); -VMMR3DECL(int) VMR3ReqCallWait(PVM pVM, VMCPUID idDstCpu, PFNRT pfnFunction, unsigned cArgs, ...); -VMMR3DECL(int) VMR3ReqCallNoWait(PVM pVM, VMCPUID idDstCpu, PFNRT pfnFunction, unsigned cArgs, ...); -VMMR3DECL(int) VMR3ReqCallVoidWait(PVM pVM, VMCPUID idDstCpu, PFNRT pfnFunction, unsigned cArgs, ...); -VMMR3DECL(int) VMR3ReqCallVoidNoWait(PVM pVM, VMCPUID idDstCpu, PFNRT pfnFunction, unsigned cArgs, ...); -VMMR3DECL(int) VMR3ReqPriorityCallWait(PVM pVM, VMCPUID idDstCpu, PFNRT pfnFunction, unsigned cArgs, ...); -VMMR3DECL(int) VMR3ReqPriorityCallVoidWait(PVM pVM, VMCPUID idDstCpu, PFNRT pfnFunction, unsigned cArgs, ...); -VMMR3DECL(int) VMR3ReqAlloc(PVM pVM, PVMREQ *ppReq, VMREQTYPE enmType, VMCPUID idDstCpu); -VMMR3DECL(int) VMR3ReqAllocU(PUVM pUVM, PVMREQ *ppReq, VMREQTYPE enmType, VMCPUID idDstCpu); -VMMR3DECL(int) VMR3ReqFree(PVMREQ pReq); -VMMR3DECL(int) VMR3ReqQueue(PVMREQ pReq, RTMSINTERVAL cMillies); -VMMR3DECL(int) VMR3ReqWait(PVMREQ pReq, RTMSINTERVAL cMillies); -VMMR3DECL(int) VMR3ReqProcessU(PUVM pUVM, VMCPUID idDstCpu, bool fPriorityOnly); -VMMR3DECL(void) VMR3NotifyGlobalFFU(PUVM pUVM, uint32_t fFlags); -VMMR3DECL(void) VMR3NotifyCpuFFU(PUVMCPU pUVMCpu, uint32_t fFlags); /** @name Flags for VMR3NotifyCpuFFU and VMR3NotifyGlobalFFU. * @{ */ /** Whether we've done REM or not. */ @@ -407,20 +469,21 @@ VMMR3DECL(void) VMR3NotifyCpuFFU(PUVMCPU pUVMCpu, uint32_t fFlags); /** Whether we should poke the CPU if it's executing guest code. */ #define VMNOTIFYFF_FLAGS_POKE RT_BIT_32(1) /** @} */ - -VMMR3DECL(int) VMR3WaitHalted(PVM pVM, PVMCPU pVCpu, bool fIgnoreInterrupts); -VMMR3DECL(int) VMR3WaitU(PUVMCPU pUVMCpu); +VMMR3_INT_DECL(void) VMR3NotifyGlobalFFU(PUVM pUVM, uint32_t fFlags); +VMMR3_INT_DECL(void) VMR3NotifyCpuFFU(PUVMCPU pUVMCpu, uint32_t fFlags); +VMMR3_INT_DECL(int) VMR3WaitHalted(PVM pVM, PVMCPU pVCpu, bool fIgnoreInterrupts); +VMMR3_INT_DECL(int) VMR3WaitU(PUVMCPU pUVMCpu); VMMR3_INT_DECL(int) VMR3AsyncPdmNotificationWaitU(PUVMCPU pUVCpu); VMMR3_INT_DECL(void) VMR3AsyncPdmNotificationWakeupU(PUVM pUVM); -VMMR3DECL(RTCPUID) VMR3GetVMCPUId(PVM pVM); -VMMR3DECL(RTTHREAD) VMR3GetVMCPUThread(PVM pVM); -VMMR3DECL(RTTHREAD) VMR3GetVMCPUThreadU(PUVM pUVM); +VMMR3_INT_DECL(RTCPUID) VMR3GetVMCPUId(PVM pVM); +VMMR3DECL(RTTHREAD) VMR3GetVMCPUThread(PUVM pUVM); VMMR3DECL(RTNATIVETHREAD) VMR3GetVMCPUNativeThread(PVM pVM); VMMR3DECL(RTNATIVETHREAD) VMR3GetVMCPUNativeThreadU(PUVM pUVM); -VMMR3DECL(int) VMR3GetCpuCoreAndPackageIdFromCpuId(PVM pVM, VMCPUID idCpu, uint32_t *pidCpuCore, uint32_t *pidCpuPackage); -VMMR3DECL(int) VMR3HotUnplugCpu(PVM pVM, VMCPUID idCpu); -VMMR3DECL(int) VMR3HotPlugCpu(PVM pVM, VMCPUID idCpu); -VMMR3DECL(int) VMR3SetCpuExecutionCap(PVM pVM, uint32_t uCpuExecutionCap); +VMMR3DECL(int) VMR3GetCpuCoreAndPackageIdFromCpuId(PUVM pUVM, VMCPUID idCpu, uint32_t *pidCpuCore, uint32_t *pidCpuPackage); +VMMR3DECL(int) VMR3HotUnplugCpu(PUVM pUVM, VMCPUID idCpu); +VMMR3DECL(int) VMR3HotPlugCpu(PUVM pUVM, VMCPUID idCpu); +VMMR3DECL(int) VMR3SetCpuExecutionCap(PUVM pUVM, uint32_t uCpuExecutionCap); +VMMR3DECL(int) VMR3SetPowerOffInsteadOfReset(PUVM pUVM, bool fPowerOffInsteadOfReset); /** @} */ #endif /* IN_RING3 */ diff --git a/include/VBox/vmm/vmm.h b/include/VBox/vmm/vmm.h index e3af0c29..bd3cee05 100644 --- a/include/VBox/vmm/vmm.h +++ b/include/VBox/vmm/vmm.h @@ -3,7 +3,7 @@ */ /* - * Copyright (C) 2006-2010 Oracle Corporation + * Copyright (C) 2006-2013 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -31,6 +31,7 @@ #include <VBox/sup.h> #include <VBox/log.h> #include <iprt/stdarg.h> +#include <iprt/thread.h> RT_C_DECLS_BEGIN @@ -63,6 +64,10 @@ typedef enum VMMSWITCHER VMMSWITCHER_AMD64_TO_PAE, /** Switcher for AMD64 host paging to AMD64 shadow paging. */ VMMSWITCHER_AMD64_TO_AMD64, + /** Stub switcher for 32-bit and PAE. */ + VMMSWITCHER_X86_STUB, + /** Stub switcher for AMD64. */ + VMMSWITCHER_AMD64_STUB, /** Used to make a count for array declarations and suchlike. */ VMMSWITCHER_MAX, /** The usual 32-bit paranoia. */ @@ -81,6 +86,10 @@ typedef enum VMMCALLRING3 VMMCALLRING3_PDM_LOCK, /** Acquire the critical section specified as argument. */ VMMCALLRING3_PDM_CRIT_SECT_ENTER, + /** Enter the R/W critical section (in argument) exclusively. */ + VMMCALLRING3_PDM_CRIT_SECT_RW_ENTER_EXCL, + /** Enter the R/W critical section (in argument) shared. */ + VMMCALLRING3_PDM_CRIT_SECT_RW_ENTER_SHARED, /** Acquire the PGM lock. */ VMMCALLRING3_PGM_LOCK, /** Grow the PGM shadow page pool. */ @@ -103,7 +112,8 @@ typedef enum VMMCALLRING3 VMMCALLRING3_VM_SET_RUNTIME_ERROR, /** Signal a ring 0 assertion. */ VMMCALLRING3_VM_R0_ASSERTION, - /** Ring switch to force preemption. */ + /** Ring switch to force preemption. This is also used by PDMCritSect to + * handle VERR_INTERRUPTED in kernel context. */ VMMCALLRING3_VM_R0_PREEMPT, /** Sync the FTM state with the standby node. */ VMMCALLRING3_FTM_SET_CHECKPOINT, @@ -112,17 +122,16 @@ typedef enum VMMCALLRING3 } VMMCALLRING3; /** - * VMMR3AtomicExecuteHandler callback function. + * VMMRZCallRing3 notification callback. * * @returns VBox status code. - * @param pVM Pointer to the shared VM structure. - * @param pvUser User specified argument - * - * @todo missing prefix. + * @param pVCpu Pointer to the VMCPU. + * @param enmOperation The operation causing the ring-3 jump. + * @param pvUser The user argument. */ -typedef DECLCALLBACK(int) FNATOMICHANDLER(PVM pVM, void *pvUser); -/** Pointer to a FNMMATOMICHANDLER(). */ -typedef FNATOMICHANDLER *PFNATOMICHANDLER; +typedef DECLCALLBACK(int) FNVMMR0CALLRING3NOTIFICATION(PVMCPU pVCpu, VMMCALLRING3 enmOperation, void *pvUser); +/** Pointer to a FNRTMPNOTIFICATION(). */ +typedef FNVMMR0CALLRING3NOTIFICATION *PFNVMMR0CALLRING3NOTIFICATION; /** * Rendezvous callback. @@ -213,6 +222,16 @@ typedef struct VMM2USERMETHODS */ DECLR3CALLBACKMEMBER(void, pfnNotifyPdmtTerm,(PCVMM2USERMETHODS pThis, PUVM pUVM)); + /** + * Notification callback that that a VM reset will be turned into a power off. + * + * @param pThis Pointer to the callback method table. + * @param pUVM The user mode VM handle. + * + * @remarks This is optional and shall be set to NULL if not wanted. + */ + DECLR3CALLBACKMEMBER(void, pfnNotifyResetTurnedIntoPowerOff,(PCVMM2USERMETHODS pThis, PUVM pUVM)); + /** Magic value (VMM2USERMETHODS_MAGIC) marking the end of the structure. */ uint32_t u32EndMagic; } VMM2USERMETHODS; @@ -220,28 +239,34 @@ typedef struct VMM2USERMETHODS /** Magic value of the VMM2USERMETHODS (Franz Kafka). */ #define VMM2USERMETHODS_MAGIC UINT32_C(0x18830703) /** The VMM2USERMETHODS structure version. */ -#define VMM2USERMETHODS_VERSION UINT32_C(0x00020000) +#define VMM2USERMETHODS_VERSION UINT32_C(0x00020001) -VMMDECL(RTRCPTR) VMMGetStackRC(PVMCPU pVCpu); -VMMDECL(VMCPUID) VMMGetCpuId(PVM pVM); -VMMDECL(PVMCPU) VMMGetCpu(PVM pVM); -VMMDECL(PVMCPU) VMMGetCpu0(PVM pVM); -VMMDECL(PVMCPU) VMMGetCpuById(PVM pVM, VMCPUID idCpu); -VMMDECL(uint32_t) VMMGetSvnRev(void); -VMMDECL(VMMSWITCHER) VMMGetSwitcher(PVM pVM); -VMMDECL(void) VMMTrashVolatileXMMRegs(void); - -/** @def VMMIsHwVirtExtForced - * Checks if forced to use the hardware assisted virtualization extensions. - * - * This is intended for making setup decisions where we can save resources when - * using hardware assisted virtualization. +/** + * Checks whether we've armed the ring-0 long jump machinery. * - * @returns true / false. - * @param pVM Pointer to the shared VM structure. + * @returns @c true / @c false + * @param pVCpu The caller's cross context virtual CPU structure. + * @thread EMT + * @sa VMMR0IsLongJumpArmed */ -#define VMMIsHwVirtExtForced(pVM) ((pVM)->fHwVirtExtForced) +#ifdef IN_RING0 +# define VMMIsLongJumpArmed(a_pVCpu) VMMR0IsLongJumpArmed(a_pVCpu) +#else +# define VMMIsLongJumpArmed(a_pVCpu) (false) +#endif + + +VMM_INT_DECL(RTRCPTR) VMMGetStackRC(PVMCPU pVCpu); +VMMDECL(VMCPUID) VMMGetCpuId(PVM pVM); +VMMDECL(PVMCPU) VMMGetCpu(PVM pVM); +VMMDECL(PVMCPU) VMMGetCpu0(PVM pVM); +VMMDECL(PVMCPU) VMMGetCpuById(PVM pVM, VMCPUID idCpu); +VMMR3DECL(PVMCPU) VMMR3GetCpuByIdU(PUVM pVM, VMCPUID idCpu); +VMM_INT_DECL(uint32_t) VMMGetSvnRev(void); +VMM_INT_DECL(VMMSWITCHER) VMMGetSwitcher(PVM pVM); +VMM_INT_DECL(bool) VMMIsInRing3Call(PVMCPU pVCpu); +VMM_INT_DECL(void) VMMTrashVolatileXMMRegs(void); #ifdef IN_RING3 @@ -251,23 +276,26 @@ VMMDECL(void) VMMTrashVolatileXMMRegs(void); */ VMMR3_INT_DECL(int) VMMR3Init(PVM pVM); VMMR3_INT_DECL(int) VMMR3InitR0(PVM pVM); +# ifdef VBOX_WITH_RAW_MODE VMMR3_INT_DECL(int) VMMR3InitRC(PVM pVM); +# endif VMMR3_INT_DECL(int) VMMR3InitCompleted(PVM pVM, VMINITCOMPLETED enmWhat); VMMR3_INT_DECL(int) VMMR3Term(PVM pVM); VMMR3_INT_DECL(void) VMMR3Relocate(PVM pVM, RTGCINTPTR offDelta); VMMR3_INT_DECL(int) VMMR3UpdateLoggers(PVM pVM); VMMR3DECL(const char *) VMMR3GetRZAssertMsg1(PVM pVM); VMMR3DECL(const char *) VMMR3GetRZAssertMsg2(PVM pVM); -VMMR3_INT_DECL(int) VMMR3GetImportRC(PVM pVM, const char *pszSymbol, PRTRCPTR pRCPtrValue); VMMR3_INT_DECL(int) VMMR3SelectSwitcher(PVM pVM, VMMSWITCHER enmSwitcher); -VMMR3_INT_DECL(int) VMMR3DisableSwitcher(PVM pVM); VMMR3_INT_DECL(RTR0PTR) VMMR3GetHostToGuestSwitcher(PVM pVM, VMMSWITCHER enmSwitcher); +VMMR3_INT_DECL(int) VMMR3HmRunGC(PVM pVM, PVMCPU pVCpu); +# ifdef VBOX_WITH_RAW_MODE VMMR3_INT_DECL(int) VMMR3RawRunGC(PVM pVM, PVMCPU pVCpu); -VMMR3_INT_DECL(int) VMMR3HwAccRunGC(PVM pVM, PVMCPU pVCpu); +VMMR3DECL(int) VMMR3ResumeHyper(PVM pVM, PVMCPU pVCpu); +VMMR3_INT_DECL(int) VMMR3GetImportRC(PVM pVM, const char *pszSymbol, PRTRCPTR pRCPtrValue); VMMR3DECL(int) VMMR3CallRC(PVM pVM, RTRCPTR RCPtrEntry, unsigned cArgs, ...); VMMR3DECL(int) VMMR3CallRCV(PVM pVM, RTRCPTR RCPtrEntry, unsigned cArgs, va_list args); +# endif VMMR3DECL(int) VMMR3CallR0(PVM pVM, uint32_t uOperation, uint64_t u64Arg, PSUPVMMR0REQHDR pReqHdr); -VMMR3DECL(int) VMMR3ResumeHyper(PVM pVM, PVMCPU pVCpu); VMMR3DECL(void) VMMR3FatalDump(PVM pVM, PVMCPU pVCpu, int rcErr); VMMR3_INT_DECL(void) VMMR3YieldSuspend(PVM pVM); VMMR3_INT_DECL(void) VMMR3YieldStop(PVM pVM); @@ -320,7 +348,7 @@ typedef enum VMMR0OPERATION /** Run guest context. */ VMMR0_DO_RAW_RUN = SUP_VMMR0_DO_RAW_RUN, /** Run guest code using the available hardware acceleration technology. */ - VMMR0_DO_HWACC_RUN = SUP_VMMR0_DO_HWACC_RUN, + VMMR0_DO_HM_RUN = SUP_VMMR0_DO_HM_RUN, /** Official NOP that we use for profiling. */ VMMR0_DO_NOP = SUP_VMMR0_DO_NOP, /** Official slow iocl NOP that we use for profiling. */ @@ -352,9 +380,9 @@ typedef enum VMMR0OPERATION /** Call VMMR0 Per VM Termination. */ VMMR0_DO_VMMR0_TERM, /** Setup the hardware accelerated raw-mode session. */ - VMMR0_DO_HWACC_SETUP_VM, + VMMR0_DO_HM_SETUP_VM, /** Attempt to enable or disable hardware accelerated raw-mode. */ - VMMR0_DO_HWACC_ENABLE, + VMMR0_DO_HM_ENABLE, /** Calls function in the hypervisor. * The caller must setup the hypervisor context so the call will be performed. * The difference between VMMR0_DO_RUN_GC and this one is the handling of @@ -475,18 +503,30 @@ typedef struct GCFGMVALUEREQ */ typedef GCFGMVALUEREQ *PGCFGMVALUEREQ; -VMMR0DECL(int) VMMR0EntryInt(PVM pVM, VMMR0OPERATION enmOperation, void *pvArg); -VMMR0DECL(void) VMMR0EntryFast(PVM pVM, VMCPUID idCpu, VMMR0OPERATION enmOperation); -VMMR0DECL(int) VMMR0EntryEx(PVM pVM, VMCPUID idCpu, VMMR0OPERATION enmOperation, PSUPVMMR0REQHDR pReq, uint64_t u64Arg, PSUPDRVSESSION); -VMMR0DECL(int) VMMR0TermVM(PVM pVM, PGVM pGVM); - -#ifdef LOG_ENABLED -VMMR0DECL(void) VMMR0LogFlushDisable(PVMCPU pVCpu); -VMMR0DECL(void) VMMR0LogFlushEnable(PVMCPU pVCpu); -#else -#define VMMR0LogFlushDisable(pVCpu) do { } while(0) -#define VMMR0LogFlushEnable(pVCpu) do { } while(0) -#endif +#ifdef IN_RING0 +VMMR0DECL(int) VMMR0EntryInt(PVM pVM, VMMR0OPERATION enmOperation, void *pvArg); +VMMR0DECL(void) VMMR0EntryFast(PVM pVM, VMCPUID idCpu, VMMR0OPERATION enmOperation); +VMMR0DECL(int) VMMR0EntryEx(PVM pVM, VMCPUID idCpu, VMMR0OPERATION enmOperation, PSUPVMMR0REQHDR pReq, uint64_t u64Arg, PSUPDRVSESSION); +VMMR0DECL(int) VMMR0TermVM(PVM pVM, PGVM pGVM); +VMMR0_INT_DECL(bool) VMMR0IsLongJumpArmed(PVMCPU pVCpu); +VMMR0_INT_DECL(bool) VMMR0IsInRing3LongJump(PVMCPU pVCpu); +VMMR0DECL(int) VMMR0ThreadCtxHooksCreate(PVMCPU pVCpu); +VMMR0DECL(void) VMMR0ThreadCtxHooksRelease(PVMCPU pVCpu); +VMMR0DECL(bool) VMMR0ThreadCtxHooksAreCreated(PVMCPU pVCpu); +VMMR0DECL(int) VMMR0ThreadCtxHooksRegister(PVMCPU pVCpu, PFNRTTHREADCTXHOOK pfnHook); +VMMR0DECL(int) VMMR0ThreadCtxHooksDeregister(PVMCPU pVCpu); +VMMR0DECL(bool) VMMR0ThreadCtxHooksAreRegistered(PVMCPU pVCpu); + +# ifdef LOG_ENABLED +VMMR0DECL(void) VMMR0LogFlushDisable(PVMCPU pVCpu); +VMMR0DECL(void) VMMR0LogFlushEnable(PVMCPU pVCpu); +VMMR0DECL(bool) VMMR0IsLogFlushDisabled(PVMCPU pVCpu); +# else +# define VMMR0LogFlushDisable(pVCpu) do { } while(0) +# define VMMR0LogFlushEnable(pVCpu) do { } while(0) +# define VMMR0IsLogFlushDisabled(pVCpu) (true) +# endif /* LOG_ENABLED */ +#endif /* IN_RING0 */ /** @} */ @@ -512,6 +552,9 @@ VMMRZDECL(int) VMMRZCallRing3NoCpu(PVM pVM, VMMCALLRING3 enmOperation, uint VMMRZDECL(void) VMMRZCallRing3Disable(PVMCPU pVCpu); VMMRZDECL(void) VMMRZCallRing3Enable(PVMCPU pVCpu); VMMRZDECL(bool) VMMRZCallRing3IsEnabled(PVMCPU pVCpu); +VMMRZDECL(int) VMMRZCallRing3SetNotification(PVMCPU pVCpu, R0PTRTYPE(PFNVMMR0CALLRING3NOTIFICATION) pfnCallback, RTR0PTR pvUser); +VMMRZDECL(void) VMMRZCallRing3RemoveNotification(PVMCPU pVCpu); +VMMRZDECL(bool) VMMRZCallRing3IsNotificationSet(PVMCPU pVCpu); /** @} */ #endif |