HMR0.cpp revision c618f4d0eeea6061ff8270e8f7023a999bd0bb91
5b281ba489ca18f0380d7efc7a5108b606cce449vboxsync * Hardware Assisted Virtualization Manager (HM) - Host Context Ring-0.
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * Copyright (C) 2006-2013 Oracle Corporation
5e91fc5e5ea9cccb7a40636f73253d489fbe340bvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
5e91fc5e5ea9cccb7a40636f73253d489fbe340bvboxsync * available from http://www.virtualbox.org. This file is free software;
5e91fc5e5ea9cccb7a40636f73253d489fbe340bvboxsync * you can redistribute it and/or modify it under the terms of the GNU
5e91fc5e5ea9cccb7a40636f73253d489fbe340bvboxsync * General Public License (GPL) as published by the Free Software
5e91fc5e5ea9cccb7a40636f73253d489fbe340bvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
5e91fc5e5ea9cccb7a40636f73253d489fbe340bvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
5e91fc5e5ea9cccb7a40636f73253d489fbe340bvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
5e91fc5e5ea9cccb7a40636f73253d489fbe340bvboxsync/*******************************************************************************
5e91fc5e5ea9cccb7a40636f73253d489fbe340bvboxsync* Header Files *
5e91fc5e5ea9cccb7a40636f73253d489fbe340bvboxsync*******************************************************************************/
bd4d5b99a9ad50d23a13cf695bbf48f8d9364618vboxsync/*******************************************************************************
bd4d5b99a9ad50d23a13cf695bbf48f8d9364618vboxsync* Internal Functions *
bd4d5b99a9ad50d23a13cf695bbf48f8d9364618vboxsync*******************************************************************************/
bd4d5b99a9ad50d23a13cf695bbf48f8d9364618vboxsyncstatic DECLCALLBACK(void) hmR0EnableCpuCallback(RTCPUID idCpu, void *pvUser1, void *pvUser2);
bd4d5b99a9ad50d23a13cf695bbf48f8d9364618vboxsyncstatic DECLCALLBACK(void) hmR0DisableCpuCallback(RTCPUID idCpu, void *pvUser1, void *pvUser2);
bd4d5b99a9ad50d23a13cf695bbf48f8d9364618vboxsyncstatic DECLCALLBACK(void) hmR0InitIntelCpu(RTCPUID idCpu, void *pvUser1, void *pvUser2);
bd4d5b99a9ad50d23a13cf695bbf48f8d9364618vboxsyncstatic DECLCALLBACK(void) hmR0InitAmdCpu(RTCPUID idCpu, void *pvUser1, void *pvUser2);
bd4d5b99a9ad50d23a13cf695bbf48f8d9364618vboxsyncstatic DECLCALLBACK(void) hmR0PowerCallback(RTPOWEREVENT enmEvent, void *pvUser);
bd4d5b99a9ad50d23a13cf695bbf48f8d9364618vboxsyncstatic DECLCALLBACK(void) hmR0MpEventCallback(RTMPEVENT enmEvent, RTCPUID idCpu, void *pvData);
bd4d5b99a9ad50d23a13cf695bbf48f8d9364618vboxsync/*******************************************************************************
bd4d5b99a9ad50d23a13cf695bbf48f8d9364618vboxsync* Structures and Typedefs *
bd4d5b99a9ad50d23a13cf695bbf48f8d9364618vboxsync*******************************************************************************/
bd4d5b99a9ad50d23a13cf695bbf48f8d9364618vboxsync * This is used to manage the status code of a RTMpOnAll in HM.
bd4d5b99a9ad50d23a13cf695bbf48f8d9364618vboxsynctypedef struct HMR0FIRSTRC
bd4d5b99a9ad50d23a13cf695bbf48f8d9364618vboxsync /** The status code. */
1ba8a0ccd2665ea7cdb82f6b0f65c5145265c786vboxsync /** The ID of the CPU reporting the first failure. */
bd4d5b99a9ad50d23a13cf695bbf48f8d9364618vboxsync/** Pointer to a first return code structure. */
1ba8a0ccd2665ea7cdb82f6b0f65c5145265c786vboxsync/*******************************************************************************
5e91fc5e5ea9cccb7a40636f73253d489fbe340bvboxsync* Global Variables *
5e91fc5e5ea9cccb7a40636f73253d489fbe340bvboxsync*******************************************************************************/
5e91fc5e5ea9cccb7a40636f73253d489fbe340bvboxsync * Global data.
5e91fc5e5ea9cccb7a40636f73253d489fbe340bvboxsyncstatic struct
1ba8a0ccd2665ea7cdb82f6b0f65c5145265c786vboxsync /** Per CPU globals. */
1ba8a0ccd2665ea7cdb82f6b0f65c5145265c786vboxsync /** @name Ring-0 method table for AMD-V and VT-x specific operations.
1ba8a0ccd2665ea7cdb82f6b0f65c5145265c786vboxsync DECLR0CALLBACKMEMBER(int, pfnEnterSession,(PVM pVM, PVMCPU pVCpu, PHMGLOBLCPUINFO pCpu));
1ba8a0ccd2665ea7cdb82f6b0f65c5145265c786vboxsync DECLR0CALLBACKMEMBER(int, pfnLeaveSession,(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx));
1ba8a0ccd2665ea7cdb82f6b0f65c5145265c786vboxsync DECLR0CALLBACKMEMBER(int, pfnSaveHostState,(PVM pVM, PVMCPU pVCpu));
1ba8a0ccd2665ea7cdb82f6b0f65c5145265c786vboxsync DECLR0CALLBACKMEMBER(int, pfnLoadGuestState,(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx));
1ba8a0ccd2665ea7cdb82f6b0f65c5145265c786vboxsync DECLR0CALLBACKMEMBER(int, pfnRunGuestCode,(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx));
1ba8a0ccd2665ea7cdb82f6b0f65c5145265c786vboxsync DECLR0CALLBACKMEMBER(int, pfnEnableCpu,(PHMGLOBLCPUINFO pCpu, PVM pVM, void *pvCpuPage, RTHCPHYS HCPhysCpuPage,
1ba8a0ccd2665ea7cdb82f6b0f65c5145265c786vboxsync DECLR0CALLBACKMEMBER(int, pfnDisableCpu,(PHMGLOBLCPUINFO pCpu, void *pvCpuPage, RTHCPHYS HCPhysCpuPage));
1ba8a0ccd2665ea7cdb82f6b0f65c5145265c786vboxsync /** Maximum ASID allowed. */
1ba8a0ccd2665ea7cdb82f6b0f65c5145265c786vboxsync /** VT-x data. */
1ba8a0ccd2665ea7cdb82f6b0f65c5145265c786vboxsync /** Set to by us to indicate VMX is supported by the CPU. */
1ba8a0ccd2665ea7cdb82f6b0f65c5145265c786vboxsync /** Whether we're using SUPR0EnableVTx or not. */
2d059d153e5d436dd4c6b8a15bb8f17ad1b3fa26vboxsync /** Whether we're using the preemption timer or not. */
2d059d153e5d436dd4c6b8a15bb8f17ad1b3fa26vboxsync /** The shift mask employed by the VMX-Preemption timer. */
2d059d153e5d436dd4c6b8a15bb8f17ad1b3fa26vboxsync /** Host CR4 value (set by ring-0 VMX init) */
2d059d153e5d436dd4c6b8a15bb8f17ad1b3fa26vboxsync /** Host EFER value (set by ring-0 VMX init) */
1ba8a0ccd2665ea7cdb82f6b0f65c5145265c786vboxsync /** VMX MSR values */
1ba8a0ccd2665ea7cdb82f6b0f65c5145265c786vboxsync /* Last instruction error */
1ba8a0ccd2665ea7cdb82f6b0f65c5145265c786vboxsync /** AMD-V information. */
1ba8a0ccd2665ea7cdb82f6b0f65c5145265c786vboxsync /* HWCR MSR (for diagnostics) */
1ba8a0ccd2665ea7cdb82f6b0f65c5145265c786vboxsync /** SVM revision. */
1ba8a0ccd2665ea7cdb82f6b0f65c5145265c786vboxsync /** SVM feature bits from cpuid 0x8000000a */
1ba8a0ccd2665ea7cdb82f6b0f65c5145265c786vboxsync /** Set by us to indicate SVM is supported by the CPU. */
1ba8a0ccd2665ea7cdb82f6b0f65c5145265c786vboxsync /** Saved error from detection */
1ba8a0ccd2665ea7cdb82f6b0f65c5145265c786vboxsync /** If set, VT-x/AMD-V is enabled globally at init time, otherwise it's
1ba8a0ccd2665ea7cdb82f6b0f65c5145265c786vboxsync * enabled and disabled each time it's used to execute guest code. */
1ba8a0ccd2665ea7cdb82f6b0f65c5145265c786vboxsync /** Indicates whether the host is suspending or not. We'll refuse a few
1ba8a0ccd2665ea7cdb82f6b0f65c5145265c786vboxsync * actions when the host is being suspended to speed up the suspending and
1ba8a0ccd2665ea7cdb82f6b0f65c5145265c786vboxsync * avoid trouble. */
1ba8a0ccd2665ea7cdb82f6b0f65c5145265c786vboxsync volatile bool fSuspended;
1ba8a0ccd2665ea7cdb82f6b0f65c5145265c786vboxsync /** Whether we've already initialized all CPUs.
1ba8a0ccd2665ea7cdb82f6b0f65c5145265c786vboxsync * @remarks We could check the EnableAllCpusOnce state, but this is
1ba8a0ccd2665ea7cdb82f6b0f65c5145265c786vboxsync * simpler and hopefully easier to understand. */
1ba8a0ccd2665ea7cdb82f6b0f65c5145265c786vboxsync /** Serialize initialization in HMR0EnableAllCpus. */
d9658602103599d13b5449fc1ea49d765a23e6f1vboxsync * Initializes a first return code structure.
1ba8a0ccd2665ea7cdb82f6b0f65c5145265c786vboxsync * @param pFirstRc The structure to init.
5e91fc5e5ea9cccb7a40636f73253d489fbe340bvboxsync * Try set the status code (success ignored).
5e91fc5e5ea9cccb7a40636f73253d489fbe340bvboxsync * @param pFirstRc The first return code structure.
5e91fc5e5ea9cccb7a40636f73253d489fbe340bvboxsync * @param rc The status code.
5e91fc5e5ea9cccb7a40636f73253d489fbe340bvboxsyncstatic void hmR0FirstRcSetStatus(PHMR0FIRSTRC pFirstRc, int rc)
5e91fc5e5ea9cccb7a40636f73253d489fbe340bvboxsync && ASMAtomicCmpXchgS32(&pFirstRc->rc, rc, VINF_SUCCESS))
5e91fc5e5ea9cccb7a40636f73253d489fbe340bvboxsync * Get the status code of a first return code structure.
1ba8a0ccd2665ea7cdb82f6b0f65c5145265c786vboxsync * @returns The status code; VINF_SUCCESS or error status, no informational or
1ba8a0ccd2665ea7cdb82f6b0f65c5145265c786vboxsync * warning errors.
5e91fc5e5ea9cccb7a40636f73253d489fbe340bvboxsync * @param pFirstRc The first return code structure.
5e91fc5e5ea9cccb7a40636f73253d489fbe340bvboxsyncstatic int hmR0FirstRcGetStatus(PHMR0FIRSTRC pFirstRc)
5e91fc5e5ea9cccb7a40636f73253d489fbe340bvboxsync * Get the CPU ID on which the failure status code was reported.
5e91fc5e5ea9cccb7a40636f73253d489fbe340bvboxsync * @returns The CPU ID, NIL_RTCPUID if no failure was reported.
5e91fc5e5ea9cccb7a40636f73253d489fbe340bvboxsync * @param pFirstRc The first return code structure.
5e91fc5e5ea9cccb7a40636f73253d489fbe340bvboxsyncstatic RTCPUID hmR0FirstRcGetCpuId(PHMR0FIRSTRC pFirstRc)
5e91fc5e5ea9cccb7a40636f73253d489fbe340bvboxsync#endif /* VBOX_STRICT */
1ba8a0ccd2665ea7cdb82f6b0f65c5145265c786vboxsync/** @name Dummy callback handlers.
5e91fc5e5ea9cccb7a40636f73253d489fbe340bvboxsyncstatic DECLCALLBACK(int) hmR0DummyEnter(PVM pVM, PVMCPU pVCpu, PHMGLOBLCPUINFO pCpu)
5e91fc5e5ea9cccb7a40636f73253d489fbe340bvboxsyncstatic DECLCALLBACK(int) hmR0DummyLeave(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx)
5e91fc5e5ea9cccb7a40636f73253d489fbe340bvboxsyncstatic DECLCALLBACK(int) hmR0DummyEnableCpu(PHMGLOBLCPUINFO pCpu, PVM pVM, void *pvCpuPage, RTHCPHYS HCPhysCpuPage,
5e91fc5e5ea9cccb7a40636f73253d489fbe340bvboxsync NOREF(pCpu); NOREF(pVM); NOREF(pvCpuPage); NOREF(HCPhysCpuPage); NOREF(fEnabledBySystem);
5e91fc5e5ea9cccb7a40636f73253d489fbe340bvboxsyncstatic DECLCALLBACK(int) hmR0DummyDisableCpu(PHMGLOBLCPUINFO pCpu, void *pvCpuPage, RTHCPHYS HCPhysCpuPage)
5e91fc5e5ea9cccb7a40636f73253d489fbe340bvboxsync NOREF(pCpu); NOREF(pvCpuPage); NOREF(HCPhysCpuPage);
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.msr.feature_ctrl & (MSR_IA32_FEATURE_CONTROL_VMXON | MSR_IA32_FEATURE_CONTROL_LOCK))
return rc;
VMXDisable();
#ifdef LOG_ENABLED
return VINF_SUCCESS;
#ifndef DEBUG_bird
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;
* 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)
int rc;
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;
int rc;
#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE
#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE
if (fStartedSet)
return rc;
int rc;
return rc;
#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)