218e99
From 99ce2407227bd5474e69c93ab0f061f2a3438eac Mon Sep 17 00:00:00 2001
218e99
From: Eduardo Habkost <ehabkost@redhat.com>
218e99
Date: Fri, 2 Aug 2013 14:08:52 +0200
218e99
Subject: target-i386: Disable PMU CPUID leaf by default
218e99
218e99
RH-Author: Eduardo Habkost <ehabkost@redhat.com>
218e99
Message-id: <1375452533-12507-3-git-send-email-ehabkost@redhat.com>
218e99
Patchwork-id: 52933
218e99
O-Subject: [RHEL-7 PATCH 2/3] target-i386: Disable PMU CPUID leaf by default
218e99
Bugzilla: 853101
218e99
RH-Acked-by: Bandan Das <bsd@redhat.com>
218e99
RH-Acked-by: Markus Armbruster <armbru@redhat.com>
218e99
RH-Acked-by: Gleb Natapov <gleb@redhat.com>
218e99
218e99
Bugzilla: 853101
218e99
218e99
Bug description: QEMU currently gets all bits from GET_SUPPORTED_CPUID
218e99
for CPUID leaf 0xA and passes them directly to the guest. This makes
218e99
the guest ABI depend on host kernel and host CPU capabilities, and
218e99
breaks live migration if we migrate between hosts with different
218e99
capabilities (e.g., different number of PMU counters).
218e99
218e99
Add a "pmu" property to X86CPU, and set it to true only on "-cpu host",
218e99
or on pc-*-1.5 and older machine-types.
218e99
218e99
For now, setting pmu=on will enable the current passthrough mode that
218e99
doesn't have any ABI stability guarantees, but in the future we may
218e99
implement a mode where the PMU CPUID bits are stable and configurable.
218e99
218e99
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
218e99
Cc: Paolo Bonzini <pbonzini@redhat.com>
218e99
Signed-off-by: Andreas Färber <afaerber@suse.de>
218e99
(cherry picked from commit 9337e3b6e1d779215423d9b419d42200506deaab)
218e99
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
218e99
218e99
Conflicts:
218e99
	include/hw/i386/pc.h
218e99
	target-i386/cpu.c
218e99
218e99
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
218e99
index 6692728..45487ba 100644
218e99
--- a/include/hw/i386/pc.h
218e99
+++ b/include/hw/i386/pc.h
218e99
@@ -211,6 +211,10 @@ int e820_add_entry(uint64_t, uint64_t, uint32_t);
218e99
             .driver   = "Nehalem-" TYPE_X86_CPU,\
218e99
             .property = "level",\
218e99
             .value    = stringify(2),\
218e99
+        },{\
218e99
+            .driver = TYPE_X86_CPU,\
218e99
+            .property = "pmu",\
218e99
+            .value = "on",\
218e99
         }
218e99
 
218e99
 #define PC_COMPAT_1_4 \
218e99
diff --git a/target-i386/cpu-qom.h b/target-i386/cpu-qom.h
218e99
index 849cedf..5231005 100644
218e99
--- a/target-i386/cpu-qom.h
218e99
+++ b/target-i386/cpu-qom.h
218e99
@@ -68,6 +68,13 @@ typedef struct X86CPU {
218e99
 
218e99
     /* Features that were filtered out because of missing host capabilities */
218e99
     uint32_t filtered_features[FEATURE_WORDS];
218e99
+
218e99
+    /* Enable PMU CPUID bits. This can't be enabled by default yet because
218e99
+     * it doesn't have ABI stability guarantees, as it passes all PMU CPUID
218e99
+     * bits returned by GET_SUPPORTED_CPUID (that depend on host CPU and kernel
218e99
+     * capabilities) directly to the guest.
218e99
+     */
218e99
+    bool enable_pmu;
218e99
 } X86CPU;
218e99
 
218e99
 static inline X86CPU *x86_env_get_cpu(CPUX86State *env)
218e99
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
218e99
index 0c9a99a..2bcc21e 100644
218e99
--- a/target-i386/cpu.c
218e99
+++ b/target-i386/cpu.c
218e99
@@ -1479,6 +1479,7 @@ static int cpu_x86_find_by_name(X86CPU *cpu, x86_def_t *x86_cpu_def,
218e99
                                 const char *name)
218e99
 {
218e99
     x86_def_t *def;
218e99
+    Error *err = NULL;
218e99
     int i;
218e99
 
218e99
     if (name == NULL) {
218e99
@@ -1486,6 +1487,8 @@ static int cpu_x86_find_by_name(X86CPU *cpu, x86_def_t *x86_cpu_def,
218e99
     }
218e99
     if (kvm_enabled() && strcmp(name, "host") == 0) {
218e99
         kvm_cpu_fill_host(x86_cpu_def);
218e99
+        object_property_set_bool(OBJECT(cpu), true, "pmu", &err);
218e99
+        assert_no_error(err);
218e99
         return 0;
218e99
     }
218e99
 
218e99
@@ -2017,7 +2020,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
218e99
         break;
218e99
     case 0xA:
218e99
         /* Architectural Performance Monitoring Leaf */
218e99
-        if (kvm_enabled()) {
218e99
+        if (kvm_enabled() && cpu->enable_pmu) {
218e99
             KVMState *s = cs->kvm_state;
218e99
 
218e99
             *eax = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EAX);
218e99
@@ -2506,6 +2509,11 @@ static int64_t x86_cpu_get_arch_id(CPUState *cs)
218e99
     return env->cpuid_apic_id;
218e99
 }
218e99
 
218e99
+static Property x86_cpu_properties[] = {
218e99
+    DEFINE_PROP_BOOL("pmu", X86CPU, enable_pmu, false),
218e99
+    DEFINE_PROP_END_OF_LIST()
218e99
+};
218e99
+
218e99
 static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
218e99
 {
218e99
     X86CPUClass *xcc = X86_CPU_CLASS(oc);
218e99
@@ -2515,6 +2523,7 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
218e99
     xcc->parent_realize = dc->realize;
218e99
     dc->realize = x86_cpu_realizefn;
218e99
     dc->bus_type = TYPE_ICC_BUS;
218e99
+    dc->props = x86_cpu_properties;
218e99
 
218e99
     xcc->parent_reset = cc->reset;
218e99
     cc->reset = x86_cpu_reset;