VirtualBox

Changeset 87535 in vbox for trunk/src/VBox/VMM/VMMR0


Ignore:
Timestamp:
Feb 2, 2021 2:02:11 PM (4 years ago)
Author:
vboxsync
Message:

VMM/HM: Moved the ring-0 HM vtable out of the g_HmR0 structure and copy from pre-initialized const copies. Some error path cleanups (RTMpNotificationRegister and RTPowerNotificationRegister failures must not be ignored, however unlikely). bugref:9217

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMR0/HMR0.cpp

    r87532 r87535  
    5151static DECLCALLBACK(void) hmR0EnableCpuCallback(RTCPUID idCpu, void *pvUser1, void *pvUser2);
    5252static DECLCALLBACK(void) hmR0DisableCpuCallback(RTCPUID idCpu, void *pvUser1, void *pvUser2);
    53 static DECLCALLBACK(void) hmR0InitIntelCpu(RTCPUID idCpu, void *pvUser1, void *pvUser2);
    54 static DECLCALLBACK(void) hmR0InitAmdCpu(RTCPUID idCpu, void *pvUser1, void *pvUser2);
    5553static DECLCALLBACK(void) hmR0PowerCallback(RTPOWEREVENT enmEvent, void *pvUser);
    5654static DECLCALLBACK(void) hmR0MpEventCallback(RTMPEVENT enmEvent, RTCPUID idCpu, void *pvData);
     
    7371typedef HMR0FIRSTRC *PHMR0FIRSTRC;
    7472
    75 
    76 /*********************************************************************************************************************************
    77 *   Global Variables                                                                                                             *
    78 *********************************************************************************************************************************/
    79 /**
    80  * Global data.
    81  */
    82 static struct
    83 {
    84     /** Per CPU globals. */
    85     HMPHYSCPU                       aCpuInfo[RTCPUSET_MAX_CPUS];
    86 
    87     /** @name Ring-0 method table for AMD-V and VT-x specific operations.
    88      * @{ */
     73/**
     74 * Ring-0 method table for AMD-V and VT-x specific operations.
     75 */
     76typedef struct HMR0VTABLE
     77{
    8978    DECLR0CALLBACKMEMBER(int,          pfnEnterSession, (PVMCPUCC pVCpu));
    9079    DECLR0CALLBACKMEMBER(void,         pfnThreadCtxCallback, (RTTHREADCTXEVENT enmEvent, PVMCPUCC pVCpu, bool fGlobalInit));
     
    9887    DECLR0CALLBACKMEMBER(int,          pfnTermVM, (PVMCC pVM));
    9988    DECLR0CALLBACKMEMBER(int,          pfnSetupVM, (PVMCC pVM));
    100     /** @} */
     89} HMR0VTABLE;
     90
     91
     92/*********************************************************************************************************************************
     93*   Global Variables                                                                                                             *
     94*********************************************************************************************************************************/
     95/** The active ring-0 HM operations (copied from one of the table at init). */
     96static HMR0VTABLE   g_HmR0Ops;
     97
     98/** Set if VT-x (VMX) is supported by the CPU. */
     99bool                g_fHmVmxSupported = false;
     100/** Set if AMD-V is supported by the CPU. */
     101bool                g_fHmSvmSupported = false;
     102/** Maximum allowed ASID/VPID (inclusive).
     103 * @todo r=bird: This is exclusive for VT-x according to source code comment.
     104 *       Couldn't immediately find any docs on AMD-V, but suspect it is
     105 *       exclusive there as well given how hmR0SvmFlushTaggedTlb() use it. */
     106uint32_t            g_uHmMaxAsid;
     107
     108
     109/**
     110 * Global data.
     111 */
     112static struct
     113{
     114    /** Per CPU globals. */
     115    HMPHYSCPU                       aCpuInfo[RTCPUSET_MAX_CPUS];
    101116
    102117    /** Hardware-virtualization data. */
     
    160175
    161176
    162 /** Set if VT-x (VMX) is supported by the CPU. */
    163 bool        g_fHmVmxSupported = false;
    164 /** Set if AMD-V is supported by the CPU. */
    165 bool        g_fHmSvmSupported = false;
    166 /** Maximum allowed ASID/VPID (inclusive).
    167  * @todo r=bird: This is exclusive for VT-x according to source code comment.
    168  *       Couldn't immediately find any docs on AMD-V, but suspect it is
    169  *       exclusive there as well given how hmR0SvmFlushTaggedTlb() use it. */
    170 uint32_t    g_uHmMaxAsid;
     177/** HM ring-0 operations for VT-x. */
     178static HMR0VTABLE const g_HmR0OpsVmx =
     179{
     180    /* .pfnEnterSession = */        VMXR0Enter,
     181    /* .pfnThreadCtxCallback = */   VMXR0ThreadCtxCallback,
     182    /* .pfnCallRing3Callback = */   VMXR0CallRing3Callback,
     183    /* .pfnExportHostState = */     VMXR0ExportHostState,
     184    /* .pfnRunGuestCode = */        VMXR0RunGuestCode,
     185    /* .pfnEnableCpu = */           VMXR0EnableCpu,
     186    /* .pfnDisableCpu = */          VMXR0DisableCpu,
     187    /* .pfnInitVM = */              VMXR0InitVM,
     188    /* .pfnTermVM = */              VMXR0TermVM,
     189    /* .pfnSetupVM = */             VMXR0SetupVM,
     190};
     191
     192/** HM ring-0 operations for AMD-V. */
     193static HMR0VTABLE const g_HmR0OpsSvm =
     194{
     195    /* .pfnEnterSession = */        SVMR0Enter,
     196    /* .pfnThreadCtxCallback = */   SVMR0ThreadCtxCallback,
     197    /* .pfnCallRing3Callback = */   SVMR0CallRing3Callback,
     198    /* .pfnExportHostState = */     SVMR0ExportHostState,
     199    /* .pfnRunGuestCode = */        SVMR0RunGuestCode,
     200    /* .pfnEnableCpu = */           SVMR0EnableCpu,
     201    /* .pfnDisableCpu = */          SVMR0DisableCpu,
     202    /* .pfnInitVM = */              SVMR0InitVM,
     203    /* .pfnTermVM = */              SVMR0TermVM,
     204    /* .pfnSetupVM = */             SVMR0SetupVM,
     205};
     206
     207
     208/** @name Dummy callback handlers for when neither VT-x nor AMD-V is supported.
     209 * @{ */
     210
     211static DECLCALLBACK(int) hmR0DummyEnter(PVMCPUCC pVCpu)
     212{
     213    RT_NOREF(pVCpu);
     214    return VINF_SUCCESS;
     215}
     216
     217static DECLCALLBACK(void) hmR0DummyThreadCtxCallback(RTTHREADCTXEVENT enmEvent, PVMCPUCC pVCpu, bool fGlobalInit)
     218{
     219    RT_NOREF(enmEvent, pVCpu, fGlobalInit);
     220}
     221
     222static DECLCALLBACK(int) hmR0DummyEnableCpu(PHMPHYSCPU pHostCpu, PVMCC pVM, void *pvCpuPage, RTHCPHYS HCPhysCpuPage,
     223                                            bool fEnabledBySystem, PCSUPHWVIRTMSRS pHwvirtMsrs)
     224{
     225    RT_NOREF(pHostCpu, pVM, pvCpuPage, HCPhysCpuPage, fEnabledBySystem, pHwvirtMsrs);
     226    return VINF_SUCCESS;
     227}
     228
     229static DECLCALLBACK(int) hmR0DummyDisableCpu(PHMPHYSCPU pHostCpu, void *pvCpuPage, RTHCPHYS HCPhysCpuPage)
     230{
     231    RT_NOREF(pHostCpu, pvCpuPage, HCPhysCpuPage);
     232    return VINF_SUCCESS;
     233}
     234
     235static DECLCALLBACK(int) hmR0DummyInitVM(PVMCC pVM)
     236{
     237    RT_NOREF(pVM);
     238    return VINF_SUCCESS;
     239}
     240
     241static DECLCALLBACK(int) hmR0DummyTermVM(PVMCC pVM)
     242{
     243    RT_NOREF(pVM);
     244    return VINF_SUCCESS;
     245}
     246
     247static DECLCALLBACK(int) hmR0DummySetupVM(PVMCC pVM)
     248{
     249    RT_NOREF(pVM);
     250    return VINF_SUCCESS;
     251}
     252
     253static DECLCALLBACK(int) hmR0DummyCallRing3Callback(PVMCPUCC pVCpu, VMMCALLRING3 enmOperation)
     254{
     255    RT_NOREF(pVCpu, enmOperation);
     256    return VINF_SUCCESS;
     257}
     258
     259static DECLCALLBACK(VBOXSTRICTRC) hmR0DummyRunGuestCode(PVMCPUCC pVCpu)
     260{
     261    RT_NOREF(pVCpu);
     262    return VERR_NOT_SUPPORTED;
     263}
     264
     265static DECLCALLBACK(int) hmR0DummyExportHostState(PVMCPUCC pVCpu)
     266{
     267    RT_NOREF(pVCpu);
     268    return VINF_SUCCESS;
     269}
     270
     271/** Dummy ops.    */
     272static HMR0VTABLE const g_HmR0OpsDummy =
     273{
     274    /* .pfnEnterSession = */        hmR0DummyEnter,
     275    /* .pfnThreadCtxCallback = */   hmR0DummyThreadCtxCallback,
     276    /* .pfnCallRing3Callback = */   hmR0DummyCallRing3Callback,
     277    /* .pfnExportHostState = */     hmR0DummyExportHostState,
     278    /* .pfnRunGuestCode = */        hmR0DummyRunGuestCode,
     279    /* .pfnEnableCpu = */           hmR0DummyEnableCpu,
     280    /* .pfnDisableCpu = */          hmR0DummyDisableCpu,
     281    /* .pfnInitVM = */              hmR0DummyInitVM,
     282    /* .pfnTermVM = */              hmR0DummyTermVM,
     283    /* .pfnSetupVM = */             hmR0DummySetupVM,
     284};
     285
     286/** @} */
    171287
    172288
     
    226342
    227343
    228 /** @name Dummy callback handlers.
    229  * @{ */
    230 
    231 static DECLCALLBACK(int) hmR0DummyEnter(PVMCPUCC pVCpu)
    232 {
    233     RT_NOREF1(pVCpu);
    234     return VINF_SUCCESS;
    235 }
    236 
    237 static DECLCALLBACK(void) hmR0DummyThreadCtxCallback(RTTHREADCTXEVENT enmEvent, PVMCPUCC pVCpu, bool fGlobalInit)
    238 {
    239     RT_NOREF3(enmEvent, pVCpu, fGlobalInit);
    240 }
    241 
    242 static DECLCALLBACK(int) hmR0DummyEnableCpu(PHMPHYSCPU pHostCpu, PVMCC pVM, void *pvCpuPage, RTHCPHYS HCPhysCpuPage,
    243                                             bool fEnabledBySystem, PCSUPHWVIRTMSRS pHwvirtMsrs)
    244 {
    245     RT_NOREF6(pHostCpu, pVM, pvCpuPage, HCPhysCpuPage, fEnabledBySystem, pHwvirtMsrs);
    246     return VINF_SUCCESS;
    247 }
    248 
    249 static DECLCALLBACK(int) hmR0DummyDisableCpu(PHMPHYSCPU pHostCpu, void *pvCpuPage, RTHCPHYS HCPhysCpuPage)
    250 {
    251     RT_NOREF3(pHostCpu, pvCpuPage, HCPhysCpuPage);
    252     return VINF_SUCCESS;
    253 }
    254 
    255 static DECLCALLBACK(int) hmR0DummyInitVM(PVMCC pVM)
    256 {
    257     RT_NOREF1(pVM);
    258     return VINF_SUCCESS;
    259 }
    260 
    261 static DECLCALLBACK(int) hmR0DummyTermVM(PVMCC pVM)
    262 {
    263     RT_NOREF1(pVM);
    264     return VINF_SUCCESS;
    265 }
    266 
    267 static DECLCALLBACK(int) hmR0DummySetupVM(PVMCC pVM)
    268 {
    269     RT_NOREF1(pVM);
    270     return VINF_SUCCESS;
    271 }
    272 
    273 static DECLCALLBACK(int) hmR0DummyCallRing3Callback(PVMCPUCC pVCpu, VMMCALLRING3 enmOperation)
    274 {
    275     RT_NOREF2(pVCpu, enmOperation);
    276     return VINF_SUCCESS;
    277 }
    278 
    279 static DECLCALLBACK(VBOXSTRICTRC) hmR0DummyRunGuestCode(PVMCPUCC pVCpu)
    280 {
    281     RT_NOREF(pVCpu);
    282     return VINF_SUCCESS;
    283 }
    284 
    285 static DECLCALLBACK(int) hmR0DummyExportHostState(PVMCPUCC pVCpu)
    286 {
    287     RT_NOREF1(pVCpu);
    288     return VINF_SUCCESS;
    289 }
    290 
    291 /** @} */
     344
     345/**
     346 * Worker function used by hmR0PowerCallback() and HMR0Init() to initalize VT-x
     347 * on a CPU.
     348 *
     349 * @param   idCpu       The identifier for the CPU the function is called on.
     350 * @param   pvUser1     Pointer to the first RC structure.
     351 * @param   pvUser2     Ignored.
     352 */
     353static DECLCALLBACK(void) hmR0InitIntelCpu(RTCPUID idCpu, void *pvUser1, void *pvUser2)
     354{
     355    PHMR0FIRSTRC pFirstRc = (PHMR0FIRSTRC)pvUser1;
     356    Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
     357    Assert(idCpu == (RTCPUID)RTMpCpuIdToSetIndex(idCpu)); /** @todo fix idCpu == index assumption (rainy day) */
     358    NOREF(idCpu); NOREF(pvUser2);
     359
     360    int rc = SUPR0GetVmxUsability(NULL /* pfIsSmxModeAmbiguous */);
     361    hmR0FirstRcSetStatus(pFirstRc, rc);
     362}
    292363
    293364
     
    306377     * (This is only supported by some Mac OS X kernels atm.)
    307378     */
    308     int rc = g_HmR0.rcInit = SUPR0EnableVTx(true /* fEnable */);
     379    int rc;
     380    g_HmR0.rcInit = rc = SUPR0EnableVTx(true /* fEnable */);
    309381    g_HmR0.hwvirt.u.vmx.fUsingSUPR0EnableVTx = rc != VERR_NOT_SUPPORTED;
    310382    if (g_HmR0.hwvirt.u.vmx.fUsingSUPR0EnableVTx)
     
    316388            rc = SUPR0EnableVTx(false /* fEnable */);
    317389            AssertLogRelRC(rc);
     390            rc = VINF_SUCCESS;
    318391        }
    319392    }
     
    322395        HMR0FIRSTRC FirstRc;
    323396        hmR0FirstRcInit(&FirstRc);
    324         g_HmR0.rcInit = RTMpOnAll(hmR0InitIntelCpu, &FirstRc, NULL);
    325         if (RT_SUCCESS(g_HmR0.rcInit))
    326             g_HmR0.rcInit = hmR0FirstRcGetStatus(&FirstRc);
    327     }
    328 
    329     if (RT_SUCCESS(g_HmR0.rcInit))
     397        g_HmR0.rcInit = rc = RTMpOnAll(hmR0InitIntelCpu, &FirstRc, NULL);
     398        if (RT_SUCCESS(rc))
     399            g_HmR0.rcInit = rc = hmR0FirstRcGetStatus(&FirstRc);
     400    }
     401
     402    if (RT_SUCCESS(rc))
    330403    {
    331404        /* Read CR4 and EFER for logging/diagnostic purposes. */
     
    416489        {
    417490            rc = VMXR0GlobalInit();
    418             if (RT_FAILURE(rc))
     491            if (RT_SUCCESS(rc))
     492            {
     493                /*
     494                 * Install the VT-x methods.
     495                 */
     496                g_HmR0Ops = g_HmR0OpsVmx;
     497
     498                /*
     499                 * Check for the VMX-Preemption Timer and adjust for the "VMX-Preemption
     500                 * Timer Does Not Count Down at the Rate Specified" CPU erratum.
     501                 */
     502                VMXCTLSMSR PinCtls;
     503                PinCtls.u = g_HmR0.hwvirt.Msrs.u.vmx.u64PinCtls;
     504                if (PinCtls.n.allowed1 & VMX_PIN_CTLS_PREEMPT_TIMER)
     505                {
     506                    uint64_t const uVmxMiscMsr = g_HmR0.hwvirt.Msrs.u.vmx.u64Misc;
     507                    g_HmR0.hwvirt.u.vmx.fUsePreemptTimer   = true;
     508                    g_HmR0.hwvirt.u.vmx.cPreemptTimerShift = RT_BF_GET(uVmxMiscMsr, VMX_BF_MISC_PREEMPT_TIMER_TSC);
     509                    if (HMIsSubjectToVmxPreemptTimerErratum())
     510                        g_HmR0.hwvirt.u.vmx.cPreemptTimerShift = 0; /* This is about right most of the time here. */
     511                }
     512            }
     513            else
     514            {
    419515                g_HmR0.rcInit = rc;
    420 
    421             /*
    422              * Install the VT-x methods.
    423              */
    424             g_HmR0.pfnEnterSession      = VMXR0Enter;
    425             g_HmR0.pfnThreadCtxCallback = VMXR0ThreadCtxCallback;
    426             g_HmR0.pfnCallRing3Callback = VMXR0CallRing3Callback;
    427             g_HmR0.pfnExportHostState   = VMXR0ExportHostState;
    428             g_HmR0.pfnRunGuestCode      = VMXR0RunGuestCode;
    429             g_HmR0.pfnEnableCpu         = VMXR0EnableCpu;
    430             g_HmR0.pfnDisableCpu        = VMXR0DisableCpu;
    431             g_HmR0.pfnInitVM            = VMXR0InitVM;
    432             g_HmR0.pfnTermVM            = VMXR0TermVM;
    433             g_HmR0.pfnSetupVM           = VMXR0SetupVM;
    434 
    435             /*
    436              * Check for the VMX-Preemption Timer and adjust for the "VMX-Preemption
    437              * Timer Does Not Count Down at the Rate Specified" CPU erratum.
    438              */
    439             VMXCTLSMSR PinCtls;
    440             PinCtls.u = g_HmR0.hwvirt.Msrs.u.vmx.u64PinCtls;
    441             if (PinCtls.n.allowed1 & VMX_PIN_CTLS_PREEMPT_TIMER)
    442             {
    443                 uint64_t const uVmxMiscMsr = g_HmR0.hwvirt.Msrs.u.vmx.u64Misc;
    444                 g_HmR0.hwvirt.u.vmx.fUsePreemptTimer   = true;
    445                 g_HmR0.hwvirt.u.vmx.cPreemptTimerShift = RT_BF_GET(uVmxMiscMsr, VMX_BF_MISC_PREEMPT_TIMER_TSC);
    446                 if (HMIsSubjectToVmxPreemptTimerErratum())
    447                     g_HmR0.hwvirt.u.vmx.cPreemptTimerShift = 0; /* This is about right most of the time here. */
     516                g_fHmVmxSupported = false;
    448517            }
    449518        }
     
    458527
    459528/**
     529 * Worker function used by hmR0PowerCallback() and HMR0Init() to initalize AMD-V
     530 * on a CPU.
     531 *
     532 * @param   idCpu       The identifier for the CPU the function is called on.
     533 * @param   pvUser1     Pointer to the first RC structure.
     534 * @param   pvUser2     Ignored.
     535 */
     536static DECLCALLBACK(void) hmR0InitAmdCpu(RTCPUID idCpu, void *pvUser1, void *pvUser2)
     537{
     538    PHMR0FIRSTRC pFirstRc = (PHMR0FIRSTRC)pvUser1;
     539    Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
     540    Assert(idCpu == (RTCPUID)RTMpCpuIdToSetIndex(idCpu)); /** @todo fix idCpu == index assumption (rainy day) */
     541    NOREF(idCpu); NOREF(pvUser2);
     542
     543    int rc = SUPR0GetSvmUsability(true /* fInitSvm */);
     544    hmR0FirstRcSetStatus(pFirstRc, rc);
     545}
     546
     547
     548/**
    460549 * AMD-specific initialization code.
    461550 *
     
    466555    /* Call the global AMD-V initialization routine (should only fail in out-of-memory situations). */
    467556    int rc = SVMR0GlobalInit();
    468     if (RT_FAILURE(rc))
    469     {
     557    if (RT_SUCCESS(rc))
     558    {
     559        /*
     560         * Install the AMD-V methods.
     561         */
     562        g_HmR0Ops = g_HmR0OpsSvm;
     563
     564        /* Query AMD features. */
     565        uint32_t u32Dummy;
     566        ASMCpuId(0x8000000a, &g_HmR0.hwvirt.u.svm.u32Rev, &g_uHmMaxAsid, &u32Dummy, &g_HmR0.hwvirt.u.svm.u32Features);
     567
     568        /*
     569         * We need to check if AMD-V has been properly initialized on all CPUs.
     570         * Some BIOSes might do a poor job.
     571         */
     572        HMR0FIRSTRC FirstRc;
     573        hmR0FirstRcInit(&FirstRc);
     574        rc = RTMpOnAll(hmR0InitAmdCpu, &FirstRc, NULL);
     575        AssertRC(rc);
     576        if (RT_SUCCESS(rc))
     577            rc = hmR0FirstRcGetStatus(&FirstRc);
     578#ifndef DEBUG_bird
     579        AssertMsg(rc == VINF_SUCCESS || rc == VERR_SVM_IN_USE,
     580                  ("hmR0InitAmdCpu failed for cpu %d with rc=%Rrc\n", hmR0FirstRcGetCpuId(&FirstRc), rc));
     581#endif
     582        if (RT_SUCCESS(rc))
     583        {
     584            SUPR0GetHwvirtMsrs(&g_HmR0.hwvirt.Msrs, SUPVTCAPS_AMD_V, false /* fForce */);
     585            g_fHmSvmSupported = true;
     586        }
     587        else
     588        {
     589            g_HmR0.rcInit = rc;
     590            if (rc == VERR_SVM_DISABLED || rc == VERR_SVM_IN_USE)
     591                rc = VINF_SUCCESS; /* Don't fail if AMD-V is disabled or in use. */
     592        }
     593    }
     594    else
    470595        g_HmR0.rcInit = rc;
    471         return rc;
    472     }
    473 
    474     /*
    475      * Install the AMD-V methods.
    476      */
    477     g_HmR0.pfnEnterSession      = SVMR0Enter;
    478     g_HmR0.pfnThreadCtxCallback = SVMR0ThreadCtxCallback;
    479     g_HmR0.pfnCallRing3Callback = SVMR0CallRing3Callback;
    480     g_HmR0.pfnExportHostState   = SVMR0ExportHostState;
    481     g_HmR0.pfnRunGuestCode      = SVMR0RunGuestCode;
    482     g_HmR0.pfnEnableCpu         = SVMR0EnableCpu;
    483     g_HmR0.pfnDisableCpu        = SVMR0DisableCpu;
    484     g_HmR0.pfnInitVM            = SVMR0InitVM;
    485     g_HmR0.pfnTermVM            = SVMR0TermVM;
    486     g_HmR0.pfnSetupVM           = SVMR0SetupVM;
    487 
    488     /* Query AMD features. */
    489     uint32_t u32Dummy;
    490     ASMCpuId(0x8000000a, &g_HmR0.hwvirt.u.svm.u32Rev, &g_uHmMaxAsid, &u32Dummy, &g_HmR0.hwvirt.u.svm.u32Features);
    491 
    492     /*
    493      * We need to check if AMD-V has been properly initialized on all CPUs.
    494      * Some BIOSes might do a poor job.
    495      */
    496     HMR0FIRSTRC FirstRc;
    497     hmR0FirstRcInit(&FirstRc);
    498     rc = RTMpOnAll(hmR0InitAmdCpu, &FirstRc, NULL);
    499     AssertRC(rc);
    500     if (RT_SUCCESS(rc))
    501         rc = hmR0FirstRcGetStatus(&FirstRc);
    502 #ifndef DEBUG_bird
    503     AssertMsg(rc == VINF_SUCCESS || rc == VERR_SVM_IN_USE,
    504               ("hmR0InitAmdCpu failed for cpu %d with rc=%Rrc\n", hmR0FirstRcGetCpuId(&FirstRc), rc));
    505 #endif
    506     if (RT_SUCCESS(rc))
    507     {
    508         SUPR0GetHwvirtMsrs(&g_HmR0.hwvirt.Msrs, SUPVTCAPS_AMD_V, false /* fForce */);
    509         g_fHmSvmSupported = true;
    510     }
    511     else
    512     {
    513         g_HmR0.rcInit = rc;
    514         if (rc == VERR_SVM_DISABLED || rc == VERR_SVM_IN_USE)
    515             rc = VINF_SUCCESS; /* Don't fail if AMD-V is disabled or in use. */
    516     }
    517596    return rc;
    518597}
     
    546625
    547626    /* Fill in all callbacks with placeholders. */
    548     g_HmR0.pfnEnterSession      = hmR0DummyEnter;
    549     g_HmR0.pfnThreadCtxCallback = hmR0DummyThreadCtxCallback;
    550     g_HmR0.pfnCallRing3Callback = hmR0DummyCallRing3Callback;
    551     g_HmR0.pfnExportHostState   = hmR0DummyExportHostState;
    552     g_HmR0.pfnRunGuestCode      = hmR0DummyRunGuestCode;
    553     g_HmR0.pfnEnableCpu         = hmR0DummyEnableCpu;
    554     g_HmR0.pfnDisableCpu        = hmR0DummyDisableCpu;
    555     g_HmR0.pfnInitVM            = hmR0DummyInitVM;
    556     g_HmR0.pfnTermVM            = hmR0DummyTermVM;
    557     g_HmR0.pfnSetupVM           = hmR0DummySetupVM;
     627    g_HmR0Ops            = g_HmR0OpsDummy;
    558628
    559629    /* Default is global VT-x/AMD-V init. */
    560     g_HmR0.fGlobalInit         = true;
     630    g_HmR0.fGlobalInit = true;
    561631
    562632    g_fHmVmxSupported  = false;
     
    582652    {
    583653        if (fCaps & SUPVTCAPS_VT_X)
    584         {
    585654            rc = hmR0InitIntel();
    586             if (RT_FAILURE(rc))
    587                 return rc;
    588         }
    589655        else
    590656        {
    591657            Assert(fCaps & SUPVTCAPS_AMD_V);
    592658            rc = hmR0InitAmd();
    593             if (RT_FAILURE(rc))
    594                 return rc;
    595659        }
     660        if (RT_SUCCESS(rc))
     661        {
     662            /*
     663             * Register notification callbacks that we can use to disable/enable CPUs
     664             * when brought offline/online or suspending/resuming.
     665             */
     666            if (!g_HmR0.hwvirt.u.vmx.fUsingSUPR0EnableVTx)
     667            {
     668                rc = RTMpNotificationRegister(hmR0MpEventCallback, NULL);
     669                if (RT_SUCCESS(rc))
     670                {
     671                    rc = RTPowerNotificationRegister(hmR0PowerCallback, NULL);
     672                    if (RT_FAILURE(rc))
     673                        RTMpNotificationDeregister(hmR0MpEventCallback, NULL);
     674                }
     675                if (RT_FAILURE(rc))
     676                {
     677                    /* There shouldn't be any per-cpu allocations at this point,
     678                       so just have to call SVMR0GlobalTerm and VMXR0GlobalTerm. */
     679                    if (fCaps & SUPVTCAPS_VT_X)
     680                        VMXR0GlobalTerm();
     681                    else
     682                        SVMR0GlobalTerm();
     683                    g_HmR0Ops         = g_HmR0OpsDummy;
     684                    g_HmR0.rcInit     = rc;
     685                    g_fHmSvmSupported = false;
     686                    g_fHmVmxSupported = false;
     687                }
     688            }
     689        }
    596690    }
    597691    else
    598         g_HmR0.rcInit = VERR_UNSUPPORTED_CPU;
    599 
    600     /*
    601      * Register notification callbacks that we can use to disable/enable CPUs
    602      * when brought offline/online or suspending/resuming.
    603      */
    604     if (!g_HmR0.hwvirt.u.vmx.fUsingSUPR0EnableVTx)
    605     {
    606         rc = RTMpNotificationRegister(hmR0MpEventCallback, NULL);
    607         AssertRC(rc);
    608 
    609         rc = RTPowerNotificationRegister(hmR0PowerCallback, NULL);
    610         AssertRC(rc);
    611     }
    612 
    613     /* We return success here because module init shall not fail if HM fails to initialize. */
    614     return VINF_SUCCESS;
     692    {
     693        g_HmR0.rcInit = rc;
     694        rc = VINF_SUCCESS; /* We return success here because module init shall not fail if HM fails to initialize. */
     695    }
     696    return rc;
    615697}
    616698
     
    619701 * Does global Ring-0 HM termination (at module termination).
    620702 *
    621  * @returns VBox status code.
     703 * @returns VBox status code (ignored).
    622704 */
    623705VMMR0_INT_DECL(int) HMR0Term(void)
     
    651733
    652734        /* Doesn't really matter if this fails. */
    653         rc = RTMpNotificationDeregister(hmR0MpEventCallback, NULL);  AssertRC(rc);
    654         rc = RTPowerNotificationDeregister(hmR0PowerCallback, NULL); AssertRC(rc);
     735        RTMpNotificationDeregister(hmR0MpEventCallback, NULL);
     736        RTPowerNotificationDeregister(hmR0PowerCallback, NULL);
     737        rc = VINF_SUCCESS;
    655738
    656739        /*
     
    705788
    706789/**
    707  * Worker function used by hmR0PowerCallback() and HMR0Init() to initalize VT-x
    708  * on a CPU.
    709  *
    710  * @param   idCpu       The identifier for the CPU the function is called on.
    711  * @param   pvUser1     Pointer to the first RC structure.
    712  * @param   pvUser2     Ignored.
    713  */
    714 static DECLCALLBACK(void) hmR0InitIntelCpu(RTCPUID idCpu, void *pvUser1, void *pvUser2)
    715 {
    716     PHMR0FIRSTRC pFirstRc = (PHMR0FIRSTRC)pvUser1;
    717     Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
    718     Assert(idCpu == (RTCPUID)RTMpCpuIdToSetIndex(idCpu)); /** @todo fix idCpu == index assumption (rainy day) */
    719     NOREF(idCpu); NOREF(pvUser2);
    720 
    721     int rc = SUPR0GetVmxUsability(NULL /* pfIsSmxModeAmbiguous */);
    722     hmR0FirstRcSetStatus(pFirstRc, rc);
    723 }
    724 
    725 
    726 /**
    727  * Worker function used by hmR0PowerCallback() and HMR0Init() to initalize AMD-V
    728  * on a CPU.
    729  *
    730  * @param   idCpu       The identifier for the CPU the function is called on.
    731  * @param   pvUser1     Pointer to the first RC structure.
    732  * @param   pvUser2     Ignored.
    733  */
    734 static DECLCALLBACK(void) hmR0InitAmdCpu(RTCPUID idCpu, void *pvUser1, void *pvUser2)
    735 {
    736     PHMR0FIRSTRC pFirstRc = (PHMR0FIRSTRC)pvUser1;
    737     Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
    738     Assert(idCpu == (RTCPUID)RTMpCpuIdToSetIndex(idCpu)); /** @todo fix idCpu == index assumption (rainy day) */
    739     NOREF(idCpu); NOREF(pvUser2);
    740 
    741     int rc = SUPR0GetSvmUsability(true /* fInitSvm */);
    742     hmR0FirstRcSetStatus(pFirstRc, rc);
    743 }
    744 
    745 
    746 /**
    747790 * Enable VT-x or AMD-V on the current CPU
    748791 *
     
    768811    if (   g_fHmVmxSupported
    769812        && g_HmR0.hwvirt.u.vmx.fUsingSUPR0EnableVTx)
    770         rc = g_HmR0.pfnEnableCpu(pHostCpu, pVM, NULL /* pvCpuPage */, NIL_RTHCPHYS, true, &g_HmR0.hwvirt.Msrs);
     813        rc = g_HmR0Ops.pfnEnableCpu(pHostCpu, pVM, NULL /* pvCpuPage */, NIL_RTHCPHYS, true, &g_HmR0.hwvirt.Msrs);
    771814    else
    772815    {
    773816        AssertLogRelMsgReturn(pHostCpu->hMemObj != NIL_RTR0MEMOBJ, ("hmR0EnableCpu failed idCpu=%u.\n", idCpu), VERR_HM_IPE_1);
    774         rc = g_HmR0.pfnEnableCpu(pHostCpu, pVM, pHostCpu->pvMemObj, pHostCpu->HCPhysMemObj, false, &g_HmR0.hwvirt.Msrs);
     817        rc = g_HmR0Ops.pfnEnableCpu(pHostCpu, pVM, pHostCpu->pvMemObj, pHostCpu->HCPhysMemObj, false, &g_HmR0.hwvirt.Msrs);
    775818    }
    776819    if (RT_SUCCESS(rc))
     
    9581001    if (pHostCpu->fConfigured)
    9591002    {
    960         rc = g_HmR0.pfnDisableCpu(pHostCpu, pHostCpu->pvMemObj, pHostCpu->HCPhysMemObj);
     1003        rc = g_HmR0Ops.pfnDisableCpu(pHostCpu, pHostCpu->pvMemObj, pHostCpu->HCPhysMemObj);
    9611004        AssertRCReturn(rc, rc);
    9621005
     
    12581301     * Call the hardware specific initialization method.
    12591302     */
    1260     return g_HmR0.pfnInitVM(pVM);
     1303    return g_HmR0Ops.pfnInitVM(pVM);
    12611304}
    12621305
     
    12791322     * mess with VT-x/AMD-V features on the CPU, currently all they do is free memory so this is safe.
    12801323     */
    1281     return g_HmR0.pfnTermVM(pVM);
     1324    return g_HmR0Ops.pfnTermVM(pVM);
    12821325}
    12831326
     
    13241367
    13251368    /* Setup VT-x or AMD-V. */
    1326     rc = g_HmR0.pfnSetupVM(pVM);
     1369    rc = g_HmR0Ops.pfnSetupVM(pVM);
    13271370
    13281371    /* Disable VT-x or AMD-V if local init was done before. */
     
    13511394    RT_NOREF(pvUser);
    13521395    Assert(pVCpu);
    1353     Assert(g_HmR0.pfnCallRing3Callback);
    1354     return g_HmR0.pfnCallRing3Callback(pVCpu, enmOperation);
     1396    Assert(g_HmR0Ops.pfnCallRing3Callback);
     1397    return g_HmR0Ops.pfnCallRing3Callback(pVCpu, enmOperation);
    13551398}
    13561399
     
    14241467
    14251468        /* Keep track of the CPU owning the VMCS for debugging scheduling weirdness and ring-3 calls. */
    1426         rc = g_HmR0.pfnEnterSession(pVCpu);
     1469        rc = g_HmR0Ops.pfnEnterSession(pVCpu);
    14271470        AssertMsgRCReturnStmt(rc, ("rc=%Rrc pVCpu=%p\n", rc, pVCpu),  pVCpu->hmr0.s.idEnteredCpu = NIL_RTCPUID, rc);
    14281471
    14291472        /* Exports the host-state as we may be resuming code after a longjmp and quite
    14301473           possibly now be scheduled on a different CPU. */
    1431         rc = g_HmR0.pfnExportHostState(pVCpu);
     1474        rc = g_HmR0Ops.pfnExportHostState(pVCpu);
    14321475        AssertMsgRCReturnStmt(rc, ("rc=%Rrc pVCpu=%p\n", rc, pVCpu),  pVCpu->hmr0.s.idEnteredCpu = NIL_RTCPUID, rc);
    14331476
     
    14891532    PVMCPUCC pVCpu = (PVMCPUCC)pvUser;
    14901533    Assert(pVCpu);
    1491     Assert(g_HmR0.pfnThreadCtxCallback);
    1492 
    1493     g_HmR0.pfnThreadCtxCallback(enmEvent, pVCpu, g_HmR0.fGlobalInit);
     1534    Assert(g_HmR0Ops.pfnThreadCtxCallback);
     1535
     1536    g_HmR0Ops.pfnThreadCtxCallback(enmEvent, pVCpu, g_HmR0.fGlobalInit);
    14941537}
    14951538
     
    15271570#endif
    15281571
    1529     VBOXSTRICTRC rcStrict = g_HmR0.pfnRunGuestCode(pVCpu);
     1572    VBOXSTRICTRC rcStrict = g_HmR0Ops.pfnRunGuestCode(pVCpu);
    15301573
    15311574#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette