HMR0.cpp revision 476493afbafe452ee52b3b3b2bb77e07e5e56285
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync * Hardware Assisted Virtualization Manager (HM) - Host Context Ring-0.
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync * Copyright (C) 2006-2014 Oracle Corporation
e64031e20c39650a7bc902a3e1aba613b9415deevboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync * available from http://www.virtualbox.org. This file is free software;
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync * you can redistribute it and/or modify it under the terms of the GNU
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync * General Public License (GPL) as published by the Free Software
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync/*******************************************************************************
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync* Header Files *
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync*******************************************************************************/
f7c0f913c4c22ee18059ff97055442566d0f14a1vboxsync/*******************************************************************************
f7c0f913c4c22ee18059ff97055442566d0f14a1vboxsync* Internal Functions *
f7c0f913c4c22ee18059ff97055442566d0f14a1vboxsync*******************************************************************************/
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsyncstatic DECLCALLBACK(void) hmR0EnableCpuCallback(RTCPUID idCpu, void *pvUser1, void *pvUser2);
eeb2d581c99b451fb1a26a5870af65981dc9cd5dvboxsyncstatic DECLCALLBACK(void) hmR0DisableCpuCallback(RTCPUID idCpu, void *pvUser1, void *pvUser2);
f32de6c198a491c28ace2b4c53f8d04a79fd6d69vboxsyncstatic DECLCALLBACK(void) hmR0InitIntelCpu(RTCPUID idCpu, void *pvUser1, void *pvUser2);
f32de6c198a491c28ace2b4c53f8d04a79fd6d69vboxsyncstatic DECLCALLBACK(void) hmR0InitAmdCpu(RTCPUID idCpu, void *pvUser1, void *pvUser2);
0ce6ae9d6efed5d54222a13bbdabce9e688e4447vboxsyncstatic DECLCALLBACK(void) hmR0PowerCallback(RTPOWEREVENT enmEvent, void *pvUser);
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsyncstatic DECLCALLBACK(void) hmR0MpEventCallback(RTMPEVENT enmEvent, RTCPUID idCpu, void *pvData);
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync/*******************************************************************************
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync* Structures and Typedefs *
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync*******************************************************************************/
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync * This is used to manage the status code of a RTMpOnAll in HM.
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsynctypedef struct HMR0FIRSTRC
57b49c1557a310ee615bc0ee79dd2a2e92319a1bvboxsync /** The status code. */
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync /** The ID of the CPU reporting the first failure. */
f2490dbf97c8247439446844458461b00e50beb0vboxsync/** Pointer to a first return code structure. */
f2490dbf97c8247439446844458461b00e50beb0vboxsync/*******************************************************************************
f2490dbf97c8247439446844458461b00e50beb0vboxsync* Global Variables *
f2490dbf97c8247439446844458461b00e50beb0vboxsync*******************************************************************************/
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync * Global data.
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsyncstatic struct
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync /** Per CPU globals. */
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync /** @name Ring-0 method table for AMD-V and VT-x specific operations.
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync DECLR0CALLBACKMEMBER(int, pfnEnterSession, (PVM pVM, PVMCPU pVCpu, PHMGLOBALCPUINFO pCpu));
ee5869bb73f07de9c139dc6a608836a7b5767933vboxsync DECLR0CALLBACKMEMBER(void, pfnThreadCtxCallback, (RTTHREADCTXEVENT enmEvent, PVMCPU pVCpu, bool fGlobalInit));
f6dde23cd488aee26203b38ec67220270f5c4273vboxsync DECLR0CALLBACKMEMBER(int, pfnSaveHostState, (PVM pVM, PVMCPU pVCpu));
f6dde23cd488aee26203b38ec67220270f5c4273vboxsync DECLR0CALLBACKMEMBER(int, pfnRunGuestCode, (PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx));
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync DECLR0CALLBACKMEMBER(int, pfnEnableCpu, (PHMGLOBALCPUINFO pCpu, PVM pVM, void *pvCpuPage, RTHCPHYS HCPhysCpuPage,
dc311b529996345ea65d51c87b60b6849642d894vboxsync DECLR0CALLBACKMEMBER(int, pfnDisableCpu, (PHMGLOBALCPUINFO pCpu, void *pvCpuPage, RTHCPHYS HCPhysCpuPage));
0a3eb63419e41ef10cd135aeb66dcd6bd6f87cdcvboxsync /** Maximum ASID allowed. */
c4d6c81bd0de216d0f42db2e477b1d788fbaefb4vboxsync /** VT-x data. */
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync /** Set to by us to indicate VMX is supported by the CPU. */
482a222498aae619afda0255a7edf4ebda97268cvboxsync /** Whether we're using SUPR0EnableVTx or not. */
482a222498aae619afda0255a7edf4ebda97268cvboxsync /** Whether we're using the preemption timer or not. */
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync /** The shift mask employed by the VMX-Preemption timer. */
25c5ce7baf4b227ea80250c46d427d0e9fdab4c1vboxsync /** Host CR4 value (set by ring-0 VMX init) */
d91dc86210d602f51a4701762488a5e696c80a45vboxsync /** @todo This isn't used for anything relevant. Remove later? */
59d96bafa78f7257869e30b88f2f98142ef5928evboxsync /** Host EFER value (set by ring-0 VMX init) */
35d8d2372afb180daa0ba01af33a1922511d6b07vboxsync /** VMX MSR values */
35d8d2372afb180daa0ba01af33a1922511d6b07vboxsync /* Last instruction error */
b8ae33177906f4130b85b7c861cae0e78ed4859bvboxsync /** AMD-V information. */
b8ae33177906f4130b85b7c861cae0e78ed4859bvboxsync /* HWCR MSR (for diagnostics) */
b8ae33177906f4130b85b7c861cae0e78ed4859bvboxsync /** SVM revision. */
6b9316bfe743cc7d2ee00d925f4ab455bc224e86vboxsync /** SVM feature bits from cpuid 0x8000000a */
d5bf937d132098565e18a0d1fc408fb777c5e5b6vboxsync /** Set by us to indicate SVM is supported by the CPU. */
15760030457c4d8548d42a9d543646b27eae7040vboxsync /** Saved error from detection */
35d8d2372afb180daa0ba01af33a1922511d6b07vboxsync /** If set, VT-x/AMD-V is enabled globally at init time, otherwise it's
35d8d2372afb180daa0ba01af33a1922511d6b07vboxsync * enabled and disabled each time it's used to execute guest code. */
35d8d2372afb180daa0ba01af33a1922511d6b07vboxsync /** Indicates whether the host is suspending or not. We'll refuse a few
21293ca6a2967f796ed30a6c8492911619476a48vboxsync * actions when the host is being suspended to speed up the suspending and
21293ca6a2967f796ed30a6c8492911619476a48vboxsync * avoid trouble. */
21293ca6a2967f796ed30a6c8492911619476a48vboxsync volatile bool fSuspended;
2c1d8cd8efdd4c486ff681135035d24111b03af8vboxsync /** Whether we've already initialized all CPUs.
35d8d2372afb180daa0ba01af33a1922511d6b07vboxsync * @remarks We could check the EnableAllCpusOnce state, but this is
35d8d2372afb180daa0ba01af33a1922511d6b07vboxsync * simpler and hopefully easier to understand. */
6b9316bfe743cc7d2ee00d925f4ab455bc224e86vboxsync /** Serialize initialization in HMR0EnableAllCpus. */
f2490dbf97c8247439446844458461b00e50beb0vboxsync * Initializes a first return code structure.
f2490dbf97c8247439446844458461b00e50beb0vboxsync * @param pFirstRc The structure to init.
4831e82ecaa3c813398d2f343e9d38ee34a3acf4vboxsync * Try set the status code (success ignored).
40becad9511726726c5959a8ad8b62fb3e1c020cvboxsync * @param pFirstRc The first return code structure.
40becad9511726726c5959a8ad8b62fb3e1c020cvboxsync * @param rc The status code.
50453af238fcec34bf98f91cc4c32bf57f738bd3vboxsyncstatic void hmR0FirstRcSetStatus(PHMR0FIRSTRC pFirstRc, int rc)
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync && ASMAtomicCmpXchgS32(&pFirstRc->rc, rc, VINF_SUCCESS))
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync * Get the status code of a first return code structure.
c4d6c81bd0de216d0f42db2e477b1d788fbaefb4vboxsync * @returns The status code; VINF_SUCCESS or error status, no informational or
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync * warning errors.
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync * @param pFirstRc The first return code structure.
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsyncstatic int hmR0FirstRcGetStatus(PHMR0FIRSTRC pFirstRc)
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync * Get the CPU ID on which the failure status code was reported.
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync * @returns The CPU ID, NIL_RTCPUID if no failure was reported.
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync * @param pFirstRc The first return code structure.
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsyncstatic RTCPUID hmR0FirstRcGetCpuId(PHMR0FIRSTRC pFirstRc)
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync#endif /* VBOX_STRICT */
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync/** @name Dummy callback handlers.
23ab2e25f17cdd6af9c0448ee70905a8c1c82896vboxsyncstatic DECLCALLBACK(int) hmR0DummyEnter(PVM pVM, PVMCPU pVCpu, PHMGLOBALCPUINFO pCpu)
40becad9511726726c5959a8ad8b62fb3e1c020cvboxsyncstatic DECLCALLBACK(void) hmR0DummyThreadCtxCallback(RTTHREADCTXEVENT enmEvent, PVMCPU pVCpu, bool fGlobalInit)
d07e901177d22a8f66c66f155c423a524ac07776vboxsyncstatic DECLCALLBACK(int) hmR0DummyEnableCpu(PHMGLOBALCPUINFO pCpu, PVM pVM, void *pvCpuPage, RTHCPHYS HCPhysCpuPage,
d07e901177d22a8f66c66f155c423a524ac07776vboxsync NOREF(pCpu); NOREF(pVM); NOREF(pvCpuPage); NOREF(HCPhysCpuPage); NOREF(fEnabledBySystem); NOREF(pvArg);
f48fe310f85f13db0140bef980de1f56c2007957vboxsyncstatic DECLCALLBACK(int) hmR0DummyDisableCpu(PHMGLOBALCPUINFO pCpu, void *pvCpuPage, RTHCPHYS HCPhysCpuPage)
1b186b95b77faa977d3651bbfc13afb3f13e0225vboxsync NOREF(pCpu); NOREF(pvCpuPage); NOREF(HCPhysCpuPage);
f7c0f913c4c22ee18059ff97055442566d0f14a1vboxsyncstatic DECLCALLBACK(int) hmR0DummyRunGuestCode(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx)
3221ae1f7bf53d9cccdd578099f55f782dba1447vboxsyncstatic DECLCALLBACK(int) hmR0DummySaveHostState(PVM pVM, PVMCPU pVCpu)
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) */
Assert(idCpu == (RTCPUID)RTMpCpuIdToSetIndex(idCpu)); /** @todo fix idCpu == index assumption (rainy day) */
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;
#ifdef VBOX_STRICT
int rc;
rc = RTR0MemObjAllocCont(&g_HvmR0.aCpuInfo[i].hMemObj, PAGE_SIZE, false /* 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;
static DECLCALLBACK(void) hmR0DisableCpuOnSpecificCallback(RTCPUID idCpu, void *pvUser1, void *pvUser2)
switch (enmEvent)
case RTMPEVENT_OFFLINE:
#ifdef LOG_ENABLED
int rc;
#ifdef LOG_ENABLED
#ifdef LOG_ENABLED
return VERR_HM_SUSPEND_PENDING;
pVM->hm.s.vmx.fUsePreemptTimer &= g_HvmR0.vmx.fUsePreemptTimer; /* Can be overridden by CFGM. See HMR3Init(). */
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)