qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] kvm: i386: allow TSC to differ by NTP correction bounds without TSC scaling
@ 2020-06-15 12:01 Marcelo Tosatti
  2020-06-16 16:58 ` [PATCH v2] " Marcelo Tosatti
  0 siblings, 1 reply; 3+ messages in thread
From: Marcelo Tosatti @ 2020-06-15 12:01 UTC (permalink / raw)
  To: qemu-devel, kvm-devel; +Cc: Paolo Bonzini, Vitaly Kuznetsov, Eduardo Habkost


The Linux TSC calibration procedure is subject to small variations
(its common to see +-1 kHz difference between reboots on a given CPU, for example).

So migrating a guest between two hosts with identical processor can fail, in case 
of a small variation in calibrated TSC between them.

Allow a conservative 250ppm error between host TSC and VM TSC frequencies,
rather than requiring an exact match. NTP daemon in the guest can
correct this difference.

Also change migration to accept this bound.

Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>

diff --git a/target/i386/kvm.c b/target/i386/kvm.c
index 34f8387..257fee4 100644
--- a/target/i386/kvm.c
+++ b/target/i386/kvm.c
@@ -739,23 +739,44 @@ static int kvm_arch_set_tsc_khz(CPUState *cs)
 {
     X86CPU *cpu = X86_CPU(cs);
     CPUX86State *env = &cpu->env;
-    int r;
+    int r, cur_freq;
+    bool set_ioctl = false;
 
     if (!env->tsc_khz) {
         return 0;
     }
 
-    r = kvm_check_extension(cs->kvm_state, KVM_CAP_TSC_CONTROL) ?
+    cur_freq = kvm_check_extension(cs->kvm_state, KVM_CAP_GET_TSC_KHZ) ?
+               kvm_vcpu_ioctl(cs, KVM_GET_TSC_KHZ) : -ENOTSUP;
+
+    /*
+     * If TSC scaling is supported, attempt to set TSC frequency.
+     */
+    if (kvm_check_extension(cs->kvm_state, KVM_CAP_TSC_CONTROL)) {
+        set_ioctl = true;
+    }
+
+    /*
+     * If desired TSC frequency is within bounds of NTP correction,
+     * attempt to set TSC frequency.
+     */
+    if (cur_freq != -ENOTSUP && freq_within_bounds(cur_freq, env->tsc_khz)) {
+        set_ioctl = true;
+    }
+
+    r = set_ioctl ?
         kvm_vcpu_ioctl(cs, KVM_SET_TSC_KHZ, env->tsc_khz) :
         -ENOTSUP;
+
     if (r < 0) {
         /* When KVM_SET_TSC_KHZ fails, it's an error only if the current
          * TSC frequency doesn't match the one we want.
          */
-        int cur_freq = kvm_check_extension(cs->kvm_state, KVM_CAP_GET_TSC_KHZ) ?
-                       kvm_vcpu_ioctl(cs, KVM_GET_TSC_KHZ) :
-                       -ENOTSUP;
-        if (cur_freq <= 0 || cur_freq != env->tsc_khz) {
+        cur_freq = kvm_check_extension(cs->kvm_state, KVM_CAP_GET_TSC_KHZ) ?
+                   kvm_vcpu_ioctl(cs, KVM_GET_TSC_KHZ) :
+                   -ENOTSUP;
+        if (cur_freq <= 0 || (cur_freq != env->tsc_khz &&
+                              !freq_within_bounds(cur_freq, env->tsc_khz))) {
             warn_report("TSC frequency mismatch between "
                         "VM (%" PRId64 " kHz) and host (%d kHz), "
                         "and TSC scaling unavailable",
diff --git a/target/i386/kvm_i386.h b/target/i386/kvm_i386.h
index 00bde7a..ebf9a64 100644
--- a/target/i386/kvm_i386.h
+++ b/target/i386/kvm_i386.h
@@ -47,4 +47,20 @@ bool kvm_has_x2apic_api(void);
 
 bool kvm_hv_vpindex_settable(void);
 
+/*
+ * Check whether target_freq is within conservative
+ * ntp correctable bounds (250ppm) of freq
+ */
+static inline bool freq_within_bounds(int freq, int target_freq)
+{
+        int max_freq = freq + (freq * 250 / 1000000);
+        int min_freq = freq - (freq * 250 / 1000000);
+
+        if (target_freq >= min_freq && target_freq <= max_freq) {
+                return true;
+        }
+
+        return false;
+}
+
 #endif
diff --git a/target/i386/machine.c b/target/i386/machine.c
index 0c96531..b052654 100644
--- a/target/i386/machine.c
+++ b/target/i386/machine.c
@@ -300,7 +300,7 @@ static int cpu_post_load(void *opaque, int version_id)
     int i;
 
     if (env->tsc_khz && env->user_tsc_khz &&
-        env->tsc_khz != env->user_tsc_khz) {
+        !freq_within_bounds(env->tsc_khz, env->user_tsc_khz)) {
         error_report("Mismatch between user-specified TSC frequency and "
                      "migrated TSC frequency");
         return -EINVAL;



^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2020-06-16 21:37 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2020-06-15 12:01 [PATCH] kvm: i386: allow TSC to differ by NTP correction bounds without TSC scaling Marcelo Tosatti
2020-06-16 16:58 ` [PATCH v2] " Marcelo Tosatti
2020-06-16 21:35   ` no-reply

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).