HMR0.cpp revision a9e0e218c8f68e6f822cbf2596fedc529539713a
45e9809aff7304721fddb95654901b32195c9c7avboxsync * Hardware Assisted Virtualization Manager (HM) - Host Context Ring-0.
45e9809aff7304721fddb95654901b32195c9c7avboxsync * Copyright (C) 2006-2013 Oracle Corporation
45e9809aff7304721fddb95654901b32195c9c7avboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
45e9809aff7304721fddb95654901b32195c9c7avboxsync * available from http://www.virtualbox.org. This file is free software;
45e9809aff7304721fddb95654901b32195c9c7avboxsync * you can redistribute it and/or modify it under the terms of the GNU
45e9809aff7304721fddb95654901b32195c9c7avboxsync * General Public License (GPL) as published by the Free Software
45e9809aff7304721fddb95654901b32195c9c7avboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
45e9809aff7304721fddb95654901b32195c9c7avboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
45e9809aff7304721fddb95654901b32195c9c7avboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
45e9809aff7304721fddb95654901b32195c9c7avboxsync/*******************************************************************************
45e9809aff7304721fddb95654901b32195c9c7avboxsync* Header Files *
45e9809aff7304721fddb95654901b32195c9c7avboxsync*******************************************************************************/
45e9809aff7304721fddb95654901b32195c9c7avboxsync/*******************************************************************************
45e9809aff7304721fddb95654901b32195c9c7avboxsync* Internal Functions *
45e9809aff7304721fddb95654901b32195c9c7avboxsync*******************************************************************************/
45e9809aff7304721fddb95654901b32195c9c7avboxsyncstatic DECLCALLBACK(void) hmR0EnableCpuCallback(RTCPUID idCpu, void *pvUser1, void *pvUser2);
45e9809aff7304721fddb95654901b32195c9c7avboxsyncstatic DECLCALLBACK(void) hmR0DisableCpuCallback(RTCPUID idCpu, void *pvUser1, void *pvUser2);
45e9809aff7304721fddb95654901b32195c9c7avboxsyncstatic DECLCALLBACK(void) hmR0InitIntelCpu(RTCPUID idCpu, void *pvUser1, void *pvUser2);
45e9809aff7304721fddb95654901b32195c9c7avboxsyncstatic DECLCALLBACK(void) hmR0InitAmdCpu(RTCPUID idCpu, void *pvUser1, void *pvUser2);
45e9809aff7304721fddb95654901b32195c9c7avboxsyncstatic DECLCALLBACK(void) hmR0PowerCallback(RTPOWEREVENT enmEvent, void *pvUser);
45e9809aff7304721fddb95654901b32195c9c7avboxsyncstatic DECLCALLBACK(void) hmR0MpEventCallback(RTMPEVENT enmEvent, RTCPUID idCpu, void *pvData);
45e9809aff7304721fddb95654901b32195c9c7avboxsync/*******************************************************************************
45e9809aff7304721fddb95654901b32195c9c7avboxsync* Structures and Typedefs *
45e9809aff7304721fddb95654901b32195c9c7avboxsync*******************************************************************************/
45e9809aff7304721fddb95654901b32195c9c7avboxsync * This is used to manage the status code of a RTMpOnAll in HM.
45e9809aff7304721fddb95654901b32195c9c7avboxsynctypedef struct HMR0FIRSTRC
45e9809aff7304721fddb95654901b32195c9c7avboxsync /** The status code. */
45e9809aff7304721fddb95654901b32195c9c7avboxsync /** The ID of the CPU reporting the first failure. */
45e9809aff7304721fddb95654901b32195c9c7avboxsync/** Pointer to a first return code structure. */
45e9809aff7304721fddb95654901b32195c9c7avboxsync/*******************************************************************************
45e9809aff7304721fddb95654901b32195c9c7avboxsync* Global Variables *
45e9809aff7304721fddb95654901b32195c9c7avboxsync*******************************************************************************/
45e9809aff7304721fddb95654901b32195c9c7avboxsync * Global data.
45e9809aff7304721fddb95654901b32195c9c7avboxsyncstatic struct
45e9809aff7304721fddb95654901b32195c9c7avboxsync /** Per CPU globals. */
45e9809aff7304721fddb95654901b32195c9c7avboxsync /** @name Ring-0 method table for AMD-V and VT-x specific operations.
45e9809aff7304721fddb95654901b32195c9c7avboxsync DECLR0CALLBACKMEMBER(int, pfnEnterSession,(PVM pVM, PVMCPU pVCpu, PHMGLOBALCPUINFO pCpu));
45e9809aff7304721fddb95654901b32195c9c7avboxsync DECLR0CALLBACKMEMBER(void, pfnThreadCtxCallback,(RTTHREADCTXEVENT enmEvent, PVMCPU pVCpu, bool fGlobalInit));
45e9809aff7304721fddb95654901b32195c9c7avboxsync DECLR0CALLBACKMEMBER(int, pfnSaveHostState,(PVM pVM, PVMCPU pVCpu));
45e9809aff7304721fddb95654901b32195c9c7avboxsync DECLR0CALLBACKMEMBER(int, pfnRunGuestCode,(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx));
45e9809aff7304721fddb95654901b32195c9c7avboxsync DECLR0CALLBACKMEMBER(int, pfnEnableCpu,(PHMGLOBALCPUINFO pCpu, PVM pVM, void *pvCpuPage, RTHCPHYS HCPhysCpuPage,
45e9809aff7304721fddb95654901b32195c9c7avboxsync DECLR0CALLBACKMEMBER(int, pfnDisableCpu,(PHMGLOBALCPUINFO pCpu, void *pvCpuPage, RTHCPHYS HCPhysCpuPage));
45e9809aff7304721fddb95654901b32195c9c7avboxsync /** Maximum ASID allowed. */
45e9809aff7304721fddb95654901b32195c9c7avboxsync /** VT-x data. */
45e9809aff7304721fddb95654901b32195c9c7avboxsync /** Set to by us to indicate VMX is supported by the CPU. */
45e9809aff7304721fddb95654901b32195c9c7avboxsync /** Whether we're using SUPR0EnableVTx or not. */
45e9809aff7304721fddb95654901b32195c9c7avboxsync /** Whether we're using the preemption timer or not. */
45e9809aff7304721fddb95654901b32195c9c7avboxsync /** The shift mask employed by the VMX-Preemption timer. */
45e9809aff7304721fddb95654901b32195c9c7avboxsync /** Host CR4 value (set by ring-0 VMX init) */
45e9809aff7304721fddb95654901b32195c9c7avboxsync /** @todo This isn't used for anything relevant. Remove later? */
} vmx;
bool fSupported;
} svm;
} cpuid;
bool fGlobalInit;
volatile bool fSuspended;
bool fEnabled;
} g_HvmR0;
#ifdef VBOX_STRICT
return VINF_SUCCESS;
return VINF_SUCCESS;
static DECLCALLBACK(void) hmR0DummyThreadCtxCallback(RTTHREADCTXEVENT enmEvent, PVMCPU pVCpu, bool fGlobalInit)
static DECLCALLBACK(int) hmR0DummyEnableCpu(PHMGLOBALCPUINFO pCpu, PVM pVM, void *pvCpuPage, RTHCPHYS HCPhysCpuPage,
NOREF(pCpu); NOREF(pVM); NOREF(pvCpuPage); NOREF(HCPhysCpuPage); NOREF(fEnabledBySystem); NOREF(pvArg);
return VINF_SUCCESS;
static DECLCALLBACK(int) hmR0DummyDisableCpu(PHMGLOBALCPUINFO pCpu, void *pvCpuPage, RTHCPHYS HCPhysCpuPage)
return VINF_SUCCESS;
return VINF_SUCCESS;
return VINF_SUCCESS;
return VINF_SUCCESS;
return VINF_SUCCESS;
return VINF_SUCCESS;
return VINF_SUCCESS;
static bool hmR0InitIntelIsSubjectToVmxPreemptionTimerErratum(void)
u &= ~(RT_BIT_32(14) | RT_BIT_32(15) | RT_BIT_32(28) | RT_BIT_32(29) | RT_BIT_32(30) | RT_BIT_32(31));
|| u == UINT32_C(0x00020652) /* 322814.pdf - AAT59 - C2 - Intel CoreTM i7-600, i5-500, i5-400 and i3-300 Mobile Processor Series */
|| u == UINT32_C(0x00020652) /* 322911.pdf - AAU65 - C2 - Intel CoreTM i5-600, i3-500 Desktop Processor Series and Intel Pentium Processor G6950 */
|| u == UINT32_C(0x00020655) /* 322911.pdf - AAU65 - K0 - Intel CoreTM i5-600, i3-500 Desktop Processor Series and Intel Pentium Processor G6950 */
|| u == UINT32_C(0x000106E5) /* 322166.pdf - AAN92 - B1 - Intel CoreTM i7-800 and i5-700 Desktop Processor Series */
|| u == UINT32_C(0x000106E5) /* 320767.pdf - AAP86 - B1 - Intel Core i7-900 Mobile Processor Extreme Edition Series, Intel Core i7-800 and i7-700 Mobile Processor Series */
|| u == UINT32_C(0x000106A0) /* 321333.pdf - AAM126 - C0 - Intel Xeon Processor 3500 Series Specification */
|| u == UINT32_C(0x000106A1) /* 321333.pdf - AAM126 - C1 - Intel Xeon Processor 3500 Series Specification */
|| u == UINT32_C(0x000106A4) /* 320836.pdf - AAJ124 - C0 - Intel Core i7-900 Desktop Processor Extreme Edition Series and Intel Core i7-900 Desktop Processor Series */
|| u == UINT32_C(0x000106A5) /* 321333.pdf - AAM126 - D0 - Intel Xeon Processor 3500 Series Specification */
|| u == UINT32_C(0x000106A5) /* 321324.pdf - AAK139 - D0 - Intel Xeon Processor 5500 Series Specification */
|| u == UINT32_C(0x000106A5) /* 320836.pdf - AAJ124 - D0 - Intel Core i7-900 Desktop Processor Extreme Edition Series and Intel Core i7-900 Desktop Processor Series */
AssertLogRelMsg(rc == VINF_SUCCESS || rc == VERR_VMX_IN_VMX_ROOT_MODE || rc == VERR_VMX_NO_VMX, ("%Rrc\n", rc));
if (g_HvmR0.vmx.Msrs.VmxProcCtls2.n.allowed1 & (VMX_VMCS_CTRL_PROC_EXEC2_EPT | VMX_VMCS_CTRL_PROC_EXEC2_VPID))
return rc;
VMXDisable();
#ifdef LOG_ENABLED
return VINF_SUCCESS;
int rc;
return rc;
#ifndef DEBUG_bird
return rc;
LogRel(("HM: Too many real CPUs/cores/threads - %u, max %u\n", RTMpGetArraySize(), RT_ELEMENTS(g_HvmR0.aCpuInfo)));
return VERR_TOO_MANY_CPUS;
int rc;
if (ASMHasCpuId())
return rc;
return rc;
* when brought offline/online or suspending/resuming.
return VINF_SUCCESS;
int rc;
return rc;
Assert(idCpu == (RTCPUID)RTMpCpuIdToSetIndex(idCpu)); /** @todo fix idCpu == index assumption (rainy day) */
if (fMsrLocked)
else if (!fVmxAllowed)
if (fInSmxMode)
if (fAllowed)
Assert(idCpu == (RTCPUID)RTMpCpuIdToSetIndex(idCpu)); /** @todo fix idCpu == index assumption (rainy day) */
int rc;
Assert(idCpu == (RTCPUID)RTMpCpuIdToSetIndex(idCpu)); /** @todo fix idCpu == index assumption (rainy day) */
int rc;
AssertLogRelMsgReturn(pCpu->hMemObj != NIL_RTR0MEMOBJ, ("hmR0EnableCpu failed idCpu=%u.\n", idCpu), VERR_HM_IPE_1);
return rc;
int rc;
rc = RTR0MemObjAllocCont(&g_HvmR0.aCpuInfo[i].hMemObj, PAGE_SIZE, true /* executable R0 mapping */);
AssertMsgRC(rc, ("hmR0EnableAllCpuOnce failed for cpu %d with rc=%d\n", hmR0FirstRcGetCpuId(&FirstRc), rc));
return rc;
return VERR_HM_SUSPEND_PENDING;
Assert(idCpu == (RTCPUID)RTMpCpuIdToSetIndex(idCpu)); /** @todo fix idCpu == index assumption (rainy day) */
int rc;
return rc;
switch (enmEvent)
case RTMPEVENT_OFFLINE:
#ifdef LOG_ENABLED
int rc;
#ifdef LOG_ENABLED
#ifdef LOG_ENABLED
return VERR_HM_SUSPEND_PENDING;
return rc;
return rc;
int rc;
return rc;
return rc;
#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE
AssertMsgRCReturn(rc, ("pfnEnterSession failed. rc=%Rrc pVCpu=%p HostCpuId=%u\n", rc, pVCpu, idCpu), rc);
AssertMsgRCReturn(rc, ("pfnSaveHostState failed. rc=%Rrc pVCpu=%p HostCpuId=%u\n", rc, pVCpu, idCpu), rc);
#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE
if (fStartedSet)
return rc;
return VINF_SUCCESS;
#ifdef VBOX_STRICT
#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE
#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE
return rc;
#if HC_ARCH_BITS == 32 && defined(VBOX_ENABLE_64_BITS_GUESTS) && !defined(VBOX_WITH_HYBRID_32BIT_KERNEL)
int rc;
return rc;
#endif /* HC_ARCH_BITS == 32 && defined(VBOX_WITH_64_BITS_GUESTS) && !defined(VBOX_WITH_HYBRID_32BIT_KERNEL) */
VMMR0_INT_DECL(void) HMR0SavePendingIOPortRead(PVMCPU pVCpu, RTGCPTR GCPtrRip, RTGCPTR GCPtrRipNext,
VMMR0_INT_DECL(void) HMR0SavePendingIOPortWrite(PVMCPU pVCpu, RTGCPTR GCPtrRip, RTGCPTR GCPtrRipNext,
*pfVTxDisabled = false;
return VINF_SUCCESS;
switch (enmSwitcher)
case VMMSWITCHER_32_TO_32:
case VMMSWITCHER_PAE_TO_PAE:
case VMMSWITCHER_32_TO_PAE:
case VMMSWITCHER_AMD64_TO_32:
case VMMSWITCHER_AMD64_TO_PAE:
return VINF_SUCCESS;
return VINF_SUCCESS;
return VINF_SUCCESS;
*pfVTxDisabled = true;
if (!fVTxDisabled)
#ifdef VBOX_STRICT
unsigned cch;
const char *psz;
} const s_aFlags[] =
if (pszAdd)