]> git.proxmox.com Git - mirror_qemu.git/commitdiff
target-i386: Add support to migrate vcpu's TSC rate
authorHaozhong Zhang <haozhong.zhang@intel.com>
Tue, 24 Nov 2015 03:33:57 +0000 (11:33 +0800)
committerEduardo Habkost <ehabkost@redhat.com>
Thu, 21 Jan 2016 14:47:16 +0000 (12:47 -0200)
This patch enables migrating vcpu's TSC rate. If KVM on the
destination machine supports TSC scaling, guest programs will
observe a consistent TSC rate across the migration.

If TSC scaling is not supported on the destination machine, the
migration will not be aborted and QEMU on the destination will
not set vcpu's TSC rate to the migrated value.

If vcpu's TSC rate specified by CPU option 'tsc-freq' on the
destination machine is inconsistent with the migrated TSC rate,
the migration will be aborted.

For backwards compatibility, the migration of vcpu's TSC rate is
disabled on pc-*-2.5 and older machine types.

Signed-off-by: Haozhong Zhang <haozhong.zhang@intel.com>
Reviewed-by: Eduardo Habkost <ehabkost@redhat.com>
[ehabkost: Rewrote comment at kvm_arch_put_registers()]
[ehabkost: Moved compat code to pc-2.5]
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
hw/i386/pc.c
hw/i386/pc_piix.c
hw/i386/pc_q35.c
include/hw/i386/pc.h
roms/seabios
target-i386/cpu.c
target-i386/cpu.h
target-i386/kvm.c
target-i386/machine.c

index 9e371867765c40214147de3ec0fe15bee4cf34f1..293e22a7e1526b225f224ad1826637431f13ca4e 100644 (file)
@@ -1963,6 +1963,7 @@ static void pc_machine_class_init(ObjectClass *oc, void *data)
     /* BIOS ACPI tables: 128K. Other BIOS datastructures: less than 4K reported
      * to be used at the moment, 32K should be enough for a while.  */
     pcmc->acpi_data_size = 0x20000 + 0x8000;
+    pcmc->save_tsc_khz = true;
     mc->get_hotplug_handler = pc_get_hotpug_handler;
     mc->cpu_index_to_socket_id = pc_cpu_index_to_socket_id;
     mc->default_boot_order = "cad";
index df2b824385b8626244d2487d8d539a417a0885da..97219129ace1c8f8a008c524a6f3a78e3a5cb4a6 100644 (file)
@@ -432,9 +432,11 @@ DEFINE_I440FX_MACHINE(v2_6, "pc-i440fx-2.6", NULL,
 
 static void pc_i440fx_2_5_machine_options(MachineClass *m)
 {
+    PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
     pc_i440fx_2_6_machine_options(m);
     m->alias = NULL;
     m->is_default = 0;
+    pcmc->save_tsc_khz = false;
     SET_MACHINE_COMPAT(m, PC_COMPAT_2_5);
 }
 
index 412b3cd375aa95e6cc11ee78bdbcf1d14b06c506..8b76d5c94b0301db463471d2b840c24fc9b0c8cc 100644 (file)
@@ -360,8 +360,10 @@ DEFINE_Q35_MACHINE(v2_6, "pc-q35-2.6", NULL,
 
 static void pc_q35_2_5_machine_options(MachineClass *m)
 {
+    PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
     pc_q35_2_6_machine_options(m);
     m->alias = NULL;
+    pcmc->save_tsc_khz = false;
     SET_MACHINE_COMPAT(m, PC_COMPAT_2_5);
 }
 
index 588a33cfa3733248b1edb322ecd70ef5476d90eb..5bac03d9757d738190fb4ce36e5938e4c39bcec2 100644 (file)
@@ -120,6 +120,9 @@ struct PCMachineClass {
     bool has_reserved_memory;
     bool enforce_aligned_dimm;
     bool broken_reserved_end;
+
+    /* TSC rate migration: */
+    bool save_tsc_khz;
 };
 
 #define TYPE_PC_MACHINE "generic-pc-machine"
index 01a84bea2d28a19d2405c1ecac4bdef17683cc0c..33fbe13a3e2a01e0ba1087a8feed801a0451db21 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 01a84bea2d28a19d2405c1ecac4bdef17683cc0c
+Subproject commit 33fbe13a3e2a01e0ba1087a8feed801a0451db21
index 69880b79fab879a8d1d4f59d59b477515a1d16a7..d3f8a4e4eace199b563b83c9ad24ac74cbebb902 100644 (file)
@@ -1728,7 +1728,7 @@ static void x86_cpuid_set_tsc_freq(Object *obj, Visitor *v, void *opaque,
         return;
     }
 
-    cpu->env.tsc_khz = value / 1000;
+    cpu->env.tsc_khz = cpu->env.user_tsc_khz = value / 1000;
 }
 
 static void x86_cpuid_get_apic_id(Object *obj, Visitor *v, void *opaque,
index 77e62b250673d89a78981afd9d5b9f5af0b31340..28cbaf503061d4e84cf74be788aa9366dc5e7aac 100644 (file)
@@ -978,6 +978,7 @@ typedef struct CPUX86State {
     uint32_t sipi_vector;
     bool tsc_valid;
     int64_t tsc_khz;
+    int64_t user_tsc_khz; /* for sanity check only */
     void *kvm_xsave_buf;
 
     uint64_t mcg_cap;
index 23d6b869a342ee9275ee79d771df6b8fbd78ccaf..419bb18bb3def9123790003779be01df8ab2977a 100644 (file)
@@ -2507,6 +2507,15 @@ int kvm_arch_put_registers(CPUState *cpu, int level)
         }
     }
 
+    if (level == KVM_PUT_FULL_STATE) {
+        /* We don't check for kvm_arch_set_tsc_khz() errors here,
+         * because TSC frequency mismatch shouldn't abort migration,
+         * unless the user explicitly asked for a more strict TSC
+         * setting (e.g. using an explicit "tsc-freq" option).
+         */
+        kvm_arch_set_tsc_khz(cpu);
+    }
+
     ret = kvm_getput_regs(x86_cpu, 1);
     if (ret < 0) {
         return ret;
index 4d802882f529d4294f84e1458ddfbd8e67ac79dc..0d381ac0c0e118a49ebb1b8b738df54d5359cd18 100644 (file)
@@ -6,6 +6,8 @@
 #include "cpu.h"
 #include "sysemu/kvm.h"
 
+#include "qemu/error-report.h"
+
 static const VMStateDescription vmstate_segment = {
     .name = "segment",
     .version_id = 1,
@@ -331,6 +333,13 @@ static int cpu_post_load(void *opaque, int version_id)
     CPUX86State *env = &cpu->env;
     int i;
 
+    if (env->tsc_khz && env->user_tsc_khz &&
+        env->tsc_khz != env->user_tsc_khz) {
+        error_report("Mismatch between user-specified TSC frequency and "
+                     "migrated TSC frequency");
+        return -EINVAL;
+    }
+
     /*
      * Real mode guest segments register DPL should be zero.
      * Older KVM version were setting it wrongly.
@@ -839,6 +848,26 @@ static const VMStateDescription vmstate_xss = {
     }
 };
 
+static bool tsc_khz_needed(void *opaque)
+{
+    X86CPU *cpu = opaque;
+    CPUX86State *env = &cpu->env;
+    MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine());
+    PCMachineClass *pcmc = PC_MACHINE_CLASS(mc);
+    return env->tsc_khz && pcmc->save_tsc_khz;
+}
+
+static const VMStateDescription vmstate_tsc_khz = {
+    .name = "cpu/tsc_khz",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .needed = tsc_khz_needed,
+    .fields = (VMStateField[]) {
+        VMSTATE_INT64(env.tsc_khz, X86CPU),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
 VMStateDescription vmstate_x86_cpu = {
     .name = "cpu",
     .version_id = 12,
@@ -961,6 +990,7 @@ VMStateDescription vmstate_x86_cpu = {
         &vmstate_msr_hyperv_stimer,
         &vmstate_avx512,
         &vmstate_xss,
+        &vmstate_tsc_khz,
         NULL
     }
 };