From 8663586f2bc64d4761d4f621bc7aa781a4a450b2 Mon Sep 17 00:00:00 2001 From: Laurent Vivier 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 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 RH-Acked-by: Thomas Huth RH-Acked-by: David Gibson 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 Signed-off-by: Miroslav Rezanina --- 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