Changeset 54672 in vbox
- Timestamp:
- Mar 6, 2015 5:53:07 PM (10 years ago)
- svn:sync-xref-src-repo-rev:
- 98825
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR3/TM.cpp
r54550 r54672 1047 1047 * GIM is now initialized. Determine if TSC mode switching is allowed (respecting CFGM override). 1048 1048 */ 1049 pVM->tm.s.fTSCModeSwitchAllowed &= GIMIsEnabled(pVM) && HMIsEnabled(pVM);1049 pVM->tm.s.fTSCModeSwitchAllowed &= tmR3HasFixedTSC(pVM) && GIMIsEnabled(pVM) && HMIsEnabled(pVM); 1050 1050 return rc; 1051 1051 } … … 3086 3086 AssertPtr(pVM); Assert(pVM->tm.s.fTSCModeSwitchAllowed); NOREF(pVCpuEmt); NOREF(pvData); 3087 3087 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))); 3126 3119 return VINF_SUCCESS; 3127 3120 } … … 3140 3133 int rc = VINF_SUCCESS; 3141 3134 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))); 3143 3142 pVM->tm.s.fParavirtTscEnabled = true; 3144 3143 return rc; … … 3154 3153 AssertPtr(pVM); Assert(pVM->tm.s.fTSCModeSwitchAllowed); NOREF(pVCpuEmt); 3155 3154 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))); 3184 3177 return VINF_SUCCESS; 3185 3178 } … … 3189 3182 * Notify TM that the guest has disabled usage of a paravirtualized TSC. 3190 3183 * 3191 * If TMR3CpuTickParavirtEnable changed the TSC virtualization mode, this will3184 * If TMR3CpuTickParavirtEnable() changed the TSC virtualization mode, this will 3192 3185 * perform an EMT rendezvous to revert those changes. 3193 3186 * … … 3198 3191 { 3199 3192 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) 3201 3196 rc = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_ONCE, tmR3CpuTickParavirtDisable, NULL); 3202 3197 pVM->tm.s.fParavirtTscEnabled = false; 3203 3198 return rc; 3204 3199 } 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 */ 3213 VMMR3_INT_DECL(bool) TMR3CpuTickIsFixedRateMonotonic(PVM pVM, bool fWithParavirtEnabled) 3214 { 3215 /** @todo */ 3216 } 3217 #endif 3205 3218 3206 3219
Note:
See TracChangeset
for help on using the changeset viewer.