VirtualBox

Changeset 36245 in vbox


Ignore:
Timestamp:
Mar 9, 2011 8:22:00 PM (14 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
70469
Message:

HWACCMR0: Replaced return code arrays used by RTMpOnAll operation with a structure for remembering the failure and cpu id.

File:
1 edited

Legend:

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

    r36237 r36245  
    3434#include <iprt/asm-amd64-x86.h>
    3535#include <iprt/cpuset.h>
     36#include <iprt/mem.h>
    3637#include <iprt/memobj.h>
    3738#include <iprt/param.h>
     
    4748static DECLCALLBACK(void) hwaccmR0EnableCpuCallback(RTCPUID idCpu, void *pvUser1, void *pvUser2);
    4849static DECLCALLBACK(void) hwaccmR0DisableCpuCallback(RTCPUID idCpu, void *pvUser1, void *pvUser2);
    49 static DECLCALLBACK(void) HWACCMR0InitCPU(RTCPUID idCpu, void *pvUser1, void *pvUser2);
    50 static              int   hwaccmR0CheckCpuRcArray(int *paRc, unsigned cErrorCodes, RTCPUID *pidCpu);
     50static DECLCALLBACK(void) hwaccmR0InitCpu(RTCPUID idCpu, void *pvUser1, void *pvUser2);
    5151static bool               hwaccmR0IsSubjectToVmxPreemptionTimerErratum(void);
    5252static DECLCALLBACK(void) hwaccmR0PowerCallback(RTPOWEREVENT enmEvent, void *pvUser);
     
    143143
    144144
     145/**
     146 * This is used to manage the status code of a RTMpOnAll in HWACCM.
     147 */
     148typedef struct HWACCMR0FIRSTRC
     149{
     150    /** The status code. */
     151    int32_t volatile    rc;
     152    /** The ID of the CPU reporting the first failure. */
     153    RTCPUID volatile    idCpu;
     154} HWACCMR0FIRSTRC;
     155/** Pointer to a first return code structure. */
     156typedef HWACCMR0FIRSTRC *PHWACCMR0FIRSTRC;
     157
     158
     159/**
     160 * Initializes a first return code structure.
     161 *
     162 * @param   pFirstRc            The structure to init.
     163 */
     164static void hwaccmR0FirstRcInit(PHWACCMR0FIRSTRC pFirstRc)
     165{
     166    pFirstRc->rc    = VINF_SUCCESS;
     167    pFirstRc->idCpu = NIL_RTCPUID;
     168}
     169
     170
     171/**
     172 * Try se the status code (success ignored).
     173 *
     174 * @param   pFirstRc            The first return code structure.
     175 * @param   rc                  The status code.
     176 */
     177static void hwaccmR0FirstRcSetStatus(PHWACCMR0FIRSTRC pFirstRc, int rc)
     178{
     179    if (   RT_FAILURE(rc)
     180        && ASMAtomicCmpXchgS32(&pFirstRc->rc, rc, VINF_SUCCESS))
     181        pFirstRc->idCpu = RTMpCpuId();
     182}
     183
     184
     185/**
     186 * Get the status code of a first return code structure.
     187 *
     188 * @returns The status code; VINF_SUCCESS or error status, no informational or
     189 *          warning errors.
     190 * @param   pFirstRc            The first return code structure.
     191 */
     192static int hwaccmR0FirstRcGetStatus(PHWACCMR0FIRSTRC pFirstRc)
     193{
     194    return pFirstRc->rc;
     195}
     196
     197
     198/**
     199 * Get the CPU ID on which the failure status code was reported.
     200 *
     201 * @returns The CPU ID, NIL_RTCPUID if no failure was reported.
     202 * @param   pFirstRc            The first return code structure.
     203 */
     204static RTCPUID hwaccmR0FirstRcGetCpuId(PHWACCMR0FIRSTRC pFirstRc)
     205{
     206    return pFirstRc->idCpu;
     207}
     208
    145209
    146210/**
     
    211275               )
    212276            {
    213                 int     aRc[RTCPUSET_MAX_CPUS]; /** @todo 256 CPUs: move this off the stack */
    214                 RTCPUID idCpu = 0;
    215 
    216277                HWACCMR0Globals.vmx.msr.feature_ctrl = ASMRdMsr(MSR_IA32_FEATURE_CONTROL);
    217278
     
    237298
    238299                    /* We need to check if VT-x has been properly initialized on all CPUs. Some BIOSes do a lousy job. */
    239                     memset(aRc, 0, sizeof(aRc));
    240                     HWACCMR0Globals.lLastError = RTMpOnAll(HWACCMR0InitCPU, (void *)u32VendorEBX, aRc);
    241 
    242                     /* Check the return code of all invocations. */
     300                    HWACCMR0FIRSTRC FirstRc;
     301                    hwaccmR0FirstRcInit(&FirstRc);
     302                    HWACCMR0Globals.lLastError = RTMpOnAll(hwaccmR0InitCpu, (void *)u32VendorEBX, &FirstRc);
    243303                    if (RT_SUCCESS(HWACCMR0Globals.lLastError))
    244                         HWACCMR0Globals.lLastError = hwaccmR0CheckCpuRcArray(aRc, RT_ELEMENTS(aRc), &idCpu);
     304                        HWACCMR0Globals.lLastError = hwaccmR0FirstRcGetStatus(&FirstRc);
    245305                }
    246306                if (RT_SUCCESS(HWACCMR0Globals.lLastError))
     
    355415#ifdef LOG_ENABLED
    356416                else
    357                     SUPR0Printf("HWACCMR0InitCPU failed with rc=%d\n", HWACCMR0Globals.lLastError);
     417                    SUPR0Printf("hwaccmR0InitCpu failed with rc=%d\n", HWACCMR0Globals.lLastError);
    358418#endif
    359419            }
     
    376436               )
    377437            {
    378                 int     aRc[RTCPUSET_MAX_CPUS]; /** @todo 256 CPUs: Move this off the stack */
    379                 RTCPUID idCpu = 0;
    380 
    381438                fAMDVPresent = true;
    382439
     
    385442
    386443                /* We need to check if AMD-V has been properly initialized on all CPUs. Some BIOSes might do a poor job. */
    387                 memset(aRc, 0, sizeof(aRc));
    388                 rc = RTMpOnAll(HWACCMR0InitCPU, (void *)u32VendorEBX, aRc);
    389                 AssertRC(rc);
    390 
    391                 /* Check the return code of all invocations. */
     444                HWACCMR0FIRSTRC FirstRc;
     445                hwaccmR0FirstRcInit(&FirstRc);
     446                rc = RTMpOnAll(hwaccmR0InitCpu, (void *)u32VendorEBX, &FirstRc);    AssertRC(rc);
    392447                if (RT_SUCCESS(rc))
    393                     rc = hwaccmR0CheckCpuRcArray(aRc, RT_ELEMENTS(aRc), &idCpu);
    394 
     448                    rc = hwaccmR0FirstRcGetStatus(&FirstRc);
    395449#ifndef DEBUG_bird
    396                 AssertMsg(rc == VINF_SUCCESS || rc == VERR_SVM_IN_USE, ("HWACCMR0InitCPU failed for cpu %d with rc=%d\n", idCpu, rc));
     450                AssertMsg(rc == VINF_SUCCESS || rc == VERR_SVM_IN_USE, ("hwaccmR0InitCpu failed for cpu %d with rc=%d\n", hwaccmR0FirstRcGetCpuId(&FirstRc), rc));
    397451#endif
    398452                if (RT_SUCCESS(rc))
     
    449503
    450504    return VINF_SUCCESS;
    451 }
    452 
    453 
    454 /**
    455  * Checks the error code array filled in for each cpu in the system.
    456  *
    457  * @returns VBox status code.
    458  * @param   paRc        Error code array
    459  * @param   cErrorCodes Array size
    460  * @param   pidCpu      Value of the first cpu that set an error (out)
    461  */
    462 static int hwaccmR0CheckCpuRcArray(int *paRc, unsigned cErrorCodes, RTCPUID *pidCpu)
    463 {
    464     int rc = VINF_SUCCESS;
    465 
    466     Assert(cErrorCodes == RTCPUSET_MAX_CPUS);
    467 
    468     for (unsigned i=0;i<cErrorCodes;i++)
    469     {
    470         if (RTMpIsCpuOnline(i))
    471         {
    472             if (RT_FAILURE(paRc[i]))
    473             {
    474                 rc      = paRc[i];
    475                 *pidCpu = i;
    476                 break;
    477             }
    478         }
    479     }
    480     return rc;
    481505}
    482506
     
    560584        if (HWACCMR0Globals.fGlobalInit)
    561585        {
    562             int aRc[RTCPUSET_MAX_CPUS]; /** @todo 256 CPUs: Move this off the stack */
    563 
    564             memset(aRc, 0, sizeof(aRc));
    565             rc = RTMpOnAll(hwaccmR0DisableCpuCallback, aRc, NULL);
     586            HWACCMR0FIRSTRC FirstRc;
     587            hwaccmR0FirstRcInit(&FirstRc);
     588            rc = RTMpOnAll(hwaccmR0DisableCpuCallback, NULL, &FirstRc);
    566589            Assert(RT_SUCCESS(rc) || rc == VERR_NOT_SUPPORTED);
    567 #ifdef VBOX_STRICT
    568             for (unsigned i=0;i<RT_ELEMENTS(HWACCMR0Globals.aCpuInfo);i++)
    569                 AssertMsgRC(aRc[i], ("hwaccmR0DisableCpuCallback failed for cpu %d with rc=%d\n", i, aRc[i]));
    570 #endif
     590            if (RT_SUCCESS(rc))
     591            {
     592                rc = hwaccmR0FirstRcGetStatus(&FirstRc);
     593                AssertMsgRC(rc, ("%u: %Rrc\n", hwaccmR0FirstRcGetCpuId(&FirstRc), rc));
     594            }
    571595        }
    572596
     
    593617 * @param   pvUser2     The 2nd user argument.
    594618 */
    595 static DECLCALLBACK(void) HWACCMR0InitCPU(RTCPUID idCpu, void *pvUser1, void *pvUser2)
    596 {
    597     unsigned u32VendorEBX = (uintptr_t)pvUser1;
    598     int     *paRc         = (int *)pvUser2;
    599     uint64_t val;
     619static DECLCALLBACK(void) hwaccmR0InitCpu(RTCPUID idCpu, void *pvUser1, void *pvUser2)
     620{
     621    unsigned            u32VendorEBX = (uintptr_t)pvUser1;
     622    PHWACCMR0FIRSTRC    pFirstRc     = (PHWACCMR0FIRSTRC)pvUser2;
     623    uint64_t            val;
     624    int                 rc;
    600625
    601626#if defined(LOG_ENABLED) && !defined(DEBUG_bird)
    602     SUPR0Printf("HWACCMR0InitCPU cpu %d\n", idCpu);
     627    SUPR0Printf("hwaccmR0InitCpu cpu %d\n", idCpu);
    603628#endif
    604629    Assert(idCpu == (RTCPUID)RTMpCpuIdToSetIndex(idCpu)); /// @todo fix idCpu == index assumption (rainy day)
     
    622647        if (   (val & (MSR_IA32_FEATURE_CONTROL_VMXON|MSR_IA32_FEATURE_CONTROL_LOCK))
    623648                   == (MSR_IA32_FEATURE_CONTROL_VMXON|MSR_IA32_FEATURE_CONTROL_LOCK))
    624             paRc[idCpu] = VINF_SUCCESS;
     649            rc = VINF_SUCCESS;
    625650        else
    626             paRc[idCpu] = VERR_VMX_MSR_LOCKED_OR_DISABLED;
    627     }
    628     else
    629     if (u32VendorEBX == X86_CPUID_VENDOR_AMD_EBX)
     651            rc = VERR_VMX_MSR_LOCKED_OR_DISABLED;
     652    }
     653    else if (u32VendorEBX == X86_CPUID_VENDOR_AMD_EBX)
    630654    {
    631655        /* Check if SVM is disabled */
     
    636660            val = ASMRdMsr(MSR_K6_EFER);
    637661            if (val & MSR_K6_EFER_SVME)
    638             {
    639                 paRc[idCpu] = VERR_SVM_IN_USE;
    640             }
     662                rc = VERR_SVM_IN_USE;
    641663            else
    642664            {
     
    649671                    /* Restore previous value. */
    650672                    ASMWrMsr(MSR_K6_EFER, val & ~MSR_K6_EFER_SVME);
    651                     paRc[idCpu] = VINF_SUCCESS;
     673                    rc = VINF_SUCCESS;
    652674                }
    653675                else
    654                     paRc[idCpu] = VERR_SVM_ILLEGAL_EFER_MSR;
     676                    rc = VERR_SVM_ILLEGAL_EFER_MSR;
    655677            }
    656678        }
    657679        else
    658             paRc[idCpu] = VERR_SVM_DISABLED;
     680            rc = VERR_SVM_DISABLED;
    659681    }
    660682    else
     683    {
    661684        AssertFailed(); /* can't happen */
    662     return;
     685        rc = VERR_INTERNAL_ERROR_5;
     686    }
     687
     688    hwaccmR0FirstRcSetStatus(pFirstRc, rc);
    663689}
    664690
     
    704730        else
    705731        {
    706             int     aRc[RTCPUSET_MAX_CPUS]; /** @todo 256 CPUs: Move this off the stack */
    707             RTCPUID idCpu = 0;
    708 
    709             memset(aRc, 0, sizeof(aRc));
    710 
    711732            /* Allocate one page per cpu for the global vt-x and amd-v pages */
    712733            for (unsigned i=0;i<RT_ELEMENTS(HWACCMR0Globals.aCpuInfo);i++)
     
    734755            {
    735756                /* First time, so initialize each cpu/core */
    736                 rc = RTMpOnAll(hwaccmR0EnableCpuCallback, (void *)pVM, aRc);
    737 
    738                 /* Check the return code of all invocations. */
     757                HWACCMR0FIRSTRC FirstRc;
     758                hwaccmR0FirstRcInit(&FirstRc);
     759                rc = RTMpOnAll(hwaccmR0EnableCpuCallback, (void *)pVM, &FirstRc);
    739760                if (RT_SUCCESS(rc))
    740                     rc = hwaccmR0CheckCpuRcArray(aRc, RT_ELEMENTS(aRc), &idCpu);
    741                 AssertMsgRC(rc, ("HWACCMR0EnableAllCpus failed for cpu %d with rc=%d\n", idCpu, rc));
     761                    rc = hwaccmR0FirstRcGetStatus(&FirstRc);
     762                AssertMsgRC(rc, ("HWACCMR0EnableAllCpus failed for cpu %d with rc=%d\n", hwaccmR0FirstRcGetCpuId(&FirstRc), rc));
    742763            }
    743764            else
     
    806827static DECLCALLBACK(void) hwaccmR0EnableCpuCallback(RTCPUID idCpu, void *pvUser1, void *pvUser2)
    807828{
    808     PVM             pVM = (PVM)pvUser1;     /* can be NULL! */
    809     int            *paRc = (int *)pvUser2;
    810 
    811     if (!HWACCMR0Globals.fGlobalInit)
    812     {
    813         paRc[idCpu] = VINF_SUCCESS;
    814         AssertFailed();
    815         return;
    816     }
    817 
    818     paRc[idCpu] = hwaccmR0EnableCpu(pVM, idCpu);
     829    PVM                 pVM      = (PVM)pvUser1;     /* can be NULL! */
     830    PHWACCMR0FIRSTRC    pFirstRc = (PHWACCMR0FIRSTRC)pvUser2;
     831    AssertReturnVoid(HWACCMR0Globals.fGlobalInit);
     832    hwaccmR0FirstRcSetStatus(pFirstRc, hwaccmR0EnableCpu(pVM, idCpu));
    819833}
    820834
     
    868882static DECLCALLBACK(void) hwaccmR0DisableCpuCallback(RTCPUID idCpu, void *pvUser1, void *pvUser2)
    869883{
    870     int            *paRc = (int *)pvUser1;
    871 
    872     if (!HWACCMR0Globals.fGlobalInit)
    873     {
    874         paRc[idCpu] = VINF_SUCCESS;
    875         AssertFailed();
    876         return;
    877     }
    878 
    879     paRc[idCpu] = hwaccmR0DisableCpu(idCpu);
     884    PHWACCMR0FIRSTRC pFirstRc = (PHWACCMR0FIRSTRC)pvUser2;
     885    AssertReturnVoid(HWACCMR0Globals.fGlobalInit);
     886    hwaccmR0FirstRcSetStatus(pFirstRc, hwaccmR0DisableCpu(idCpu));
    880887}
    881888
     
    903910    if (HWACCMR0Globals.enmHwAccmState == HWACCMSTATE_ENABLED)
    904911    {
    905         int     aRc[RTCPUSET_MAX_CPUS]; /** @todo 256 CPUs: Move this off the stack */
    906         int     rc;
    907         RTCPUID idCpu;
    908 
    909         memset(aRc, 0, sizeof(aRc));
     912        int             rc;
     913        HWACCMR0FIRSTRC FirstRc;
     914        hwaccmR0FirstRcInit(&FirstRc);
     915
    910916        if (enmEvent == RTPOWEREVENT_SUSPEND)
    911917        {
     
    913919            {
    914920                /* Turn off VT-x or AMD-V on all CPUs. */
    915                 rc = RTMpOnAll(hwaccmR0DisableCpuCallback, aRc, NULL);
     921                rc = RTMpOnAll(hwaccmR0DisableCpuCallback, NULL, &FirstRc);
    916922                Assert(RT_SUCCESS(rc) || rc == VERR_NOT_SUPPORTED);
    917923            }
     
    921927        {
    922928            /* Reinit the CPUs from scratch as the suspend state might have messed with the MSRs. (lousy BIOSes as usual) */
    923             rc = RTMpOnAll(HWACCMR0InitCPU, (void *)((HWACCMR0Globals.vmx.fSupported) ? X86_CPUID_VENDOR_INTEL_EBX : X86_CPUID_VENDOR_AMD_EBX), aRc);
     929            uintptr_t uFirstArg = HWACCMR0Globals.vmx.fSupported ? X86_CPUID_VENDOR_INTEL_EBX : X86_CPUID_VENDOR_AMD_EBX;
     930            rc = RTMpOnAll(hwaccmR0InitCpu, (void *)uFirstArg , &FirstRc);
    924931            Assert(RT_SUCCESS(rc) || rc == VERR_NOT_SUPPORTED);
    925 
    926932            if (RT_SUCCESS(rc))
    927                 rc = hwaccmR0CheckCpuRcArray(aRc, RT_ELEMENTS(aRc), &idCpu);
     933                rc = hwaccmR0FirstRcGetStatus(&FirstRc);
    928934#ifdef LOG_ENABLED
    929935            if (RT_FAILURE(rc))
    930                 SUPR0Printf("hwaccmR0PowerCallback HWACCMR0InitCPU failed with %d\n", rc);
     936                SUPR0Printf("hwaccmR0PowerCallback hwaccmR0InitCpu failed with %Rc\n", rc);
    931937#endif
    932938
     
    934940            {
    935941                /* Turn VT-x or AMD-V back on on all CPUs. */
    936                 rc = RTMpOnAll(hwaccmR0EnableCpuCallback, NULL, aRc);
     942                rc = RTMpOnAll(hwaccmR0EnableCpuCallback, NULL, &FirstRc /* output ignored */);
    937943                Assert(RT_SUCCESS(rc) || rc == VERR_NOT_SUPPORTED);
    938944            }
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