HWVMXR0.cpp revision bba5b0889e561826d405efd16eaa8c38694ac291
af062818b47340eef15700d2f0211576ba3506eevboxsync * HWACCM VMX - Host Context Ring 0.
af062818b47340eef15700d2f0211576ba3506eevboxsync * Copyright (C) 2006-2007 Sun Microsystems, Inc.
af062818b47340eef15700d2f0211576ba3506eevboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
af062818b47340eef15700d2f0211576ba3506eevboxsync * available from http://www.virtualbox.org. This file is free software;
af062818b47340eef15700d2f0211576ba3506eevboxsync * you can redistribute it and/or modify it under the terms of the GNU
af062818b47340eef15700d2f0211576ba3506eevboxsync * General Public License (GPL) as published by the Free Software
af062818b47340eef15700d2f0211576ba3506eevboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
af062818b47340eef15700d2f0211576ba3506eevboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
af062818b47340eef15700d2f0211576ba3506eevboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
af062818b47340eef15700d2f0211576ba3506eevboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
af062818b47340eef15700d2f0211576ba3506eevboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync * additional information or have any questions.
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync/*******************************************************************************
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync* Header Files *
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync*******************************************************************************/
af062818b47340eef15700d2f0211576ba3506eevboxsync/* IO operation lookup arrays. */
af062818b47340eef15700d2f0211576ba3506eevboxsyncstatic uint32_t aIOOpAnd[4] = {0xff, 0xffff, 0, 0xffffffff};
af062818b47340eef15700d2f0211576ba3506eevboxsync VMXReadVMCS(VMX_VMCS_RO_VM_INSTR_ERROR, &instrError);
af062818b47340eef15700d2f0211576ba3506eevboxsync * Sets up and activates VT-x on the current CPU
af062818b47340eef15700d2f0211576ba3506eevboxsync * @returns VBox status code.
af062818b47340eef15700d2f0211576ba3506eevboxsync * @param pCpu CPU info struct
af062818b47340eef15700d2f0211576ba3506eevboxsync * @param pVM The VM to operate on.
af062818b47340eef15700d2f0211576ba3506eevboxsync * @param pvPageCpu Pointer to the global cpu page
af062818b47340eef15700d2f0211576ba3506eevboxsync * @param pPageCpuPhys Physical address of the global cpu page
af062818b47340eef15700d2f0211576ba3506eevboxsyncHWACCMR0DECL(int) VMXR0EnableCpu(PHWACCM_CPUINFO pCpu, PVM pVM, void *pvPageCpu, RTHCPHYS pPageCpuPhys)
af062818b47340eef15700d2f0211576ba3506eevboxsync AssertReturn(pPageCpuPhys, VERR_INVALID_PARAMETER);
af062818b47340eef15700d2f0211576ba3506eevboxsync /* Setup Intel VMX. */
af062818b47340eef15700d2f0211576ba3506eevboxsync SUPR0Printf("VMXR0EnableCpu cpu %d page (%x) %x\n", pCpu->idCpu, pvPageCpu, (uint32_t)pPageCpuPhys);
af062818b47340eef15700d2f0211576ba3506eevboxsync /* Set revision dword at the beginning of the VMXON structure. */
af062818b47340eef15700d2f0211576ba3506eevboxsync *(uint32_t *)pvPageCpu = MSR_IA32_VMX_BASIC_INFO_VMCS_ID(pVM->hwaccm.s.vmx.msr.vmx_basic_info);
af062818b47340eef15700d2f0211576ba3506eevboxsync /* @todo we should unmap the two pages from the virtual address space in order to prevent accidental corruption.
af062818b47340eef15700d2f0211576ba3506eevboxsync * (which can have very bad consequences!!!)
af062818b47340eef15700d2f0211576ba3506eevboxsync /* Make sure the VMX instructions don't cause #UD faults. */
af062818b47340eef15700d2f0211576ba3506eevboxsync /* Enter VMX Root Mode */
af062818b47340eef15700d2f0211576ba3506eevboxsync * Deactivates VT-x on the current CPU
af062818b47340eef15700d2f0211576ba3506eevboxsync * @returns VBox status code.
af062818b47340eef15700d2f0211576ba3506eevboxsync * @param pCpu CPU info struct
af062818b47340eef15700d2f0211576ba3506eevboxsync * @param pvPageCpu Pointer to the global cpu page
af062818b47340eef15700d2f0211576ba3506eevboxsync * @param pPageCpuPhys Physical address of the global cpu page
af062818b47340eef15700d2f0211576ba3506eevboxsyncHWACCMR0DECL(int) VMXR0DisableCpu(PHWACCM_CPUINFO pCpu, void *pvPageCpu, RTHCPHYS pPageCpuPhys)
af062818b47340eef15700d2f0211576ba3506eevboxsync AssertReturn(pPageCpuPhys, VERR_INVALID_PARAMETER);
af062818b47340eef15700d2f0211576ba3506eevboxsync /* Leave VMX Root Mode. */
af062818b47340eef15700d2f0211576ba3506eevboxsync /* And clear the X86_CR4_VMXE bit */
af062818b47340eef15700d2f0211576ba3506eevboxsync SUPR0Printf("VMXR0DisableCpu cpu %d\n", pCpu->idCpu);
af062818b47340eef15700d2f0211576ba3506eevboxsync * Does Ring-0 per VM VT-x init.
af062818b47340eef15700d2f0211576ba3506eevboxsync * @returns VBox status code.
af062818b47340eef15700d2f0211576ba3506eevboxsync * @param pVM The VM to operate on.
af062818b47340eef15700d2f0211576ba3506eevboxsync pVM->hwaccm.s.vmx.pMemObjRealModeTSS = NIL_RTR0MEMOBJ;
af062818b47340eef15700d2f0211576ba3506eevboxsync /* Allocate one page for the VM control structure (VMCS). */
af062818b47340eef15700d2f0211576ba3506eevboxsync rc = RTR0MemObjAllocCont(&pVM->hwaccm.s.vmx.pMemObjVMCS, 1 << PAGE_SHIFT, true /* executable R0 mapping */);
af062818b47340eef15700d2f0211576ba3506eevboxsync pVM->hwaccm.s.vmx.pVMCS = RTR0MemObjAddress(pVM->hwaccm.s.vmx.pMemObjVMCS);
af062818b47340eef15700d2f0211576ba3506eevboxsync pVM->hwaccm.s.vmx.pVMCSPhys = RTR0MemObjGetPagePhysAddr(pVM->hwaccm.s.vmx.pMemObjVMCS, 0);
af062818b47340eef15700d2f0211576ba3506eevboxsync /* Allocate one page for the TSS we need for real mode emulation. */
af062818b47340eef15700d2f0211576ba3506eevboxsync rc = RTR0MemObjAllocCont(&pVM->hwaccm.s.vmx.pMemObjRealModeTSS, 1 << PAGE_SHIFT, true /* executable R0 mapping */);
af062818b47340eef15700d2f0211576ba3506eevboxsync pVM->hwaccm.s.vmx.pRealModeTSS = (PVBOXTSS)RTR0MemObjAddress(pVM->hwaccm.s.vmx.pMemObjRealModeTSS);
af062818b47340eef15700d2f0211576ba3506eevboxsync pVM->hwaccm.s.vmx.pRealModeTSSPhys = RTR0MemObjGetPagePhysAddr(pVM->hwaccm.s.vmx.pMemObjRealModeTSS, 0);
af062818b47340eef15700d2f0211576ba3506eevboxsync /* The I/O bitmap starts right after the virtual interrupt redirection bitmap. Outside the TSS on purpose; the CPU will not check it
af062818b47340eef15700d2f0211576ba3506eevboxsync * for I/O operations. */
af062818b47340eef15700d2f0211576ba3506eevboxsync ASMMemZero32(pVM->hwaccm.s.vmx.pRealModeTSS, PAGE_SIZE);
af062818b47340eef15700d2f0211576ba3506eevboxsync pVM->hwaccm.s.vmx.pRealModeTSS->offIoBitmap = sizeof(*pVM->hwaccm.s.vmx.pRealModeTSS);
af062818b47340eef15700d2f0211576ba3506eevboxsync /* Bit set to 0 means redirection enabled. */
af062818b47340eef15700d2f0211576ba3506eevboxsync memset(pVM->hwaccm.s.vmx.pRealModeTSS->IntRedirBitmap, 0x0, sizeof(pVM->hwaccm.s.vmx.pRealModeTSS->IntRedirBitmap));
af062818b47340eef15700d2f0211576ba3506eevboxsync if (pVM->hwaccm.s.vmx.msr.vmx_proc_ctls.n.allowed1 & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_USE_TPR_SHADOW)
af062818b47340eef15700d2f0211576ba3506eevboxsync /* Allocate one page for the virtual APIC mmio cache. */
af062818b47340eef15700d2f0211576ba3506eevboxsync rc = RTR0MemObjAllocCont(&pVM->hwaccm.s.vmx.pMemObjAPIC, 1 << PAGE_SHIFT, true /* executable R0 mapping */);
af062818b47340eef15700d2f0211576ba3506eevboxsync pVM->hwaccm.s.vmx.pAPIC = (uint8_t *)RTR0MemObjAddress(pVM->hwaccm.s.vmx.pMemObjAPIC);
af062818b47340eef15700d2f0211576ba3506eevboxsync pVM->hwaccm.s.vmx.pAPICPhys = RTR0MemObjGetPagePhysAddr(pVM->hwaccm.s.vmx.pMemObjAPIC, 0);
af062818b47340eef15700d2f0211576ba3506eevboxsync /* Allocate the MSR bitmap if this feature is supported. */
af062818b47340eef15700d2f0211576ba3506eevboxsync if (pVM->hwaccm.s.vmx.msr.vmx_proc_ctls.n.allowed1 & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_USE_MSR_BITMAPS)
af062818b47340eef15700d2f0211576ba3506eevboxsync rc = RTR0MemObjAllocCont(&pVM->hwaccm.s.vmx.pMemObjMSRBitmap, 1 << PAGE_SHIFT, true /* executable R0 mapping */);
af062818b47340eef15700d2f0211576ba3506eevboxsync pVM->hwaccm.s.vmx.pMSRBitmap = (uint8_t *)RTR0MemObjAddress(pVM->hwaccm.s.vmx.pMemObjMSRBitmap);
af062818b47340eef15700d2f0211576ba3506eevboxsync pVM->hwaccm.s.vmx.pMSRBitmapPhys = RTR0MemObjGetPagePhysAddr(pVM->hwaccm.s.vmx.pMemObjMSRBitmap, 0);
af062818b47340eef15700d2f0211576ba3506eevboxsync memset(pVM->hwaccm.s.vmx.pMSRBitmap, 0xff, PAGE_SIZE);
af062818b47340eef15700d2f0211576ba3506eevboxsync SUPR0Printf("VMXR0InitVM %x VMCS=%x (%x) RealModeTSS=%x (%x)\n", pVM, pVM->hwaccm.s.vmx.pVMCS, (uint32_t)pVM->hwaccm.s.vmx.pVMCSPhys, pVM->hwaccm.s.vmx.pRealModeTSS, (uint32_t)pVM->hwaccm.s.vmx.pRealModeTSSPhys);
af062818b47340eef15700d2f0211576ba3506eevboxsync * Does Ring-0 per VM VT-x termination.
af062818b47340eef15700d2f0211576ba3506eevboxsync * @returns VBox status code.
af062818b47340eef15700d2f0211576ba3506eevboxsync * @param pVM The VM to operate on.
af062818b47340eef15700d2f0211576ba3506eevboxsync if (pVM->hwaccm.s.vmx.pMemObjVMCS != NIL_RTR0MEMOBJ)
af062818b47340eef15700d2f0211576ba3506eevboxsync RTR0MemObjFree(pVM->hwaccm.s.vmx.pMemObjVMCS, false);
af062818b47340eef15700d2f0211576ba3506eevboxsync if (pVM->hwaccm.s.vmx.pMemObjRealModeTSS != NIL_RTR0MEMOBJ)
af062818b47340eef15700d2f0211576ba3506eevboxsync RTR0MemObjFree(pVM->hwaccm.s.vmx.pMemObjRealModeTSS, false);
af062818b47340eef15700d2f0211576ba3506eevboxsync pVM->hwaccm.s.vmx.pMemObjRealModeTSS = NIL_RTR0MEMOBJ;
af062818b47340eef15700d2f0211576ba3506eevboxsync if (pVM->hwaccm.s.vmx.pMemObjAPIC != NIL_RTR0MEMOBJ)
af062818b47340eef15700d2f0211576ba3506eevboxsync RTR0MemObjFree(pVM->hwaccm.s.vmx.pMemObjAPIC, false);
af062818b47340eef15700d2f0211576ba3506eevboxsync if (pVM->hwaccm.s.vmx.pMemObjMSRBitmap != NIL_RTR0MEMOBJ)
af062818b47340eef15700d2f0211576ba3506eevboxsync RTR0MemObjFree(pVM->hwaccm.s.vmx.pMemObjMSRBitmap, false);
af062818b47340eef15700d2f0211576ba3506eevboxsync pVM->hwaccm.s.vmx.pMemObjMSRBitmap = NIL_RTR0MEMOBJ;
af062818b47340eef15700d2f0211576ba3506eevboxsync * Sets up VT-x for the specified VM
af062818b47340eef15700d2f0211576ba3506eevboxsync * @returns VBox status code.
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync * @param pVM The VM to operate on.
af062818b47340eef15700d2f0211576ba3506eevboxsync /* Set revision dword at the beginning of the VMCS structure. */
af062818b47340eef15700d2f0211576ba3506eevboxsync *(uint32_t *)pVM->hwaccm.s.vmx.pVMCS = MSR_IA32_VMX_BASIC_INFO_VMCS_ID(pVM->hwaccm.s.vmx.msr.vmx_basic_info);
af062818b47340eef15700d2f0211576ba3506eevboxsync /* Clear VM Control Structure. */
af062818b47340eef15700d2f0211576ba3506eevboxsync Log(("pVMCSPhys = %VHp\n", pVM->hwaccm.s.vmx.pVMCSPhys));
af062818b47340eef15700d2f0211576ba3506eevboxsync /* Activate the VM Control Structure. */
af062818b47340eef15700d2f0211576ba3506eevboxsync /* VMX_VMCS_CTRL_PIN_EXEC_CONTROLS
af062818b47340eef15700d2f0211576ba3506eevboxsync * Set required bits to one and zero according to the MSR capabilities.
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync val = pVM->hwaccm.s.vmx.msr.vmx_pin_ctls.n.disallowed0;
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync /* External and non-maskable interrupts cause VM-exits. */
af062818b47340eef15700d2f0211576ba3506eevboxsync val = val | VMX_VMCS_CTRL_PIN_EXEC_CONTROLS_EXT_INT_EXIT | VMX_VMCS_CTRL_PIN_EXEC_CONTROLS_NMI_EXIT;
af062818b47340eef15700d2f0211576ba3506eevboxsync val &= pVM->hwaccm.s.vmx.msr.vmx_pin_ctls.n.allowed1;
af062818b47340eef15700d2f0211576ba3506eevboxsync rc = VMXWriteVMCS(VMX_VMCS_CTRL_PIN_EXEC_CONTROLS, val);
af062818b47340eef15700d2f0211576ba3506eevboxsync /* VMX_VMCS_CTRL_PROC_EXEC_CONTROLS
af062818b47340eef15700d2f0211576ba3506eevboxsync * Set required bits to one and zero according to the MSR capabilities.
af062818b47340eef15700d2f0211576ba3506eevboxsync val = pVM->hwaccm.s.vmx.msr.vmx_proc_ctls.n.disallowed0;
af062818b47340eef15700d2f0211576ba3506eevboxsync /* Program which event cause VM-exits and which features we want to use. */
af062818b47340eef15700d2f0211576ba3506eevboxsync val = val | VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_HLT_EXIT
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync | VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_MWAIT_EXIT; /* don't execute mwait or else we'll idle inside the guest (host thinks the cpu load is high) */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** @note VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_MWAIT_EXIT might cause a vmlaunch failure with an invalid control fields error. (combined with some other exit reasons) */
af062818b47340eef15700d2f0211576ba3506eevboxsync if (pVM->hwaccm.s.vmx.msr.vmx_proc_ctls.n.allowed1 & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_USE_TPR_SHADOW)
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync /* CR8 reads from the APIC shadow page; writes cause an exit is they lower the TPR below the threshold */
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync val |= VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_USE_TPR_SHADOW;
af062818b47340eef15700d2f0211576ba3506eevboxsync /* Exit on CR8 reads & writes in case the TPR shadow feature isn't present. */
af062818b47340eef15700d2f0211576ba3506eevboxsync val |= VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_CR8_STORE_EXIT | VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_CR8_LOAD_EXIT;
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync if (pVM->hwaccm.s.vmx.msr.vmx_proc_ctls.n.allowed1 & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_USE_MSR_BITMAPS)
af062818b47340eef15700d2f0211576ba3506eevboxsync val |= VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_USE_MSR_BITMAPS;
af062818b47340eef15700d2f0211576ba3506eevboxsync /* We will use the secondary control if it's present. */
af062818b47340eef15700d2f0211576ba3506eevboxsync val |= VMX_VMCS_CTRL_PROC_EXEC_USE_SECONDARY_EXEC_CTRL;
af062818b47340eef15700d2f0211576ba3506eevboxsync /* Mask away the bits that the CPU doesn't support */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** @todo make sure they don't conflict with the above requirements. */
af062818b47340eef15700d2f0211576ba3506eevboxsync val &= pVM->hwaccm.s.vmx.msr.vmx_proc_ctls.n.allowed1;
af062818b47340eef15700d2f0211576ba3506eevboxsync rc = VMXWriteVMCS(VMX_VMCS_CTRL_PROC_EXEC_CONTROLS, val);
af062818b47340eef15700d2f0211576ba3506eevboxsync if (pVM->hwaccm.s.vmx.msr.vmx_proc_ctls.n.allowed1 & VMX_VMCS_CTRL_PROC_EXEC_USE_SECONDARY_EXEC_CTRL)
af062818b47340eef15700d2f0211576ba3506eevboxsync /* VMX_VMCS_CTRL_PROC_EXEC_CONTROLS2
af062818b47340eef15700d2f0211576ba3506eevboxsync * Set required bits to one and zero according to the MSR capabilities.
af062818b47340eef15700d2f0211576ba3506eevboxsync val = pVM->hwaccm.s.vmx.msr.vmx_proc_ctls2.n.disallowed0;
af062818b47340eef15700d2f0211576ba3506eevboxsync /* Mask away the bits that the CPU doesn't support */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** @todo make sure they don't conflict with the above requirements. */
af062818b47340eef15700d2f0211576ba3506eevboxsync val &= pVM->hwaccm.s.vmx.msr.vmx_proc_ctls2.n.allowed1;
af062818b47340eef15700d2f0211576ba3506eevboxsync rc = VMXWriteVMCS(VMX_VMCS_CTRL_PROC_EXEC_CONTROLS2, val);
af062818b47340eef15700d2f0211576ba3506eevboxsync /* VMX_VMCS_CTRL_CR3_TARGET_COUNT
af062818b47340eef15700d2f0211576ba3506eevboxsync * Set required bits to one and zero according to the MSR capabilities.
af062818b47340eef15700d2f0211576ba3506eevboxsync rc = VMXWriteVMCS(VMX_VMCS_CTRL_CR3_TARGET_COUNT, 0);
af062818b47340eef15700d2f0211576ba3506eevboxsync /* VMX_VMCS_CTRL_EXIT_CONTROLS
af062818b47340eef15700d2f0211576ba3506eevboxsync * Set required bits to one and zero according to the MSR capabilities.
af062818b47340eef15700d2f0211576ba3506eevboxsync val = pVM->hwaccm.s.vmx.msr.vmx_exit.n.disallowed0;
af062818b47340eef15700d2f0211576ba3506eevboxsync /* else Must be zero when AMD64 is not available. */
af062818b47340eef15700d2f0211576ba3506eevboxsync /* Don't acknowledge external interrupts on VM-exit. */
af062818b47340eef15700d2f0211576ba3506eevboxsync rc = VMXWriteVMCS(VMX_VMCS_CTRL_EXIT_CONTROLS, val);
af062818b47340eef15700d2f0211576ba3506eevboxsync /* Forward all exception except #NM & #PF to the guest.
af062818b47340eef15700d2f0211576ba3506eevboxsync * We always need to check pagefaults since our shadow page table can be out of sync.
af062818b47340eef15700d2f0211576ba3506eevboxsync * And we always lazily sync the FPU & XMM state.
af062818b47340eef15700d2f0211576ba3506eevboxsync * @todo Possible optimization:
af062818b47340eef15700d2f0211576ba3506eevboxsync * Keep the FPU and XMM state current in the EM thread. That way there's no need to
af062818b47340eef15700d2f0211576ba3506eevboxsync * lazily sync anything, but the downside is that we can't use the FPU stack or XMM
af062818b47340eef15700d2f0211576ba3506eevboxsync * registers ourselves of course.
af062818b47340eef15700d2f0211576ba3506eevboxsync * @note only possible if the current state is actually ours (X86_CR0_TS flag)
af062818b47340eef15700d2f0211576ba3506eevboxsync pVM->hwaccm.s.vmx.u32TrapMask = HWACCM_VMX_TRAP_MASK;
af062818b47340eef15700d2f0211576ba3506eevboxsync rc = VMXWriteVMCS(VMX_VMCS_CTRL_EXCEPTION_BITMAP, pVM->hwaccm.s.vmx.u32TrapMask);
af062818b47340eef15700d2f0211576ba3506eevboxsync /* Don't filter page faults; all of them should cause a switch. */
af062818b47340eef15700d2f0211576ba3506eevboxsync rc = VMXWriteVMCS(VMX_VMCS_CTRL_PAGEFAULT_ERROR_MASK, 0);
af062818b47340eef15700d2f0211576ba3506eevboxsync rc |= VMXWriteVMCS(VMX_VMCS_CTRL_PAGEFAULT_ERROR_MATCH, 0);
af062818b47340eef15700d2f0211576ba3506eevboxsync /* Init TSC offset to zero. */
af062818b47340eef15700d2f0211576ba3506eevboxsync rc = VMXWriteVMCS(VMX_VMCS_CTRL_TSC_OFFSET_FULL, 0);
af062818b47340eef15700d2f0211576ba3506eevboxsync rc |= VMXWriteVMCS(VMX_VMCS_CTRL_TSC_OFFSET_HIGH, 0);
af062818b47340eef15700d2f0211576ba3506eevboxsync rc = VMXWriteVMCS(VMX_VMCS_CTRL_IO_BITMAP_A_FULL, 0);
af062818b47340eef15700d2f0211576ba3506eevboxsync rc |= VMXWriteVMCS(VMX_VMCS_CTRL_IO_BITMAP_A_HIGH, 0);
af062818b47340eef15700d2f0211576ba3506eevboxsync rc = VMXWriteVMCS(VMX_VMCS_CTRL_IO_BITMAP_B_FULL, 0);
af062818b47340eef15700d2f0211576ba3506eevboxsync rc |= VMXWriteVMCS(VMX_VMCS_CTRL_IO_BITMAP_B_HIGH, 0);
af062818b47340eef15700d2f0211576ba3506eevboxsync /* Set the MSR bitmap address. */
af062818b47340eef15700d2f0211576ba3506eevboxsync if (pVM->hwaccm.s.vmx.msr.vmx_proc_ctls.n.allowed1 & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_USE_MSR_BITMAPS)
af062818b47340eef15700d2f0211576ba3506eevboxsync /* Optional */
af062818b47340eef15700d2f0211576ba3506eevboxsync rc = VMXWriteVMCS(VMX_VMCS_CTRL_MSR_BITMAP_FULL, pVM->hwaccm.s.vmx.pMSRBitmapPhys);
af062818b47340eef15700d2f0211576ba3506eevboxsync rc |= VMXWriteVMCS(VMX_VMCS_CTRL_MSR_BITMAP_HIGH, pVM->hwaccm.s.vmx.pMSRBitmapPhys >> 32);
af062818b47340eef15700d2f0211576ba3506eevboxsync /* Clear MSR controls. */
af062818b47340eef15700d2f0211576ba3506eevboxsync rc = VMXWriteVMCS(VMX_VMCS_CTRL_VMEXIT_MSR_STORE_FULL, 0);
af062818b47340eef15700d2f0211576ba3506eevboxsync rc |= VMXWriteVMCS(VMX_VMCS_CTRL_VMEXIT_MSR_LOAD_FULL, 0);
af062818b47340eef15700d2f0211576ba3506eevboxsync rc |= VMXWriteVMCS(VMX_VMCS_CTRL_VMENTRY_MSR_LOAD_FULL, 0);
af062818b47340eef15700d2f0211576ba3506eevboxsync rc |= VMXWriteVMCS(VMX_VMCS_CTRL_VMEXIT_MSR_STORE_HIGH, 0);
af062818b47340eef15700d2f0211576ba3506eevboxsync rc |= VMXWriteVMCS(VMX_VMCS_CTRL_VMEXIT_MSR_LOAD_HIGH, 0);
af062818b47340eef15700d2f0211576ba3506eevboxsync rc |= VMXWriteVMCS(VMX_VMCS_CTRL_VMEXIT_MSR_LOAD_HIGH, 0);
af062818b47340eef15700d2f0211576ba3506eevboxsync rc |= VMXWriteVMCS(VMX_VMCS_CTRL_EXIT_MSR_STORE_COUNT, 0);
af062818b47340eef15700d2f0211576ba3506eevboxsync rc |= VMXWriteVMCS(VMX_VMCS_CTRL_EXIT_MSR_LOAD_COUNT, 0);
af062818b47340eef15700d2f0211576ba3506eevboxsync if (pVM->hwaccm.s.vmx.msr.vmx_proc_ctls.n.allowed1 & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_USE_TPR_SHADOW)
af062818b47340eef15700d2f0211576ba3506eevboxsync /* Optional */
af062818b47340eef15700d2f0211576ba3506eevboxsync rc |= VMXWriteVMCS(VMX_VMCS_CTRL_VAPIC_PAGEADDR_FULL, pVM->hwaccm.s.vmx.pAPICPhys);
af062818b47340eef15700d2f0211576ba3506eevboxsync rc |= VMXWriteVMCS(VMX_VMCS_CTRL_VAPIC_PAGEADDR_HIGH, pVM->hwaccm.s.vmx.pAPICPhys >> 32);
af062818b47340eef15700d2f0211576ba3506eevboxsync /* Set link pointer to -1. Not currently used. */
af062818b47340eef15700d2f0211576ba3506eevboxsync rc = VMXWriteVMCS(VMX_VMCS_GUEST_LINK_PTR_FULL, 0xFFFFFFFF);
af062818b47340eef15700d2f0211576ba3506eevboxsync rc |= VMXWriteVMCS(VMX_VMCS_GUEST_LINK_PTR_HIGH, 0xFFFFFFFF);
af062818b47340eef15700d2f0211576ba3506eevboxsync rc = VMXWriteVMCS(VMX_VMCS_GUEST_LINK_PTR_FULL, 0xFFFFFFFFFFFFFFFF);
af062818b47340eef15700d2f0211576ba3506eevboxsync /* Clear VM Control Structure. Marking it inactive, clearing implementation specific data and writing back VMCS data to memory. */
af062818b47340eef15700d2f0211576ba3506eevboxsync * Injects an event (trap or external interrupt)
af062818b47340eef15700d2f0211576ba3506eevboxsync * @returns VBox status code.
af062818b47340eef15700d2f0211576ba3506eevboxsync * @param pVM The VM to operate on.
af062818b47340eef15700d2f0211576ba3506eevboxsync * @param pCtx CPU Context
af062818b47340eef15700d2f0211576ba3506eevboxsync * @param intInfo VMX interrupt info
af062818b47340eef15700d2f0211576ba3506eevboxsync * @param cbInstr Opcode length of faulting instruction
af062818b47340eef15700d2f0211576ba3506eevboxsync * @param errCode Error code (optional)
af062818b47340eef15700d2f0211576ba3506eevboxsyncstatic int VMXR0InjectEvent(PVM pVM, CPUMCTX *pCtx, uint32_t intInfo, uint32_t cbInstr, uint32_t errCode)
af062818b47340eef15700d2f0211576ba3506eevboxsync uint32_t iGate = VMX_EXIT_INTERRUPTION_INFO_VECTOR(intInfo);
af062818b47340eef15700d2f0211576ba3506eevboxsync Log2(("VMXR0InjectEvent: Injecting interrupt %d at %VGv error code=%08x CR2=%08x intInfo=%08x\n", iGate, pCtx->rip, errCode, pCtx->cr2, intInfo));
af062818b47340eef15700d2f0211576ba3506eevboxsync Log2(("VMXR0InjectEvent: Injecting interrupt %d at %VGv error code=%08x\n", iGate, pCtx->rip, errCode));
af062818b47340eef15700d2f0211576ba3506eevboxsync Assert(!VM_FF_ISSET(pVM, VM_FF_INHIBIT_INTERRUPTS));
af062818b47340eef15700d2f0211576ba3506eevboxsync /* Set event injection state. */
af062818b47340eef15700d2f0211576ba3506eevboxsync intInfo | (1 << VMX_EXIT_INTERRUPTION_INFO_VALID_SHIFT)
af062818b47340eef15700d2f0211576ba3506eevboxsync rc |= VMXWriteVMCS(VMX_VMCS_CTRL_ENTRY_INSTR_LENGTH, cbInstr);
af062818b47340eef15700d2f0211576ba3506eevboxsync rc |= VMXWriteVMCS(VMX_VMCS_CTRL_ENTRY_EXCEPTION_ERRCODE, errCode);
af062818b47340eef15700d2f0211576ba3506eevboxsync * Checks for pending guest interrupts and injects them
af062818b47340eef15700d2f0211576ba3506eevboxsync * @returns VBox status code.
af062818b47340eef15700d2f0211576ba3506eevboxsync * @param pVM The VM to operate on.
af062818b47340eef15700d2f0211576ba3506eevboxsync * @param pCtx CPU Context
af062818b47340eef15700d2f0211576ba3506eevboxsyncstatic int VMXR0CheckPendingInterrupt(PVM pVM, CPUMCTX *pCtx)
af062818b47340eef15700d2f0211576ba3506eevboxsync /* Dispatch any pending interrupts. (injected before, but a VM exit occurred prematurely) */
af062818b47340eef15700d2f0211576ba3506eevboxsync Log(("Reinjecting event %VX64 %08x at %VGv cr2=%RX64\n", pVM->hwaccm.s.Event.intInfo, pVM->hwaccm.s.Event.errCode, pCtx->rip, pCtx->cr2));
af062818b47340eef15700d2f0211576ba3506eevboxsync rc = VMXR0InjectEvent(pVM, pCtx, pVM->hwaccm.s.Event.intInfo, 0, pVM->hwaccm.s.Event.errCode);
af062818b47340eef15700d2f0211576ba3506eevboxsync /* When external interrupts are pending, we should exit the VM when IF is set. */
af062818b47340eef15700d2f0211576ba3506eevboxsync && VM_FF_ISPENDING(pVM, (VM_FF_INTERRUPT_APIC|VM_FF_INTERRUPT_PIC)))
af062818b47340eef15700d2f0211576ba3506eevboxsync pVM->hwaccm.s.vmx.proc_ctls |= VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_IRQ_WINDOW_EXIT;
af062818b47340eef15700d2f0211576ba3506eevboxsync rc = VMXWriteVMCS(VMX_VMCS_CTRL_PROC_EXEC_CONTROLS, pVM->hwaccm.s.vmx.proc_ctls);
af062818b47340eef15700d2f0211576ba3506eevboxsync Log(("Dispatch interrupt: u8Interrupt=%x (%d) rc=%Vrc cs:eip=%04X:%VGv\n", u8Interrupt, u8Interrupt, rc, pCtx->cs, pCtx->rip));
af062818b47340eef15700d2f0211576ba3506eevboxsync rc = TRPMAssertTrap(pVM, u8Interrupt, TRPM_HARDWARE_INT);
af062818b47340eef15700d2f0211576ba3506eevboxsync /* Can only happen in rare cases where a pending interrupt is cleared behind our back */
af062818b47340eef15700d2f0211576ba3506eevboxsync Assert(!VM_FF_ISPENDING(pVM, (VM_FF_INTERRUPT_APIC|VM_FF_INTERRUPT_PIC)));
af062818b47340eef15700d2f0211576ba3506eevboxsync STAM_COUNTER_INC(&pVM->hwaccm.s.StatSwitchGuestIrq);
af062818b47340eef15700d2f0211576ba3506eevboxsync /* Just continue */
af062818b47340eef15700d2f0211576ba3506eevboxsync Log(("Pending interrupt blocked at %VGv by VM_FF_INHIBIT_INTERRUPTS!!\n", pCtx->rip));
af062818b47340eef15700d2f0211576ba3506eevboxsync /* If a new event is pending, then dispatch it now. */
af062818b47340eef15700d2f0211576ba3506eevboxsync rc = TRPMQueryTrapAll(pVM, &u8Vector, &enmType, &errCode, 0);
af062818b47340eef15700d2f0211576ba3506eevboxsync Assert(pCtx->eflags.Bits.u1IF == 1 || enmType == TRPM_TRAP);
af062818b47340eef15700d2f0211576ba3506eevboxsync /* Clear the pending trap. */
af062818b47340eef15700d2f0211576ba3506eevboxsync intInfo |= (1 << VMX_EXIT_INTERRUPTION_INFO_VALID_SHIFT);
af062818b47340eef15700d2f0211576ba3506eevboxsync /* Valid error codes. */
af062818b47340eef15700d2f0211576ba3506eevboxsync intInfo |= VMX_EXIT_INTERRUPTION_INFO_ERROR_CODE_VALID;
af062818b47340eef15700d2f0211576ba3506eevboxsync if (u8Vector == X86_XCPT_BP || u8Vector == X86_XCPT_OF)
af062818b47340eef15700d2f0211576ba3506eevboxsync intInfo |= (VMX_EXIT_INTERRUPTION_INFO_TYPE_SWEXCPT << VMX_EXIT_INTERRUPTION_INFO_TYPE_SHIFT);
af062818b47340eef15700d2f0211576ba3506eevboxsync intInfo |= (VMX_EXIT_INTERRUPTION_INFO_TYPE_HWEXCPT << VMX_EXIT_INTERRUPTION_INFO_TYPE_SHIFT);
af062818b47340eef15700d2f0211576ba3506eevboxsync intInfo |= (VMX_EXIT_INTERRUPTION_INFO_TYPE_EXT << VMX_EXIT_INTERRUPTION_INFO_TYPE_SHIFT);
af062818b47340eef15700d2f0211576ba3506eevboxsync rc = VMXR0InjectEvent(pVM, pCtx, intInfo, 0, errCode);
af062818b47340eef15700d2f0211576ba3506eevboxsync } /* if (interrupts can be dispatched) */
af062818b47340eef15700d2f0211576ba3506eevboxsync * Save the host state
af062818b47340eef15700d2f0211576ba3506eevboxsync * @returns VBox status code.
af062818b47340eef15700d2f0211576ba3506eevboxsync * @param pVM The VM to operate on.
af062818b47340eef15700d2f0211576ba3506eevboxsync * Host CPU Context
af062818b47340eef15700d2f0211576ba3506eevboxsync if (pVM->hwaccm.s.fContextUseFlags & HWACCM_CHANGED_HOST_CONTEXT)
af062818b47340eef15700d2f0211576ba3506eevboxsync /* Control registers */
af062818b47340eef15700d2f0211576ba3506eevboxsync rc |= VMXWriteVMCS(VMX_VMCS_HOST_CR3, ASMGetCR3());
af062818b47340eef15700d2f0211576ba3506eevboxsync rc |= VMXWriteVMCS(VMX_VMCS_HOST_CR4, ASMGetCR4());
af062818b47340eef15700d2f0211576ba3506eevboxsync /* Selector registers. */
af062818b47340eef15700d2f0211576ba3506eevboxsync rc = VMXWriteVMCS(VMX_VMCS_HOST_FIELD_CS, ASMGetCS());
af062818b47340eef15700d2f0211576ba3506eevboxsync /** @note VMX is (again) very picky about the RPL of the selectors here; we'll restore them manually. */
af062818b47340eef15700d2f0211576ba3506eevboxsync rc |= VMXWriteVMCS(VMX_VMCS_HOST_FIELD_SS, ASMGetSS());
af062818b47340eef15700d2f0211576ba3506eevboxsync Log2(("VMX_VMCS_HOST_FIELD_CS %08x\n", ASMGetCS()));
af062818b47340eef15700d2f0211576ba3506eevboxsync Log2(("VMX_VMCS_HOST_FIELD_DS %08x\n", ASMGetDS()));
af062818b47340eef15700d2f0211576ba3506eevboxsync Log2(("VMX_VMCS_HOST_FIELD_ES %08x\n", ASMGetES()));
af062818b47340eef15700d2f0211576ba3506eevboxsync Log2(("VMX_VMCS_HOST_FIELD_FS %08x\n", ASMGetFS()));
af062818b47340eef15700d2f0211576ba3506eevboxsync Log2(("VMX_VMCS_HOST_FIELD_GS %08x\n", ASMGetGS()));
af062818b47340eef15700d2f0211576ba3506eevboxsync Log2(("VMX_VMCS_HOST_FIELD_SS %08x\n", ASMGetSS()));
af062818b47340eef15700d2f0211576ba3506eevboxsync Log2(("VMX_VMCS_HOST_FIELD_TR %08x\n", ASMGetTR()));
af062818b47340eef15700d2f0211576ba3506eevboxsync /* GDTR & IDTR */
af062818b47340eef15700d2f0211576ba3506eevboxsync rc = VMXWriteVMCS(VMX_VMCS_HOST_GDTR_BASE, gdtr.pGdt);
af062818b47340eef15700d2f0211576ba3506eevboxsync rc |= VMXWriteVMCS(VMX_VMCS_HOST_IDTR_BASE, idtr.pIdt);
af062818b47340eef15700d2f0211576ba3506eevboxsync Log2(("VMX_VMCS_HOST_GDTR_BASE %VHv\n", gdtr.pGdt));
af062818b47340eef15700d2f0211576ba3506eevboxsync Log2(("VMX_VMCS_HOST_IDTR_BASE %VHv\n", idtr.pIdt));
af062818b47340eef15700d2f0211576ba3506eevboxsync /* Save the base address of the TR selector. */
af062818b47340eef15700d2f0211576ba3506eevboxsync AssertMsgFailed(("Invalid TR selector %x. GDTR.cbGdt=%x\n", SelTR, gdtr.cbGdt));
af062818b47340eef15700d2f0211576ba3506eevboxsync pDesc = &((PX86DESCHC)gdtr.pGdt)[SelTR >> X86_SEL_SHIFT_HC];
af062818b47340eef15700d2f0211576ba3506eevboxsync /* FS and GS base. */
af062818b47340eef15700d2f0211576ba3506eevboxsync Log2(("MSR_K8_FS_BASE = %VHv\n", ASMRdMsr(MSR_K8_FS_BASE)));
af062818b47340eef15700d2f0211576ba3506eevboxsync Log2(("MSR_K8_GS_BASE = %VHv\n", ASMRdMsr(MSR_K8_GS_BASE)));
af062818b47340eef15700d2f0211576ba3506eevboxsync rc = VMXWriteVMCS64(VMX_VMCS_HOST_FS_BASE, ASMRdMsr(MSR_K8_FS_BASE));
af062818b47340eef15700d2f0211576ba3506eevboxsync rc |= VMXWriteVMCS64(VMX_VMCS_HOST_GS_BASE, ASMRdMsr(MSR_K8_GS_BASE));
af062818b47340eef15700d2f0211576ba3506eevboxsync /* Sysenter MSRs. */
af062818b47340eef15700d2f0211576ba3506eevboxsync /** @todo expensive!! */
af062818b47340eef15700d2f0211576ba3506eevboxsync rc = VMXWriteVMCS(VMX_VMCS_HOST_SYSENTER_CS, ASMRdMsr_Low(MSR_IA32_SYSENTER_CS));
af062818b47340eef15700d2f0211576ba3506eevboxsync Log2(("VMX_VMCS_HOST_SYSENTER_CS %08x\n", ASMRdMsr_Low(MSR_IA32_SYSENTER_CS)));
af062818b47340eef15700d2f0211576ba3506eevboxsync rc |= VMXWriteVMCS(VMX_VMCS_HOST_SYSENTER_ESP, ASMRdMsr_Low(MSR_IA32_SYSENTER_ESP));
af062818b47340eef15700d2f0211576ba3506eevboxsync rc |= VMXWriteVMCS(VMX_VMCS_HOST_SYSENTER_EIP, ASMRdMsr_Low(MSR_IA32_SYSENTER_EIP));
af062818b47340eef15700d2f0211576ba3506eevboxsync Log2(("VMX_VMCS_HOST_SYSENTER_EIP %VHv\n", ASMRdMsr_Low(MSR_IA32_SYSENTER_EIP)));
af062818b47340eef15700d2f0211576ba3506eevboxsync Log2(("VMX_VMCS_HOST_SYSENTER_ESP %VHv\n", ASMRdMsr_Low(MSR_IA32_SYSENTER_ESP)));
af062818b47340eef15700d2f0211576ba3506eevboxsync Log2(("VMX_VMCS_HOST_SYSENTER_EIP %VHv\n", ASMRdMsr(MSR_IA32_SYSENTER_EIP)));
af062818b47340eef15700d2f0211576ba3506eevboxsync Log2(("VMX_VMCS_HOST_SYSENTER_ESP %VHv\n", ASMRdMsr(MSR_IA32_SYSENTER_ESP)));
af062818b47340eef15700d2f0211576ba3506eevboxsync rc |= VMXWriteVMCS64(VMX_VMCS_HOST_SYSENTER_ESP, ASMRdMsr(MSR_IA32_SYSENTER_ESP));
af062818b47340eef15700d2f0211576ba3506eevboxsync rc |= VMXWriteVMCS64(VMX_VMCS_HOST_SYSENTER_EIP, ASMRdMsr(MSR_IA32_SYSENTER_EIP));
af062818b47340eef15700d2f0211576ba3506eevboxsync pVM->hwaccm.s.fContextUseFlags &= ~HWACCM_CHANGED_HOST_CONTEXT;
af062818b47340eef15700d2f0211576ba3506eevboxsync * Loads the guest state
af062818b47340eef15700d2f0211576ba3506eevboxsync * NOTE: Don't do anything here that can cause a jump back to ring 3!!!!!
af062818b47340eef15700d2f0211576ba3506eevboxsync * @returns VBox status code.
af062818b47340eef15700d2f0211576ba3506eevboxsync * @param pVM The VM to operate on.
af062818b47340eef15700d2f0211576ba3506eevboxsync * @param pCtx Guest context
af062818b47340eef15700d2f0211576ba3506eevboxsyncHWACCMR0DECL(int) VMXR0LoadGuestState(PVM pVM, CPUMCTX *pCtx)
af062818b47340eef15700d2f0211576ba3506eevboxsync /* Guest CPU context: ES, CS, SS, DS, FS, GS. */
af062818b47340eef15700d2f0211576ba3506eevboxsync if (pVM->hwaccm.s.fContextUseFlags & HWACCM_CHANGED_GUEST_SEGMENT_REGS)
/* The base values in the hidden fs & gs registers are not in sync with the msrs; they are cut to 32 bits. */
/* Real mode emulation using v86 mode with CR4.VME (interrupt redirection using the int bitmap in the TSS) */
/* Also catch floating point exceptions as we need to report them to the guest in a different way. */
val |= X86_CR0_NE; /* always turn on the native mechanism to report FPU errors (old style uses interrupts) */
/* Note: 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_MP;
#ifdef VBOX_ENABLE_64_BITS_GUESTS
AssertFailed();
AssertFailed();
/* Real mode emulation using v86 mode with CR4.VME (interrupt redirection using the int bitmap in the TSS) */
| X86_CR4_VMXE;
/* Real mode emulation using v86 mode with CR4.VME (interrupt redirection using the int bitmap in the TSS) */
#ifdef DEBUG
return rc;
bool fSyncTPR = false;
unsigned cResume = 0;
#ifdef VBOX_STRICT
#ifdef VBOX_STRICT
if ((val & pVM->hwaccm.s.vmx.msr.vmx_pin_ctls.n.disallowed0) != pVM->hwaccm.s.vmx.msr.vmx_pin_ctls.n.disallowed0)
if ((val & pVM->hwaccm.s.vmx.msr.vmx_proc_ctls.n.disallowed0) != pVM->hwaccm.s.vmx.msr.vmx_proc_ctls.n.disallowed0)
if ((val & pVM->hwaccm.s.vmx.msr.vmx_entry.n.disallowed0) != pVM->hwaccm.s.vmx.msr.vmx_entry.n.disallowed0)
if ((val & pVM->hwaccm.s.vmx.msr.vmx_exit.n.disallowed0) != pVM->hwaccm.s.vmx.msr.vmx_exit.n.disallowed0)
goto end;
Log(("VM_FF_INHIBIT_INTERRUPTS at %VGv successor %VGv\n", pCtx->rip, EMGetInhibitInterruptsPC(pVM)));
* 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 problem are not as rare as you might think.
goto end;
/* Pending request packets might contain actions that need immediate attention, such as pending hardware interrupts. */
goto end;
goto end;
/* Note the 32 bits exception for AMD (X86_CPUID_AMD_FEATURE_ECX_CR8L), but that appears missing in Intel CPUs */
bool fPending;
* -> We don't need to be explicitely notified. There are enough world switches for detecting pending interrupts.
fSyncTPR = true;
#ifdef VBOX_STRICT
goto end;
goto end;
#ifdef VBOX_STRICT
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* 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
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
switch (rc)
case VINF_SUCCESS:
AssertFailed();
goto end;
#ifdef VBOX_STRICT
int rc1;
Log(("Unable to start/resume VM for reason: %x. Instruction error %x\n", (uint32_t)exitReason, (uint32_t)instrError));
goto end;
AssertFailed();
goto end;
if (uInterruptState != 0)
/* Real mode emulation using v86 mode with CR4.VME (interrupt redirection using the int bitmap in the TSS) */
/* Misc. registers; must sync everything otherwise we can get out of sync when jumping to ring 3. */
&& VMX_EXIT_INTERRUPTION_INFO_TYPE(pVM->hwaccm.s.Event.intInfo) != VMX_EXIT_INTERRUPTION_INFO_TYPE_SW)
Log(("Pending inject %VX64 at %VGv exit=%08x intInfo=%08x exitQualification=%08x pending error=%RX64\n", pVM->hwaccm.s.Event.intInfo, pCtx->rip, exitReason, intInfo, exitQualification, val));
Log(("Pending inject %VX64 at %VGv exit=%08x intInfo=%08x exitQualification=%08x\n", pVM->hwaccm.s.Event.intInfo, pCtx->rip, exitReason, intInfo, exitQualification));
#ifdef VBOX_STRICT
if (fSyncTPR)
switch (exitReason)
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;
rc = VMXR0InjectEvent(pVM, pCtx, VMX_VMCS_CTRL_ENTRY_IRQ_INFO_FROM_EXIT_INT_INFO(intInfo), cbInstr, 0);
goto ResumeExecution;
Log2(("Shadow page fault at %VGv cr2=%VGv error code %x\n", pCtx->rip, exitQualification ,errCode));
goto ResumeExecution;
rc = VMXR0InjectEvent(pVM, pCtx, VMX_VMCS_CTRL_ENTRY_IRQ_INFO_FROM_EXIT_INT_INFO(intInfo), cbInstr, errCode);
goto ResumeExecution;
#ifdef VBOX_STRICT
rc = VMXR0InjectEvent(pVM, pCtx, VMX_VMCS_CTRL_ENTRY_IRQ_INFO_FROM_EXIT_INT_INFO(intInfo), cbInstr, errCode);
goto ResumeExecution;
rc = VMXR0InjectEvent(pVM, pCtx, VMX_VMCS_CTRL_ENTRY_IRQ_INFO_FROM_EXIT_INT_INFO(intInfo), cbInstr, errCode);
goto ResumeExecution;
#ifdef VBOX_STRICT
switch(vector)
case X86_XCPT_DE:
case X86_XCPT_UD:
case X86_XCPT_SS:
case X86_XCPT_NP:
case X86_XCPT_GP:
rc = VMXR0InjectEvent(pVM, pCtx, VMX_VMCS_CTRL_ENTRY_IRQ_INFO_FROM_EXIT_INT_INFO(intInfo), cbInstr, errCode);
goto ResumeExecution;
AssertFailed();
goto ResumeExecution;
goto ResumeExecution;
goto ResumeExecution;
goto ResumeExecution;
AssertMsg(rc == VERR_EM_INTERPRETER, ("EMU: invlpg %VGv failed with %Vrc\n", exitQualification, rc));
/* Note: the intel manual claims there's a REX version of RDMSR that's slightly different, so we play safe by completely disassembling the instruction. */
goto ResumeExecution;
AssertMsg(rc == VERR_EM_INTERPRETER, ("EMU: %s failed with %Vrc\n", (exitReason == VMX_EXIT_RDMSR) ? "rdmsr" : "wrmsr", rc));
Log2(("VMX: %VGv mov cr%d, x\n", pCtx->rip, VMX_EXIT_QUALIFICATION_CRX_REGISTER(exitQualification)));
Assert(!(pVM->hwaccm.s.vmx.msr.vmx_proc_ctls.n.allowed1 & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_USE_TPR_SHADOW));
AssertFailed();
rc = PGMSyncCR3(pVM, CPUMGetGuestCR0(pVM), CPUMGetGuestCR3(pVM), CPUMGetGuestCR4(pVM), VM_FF_ISSET(pVM, VM_FF_PGM_SYNC_CR3));
Assert(VMX_EXIT_QUALIFICATION_CRX_REGISTER(exitQualification) != 8 || !(pVM->hwaccm.s.vmx.msr.vmx_proc_ctls.n.allowed1 & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_USE_TPR_SHADOW));
goto ResumeExecution;
#ifdef VBOX_WITH_STATISTICS
if (VMX_EXIT_QUALIFICATION_DRX_DIRECTION(exitQualification) == VMX_EXIT_QUALIFICATION_DRX_DIRECTION_WRITE)
goto ResumeExecution;
/** @todo clear VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_MOV_DR_EXIT after the first time and restore drx registers afterwards */
if (VMX_EXIT_QUALIFICATION_DRX_DIRECTION(exitQualification) == VMX_EXIT_QUALIFICATION_DRX_DIRECTION_WRITE)
Log2(("VMX: mov drx%d, genreg%d\n", VMX_EXIT_QUALIFICATION_DRX_REGISTER(exitQualification), VMX_EXIT_QUALIFICATION_DRX_GENREG(exitQualification)));
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)
if (fIOWrite)
goto ResumeExecution;
#ifdef VBOX_STRICT
AssertMsg(VBOX_FAILURE(rc) || rc == VINF_EM_RAW_EMULATE_INSTR || rc == VINF_EM_RAW_GUEST_TRAP || rc == VINF_TRPM_XCPT_DISPATCHED, ("%Vrc\n", rc));
goto ResumeExecution;
switch (exitReason)
goto ResumeExecution;
/* Note: If we decide to emulate them here, then we must sync the MSRs that could have been changed (sysenter, fs/gs base)!!! */
#ifdef VBOX_STRICT
end:
CPUMSetChangedFlags(pVM, CPUM_CHANGED_SYSENTER_MSR | CPUM_CHANGED_LDTR | CPUM_CHANGED_GDTR | CPUM_CHANGED_IDTR | CPUM_CHANGED_TR | CPUM_CHANGED_HIDDEN_SEL_REGS);
/* 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 rc;
return VERR_VMX_X86_CR4_VMXE_CLEARED;
return rc;
return VINF_SUCCESS;
/* Clear VM Control Structure. Marking it inactive, clearing implementation specific data and writing back VMCS data to memory. */
return VINF_SUCCESS;