From patchwork Thu Jan 21 15:09:40 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eduardo Habkost X-Patchwork-Id: 8082481 Return-Path: X-Original-To: patchwork-qemu-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 03AED9F440 for ; Thu, 21 Jan 2016 15:19:04 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 2CF73204FF for ; Thu, 21 Jan 2016 15:19:03 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 23663204A7 for ; Thu, 21 Jan 2016 15:19:02 +0000 (UTC) Received: from localhost ([::1]:48282 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aMH0n-0002hn-Ep for patchwork-qemu-devel@patchwork.kernel.org; Thu, 21 Jan 2016 10:19:01 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:50103) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aMGsf-0004gh-Jl for qemu-devel@nongnu.org; Thu, 21 Jan 2016 10:10:40 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1aMGsZ-0006x3-Fq for qemu-devel@nongnu.org; Thu, 21 Jan 2016 10:10:37 -0500 Received: from mx1.redhat.com ([209.132.183.28]:54129) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aMGsZ-0006ww-8R for qemu-devel@nongnu.org; Thu, 21 Jan 2016 10:10:31 -0500 Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) by mx1.redhat.com (Postfix) with ESMTPS id E33873D1EB; Thu, 21 Jan 2016 15:10:30 +0000 (UTC) Received: from localhost (ovpn-113-39.phx2.redhat.com [10.3.113.39]) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u0LFAT8o019700; Thu, 21 Jan 2016 10:10:30 -0500 From: Eduardo Habkost To: Peter Maydell Date: Thu, 21 Jan 2016 13:09:40 -0200 Message-Id: <1453388981-24807-12-git-send-email-ehabkost@redhat.com> In-Reply-To: <1453388981-24807-1-git-send-email-ehabkost@redhat.com> References: <1453388981-24807-1-git-send-email-ehabkost@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.27 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 209.132.183.28 Cc: qemu-devel@nongnu.org, Paolo Bonzini , =?UTF-8?q?Andreas=20F=C3=A4rber?= , Haozhong Zhang , Richard Henderson Subject: [Qemu-devel] [PULL 11/12] target-i386: Add support to migrate vcpu's TSC rate X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Haozhong Zhang 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 Reviewed-by: Eduardo Habkost [ehabkost: Rewrote comment at kvm_arch_put_registers()] [ehabkost: Moved compat code to pc-2.5] Signed-off-by: Eduardo Habkost --- hw/i386/pc.c | 1 + hw/i386/pc_piix.c | 2 ++ hw/i386/pc_q35.c | 2 ++ include/hw/i386/pc.h | 3 +++ roms/seabios | 2 +- target-i386/cpu.c | 2 +- target-i386/cpu.h | 1 + target-i386/kvm.c | 9 +++++++++ target-i386/machine.c | 30 ++++++++++++++++++++++++++++++ 9 files changed, 50 insertions(+), 2 deletions(-) diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 9e37186..293e22a 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -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"; diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index df2b824..9721912 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -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); } diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c index 412b3cd..8b76d5c 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c @@ -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); } diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index 588a33c..5bac03d 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -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" diff --git a/roms/seabios b/roms/seabios index 01a84be..33fbe13 160000 --- a/roms/seabios +++ b/roms/seabios @@ -1 +1 @@ -Subproject commit 01a84bea2d28a19d2405c1ecac4bdef17683cc0c +Subproject commit 33fbe13a3e2a01e0ba1087a8feed801a0451db21 diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 69880b7..d3f8a4e 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -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, diff --git a/target-i386/cpu.h b/target-i386/cpu.h index 77e62b2..28cbaf5 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -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; diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 23d6b86..419bb18 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -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; diff --git a/target-i386/machine.c b/target-i386/machine.c index 4d80288..0d381ac 100644 --- a/target-i386/machine.c +++ b/target-i386/machine.c @@ -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 } };