提交 36f96c4b 编写于 作者: H Haozhong Zhang 提交者: Eduardo Habkost

target-i386: Add support to migrate vcpu's TSC rate

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: NHaozhong Zhang <haozhong.zhang@intel.com>
Reviewed-by: NEduardo Habkost <ehabkost@redhat.com>
[ehabkost: Rewrote comment at kvm_arch_put_registers()]
[ehabkost: Moved compat code to pc-2.5]
Signed-off-by: NEduardo Habkost <ehabkost@redhat.com>
上级 5031283d
......@@ -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";
......
......@@ -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);
}
......
......@@ -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);
}
......
......@@ -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"
......
seabios @ 33fbe13a
Subproject commit 01a84bea2d28a19d2405c1ecac4bdef17683cc0c
Subproject commit 33fbe13a3e2a01e0ba1087a8feed801a0451db21
......@@ -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,
......
......@@ -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;
......
......@@ -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;
......
......@@ -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
}
};
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册