HWACCMR0.cpp revision d86957f8d045688273190dc6d8d55ab1a5afbe81
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * HWACCM - Host Context Ring 0.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Copyright (C) 2006-2007 Sun Microsystems, Inc.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * available from http://www.virtualbox.org. This file is free software;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * you can redistribute it and/or modify it under the terms of the GNU
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * General Public License (GPL) as published by the Free Software
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * additional information or have any questions.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/*******************************************************************************
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync* Header Files *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync*******************************************************************************/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/*******************************************************************************
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync* Internal Functions *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync*******************************************************************************/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic DECLCALLBACK(void) HWACCMR0EnableCPU(RTCPUID idCpu, void *pvUser1, void *pvUser2);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic DECLCALLBACK(void) HWACCMR0DisableCPU(RTCPUID idCpu, void *pvUser1, void *pvUser2);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic DECLCALLBACK(void) HWACCMR0InitCPU(RTCPUID idCpu, void *pvUser1, void *pvUser2);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic int hwaccmr0CheckCpuRcArray(int *paRc, unsigned cErrorCodes, RTCPUID *pidCpu);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/*******************************************************************************
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync* Local Variables *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync*******************************************************************************/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic struct
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /** Ring 0 handlers for VT-x and AMD-V. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DECLR0CALLBACKMEMBER(int, pfnEnterSession,(PVM pVM, PHWACCM_CPUINFO pCpu));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DECLR0CALLBACKMEMBER(int, pfnLeaveSession,(PVM pVM));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DECLR0CALLBACKMEMBER(int, pfnSaveHostState,(PVM pVM));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DECLR0CALLBACKMEMBER(int, pfnLoadGuestState,(PVM pVM, CPUMCTX *pCtx));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DECLR0CALLBACKMEMBER(int, pfnRunGuestCode,(PVM pVM, CPUMCTX *pCtx));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DECLR0CALLBACKMEMBER(int, pfnEnableCpu, (PHWACCM_CPUINFO pCpu, PVM pVM, void *pvPageCpu, RTHCPHYS pPageCpuPhys));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DECLR0CALLBACKMEMBER(int, pfnDisableCpu, (PHWACCM_CPUINFO pCpu, void *pvPageCpu, RTHCPHYS pPageCpuPhys));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /** Set by the ring-0 driver to indicate VMX is supported by the CPU. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /** Host CR4 value (set by ring-0 VMX init) */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /** VMX MSR values */
} msr;
} vmx;
bool fSupported;
} svm;
} cpuid;
int rc;
if (ASMHasCpuId())
ASMCpuId(0x80000001, &u32Dummy, &u32Dummy, &HWACCMR0Globals.cpuid.u32AMDFeatureECX, &HWACCMR0Globals.cpuid.u32AMDFeatureEDX);
/* We need to check if VT-x has been properly initialized on all CPUs. Some BIOSes do a lousy job. */
if ( (HWACCMR0Globals.vmx.msr.feature_ctrl & (MSR_IA32_FEATURE_CONTROL_VMXON|MSR_IA32_FEATURE_CONTROL_LOCK))
void *pvScatchPage;
return rc;
*(uint32_t *)pvScatchPage = MSR_IA32_VMX_BASIC_INFO_VMCS_ID(HWACCMR0Globals.vmx.msr.vmx_basic_info);
/* KVM leaves the CPU in VMX root mode. Not only is this not allowed, it will crash the host when we enter raw mode, because
* (b) turning off paging causes a #GP (unavoidable when switching from long to 32 bits mode or 32 bits to PAE)
VMXDisable();
/* Restore CR4 again; don't leave the X86_CR4_VMXE flag set if it wasn't so before (some software could incorrectly think it's in VMX mode) */
#ifdef LOG_ENABLED
/* We need to check if AMD-V has been properly initialized on all CPUs. Some BIOSes might do a poor job. */
ASMCpuId(0x8000000A, &HWACCMR0Globals.svm.u32Rev, &HWACCMR0Globals.svm.u32MaxASID, &u32Dummy, &HWACCMR0Globals.svm.u32Features);
return VINF_SUCCESS;
for (unsigned i=0;i<cErrorCodes;i++)
if (RTMpIsCpuOnline(i))
*pidCpu = i;
return rc;
return rc;
#ifdef LOG_ENABLED
Assert(idCpu == (RTCPUID)RTMpCpuIdToSetIndex(idCpu)); /// @todo fix idCpu == index assumption (rainy day)
ASMWrMsr(MSR_IA32_FEATURE_CONTROL, HWACCMR0Globals.vmx.msr.feature_ctrl | MSR_IA32_FEATURE_CONTROL_VMXON | MSR_IA32_FEATURE_CONTROL_LOCK);
if (ASMAtomicCmpXchgU32((volatile uint32_t *)&HWACCMR0Globals.enmHwAccmState, enmNewHwAccmState, HWACCMSTATE_UNINITIALIZED))
return VINF_SUCCESS;
if (RTMpIsCpuOnline(i))
int rc = RTR0MemObjAllocCont(&HWACCMR0Globals.aCpuInfo[i].pMemObj, 1 << PAGE_SHIFT, true /* executable R0 mapping */);
return rc;
#ifdef LOG_ENABLED
SUPR0Printf("address %x phys %x\n", pvR0, (uint32_t)RTR0MemObjGetPagePhysAddr(HWACCMR0Globals.aCpuInfo[i].pMemObj, 0));
return rc;
return VINF_SUCCESS;
return VERR_ACCESS_DENIED;
void *pvPageCpu;
Assert(idCpu == (RTCPUID)RTMpCpuIdToSetIndex(idCpu)); /// @todo fix idCpu == index assumption (rainy day)
AssertFailed();
void *pvPageCpu;
Assert(idCpu == (RTCPUID)RTMpCpuIdToSetIndex(idCpu)); /// @todo fix idCpu == index assumption (rainy day)
paRc[idCpu] = HWACCMR0Globals.pfnDisableCpu(&HWACCMR0Globals.aCpuInfo[idCpu], pvPageCpu, pPageCpuPhys);
#ifdef LOG_ENABLED
#ifdef LOG_ENABLED
#ifdef LOG_ENABLED
int rc;
return rc;
return rc;
int rc;
return rc;
/** @note It's rather tricky with longjmps done by e.g. Log statements or the page fault handler. */
/* We must restore the host FPU here to make absolutely sure we don't leave the guest FPU state active
int rc;
return rc;
#ifdef VBOX_STRICT
unsigned cch;
const char *psz;
} aFlags[] =
if (pszAdd)
(RTSEL)pCtx->cs, pCtx->csHid.u64Base, pCtx->csHid.u32Limit, pCtx->csHid.Attr.u, pCtx->dr0, pCtx->dr1,
(RTSEL)pCtx->ds, pCtx->dsHid.u64Base, pCtx->dsHid.u32Limit, pCtx->dsHid.Attr.u, pCtx->dr2, pCtx->dr3,
(RTSEL)pCtx->es, pCtx->esHid.u64Base, pCtx->esHid.u32Limit, pCtx->esHid.Attr.u, pCtx->dr4, pCtx->dr5,
(RTSEL)pCtx->fs, pCtx->fsHid.u64Base, pCtx->fsHid.u32Limit, pCtx->fsHid.Attr.u, pCtx->dr6, pCtx->dr7,
(RTSEL)pCtx->gs, pCtx->gsHid.u64Base, pCtx->gsHid.u32Limit, pCtx->gsHid.Attr.u, pCtx->cr0, pCtx->cr2,
(RTSEL)pCtx->ss, pCtx->ssHid.u64Base, pCtx->ssHid.u32Limit, pCtx->ssHid.Attr.u, pCtx->cr3, pCtx->cr4,
return VINF_SUCCESS;
return VINF_SUCCESS;
HWACCMR0DECL(int) HWACCMR0DummyEnableCpu(PHWACCM_CPUINFO pCpu, PVM pVM, void *pvPageCpu, RTHCPHYS pPageCpuPhys)
return VINF_SUCCESS;
HWACCMR0DECL(int) HWACCMR0DummyDisableCpu(PHWACCM_CPUINFO pCpu, void *pvPageCpu, RTHCPHYS pPageCpuPhys)
return VINF_SUCCESS;
return VINF_SUCCESS;
return VINF_SUCCESS;
return VINF_SUCCESS;
return VINF_SUCCESS;
return VINF_SUCCESS;
return VINF_SUCCESS;