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