From 1c55a92bfe5e99e4c995e5a05a342d322b99a265 Mon Sep 17 00:00:00 2001 Message-Id: <1c55a92bfe5e99e4c995e5a05a342d322b99a265.1349175436.git.minovotn@redhat.com> In-Reply-To: <94968b7fa9b14e71f004474d7ce77e189e6a2bf3.1349175436.git.minovotn@redhat.com> References: <94968b7fa9b14e71f004474d7ce77e189e6a2bf3.1349175436.git.minovotn@redhat.com> From: Eduardo Habkost Date: Fri, 28 Sep 2012 21:40:11 +0200 Subject: [PATCH 14/34] enable PMU emulation only on "-cpu host" (v3) RH-Author: Eduardo Habkost Message-id: <1348868411-18680-2-git-send-email-ehabkost@redhat.com> Patchwork-id: 42545 O-Subject: [RHEL6 qemu-kvm PATCHv3 13/18] enable PMU emulation only on "-cpu host" (v3) Bugzilla: 852083 RH-Acked-by: Alex Williamson RH-Acked-by: Paolo Bonzini RH-Acked-by: Igor Mammedov Bugzilla: 852083 Upstream status: pending Fixing this upstream will require the CPU qdevification to be finished first (something that is not going to be backported to RHEL-6), so there's no point in waiting for upstream. RHEL-7 bug to avoid regressions: https://bugzilla.redhat.com/show_bug.cgi?id=860771 The current PMU emulation code on qemu-kvm is a "passthrough mode" that can break on live-migration, because it simply exposes the GET_SUPPORTED_CPUID bits (that depends on host hardware capabilities) from the kernel directly to the guest. This patch makes the PMU leaf be exposed only on "-cpu host", but with a compatibility bit that enables the old behavior on the rhel6.3.0 machine-type. Changes v2 -> v3: - Rebase on top of patch that set pmu_passthrough_enabled = true by default (resulting code is the same) Changes v1 -> v2: - Use a set_pmu_passthrough(bool) compat function, instead of enable_pmu_passthrough() Signed-off-by: Eduardo Habkost --- hw/pc.c | 1 + target-i386/cpu.h | 2 ++ target-i386/cpuid.c | 15 +++++++++++++-- 3 files changed, 16 insertions(+), 2 deletions(-) Signed-off-by: Michal Novotny --- hw/pc.c | 1 + target-i386/cpu.h | 2 ++ target-i386/cpuid.c | 15 +++++++++++++-- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/hw/pc.c b/hw/pc.c index 3e519e9..82663c9 100644 --- a/hw/pc.c +++ b/hw/pc.c @@ -1632,6 +1632,7 @@ static void rhel_common_init(const char *type1_version, static void pc_rhel630_compat(void) { disable_kvm_pv_eoi(); + set_pmu_passthrough(true); } static void pc_rhel620_compat(void) diff --git a/target-i386/cpu.h b/target-i386/cpu.h index 71fbbd0..4a80693 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -727,6 +727,8 @@ typedef struct CPUX86State { /* Flags from CPUID[EAX=7,ECX=0].EBX */ uint32_t cpuid_7_0_ebx; uint32_t cpuid_apic_id; + /* Enables direct passthrough of PMU CPUID leaf (0xA) from the kernel */ + bool cpuid_pmu_passthrough; int cpuid_vendor_override; /* MTRRs */ diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c index 3fcbeaa..1b914c4 100644 --- a/target-i386/cpuid.c +++ b/target-i386/cpuid.c @@ -89,7 +89,7 @@ int enforce_cpuid = 0; /* machine-type compatibility settings: */ static bool kvm_pv_eoi_disabled; -static bool pmu_passthrough_enabled = true; +static bool pmu_passthrough_enabled; static void host_cpuid(uint32_t function, uint32_t count, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx); @@ -192,6 +192,7 @@ typedef struct x86_def_t { int vendor_override; /* The feature bits on CPUID[EAX=7,ECX=0].EBX */ uint32_t cpuid_7_0_ebx_features; + bool pmu_passthrough; } x86_def_t; #define I486_FEATURES (CPUID_FP87 | CPUID_VME | CPUID_PSE) @@ -735,6 +736,7 @@ static int cpu_x86_fill_host(x86_def_t *x86_cpu_def) x86_cpu_def->ext3_features = ecx; cpu_x86_fill_model_id(x86_cpu_def->model_id); x86_cpu_def->vendor_override = 0; + x86_cpu_def->pmu_passthrough = true; return 0; } @@ -839,11 +841,19 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model) } plus_kvm_features = ~0; /* not supported bits will be filtered out later */ + + /* machine-type compatibility bits: */ + /* Disable PV EOI for old machine types. * Feature flags can still override. */ if (kvm_pv_eoi_disabled) { plus_kvm_features &= ~(0x1 << KVM_FEATURE_PV_EOI); } + if (pmu_passthrough_enabled) { + x86_cpu_def->pmu_passthrough = true; + } + + /* end of machine-type compatibility bits */ add_flagname_to_bitmaps("hypervisor", &plus_features, &plus_ext_features, &plus_ext2_features, &plus_ext3_features, @@ -1036,6 +1046,7 @@ int cpu_x86_register (CPUX86State *env, const char *cpu_model) env->cpuid_ext3_features = def->ext3_features; env->cpuid_7_0_ebx = def->cpuid_7_0_ebx_features; env->cpuid_kvm_features = def->kvm_features; + env->cpuid_pmu_passthrough = def->pmu_passthrough; { const char *model_id = def->model_id; int c, len, i; @@ -1232,7 +1243,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, break; case 0xA: /* Architectural Performance Monitoring Leaf */ - if (kvm_enabled() && pmu_passthrough_enabled) { + if (kvm_enabled() && env->cpuid_pmu_passthrough) { KVMState *s = env->kvm_state; *eax = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EAX); *ebx = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EBX); -- 1.7.11.4