VirtualBox

Changeset 54672 in vbox


Ignore:
Timestamp:
Mar 6, 2015 5:53:07 PM (10 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
98825
Message:

VMM/TM: Update fTSCModeSwitchAllowed to include tmR3HasFixedTSC() and avoid rendezvous when not necessary.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMR3/TM.cpp

    r54550 r54672  
    10471047     * GIM is now initialized. Determine if TSC mode switching is allowed (respecting CFGM override).
    10481048     */
    1049     pVM->tm.s.fTSCModeSwitchAllowed &= GIMIsEnabled(pVM) && HMIsEnabled(pVM);
     1049    pVM->tm.s.fTSCModeSwitchAllowed &= tmR3HasFixedTSC(pVM) && GIMIsEnabled(pVM) && HMIsEnabled(pVM);
    10501050    return rc;
    10511051}
     
    30863086    AssertPtr(pVM); Assert(pVM->tm.s.fTSCModeSwitchAllowed); NOREF(pVCpuEmt); NOREF(pvData);
    30873087    Assert(pVCpuEmt->tm.s.fTSCTicking);
    3088 
    3089     if (pVM->tm.s.enmTSCMode != TMTSCMODE_REAL_TSC_OFFSET)
    3090     {
    3091         if (tmR3HasFixedTSC(pVM))
    3092         {
    3093             /*
    3094              * The return value of TMCpuTickGet() and the guest's TSC value for each
    3095              * CPU must remain constant across the TM TSC mode-switch.  Thus we have
    3096              * the following equation (new/old signifies the new/old tsc modes):
    3097              *      uNewTsc = uOldTsc
    3098              *
    3099              * Where (see tmCpuTickGetInternal):
    3100              *      uOldTsc = uRawOldTsc - offTscRawSrcOld
    3101              *      uNewTsc = uRawNewTsc - offTscRawSrcNew
    3102              *
    3103              * Solve it for offTscRawSrcNew without replacing uOldTsc:
    3104              *     uRawNewTsc - offTscRawSrcNew = uOldTsc
    3105              *  => -offTscRawSrcNew = uOldTsc - uRawNewTsc
    3106              *  => offTscRawSrcNew  = uRawNewTsc - uOldTsc
    3107              */
    3108             uint64_t uRawOldTsc = tmR3CpuTickGetRawVirtualNoCheck(pVM);
    3109             uint64_t uRawNewTsc = SUPReadTsc();
    3110             uint32_t cCpus = pVM->cCpus;
    3111             for (uint32_t i = 0; i < cCpus; i++)
    3112             {
    3113                 PVMCPU   pVCpu   = &pVM->aCpus[i];
    3114                 uint64_t uOldTsc = uRawOldTsc - pVCpu->tm.s.offTSCRawSrc;
    3115                 pVCpu->tm.s.offTSCRawSrc = uRawNewTsc - uOldTsc;
    3116                 Assert(uRawNewTsc - pVCpu->tm.s.offTSCRawSrc >= uOldTsc); /* paranoia^256 */
    3117             }
    3118 
    3119             pVM->tm.s.enmTSCMode = TMTSCMODE_REAL_TSC_OFFSET;
    3120             LogRel(("TM: Switched TSC mode. New enmTSCMode=%d (%s)\n", pVM->tm.s.enmTSCMode, tmR3GetTSCModeName(pVM)));
    3121         }
    3122         else
    3123             LogRel(("TM: Host is not suitable for using TSC mode (%d - %s). Request to change TSC mode ignored.\n",
    3124                     TMTSCMODE_REAL_TSC_OFFSET, tmR3GetTSCModeNameEx(TMTSCMODE_REAL_TSC_OFFSET)));
    3125     }
     3088    Assert(pVM->tm.s.enmTSCMode != TMTSCMODE_REAL_TSC_OFFSET);
     3089    Assert(tmR3HasFixedTSC(pVM));
     3090
     3091    /*
     3092     * The return value of TMCpuTickGet() and the guest's TSC value for each
     3093     * CPU must remain constant across the TM TSC mode-switch.  Thus we have
     3094     * the following equation (new/old signifies the new/old tsc modes):
     3095     *      uNewTsc = uOldTsc
     3096     *
     3097     * Where (see tmCpuTickGetInternal):
     3098     *      uOldTsc = uRawOldTsc - offTscRawSrcOld
     3099     *      uNewTsc = uRawNewTsc - offTscRawSrcNew
     3100     *
     3101     * Solve it for offTscRawSrcNew without replacing uOldTsc:
     3102     *     uRawNewTsc - offTscRawSrcNew = uOldTsc
     3103     *  => -offTscRawSrcNew = uOldTsc - uRawNewTsc
     3104     *  => offTscRawSrcNew  = uRawNewTsc - uOldTsc
     3105     */
     3106    uint64_t uRawOldTsc = tmR3CpuTickGetRawVirtualNoCheck(pVM);
     3107    uint64_t uRawNewTsc = SUPReadTsc();
     3108    uint32_t cCpus = pVM->cCpus;
     3109    for (uint32_t i = 0; i < cCpus; i++)
     3110    {
     3111        PVMCPU   pVCpu   = &pVM->aCpus[i];
     3112        uint64_t uOldTsc = uRawOldTsc - pVCpu->tm.s.offTSCRawSrc;
     3113        pVCpu->tm.s.offTSCRawSrc = uRawNewTsc - uOldTsc;
     3114        Assert(uRawNewTsc - pVCpu->tm.s.offTSCRawSrc >= uOldTsc); /* paranoia^256 */
     3115    }
     3116
     3117    pVM->tm.s.enmTSCMode = TMTSCMODE_REAL_TSC_OFFSET;
     3118    LogRel(("TM: Switched TSC mode. New enmTSCMode=%d (%s)\n", pVM->tm.s.enmTSCMode, tmR3GetTSCModeName(pVM)));
    31263119    return VINF_SUCCESS;
    31273120}
     
    31403133    int rc = VINF_SUCCESS;
    31413134    if (pVM->tm.s.fTSCModeSwitchAllowed)
    3142         rc = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_ONCE, tmR3CpuTickParavirtEnable, NULL);
     3135    {
     3136        if (pVM->tm.s.enmTSCMode != TMTSCMODE_REAL_TSC_OFFSET)
     3137            rc = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_ONCE, tmR3CpuTickParavirtEnable, NULL);
     3138    }
     3139    else
     3140        LogRel(("TM: Host is not suitable for using TSC mode (%d - %s). Request to change TSC mode ignored.\n",
     3141                TMTSCMODE_REAL_TSC_OFFSET, tmR3GetTSCModeNameEx(TMTSCMODE_REAL_TSC_OFFSET)));
    31433142    pVM->tm.s.fParavirtTscEnabled = true;
    31443143    return rc;
     
    31543153    AssertPtr(pVM); Assert(pVM->tm.s.fTSCModeSwitchAllowed); NOREF(pVCpuEmt);
    31553154    Assert(pVCpuEmt->tm.s.fTSCTicking);
    3156 
    3157     if (   pVM->tm.s.enmTSCMode == TMTSCMODE_REAL_TSC_OFFSET
    3158         && pVM->tm.s.enmTSCMode != pVM->tm.s.enmOriginalTSCMode)
    3159     {
    3160         /*
    3161          * See tmR3CpuTickParavirtEnable for an explanation of the conversion math.
    3162          */
    3163         uint64_t uRawOldTsc = SUPReadTsc();
    3164         uint64_t uRawNewTsc = tmR3CpuTickGetRawVirtualNoCheck(pVM);
    3165         uint32_t cCpus = pVM->cCpus;
    3166         for (uint32_t i = 0; i < cCpus; i++)
    3167         {
    3168             PVMCPU   pVCpu   = &pVM->aCpus[i];
    3169             uint64_t uOldTsc = uRawOldTsc - pVCpu->tm.s.offTSCRawSrc;
    3170             pVCpu->tm.s.offTSCRawSrc = uRawNewTsc - uOldTsc;
    3171             Assert(uRawNewTsc - pVCpu->tm.s.offTSCRawSrc >= uOldTsc); /* paranoia^256 */
    3172 
    3173             /* Update the last-seen tick here as we havent't been updating it (as we don't
    3174                need it) while in pure TSC-offsetting mode. */
    3175 #if 0 /** @todo r=bird: Why use the TSC value from the last time we paused the TSC? Makes more sense to use uOldTsc doesn't it? */
    3176             pVCpu->tm.s.u64TSCLastSeen = pVCpu->tm.s.u64TSC;
    3177 #else
    3178             pVCpu->tm.s.u64TSCLastSeen = uOldTsc;
    3179 #endif
    3180         }
    3181         pVM->tm.s.enmTSCMode = pVM->tm.s.enmOriginalTSCMode;
    3182         LogRel(("TM: Switched TSC mode. New enmTSCMode=%d (%s)\n", pVM->tm.s.enmTSCMode, tmR3GetTSCModeName(pVM)));
    3183     }
     3155    Assert(   pVM->tm.s.enmTSCMode == TMTSCMODE_REAL_TSC_OFFSET
     3156           && pVM->tm.s.enmTSCMode != pVM->tm.s.enmOriginalTSCMode);
     3157
     3158    /*
     3159     * See tmR3CpuTickParavirtEnable for an explanation of the conversion math.
     3160     */
     3161    uint64_t uRawOldTsc = SUPReadTsc();
     3162    uint64_t uRawNewTsc = tmR3CpuTickGetRawVirtualNoCheck(pVM);
     3163    uint32_t cCpus = pVM->cCpus;
     3164    for (uint32_t i = 0; i < cCpus; i++)
     3165    {
     3166        PVMCPU   pVCpu   = &pVM->aCpus[i];
     3167        uint64_t uOldTsc = uRawOldTsc - pVCpu->tm.s.offTSCRawSrc;
     3168        pVCpu->tm.s.offTSCRawSrc = uRawNewTsc - uOldTsc;
     3169        Assert(uRawNewTsc - pVCpu->tm.s.offTSCRawSrc >= uOldTsc); /* paranoia^256 */
     3170
     3171        /* Update the last-seen tick here as we havent't been updating it (as we don't
     3172           need it) while in pure TSC-offsetting mode. */
     3173        pVCpu->tm.s.u64TSCLastSeen = uOldTsc;
     3174    }
     3175    pVM->tm.s.enmTSCMode = pVM->tm.s.enmOriginalTSCMode;
     3176    LogRel(("TM: Switched TSC mode. New enmTSCMode=%d (%s)\n", pVM->tm.s.enmTSCMode, tmR3GetTSCModeName(pVM)));
    31843177    return VINF_SUCCESS;
    31853178}
     
    31893182 * Notify TM that the guest has disabled usage of a paravirtualized TSC.
    31903183 *
    3191  * If TMR3CpuTickParavirtEnable changed the TSC virtualization mode, this will
     3184 * If TMR3CpuTickParavirtEnable() changed the TSC virtualization mode, this will
    31923185 * perform an EMT  rendezvous to revert those changes.
    31933186 *
     
    31983191{
    31993192    int rc = VINF_SUCCESS;
    3200     if (pVM->tm.s.fTSCModeSwitchAllowed)
     3193    if (   pVM->tm.s.fTSCModeSwitchAllowed
     3194        && pVM->tm.s.enmTSCMode == TMTSCMODE_REAL_TSC_OFFSET
     3195        && pVM->tm.s.enmTSCMode != pVM->tm.s.enmOriginalTSCMode)
    32013196        rc = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_ONCE, tmR3CpuTickParavirtDisable, NULL);
    32023197    pVM->tm.s.fParavirtTscEnabled = false;
    32033198    return rc;
    32043199}
     3200
     3201
     3202#if 0
     3203/**
     3204 * Check whether the host TSC is fixed rate & monotonic.
     3205 *
     3206 * @returns true if TSC is stable, false otherwise.
     3207 * @param   pVM                     Pointer to the VM.
     3208 * @param   fWithParavirtEnabled    Whether it's fixed & monotonic when
     3209 *                                  paravirt. TSC is enabled or not.
     3210 *
     3211 * @remarks Must be called only after TMR3InitFinalize().
     3212 */
     3213VMMR3_INT_DECL(bool) TMR3CpuTickIsFixedRateMonotonic(PVM pVM, bool fWithParavirtEnabled)
     3214{
     3215    /** @todo */
     3216}
     3217#endif
    32053218
    32063219
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