VirtualBox

Changeset 36254 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Mar 10, 2011 5:22:08 PM (14 years ago)
Author:
vboxsync
Message:

GIP,++: Lots of CPUs (disabled).

Location:
trunk/src/VBox
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostDrivers/Support/SUPDrv.c

    r36239 r36254  
    131131static DECLCALLBACK(void)   supdrvGipAsyncTimer(PRTTIMER pTimer, void *pvUser, uint64_t iTick);
    132132static DECLCALLBACK(void)   supdrvGipMpEvent(RTMPEVENT enmEvent, RTCPUID idCpu, void *pvUser);
    133 static void                 supdrvGipInit(PSUPDRVDEVEXT pDevExt, PSUPGLOBALINFOPAGE pGip, RTHCPHYS HCPhys, uint64_t u64NanoTS, unsigned uUpdateHz);
     133static void                 supdrvGipInit(PSUPDRVDEVEXT pDevExt, PSUPGLOBALINFOPAGE pGip, RTHCPHYS HCPhys,
     134                                          uint64_t u64NanoTS, unsigned uUpdateHz, unsigned cCpus);
     135static DECLCALLBACK(void)   supdrvGipInitOnCpu(RTCPUID idCpu, void *pvUser1, void *pvUser2);
    134136static void                 supdrvGipTerm(PSUPGLOBALINFOPAGE pGip);
    135 static void                 supdrvGipUpdate(PSUPGLOBALINFOPAGE pGip, uint64_t u64NanoTS, uint64_t u64TSC, uint64_t iTick);
    136 static void                 supdrvGipUpdatePerCpu(PSUPGLOBALINFOPAGE pGip, uint64_t u64NanoTS, uint64_t u64TSC, unsigned iCpu, uint64_t iTick);
     137static void                 supdrvGipUpdate(PSUPGLOBALINFOPAGE pGip, uint64_t u64NanoTS, uint64_t u64TSC, RTCPUID idCpu, uint64_t iTick);
     138static void                 supdrvGipUpdatePerCpu(PSUPGLOBALINFOPAGE pGip, uint64_t u64NanoTS, uint64_t u64TSC,
     139                                                  RTCPUID idCpu, uint8_t idApic, uint64_t iTick);
    137140
    138141
     
    289292    { "RTThreadUserWait",                       (void *)RTThreadUserWait },
    290293    { "RTThreadUserWaitNoResume",               (void *)RTThreadUserWaitNoResume },
    291 #else 
    292     /** 
    293      * @todo: remove me, once above code enabled. 
    294      * We need RTThreadCreate/RTThreadWait in the PCI driver. 
    295      */ 
    296     { "RTThreadCreate",                         (void *)RTThreadCreate }, 
    297     { "RTThreadWait",                           (void *)RTThreadWait }, 
     294#else
     295    /**
     296     * @todo: remove me, once above code enabled.
     297     * We need RTThreadCreate/RTThreadWait in the PCI driver.
     298     */
     299    { "RTThreadCreate",                         (void *)RTThreadCreate },
     300    { "RTThreadWait",                           (void *)RTThreadWait },
    298301#endif
    299302    { "RTThreadPreemptIsEnabled",               (void *)RTThreadPreemptIsEnabled },
     
    32133216{
    32143217    PSUPGLOBALINFOPAGE  pGip = (PSUPGLOBALINFOPAGE)pvUser1;
     3218#ifdef SUP_WITH_LOTS_OF_CPUS
     3219    unsigned            iCpu = pGip->aiCpuFromApicId[ASMGetApicId()];
     3220#else
    32153221    unsigned            iCpu = ASMGetApicId();
    3216 
     3222#endif
     3223
     3224#ifdef SUP_WITH_LOTS_OF_CPUS
     3225    if (RT_LIKELY(iCpu < pGip->cCpus && pGip->aCPUs[iCpu].idCpu == idCpu))
     3226#else
    32173227    if (RT_LIKELY(iCpu < RT_ELEMENTS(pGip->aCPUs)))
     3228#endif
    32183229        supdrvGipReInitCpu(&pGip->aCPUs[iCpu], *(uint64_t *)pvUser2);
    32193230
     
    48074818static int supdrvGipCreate(PSUPDRVDEVEXT pDevExt)
    48084819{
    4809     PSUPGLOBALINFOPAGE pGip;
    4810     RTHCPHYS HCPhysGip;
    4811     uint32_t u32SystemResolution;
    4812     uint32_t u32Interval;
    4813     int rc;
     4820    PSUPGLOBALINFOPAGE  pGip;
     4821    RTHCPHYS            HCPhysGip;
     4822    uint32_t            u32SystemResolution;
     4823    uint32_t            u32Interval;
     4824    unsigned            cCpus;
     4825    int                 rc;
     4826
    48144827
    48154828    LogFlow(("supdrvGipCreate:\n"));
     
    48214834
    48224835    /*
    4823      * Allocate a suitable page with a default kernel mapping.
    4824      */
    4825     rc = RTR0MemObjAllocLow(&pDevExt->GipMemObj, PAGE_SIZE, false);
     4836     * Check the CPU count.
     4837     */
     4838    cCpus = RTMpGetArraySize();
     4839#ifdef SUP_WITH_LOTS_OF_CPUS
     4840    if (   cCpus > RTCPUSET_MAX_CPUS
     4841        || cCpus > 256 /*uint8_t is used for the mappings*/)
     4842#else
     4843    if (cCpus > RT_ELEMENTS(pGip->aCPUs))
     4844#endif
     4845    {
     4846#ifdef SUP_WITH_LOTS_OF_CPUS
     4847        SUPR0Printf("VBoxDrv: Too many CPUs (%u) for the GIP (max %u)\n", cCpus, RT_MIN(RTCPUSET_MAX_CPUS, 256));
     4848#else
     4849        SUPR0Printf("VBoxDrv: Too many CPUs (%u) for the GIP (max %u)\n", cCpus, RT_MIN(RT_ELEMENTS(pGip->aCPUs), 256));
     4850#endif
     4851        return VERR_TOO_MANY_CPUS;
     4852    }
     4853
     4854    /*
     4855     * Allocate a contiguous set of pages with a default kernel mapping.
     4856     */
     4857#ifdef SUP_WITH_LOTS_OF_CPUS
     4858    rc = RTR0MemObjAllocCont(&pDevExt->GipMemObj, RT_UOFFSETOF(SUPGLOBALINFOPAGE, aCPUs[cCpus]), false /*fExecutable*/);
     4859#else
     4860    cCpus = RT_ELEMENTS(pGip->aCPUs);
     4861    rc = RTR0MemObjAllocLow(&pDevExt->GipMemObj, PAGE_SIZE, false /*fExecutable*/);
     4862#endif
    48264863    if (RT_FAILURE(rc))
    48274864    {
     
    48394876        u32Interval += u32SystemResolution;
    48404877
    4841     supdrvGipInit(pDevExt, pGip, HCPhysGip, RTTimeSystemNanoTS(), 1000000000 / u32Interval /*=Hz*/);
     4878    supdrvGipInit(pDevExt, pGip, HCPhysGip, RTTimeSystemNanoTS(), 1000000000 / u32Interval /*=Hz*/, cCpus);
    48424879
    48434880    /*
     
    48584895    if (RT_SUCCESS(rc))
    48594896    {
    4860         if (pGip->u32Mode == SUPGIPMODE_ASYNC_TSC)
    4861             rc = RTMpNotificationRegister(supdrvGipMpEvent, pDevExt);
     4897        rc = RTMpNotificationRegister(supdrvGipMpEvent, pDevExt);
    48624898        if (RT_SUCCESS(rc))
    48634899        {
    4864             /*
    4865              * We're good.
    4866              */
    4867             Log(("supdrvGipCreate: %ld ns interval.\n", (long)u32Interval));
    4868             g_pSUPGlobalInfoPage = pGip;
    4869             return VINF_SUCCESS;
    4870         }
    4871 
    4872         OSDBGPRINT(("supdrvGipCreate: failed register MP event notfication. rc=%d\n", rc));
     4900            rc = RTMpOnAll(supdrvGipInitOnCpu, pDevExt, pGip);
     4901            if (RT_SUCCESS(rc))
     4902            {
     4903                /*
     4904                 * We're good.
     4905                 */
     4906                Log(("supdrvGipCreate: %u ns interval.\n", u32Interval));
     4907                g_pSUPGlobalInfoPage = pGip;
     4908                return VINF_SUCCESS;
     4909            }
     4910
     4911            OSDBGPRINT(("supdrvGipCreate: RTMpOnAll failed with rc=%Rrc\n", rc));
     4912            RTMpNotificationDeregister(supdrvGipMpEvent, pDevExt);
     4913
     4914        }
     4915        else
     4916            OSDBGPRINT(("supdrvGipCreate: failed to register MP event notfication. rc=%Rrc\n", rc));
    48734917    }
    48744918    else
    48754919    {
    4876         OSDBGPRINT(("supdrvGipCreate: failed create GIP timer at %ld ns interval. rc=%d\n", (long)u32Interval, rc));
     4920        OSDBGPRINT(("supdrvGipCreate: failed create GIP timer at %u ns interval. rc=%Rrc\n", u32Interval, rc));
    48774921        Assert(!pDevExt->pGipTimer);
    48784922    }
     
    49454989    uint64_t        NanoTS    = RTTimeSystemNanoTS();
    49464990
    4947     supdrvGipUpdate(pDevExt->pGip, NanoTS, u64TSC, iTick);
     4991    supdrvGipUpdate(pDevExt->pGip, NanoTS, u64TSC, NIL_RTCPUID, iTick);
    49484992
    49494993    ASMSetFlags(fOldFlags);
     
    49665010    /** @todo reset the transaction number and whatnot when iTick == 1. */
    49675011    if (pDevExt->idGipMaster == idCpu)
    4968         supdrvGipUpdate(pDevExt->pGip, NanoTS, u64TSC, iTick);
     5012        supdrvGipUpdate(pDevExt->pGip, NanoTS, u64TSC, idCpu, iTick);
    49695013    else
    4970         supdrvGipUpdatePerCpu(pDevExt->pGip, NanoTS, u64TSC, ASMGetApicId(), iTick);
     5014        supdrvGipUpdatePerCpu(pDevExt->pGip, NanoTS, u64TSC, idCpu, ASMGetApicId(), iTick);
    49715015
    49725016    ASMSetFlags(fOldFlags);
     
    49755019
    49765020/**
     5021 * The calling CPU should be accounted as online, update GIP accordingly.
     5022 *
     5023 * This is used by supdrvGipMpEvent as well as the supdrvGipCreate.
     5024 *
     5025 * @param   pGip                The GIP.
     5026 * @param   idCpu               The CPU ID.
     5027 */
     5028static void supdrvGipMpEventOnline(PSUPGLOBALINFOPAGE pGip, RTCPUID idCpu)
     5029{
     5030#ifdef SUP_WITH_LOTS_OF_CPUS
     5031    int         iCpuSet;
     5032    uint8_t     idApic;
     5033    uint32_t    i;
     5034
     5035    Assert(idCpu == RTMpCpuId());
     5036    Assert(pGip->cPossibleCpus == RTMpGetCount());
     5037
     5038    /*
     5039     * Update the globals.
     5040     */
     5041    ASMAtomicWriteU32(&pGip->cPresentCpus,  RTMpGetPresentCount());
     5042    ASMAtomicWriteU32(&pGip->cOnlineCpus,   RTMpGetOnlineCount());
     5043    iCpuSet = RTMpCpuIdToSetIndex(idCpu);
     5044    if (iCpuSet >= 0)
     5045    {
     5046        Assert(RTCpuSetIsMemberByIndex(&pGip->PossibleCpuSet, iCpuSet));
     5047        RTCpuSetAddByIndex(&pGip->OnlineCpuSet, iCpuSet);
     5048        RTCpuSetAddByIndex(&pGip->PresentCpuSet, iCpuSet);
     5049    }
     5050
     5051    /*
     5052     * Find our entry, or allocate one if not found.
     5053     * ASSUMES that CPU IDs are constant.
     5054     */
     5055    for (i = 0; i < pGip->cCpus; i++)
     5056        if (pGip->aCPUs[i].idCpu == idCpu)
     5057            break;
     5058
     5059    if (i >= pGip->cCpus)
     5060        for (i = 0; i < pGip->cCpus; i++)
     5061        {
     5062            bool fRc;
     5063            ASMAtomicCmpXchgSize(&pGip->aCPUs[i].idCpu, idCpu, NIL_RTCPUID, fRc);
     5064            if (fRc)
     5065                break;
     5066        }
     5067
     5068    AssertReturnVoid(i < pGip->cCpus);
     5069
     5070    /*
     5071     * Update the entry.
     5072     */
     5073    idApic = ASMGetApicId();
     5074    ASMAtomicUoWriteU16(&pGip->aCPUs[i].idApic,  idApic);
     5075    ASMAtomicUoWriteS16(&pGip->aCPUs[i].iCpuSet, (int16_t)iCpuSet);
     5076    ASMAtomicUoWriteSize(&pGip->aCPUs[i].idCpu,  idCpu);
     5077    ASMAtomicWriteSize(&pGip->aCPUs[i].enmState, SUPGIPCPUSTATE_ONLINE);
     5078
     5079    /*
     5080     * Update the APIC ID and CPU set index mappings.
     5081     */
     5082    ASMAtomicWriteU16(&pGip->aiCpuFromApicId[idApic],     i);
     5083    ASMAtomicWriteU16(&pGip->aiCpuFromCpuSetIdx[iCpuSet], i);
     5084#endif
     5085}
     5086
     5087
     5088/**
     5089 * The CPU should be accounted as offline, update the GIP accordingly.
     5090 *
     5091 * This is used by supdrvGipMpEvent.
     5092 *
     5093 * @param   pGip                The GIP.
     5094 * @param   idCpu               The CPU ID.
     5095 */
     5096static void supdrvGipMpEventOffline(PSUPGLOBALINFOPAGE pGip, RTCPUID idCpu)
     5097{
     5098#ifdef SUP_WITH_LOTS_OF_CPUS
     5099    int         iCpuSet;
     5100    unsigned    i;
     5101
     5102    iCpuSet = RTMpCpuIdToSetIndex(idCpu);
     5103    AssertReturnVoid(iCpuSet >= 0);
     5104
     5105    i = pGip->aiCpuFromCpuSetIdx[iCpuSet];
     5106    AssertReturnVoid(i < pGip->cCpus);
     5107    AssertReturnVoid(pGip->aCPUs[i].idCpu == idCpu);
     5108
     5109    Assert(RTCpuSetIsMemberByIndex(&pGip->PossibleCpuSet, iCpuSet));
     5110    ASMAtomicWriteSize(&pGip->aCPUs[i].enmState, SUPGIPCPUSTATE_OFFLINE);
     5111    RTCpuSetDelByIndex(&pGip->OnlineCpuSet, iCpuSet);
     5112#endif
     5113}
     5114
     5115
     5116/**
    49775117 * Multiprocessor event notification callback.
    49785118 *
    4979  * This is used to make sue that the GIP master gets passed on to
    4980  * another CPU.
     5119 * This is used to make sure that the GIP master gets passed on to
     5120 * another CPU.  It also updates the associated CPU data.
    49815121 *
    49825122 * @param   enmEvent    The event.
     
    49865126static DECLCALLBACK(void) supdrvGipMpEvent(RTMPEVENT enmEvent, RTCPUID idCpu, void *pvUser)
    49875127{
    4988     PSUPDRVDEVEXT   pDevExt = (PSUPDRVDEVEXT)pvUser;
     5128    PSUPDRVDEVEXT       pDevExt = (PSUPDRVDEVEXT)pvUser;
     5129    PSUPGLOBALINFOPAGE  pGip    = pDevExt->pGip;
     5130
     5131    /*
     5132     * Update the GIP CPU data.
     5133     */
     5134    if (pGip)
     5135    {
     5136        switch (enmEvent)
     5137        {
     5138            case RTMPEVENT_ONLINE:
     5139                supdrvGipMpEventOnline(pGip, idCpu);
     5140                break;
     5141            case RTMPEVENT_OFFLINE:
     5142                supdrvGipMpEventOffline(pGip, idCpu);
     5143                break;
     5144
     5145        }
     5146    }
     5147
     5148    /*
     5149     * Make sure there is a master GIP.
     5150     */
    49895151    if (enmEvent == RTMPEVENT_OFFLINE)
    49905152    {
     
    51845346 * @param   u64NanoTS   The current nanosecond timestamp.
    51855347 * @param   uUpdateHz   The update frequency.
    5186  */
    5187 static void supdrvGipInit(PSUPDRVDEVEXT pDevExt, PSUPGLOBALINFOPAGE pGip, RTHCPHYS HCPhys, uint64_t u64NanoTS, unsigned uUpdateHz)
    5188 {
    5189     unsigned i;
     5348 * @param   cCpus       The CPU count.
     5349 */
     5350static void supdrvGipInit(PSUPDRVDEVEXT pDevExt, PSUPGLOBALINFOPAGE pGip, RTHCPHYS HCPhys,
     5351                          uint64_t u64NanoTS, unsigned uUpdateHz, unsigned cCpus)
     5352{
     5353    size_t const    cbGip = RT_ALIGN_Z(RT_OFFSETOF(SUPGLOBALINFOPAGE, aCPUs[cCpus]), PAGE_SIZE);
     5354    unsigned        i;
    51905355#ifdef DEBUG_DARWIN_GIP
    5191     OSDBGPRINT(("supdrvGipInit: pGip=%p HCPhys=%lx u64NanoTS=%llu uUpdateHz=%d\n", pGip, (long)HCPhys, u64NanoTS, uUpdateHz));
     5356    OSDBGPRINT(("supdrvGipInit: pGip=%p HCPhys=%lx u64NanoTS=%llu uUpdateHz=%d cCpus=%u\n", pGip, (long)HCPhys, u64NanoTS, uUpdateHz, cCpus));
    51925357#else
    5193     LogFlow(("supdrvGipInit: pGip=%p HCPhys=%lx u64NanoTS=%llu uUpdateHz=%d\n", pGip, (long)HCPhys, u64NanoTS, uUpdateHz));
     5358    LogFlow(("supdrvGipInit: pGip=%p HCPhys=%lx u64NanoTS=%llu uUpdateHz=%d cCpus=%u\n", pGip, (long)HCPhys, u64NanoTS, uUpdateHz, cCpus));
    51945359#endif
    51955360
     
    51975362     * Initialize the structure.
    51985363     */
    5199     memset(pGip, 0, PAGE_SIZE);
    5200     pGip->u32Magic          = SUPGLOBALINFOPAGE_MAGIC;
    5201     pGip->u32Version        = SUPGLOBALINFOPAGE_VERSION;
    5202     pGip->u32Mode           = supdrvGipDeterminTscMode(pDevExt);
    5203     pGip->u32UpdateHz       = uUpdateHz;
    5204     pGip->u32UpdateIntervalNS = 1000000000 / uUpdateHz;
     5364    memset(pGip, 0, cbGip);
     5365    pGip->u32Magic              = SUPGLOBALINFOPAGE_MAGIC;
     5366    pGip->u32Version            = SUPGLOBALINFOPAGE_VERSION;
     5367    pGip->u32Mode               = supdrvGipDeterminTscMode(pDevExt);
     5368#ifdef SUP_WITH_LOTS_OF_CPUS
     5369    pGip->cCpus                 = (uint16_t)cCpus;
     5370    pGip->cPages                = (uint16_t)(cbGip / PAGE_SIZE);
     5371#endif
     5372    pGip->u32UpdateHz           = uUpdateHz;
     5373    pGip->u32UpdateIntervalNS   = 1000000000 / uUpdateHz;
    52055374    pGip->u64NanoTSLastUpdateHz = u64NanoTS;
    5206 
    5207     for (i = 0; i < RT_ELEMENTS(pGip->aCPUs); i++)
     5375#ifdef SUP_WITH_LOTS_OF_CPUS
     5376    RTCpuSetEmpty(&pGip->OnlineCpuSet);
     5377    pGip->cOnlineCpus           = RTMpGetOnlineCount();
     5378    pGip->cPresentCpus          = RTMpGetPresentCount();
     5379    RTCpuSetEmpty(&pGip->PresentCpuSet);
     5380    RTMpGetSet(&pGip->PossibleCpuSet);
     5381    pGip->cPossibleCpus         = RTMpGetCount();
     5382    pGip->idCpuMax              = RTMpGetMaxCpuId();
     5383    for (i = 0; i < RT_ELEMENTS(pGip->aiCpuFromApicId); i++)
     5384        pGip->aiCpuFromApicId[i]    = 0;
     5385    for (i = 0; i < RT_ELEMENTS(pGip->aiCpuFromCpuSetIdx); i++)
     5386        pGip->aiCpuFromCpuSetIdx[i] = UINT16_MAX;
     5387#endif
     5388
     5389    for (i = 0; i < cCpus; i++)
    52085390    {
    52095391        pGip->aCPUs[i].u32TransactionId  = 2;
    52105392        pGip->aCPUs[i].u64NanoTS         = u64NanoTS;
    52115393        pGip->aCPUs[i].u64TSC            = ASMReadTSC();
     5394
     5395#ifdef SUP_WITH_LOTS_OF_CPUS
     5396        pGip->aCPUs[i].enmState          = SUPGIPCPUSTATE_INVALID;
     5397        pGip->aCPUs[i].idCpu             = NIL_RTCPUID;
     5398        pGip->aCPUs[i].iCpuSet           = -1;
     5399        pGip->aCPUs[i].idApic            = UINT8_MAX;
     5400#endif
    52125401
    52135402        /*
     
    52325421     * Link it to the device extension.
    52335422     */
    5234     pDevExt->pGip = pGip;
     5423    pDevExt->pGip      = pGip;
    52355424    pDevExt->HCPhysGip = HCPhys;
    52365425    pDevExt->cGipUsers = 0;
     5426}
     5427
     5428
     5429/**
     5430 * On CPU initialization callback for RTMpOnAll.
     5431 *
     5432 * @param   idCpu               The CPU ID.
     5433 * @param   pvUser1             The device extension.
     5434 * @param   pvUser2             The GIP.
     5435 */
     5436static DECLCALLBACK(void) supdrvGipInitOnCpu(RTCPUID idCpu, void *pvUser1, void *pvUser2)
     5437{
     5438    /* This is good enough, even though it will update some of the globals a
     5439       bit to much. */
     5440    supdrvGipMpEventOnline((PSUPGLOBALINFOPAGE)pvUser2, idCpu);
    52375441}
    52385442
     
    52815485     * Update the NanoTS.
    52825486     */
    5283     ASMAtomicXchgU64(&pGipCpu->u64NanoTS, u64NanoTS);
     5487    ASMAtomicWriteU64(&pGipCpu->u64NanoTS, u64NanoTS);
    52845488
    52855489    /*
     
    52885492    /** @todo validate the NanoTS delta, don't trust the OS to call us when it should... */
    52895493    u64TSCDelta = u64TSC - pGipCpu->u64TSC;
    5290     ASMAtomicXchgU64(&pGipCpu->u64TSC, u64TSC);
     5494    ASMAtomicWriteU64(&pGipCpu->u64TSC, u64TSC);
    52915495
    52925496    if (u64TSCDelta >> 32)
     
    53185522    Assert(RT_ELEMENTS(pGipCpu->au32TSCHistory) == 8);
    53195523    iTSCHistoryHead = (pGipCpu->iTSCHistoryHead + 1) & 7;
    5320     ASMAtomicXchgU32(&pGipCpu->iTSCHistoryHead, iTSCHistoryHead);
    5321     ASMAtomicXchgU32(&pGipCpu->au32TSCHistory[iTSCHistoryHead], (uint32_t)u64TSCDelta);
     5524    ASMAtomicWriteU32(&pGipCpu->iTSCHistoryHead, iTSCHistoryHead);
     5525    ASMAtomicWriteU32(&pGipCpu->au32TSCHistory[iTSCHistoryHead], (uint32_t)u64TSCDelta);
    53225526
    53235527    /*
     
    53595563        u32UpdateIntervalTSCSlack = u32UpdateIntervalTSC >> 6;
    53605564    }
    5361     ASMAtomicXchgU32(&pGipCpu->u32UpdateIntervalTSC, u32UpdateIntervalTSC + u32UpdateIntervalTSCSlack);
     5565    ASMAtomicWriteU32(&pGipCpu->u32UpdateIntervalTSC, u32UpdateIntervalTSC + u32UpdateIntervalTSCSlack);
    53625566
    53635567    /*
     
    53655569     */
    53665570    u64CpuHz = ASMMult2xU32RetU64(u32UpdateIntervalTSC, pGip->u32UpdateHz);
    5367     ASMAtomicXchgU64(&pGipCpu->u64CpuHz, u64CpuHz);
     5571    ASMAtomicWriteU64(&pGipCpu->u64CpuHz, u64CpuHz);
    53685572}
    53695573
     
    53755579 * @param   u64NanoTS       The current nanosecond timesamp.
    53765580 * @param   u64TSC          The current TSC timesamp.
     5581 * @param   idCpu           The CPU ID.
    53775582 * @param   iTick           The current timer tick.
    53785583 */
    5379 static void supdrvGipUpdate(PSUPGLOBALINFOPAGE pGip, uint64_t u64NanoTS, uint64_t u64TSC, uint64_t iTick)
     5584static void supdrvGipUpdate(PSUPGLOBALINFOPAGE pGip, uint64_t u64NanoTS, uint64_t u64TSC, RTCPUID idCpu, uint64_t iTick)
    53805585{
    53815586    /*
     
    53875592    else
    53885593    {
     5594#ifdef SUP_WITH_LOTS_OF_CPUS
     5595        unsigned iCpu = pGip->aiCpuFromApicId[ASMGetApicId()];
     5596        if (RT_UNLIKELY(iCpu >= pGip->cCpus))
     5597            return;
     5598        pGipCpu = &pGip->aCPUs[iCpu];
     5599        if (RT_UNLIKELY(pGipCpu->idCpu != idCpu))
     5600            return;
     5601#else
    53895602        unsigned iCpu = ASMGetApicId();
    53905603        if (RT_UNLIKELY(iCpu >= RT_ELEMENTS(pGip->aCPUs)))
    53915604            return;
    53925605        pGipCpu = &pGip->aCPUs[iCpu];
     5606#endif
    53935607    }
    53945608
     
    54175631            if (u32UpdateHz <= 2000 && u32UpdateHz >= 30)
    54185632            {
    5419                 ASMAtomicXchgU32(&pGip->u32UpdateHz, u32UpdateHz);
    5420                 ASMAtomicXchgU32(&pGip->u32UpdateIntervalNS, 1000000000 / u32UpdateHz);
     5633                ASMAtomicWriteU32(&pGip->u32UpdateHz, u32UpdateHz);
     5634                ASMAtomicWriteU32(&pGip->u32UpdateIntervalNS, 1000000000 / u32UpdateHz);
    54215635            }
    54225636#endif
    54235637        }
    5424         ASMAtomicXchgU64(&pGip->u64NanoTSLastUpdateHz, u64NanoTS);
     5638        ASMAtomicWriteU64(&pGip->u64NanoTSLastUpdateHz, u64NanoTS);
    54255639    }
    54265640
     
    54435657 * @param   u64NanoTS       The current nanosecond timesamp.
    54445658 * @param   u64TSC          The current TSC timesamp.
    5445  * @param   iCpu            The CPU index.
     5659 * @param   idCpu           The CPU ID.
     5660 * @param   idApic          The APIC id for the CPU index.
    54465661 * @param   iTick           The current timer tick.
    54475662 */
    5448 static void supdrvGipUpdatePerCpu(PSUPGLOBALINFOPAGE pGip, uint64_t u64NanoTS, uint64_t u64TSC, unsigned iCpu, uint64_t iTick)
    5449 {
    5450     PSUPGIPCPU  pGipCpu;
     5663static void supdrvGipUpdatePerCpu(PSUPGLOBALINFOPAGE pGip, uint64_t u64NanoTS, uint64_t u64TSC,
     5664                                  RTCPUID idCpu, uint8_t idApic, uint64_t iTick)
     5665{
     5666#ifdef SUP_WITH_LOTS_OF_CPUS
     5667    unsigned iCpu = pGip->aiCpuFromApicId[idApic];
     5668
     5669    if (RT_LIKELY(iCpu < pGip->cCpus))
     5670#else
     5671    unsigned iCpu = idApic;
    54515672
    54525673    if (RT_LIKELY(iCpu < RT_ELEMENTS(pGip->aCPUs)))
    5453     {
    5454         pGipCpu = &pGip->aCPUs[iCpu];
    5455 
    5456         /*
    5457          * Start update transaction.
    5458          */
    5459         if (!(ASMAtomicIncU32(&pGipCpu->u32TransactionId) & 1))
    5460         {
    5461             AssertMsgFailed(("Invalid transaction id, %#x, not odd!\n", pGipCpu->u32TransactionId));
     5674#endif
     5675    {
     5676        PSUPGIPCPU pGipCpu = &pGip->aCPUs[iCpu];
     5677#ifdef SUP_WITH_LOTS_OF_CPUS
     5678        if (pGipCpu->idCpu == idCpu)
     5679#endif
     5680        {
     5681
     5682            /*
     5683             * Start update transaction.
     5684             */
     5685            if (!(ASMAtomicIncU32(&pGipCpu->u32TransactionId) & 1))
     5686            {
     5687                AssertMsgFailed(("Invalid transaction id, %#x, not odd!\n", pGipCpu->u32TransactionId));
     5688                ASMAtomicIncU32(&pGipCpu->u32TransactionId);
     5689                pGipCpu->cErrors++;
     5690                return;
     5691            }
     5692
     5693            /*
     5694             * Update the data.
     5695             */
     5696            supdrvGipDoUpdateCpu(pGip, pGipCpu, u64NanoTS, u64TSC, iTick);
     5697
     5698            /*
     5699             * Complete transaction.
     5700             */
    54625701            ASMAtomicIncU32(&pGipCpu->u32TransactionId);
    5463             pGipCpu->cErrors++;
    5464             return;
    5465         }
    5466 
    5467         /*
    5468          * Update the data.
    5469          */
    5470         supdrvGipDoUpdateCpu(pGip, pGipCpu, u64NanoTS, u64TSC, iTick);
    5471 
    5472         /*
    5473          * Complete transaction.
    5474          */
    5475         ASMAtomicIncU32(&pGipCpu->u32TransactionId);
    5476     }
    5477 }
     5702        }
     5703    }
     5704}
  • trunk/src/VBox/HostDrivers/Support/freebsd/Makefile

    r33379 r36254  
    133133        RTSemEventMultiWaitNoResume-2-ex-generic.c \
    134134        RTTimerCreate-generic.c \
    135         timer-generic.c \
    136         mppresent-generic.c
     135        mppresent-generic.c \
     136        timer-generic.c
    137137
    138138.PATH:  ${.CURDIR}/r0drv
  • trunk/src/VBox/HostDrivers/Support/freebsd/files_vboxdrv

    r36190 r36254  
    158158    ${PATH_ROOT}/src/VBox/Runtime/generic/RTTimerCreate-generic.cpp=>generic/RTTimerCreate-generic.c \
    159159    ${PATH_ROOT}/src/VBox/Runtime/generic/RTMpGetArraySize-generic.cpp=>generic/RTMpGetArraySize-generic.c \
     160    ${PATH_ROOT}/src/VBox/Runtime/generic/mppresent-generic.cpp=>generic/mppresent-generic.c \
    160161    ${PATH_ROOT}/src/VBox/Runtime/generic/timer-generic.cpp=>generic/timer-generic.c \
    161     ${PATH_ROOT}/src/VBox/Runtime/generic/mppresent-generic.cpp=>generic/mppresent-generic.c \
    162162    ${PATH_ROOT}/src/VBox/Runtime/r0drv/alloc-r0drv.cpp=>r0drv/alloc-r0drv.c \
    163163    ${PATH_ROOT}/src/VBox/Runtime/r0drv/alloc-r0drv.h=>r0drv/alloc-r0drv.h \
  • trunk/src/VBox/HostDrivers/Support/linux/Makefile

    r36233 r36254  
    138138        generic/RTSemEventMultiWaitNoResume-2-ex-generic.o \
    139139        generic/RTTimerCreate-generic.o \
     140        generic/mppresent-generic.o \
    140141        generic/uuid-generic.o \
    141142        VBox/log-vbox.o
  • trunk/src/VBox/HostDrivers/Support/linux/files_vboxdrv

    r36233 r36254  
    146146    ${PATH_ROOT}/src/VBox/Runtime/generic/RTSemEventMultiWaitNoResume-2-ex-generic.cpp=>generic/RTSemEventMultiWaitNoResume-2-ex-generic.c \
    147147    ${PATH_ROOT}/src/VBox/Runtime/generic/RTTimerCreate-generic.cpp=>generic/RTTimerCreate-generic.c \
     148    ${PATH_ROOT}/src/VBox/Runtime/generic/mppresent-generic.cpp=>generic/mppresent-generic.c \
    148149    ${PATH_ROOT}/src/VBox/Runtime/generic/uuid-generic.cpp=>generic/uuid-generic.c \
    149150    ${PATH_ROOT}/src/VBox/Runtime/r0drv/alloc-r0drv.cpp=>r0drv/alloc-r0drv.c \
  • trunk/src/VBox/Runtime/common/time/timesupA.mac

    r36220 r36254  
    9595    mov     u32ApicIdPlus, ebx
    9696 %endif
    97     ; pGipCpu = &pGip->aCPU[u8ApicId];
     97    ; pGipCpu = &pGip->aCPU[pGip->aiCpuFromApicId[u8ApicId]];
    9898    shr     ebx, 24
     99 %ifdef SUP_WITH_LOTS_OF_CPUS
     100    movzx   ebx, word [esi + ebx * 2 + SUPGLOBALINFOPAGE.aiCpuFromApicId]
     101 %else
     102    and     ebx, SUPGLOBALINFOPAGE_CPUS - 1
     103 %endif
    99104    mov     eax, SUPGIPCPU_size
    100105    mul     ebx
     
    516521    mov     u32ApicIdPlus, ebx
    517522 %endif
    518     ; pGipCpu = &pGip->aCPU[u8ApicId];
     523    ; pGipCpu = &pGip->aCPU[pGip->aiCpuFromApicId[u8ApicId]];
    519524    shr     ebx, 24
     525 %ifdef SUP_WITH_LOTS_OF_CPUS
     526    movzx   eax, word [pGip + rbx * 2 + SUPGLOBALINFOPAGE.aiCpuFromApicId]
     527 %else
    520528    mov     eax, ebx
    521  %if SUPGLOBALINFOPAGE_CPUS < 256
    522529    and     eax, SUPGLOBALINFOPAGE_CPUS - 1
    523530 %endif
  • trunk/src/VBox/Runtime/common/time/timesupref.h

    r36220 r36254  
    6363
    6464#ifdef ASYNC_GIP
    65         uint8_t u8ApicId = ASMGetApicId();
    66 # if SUPGLOBALINFOPAGE_CPUS < 256
    67         PSUPGIPCPU pGipCpu = &pGip->aCPUs[u8ApicId & SUPGLOBALINFOPAGE_CPUS];
     65        uint8_t    u8ApicId = ASMGetApicId();
     66# ifdef SUP_WITH_LOTS_OF_CPUS
     67        PSUPGIPCPU pGipCpu = &pGip->aCPUs[pGip->aiCpuFromApicId[u8ApicId]];
    6868# else
    69         PSUPGIPCPU pGipCpu = &pGip->aCPUs[u8ApicId];
     69        PSUPGIPCPU pGipCpu = &pGip->aCPUs[u8ApicId & (SUPGLOBALINFOPAGE_CPUS - 1)];
    7070# endif
    7171#else
  • trunk/src/VBox/Runtime/generic/RTMpGetArraySize-generic.cpp

    r33676 r36254  
    55
    66/*
    7  * Copyright (C) 2010 Oracle Corporation
     7 * Copyright (C) 2010-2011 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    3030*******************************************************************************/
    3131#include <iprt/mp.h>
     32#include "internal/iprt.h"
     33
     34#include <iprt/asm.h>
    3235#include <iprt/cpuset.h>
    33 #include "internal/iprt.h"
    3436
    3537
    3638RTDECL(uint32_t) RTMpGetArraySize(void)
    3739{
    38     RTCPUSET    CpuSet;
    39     return RTCpuLastIndex(RTMpGetSet(&CpuSet)) + 1;
     40    /*
     41     * Cache the result here.  This whole point of this function is that it
     42     * will always return the same value, so that should be safe.
     43     *
     44     * Note! Because RTCPUSET may be to small to represent all the CPUs, we
     45     *       check with RTMpGetCount() as well.
     46     */
     47    static uint32_t s_cMaxCpus = 0;
     48    uint32_t cCpus = s_cMaxCpus;
     49    if (RT_UNLIKELY(cCpus == 0))
     50    {
     51        RTCPUSET    CpuSet;
     52        uint32_t    cCpus1 = RTCpuLastIndex(RTMpGetSet(&CpuSet)) + 1;
     53        uint32_t    cCpus2 = RTMpGetCount();
     54        uint32_t    cCpus  = RT_MAX(cCpus1, cCpus2);
     55        ASMAtomicCmpXchgU32(&s_cMaxCpus, cCpus, 0);
     56        return cCpus;
     57    }
     58    return s_cMaxCpus;
     59
    4060}
    4161RT_EXPORT_SYMBOL(RTMpGetArraySize);
  • trunk/src/VBox/VMM/VMMR3/TM.cpp

    r35346 r36254  
    122122#define LOG_GROUP LOG_GROUP_TM
    123123#include <VBox/vmm/tm.h>
     124#include <iprt/asm-amd64-x86.h> /* for SUPGetCpuHzFromGIP from sup.h  */
    124125#include <VBox/vmm/vmm.h>
    125126#include <VBox/vmm/mm.h>
     
    139140#include <iprt/asm.h>
    140141#include <iprt/asm-math.h>
    141 #include <iprt/asm-amd64-x86.h>
    142142#include <iprt/assert.h>
    143143#include <iprt/thread.h>
     
    222222    pVM->tm.s.pvGIPR3 = (void *)g_pSUPGlobalInfoPage;
    223223    AssertMsgReturn(pVM->tm.s.pvGIPR3, ("GIP support is now required!\n"), VERR_INTERNAL_ERROR);
     224    AssertMsgReturn((g_pSUPGlobalInfoPage->u32Version >> 16) == (SUPGLOBALINFOPAGE_VERSION >> 16),
     225                    ("Unsupported GIP version!\n"), VERR_INTERNAL_ERROR);
     226
    224227    RTHCPHYS HCPhysGIP;
    225228    rc = SUPR3GipGetPhys(&HCPhysGIP);
     
    227230
    228231    RTGCPTR GCPtr;
     232#ifdef SUP_WITH_LOTS_OF_CPUS
     233    rc = MMR3HyperMapHCPhys(pVM, pVM->tm.s.pvGIPR3, NIL_RTR0PTR, HCPhysGIP, (size_t)g_pSUPGlobalInfoPage->cPages * PAGE_SIZE,
     234                            "GIP", &GCPtr);
     235#else
    229236    rc = MMR3HyperMapHCPhys(pVM, pVM->tm.s.pvGIPR3, NIL_RTR0PTR, HCPhysGIP, PAGE_SIZE, "GIP", &GCPtr);
     237#endif
    230238    if (RT_FAILURE(rc))
    231239    {
     
    795803     * Use GIP when available present.
    796804     */
    797     uint64_t    u64Hz;
    798     PSUPGLOBALINFOPAGE pGip = g_pSUPGlobalInfoPage;
    799     if (    pGip
    800         &&  pGip->u32Magic == SUPGLOBALINFOPAGE_MAGIC)
    801     {
    802         unsigned iCpu = pGip->u32Mode != SUPGIPMODE_ASYNC_TSC ? 0 : ASMGetApicId();
    803         if (iCpu >= RT_ELEMENTS(pGip->aCPUs))
    804             AssertReleaseMsgFailed(("iCpu=%d - the ApicId is too high. send VBox.log and hardware specs!\n", iCpu));
     805    uint64_t u64Hz = SUPGetCpuHzFromGIP(g_pSUPGlobalInfoPage);
     806    if (u64Hz != UINT64_MAX)
     807    {
     808        if (tmR3HasFixedTSC(pVM))
     809            /* Sleep a bit to get a more reliable CpuHz value. */
     810            RTThreadSleep(32);
    805811        else
    806812        {
    807             if (tmR3HasFixedTSC(pVM))
    808                 /* Sleep a bit to get a more reliable CpuHz value. */
    809                 RTThreadSleep(32);
    810             else
    811             {
    812                 /* Spin for 40ms to try push up the CPU frequency and get a more reliable CpuHz value. */
    813                 const uint64_t u64 = RTTimeMilliTS();
    814                 while ((RTTimeMilliTS() - u64) < 40 /*ms*/)
    815                     /* nothing */;
    816             }
    817 
    818             pGip = g_pSUPGlobalInfoPage;
    819             if (    pGip
    820                 &&  pGip->u32Magic == SUPGLOBALINFOPAGE_MAGIC
    821                 &&  (u64Hz = pGip->aCPUs[iCpu].u64CpuHz)
    822                 &&  u64Hz != ~(uint64_t)0)
    823                 return u64Hz;
     813            /* Spin for 40ms to try push up the CPU frequency and get a more reliable CpuHz value. */
     814            const uint64_t u64 = RTTimeMilliTS();
     815            while ((RTTimeMilliTS() - u64) < 40 /*ms*/)
     816                /* nothing */;
    824817        }
     818
     819        u64Hz = SUPGetCpuHzFromGIP(g_pSUPGlobalInfoPage);
     820        if (u64Hz != UINT64_MAX)
     821            return u64Hz;
    825822    }
    826823
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