VirtualBox

Changeset 53087 in vbox for trunk


Ignore:
Timestamp:
Oct 17, 2014 2:18:50 PM (11 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
96606
Message:

HostDrivers/Support: Add code for measuring nominal TSC frequency using a busy-wait method.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/err.h

    r53035 r53087  
    17691769/** Failed to measure the TSC delta between two CPUs. */
    17701770#define VERR_SUPDRV_TSC_DELTA_MEASUREMENT_FAILED    (-3743)
     1771/** Failed to calculate the TSC frequency. */
     1772#define VERR_SUPDRV_TSC_FREQ_MEASUREMENT_FAILED     (-3744)
    17711773/** @} */
    17721774
  • trunk/src/VBox/HostDrivers/Support/SUPDrv.c

    r53085 r53087  
    59085908
    59095909/**
     5910 * Measures the nominal TSC frequency.
     5911 *
     5912 * Uses a busy-wait method for the async. case as it is intended to help push
     5913 * the CPU frequency up, while for the invariant cases using a sleeping method.
     5914 *
     5915 * @returns VBox status code.
     5916 * @param   pGip        Pointer to the GIP.
     5917 *
     5918 * @remarks Must be called only after measuring the TSC deltas.
     5919 */
     5920static int supdrvGipMeasureNominalTscFreq(PSUPGLOBALINFOPAGE pGip)
     5921{
     5922    int cTriesLeft = 4;
     5923    AssertReturn(pGip, VERR_INVALID_PARAMETER);
     5924    AssertReturn(pGip->u32Magic == SUPGLOBALINFOPAGE_MAGIC, VERR_WRONG_ORDER);
     5925
     5926    while (cTriesLeft-- > 0)
     5927    {
     5928        RTCCUINTREG uFlags;
     5929        uint64_t    u64NanoTS;
     5930        uint64_t    u64Before;
     5931        uint64_t    u64After;
     5932        uint8_t     idApicBefore;
     5933        uint8_t     idApicAfter;
     5934        PSUPGIPCPU  pGipCpuBefore;
     5935        PSUPGIPCPU  pGipCpuAfter;
     5936        uint16_t    iCpuBefore;
     5937        uint16_t    iCpuAfter;
     5938
     5939        uFlags = ASMIntDisableFlags();
     5940        idApicBefore = ASMGetApicId();
     5941        ASMSerializeInstruction();
     5942        u64Before = ASMReadTSC();
     5943        ASMSetFlags(uFlags);
     5944        u64NanoTS = RTTimeSystemNanoTS();
     5945
     5946        /** @todo change this to non-busy wait for invariant case. */
     5947        while (RTTimeSystemNanoTS() < RT_NS_10MS + u64NanoTS)
     5948            ;
     5949
     5950        uFlags = ASMIntDisableFlags();
     5951        u64After = ASMReadTSC();
     5952        idApicAfter = ASMGetApicId();
     5953        ASMSetFlags(uFlags);
     5954
     5955        iCpuBefore = pGip->aiCpuFromApicId[idApicBefore];
     5956        iCpuAfter  = pGip->aiCpuFromApicId[idApicAfter];
     5957        AssertMsg(iCpuBefore < pGip->cCpus, ("iCpuBefore=%u cCpus=%u\n", iCpuBefore, pGip->cCpus));
     5958        AssertMsg(iCpuAfter  < pGip->cCpus, ("iCpuAfter=%u cCpus=%u\n", iCpuAfter, pGip->cCpus));
     5959        pGipCpuBefore = &pGip->aCPUs[iCpuBefore];
     5960        pGipCpuAfter  = &pGip->aCPUs[iCpuAfter];
     5961
     5962        /** @todo replace with enum check. */
     5963        if (supdrvIsInvariantTsc())
     5964        {
     5965            if (   pGipCpuBefore->i64TSCDelta != INT64_MAX
     5966                && pGipCpuAfter->i64TSCDelta  != INT64_MAX)
     5967            {
     5968                u64Before += pGipCpuBefore->i64TSCDelta;
     5969                u64After  += pGipCpuAfter->i64TSCDelta;
     5970
     5971                SUPR0Printf("vboxdrv: TSC frequency is (%'RU64) Hz, kernel timer granularity is (%RU32) Ns\n",
     5972                            (u64After - u64Before) * 100, RTTimerGetSystemGranularity());
     5973                return VINF_SUCCESS;
     5974            }
     5975            else
     5976            {
     5977                SUPR0Printf("vboxdrv: supdrvGipMeasureNominalTscFreq: iCpuBefore=%u iCpuAfter=%u cTriesLeft=%u\n", iCpuBefore,
     5978                            iCpuAfter, cTriesLeft);
     5979            }
     5980        }
     5981        else
     5982        {
     5983            SUPR0Printf("vboxdrv: TSC frequency is (%'RU64) Hz, kernel timer granularity is (%RU32) Ns\n",
     5984                        (u64After - u64Before) * 100, RTTimerGetSystemGranularity());
     5985            return VINF_SUCCESS;
     5986        }
     5987    }
     5988
     5989    return VERR_SUPDRV_TSC_FREQ_MEASUREMENT_FAILED;
     5990}
     5991
     5992
     5993/**
    59105994 * Creates the GIP.
    59115995 *
     
    59956079                for (iCpu = 0; iCpu < pGip->cCpus; iCpu++)
    59966080                    Log(("supdrvTscDeltaInit: cpu[%u] delta %lld\n", iCpu, pGip->aCPUs[iCpu].i64TSCDelta));
     6081#endif
     6082
     6083#if 0
     6084                /** @todo refactor later and use the nominal TSC rate for invariant case as
     6085                 *        the real and constant TSC rate. */
     6086                supdrvGipMeasureNominalTscFreq(pGip);
    59976087#endif
    59986088
     
    61306220         * affected a bit until we get proper TSC deltas than implementing options like
    61316221         * rescheduling the tick to be delivered on the right CPU or missing the tick entirely.
     6222         *
     6223         * The likely hood of this happening is really low. On Windows, Linux timers
     6224         * fire on the CPU they were registered/started on. Darwin, Solaris need verification.
    61326225         */
    61336226        if (pGipCpu->i64TSCDelta != INT64_MAX)
     
    62646357     * update the state and it'll get serviced when the thread's listening interval times out.
    62656358     */
    6266     RTCpuSetAdd(&pDevExt->TscDeltaCpuSet, idCpu);
    6267     RTSpinlockAcquire(pDevExt->hTscDeltaSpinlock);
    6268     if (   pDevExt->enmTscDeltaState == kSupDrvTscDeltaState_Listening
    6269         || pDevExt->enmTscDeltaState == kSupDrvTscDeltaState_Measuring)
    6270     {
    6271         pDevExt->enmTscDeltaState = kSupDrvTscDeltaState_WaitAndMeasure;
    6272     }
    6273     RTSpinlockRelease(pDevExt->hTscDeltaSpinlock);
     6359    if (supdrvIsInvariantTsc())
     6360    {
     6361        RTCpuSetAdd(&pDevExt->TscDeltaCpuSet, idCpu);
     6362        RTSpinlockAcquire(pDevExt->hTscDeltaSpinlock);
     6363        if (   pDevExt->enmTscDeltaState == kSupDrvTscDeltaState_Listening
     6364            || pDevExt->enmTscDeltaState == kSupDrvTscDeltaState_Measuring)
     6365        {
     6366            pDevExt->enmTscDeltaState = kSupDrvTscDeltaState_WaitAndMeasure;
     6367        }
     6368        RTSpinlockRelease(pDevExt->hTscDeltaSpinlock);
     6369    }
    62746370#endif
    62756371
     
    74567552#endif
    74577553
    7458             while (!cTries--)
     7554            while (cTries--)
    74597555            {
    74607556                rc = supdrvMeasureTscDeltaOne(pDevExt, iCpu);
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