VirtualBox

Ignore:
Timestamp:
Sep 30, 2019 10:17:28 AM (5 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
133675
Message:

SUPDrv,IPRT,VMM: Support host APIC ID above 256 in GIP. (Only tested on 4 core intel.) bugref:9501

Location:
trunk/src/VBox/HostDrivers/Support
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostDrivers/Support/SUPDrvGip.cpp

    r77727 r81071  
    173173
    174174
     175/**
     176 * Gets the APIC ID using the best available method.
     177 *
     178 * @returns APIC ID.
     179 * @param   pGip                The GIP, for SUPGIPGETCPU_XXX.
     180 */
     181DECLINLINE(uint32_t) supdrvGipGetApicId(PSUPGLOBALINFOPAGE pGip)
     182{
     183    if (pGip->fGetGipCpu & SUPGIPGETCPU_APIC_ID_EXT_0B)
     184        return ASMGetApicIdExt0B();
     185    if (pGip->fGetGipCpu & SUPGIPGETCPU_APIC_ID_EXT_8000001E)
     186        return ASMGetApicIdExt8000001E();
     187    return ASMGetApicId();
     188}
     189
    175190
    176191/*
     
    212227static DECLCALLBACK(void) supdrvGipReInitCpuCallback(RTCPUID idCpu, void *pvUser1, void *pvUser2)
    213228{
    214     PSUPGLOBALINFOPAGE  pGip = (PSUPGLOBALINFOPAGE)pvUser1;
    215     unsigned            iCpu = pGip->aiCpuFromApicId[ASMGetApicId()];
    216 
    217     if (RT_LIKELY(iCpu < pGip->cCpus && pGip->aCPUs[iCpu].idCpu == idCpu))
    218         supdrvGipReInitCpu(&pGip->aCPUs[iCpu], *(uint64_t *)pvUser2);
     229    PSUPGLOBALINFOPAGE  pGip   = (PSUPGLOBALINFOPAGE)pvUser1;
     230    uint32_t const      idApic = supdrvGipGetApicId(pGip);
     231    if (idApic < RT_ELEMENTS(pGip->aiCpuFromApicId))
     232    {
     233        unsigned const  iCpu   = pGip->aiCpuFromApicId[idApic];
     234
     235        if (RT_LIKELY(iCpu < pGip->cCpus && pGip->aCPUs[iCpu].idCpu == idCpu))
     236            supdrvGipReInitCpu(&pGip->aCPUs[iCpu], *(uint64_t *)pvUser2);
     237    }
    219238
    220239    NOREF(pvUser2);
    221     NOREF(idCpu);
    222240}
    223241
     
    230248    /** Bitmap of APIC IDs that has been seen (initialized to zero).
    231249     *  Used to detect duplicate APIC IDs (paranoia). */
    232     uint8_t volatile    bmApicId[256 / 8];
     250    uint8_t volatile    bmApicId[1024 / 8];
    233251    /** Mask of supported GIP CPU getter methods (SUPGIPGETCPU_XXX) (all bits set
    234252     *  initially). The callback clears the methods not detected. */
     
    257275    PSUPGLOBALINFOPAGE      pGip   = (PSUPGLOBALINFOPAGE)pvUser2;
    258276    uint32_t                fSupported = 0;
    259     uint16_t                idApic;
     277    uint32_t                idApic;
     278    uint32_t                uEax, uEbx, uEcx, uEdx;
    260279    int                     iCpuSet;
    261280    NOREF(pGip);
     
    307326                    && (ASMCpuId_EDX(UINT32_C(0x80000001)) & X86_CPUID_EXT_FEATURE_EDX_RDTSCP) )
    308327                {
    309                     uint32_t        uAux;
     328                    uint32_t uAux;
    310329                    ASMReadTscWithAux(&uAux);
    311330                    if ((uAux & (RTCPUSET_MAX_CPUS - 1)) == idCpu)
     
    335354
    336355    /*
     356     * Check for extended APIC ID methods.
     357     */
     358    idApic = UINT32_MAX;
     359    uEax = ASMCpuId_EAX(0);
     360    if (uEax >= UINT32_C(0xb) && ASMIsValidStdRange(uEax))
     361    {
     362        ASMCpuIdExSlow(0xb, 0, 0, 0, &uEax, &uEbx, &uEcx, &uEdx);
     363        if (uEax || uEbx || uEcx || uEdx)
     364        {
     365            if (RT_LIKELY(   uEdx < RT_ELEMENTS(pGip->aiCpuFromApicId)
     366                          && !ASMBitTest(pState->bmApicId, uEdx)))
     367            {
     368                if (uEdx == ASMGetApicIdExt0B())
     369                {
     370                    idApic = uEdx;
     371                    fSupported |= SUPGIPGETCPU_APIC_ID_EXT_0B;
     372                }
     373                else
     374                    AssertMsgFailed(("%#x vs %#x\n", uEdx, ASMGetApicIdExt0B()));
     375            }
     376        }
     377    }
     378
     379    uEax = ASMCpuId_EAX(UINT32_C(0x80000000));
     380    if (uEax >= UINT32_C(0x8000001e) && ASMIsValidExtRange(uEax))
     381    {
     382        ASMCpuIdExSlow(UINT32_C(0x8000001e), 0, 0, 0, &uEax, &uEbx, &uEcx, &uEdx);
     383        if (uEax || uEbx || uEcx || uEdx)
     384        {
     385            if (RT_LIKELY(   uEax < RT_ELEMENTS(pGip->aiCpuFromApicId)
     386                          && (   idApic == UINT32_MAX
     387                              || idApic == uEax)
     388                          && !ASMBitTest(pState->bmApicId, uEax)))
     389            {
     390                if (uEax == ASMGetApicIdExt8000001E())
     391                {
     392                    idApic = uEax;
     393                    fSupported |= SUPGIPGETCPU_APIC_ID_EXT_8000001E;
     394                }
     395                else
     396                    AssertMsgFailed(("%#x vs %#x\n", uEax, ASMGetApicIdExt8000001E()));
     397            }
     398        }
     399    }
     400
     401    /*
    337402     * Check that the APIC ID is unique.
    338403     */
    339     idApic = ASMGetApicId();
    340     if (RT_LIKELY(   idApic < RT_ELEMENTS(pGip->aiCpuFromApicId)
    341                   && !ASMAtomicBitTestAndSet(pState->bmApicId, idApic)))
     404    uEax = ASMGetApicId();
     405    if (RT_LIKELY(   uEax < RT_ELEMENTS(pGip->aiCpuFromApicId)
     406                  && (   idApic == UINT32_MAX
     407                      || idApic == uEax)
     408                  && !ASMAtomicBitTestAndSet(pState->bmApicId, uEax)))
     409    {
     410        idApic = uEax;
    342411        fSupported |= SUPGIPGETCPU_APIC_ID;
    343     else
     412    }
     413    else if (   idApic == UINT32_MAX
     414             || idApic >= RT_ELEMENTS(pGip->aiCpuFromApicId) /* parnaoia */
     415             || ASMAtomicBitTestAndSet(pState->bmApicId, idApic))
    344416    {
    345417        AssertCompile(sizeof(pState->bmApicId) * 8 == RT_ELEMENTS(pGip->aiCpuFromApicId));
    346418        ASMAtomicCmpXchgU32(&pState->idCpuProblem, idCpu, NIL_RTCPUID);
    347         LogRel(("supdrvGipDetectGetGipCpuCallback: idCpu=%#x iCpuSet=%d idApic=%#x - duplicate APIC ID.\n",
    348                 idCpu, iCpuSet, idApic));
     419        LogRel(("supdrvGipDetectGetGipCpuCallback: idCpu=%#x iCpuSet=%d idApic=%#x/%#x - duplicate APIC ID.\n",
     420                idCpu, iCpuSet, uEax, idApic));
    349421    }
    350422
     
    12761348    PSUPGLOBALINFOPAGE  pGip      = pDevExt->pGip;
    12771349    int                 iCpuSet   = 0;
    1278     uint16_t            idApic    = UINT16_MAX;
     1350    uint32_t            idApic;
    12791351    uint32_t            i         = 0;
    12801352    uint64_t            u64NanoTS = 0;
     
    13121384    supdrvGipInitCpu(pGip, &pGip->aCPUs[i], u64NanoTS, pGip->u64CpuHz);
    13131385
    1314     idApic = ASMGetApicId();
     1386    idApic = supdrvGipGetApicId(pGip);
    13151387    ASMAtomicWriteU16(&pGip->aCPUs[i].idApic,  idApic);
    13161388    ASMAtomicWriteS16(&pGip->aCPUs[i].iCpuSet, (int16_t)iCpuSet);
     
    13261398     * Update the APIC ID and CPU set index mappings.
    13271399     */
    1328     ASMAtomicWriteU16(&pGip->aiCpuFromApicId[idApic],     i);
    1329     ASMAtomicWriteU16(&pGip->aiCpuFromCpuSetIdx[iCpuSet], i);
     1400    if (idApic < RT_ELEMENTS(pGip->aiCpuFromApicId))
     1401        ASMAtomicWriteU16(&pGip->aiCpuFromApicId[idApic],     i);
     1402    if ((unsigned)iCpuSet < RT_ELEMENTS(pGip->aiCpuFromCpuSetIdx))
     1403        ASMAtomicWriteU16(&pGip->aiCpuFromCpuSetIdx[iCpuSet], i);
    13301404
    13311405    /* Add this CPU to this set of CPUs we need to calculate the TSC-delta for. */
     
    23642438    else
    23652439    {
    2366         unsigned iCpu = pGip->aiCpuFromApicId[ASMGetApicId()];
    2367         if (RT_UNLIKELY(iCpu >= pGip->cCpus))
     2440        unsigned iCpu;
     2441        uint32_t idApic = supdrvGipGetApicId(pGip);
     2442        if (RT_LIKELY(idApic < RT_ELEMENTS(pGip->aiCpuFromApicId)))
     2443        { /* likely */ }
     2444        else
     2445            return;
     2446        iCpu = pGip->aiCpuFromApicId[idApic];
     2447        if (RT_LIKELY(iCpu < pGip->cCpus))
     2448        { /* likely */ }
     2449        else
    23682450            return;
    23692451        pGipCpu = &pGip->aCPUs[iCpu];
    2370         if (RT_UNLIKELY(pGipCpu->idCpu != idCpu))
     2452        if (RT_LIKELY(pGipCpu->idCpu == idCpu))
     2453        { /* likely */ }
     2454        else
    23712455            return;
    23722456    }
     
    25532637        supdrvGipUpdate(pDevExt, NanoTS, u64TSC, idCpu, iTick);
    25542638    else
    2555         supdrvGipUpdatePerCpu(pDevExt, NanoTS, u64TSC, idCpu, ASMGetApicId(), iTick);
     2639        supdrvGipUpdatePerCpu(pDevExt, NanoTS, u64TSC, idCpu, supdrvGipGetApicId(pDevExt->pGip), iTick);
    25562640
    25572641    ASMSetFlags(fEFlags);
     
    48064890                /* This really shouldn't happen. */
    48074891                AssertMsgFailed(("idCpu=%#x iCpuSet=%#x (%d)\n", RTMpCpuId(), iCpuSet, iCpuSet));
    4808                 pReq->u.Out.idApic = ASMGetApicId();
     4892                pReq->u.Out.idApic = supdrvGipGetApicId(pGip);
    48094893                pReq->u.Out.u64AdjustedTsc = ASMReadTSC();
    48104894                ASMSetFlags(fEFlags);
     
    48264910            pReq->u.Out.idApic = pGip->aCPUs[iGipCpu].idApic;
    48274911        else
    4828             pReq->u.Out.idApic = ASMGetApicId();
     4912            pReq->u.Out.idApic = supdrvGipGetApicId(pGip);
    48294913        pReq->u.Out.u64AdjustedTsc = ASMReadTSC();
    48304914        ASMSetFlags(fEFlags);
  • trunk/src/VBox/HostDrivers/Support/SUPDrvIOC.h

    r80281 r81071  
    120120 * @note Implementations ASSUMES up to 32 I/O controls codes in the fast range.
    121121 * @{ */
    122 /** Fast path IOCtl: VMMR0_DO_RAW_RUN */
    123 #define SUP_IOCTL_FAST_DO_RAW_RUN               SUP_CTL_CODE_FAST(64)
    124122/** Fast path IOCtl: VMMR0_DO_HM_RUN */
    125 #define SUP_IOCTL_FAST_DO_HM_RUN                SUP_CTL_CODE_FAST(65)
     123#define SUP_IOCTL_FAST_DO_HM_RUN                SUP_CTL_CODE_FAST(64)
     124/** Fast path IOCtl: VMMR0_DO_NEM_RUN */
     125#define SUP_IOCTL_FAST_DO_NEM_RUN               SUP_CTL_CODE_FAST(65)
    126126/** Just a NOP call for profiling the latency of a fast ioctl call to VMMR0. */
    127127#define SUP_IOCTL_FAST_DO_NOP                   SUP_CTL_CODE_FAST(66)
    128 /** Fast path IOCtl: VMMR0_DO_NEM_RUN */
    129 #define SUP_IOCTL_FAST_DO_NEM_RUN               SUP_CTL_CODE_FAST(67)
    130128/** First fast path IOCtl number. */
    131 #define SUP_IOCTL_FAST_DO_FIRST                 SUP_IOCTL_FAST_DO_RAW_RUN
     129#define SUP_IOCTL_FAST_DO_FIRST                 SUP_IOCTL_FAST_DO_HM_RUN
    132130/** @} */
    133131
     
    224222 * @todo Pending work on next major version change:
    225223 *          - Move SUP_IOCTL_FAST_DO_NOP and SUP_VMMR0_DO_NEM_RUN after NEM.
    226  *
    227  * @remarks 0x002a0000 is used by 5.1. The next version number must be 0x002b0000.
    228  */
    229 #define SUPDRV_IOC_VERSION                              0x00290009
     224 */
     225#define SUPDRV_IOC_VERSION                              0x002b0000
    230226
    231227/** SUP_IOCTL_COOKIE. */
  • trunk/src/VBox/HostDrivers/Support/SUPLib.cpp

    r80281 r81071  
    613613{
    614614    NOREF(pVMR0);
    615     static const uintptr_t s_auFunctions[4] =
    616     {
    617         SUP_IOCTL_FAST_DO_RAW_RUN,
     615    static const uintptr_t s_auFunctions[3] =
     616    {
    618617        SUP_IOCTL_FAST_DO_HM_RUN,
     618        SUP_IOCTL_FAST_DO_NEM_RUN,
    619619        SUP_IOCTL_FAST_DO_NOP,
    620         SUP_IOCTL_FAST_DO_NEM_RUN
    621620    };
    622     AssertCompile(SUP_VMMR0_DO_RAW_RUN == 0);
    623     AssertCompile(SUP_VMMR0_DO_HM_RUN == 1);
     621    AssertCompile(SUP_VMMR0_DO_HM_RUN == 0);
     622    AssertCompile(SUP_VMMR0_DO_NEM_RUN == 1);
    624623    AssertCompile(SUP_VMMR0_DO_NOP     == 2);
    625     AssertCompile(SUP_VMMR0_DO_NEM_RUN == 3);
    626624    AssertMsgReturn(uOperation < RT_ELEMENTS(s_auFunctions), ("%#x\n", uOperation), VERR_INTERNAL_ERROR);
    627625    return suplibOsIOCtlFast(&g_supLibData, s_auFunctions[uOperation], idCpu);
     
    634632     * The following operations don't belong here.
    635633     */
    636     AssertMsgReturn(    uOperation != SUP_VMMR0_DO_RAW_RUN
    637                     &&  uOperation != SUP_VMMR0_DO_HM_RUN
     634    AssertMsgReturn(    uOperation != SUP_VMMR0_DO_HM_RUN
     635                    &&  uOperation != SUP_VMMR0_DO_NEM_RUN
    638636                    &&  uOperation != SUP_VMMR0_DO_NOP,
    639637                    ("%#x\n", uOperation),
     
    721719     * The following operations don't belong here.
    722720     */
    723     AssertMsgReturn(    uOperation != SUP_VMMR0_DO_RAW_RUN
    724                     &&  uOperation != SUP_VMMR0_DO_HM_RUN
     721    AssertMsgReturn(    uOperation != SUP_VMMR0_DO_HM_RUN
     722                    &&  uOperation != SUP_VMMR0_DO_NEM_RUN
    725723                    &&  uOperation != SUP_VMMR0_DO_NOP,
    726724                    ("%#x\n", uOperation),
  • trunk/src/VBox/HostDrivers/Support/SUPLibAll.cpp

    r76553 r81071  
    9292                iCpuSet &= RTCPUSET_MAX_CPUS - 1;
    9393                iGipCpu  = pGip->aiCpuFromCpuSetIdx[iCpuSet];
     94                break;
     95            }
     96            if (cTries >= 16)
     97            {
     98                iGipCpu = UINT16_MAX;
     99                break;
     100            }
     101            cTries++;
     102        }
     103    }
     104    else if (pGip->fGetGipCpu & SUPGIPGETCPU_APIC_ID_EXT_0B)
     105    {
     106        /* Get APIC ID / 0x1b via the slow CPUID instruction, requires looping. */
     107        uint32_t cTries = 0;
     108        for (;;)
     109        {
     110            uint32_t idApic = ASMGetApicIdExt0B();
     111            uTsc = ASMReadTSC();
     112            if (RT_LIKELY(ASMGetApicIdExt0B() == idApic))
     113            {
     114                iGipCpu = pGip->aiCpuFromApicId[idApic];
     115                break;
     116            }
     117            if (cTries >= 16)
     118            {
     119                iGipCpu = UINT16_MAX;
     120                break;
     121            }
     122            cTries++;
     123        }
     124    }
     125    else if (pGip->fGetGipCpu & SUPGIPGETCPU_APIC_ID_EXT_8000001E)
     126    {
     127        /* Get APIC ID / 0x8000001e via the slow CPUID instruction, requires looping. */
     128        uint32_t cTries = 0;
     129        for (;;)
     130        {
     131            uint32_t idApic = ASMGetApicIdExt8000001E();
     132            uTsc = ASMReadTSC();
     133            if (RT_LIKELY(ASMGetApicIdExt8000001E() == idApic))
     134            {
     135                iGipCpu = pGip->aiCpuFromApicId[idApic];
    94136                break;
    95137            }
     
    204246        iGipCpu   = pGip->aiCpuFromCpuSetIdx[iCpuSet];
    205247    }
     248    else if (pGip->fGetGipCpu & SUPGIPGETCPU_APIC_ID_EXT_0B)
     249    {
     250        /* Get APIC ID via the slow CPUID/0000000B instruction. */
     251        uint32_t idApic = ASMGetApicIdExt0B();
     252        iGipCpu = pGip->aiCpuFromApicId[idApic];
     253    }
     254    else if (pGip->fGetGipCpu & SUPGIPGETCPU_APIC_ID_EXT_8000001E)
     255    {
     256        /* Get APIC ID via the slow CPUID/8000001E instruction. */
     257        uint32_t idApic = ASMGetApicIdExt8000001E();
     258        iGipCpu = pGip->aiCpuFromApicId[idApic];
     259    }
    206260    else
    207261    {
Note: See TracChangeset for help on using the changeset viewer.

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