From: David Woodhouse KVM_SET_TSC_KHZ changes the vCPU's TSC scaling ratio but does not update the VM-wide cur_tsc_scaling_ratio used by get_kvmclock(). This causes get_kvmclock() to use a stale (default 1:1) ratio when computing the KVM clock, leading to drift between the host-side kvmclock and what the guest observes. Fix this by calling kvm_synchronize_tsc() after changing the TSC frequency. This: - Updates cur_tsc_scaling_ratio (consumed by pvclock_update_vm_gtod_copy) - Ensures the TSC value is continuous across the frequency change - Triggers kvm_track_tsc_matching() for proper masterclock handling - Allows subsequent vCPUs to synchronize via the 1-second slop hack Signed-off-by: David Woodhouse --- arch/x86/kvm/x86.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 06f968007f1a..3e8cc8daf848 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -212,7 +212,6 @@ module_param(mitigate_smt_rsb, bool, 0444); #ifdef CONFIG_X86_64 static bool kvm_get_time_and_clockread(s64 *kernel_ns, u64 *tsc_timestamp); #endif - #define KVM_SUPPORTED_XCR0 (XFEATURE_MASK_FP | XFEATURE_MASK_SSE \ | XFEATURE_MASK_YMM | XFEATURE_MASK_BNDREGS \ | XFEATURE_MASK_BNDCSR | XFEATURE_MASK_AVX512 \ @@ -1051,6 +1050,7 @@ static int kvm_set_tsc_khz(struct kvm_vcpu *vcpu, u32 user_tsc_khz) { u32 thresh_lo, thresh_hi; int use_scaling = 0; + u64 tsc; /* tsc_khz can be zero if TSC calibration fails */ if (user_tsc_khz == 0) { @@ -1078,7 +1078,17 @@ static int kvm_set_tsc_khz(struct kvm_vcpu *vcpu, u32 user_tsc_khz) user_tsc_khz, thresh_lo, thresh_hi); use_scaling = 1; } - return set_tsc_khz(vcpu, user_tsc_khz, use_scaling); + /* + * Read the guest TSC before changing the ratio, so we can + * re-synchronize to preserve continuity across the change. + */ + tsc = kvm_read_l1_tsc(vcpu, rdtsc()); + + if (set_tsc_khz(vcpu, user_tsc_khz, use_scaling)) + return -1; + + kvm_synchronize_tsc(vcpu, &tsc); + return 0; } static u64 compute_guest_tsc(struct kvm_vcpu *vcpu, s64 kernel_ns) -- 2.55.0