[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH v7 23/36] KVM: x86: Re-synchronize TSC after KVM_SET_TSC_KHZ



From: David Woodhouse <dwmw@xxxxxxxxxxxx>

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 <dwmw@xxxxxxxxxxxx>
---
 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




 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.