diff options
author | David Gibson <david@gibson.dropbear.id.au> | 2017-06-11 20:33:59 +0800 |
---|---|---|
committer | David Gibson <david@gibson.dropbear.id.au> | 2017-06-30 14:03:31 +1000 |
commit | 7843c0d60db694b6d97e14ec5538fb97424016c1 (patch) | |
tree | 8b01e6524df27e8e46f5ad77696a11dd9701c4ee /hw | |
parent | a733371214b68881d84725a3c71f60e2faf3b8e2 (diff) | |
download | qemu-7843c0d60db694b6d97e14ec5538fb97424016c1.zip qemu-7843c0d60db694b6d97e14ec5538fb97424016c1.tar.gz qemu-7843c0d60db694b6d97e14ec5538fb97424016c1.tar.bz2 |
pseries: Move CPU compatibility property to machine
Server class POWER CPUs have a "compat" property, which is used to set the
backwards compatibility mode for the processor. However, this only makes
sense for machine types which don't give the guest access to hypervisor
privilege - otherwise the compatibility level is under the guest's control.
To reflect this, this removes the CPU 'compat' property and instead
creates a 'max-cpu-compat' property on the pseries machine. Strictly
speaking this breaks compatibility, but AFAIK the 'compat' option was
never (directly) used with -device or device_add.
The option was used with -cpu. So, to maintain compatibility, this
patch adds a hack to the cpu option parsing to strip out any compat
options supplied with -cpu and set them on the machine property
instead of the now deprecated cpu property.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Tested-by: Suraj Jitindar Singh <sjitindarsingh@gmail.com>
Reviewed-by: Greg Kurz <groug@kaod.org>
Tested-by: Greg Kurz <groug@kaod.org>
Tested-by: Andrea Bolognani <abologna@redhat.com>
Diffstat (limited to 'hw')
-rw-r--r-- | hw/ppc/spapr.c | 6 | ||||
-rw-r--r-- | hw/ppc/spapr_cpu_core.c | 55 | ||||
-rw-r--r-- | hw/ppc/spapr_hcall.c | 8 |
3 files changed, 62 insertions, 7 deletions
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index ea44358..67d4c13 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -2131,7 +2131,7 @@ static void ppc_spapr_init(MachineState *machine) machine->cpu_model = kvm_enabled() ? "host" : smc->tcg_default_cpu; } - ppc_cpu_parse_features(machine->cpu_model); + spapr_cpu_parse_features(spapr); spapr_init_cpus(spapr); @@ -2503,6 +2503,10 @@ static void spapr_machine_initfn(Object *obj) " place of standard EPOW events when possible" " (required for memory hot-unplug support)", NULL); + + ppc_compat_add_property(obj, "max-cpu-compat", &spapr->max_compat_pvr, + "Maximum permitted CPU compatibility mode", + &error_fatal); } static void spapr_machine_finalizefn(Object *obj) diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c index 9fb896b..97472fd 100644 --- a/hw/ppc/spapr_cpu_core.c +++ b/hw/ppc/spapr_cpu_core.c @@ -20,6 +20,57 @@ #include "sysemu/numa.h" #include "qemu/error-report.h" +void spapr_cpu_parse_features(sPAPRMachineState *spapr) +{ + /* + * Backwards compatibility hack: + * + * CPUs had a "compat=" property which didn't make sense for + * anything except pseries. It was replaced by "max-cpu-compat" + * machine option. This supports old command lines like + * -cpu POWER8,compat=power7 + * By stripping the compat option and applying it to the machine + * before passing it on to the cpu level parser. + */ + gchar **inpieces; + int i, j; + gchar *compat_str = NULL; + + inpieces = g_strsplit(MACHINE(spapr)->cpu_model, ",", 0); + + /* inpieces[0] is the actual model string */ + i = 1; + j = 1; + while (inpieces[i]) { + if (g_str_has_prefix(inpieces[i], "compat=")) { + /* in case of multiple compat= options */ + g_free(compat_str); + compat_str = inpieces[i]; + } else { + j++; + } + + i++; + /* Excise compat options from list */ + inpieces[j] = inpieces[i]; + } + + if (compat_str) { + char *val = compat_str + strlen("compat="); + gchar *newprops = g_strjoinv(",", inpieces); + + object_property_set_str(OBJECT(spapr), val, "max-cpu-compat", + &error_fatal); + + ppc_cpu_parse_features(newprops); + g_free(newprops); + } else { + ppc_cpu_parse_features(MACHINE(spapr)->cpu_model); + } + + g_strfreev(inpieces); +} + static void spapr_cpu_reset(void *opaque) { sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine()); @@ -67,10 +118,10 @@ 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 (cpu->max_compat) { + if (spapr->max_compat_pvr) { Error *local_err = NULL; - ppc_set_compat(cpu, cpu->max_compat, &local_err); + ppc_set_compat(cpu, spapr->max_compat_pvr, &local_err); if (local_err) { error_propagate(errp, local_err); return; diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c index aa1ffea..8624ce8 100644 --- a/hw/ppc/spapr_hcall.c +++ b/hw/ppc/spapr_hcall.c @@ -1045,11 +1045,11 @@ static target_ulong h_signal_sys_reset(PowerPCCPU *cpu, } } -static uint32_t cas_check_pvr(PowerPCCPU *cpu, target_ulong *addr, - Error **errp) +static uint32_t cas_check_pvr(sPAPRMachineState *spapr, PowerPCCPU *cpu, + target_ulong *addr, Error **errp) { bool explicit_match = false; /* Matched the CPU's real PVR */ - uint32_t max_compat = cpu->max_compat; + uint32_t max_compat = spapr->max_compat_pvr; uint32_t best_compat = 0; int i; @@ -1105,7 +1105,7 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu, bool guest_radix; Error *local_err = NULL; - cas_pvr = cas_check_pvr(cpu, &addr, &local_err); + cas_pvr = cas_check_pvr(spapr, cpu, &addr, &local_err); if (local_err) { error_report_err(local_err); return H_HARDWARE; |