From: David Woodhouse <[email protected]> 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 <[email protected]> --- arch/x86/kvm/x86.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index ac982652e5e0..833a4f119e22 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -206,6 +206,7 @@ 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 +static void kvm_synchronize_tsc(struct kvm_vcpu *vcpu, u64 *user_value); #define KVM_MAX_NR_USER_RETURN_MSRS 16 struct kvm_user_return_msrs { @@ -2611,7 +2612,20 @@ 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); + if (set_tsc_khz(vcpu, user_tsc_khz, use_scaling)) + return -1; + + /* + * Re-synchronize the TSC after changing frequency. This ensures + * cur_tsc_scaling_ratio is updated (used by get_kvmclock) and + * the TSC value is continuous across the frequency change. + */ + { + u64 tsc = kvm_read_l1_tsc(vcpu, rdtsc()); + + kvm_synchronize_tsc(vcpu, &tsc); + } + return 0; } static s64 compute_guest_tsc(struct kvm_vcpu *vcpu, s64 kernel_ns) -- 2.43.0
smime.p7s
Description: S/MIME cryptographic signature

