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 <ehabkost@redhat.com>
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 <ehabkost@redhat.com>
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 <alex.williamson@redhat.com>
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
RH-Acked-by: Igor Mammedov <imammedo@redhat.com>

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 <ehabkost@redhat.com>
---
 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 <minovotn@redhat.com>
---
 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

