Changeset 91988 in vbox
- Timestamp:
- Oct 22, 2021 3:23:54 AM (4 years ago)
- svn:sync-xref-src-repo-rev:
- 147796
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR3/TM.cpp
r91939 r91988 1216 1216 * Switch TM TSC mode back to the original mode after a reset for 1217 1217 * paravirtualized guests that alter the TM TSC mode during operation. 1218 * We're already in an EMT rendezvous at this point. 1218 1219 */ 1219 1220 if ( pVM->tm.s.fTSCModeSwitchAllowed … … 3636 3637 { 3637 3638 AssertPtr(pVM); Assert(pVM->tm.s.fTSCModeSwitchAllowed); NOREF(pVCpuEmt); NOREF(pvData); 3638 Assert(pVM->tm.s.enmTSCMode != TMTSCMODE_REAL_TSC_OFFSET);3639 3639 Assert(pVM->tm.s.enmTSCMode != TMTSCMODE_NATIVE_API); /** @todo figure out NEM/win and paravirt */ 3640 3640 Assert(tmR3HasFixedTSC(pVM)); 3641 3641 3642 /* 3643 * The return value of TMCpuTickGet() and the guest's TSC value for each 3644 * CPU must remain constant across the TM TSC mode-switch. Thus we have 3645 * the following equation (new/old signifies the new/old tsc modes): 3646 * uNewTsc = uOldTsc 3647 * 3648 * Where (see tmCpuTickGetInternal): 3649 * uOldTsc = uRawOldTsc - offTscRawSrcOld 3650 * uNewTsc = uRawNewTsc - offTscRawSrcNew 3651 * 3652 * Solve it for offTscRawSrcNew without replacing uOldTsc: 3653 * uRawNewTsc - offTscRawSrcNew = uOldTsc 3654 * => -offTscRawSrcNew = uOldTsc - uRawNewTsc 3655 * => offTscRawSrcNew = uRawNewTsc - uOldTsc 3656 */ 3657 uint64_t uRawOldTsc = tmR3CpuTickGetRawVirtualNoCheck(pVM); 3658 uint64_t uRawNewTsc = SUPReadTsc(); 3659 uint32_t cCpus = pVM->cCpus; 3660 for (uint32_t i = 0; i < cCpus; i++) 3661 { 3662 PVMCPU pVCpu = pVM->apCpusR3[i]; 3663 uint64_t uOldTsc = uRawOldTsc - pVCpu->tm.s.offTSCRawSrc; 3664 pVCpu->tm.s.offTSCRawSrc = uRawNewTsc - uOldTsc; 3665 Assert(uRawNewTsc - pVCpu->tm.s.offTSCRawSrc >= uOldTsc); /* paranoia^256 */ 3666 } 3667 3668 LogRel(("TM: Switching TSC mode from '%s' to '%s'\n", tmR3GetTSCModeNameEx(pVM->tm.s.enmTSCMode), 3669 tmR3GetTSCModeNameEx(TMTSCMODE_REAL_TSC_OFFSET))); 3670 pVM->tm.s.enmTSCMode = TMTSCMODE_REAL_TSC_OFFSET; 3642 if (pVM->tm.s.enmTSCMode != TMTSCMODE_REAL_TSC_OFFSET) 3643 { 3644 /* 3645 * The return value of TMCpuTickGet() and the guest's TSC value for each 3646 * CPU must remain constant across the TM TSC mode-switch. Thus we have 3647 * the following equation (new/old signifies the new/old tsc modes): 3648 * uNewTsc = uOldTsc 3649 * 3650 * Where (see tmCpuTickGetInternal): 3651 * uOldTsc = uRawOldTsc - offTscRawSrcOld 3652 * uNewTsc = uRawNewTsc - offTscRawSrcNew 3653 * 3654 * Solve it for offTscRawSrcNew without replacing uOldTsc: 3655 * uRawNewTsc - offTscRawSrcNew = uOldTsc 3656 * => -offTscRawSrcNew = uOldTsc - uRawNewTsc 3657 * => offTscRawSrcNew = uRawNewTsc - uOldTsc 3658 */ 3659 uint64_t uRawOldTsc = tmR3CpuTickGetRawVirtualNoCheck(pVM); 3660 uint64_t uRawNewTsc = SUPReadTsc(); 3661 uint32_t cCpus = pVM->cCpus; 3662 for (uint32_t i = 0; i < cCpus; i++) 3663 { 3664 PVMCPU pVCpu = pVM->apCpusR3[i]; 3665 uint64_t uOldTsc = uRawOldTsc - pVCpu->tm.s.offTSCRawSrc; 3666 pVCpu->tm.s.offTSCRawSrc = uRawNewTsc - uOldTsc; 3667 Assert(uRawNewTsc - pVCpu->tm.s.offTSCRawSrc >= uOldTsc); /* paranoia^256 */ 3668 } 3669 3670 LogRel(("TM: Switching TSC mode from '%s' to '%s'\n", tmR3GetTSCModeNameEx(pVM->tm.s.enmTSCMode), 3671 tmR3GetTSCModeNameEx(TMTSCMODE_REAL_TSC_OFFSET))); 3672 pVM->tm.s.enmTSCMode = TMTSCMODE_REAL_TSC_OFFSET; 3673 } 3671 3674 return VINF_SUCCESS; 3672 3675 } … … 3685 3688 int rc = VINF_SUCCESS; 3686 3689 if (pVM->tm.s.fTSCModeSwitchAllowed) 3687 { 3688 if (pVM->tm.s.enmTSCMode != TMTSCMODE_REAL_TSC_OFFSET) 3689 rc = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_ONCE, tmR3CpuTickParavirtEnable, NULL); 3690 } 3690 rc = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_ONCE, tmR3CpuTickParavirtEnable, NULL); 3691 3691 else 3692 3692 LogRel(("TM: Host/VM is not suitable for using TSC mode '%s', request to change TSC mode ignored\n", … … 3704 3704 { 3705 3705 AssertPtr(pVM); Assert(pVM->tm.s.fTSCModeSwitchAllowed); NOREF(pVCpuEmt); 3706 Assert( pVM->tm.s.enmTSCMode == TMTSCMODE_REAL_TSC_OFFSET3707 && pVM->tm.s.enmTSCMode != pVM->tm.s.enmOriginalTSCMode);3708 3706 RT_NOREF1(pvData); 3709 3707 3710 /* 3711 * See tmR3CpuTickParavirtEnable for an explanation of the conversion math. 3712 */ 3713 uint64_t uRawOldTsc = SUPReadTsc(); 3714 uint64_t uRawNewTsc = tmR3CpuTickGetRawVirtualNoCheck(pVM); 3715 uint32_t cCpus = pVM->cCpus; 3716 for (uint32_t i = 0; i < cCpus; i++) 3717 { 3718 PVMCPU pVCpu = pVM->apCpusR3[i]; 3719 uint64_t uOldTsc = uRawOldTsc - pVCpu->tm.s.offTSCRawSrc; 3720 pVCpu->tm.s.offTSCRawSrc = uRawNewTsc - uOldTsc; 3721 Assert(uRawNewTsc - pVCpu->tm.s.offTSCRawSrc >= uOldTsc); /* paranoia^256 */ 3722 3723 /* Update the last-seen tick here as we havent't been updating it (as we don't 3724 need it) while in pure TSC-offsetting mode. */ 3725 pVCpu->tm.s.u64TSCLastSeen = uOldTsc; 3726 } 3727 3728 LogRel(("TM: Switching TSC mode from '%s' to '%s'\n", tmR3GetTSCModeNameEx(pVM->tm.s.enmTSCMode), 3729 tmR3GetTSCModeNameEx(pVM->tm.s.enmOriginalTSCMode))); 3730 pVM->tm.s.enmTSCMode = pVM->tm.s.enmOriginalTSCMode; 3708 if ( pVM->tm.s.enmTSCMode == TMTSCMODE_REAL_TSC_OFFSET 3709 && pVM->tm.s.enmTSCMode != pVM->tm.s.enmOriginalTSCMode) 3710 { 3711 /* 3712 * See tmR3CpuTickParavirtEnable for an explanation of the conversion math. 3713 */ 3714 uint64_t uRawOldTsc = SUPReadTsc(); 3715 uint64_t uRawNewTsc = tmR3CpuTickGetRawVirtualNoCheck(pVM); 3716 uint32_t cCpus = pVM->cCpus; 3717 for (uint32_t i = 0; i < cCpus; i++) 3718 { 3719 PVMCPU pVCpu = pVM->apCpusR3[i]; 3720 uint64_t uOldTsc = uRawOldTsc - pVCpu->tm.s.offTSCRawSrc; 3721 pVCpu->tm.s.offTSCRawSrc = uRawNewTsc - uOldTsc; 3722 Assert(uRawNewTsc - pVCpu->tm.s.offTSCRawSrc >= uOldTsc); /* paranoia^256 */ 3723 3724 /* Update the last-seen tick here as we havent't been updating it (as we don't 3725 need it) while in pure TSC-offsetting mode. */ 3726 pVCpu->tm.s.u64TSCLastSeen = uOldTsc; 3727 } 3728 3729 LogRel(("TM: Switching TSC mode from '%s' to '%s'\n", tmR3GetTSCModeNameEx(pVM->tm.s.enmTSCMode), 3730 tmR3GetTSCModeNameEx(pVM->tm.s.enmOriginalTSCMode))); 3731 pVM->tm.s.enmTSCMode = pVM->tm.s.enmOriginalTSCMode; 3732 } 3731 3733 return VINF_SUCCESS; 3732 3734 } … … 3745 3747 { 3746 3748 int rc = VINF_SUCCESS; 3747 if ( pVM->tm.s.fTSCModeSwitchAllowed 3748 && pVM->tm.s.enmTSCMode == TMTSCMODE_REAL_TSC_OFFSET 3749 && pVM->tm.s.enmTSCMode != pVM->tm.s.enmOriginalTSCMode) 3749 if (pVM->tm.s.fTSCModeSwitchAllowed) 3750 3750 rc = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_ONCE, tmR3CpuTickParavirtDisable, NULL); 3751 3751 pVM->tm.s.fParavirtTscEnabled = false;
Note:
See TracChangeset
for help on using the changeset viewer.