HWVMXR0.cpp revision 6293a1351126a53fbd29b1ac410d04251618caf4
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * HM VMX (VT-x) - Host Context Ring-0.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * Copyright (C) 2006-2012 Oracle Corporation
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * This file is part of VirtualBox Open Source Edition (OSE), as
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * available from http://www.virtualbox.org. This file is free software;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * you can redistribute it and/or modify it under the terms of the GNU
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * General Public License (GPL) as published by the Free Software
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * Foundation, in version 2 as it comes in the "COPYING" file of the
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
dff2cc5646d4437ab9e0cb1dcb59da65462a5938jeff.schenk/*******************************************************************************
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk* Header Files *
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk*******************************************************************************/
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk/*******************************************************************************
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk* Defined Constants And Macros *
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk*******************************************************************************/
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk# define VMX_IS_64BIT_HOST_MODE() (g_fVMXIs64bitHost != 0)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk# define VMX_IS_64BIT_HOST_MODE() (false)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk/*******************************************************************************
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk* Global Variables *
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk*******************************************************************************/
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk/* IO operation lookup arrays. */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkstatic uint32_t const g_aIOSize[4] = {1, 2, 0, 4};
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkstatic uint32_t const g_aIOOpAnd[4] = {0xff, 0xffff, 0, 0xffffffff};
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk/** See HWACCMR0A.asm. */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk/*******************************************************************************
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk* Local Functions *
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk*******************************************************************************/
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkstatic DECLCALLBACK(void) hmR0VmxSetupTLBEPT(PVM pVM, PVMCPU pVCpu);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkstatic DECLCALLBACK(void) hmR0VmxSetupTLBVPID(PVM pVM, PVMCPU pVCpu);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkstatic DECLCALLBACK(void) hmR0VmxSetupTLBBoth(PVM pVM, PVMCPU pVCpu);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkstatic DECLCALLBACK(void) hmR0VmxSetupTLBDummy(PVM pVM, PVMCPU pVCpu);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkstatic void hmR0VmxFlushEPT(PVM pVM, PVMCPU pVCpu, VMX_FLUSH_EPT enmFlush);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkstatic void hmR0VmxFlushVPID(PVM pVM, PVMCPU pVCpu, VMX_FLUSH_VPID enmFlush, RTGCPTR GCPtr);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkstatic void hmR0VmxUpdateExceptionBitmap(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkstatic void hmR0VmxSetMSRPermission(PVMCPU pVCpu, unsigned ulMSR, bool fRead, bool fWrite);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkstatic void hmR0VmxReportWorldSwitchError(PVM pVM, PVMCPU pVCpu, VBOXSTRICTRC rc, PCPUMCTX pCtx);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * Updates error from VMCS to HWACCMCPU's lasterror record.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * @param pVM Pointer to the VM.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * @param pVCpu Pointer to the VMCPU.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * @param rc The error code.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkstatic void hmR0VmxCheckError(PVM pVM, PVMCPU pVCpu, int rc)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk VMXReadVMCS(VMX_VMCS32_RO_VM_INSTR_ERROR, &instrError);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk pVCpu->hwaccm.s.vmx.lasterror.ulInstrError = instrError;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * Sets up and activates VT-x on the current CPU.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * @returns VBox status code.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * @param pCpu Pointer to the CPU info struct.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * @param pVM Pointer to the VM. (can be NULL after a resume!!)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * @param pvCpuPage Pointer to the global CPU page.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * @param HCPhysCpuPage Physical address of the global CPU page.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * @param fEnabledByHost Set if SUPR0EnableVTx or similar was used to enable
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * VT-x/AMD-V on the host.
dff2cc5646d4437ab9e0cb1dcb59da65462a5938jeff.schenkVMMR0DECL(int) VMXR0EnableCpu(PHMGLOBLCPUINFO pCpu, PVM pVM, void *pvCpuPage, RTHCPHYS HCPhysCpuPage, bool fEnabledByHost)
dff2cc5646d4437ab9e0cb1dcb59da65462a5938jeff.schenk AssertReturn(HCPhysCpuPage != 0 && HCPhysCpuPage != NIL_RTHCPHYS, VERR_INVALID_PARAMETER);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk AssertReturn(pvCpuPage, VERR_INVALID_PARAMETER);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk /* Set revision dword at the beginning of the VMXON structure. */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk *(uint32_t *)pvCpuPage = MSR_IA32_VMX_BASIC_INFO_VMCS_ID(pVM->hwaccm.s.vmx.msr.vmx_basic_info);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk /** @todo we should unmap the two pages from the virtual address space in order to prevent accidental corruption.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * (which can have very bad consequences!!!)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk /** @todo r=bird: Why is this code different than the probing code earlier
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * on? It just sets VMXE if needed and doesn't check that it isn't
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * set. Mac OS X host_vmxoff may leave this set and we'll fail here
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * and debug-assert in the calling code. This is what caused the
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * "regression" after backing out the SUPR0EnableVTx code hours before
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * 4.2.0GA (reboot fixed the issue). I've changed here to do the same
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * as the init code. */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk ASMSetCR4(ASMGetCR4() | X86_CR4_VMXE); /* Make sure the VMX instructions don't cause #UD faults. */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * Enter VM root mode.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * Flush all VPIDs (in case we or any other hypervisor have been using VPIDs) so that
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * we can avoid an explicit flush while using new VPIDs. We would still need to flush
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * each time while reusing a VPID after hitting the MaxASID limit once.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk && (pVM->hwaccm.s.vmx.msr.vmx_eptcaps & MSR_IA32_VMX_EPT_CAPS_INVVPID_CAPS_ALL_CONTEXTS))
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk hmR0VmxFlushVPID(pVM, NULL /* pvCpu */, VMX_FLUSH_VPID_ALL_CONTEXTS, 0 /* GCPtr */);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * Ensure each VCPU scheduled on this CPU gets a new VPID on resume. See @bugref{6255}.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * Deactivates VT-x on the current CPU.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * @returns VBox status code.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * @param pCpu Pointer to the CPU info struct.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * @param pvCpuPage Pointer to the global CPU page.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * @param HCPhysCpuPage Physical address of the global CPU page.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkVMMR0DECL(int) VMXR0DisableCpu(PHMGLOBLCPUINFO pCpu, void *pvCpuPage, RTHCPHYS HCPhysCpuPage)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk AssertReturn(HCPhysCpuPage != 0 && HCPhysCpuPage != NIL_RTHCPHYS, VERR_INVALID_PARAMETER);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk AssertReturn(pvCpuPage, VERR_INVALID_PARAMETER);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk /* If we're somehow not in VMX root mode, then we shouldn't dare leaving it. */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk /* Leave VMX Root Mode. */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk /* And clear the X86_CR4_VMXE bit. */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * Does Ring-0 per VM VT-x initialization.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * @returns VBox status code.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * @param pVM Pointer to the VM.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk if (pVM->hwaccm.s.vmx.msr.vmx_proc_ctls.n.allowed1 & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_USE_TPR_SHADOW)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk /* Allocate one page for the APIC physical page (serves for filtering accesses). */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk rc = RTR0MemObjAllocCont(&pVM->hwaccm.s.vmx.pMemObjAPIC, PAGE_SIZE, false /* executable R0 mapping */);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk pVM->hwaccm.s.vmx.pAPIC = (uint8_t *)RTR0MemObjAddress(pVM->hwaccm.s.vmx.pMemObjAPIC);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk pVM->hwaccm.s.vmx.pAPICPhys = RTR0MemObjGetPagePhysAddr(pVM->hwaccm.s.vmx.pMemObjAPIC, 0);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk ASMMemZero32(pVM->hwaccm.s.vmx.pAPIC, PAGE_SIZE);
#ifdef VBOX_WITH_CRASHDUMP_MAGIC
rc = RTR0MemObjAllocCont(&pVM->hwaccm.s.vmx.pMemObjScratch, PAGE_SIZE, false /* executable R0 mapping */);
return rc;
rc = RTR0MemObjAllocCont(&pVCpu->hwaccm.s.vmx.hMemObjVMCS, PAGE_SIZE, false /* executable R0 mapping */);
return rc;
rc = RTR0MemObjAllocCont(&pVCpu->hwaccm.s.vmx.hMemObjVAPIC, PAGE_SIZE, false /* executable R0 mapping */);
return rc;
if (pVM->hwaccm.s.vmx.msr.vmx_proc_ctls.n.allowed1 & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_USE_MSR_BITMAPS)
rc = RTR0MemObjAllocCont(&pVCpu->hwaccm.s.vmx.pMemObjMSRBitmap, PAGE_SIZE, false /* executable R0 mapping */);
return rc;
pVCpu->hwaccm.s.vmx.pMSRBitmap = (uint8_t *)RTR0MemObjAddress(pVCpu->hwaccm.s.vmx.pMemObjMSRBitmap);
pVCpu->hwaccm.s.vmx.pMSRBitmapPhys = RTR0MemObjGetPagePhysAddr(pVCpu->hwaccm.s.vmx.pMemObjMSRBitmap, 0);
/* Allocate one page for the guest MSR load area (for preloading guest MSRs during the world switch). */
rc = RTR0MemObjAllocCont(&pVCpu->hwaccm.s.vmx.pMemObjGuestMSR, PAGE_SIZE, false /* executable R0 mapping */);
return rc;
pVCpu->hwaccm.s.vmx.pGuestMSRPhys = RTR0MemObjGetPagePhysAddr(pVCpu->hwaccm.s.vmx.pMemObjGuestMSR, 0);
/* Allocate one page for the host MSR load area (for restoring host MSRs after the world switch back). */
rc = RTR0MemObjAllocCont(&pVCpu->hwaccm.s.vmx.pMemObjHostMSR, PAGE_SIZE, false /* executable R0 mapping */);
return rc;
pVCpu->hwaccm.s.vmx.pHostMSRPhys = RTR0MemObjGetPagePhysAddr(pVCpu->hwaccm.s.vmx.pMemObjHostMSR, 0);
#ifdef LOG_ENABLED
SUPR0Printf("VMXR0InitVM %x VMCS=%x (%x)\n", pVM, pVCpu->hwaccm.s.vmx.pvVMCS, (uint32_t)pVCpu->hwaccm.s.vmx.HCPhysVMCS);
return VINF_SUCCESS;
#ifdef VBOX_WITH_CRASHDUMP_MAGIC
return VINF_SUCCESS;
return VERR_VMX_GENERIC;
return VERR_VMX_GENERIC;
if (pVM->hwaccm.s.vmx.msr.vmx_eptcaps & MSR_IA32_VMX_EPT_CAPS_INVVPID_CAPS_SINGLE_CONTEXT_RETAIN_GLOBALS)
Log(("VMXR0SetupVM: Only VMX_FLUSH_VPID_SINGLE_CONTEXT_RETAIN_GLOBALS supported. Ignoring VPID.\n"));
*(uint32_t *)pVCpu->hwaccm.s.vmx.pvVMCS = MSR_IA32_VMX_BASIC_INFO_VMCS_ID(pVM->hwaccm.s.vmx.msr.vmx_basic_info);
goto vmx_end;
goto vmx_end;
if (pVM->hwaccm.s.vmx.msr.vmx_proc_ctls.n.allowed1 & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_USE_TPR_SHADOW)
/* CR8 reads from the APIC shadow page; writes cause an exit is they lower the TPR below the threshold */
val |= VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_CR8_STORE_EXIT | VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_CR8_LOAD_EXIT;
if (pVM->hwaccm.s.vmx.msr.vmx_proc_ctls.n.allowed1 & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_USE_MSR_BITMAPS)
if (pVM->hwaccm.s.vmx.msr.vmx_proc_ctls.n.allowed1 & VMX_VMCS_CTRL_PROC_EXEC_USE_SECONDARY_EXEC_CTRL)
if (pVM->hwaccm.s.vmx.msr.vmx_proc_ctls.n.allowed1 & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_USE_MSR_BITMAPS)
if (pVM->hwaccm.s.vmx.msr.vmx_proc_ctls.n.allowed1 & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_USE_TPR_SHADOW)
return rc;
unsigned ulBit;
AssertFailed();
if (fRead)
if (fWrite)
static int hmR0VmxInjectEvent(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, uint32_t intInfo, uint32_t cbInstr, uint32_t errCode)
int rc;
#ifdef VBOX_WITH_STATISTICS
#ifdef VBOX_STRICT
LogFlow(("hmR0VmxInjectEvent: Injecting interrupt %d at %RGv error code=%08x CR2=%RGv intInfo=%08x\n", iGate,
LogFlow(("hmR0VmxInjectEvent: Injecting interrupt %d at %RGv error code=%08x\n", iGate, (RTGCPTR)pCtx->rip,
errCode));
return hmR0VmxInjectEvent(pVM, pVCpu, pCtx, intInfo2, 0, 0 /* no error code according to the Intel docs */);
return VINF_EM_RESET;
rc = PGMPhysSimpleWriteGCPhys(pVM, pCtx->ss.u64Base + pCtx->sp, &pCtx->eflags, sizeof(uint16_t)); AssertRC(rc);
rc = PGMPhysSimpleWriteGCPhys(pVM, pCtx->ss.u64Base + pCtx->sp, &pCtx->cs, sizeof(uint16_t)); AssertRC(rc);
return VINF_SUCCESS;
rc = VMXWriteVMCS(VMX_VMCS_CTRL_ENTRY_IRQ_INFO, intInfo | (1 << VMX_EXIT_INTERRUPTION_INFO_VALID_SHIFT));
return rc;
int rc;
Log(("CPU%d: Reinjecting event %RX64 %08x at %RGv cr2=%RX64\n", pVCpu->idCpu, pVCpu->hwaccm.s.Event.intInfo,
rc = hmR0VmxInjectEvent(pVM, pVCpu, pCtx, pVCpu->hwaccm.s.Event.intInfo, 0, pVCpu->hwaccm.s.Event.errCode);
return VINF_SUCCESS;
return VINF_SUCCESS;
#ifdef VBOX_STRICT
switch (u8Vector)
case X86_XCPT_DF:
case X86_XCPT_TS:
case X86_XCPT_NP:
case X86_XCPT_SS:
case X86_XCPT_GP:
case X86_XCPT_PF:
case X86_XCPT_AC:
return VINF_SUCCESS;
if (VMX_IS_64BIT_HOST_MODE())
if (VMX_IS_64BIT_HOST_MODE())
/* Note: VMX is (again) very picky about the RPL of the selectors here; we'll restore them manually. */
if (!VMX_IS_64BIT_HOST_MODE())
if (VMX_IS_64BIT_HOST_MODE())
return VERR_VMX_INVALID_HOST_STATE;
if (VMX_IS_64BIT_HOST_MODE())
if (VMX_IS_64BIT_HOST_MODE())
if (VMX_IS_64BIT_HOST_MODE())
unsigned idxMsr = 0;
# if HC_ARCH_BITS == 32 && defined(VBOX_ENABLE_64_BITS_GUESTS) && !defined(VBOX_WITH_HYBRID_32BIT_KERNEL)
if (VMX_IS_64BIT_HOST_MODE())
return rc;
return VINF_SUCCESS;
int rc;
return VINF_SUCCESS;
#ifdef VBOX_ALWAYS_TRAP_PF
#ifdef VBOX_STRICT
#ifdef VBOX_STRICT
int rc;
if (VMX_IS_64BIT_HOST_MODE())
#ifdef VBOX_WITH_REM
attr.u = 0;
AssertMsg((val & 0xf) == X86_SEL_TYPE_SYS_386_TSS_BUSY || (val & 0xf) == X86_SEL_TYPE_SYS_286_TSS_BUSY,
val |= X86_CR0_NE; /* always turn on the native mechanism to report FPU errors (old style uses interrupts) */
/* Protected mode & paging are always enabled; we use them for emulating real and protected mode without paging too. */
/* Note: We must also set this as we rely on protecting various pages for which supervisor writes must be caught. */
| X86_CR0_PG /* Must monitor this bit (assumptions are made for real mode & protected mode without paging emulation) */
| X86_CR0_NE;
#ifdef VBOX_ENABLE_64_BITS_GUESTS
AssertFailed();
AssertFailed();
/* We use 4 MB pages in our identity mapping page table for real and protected mode without paging. */
val = 0
| X86_CR4_VMXE;
if (pVM->hwaccm.s.vmx.msr.vmx_proc_ctls.n.allowed1 & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_MONITOR_TRAP_FLAG)
AssertMsgRC(rc, ("pNonPagingModeEPTPageTable = %RGv\n", pVM->hwaccm.s.vmx.pNonPagingModeEPTPageTable));
#ifdef DEBUG
#if !defined(VBOX_ENABLE_64_BITS_GUESTS)
# ifdef VBOX_WITH_HYBRID_32BIT_KERNEL
unsigned idxMsr = 0;
bool fOffsettedTsc;
uint64_t cTicksToDeadline = TMCpuTickGetDeadlineAndTscOffset(pVCpu, &fOffsettedTsc, &pVCpu->hwaccm.s.vmx.u64TSCOffset);
if (fOffsettedTsc)
/* Note: VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_RDTSC_EXIT takes precedence over TSC_OFFSET, applies to RDTSCP too. */
/* Fall back to rdtsc, rdtscp emulation as we would otherwise pass decreasing tsc values to the guest. */
TMCpuTickGetLastSeen(pVCpu), TMCpuTickGetLastSeen(pVCpu) - u64CurTSC - pVCpu->hwaccm.s.vmx.u64TSCOffset,
return rc;
int rc;
if (uInterruptState != 0)
&& CPUMIsGuestInPagedProtectedModeEx(pCtx)) /** @todo check if we will always catch mode switches and such... */
/* Misc. registers; must sync everything otherwise we can get out of sync when jumping to ring 3. */
pMsr += i;
case MSR_K8_LSTAR:
case MSR_K6_STAR:
case MSR_K8_SF_MASK:
case MSR_K8_KERNEL_GS_BASE:
case MSR_K8_TSC_AUX:
case MSR_K6_EFER:
AssertFailed();
return VERR_HM_UNEXPECTED_LD_ST_MSR;
return VINF_SUCCESS;
* Force a TLB flush for the first world switch if the current CPU differs from the one we ran on last
* If the TLB flush count changed, another VM (VCPU rather) has hit the ASID limit while flushing the TLB
bool fNewASID = false;
fNewASID = true;
if (fNewASID)
#ifdef VBOX_WITH_STATISTICS
#ifdef VBOX_WITH_STATISTICS
* This is not terribly accurate (i.e. we don't have any StatFlushEPT counter). We currently count these
#ifdef VBOX_WITH_STATISTICS
("Flush count mismatch for cpu %d (%x vs %x)\n", pCpu->idCpu, pVCpu->hwaccm.s.cTLBFlushes, pCpu->cTLBFlushes));
AssertMsg(pVCpu->hwaccm.s.uCurrentASID >= 1 && pVCpu->hwaccm.s.uCurrentASID < pVM->hwaccm.s.uMaxASID,
* Force a TLB flush for the first world switch if the current CPU differs from the one we ran on last
#ifdef VBOX_WITH_STATISTICS
* Force a TLB flush for the first world switch if the current CPU differs from the one we ran on last
* If the TLB flush count changed, another VM (VCPU rather) has hit the ASID limit while flushing the TLB
("Flush count mismatch for cpu %d (%x vs %x)\n", pCpu->idCpu, pVCpu->hwaccm.s.cTLBFlushes, pCpu->cTLBFlushes));
AssertMsg(pVCpu->hwaccm.s.uCurrentASID >= 1 && pVCpu->hwaccm.s.uCurrentASID < pVM->hwaccm.s.uMaxASID,
# ifdef VBOX_WITH_STATISTICS
int rc2;
bool fSetupTPRCaching = false;
unsigned cResume = 0;
#ifdef VBOX_STRICT
bool fWasInLongMode = false;
fSetupTPRCaching = true;
#ifdef VBOX_STRICT
if ((val2 & pVM->hwaccm.s.vmx.msr.vmx_pin_ctls.n.disallowed0) != pVM->hwaccm.s.vmx.msr.vmx_pin_ctls.n.disallowed0)
if ((val2 & pVM->hwaccm.s.vmx.msr.vmx_proc_ctls.n.disallowed0) != pVM->hwaccm.s.vmx.msr.vmx_proc_ctls.n.disallowed0)
if ((val2 & pVM->hwaccm.s.vmx.msr.vmx_entry.n.disallowed0) != pVM->hwaccm.s.vmx.msr.vmx_entry.n.disallowed0)
if ((val2 & pVM->hwaccm.s.vmx.msr.vmx_exit.n.disallowed0) != pVM->hwaccm.s.vmx.msr.vmx_exit.n.disallowed0)
#ifdef VBOX_WITH_CRASHDUMP_MAGIC
goto end;
Log(("VM_FF_INHIBIT_INTERRUPTS at %RGv successor %RGv\n", (RTGCPTR)pCtx->rip, EMGetInhibitInterruptsPC(pVCpu)));
* Before we are able to execute this instruction in raw mode (iret to guest code) an external interrupt might
* force a world switch again. Possibly allowing a guest interrupt to be dispatched in the process. This could
* break the guest. Sounds very unlikely, but such timing sensitive problems are not as rare as you might think.
if ( VM_FF_ISPENDING(pVM, VM_FF_HWACCM_TO_R3_MASK | VM_FF_REQUEST | VM_FF_PGM_POOL_FLUSH_PENDING | VM_FF_PDM_DMA)
|| VMCPU_FF_ISPENDING(pVCpu, VMCPU_FF_HWACCM_TO_R3_MASK | VMCPU_FF_PGM_SYNC_CR3 | VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL | VMCPU_FF_REQUEST))
rc = PGMSyncCR3(pVCpu, pCtx->cr0, pCtx->cr3, pCtx->cr4, VMCPU_FF_ISSET(pVCpu, VMCPU_FF_PGM_SYNC_CR3));
goto end;
#ifdef DEBUG
rc = RT_UNLIKELY(VM_FF_ISPENDING(pVM, VM_FF_PGM_NO_MEMORY)) ? VINF_EM_NO_MEMORY : VINF_EM_RAW_TO_R3;
goto end;
/* Pending request packets might contain actions that need immediate attention, such as pending hardware interrupts. */
goto end;
goto end;
goto end;
* Exit to ring-3 preemption/work is pending.
goto end;
goto end;
* Note: The 32-bit exception for AMD (X86_CPUID_AMD_FEATURE_ECX_CR8L), but this appears missing in Intel CPUs.
* Note: We can't do this in LoadGuestState() as PDMApicGetTPR can jump back to ring-3 (lock)!! (no longer true) .
if (fSetupTPRCaching)
bool fPending;
* -> We don't need to be explicitely notified. There are enough world switches for detecting pending interrupts.
if (fPending)
#ifdef LOG_ENABLED
LogFlow(("Force TLB flush due to rescheduling to a different cpu (%d vs %d)\n", pVCpu->hwaccm.s.idLastCpu,
LogFlow(("Force TLB flush due to changed TLB flush count (%x vs %x)\n", pVCpu->hwaccm.s.cTLBFlushes,
#ifdef VBOX_STRICT
#ifdef LOG_ENABLED
goto end;
goto end;
#ifdef VBOX_WITH_CRASHDUMP_MAGIC
#ifndef VBOX_WITH_AUTO_MSR_LOAD_RESTORE
#ifdef VBOX_WITH_KERNEL_USING_XMM
rc = hwaccmR0VMXStartVMWrapXMM(pVCpu->hwaccm.s.fResumeVM, pCtx, &pVCpu->hwaccm.s.vmx.VMCSCache, pVM, pVCpu, pVCpu->hwaccm.s.vmx.pfnStartVM);
rc = pVCpu->hwaccm.s.vmx.pfnStartVM(pVCpu->hwaccm.s.fResumeVM, pCtx, &pVCpu->hwaccm.s.vmx.VMCSCache, pVM, pVCpu);
/* Possibly the last TSC value seen by the guest (too high) (only when we're in TSC offset mode). */
#ifndef VBOX_WITH_AUTO_MSR_LOAD_RESTORE
ASMReadTSC() + pVCpu->hwaccm.s.vmx.u64TSCOffset - 0x400 /* guestimate of world switch overhead in clock ticks */);
AssertMsg(!pVCpu->hwaccm.s.vmx.VMCSCache.Write.cValidEntries, ("pVCpu->hwaccm.s.vmx.VMCSCache.Write.cValidEntries=%d\n",
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* IMPORTANT: WE CAN'T DO ANY LOGGING OR OPERATIONS THAT CAN DO A LONGJMP BACK TO RING 3 *BEFORE* WE'VE SYNCED BACK (MOST OF) THE GUEST STATE
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
goto end;
&& VMX_EXIT_INTERRUPTION_INFO_TYPE(pVCpu->hwaccm.s.Event.intInfo) != VMX_EXIT_INTERRUPTION_INFO_TYPE_SW
/* Ignore software exceptions (such as int3) as they'll reoccur when we restart the instruction anyway. */
&& VMX_EXIT_INTERRUPTION_INFO_TYPE(pVCpu->hwaccm.s.Event.intInfo) != VMX_EXIT_INTERRUPTION_INFO_TYPE_SWEXCPT)
Log(("Pending inject %RX64 at %RGv exit=%08x intInfo=%08x exitQualification=%RGv pending error=%RX64\n",
Log(("Pending inject %RX64 at %RGv exit=%08x intInfo=%08x exitQualification=%RGv\n", pVCpu->hwaccm.s.Event.intInfo,
#ifdef VBOX_STRICT
/* Ignore software exceptions (such as int3) as they're reoccur when we restart the instruction anyway. */
&& VMX_EXIT_INTERRUPTION_INFO_TYPE(pVCpu->hwaccm.s.Event.intInfo) == VMX_EXIT_INTERRUPTION_INFO_TYPE_SWEXCPT)
Log2(("instrInfo=%d instrError=%d instr length=%d\n", (uint32_t)instrInfo, (uint32_t)instrError, (uint32_t)cbInstr));
if ( fSetupTPRCaching
switch (exitReason)
goto ResumeExecution;
switch (vector)
case X86_XCPT_NM:
/* If we sync the FPU/XMM state on-demand, then we can continue execution as if nothing has happened. */
goto ResumeExecution;
rc2 = hmR0VmxInjectEvent(pVM, pVCpu, pCtx, VMX_VMCS_CTRL_ENTRY_IRQ_INFO_FROM_EXIT_INT_INFO(intInfo),
cbInstr, 0);
goto ResumeExecution;
#ifdef VBOX_ALWAYS_TRAP_PF
* A genuine pagefault. Forward the trap to the guest by injecting the exception and resuming execution.
Log(("Guest page fault at %RGv cr2=%RGv error code %RGv rsp=%RGv\n", (RTGCPTR)pCtx->rip, exitQualification,
rc2 = hmR0VmxInjectEvent(pVM, pVCpu, pCtx, VMX_VMCS_CTRL_ENTRY_IRQ_INFO_FROM_EXIT_INT_INFO(intInfo),
goto ResumeExecution;
PHWACCMTPRPATCH pPatch = (PHWACCMTPRPATCH)RTAvloU32Get(&pVM->hwaccm.s.PatchTree, (AVLOU32KEY)pCtx->eip);
if (!pPatch)
rc2 = IOMMMIOMapMMIOHCPage(pVM, GCPhysApicBase, pVM->hwaccm.s.vmx.pAPICPhys, X86_PTE_RW | X86_PTE_P);
Log2(("Shadow page fault at %RGv cr2=%RGv error code %x\n", (RTGCPTR)pCtx->rip, exitQualification ,errCode));
goto ResumeExecution;
* A genuine pagefault. Forward the trap to the guest by injecting the exception and resuming execution.
rc2 = hmR0VmxInjectEvent(pVM, pVCpu, pCtx, VMX_VMCS_CTRL_ENTRY_IRQ_INFO_FROM_EXIT_INT_INFO(intInfo),
goto ResumeExecution;
#ifdef VBOX_STRICT
rc2 = hmR0VmxInjectEvent(pVM, pVCpu, pCtx, VMX_VMCS_CTRL_ENTRY_IRQ_INFO_FROM_EXIT_INT_INFO(intInfo),
goto ResumeExecution;
Log(("Trap %x (debug) at %RGv exit qualification %RX64 dr6=%x dr7=%x\n", vector, (RTGCPTR)pCtx->rip,
rc2 = hmR0VmxInjectEvent(pVM, pVCpu, pCtx, VMX_VMCS_CTRL_ENTRY_IRQ_INFO_FROM_EXIT_INT_INFO(intInfo),
goto ResumeExecution;
Log(("Debugger hardware BP at %04x:%RGv (rc=%Rrc)\n", pCtx->cs.Sel, pCtx->rip, VBOXSTRICTRC_VAL(rc)));
rc2 = hmR0VmxInjectEvent(pVM, pVCpu, pCtx, VMX_VMCS_CTRL_ENTRY_IRQ_INFO_FROM_EXIT_INT_INFO(intInfo),
goto ResumeExecution;
goto ResumeExecution;
#ifdef VBOX_STRICT
rc2 = hmR0VmxInjectEvent(pVM, pVCpu, pCtx, VMX_VMCS_CTRL_ENTRY_IRQ_INFO_FROM_EXIT_INT_INFO(intInfo),
goto ResumeExecution;
LogFlow(("Real mode X86_XCPT_GP instruction emulation at %x:%RGv\n", pCtx->cs.Sel, (RTGCPTR)pCtx->rip));
bool fUpdateRIP = true;
case OP_CLI:
case OP_STI:
case OP_HLT:
fUpdateRIP = false;
case OP_POPF:
eflags.u = 0;
case OP_PUSHF:
&GCPtrStack);
case OP_IRET:
fUpdateRIP = false;
case OP_INT:
fUpdateRIP = false;
case OP_INTO:
fUpdateRIP = false;
case OP_INT3:
fUpdateRIP = false;
fUpdateRIP = false;
if (fUpdateRIP)
goto ResumeExecution;
#ifdef VBOX_STRICT
switch (vector)
rc2 = hmR0VmxInjectEvent(pVM, pVCpu, pCtx, VMX_VMCS_CTRL_ENTRY_IRQ_INFO_FROM_EXIT_INT_INFO(intInfo),
goto ResumeExecution;
goto ResumeExecution;
case VMX_EXIT_EPT_VIOLATION:
errCode = 0;
rc2 = IOMMMIOMapMMIOHCPage(pVM, GCPhysApicBase, pVM->hwaccm.s.vmx.pAPICPhys, X86_PTE_RW | X86_PTE_P);
Log2(("Shadow page fault at %RGv cr2=%RGp error code %x\n", (RTGCPTR)pCtx->rip, exitQualification , errCode));
goto ResumeExecution;
#ifdef VBOX_STRICT
LogFlow(("PGMTrap0eHandlerNestedPaging at %RGv failed with %Rrc\n", (RTGCPTR)pCtx->rip, VBOXSTRICTRC_VAL(rc)));
case VMX_EXIT_EPT_MISCONFIG:
rc2 = IOMMMIOMapMMIOHCPage(pVM, GCPhysApicBase, pVM->hwaccm.s.vmx.pAPICPhys, X86_PTE_RW | X86_PTE_P);
rc = PGMR0Trap0eHandlerNPMisconfig(pVM, pVCpu, PGMMODE_EPT, CPUMCTX2CORE(pCtx), GCPhys, UINT32_MAX);
* of the page containing the instruction via the guest's page tables (we would invalidate the guest page
* in the host TLB), resume execution which would cause a guest page fault to let the guest handle this
goto ResumeExecution;
Log2(("PGMR0Trap0eHandlerNPMisconfig(,,,%RGp) at %RGv -> %Rrc\n", GCPhys, (RTGCPTR)pCtx->rip, VBOXSTRICTRC_VAL(rc)));
VMCPU_FF_ISPENDING(pVCpu, (VMCPU_FF_INTERRUPT_APIC|VMCPU_FF_INTERRUPT_PIC)), pCtx->eflags.Bits.u1IF));
goto ResumeExecution;
goto ResumeExecution;
goto ResumeExecution;
goto ResumeExecution;
goto ResumeExecution;
goto ResumeExecution;
AssertMsg(rc == VERR_EM_INTERPRETER, ("EMU: invlpg %RGv failed with %Rrc\n", exitQualification, VBOXSTRICTRC_VAL(rc)));
goto ResumeExecution;
goto ResumeExecution;
STAM_COUNTER_INC((exitReason == VMX_EXIT_RDMSR) ? &pVCpu->hwaccm.s.StatExitRdmsr : &pVCpu->hwaccm.s.StatExitWrmsr);
goto ResumeExecution;
Log2(("VMX: %RGv mov cr%d, x\n", (RTGCPTR)pCtx->rip, VMX_EXIT_QUALIFICATION_CRX_REGISTER(exitQualification)));
STAM_COUNTER_INC(&pVCpu->hwaccm.s.StatExitCRxWrite[VMX_EXIT_QUALIFICATION_CRX_REGISTER(exitQualification)]);
AssertFailed();
STAM_COUNTER_INC(&pVCpu->hwaccm.s.StatExitCRxRead[VMX_EXIT_QUALIFICATION_CRX_REGISTER(exitQualification)]);
|| !(pVM->hwaccm.s.vmx.msr.vmx_proc_ctls.n.allowed1 & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_USE_TPR_SHADOW));
rc = EMInterpretLMSW(pVM, pVCpu, CPUMCTX2CORE(pCtx), VMX_EXIT_QUALIFICATION_CRX_LMSW_DATA(exitQualification));
goto ResumeExecution;
#ifdef LOG_ENABLED
if (VMX_EXIT_QUALIFICATION_DRX_DIRECTION(exitQualification) == VMX_EXIT_QUALIFICATION_DRX_DIRECTION_WRITE)
Log(("VMX_EXIT_DRX_MOVE: write DR%d genreg %d\n", VMX_EXIT_QUALIFICATION_DRX_REGISTER(exitQualification),
#ifdef VBOX_WITH_STATISTICS
if (VMX_EXIT_QUALIFICATION_DRX_DIRECTION(exitQualification) == VMX_EXIT_QUALIFICATION_DRX_DIRECTION_WRITE)
goto ResumeExecution;
if (VMX_EXIT_QUALIFICATION_DRX_DIRECTION(exitQualification) == VMX_EXIT_QUALIFICATION_DRX_DIRECTION_WRITE)
goto ResumeExecution;
/* Note: We'll get a #GP if the IO instruction isn't allowed (IOPL or TSS bitmap); no need to double check. */
bool fIOWrite = (VMX_EXIT_QUALIFICATION_IO_DIRECTION(exitQualification) == VMX_EXIT_QUALIFICATION_IO_DIRECTION_OUT);
if (fIOWrite)
rc = IOMInterpretOUTSEx(pVM, CPUMCTX2CORE(pCtx), uPort, pDis->fPrefix, (DISCPUMODE)pDis->uAddrMode, cbSize);
rc = IOMInterpretINSEx(pVM, CPUMCTX2CORE(pCtx), uPort, pDis->fPrefix, (DISCPUMODE)pDis->uAddrMode, cbSize);
if (fIOWrite)
rc2 = hmR0VmxInjectEvent(pVM, pVCpu, pCtx, VMX_VMCS_CTRL_ENTRY_IRQ_INFO_FROM_EXIT_INT_INFO(intInfo),
goto ResumeExecution;
goto ResumeExecution;
#ifdef VBOX_STRICT
goto ResumeExecution;
case VMX_EXIT_APIC_ACCESS: /* 44 APIC access. Guest software attempted to access memory at a physical address
switch (uAccessType)
rc = IOMMMIOPhysHandler(pVM, (uAccessType == VMX_APIC_ACCESS_TYPE_LINEAR_READ) ? 0 : X86_TRAP_PF_RW,
case VMX_EXIT_PREEMPTION_TIMER: /* 52 VMX-preemption timer expired. The preemption timer counted down to zero. */
goto ResumeExecution;
switch (exitReason)
case VMX_EXIT_EPT_VIOLATION:
case VMX_EXIT_PREEMPTION_TIMER: /* 52 VMX-preemption timer expired. The preemption timer counted down to zero. */
case VMX_EXIT_TASK_SWITCH: /* 9 Task switch: too complicated to emulate, so fall back to the recompiler */
if ( (VMX_EXIT_QUALIFICATION_TASK_SWITCH_TYPE(exitQualification) == VMX_EXIT_QUALIFICATION_TASK_SWITCH_TYPE_IDT)
Log(("VMX_EXIT_TASK_SWITCH: reassert trap %d\n", VMX_EXIT_INTERRUPTION_INFO_VECTOR(pVCpu->hwaccm.s.Event.intInfo)));
rc2 = TRPMAssertTrap(pVCpu, VMX_EXIT_INTERRUPTION_INFO_VECTOR(pVCpu->hwaccm.s.Event.intInfo), TRPM_HARDWARE_INT);
goto ResumeExecution;
goto ResumeExecution;
AssertMsg(rc == VERR_EM_INTERPRETER || rc == VINF_EM_HALT, ("EMU: mwait failed with %Rrc\n", VBOXSTRICTRC_VAL(rc)));
case VMX_EXIT_APIC_ACCESS: /* 44 APIC access. Guest software attempted to access memory at a physical address
* If we decided to emulate them here, then we must sync the MSRs that could have been changed (sysenter, FS/GS base)
#ifdef VBOX_STRICT
end:
* If we executed vmlaunch/vmresume and an external IRQ was pending, then we don't have to do a full sync the next time.
return VERR_VMX_X86_CR4_VMXE_CLEARED;
return rc;
return VINF_SUCCESS;
#ifdef DEBUG
return VINF_SUCCESS;
AssertMsg(rc == VINF_SUCCESS, ("VMXR0InvEPT %x %RGv failed with %d\n", enmFlush, pVCpu->hwaccm.s.vmx.GCPhysEPTP, rc));
descriptor[0] = 0;
AssertMsg(pVCpu->hwaccm.s.uCurrentASID != 0, ("VMXR0InvVPID invalid ASID %lu\n", pVCpu->hwaccm.s.uCurrentASID));
AssertMsg(pVCpu->hwaccm.s.uCurrentASID <= UINT16_MAX, ("VMXR0InvVPID invalid ASID %lu\n", pVCpu->hwaccm.s.uCurrentASID));
("VMXR0InvVPID %x %x %RGv failed with %d\n", enmFlush, pVCpu ? pVCpu->hwaccm.s.uCurrentASID : 0, GCPtr, rc));
if (!fFlushPending)
return VINF_SUCCESS;
return VINF_SUCCESS;
AssertFailed();
int rc2;
#ifdef VBOX_STRICT
if (VMX_IS_64BIT_HOST_MODE())
#if HC_ARCH_BITS == 32 && defined(VBOX_ENABLE_64_BITS_GUESTS) && !defined(VBOX_WITH_HYBRID_32BIT_KERNEL)
DECLASM(int) VMXR0SwitcherStartVM64(RTHCUINT fResume, PCPUMCTX pCtx, PVMCSCACHE pCache, PVM pVM, PVMCPU pVCpu)
int rc;
#ifdef VBOX_WITH_CRASHDUMP_MAGIC
#ifdef DEBUG
aParam[3] = (uint32_t)(pVCpu->hwaccm.s.vmx.HCPhysVMCS >> 32); /* Param 2: VMCS physical address - Hi. */
#ifdef VBOX_WITH_CRASHDUMP_MAGIC
#ifdef VBOX_WITH_CRASHDUMP_MAGIC
#ifdef DEBUG
AssertMsg(pCache->TestIn.HCPhysCpuPage== HCPhysCpuPage, ("%RHp vs %RHp\n", pCache->TestIn.HCPhysCpuPage, HCPhysCpuPage));
AssertMsg(pCache->TestIn.HCPhysVMCS == pVCpu->hwaccm.s.vmx.HCPhysVMCS, ("%RHp vs %RHp\n", pCache->TestIn.HCPhysVMCS,
AssertMsg(pCache->TestIn.HCPhysVMCS == pCache->TestOut.HCPhysVMCS, ("%RHp vs %RHp\n", pCache->TestIn.HCPhysVMCS,
AssertMsg(pCache->TestIn.pCache == pCache->TestOut.pCache, ("%RGv vs %RGv\n", pCache->TestIn.pCache,
AssertMsg(pCache->TestIn.pCache == VM_RC_ADDR(pVM, &pVM->aCpus[pVCpu->idCpu].hwaccm.s.vmx.VMCSCache),
("%RGv vs %RGv\n", pCache->TestIn.pCache, VM_RC_ADDR(pVM, &pVM->aCpus[pVCpu->idCpu].hwaccm.s.vmx.VMCSCache)));
return rc;
# ifdef VBOX_STRICT
switch (idxField)
case VMX_VMCS64_GUEST_RIP:
case VMX_VMCS64_GUEST_RSP:
case VMX_VMCS_GUEST_RFLAGS:
case VMX_VMCS64_GUEST_CR0:
case VMX_VMCS64_GUEST_CR4:
case VMX_VMCS64_GUEST_DR7:
case VMX_VMCS64_GUEST_CS_BASE:
case VMX_VMCS64_GUEST_DS_BASE:
case VMX_VMCS64_GUEST_ES_BASE:
case VMX_VMCS64_GUEST_FS_BASE:
case VMX_VMCS64_GUEST_GS_BASE:
case VMX_VMCS64_GUEST_SS_BASE:
case VMX_VMCS64_GUEST_TR_BASE:
case VMX_VMCS32_RO_IDT_INFO:
case VMX_VMCS64_GUEST_CR3:
switch (idxField)
case VMX_VMCS64_GUEST_TR_BASE:
case VMX_VMCS64_GUEST_CR0:
case VMX_VMCS64_GUEST_CR4:
case VMX_VMCS64_GUEST_CR3:
case VMX_VMCS64_GUEST_DR7:
case VMX_VMCS64_GUEST_RIP:
case VMX_VMCS64_GUEST_RSP:
case VMX_VMCS64_GUEST_CS_BASE:
case VMX_VMCS64_GUEST_DS_BASE:
case VMX_VMCS64_GUEST_ES_BASE:
case VMX_VMCS64_GUEST_FS_BASE:
case VMX_VMCS64_GUEST_GS_BASE:
case VMX_VMCS64_GUEST_SS_BASE:
VMMR0DECL(int) VMXR0Execute64BitsHandler(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, RTRCPTR pfnHandler, uint32_t cbParam,
Assert(pVCpu->hwaccm.s.vmx.VMCSCache.Write.cValidEntries <= RT_ELEMENTS(pVCpu->hwaccm.s.vmx.VMCSCache.Write.aField));
Assert(pVCpu->hwaccm.s.vmx.VMCSCache.Read.cValidEntries <= RT_ELEMENTS(pVCpu->hwaccm.s.vmx.VMCSCache.Read.aField));
#ifdef VBOX_STRICT
/* Clear VMCS. Marking it inactive, clearing implementation-specific data and writing VMCS data back to memory. */
VMXDisable();
rc = pVM->hwaccm.s.pfnHost32ToGuest64R0(pVM, RT_OFFSETOF(VM, aCpus[pVCpu->idCpu].cpum) - RT_OFFSETOF(VM, cpum));
return VERR_VMX_VMXON_FAILED;
return rc;
#endif /* HC_ARCH_BITS == 32 && defined(VBOX_ENABLE_64_BITS_GUESTS) && !defined(VBOX_WITH_HYBRID_32BIT_KERNEL) */
int rc;
switch (idxField)
case VMX_VMCS_GUEST_EFER_FULL:
case VMX_VMCS_CTRL_EPTP_FULL:
return rc;
case VMX_VMCS64_GUEST_TR_BASE:
case VMX_VMCS64_GUEST_CR0:
case VMX_VMCS64_GUEST_CR4:
case VMX_VMCS64_GUEST_CR3:
case VMX_VMCS64_GUEST_DR7:
case VMX_VMCS64_GUEST_RIP:
case VMX_VMCS64_GUEST_RSP:
case VMX_VMCS64_GUEST_CS_BASE:
case VMX_VMCS64_GUEST_DS_BASE:
case VMX_VMCS64_GUEST_ES_BASE:
case VMX_VMCS64_GUEST_FS_BASE:
case VMX_VMCS64_GUEST_GS_BASE:
case VMX_VMCS64_GUEST_SS_BASE:
return rc;
return VERR_INVALID_PARAMETER;
* Cache VMCS writes for performance reasons (Darwin) and for running 64 bits guests on 32 bits hosts.
return VINF_SUCCESS;
return VINF_SUCCESS;