Blob Blame History Raw
From 8663586f2bc64d4761d4f621bc7aa781a4a450b2 Mon Sep 17 00:00:00 2001
From: Laurent Vivier <lvivier@redhat.com>
Date: Fri, 20 Oct 2017 14:02:07 +0200
Subject: [PATCH 1/9] qemu-kvm-rhev: only allows pseries-rhel7.5.0 machine type
 with POWER9 guest

RH-Author: Laurent Vivier <lvivier@redhat.com>
Message-id: <20171020140207.15190-1-lvivier@redhat.com>
Patchwork-id: 77416
O-Subject: [RHV7.5 qemu-kvm-rhev PATCH v3 3/4] qemu-kvm-rhev: only allows pseries-rhel7.5.0 machine type with POWER9 guest
Bugzilla: 1478469
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
RH-Acked-by: Thomas Huth <thuth@redhat.com>
RH-Acked-by: David Gibson <dgibson@redhat.com>

We disable all machine types except pseries-rhel7.5.0 for POWER9
guest.

qemu-kvm-rhev does't not support POWER9 with former machine types
so disable them dynamically. We allow all machine types on POWER9
host but with guest in POWER8 CPU mode
(for instance "-M pseries-rhel7.4.0,max-cpu-compat=power8")

"-M help" display all the machine types, but if the guest is started
with "-cpu POWER9" and with a machine type which is not
"pseries-rhel7.5.0" an error message is displayed and the guest is
stopped.

We use the ppc_check_compat() to compare current CPU version with ISA
level of POWER9 (CPU_POWERPC_LOGICAL_3_00), but as POWER9 DD1 has some
bugs, POWER9 DD1 does not advertise PCR_COMPAT_3_00 (see
kvmppc_host_cpu_class_init()), and thus this allows to run all the machine
types with POWER9 DD1.

Signed-off-by: Laurent Vivier <lvivier@redhat.com>
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
 hw/ppc/spapr.c          |  2 ++
 hw/ppc/spapr_cpu_core.c | 13 +++++++++++++
 include/hw/ppc/spapr.h  |  1 +
 target/ppc/compat.c     | 11 +++++++++++
 target/ppc/cpu.h        |  1 +
 5 files changed, 28 insertions(+)

diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 5fe7769..42028ef 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -3592,6 +3592,7 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data)
      * in which LMBs are represented and hot-added
      */
     mc->numa_mem_align_shift = 28;
+    smc->has_power9_support = true;
 }
 
 static const TypeInfo spapr_machine_info = {
@@ -3993,6 +3994,7 @@ static void spapr_machine_rhel740_class_options(MachineClass *mc)
     spapr_machine_rhel750_class_options(mc);
     SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_RHEL7_4);
     mc->numa_auto_assign_ram = numa_legacy_auto_assign_ram;
+    smc->has_power9_support = false;
     smc->pre_2_10_has_unused_icps = true;
     smc->resize_hpt_default = SPAPR_RESIZE_HPT_DISABLED;
 }
diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c
index 3e731e4..400ab56 100644
--- a/hw/ppc/spapr_cpu_core.c
+++ b/hw/ppc/spapr_cpu_core.c
@@ -19,6 +19,7 @@
 #include "target/ppc/mmu-hash64.h"
 #include "sysemu/numa.h"
 #include "qemu/error-report.h"
+#include "cpu-models.h"
 
 void spapr_cpu_parse_features(sPAPRMachineState *spapr)
 {
@@ -111,6 +112,7 @@ static void spapr_cpu_init(sPAPRMachineState *spapr, PowerPCCPU *cpu,
                            Error **errp)
 {
     CPUPPCState *env = &cpu->env;
+    sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
 
     /* Set time-base frequency to 512 MHz */
     cpu_ppc_tb_init(env, SPAPR_TIMEBASE_FREQ);
@@ -118,6 +120,17 @@ static void spapr_cpu_init(sPAPRMachineState *spapr, PowerPCCPU *cpu,
     /* Enable PAPR mode in TCG or KVM */
     cpu_ppc_set_papr(cpu, PPC_VIRTUAL_HYPERVISOR(spapr));
 
+    if (!smc->has_power9_support &&
+        (((spapr->max_compat_pvr &&
+           ppc_compat_cmp(spapr->max_compat_pvr,
+                          CPU_POWERPC_LOGICAL_3_00) >= 0)) ||
+          (!spapr->max_compat_pvr &&
+           ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_3_00, 0, 0)))) {
+        error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
+                  "POWER9 CPU is not supported by this machine class");
+        return;
+    }
+
     qemu_register_reset(spapr_cpu_reset, cpu);
     spapr_cpu_reset(cpu);
 }
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index 3d0d206..d9e8e5a 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -62,6 +62,7 @@ struct sPAPRMachineClass {
     bool use_ohci_by_default;  /* use USB-OHCI instead of XHCI */
     const char *tcg_default_cpu; /* which (TCG) CPU to simulate by default */
     bool pre_2_10_has_unused_icps;
+    bool has_power9_support;
     void (*phb_placement)(sPAPRMachineState *spapr, uint32_t index,
                           uint64_t *buid, hwaddr *pio, 
                           hwaddr *mmio32, hwaddr *mmio64,
diff --git a/target/ppc/compat.c b/target/ppc/compat.c
index f8729fe..540b4eb 100644
--- a/target/ppc/compat.c
+++ b/target/ppc/compat.c
@@ -89,6 +89,17 @@ static const CompatInfo *compat_by_pvr(uint32_t pvr)
     return NULL;
 }
 
+long ppc_compat_cmp(uint32_t pvr1, uint32_t pvr2)
+{
+    const CompatInfo *compat1 = compat_by_pvr(pvr1);
+    const CompatInfo *compat2 = compat_by_pvr(pvr2);
+
+    g_assert(compat1);
+    g_assert(compat2);
+
+    return compat1 - compat2;
+}
+
 bool ppc_check_compat(PowerPCCPU *cpu, uint32_t compat_pvr,
                       uint32_t min_compat_pvr, uint32_t max_compat_pvr)
 {
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index 46d3dd8..6c770a2 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -1367,6 +1367,7 @@ static inline int cpu_mmu_index (CPUPPCState *env, bool ifetch)
 
 /* Compatibility modes */
 #if defined(TARGET_PPC64)
+long ppc_compat_cmp(uint32_t pvr1, uint32_t pvr2);
 bool ppc_check_compat(PowerPCCPU *cpu, uint32_t compat_pvr,
                       uint32_t min_compat_pvr, uint32_t max_compat_pvr);
 void ppc_set_compat(PowerPCCPU *cpu, uint32_t compat_pvr, Error **errp);
-- 
1.8.3.1