VirtualBox

Ignore:
Timestamp:
Feb 22, 2015 2:36:45 PM (10 years ago)
Author:
vboxsync
Message:

docs.

File:
1 edited

Legend:

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

    r54354 r54355  
    768768 */
    769769
     770/**
     771 * Used by supdrvInitRefineInvariantTscFreqTimer and supdrvGipInitMeasureTscFreq
     772 * to update the TSC frequency related GIP variables.
     773 *
     774 * @param   pGip                The GIP.
     775 * @param   nsElapsed           The number of nano seconds elapsed.
     776 * @param   cElapsedTscTicks    The corresponding number of TSC ticks.
     777 */
    770778static void supdrvGipInitSetCpuFreq(PSUPGLOBALINFOPAGE pGip, uint64_t nsElapsed, uint64_t cElapsedTscTicks)
    771779{
     
    805813 * @param   iTick       The timer tick.
    806814 */
    807 static DECLCALLBACK(void) supdrvInitRefineInvariantTscTimer(PRTTIMER pTimer, void *pvUser, uint64_t iTick)
     815static DECLCALLBACK(void) supdrvInitRefineInvariantTscFreqTimer(PRTTIMER pTimer, void *pvUser, uint64_t iTick)
    808816{
    809817    PSUPDRVDEVEXT       pDevExt = (PSUPDRVDEVEXT)pvUser;
     
    937945 * @param   pDevExt         Pointer to the device instance data.
    938946 * @param   pGip            Pointer to the GIP.
    939  *
    940  * @remarks We cannot use this
    941947 */
    942948static void supdrvGipInitStartTimerForRefiningInvariantTscFreq(PSUPDRVDEVEXT pDevExt, PSUPGLOBALINFOPAGE pGip)
     
    983989    rc = RTTimerCreateEx(&pDevExt->pInvarTscRefineTimer, 0 /* one-shot */,
    984990                         RTTIMER_FLAGS_CPU(RTMpCpuIdToSetIndex(pDevExt->idCpuInvarTscRefine)),
    985                          supdrvInitRefineInvariantTscTimer, pDevExt);
     991                         supdrvInitRefineInvariantTscFreqTimer, pDevExt);
    986992    if (RT_SUCCESS(rc))
    987993    {
     
    9951001    {
    9961002        rc = RTTimerCreateEx(&pDevExt->pInvarTscRefineTimer, 0 /* one-shot */, RTTIMER_FLAGS_CPU_ANY,
    997                              supdrvInitRefineInvariantTscTimer, pDevExt);
     1003                             supdrvInitRefineInvariantTscFreqTimer, pDevExt);
    9981004        if (RT_SUCCESS(rc))
    9991005        {
     
    11521158            else if (pGip->u32Mode == SUPGIPMODE_INVARIANT_TSC)
    11531159            {
     1160/** @todo This section of code is never reached atm, consider dropping it later on... */
    11541161                if (pGip->enmUseTscDelta > SUPGIPUSETSCDELTA_ZERO_CLAIMED)
    11551162                {
     
    21302137    ASMAtomicWriteU64(&pGipCpu->u64TSC, u64TSC);
    21312138
    2132     /* We don't need to keep realculating the frequency when it's invariant. */
    2133     if (pGip->u32Mode == SUPGIPMODE_INVARIANT_TSC)
    2134         return;
    2135 
    2136     if (u64TSCDelta >> 32)
    2137     {
    2138         u64TSCDelta = pGipCpu->u32UpdateIntervalTSC;
    2139         pGipCpu->cErrors++;
    2140     }
    2141 
    2142     /*
    2143      * On the 2nd and 3rd callout, reset the history with the current TSC
    2144      * interval since the values entered by supdrvGipInit are totally off.
    2145      * The interval on the 1st callout completely unreliable, the 2nd is a bit
    2146      * better, while the 3rd should be most reliable.
    2147      */
    2148     u32TransactionId = pGipCpu->u32TransactionId;
    2149     if (RT_UNLIKELY(   (   u32TransactionId == 5
    2150                         || u32TransactionId == 7)
    2151                     && (   iTick == 2
    2152                         || iTick == 3) ))
    2153     {
    2154         unsigned i;
    2155         for (i = 0; i < RT_ELEMENTS(pGipCpu->au32TSCHistory); i++)
    2156             ASMAtomicUoWriteU32(&pGipCpu->au32TSCHistory[i], (uint32_t)u64TSCDelta);
    2157     }
    2158 
    2159     /*
    2160      * Validate the NanoTS deltas between timer fires with an arbitrary threshold of 0.5%.
    2161      * Wait until we have at least one full history since the above history reset. The
    2162      * assumption is that the majority of the previous history values will be tolerable.
    2163      * See @bugref{6710} comment #67.
    2164      */
    2165     if (   u32TransactionId > 23 /* 7 + (8 * 2) */
    2166         && pGip->u32Mode != SUPGIPMODE_ASYNC_TSC)
    2167     {
    2168         uint32_t uNanoTsThreshold = pGip->u32UpdateIntervalNS / 200;
    2169         if (   pGipCpu->u32PrevUpdateIntervalNS > pGip->u32UpdateIntervalNS + uNanoTsThreshold
    2170             || pGipCpu->u32PrevUpdateIntervalNS < pGip->u32UpdateIntervalNS - uNanoTsThreshold)
     2139    /*
     2140     * We don't need to keep realculating the frequency when it's invariant, so
     2141     * the remainder of this function is only for the sync and async TSC modes.
     2142     */
     2143    if (pGip->u32Mode != SUPGIPMODE_INVARIANT_TSC)
     2144    {
     2145        if (u64TSCDelta >> 32)
     2146        {
     2147            u64TSCDelta = pGipCpu->u32UpdateIntervalTSC;
     2148            pGipCpu->cErrors++;
     2149        }
     2150
     2151        /*
     2152         * On the 2nd and 3rd callout, reset the history with the current TSC
     2153         * interval since the values entered by supdrvGipInit are totally off.
     2154         * The interval on the 1st callout completely unreliable, the 2nd is a bit
     2155         * better, while the 3rd should be most reliable.
     2156         */
     2157        /** @todo Could we drop this now that we initializes the history
     2158         *        with nominal TSC frequency values? */
     2159        u32TransactionId = pGipCpu->u32TransactionId;
     2160        if (RT_UNLIKELY(   (   u32TransactionId == 5
     2161                            || u32TransactionId == 7)
     2162                        && (   iTick == 2
     2163                            || iTick == 3) ))
     2164        {
     2165            unsigned i;
     2166            for (i = 0; i < RT_ELEMENTS(pGipCpu->au32TSCHistory); i++)
     2167                ASMAtomicUoWriteU32(&pGipCpu->au32TSCHistory[i], (uint32_t)u64TSCDelta);
     2168        }
     2169
     2170        /*
     2171         * Validate the NanoTS deltas between timer fires with an arbitrary threshold of 0.5%.
     2172         * Wait until we have at least one full history since the above history reset. The
     2173         * assumption is that the majority of the previous history values will be tolerable.
     2174         * See @bugref{6710} comment #67.
     2175         */
     2176        /** @todo Could we drop the fuding there now that we initializes the history
     2177         *        with nominal TSC frequency values?  */
     2178        if (   u32TransactionId > 23 /* 7 + (8 * 2) */
     2179            && pGip->u32Mode != SUPGIPMODE_ASYNC_TSC)
     2180        {
     2181            uint32_t uNanoTsThreshold = pGip->u32UpdateIntervalNS / 200;
     2182            if (   pGipCpu->u32PrevUpdateIntervalNS > pGip->u32UpdateIntervalNS + uNanoTsThreshold
     2183                || pGipCpu->u32PrevUpdateIntervalNS < pGip->u32UpdateIntervalNS - uNanoTsThreshold)
     2184            {
     2185                uint32_t u32;
     2186                u32  = pGipCpu->au32TSCHistory[0];
     2187                u32 += pGipCpu->au32TSCHistory[1];
     2188                u32 += pGipCpu->au32TSCHistory[2];
     2189                u32 += pGipCpu->au32TSCHistory[3];
     2190                u32 >>= 2;
     2191                u64TSCDelta  = pGipCpu->au32TSCHistory[4];
     2192                u64TSCDelta += pGipCpu->au32TSCHistory[5];
     2193                u64TSCDelta += pGipCpu->au32TSCHistory[6];
     2194                u64TSCDelta += pGipCpu->au32TSCHistory[7];
     2195                u64TSCDelta >>= 2;
     2196                u64TSCDelta += u32;
     2197                u64TSCDelta >>= 1;
     2198            }
     2199        }
     2200
     2201        /*
     2202         * TSC History.
     2203         */
     2204        Assert(RT_ELEMENTS(pGipCpu->au32TSCHistory) == 8);
     2205        iTSCHistoryHead = (pGipCpu->iTSCHistoryHead + 1) & 7;
     2206        ASMAtomicWriteU32(&pGipCpu->iTSCHistoryHead, iTSCHistoryHead);
     2207        ASMAtomicWriteU32(&pGipCpu->au32TSCHistory[iTSCHistoryHead], (uint32_t)u64TSCDelta);
     2208
     2209        /*
     2210         * UpdateIntervalTSC = average of last 8,2,1 intervals depending on update HZ.
     2211         *
     2212         * On Windows, we have an occasional (but recurring) sour value that messed up
     2213         * the history but taking only 1 interval reduces the precision overall.
     2214         */
     2215        if (   pGip->u32Mode == SUPGIPMODE_INVARIANT_TSC
     2216            || pGip->u32UpdateHz >= 1000)
    21712217        {
    21722218            uint32_t u32;
     
    21762222            u32 += pGipCpu->au32TSCHistory[3];
    21772223            u32 >>= 2;
    2178             u64TSCDelta  = pGipCpu->au32TSCHistory[4];
    2179             u64TSCDelta += pGipCpu->au32TSCHistory[5];
    2180             u64TSCDelta += pGipCpu->au32TSCHistory[6];
    2181             u64TSCDelta += pGipCpu->au32TSCHistory[7];
    2182             u64TSCDelta >>= 2;
    2183             u64TSCDelta += u32;
    2184             u64TSCDelta >>= 1;
    2185         }
    2186     }
    2187 
    2188     /*
    2189      * TSC History.
    2190      */
    2191     Assert(RT_ELEMENTS(pGipCpu->au32TSCHistory) == 8);
    2192     iTSCHistoryHead = (pGipCpu->iTSCHistoryHead + 1) & 7;
    2193     ASMAtomicWriteU32(&pGipCpu->iTSCHistoryHead, iTSCHistoryHead);
    2194     ASMAtomicWriteU32(&pGipCpu->au32TSCHistory[iTSCHistoryHead], (uint32_t)u64TSCDelta);
    2195 
    2196     /*
    2197      * UpdateIntervalTSC = average of last 8,2,1 intervals depending on update HZ.
    2198      *
    2199      * On Windows, we have an occasional (but recurring) sour value that messed up
    2200      * the history but taking only 1 interval reduces the precision overall.
    2201      * However, this problem existed before the invariant mode was introduced.
    2202      */
    2203     if (   pGip->u32Mode == SUPGIPMODE_INVARIANT_TSC
    2204         || pGip->u32UpdateHz >= 1000)
    2205     {
    2206         uint32_t u32;
    2207         u32  = pGipCpu->au32TSCHistory[0];
    2208         u32 += pGipCpu->au32TSCHistory[1];
    2209         u32 += pGipCpu->au32TSCHistory[2];
    2210         u32 += pGipCpu->au32TSCHistory[3];
    2211         u32 >>= 2;
    2212         u32UpdateIntervalTSC  = pGipCpu->au32TSCHistory[4];
    2213         u32UpdateIntervalTSC += pGipCpu->au32TSCHistory[5];
    2214         u32UpdateIntervalTSC += pGipCpu->au32TSCHistory[6];
    2215         u32UpdateIntervalTSC += pGipCpu->au32TSCHistory[7];
    2216         u32UpdateIntervalTSC >>= 2;
    2217         u32UpdateIntervalTSC += u32;
    2218         u32UpdateIntervalTSC >>= 1;
    2219 
    2220         /* Value chosen for a 2GHz Athlon64 running linux 2.6.10/11. */
    2221         u32UpdateIntervalTSCSlack = u32UpdateIntervalTSC >> 14;
    2222     }
    2223     else if (pGip->u32UpdateHz >= 90)
    2224     {
    2225         u32UpdateIntervalTSC  = (uint32_t)u64TSCDelta;
    2226         u32UpdateIntervalTSC += pGipCpu->au32TSCHistory[(iTSCHistoryHead - 1) & 7];
    2227         u32UpdateIntervalTSC >>= 1;
    2228 
    2229         /* value chosen on a 2GHz thinkpad running windows */
    2230         u32UpdateIntervalTSCSlack = u32UpdateIntervalTSC >> 7;
    2231     }
    2232     else
    2233     {
    2234         u32UpdateIntervalTSC  = (uint32_t)u64TSCDelta;
    2235 
    2236         /* This value hasn't be checked yet.. waiting for OS/2 and 33Hz timers.. :-) */
    2237         u32UpdateIntervalTSCSlack = u32UpdateIntervalTSC >> 6;
    2238     }
    2239     ASMAtomicWriteU32(&pGipCpu->u32UpdateIntervalTSC, u32UpdateIntervalTSC + u32UpdateIntervalTSCSlack);
    2240 
    2241     /*
    2242      * CpuHz.
    2243      */
    2244     u64CpuHz = ASMMult2xU32RetU64(u32UpdateIntervalTSC, RT_NS_1SEC);
    2245     u64CpuHz /= pGip->u32UpdateIntervalNS;
    2246     ASMAtomicWriteU64(&pGipCpu->u64CpuHz, u64CpuHz);
     2224            u32UpdateIntervalTSC  = pGipCpu->au32TSCHistory[4];
     2225            u32UpdateIntervalTSC += pGipCpu->au32TSCHistory[5];
     2226            u32UpdateIntervalTSC += pGipCpu->au32TSCHistory[6];
     2227            u32UpdateIntervalTSC += pGipCpu->au32TSCHistory[7];
     2228            u32UpdateIntervalTSC >>= 2;
     2229            u32UpdateIntervalTSC += u32;
     2230            u32UpdateIntervalTSC >>= 1;
     2231
     2232            /* Value chosen for a 2GHz Athlon64 running linux 2.6.10/11. */
     2233            u32UpdateIntervalTSCSlack = u32UpdateIntervalTSC >> 14;
     2234        }
     2235        else if (pGip->u32UpdateHz >= 90)
     2236        {
     2237            u32UpdateIntervalTSC  = (uint32_t)u64TSCDelta;
     2238            u32UpdateIntervalTSC += pGipCpu->au32TSCHistory[(iTSCHistoryHead - 1) & 7];
     2239            u32UpdateIntervalTSC >>= 1;
     2240
     2241            /* value chosen on a 2GHz thinkpad running windows */
     2242            u32UpdateIntervalTSCSlack = u32UpdateIntervalTSC >> 7;
     2243        }
     2244        else
     2245        {
     2246            u32UpdateIntervalTSC  = (uint32_t)u64TSCDelta;
     2247
     2248            /* This value hasn't be checked yet.. waiting for OS/2 and 33Hz timers.. :-) */
     2249            u32UpdateIntervalTSCSlack = u32UpdateIntervalTSC >> 6;
     2250        }
     2251        ASMAtomicWriteU32(&pGipCpu->u32UpdateIntervalTSC, u32UpdateIntervalTSC + u32UpdateIntervalTSCSlack);
     2252
     2253        /*
     2254         * CpuHz.
     2255         */
     2256        u64CpuHz = ASMMult2xU32RetU64(u32UpdateIntervalTSC, RT_NS_1SEC);
     2257        u64CpuHz /= pGip->u32UpdateIntervalNS;
     2258        ASMAtomicWriteU64(&pGipCpu->u64CpuHz, u64CpuHz);
     2259    }
    22472260}
    22482261
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