VirtualBox

Changeset 54298 in vbox for trunk


Ignore:
Timestamp:
Feb 19, 2015 3:19:34 PM (10 years ago)
Author:
vboxsync
Message:

SUPDrv.c: Shouldn't not check for invariant tsc cpuid bit in supdrvGipMpEventOffline. Restructured, clarified and fixed the code and comments in supdrvGipInitDetermineTscMode.

File:
1 edited

Legend:

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

    r54290 r54298  
    43214321                {
    43224322                    SUPDRVGIPDETECTGETCPU DetectState;
    4323                     RT_ZERO(DetectState.bmApicId);
     4323                    RT_BZERO((void *)&DetectState.bmApicId, sizeof(DetectState.bmApicId));
    43244324                    DetectState.fSupported   = UINT32_MAX;
    43254325                    DetectState.idCpuProblem = NIL_RTCPUID;
     
    59655965    return VERR_NOT_IMPLEMENTED;
    59665966#endif
    5967 }
    5968 
    5969 
    5970 /**
    5971  * Returns whether the host CPU sports an invariant TSC or not.
    5972  *
    5973  * @returns true if invariant TSC is supported, false otherwise.
    5974  */
    5975 static bool supdrvIsInvariantTsc(void)
    5976 {
    5977     static bool s_fQueried        = false;
    5978     static bool s_fIsInvariantTsc = false;
    5979     if (!s_fQueried)
    5980     {
    5981         if (ASMHasCpuId())
    5982         {
    5983             uint32_t uEax, uEbx, uEcx, uEdx;
    5984             ASMCpuId(0x80000000, &uEax, &uEbx, &uEcx, &uEdx);
    5985             if (uEax >= 0x80000007)
    5986             {
    5987                 ASMCpuId(0x80000007, &uEax, &uEbx, &uEcx, &uEdx);
    5988                 if (uEdx & X86_CPUID_AMD_ADVPOWER_EDX_TSCINVAR)
    5989                     s_fIsInvariantTsc = true;
    5990             }
    5991         }
    5992         s_fQueried = true;
    5993     }
    5994 
    5995     return s_fIsInvariantTsc;
    59965967}
    59975968
     
    71597130    /* Reset the TSC delta, we will recalculate it lazily. */
    71607131    if (pGip->enmUseTscDelta > SUPGIPUSETSCDELTA_ZERO_CLAIMED)
     7132    {
    71617133        ASMAtomicWriteS64(&pGip->aCPUs[i].i64TSCDelta, INT64_MAX);
    7162 
    71637134#ifdef SUPDRV_USE_TSC_DELTA_THREAD
    7164     /* Remove this CPU from the set of CPUs that we have obtained the TSC deltas. */
    7165     if (supdrvIsInvariantTsc())
     7135        /* Remove this CPU from the set of CPUs that we have obtained the TSC deltas. */
    71667136        RTCpuSetDel(&pDevExt->TscDeltaObtainedCpuSet, idCpu);
    71677137#endif
     7138    }
    71687139
    71697140    /* commit it */
     
    77697740
    77707741/**
    7771  * Determine the GIP TSC mode.
     7742 * supdrvGipInit() worker that determines the GIP TSC mode.
    77727743 *
    77737744 * @returns The most suitable TSC mode.
    77747745 * @param   pDevExt     Pointer to the device instance data.
    77757746 */
    7776 static SUPGIPMODE supdrvGipDetermineTscMode(PSUPDRVDEVEXT pDevExt)
    7777 {
    7778     /* Trust CPUs that declare their TSC to be invariant. */
    7779 #if 0       /** @todo this cannot be enabled until Michal's AMD laptop with insane deltas are working. */
    7780     if (supdrvIsInvariantTsc())
     7747static SUPGIPMODE supdrvGipInitDetermineTscMode(PSUPDRVDEVEXT pDevExt)
     7748{
     7749    uint64_t u64DiffCoresIgnored;
     7750    uint32_t uEAX, uEBX, uECX, uEDX;
     7751
     7752    /*
     7753     * Establish whether the CPU advertises TSC as invariant, we need that in
     7754     * a couple of places below.
     7755     */
     7756    bool fInvariantTsc = false;
     7757    if (ASMHasCpuId())
     7758    {
     7759        uEAX = ASMCpuId_EAX(0x80000000);
     7760        if (ASMIsValidExtRange(uEAX) && uEAX >= 0x80000007)
     7761        {
     7762            uEDX = ASMCpuId_EDX(0x80000007);
     7763            if (uEDX & X86_CPUID_AMD_ADVPOWER_EDX_TSCINVAR)
     7764                fInvariantTsc = true;
     7765        }
     7766    }
     7767
     7768    /*
     7769     * On single CPU systems, we don't need to consider ASYNC mode.
     7770     */
     7771    if (RTMpGetCount() <= 1)
     7772        return fInvariantTsc ? SUPGIPMODE_INVARIANT_TSC : SUPGIPMODE_SYNC_TSC;
     7773
     7774    /*
     7775     * Allow the user and/or OS specific bits to force async mode.
     7776     */
     7777    if (supdrvOSGetForcedAsyncTscMode(pDevExt))
     7778        return SUPGIPMODE_ASYNC_TSC;
     7779
     7780
     7781#if 0 /** @todo enable this when i64TscDelta is applied in all places where it's needed */
     7782    /*
     7783     * Use invariant mode if the CPU says TSC is invariant.
     7784     */
     7785    if (fInvariantTsc)
    77817786        return SUPGIPMODE_INVARIANT_TSC;
    77827787#endif
    77837788
    77847789    /*
    7785      * Without invariant CPU ID bit - On SMP we're faced with two problems:
     7790     * TSC is not invariant and we're on SMP, this presents two problems:
     7791     *
    77867792     *      (1) There might be a skew between the CPU, so that cpu0
    77877793     *          returns a TSC that is slightly different from cpu1.
     7794     *          This screw may be due to (2), bad TSC initialization
     7795     *          or slightly different TSC rates.
     7796     *
    77887797     *      (2) Power management (and other things) may cause the TSC
    77897798     *          to run at a non-constant speed, and cause the speed
    77907799     *          to be different on the cpus. This will result in (1).
    77917800     *
    7792      * So, on SMP systems we'll have to select the ASYNC update method
    7793      * if there are symptoms of these problems.
    7794      */
    7795     if (RTMpGetCount() > 1)
    7796     {
    7797         uint32_t uEAX, uEBX, uECX, uEDX;
    7798         uint64_t u64DiffCoresIgnored;
    7799 
    7800         /* Permit the user and/or the OS specific bits to force async mode. */
    7801         if (supdrvOSGetForcedAsyncTscMode(pDevExt))
    7802             return SUPGIPMODE_ASYNC_TSC;
    7803 
    7804         /* Try check for current differences between the cpus. */
    7805         if (supdrvDetermineAsyncTsc(&u64DiffCoresIgnored))
    7806             return SUPGIPMODE_ASYNC_TSC;
    7807 
    7808         /*
    7809          * If the CPU supports power management and is an AMD one we
    7810          * won't trust it unless it has the TscInvariant bit is set.
    7811          */
    7812         /** @todo this is now redundant. remove later. */
    7813         /* Check for "AuthenticAMD" */
    7814         ASMCpuId(0, &uEAX, &uEBX, &uECX, &uEDX);
    7815         if (   uEAX >= 1
    7816             && ASMIsAmdCpuEx(uEBX, uECX, uEDX))
    7817         {
    7818             /* Check for APM support and that TscInvariant is cleared. */
    7819             ASMCpuId(0x80000000, &uEAX, &uEBX, &uECX, &uEDX);
    7820             if (uEAX >= 0x80000007)
    7821             {
    7822                 ASMCpuId(0x80000007, &uEAX, &uEBX, &uECX, &uEDX);
    7823                 if (    !(uEDX & X86_CPUID_AMD_ADVPOWER_EDX_TSCINVAR) /* TscInvariant */
    7824                     &&  (uEDX & 0x3e))  /* STC|TM|THERMTRIP|VID|FID. Ignore TS. */
    7825                     return SUPGIPMODE_ASYNC_TSC;
    7826             }
    7827         }
    7828     }
    7829 
    7830     /** @todo later remove this when the above todo with AMD laptop is done (i.e.
    7831      *        TSC deltas handled everywhere). */
    7832     if (supdrvIsInvariantTsc())
     7801     * If any of the above is detected, we will have to use ASYNC mode.
     7802     */
     7803
     7804    /* (1). Try check for current differences between the cpus. */
     7805    if (supdrvDetermineAsyncTsc(&u64DiffCoresIgnored))
     7806        return SUPGIPMODE_ASYNC_TSC;
     7807
     7808#if 1 /** @todo remove once i64TscDelta is applied everywhere. Enable #if 0 above. */
     7809    if (fInvariantTsc)
    78337810        return SUPGIPMODE_INVARIANT_TSC;
     7811#endif
     7812
     7813    /* (2) If it's an AMD CPU with power management, we won't trust its TSC. */
     7814    ASMCpuId(0, &uEAX, &uEBX, &uECX, &uEDX);
     7815    if (   ASMIsValidStdRange(uEAX)
     7816        && ASMIsAmdCpuEx(uEBX, uECX, uEDX))
     7817    {
     7818        /* Check for APM support. */
     7819        uEAX = ASMCpuId_EAX(0x80000000);
     7820        if (ASMIsValidExtRange(uEAX) && uEAX >= 0x80000007)
     7821        {
     7822            uEDX = ASMCpuId_EDX(0x80000007);
     7823            if (uEDX & 0x3e)  /* STC|TM|THERMTRIP|VID|FID. Ignore TS. */
     7824                return SUPGIPMODE_ASYNC_TSC;
     7825        }
     7826    }
     7827
    78347828    return SUPGIPMODE_SYNC_TSC;
    78357829}
     
    79077901    pGip->u32Magic                = SUPGLOBALINFOPAGE_MAGIC;
    79087902    pGip->u32Version              = SUPGLOBALINFOPAGE_VERSION;
    7909     pGip->u32Mode                 = supdrvGipDetermineTscMode(pDevExt);
     7903    pGip->u32Mode                 = supdrvGipInitDetermineTscMode(pDevExt);
    79107904    if (   pGip->u32Mode == SUPGIPMODE_INVARIANT_TSC
    79117905        /*|| pGip->u32Mode == SUPGIPMODE_SYNC_TSC */)
    7912         pGip->enmUseTscDelta      = supdrvIsInvariantTsc() && supdrvOSAreTscDeltasInSync() /* Allow OS override (windows). */
     7906        pGip->enmUseTscDelta      = supdrvOSAreTscDeltasInSync() /* Allow OS override (windows). */
    79137907                                  ? SUPGIPUSETSCDELTA_ZERO_CLAIMED : SUPGIPUSETSCDELTA_PRACTICALLY_ZERO /* downgrade later */;
    79147908    else
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