summaryrefslogtreecommitdiff
path: root/src/VBox/VMM/include/HMInternal.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/VMM/include/HMInternal.h')
-rw-r--r--src/VBox/VMM/include/HMInternal.h1002
1 files changed, 1002 insertions, 0 deletions
diff --git a/src/VBox/VMM/include/HMInternal.h b/src/VBox/VMM/include/HMInternal.h
new file mode 100644
index 00000000..fc1c953f
--- /dev/null
+++ b/src/VBox/VMM/include/HMInternal.h
@@ -0,0 +1,1002 @@
+/* $Id: HMInternal.h $ */
+/** @file
+ * HM - Internal header file.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef ___HMInternal_h
+#define ___HMInternal_h
+
+#include <VBox/cdefs.h>
+#include <VBox/types.h>
+#include <VBox/vmm/em.h>
+#include <VBox/vmm/stam.h>
+#include <VBox/dis.h>
+#include <VBox/vmm/hm.h>
+#include <VBox/vmm/hm_vmx.h>
+#include <VBox/vmm/pgm.h>
+#include <VBox/vmm/cpum.h>
+#include <iprt/memobj.h>
+#include <iprt/cpuset.h>
+#include <iprt/mp.h>
+#include <iprt/avl.h>
+
+#if HC_ARCH_BITS == 64 || defined(VBOX_WITH_HYBRID_32BIT_KERNEL) || defined (VBOX_WITH_64_BITS_GUESTS)
+/* Enable 64 bits guest support. */
+# define VBOX_ENABLE_64_BITS_GUESTS
+#endif
+
+#if HC_ARCH_BITS == 32 && defined(VBOX_ENABLE_64_BITS_GUESTS) && !defined(VBOX_WITH_HYBRID_32BIT_KERNEL)
+# define VMX_USE_CACHED_VMCS_ACCESSES
+#endif
+
+/** @def HM_PROFILE_EXIT_DISPATCH
+ * Enables profiling of the VM exit handler dispatching. */
+#if 0
+# define HM_PROFILE_EXIT_DISPATCH
+#endif
+
+/* The MSR auto load/store used to not work for KERNEL_GS_BASE MSR, thus we
+ * used to handle this MSR manually. See @bugref{6208}. This was clearly visible while
+ * booting Solaris 11 (11.1 b19) VMs with 2 Cpus. This is no longer the case and we
+ * always auto load/store the KERNEL_GS_BASE MSR.
+ *
+ * Note: don't forget to update the assembly files while modifying this!
+ */
+/** @todo This define should always be in effect and the define itself removed
+ after 'sufficient' testing. */
+# define VBOX_WITH_AUTO_MSR_LOAD_RESTORE
+
+RT_C_DECLS_BEGIN
+
+
+/** @defgroup grp_hm_int Internal
+ * @ingroup grp_hm
+ * @internal
+ * @{
+ */
+
+/** @def HMCPU_CF_CLEAR
+ * Clears a HM-context flag for the given VCPU.
+ *
+ * @param pVCpu Pointer to the VMCPU.
+ * @param fFlag The flag to clear.
+ */
+#define HMCPU_CF_CLEAR(pVCpu, fFlag) (ASMAtomicUoAndU32(&(pVCpu)->hm.s.fContextUseFlags, ~(fFlag)))
+
+/** @def VMCPU_FF_SET
+ * Sets a HM-context flag for the given VCPU.
+ *
+ * @param pVCpu Pointer to the VMCPU.
+ * @param fFlag The flag to set.
+ */
+#define HMCPU_CF_SET(pVCpu, fFlag) (ASMAtomicUoOrU32(&(pVCpu)->hm.s.fContextUseFlags, (fFlag)))
+
+/** @def HMCPU_CF_IS_SET
+ * Checks if all the flags in the specified HM-context set is pending.
+ *
+ * @param pVCpu Pointer to the VMCPU.
+ * @param fFlag The flag to check.
+ */
+#define HMCPU_CF_IS_SET(pVCpu, fFlag) ((ASMAtomicUoReadU32(&(pVCpu)->hm.s.fContextUseFlags) & (fFlag)) == (fFlag))
+
+/** @def HMCPU_CF_IS_PENDING
+ * Checks if one or more of the flags in the specified HM-context set is
+ * pending.
+ *
+ * @param pVCpu Pointer to the VMCPU.
+ * @param fFlags The flags to check for.
+ */
+#define HMCPU_CF_IS_PENDING(pVCpu, fFlags) RT_BOOL(ASMAtomicUoReadU32(&(pVCpu)->hm.s.fContextUseFlags) & (fFlags))
+
+/** @def HMCPU_CF_IS_PENDING_ONLY
+ * Checks if -only- one or more of the specified HM-context flags is pending.
+ *
+ * @param pVCpu Pointer to the VMCPU.
+ * @param fFlags The flags to check for.
+ */
+#define HMCPU_CF_IS_PENDING_ONLY(pVCpu, fFlags) !RT_BOOL(ASMAtomicUoReadU32(&(pVCpu)->hm.s.fContextUseFlags) & ~(fFlags))
+
+/** @def HMCPU_CF_IS_SET_ONLY
+ * Checks if -only- all the flags in the specified HM-context set is pending.
+ *
+ * @param pVCpu Pointer to the VMCPU.
+ * @param fFlags The flags to check for.
+ */
+#define HMCPU_CF_IS_SET_ONLY(pVCpu, fFlags) (ASMAtomicUoReadU32(&(pVCpu)->hm.s.fContextUseFlags) == (fFlags))
+
+/** @def HMCPU_CF_RESET_TO
+ * Resets the HM-context flags to the specified value.
+ *
+ * @param pVCpu Pointer to the VMCPU.
+ * @param fFlags The new value.
+ */
+#define HMCPU_CF_RESET_TO(pVCpu, fFlags) (ASMAtomicUoWriteU32(&(pVCpu)->hm.s.fContextUseFlags, (fFlags)))
+
+/** @def HMCPU_CF_VALUE
+ * Returns the current HM-context flags value.
+ *
+ * @param pVCpu Pointer to the VMCPU.
+ */
+#define HMCPU_CF_VALUE(pVCpu) (ASMAtomicUoReadU32(&(pVCpu)->hm.s.fContextUseFlags))
+
+
+/** Maximum number of exit reason statistics counters. */
+#define MAX_EXITREASON_STAT 0x100
+#define MASK_EXITREASON_STAT 0xff
+#define MASK_INJECT_IRQ_STAT 0xff
+
+/** @name HM changed flags.
+ * These flags are used to keep track of which important registers that
+ * have been changed since last they were reset.
+ * @{
+ */
+#define HM_CHANGED_GUEST_CR0 RT_BIT(0)
+#define HM_CHANGED_GUEST_CR3 RT_BIT(1)
+#define HM_CHANGED_GUEST_CR4 RT_BIT(2)
+#define HM_CHANGED_GUEST_GDTR RT_BIT(3)
+#define HM_CHANGED_GUEST_IDTR RT_BIT(4)
+#define HM_CHANGED_GUEST_LDTR RT_BIT(5)
+#define HM_CHANGED_GUEST_TR RT_BIT(6)
+#define HM_CHANGED_GUEST_SEGMENT_REGS RT_BIT(7)
+#define HM_CHANGED_GUEST_DEBUG RT_BIT(8)
+#define HM_CHANGED_GUEST_RIP RT_BIT(9)
+#define HM_CHANGED_GUEST_RSP RT_BIT(10)
+#define HM_CHANGED_GUEST_RFLAGS RT_BIT(11)
+#define HM_CHANGED_GUEST_CR2 RT_BIT(12)
+#define HM_CHANGED_GUEST_SYSENTER_CS_MSR RT_BIT(13)
+#define HM_CHANGED_GUEST_SYSENTER_EIP_MSR RT_BIT(14)
+#define HM_CHANGED_GUEST_SYSENTER_ESP_MSR RT_BIT(15)
+/* VT-x specific state. */
+#define HM_CHANGED_VMX_GUEST_AUTO_MSRS RT_BIT(16)
+#define HM_CHANGED_VMX_GUEST_ACTIVITY_STATE RT_BIT(17)
+#define HM_CHANGED_VMX_GUEST_APIC_STATE RT_BIT(18)
+#define HM_CHANGED_VMX_ENTRY_CTLS RT_BIT(19)
+#define HM_CHANGED_VMX_EXIT_CTLS RT_BIT(20)
+/* AMD-V specific state. */
+#define HM_CHANGED_SVM_GUEST_EFER_MSR RT_BIT(16)
+#define HM_CHANGED_SVM_GUEST_APIC_STATE RT_BIT(17)
+#define HM_CHANGED_SVM_RESERVED1 RT_BIT(18)
+#define HM_CHANGED_SVM_RESERVED2 RT_BIT(19)
+#define HM_CHANGED_SVM_RESERVED3 RT_BIT(20)
+
+#define HM_CHANGED_ALL_GUEST ( HM_CHANGED_GUEST_CR0 \
+ | HM_CHANGED_GUEST_CR3 \
+ | HM_CHANGED_GUEST_CR4 \
+ | HM_CHANGED_GUEST_GDTR \
+ | HM_CHANGED_GUEST_IDTR \
+ | HM_CHANGED_GUEST_LDTR \
+ | HM_CHANGED_GUEST_TR \
+ | HM_CHANGED_GUEST_SEGMENT_REGS \
+ | HM_CHANGED_GUEST_DEBUG \
+ | HM_CHANGED_GUEST_RIP \
+ | HM_CHANGED_GUEST_RSP \
+ | HM_CHANGED_GUEST_RFLAGS \
+ | HM_CHANGED_GUEST_CR2 \
+ | HM_CHANGED_GUEST_SYSENTER_CS_MSR \
+ | HM_CHANGED_GUEST_SYSENTER_EIP_MSR \
+ | HM_CHANGED_GUEST_SYSENTER_ESP_MSR \
+ | HM_CHANGED_VMX_GUEST_AUTO_MSRS \
+ | HM_CHANGED_VMX_GUEST_ACTIVITY_STATE \
+ | HM_CHANGED_VMX_GUEST_APIC_STATE \
+ | HM_CHANGED_VMX_ENTRY_CTLS \
+ | HM_CHANGED_VMX_EXIT_CTLS)
+
+#define HM_CHANGED_HOST_CONTEXT RT_BIT(21)
+
+/* Bits shared between host and guest. */
+#define HM_CHANGED_HOST_GUEST_SHARED_STATE ( HM_CHANGED_GUEST_CR0 \
+ | HM_CHANGED_GUEST_DEBUG)
+/** @} */
+
+/** Maximum number of page flushes we are willing to remember before considering a full TLB flush. */
+#define HM_MAX_TLB_SHOOTDOWN_PAGES 8
+
+/** Size for the EPT identity page table (1024 4 MB pages to cover the entire address space). */
+#define HM_EPT_IDENTITY_PG_TABLE_SIZE PAGE_SIZE
+/** Size of the TSS structure + 2 pages for the IO bitmap + end byte. */
+#define HM_VTX_TSS_SIZE (sizeof(VBOXTSS) + 2 * PAGE_SIZE + 1)
+/** Total guest mapped memory needed. */
+#define HM_VTX_TOTAL_DEVHEAP_MEM (HM_EPT_IDENTITY_PG_TABLE_SIZE + HM_VTX_TSS_SIZE)
+
+/** Enable for TPR guest patching. */
+#define VBOX_HM_WITH_GUEST_PATCHING
+
+/** HM SSM version
+ */
+#ifdef VBOX_HM_WITH_GUEST_PATCHING
+# define HM_SSM_VERSION 5
+# define HM_SSM_VERSION_NO_PATCHING 4
+#else
+# define HM_SSM_VERSION 4
+# define HM_SSM_VERSION_NO_PATCHING 4
+#endif
+#define HM_SSM_VERSION_2_0_X 3
+
+/**
+ * Global per-cpu information. (host)
+ */
+typedef struct HMGLOBALCPUINFO
+{
+ /** The CPU ID. */
+ RTCPUID idCpu;
+ /** The memory object */
+ RTR0MEMOBJ hMemObj;
+ /** Current ASID (AMD-V) / VPID (Intel). */
+ uint32_t uCurrentAsid;
+ /** TLB flush count. */
+ uint32_t cTlbFlushes;
+ /** Whether to flush each new ASID/VPID before use. */
+ bool fFlushAsidBeforeUse;
+ /** Configured for VT-x or AMD-V. */
+ bool fConfigured;
+ /** Set if the VBOX_HWVIRTEX_IGNORE_SVM_IN_USE hack is active. */
+ bool fIgnoreAMDVInUseError;
+ /** In use by our code. (for power suspend) */
+ volatile bool fInUse;
+} HMGLOBALCPUINFO;
+/** Pointer to the per-cpu global information. */
+typedef HMGLOBALCPUINFO *PHMGLOBALCPUINFO;
+
+typedef enum
+{
+ HMPENDINGIO_INVALID = 0,
+ HMPENDINGIO_PORT_READ,
+ HMPENDINGIO_PORT_WRITE,
+ HMPENDINGIO_STRING_READ,
+ HMPENDINGIO_STRING_WRITE,
+ /** The usual 32-bit paranoia. */
+ HMPENDINGIO_32BIT_HACK = 0x7fffffff
+} HMPENDINGIO;
+
+
+typedef enum
+{
+ HMTPRINSTR_INVALID,
+ HMTPRINSTR_READ,
+ HMTPRINSTR_READ_SHR4,
+ HMTPRINSTR_WRITE_REG,
+ HMTPRINSTR_WRITE_IMM,
+ HMTPRINSTR_JUMP_REPLACEMENT,
+ /** The usual 32-bit paranoia. */
+ HMTPRINSTR_32BIT_HACK = 0x7fffffff
+} HMTPRINSTR;
+
+typedef struct
+{
+ /** The key is the address of patched instruction. (32 bits GC ptr) */
+ AVLOU32NODECORE Core;
+ /** Original opcode. */
+ uint8_t aOpcode[16];
+ /** Instruction size. */
+ uint32_t cbOp;
+ /** Replacement opcode. */
+ uint8_t aNewOpcode[16];
+ /** Replacement instruction size. */
+ uint32_t cbNewOp;
+ /** Instruction type. */
+ HMTPRINSTR enmType;
+ /** Source operand. */
+ uint32_t uSrcOperand;
+ /** Destination operand. */
+ uint32_t uDstOperand;
+ /** Number of times the instruction caused a fault. */
+ uint32_t cFaults;
+ /** Patch address of the jump replacement. */
+ RTGCPTR32 pJumpTarget;
+} HMTPRPATCH;
+/** Pointer to HMTPRPATCH. */
+typedef HMTPRPATCH *PHMTPRPATCH;
+
+/**
+ * Switcher function, HC to the special 64-bit RC.
+ *
+ * @param pVM Pointer to the VM.
+ * @param offCpumVCpu Offset from pVM->cpum to pVM->aCpus[idCpu].cpum.
+ * @returns Return code indicating the action to take.
+ */
+typedef DECLCALLBACK(int) FNHMSWITCHERHC(PVM pVM, uint32_t offCpumVCpu);
+/** Pointer to switcher function. */
+typedef FNHMSWITCHERHC *PFNHMSWITCHERHC;
+
+/**
+ * HM VM Instance data.
+ * Changes to this must checked against the padding of the hm union in VM!
+ */
+typedef struct HM
+{
+ /** Set when we've initialized VMX or SVM. */
+ bool fInitialized;
+
+ /** Set if nested paging is enabled. */
+ bool fNestedPaging;
+
+ /** Set if nested paging is allowed. */
+ bool fAllowNestedPaging;
+
+ /** Set if large pages are enabled (requires nested paging). */
+ bool fLargePages;
+
+ /** Set if we can support 64-bit guests or not. */
+ bool fAllow64BitGuests;
+
+ /** Set if an IO-APIC is configured for this VM. */
+ bool fHasIoApic;
+
+ /** Set when TPR patching is allowed. */
+ bool fTRPPatchingAllowed;
+
+ /** Set when we initialize VT-x or AMD-V once for all CPUs. */
+ bool fGlobalInit;
+
+ /** Set when TPR patching is active. */
+ bool fTPRPatchingActive;
+ bool u8Alignment[7];
+
+ /** Maximum ASID allowed. */
+ uint32_t uMaxAsid;
+
+ /** The maximum number of resumes loops allowed in ring-0 (safety precaution).
+ * This number is set much higher when RTThreadPreemptIsPending is reliable. */
+ uint32_t cMaxResumeLoops;
+
+ /** Guest allocated memory for patching purposes. */
+ RTGCPTR pGuestPatchMem;
+ /** Current free pointer inside the patch block. */
+ RTGCPTR pFreeGuestPatchMem;
+ /** Size of the guest patch memory block. */
+ uint32_t cbGuestPatchMem;
+ uint32_t uPadding1;
+
+#if HC_ARCH_BITS == 32 && defined(VBOX_ENABLE_64_BITS_GUESTS) && !defined(VBOX_WITH_HYBRID_32BIT_KERNEL)
+ /** 32 to 64 bits switcher entrypoint. */
+ R0PTRTYPE(PFNHMSWITCHERHC) pfnHost32ToGuest64R0;
+ RTR0PTR uPadding2;
+#endif
+
+ struct
+ {
+ /** Set by the ring-0 side of HM to indicate VMX is supported by the
+ * CPU. */
+ bool fSupported;
+
+ /** Set when we've enabled VMX. */
+ bool fEnabled;
+
+ /** Set if VPID is supported. */
+ bool fVpid;
+
+ /** Set if VT-x VPID is allowed. */
+ bool fAllowVpid;
+
+ /** Set if unrestricted guest execution is in use (real and protected mode without paging). */
+ bool fUnrestrictedGuest;
+
+ /** Set if unrestricted guest execution is allowed to be used. */
+ bool fAllowUnrestricted;
+
+ /** Whether we're using the preemption timer or not. */
+ bool fUsePreemptTimer;
+ /** The shift mask employed by the VMX-Preemption timer. */
+ uint8_t cPreemptTimerShift;
+
+ /** Virtual address of the TSS page used for real mode emulation. */
+ R3PTRTYPE(PVBOXTSS) pRealModeTSS;
+
+ /** Virtual address of the identity page table used for real mode and protected mode without paging emulation in EPT mode. */
+ R3PTRTYPE(PX86PD) pNonPagingModeEPTPageTable;
+
+ /** R0 memory object for the APIC-access page. */
+ RTR0MEMOBJ hMemObjApicAccess;
+ /** Physical address of the APIC-access page. */
+ RTHCPHYS HCPhysApicAccess;
+ /** Virtual address of the APIC-access page. */
+ R0PTRTYPE(uint8_t *) pbApicAccess;
+
+#ifdef VBOX_WITH_CRASHDUMP_MAGIC
+ RTR0MEMOBJ hMemObjScratch;
+ RTHCPHYS HCPhysScratch;
+ R0PTRTYPE(uint8_t *) pbScratch;
+#endif
+
+ /** Internal Id of which flush-handler to use for tagged-TLB entries. */
+ unsigned uFlushTaggedTlb;
+
+#if HC_ARCH_BITS == 32 && defined(VBOX_ENABLE_64_BITS_GUESTS)
+ uint32_t u32Alignment;
+#endif
+ /** Host CR4 value (set by ring-0 VMX init) */
+ uint64_t u64HostCr4;
+
+ /** Host EFER value (set by ring-0 VMX init) */
+ uint64_t u64HostEfer;
+
+ /** VMX MSR values */
+ VMXMSRS Msrs;
+
+ /** Flush types for invept & invvpid; they depend on capabilities. */
+ VMX_FLUSH_EPT enmFlushEpt;
+ VMX_FLUSH_VPID enmFlushVpid;
+ } vmx;
+
+ struct
+ {
+ /** Set by the ring-0 side of HM to indicate SVM is supported by the
+ * CPU. */
+ bool fSupported;
+ /** Set when we've enabled SVM. */
+ bool fEnabled;
+ /** Set if erratum 170 affects the AMD cpu. */
+ bool fAlwaysFlushTLB;
+ /** Set when the hack to ignore VERR_SVM_IN_USE is active. */
+ bool fIgnoreInUseError;
+
+ /** R0 memory object for the IO bitmap (12kb). */
+ RTR0MEMOBJ hMemObjIOBitmap;
+ /** Physical address of the IO bitmap (12kb). */
+ RTHCPHYS HCPhysIOBitmap;
+ /** Virtual address of the IO bitmap. */
+ R0PTRTYPE(void *) pvIOBitmap;
+
+ /* HWCR MSR (for diagnostics) */
+ uint64_t u64MsrHwcr;
+
+ /** SVM revision. */
+ uint32_t u32Rev;
+
+ /** SVM feature bits from cpuid 0x8000000a */
+ uint32_t u32Features;
+ } svm;
+
+ /**
+ * AVL tree with all patches (active or disabled) sorted by guest instruction address
+ */
+ AVLOU32TREE PatchTree;
+ uint32_t cPatches;
+ HMTPRPATCH aPatches[64];
+
+ struct
+ {
+ uint32_t u32AMDFeatureECX;
+ uint32_t u32AMDFeatureEDX;
+ } cpuid;
+
+ /** Saved error from detection */
+ int32_t lLastError;
+
+ /** HMR0Init was run */
+ bool fHMR0Init;
+ bool u8Alignment1[7];
+
+ STAMCOUNTER StatTprPatchSuccess;
+ STAMCOUNTER StatTprPatchFailure;
+ STAMCOUNTER StatTprReplaceSuccess;
+ STAMCOUNTER StatTprReplaceFailure;
+} HM;
+/** Pointer to HM VM instance data. */
+typedef HM *PHM;
+
+/* Maximum number of cached entries. */
+#define VMCSCACHE_MAX_ENTRY 128
+
+/* Structure for storing read and write VMCS actions. */
+typedef struct VMCSCACHE
+{
+#ifdef VBOX_WITH_CRASHDUMP_MAGIC
+ /* Magic marker for searching in crash dumps. */
+ uint8_t aMagic[16];
+ uint64_t uMagic;
+ uint64_t u64TimeEntry;
+ uint64_t u64TimeSwitch;
+ uint64_t cResume;
+ uint64_t interPD;
+ uint64_t pSwitcher;
+ uint32_t uPos;
+ uint32_t idCpu;
+#endif
+ /* CR2 is saved here for EPT syncing. */
+ uint64_t cr2;
+ struct
+ {
+ uint32_t cValidEntries;
+ uint32_t uAlignment;
+ uint32_t aField[VMCSCACHE_MAX_ENTRY];
+ uint64_t aFieldVal[VMCSCACHE_MAX_ENTRY];
+ } Write;
+ struct
+ {
+ uint32_t cValidEntries;
+ uint32_t uAlignment;
+ uint32_t aField[VMCSCACHE_MAX_ENTRY];
+ uint64_t aFieldVal[VMCSCACHE_MAX_ENTRY];
+ } Read;
+#ifdef VBOX_STRICT
+ struct
+ {
+ RTHCPHYS HCPhysCpuPage;
+ RTHCPHYS HCPhysVmcs;
+ RTGCPTR pCache;
+ RTGCPTR pCtx;
+ } TestIn;
+ struct
+ {
+ RTHCPHYS HCPhysVmcs;
+ RTGCPTR pCache;
+ RTGCPTR pCtx;
+ uint64_t eflags;
+ uint64_t cr8;
+ } TestOut;
+ struct
+ {
+ uint64_t param1;
+ uint64_t param2;
+ uint64_t param3;
+ uint64_t param4;
+ } ScratchPad;
+#endif
+} VMCSCACHE;
+/** Pointer to VMCSCACHE. */
+typedef VMCSCACHE *PVMCSCACHE;
+
+/** VMX StartVM function. */
+typedef DECLCALLBACK(int) FNHMVMXSTARTVM(RTHCUINT fResume, PCPUMCTX pCtx, PVMCSCACHE pCache, PVM pVM, PVMCPU pVCpu);
+/** Pointer to a VMX StartVM function. */
+typedef R0PTRTYPE(FNHMVMXSTARTVM *) PFNHMVMXSTARTVM;
+
+/** SVM VMRun function. */
+typedef DECLCALLBACK(int) FNHMSVMVMRUN(RTHCPHYS pVmcbHostPhys, RTHCPHYS pVmcbPhys, PCPUMCTX pCtx, PVM pVM, PVMCPU pVCpu);
+/** Pointer to a SVM VMRun function. */
+typedef R0PTRTYPE(FNHMSVMVMRUN *) PFNHMSVMVMRUN;
+
+/**
+ * HM VMCPU Instance data.
+ */
+typedef struct HMCPU
+{
+ /** Set if we need to flush the TLB during the world switch. */
+ bool fForceTLBFlush;
+ /** Set when we're using VT-x or AMD-V at that moment. */
+ bool fActive;
+ /** Set when the TLB has been checked until we return from the world switch. */
+ volatile bool fCheckedTLBFlush;
+ /** Whether we're executing a single instruction. */
+ bool fSingleInstruction;
+ /** Set if we need to clear the trap flag because of single stepping. */
+ bool fClearTrapFlag;
+ /** Whether we've completed the inner HM leave function. */
+ bool fLeaveDone;
+ /** Whether we're using the hyper DR7 or guest DR7. */
+ bool fUsingHyperDR7;
+ uint8_t abAlignment[1];
+
+ /** World switch exit counter. */
+ volatile uint32_t cWorldSwitchExits;
+ /** HM_CHANGED_* flags. */
+ volatile uint32_t fContextUseFlags;
+ /** Id of the last cpu we were executing code on (NIL_RTCPUID for the first
+ * time). */
+ RTCPUID idLastCpu;
+ /** TLB flush count. */
+ uint32_t cTlbFlushes;
+ /** Current ASID in use by the VM. */
+ uint32_t uCurrentAsid;
+ /** An additional error code used for some gurus. */
+ uint32_t u32HMError;
+ /** Host's TSC_AUX MSR (used when RDTSCP doesn't cause VM-exits). */
+ uint64_t u64HostTscAux;
+
+ struct
+ {
+ /** Physical address of the VM control structure (VMCS). */
+ RTHCPHYS HCPhysVmcs;
+ /** R0 memory object for the VM control structure (VMCS). */
+ RTR0MEMOBJ hMemObjVmcs;
+ /** Virtual address of the VM control structure (VMCS). */
+ R0PTRTYPE(void *) pvVmcs;
+ /** Ring 0 handlers for VT-x. */
+ PFNHMVMXSTARTVM pfnStartVM;
+#if HC_ARCH_BITS == 32
+ uint32_t u32Alignment1;
+#endif
+
+ /** Current VMX_VMCS32_CTRL_PIN_EXEC. */
+ uint32_t u32PinCtls;
+ /** Current VMX_VMCS32_CTRL_PROC_EXEC. */
+ uint32_t u32ProcCtls;
+ /** Current VMX_VMCS32_CTRL_PROC_EXEC2. */
+ uint32_t u32ProcCtls2;
+ /** Current VMX_VMCS32_CTRL_EXIT. */
+ uint32_t u32ExitCtls;
+ /** Current VMX_VMCS32_CTRL_ENTRY. */
+ uint32_t u32EntryCtls;
+
+ /** Physical address of the virtual APIC page for TPR caching. */
+ RTHCPHYS HCPhysVirtApic;
+ /** R0 memory object for the virtual APIC page for TPR caching. */
+ RTR0MEMOBJ hMemObjVirtApic;
+ /** Virtual address of the virtual APIC page for TPR caching. */
+ R0PTRTYPE(uint8_t *) pbVirtApic;
+#if HC_ARCH_BITS == 32
+ uint32_t u32Alignment2;
+#endif
+
+ /** Current CR0 mask. */
+ uint32_t u32CR0Mask;
+ /** Current CR4 mask. */
+ uint32_t u32CR4Mask;
+ /** Current exception bitmap. */
+ uint32_t u32XcptBitmap;
+ /** The updated-guest-state mask. */
+ volatile uint32_t fUpdatedGuestState;
+ /** Current EPTP. */
+ RTHCPHYS HCPhysEPTP;
+
+ /** Physical address of the MSR bitmap. */
+ RTHCPHYS HCPhysMsrBitmap;
+ /** R0 memory object for the MSR bitmap. */
+ RTR0MEMOBJ hMemObjMsrBitmap;
+ /** Virtual address of the MSR bitmap. */
+ R0PTRTYPE(void *) pvMsrBitmap;
+
+#ifdef VBOX_WITH_AUTO_MSR_LOAD_RESTORE
+ /** Physical address of the VM-entry MSR-load and VM-exit MSR-store area (used
+ * for guest MSRs). */
+ RTHCPHYS HCPhysGuestMsr;
+ /** R0 memory object of the VM-entry MSR-load and VM-exit MSR-store area
+ * (used for guest MSRs). */
+ RTR0MEMOBJ hMemObjGuestMsr;
+ /** Virtual address of the VM-entry MSR-load and VM-exit MSR-store area (used
+ * for guest MSRs). */
+ R0PTRTYPE(void *) pvGuestMsr;
+
+ /** Physical address of the VM-exit MSR-load area (used for host MSRs). */
+ RTHCPHYS HCPhysHostMsr;
+ /** R0 memory object for the VM-exit MSR-load area (used for host MSRs). */
+ RTR0MEMOBJ hMemObjHostMsr;
+ /** Virtual address of the VM-exit MSR-load area (used for host MSRs). */
+ R0PTRTYPE(void *) pvHostMsr;
+
+ /** Number of automatically loaded/restored guest MSRs during the world switch. */
+ uint32_t cGuestMsrs;
+ uint32_t uAlignment;
+#endif /* VBOX_WITH_AUTO_MSR_LOAD_RESTORE */
+
+ /** The cached APIC-base MSR used for identifying when to map the HC physical APIC-access page. */
+ uint64_t u64MsrApicBase;
+ /** Last use TSC offset value. (cached) */
+ uint64_t u64TSCOffset;
+
+ /** VMCS cache. */
+ VMCSCACHE VMCSCache;
+
+ /** Real-mode emulation state. */
+ struct
+ {
+ X86DESCATTR AttrCS;
+ X86DESCATTR AttrDS;
+ X86DESCATTR AttrES;
+ X86DESCATTR AttrFS;
+ X86DESCATTR AttrGS;
+ X86DESCATTR AttrSS;
+ X86EFLAGS Eflags;
+ uint32_t fRealOnV86Active;
+ } RealMode;
+
+ struct
+ {
+ uint64_t u64VMCSPhys;
+ uint32_t u32VMCSRevision;
+ uint32_t u32InstrError;
+ uint32_t u32ExitReason;
+ RTCPUID idEnteredCpu;
+ RTCPUID idCurrentCpu;
+ uint32_t u32Padding;
+ } LastError;
+
+ /** State of the VMCS. */
+ uint32_t uVmcsState;
+ /** Which host-state bits to restore before being preempted. */
+ uint32_t fRestoreHostFlags;
+ /** The host-state restoration structure. */
+ VMXRESTOREHOST RestoreHost;
+ /** Set if guest was executing in real mode (extra checks). */
+ bool fWasInRealMode;
+ /** Padding. */
+ uint32_t u32Padding;
+ } vmx;
+
+ struct
+ {
+ /** R0 memory object for the host VMCB which holds additional host-state. */
+ RTR0MEMOBJ hMemObjVmcbHost;
+ /** Physical address of the host VMCB which holds additional host-state. */
+ RTHCPHYS HCPhysVmcbHost;
+ /** Virtual address of the host VMCB which holds additional host-state. */
+ R0PTRTYPE(void *) pvVmcbHost;
+
+ /** R0 memory object for the guest VMCB. */
+ RTR0MEMOBJ hMemObjVmcb;
+ /** Physical address of the guest VMCB. */
+ RTHCPHYS HCPhysVmcb;
+ /** Virtual address of the guest VMCB. */
+ R0PTRTYPE(void *) pvVmcb;
+
+ /** Ring 0 handlers for VT-x. */
+ PFNHMSVMVMRUN pfnVMRun;
+
+ /** R0 memory object for the MSR bitmap (8 KB). */
+ RTR0MEMOBJ hMemObjMsrBitmap;
+ /** Physical address of the MSR bitmap (8 KB). */
+ RTHCPHYS HCPhysMsrBitmap;
+ /** Virtual address of the MSR bitmap. */
+ R0PTRTYPE(void *) pvMsrBitmap;
+
+ /** Whether VTPR with V_INTR_MASKING set is in effect, indicating
+ * we should check if the VTPR changed on every VM-exit. */
+ bool fSyncVTpr;
+ uint8_t u8Align[7];
+
+ /** Alignment padding. */
+ uint32_t u32Padding;
+ } svm;
+
+ /** Event injection state. */
+ struct
+ {
+ uint32_t fPending;
+ uint32_t u32ErrCode;
+ uint32_t cbInstr;
+ uint32_t u32Padding; /**< Explicit alignment padding. */
+ uint64_t u64IntInfo;
+ RTGCUINTPTR GCPtrFaultAddress;
+ } Event;
+
+ /** IO Block emulation state. */
+ struct
+ {
+ bool fEnabled;
+ uint8_t u8Align[7];
+
+ /** RIP at the start of the io code we wish to emulate in the recompiler. */
+ RTGCPTR GCPtrFunctionEip;
+
+ uint64_t cr0;
+ } EmulateIoBlock;
+
+ struct
+ {
+ /** Pending IO operation type. */
+ HMPENDINGIO enmType;
+ uint32_t uPadding;
+ RTGCPTR GCPtrRip;
+ RTGCPTR GCPtrRipNext;
+ union
+ {
+ struct
+ {
+ uint32_t uPort;
+ uint32_t uAndVal;
+ uint32_t cbSize;
+ } Port;
+ uint64_t aRaw[2];
+ } s;
+ } PendingIO;
+
+ /** The PAE PDPEs used with Nested Paging (only valid when
+ * VMCPU_FF_HM_UPDATE_PAE_PDPES is set). */
+ X86PDPE aPdpes[4];
+
+ /** Current shadow paging mode. */
+ PGMMODE enmShadowMode;
+
+ /** The CPU ID of the CPU currently owning the VMCS. Set in
+ * HMR0Enter and cleared in HMR0Leave. */
+ RTCPUID idEnteredCpu;
+
+ /** To keep track of pending TLB shootdown pages. (SMP guest only) */
+ struct
+ {
+ RTGCPTR aPages[HM_MAX_TLB_SHOOTDOWN_PAGES];
+ uint32_t cPages;
+ uint32_t u32Padding; /**< Explicit alignment padding. */
+ } TlbShootdown;
+
+ /** For saving stack space, the disassembler state is allocated here instead of
+ * on the stack. */
+ DISCPUSTATE DisState;
+
+ STAMPROFILEADV StatEntry;
+ STAMPROFILEADV StatExit1;
+ STAMPROFILEADV StatExit2;
+ STAMPROFILEADV StatExitIO;
+ STAMPROFILEADV StatExitMovCRx;
+ STAMPROFILEADV StatExitXcptNmi;
+ STAMPROFILEADV StatLoadGuestState;
+ STAMPROFILEADV StatInGC;
+
+#if HC_ARCH_BITS == 32 && defined(VBOX_ENABLE_64_BITS_GUESTS) && !defined(VBOX_WITH_HYBRID_32BIT_KERNEL)
+ STAMPROFILEADV StatWorldSwitch3264;
+#endif
+ STAMPROFILEADV StatPoke;
+ STAMPROFILEADV StatSpinPoke;
+ STAMPROFILEADV StatSpinPokeFailed;
+
+ STAMCOUNTER StatInjectInterrupt;
+ STAMCOUNTER StatInjectXcpt;
+ STAMCOUNTER StatInjectPendingReflect;
+
+ STAMCOUNTER StatExitAll;
+ STAMCOUNTER StatExitShadowNM;
+ STAMCOUNTER StatExitGuestNM;
+ STAMCOUNTER StatExitShadowPF; /* Misleading, currently used for MMIO #PFs as well. */
+ STAMCOUNTER StatExitShadowPFEM;
+ STAMCOUNTER StatExitGuestPF;
+ STAMCOUNTER StatExitGuestUD;
+ STAMCOUNTER StatExitGuestSS;
+ STAMCOUNTER StatExitGuestNP;
+ STAMCOUNTER StatExitGuestGP;
+ STAMCOUNTER StatExitGuestDE;
+ STAMCOUNTER StatExitGuestDB;
+ STAMCOUNTER StatExitGuestMF;
+ STAMCOUNTER StatExitGuestBP;
+ STAMCOUNTER StatExitGuestXF;
+ STAMCOUNTER StatExitGuestXcpUnk;
+ STAMCOUNTER StatExitInvlpg;
+ STAMCOUNTER StatExitInvd;
+ STAMCOUNTER StatExitWbinvd;
+ STAMCOUNTER StatExitPause;
+ STAMCOUNTER StatExitCpuid;
+ STAMCOUNTER StatExitRdtsc;
+ STAMCOUNTER StatExitRdtscp;
+ STAMCOUNTER StatExitRdpmc;
+ STAMCOUNTER StatExitRdrand;
+ STAMCOUNTER StatExitCli;
+ STAMCOUNTER StatExitSti;
+ STAMCOUNTER StatExitPushf;
+ STAMCOUNTER StatExitPopf;
+ STAMCOUNTER StatExitIret;
+ STAMCOUNTER StatExitInt;
+ STAMCOUNTER StatExitCRxWrite[16];
+ STAMCOUNTER StatExitCRxRead[16];
+ STAMCOUNTER StatExitDRxWrite;
+ STAMCOUNTER StatExitDRxRead;
+ STAMCOUNTER StatExitRdmsr;
+ STAMCOUNTER StatExitWrmsr;
+ STAMCOUNTER StatExitClts;
+ STAMCOUNTER StatExitXdtrAccess;
+ STAMCOUNTER StatExitHlt;
+ STAMCOUNTER StatExitMwait;
+ STAMCOUNTER StatExitMonitor;
+ STAMCOUNTER StatExitLmsw;
+ STAMCOUNTER StatExitIOWrite;
+ STAMCOUNTER StatExitIORead;
+ STAMCOUNTER StatExitIOStringWrite;
+ STAMCOUNTER StatExitIOStringRead;
+ STAMCOUNTER StatExitIntWindow;
+ STAMCOUNTER StatExitMaxResume;
+ STAMCOUNTER StatExitExtInt;
+ STAMCOUNTER StatExitHostNmiInGC;
+ STAMCOUNTER StatExitPreemptTimer;
+ STAMCOUNTER StatExitTprBelowThreshold;
+ STAMCOUNTER StatExitTaskSwitch;
+ STAMCOUNTER StatExitMtf;
+ STAMCOUNTER StatExitApicAccess;
+ STAMCOUNTER StatPendingHostIrq;
+
+ STAMCOUNTER StatPreemptPreempting;
+ STAMCOUNTER StatPreemptSaveHostState;
+
+ STAMCOUNTER StatFlushPage;
+ STAMCOUNTER StatFlushPageManual;
+ STAMCOUNTER StatFlushPhysPageManual;
+ STAMCOUNTER StatFlushTlb;
+ STAMCOUNTER StatFlushTlbManual;
+ STAMCOUNTER StatFlushTlbWorldSwitch;
+ STAMCOUNTER StatNoFlushTlbWorldSwitch;
+ STAMCOUNTER StatFlushEntire;
+ STAMCOUNTER StatFlushAsid;
+ STAMCOUNTER StatFlushNestedPaging;
+ STAMCOUNTER StatFlushTlbInvlpgVirt;
+ STAMCOUNTER StatFlushTlbInvlpgPhys;
+ STAMCOUNTER StatTlbShootdown;
+ STAMCOUNTER StatTlbShootdownFlush;
+
+ STAMCOUNTER StatSwitchGuestIrq;
+ STAMCOUNTER StatSwitchHmToR3FF;
+ STAMCOUNTER StatSwitchExitToR3;
+ STAMCOUNTER StatSwitchLongJmpToR3;
+
+ STAMCOUNTER StatTscOffset;
+ STAMCOUNTER StatTscIntercept;
+ STAMCOUNTER StatTscInterceptOverFlow;
+
+ STAMCOUNTER StatExitReasonNpf;
+ STAMCOUNTER StatDRxArmed;
+ STAMCOUNTER StatDRxContextSwitch;
+ STAMCOUNTER StatDRxIoCheck;
+
+ STAMCOUNTER StatLoadMinimal;
+ STAMCOUNTER StatLoadFull;
+
+ STAMCOUNTER StatVmxCheckBadRmSelBase;
+ STAMCOUNTER StatVmxCheckBadRmSelLimit;
+ STAMCOUNTER StatVmxCheckRmOk;
+
+ STAMCOUNTER StatVmxCheckBadSel;
+ STAMCOUNTER StatVmxCheckBadRpl;
+ STAMCOUNTER StatVmxCheckBadLdt;
+ STAMCOUNTER StatVmxCheckBadTr;
+ STAMCOUNTER StatVmxCheckPmOk;
+
+#if HC_ARCH_BITS == 32 && defined(VBOX_ENABLE_64_BITS_GUESTS) && !defined(VBOX_WITH_HYBRID_32BIT_KERNEL)
+ STAMCOUNTER StatFpu64SwitchBack;
+ STAMCOUNTER StatDebug64SwitchBack;
+#endif
+
+#ifdef VBOX_WITH_STATISTICS
+ R3PTRTYPE(PSTAMCOUNTER) paStatExitReason;
+ R0PTRTYPE(PSTAMCOUNTER) paStatExitReasonR0;
+ R3PTRTYPE(PSTAMCOUNTER) paStatInjectedIrqs;
+ R0PTRTYPE(PSTAMCOUNTER) paStatInjectedIrqsR0;
+#endif
+#ifdef HM_PROFILE_EXIT_DISPATCH
+ STAMPROFILEADV StatExitDispatch;
+#endif
+} HMCPU;
+/** Pointer to HM VM instance data. */
+typedef HMCPU *PHMCPU;
+
+
+#ifdef IN_RING0
+
+VMMR0DECL(PHMGLOBALCPUINFO) HMR0GetCurrentCpu(void);
+VMMR0DECL(PHMGLOBALCPUINFO) HMR0GetCurrentCpuEx(RTCPUID idCpu);
+
+
+#ifdef VBOX_STRICT
+VMMR0DECL(void) HMDumpRegs(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx);
+VMMR0DECL(void) HMR0DumpDescriptor(PCX86DESCHC pDesc, RTSEL Sel, const char *pszMsg);
+#else
+# define HMDumpRegs(a, b ,c) do { } while (0)
+# define HMR0DumpDescriptor(a, b, c) do { } while (0)
+#endif
+
+# ifdef VBOX_WITH_KERNEL_USING_XMM
+DECLASM(int) HMR0VMXStartVMWrapXMM(RTHCUINT fResume, PCPUMCTX pCtx, PVMCSCACHE pCache, PVM pVM, PVMCPU pVCpu, PFNHMVMXSTARTVM pfnStartVM);
+DECLASM(int) HMR0SVMRunWrapXMM(RTHCPHYS pVmcbHostPhys, RTHCPHYS pVmcbPhys, PCPUMCTX pCtx, PVM pVM, PVMCPU pVCpu, PFNHMSVMVMRUN pfnVMRun);
+# endif
+
+# ifdef VBOX_WITH_HYBRID_32BIT_KERNEL
+/**
+ * Gets 64-bit GDTR and IDTR on darwin.
+ * @param pGdtr Where to store the 64-bit GDTR.
+ * @param pIdtr Where to store the 64-bit IDTR.
+ */
+DECLASM(void) HMR0Get64bitGdtrAndIdtr(PX86XDTR64 pGdtr, PX86XDTR64 pIdtr);
+
+/**
+ * Gets 64-bit CR3 on darwin.
+ * @returns CR3
+ */
+DECLASM(uint64_t) HMR0Get64bitCR3(void);
+# endif
+
+#endif /* IN_RING0 */
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif
+