qemu-devel
[Top][All Lists]
Advanced

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

[PATCH 3/3] i386: Make sure kvm_arch_set_tsc_khz() succeeds on migration


From: Vitaly Kuznetsov
Subject: [PATCH 3/3] i386: Make sure kvm_arch_set_tsc_khz() succeeds on migration when 'hv-reenlightenment' was exposed
Date: Thu, 18 Mar 2021 17:02:49 +0100

KVM doesn't fully support Hyper-V reenlightenment notifications on
migration. In particular, it doesn't support emulating TSC frequency
of the source host by trapping all TSC accesses so unless TSC scaling
is supported on the destination host and KVM_SET_TSC_KHZ succeeds, it
is unsafe to proceed with migration.

Normally, we only require KVM_SET_TSC_KHZ to succeed when 'user_tsc_khz'
was set and just 'try' KVM_SET_TSC_KHZ without otherwise.

Introduce a new vmstate section (which is added when the guest has
reenlightenment feature enabled) and add env.tsc_khz to it. We already
have env.tsc_khz packed in 'cpu/tsc_khz' but we don't want to be dependent
on the section order.

Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
---
 target/i386/kvm/hyperv.h |  1 +
 target/i386/kvm/kvm.c    | 11 +++++++++++
 target/i386/machine.c    | 37 +++++++++++++++++++++++++++++++++++++
 3 files changed, 49 insertions(+)

diff --git a/target/i386/kvm/hyperv.h b/target/i386/kvm/hyperv.h
index 67543296c3a4..c65e5c85c4d3 100644
--- a/target/i386/kvm/hyperv.h
+++ b/target/i386/kvm/hyperv.h
@@ -20,6 +20,7 @@
 
 #ifdef CONFIG_KVM
 int kvm_hv_handle_exit(X86CPU *cpu, struct kvm_hyperv_exit *exit);
+int kvm_hv_tsc_frequency_loaded(X86CPU *cpu);
 #endif
 
 int hyperv_x86_synic_add(X86CPU *cpu);
diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
index 7fe9f527103c..f6c4093778e9 100644
--- a/target/i386/kvm/kvm.c
+++ b/target/i386/kvm/kvm.c
@@ -1460,6 +1460,17 @@ static int hyperv_init_vcpu(X86CPU *cpu)
     return 0;
 }
 
+int kvm_hv_tsc_frequency_loaded(X86CPU *cpu)
+{
+    CPUState *cs = CPU(cpu);
+
+    /*
+     * KVM doens't fully support re-enlightenment notifications so we need to
+     * make sure TSC frequency doesn't change upon migration.
+     */
+    return kvm_arch_set_tsc_khz(cs);
+}
+
 static Error *invtsc_mig_blocker;
 
 #define KVM_MAX_CPUID_ENTRIES  100
diff --git a/target/i386/machine.c b/target/i386/machine.c
index 715620c58809..369a8f1e7a7a 100644
--- a/target/i386/machine.c
+++ b/target/i386/machine.c
@@ -896,6 +896,42 @@ static const VMStateDescription 
vmstate_msr_hyperv_reenlightenment = {
         VMSTATE_END_OF_LIST()
     }
 };
+
+static bool hyperv_tsc_frequency_needed(void *opaque)
+{
+    X86CPU *cpu = opaque;
+    CPUX86State *env = &cpu->env;
+
+    return env->tsc_khz != 0 && (env->msr_hv_reenlightenment_control ||
+                                 env->msr_hv_tsc_emulation_control);
+}
+
+static int hyperv_tsc_frequency_post_load(void *opaque, int version_id)
+{
+    X86CPU *cpu = opaque;
+    int r;
+
+    r = kvm_hv_tsc_frequency_loaded(cpu);
+    if (r) {
+        error_report("Failed to set the desired TSC frequency and "
+                     "reenlightenment was exposed");
+        return -EINVAL;
+    }
+
+    return 0;
+}
+
+static const VMStateDescription vmstate_msr_hyperv_tsc_frequency = {
+    .name = "cpu/msr_hyperv_tsc_frequency",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .needed = hyperv_tsc_frequency_needed,
+    .post_load = hyperv_tsc_frequency_post_load,
+    .fields = (VMStateField[]) {
+        VMSTATE_INT64(env.tsc_khz, X86CPU),
+        VMSTATE_END_OF_LIST()
+    }
+};
 #endif
 
 static bool avx512_needed(void *opaque)
@@ -1495,6 +1531,7 @@ VMStateDescription vmstate_x86_cpu = {
         &vmstate_msr_hyperv_synic,
         &vmstate_msr_hyperv_stimer,
         &vmstate_msr_hyperv_reenlightenment,
+        &vmstate_msr_hyperv_tsc_frequency,
 #endif
         &vmstate_avx512,
         &vmstate_xss,
-- 
2.30.2




reply via email to

[Prev in Thread] Current Thread [Next in Thread]