summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Maydell2017-10-17 16:26:51 +0200
committerPeter Maydell2017-10-17 16:26:51 +0200
commit861cd431c99e56ddb5953ca1da164a9c32b477ca (patch)
tree09fe4c00de95986b32078b1836a52c49bfc6dd6e
parentMerge remote-tracking branch 'remotes/mjt/tags/trivial-patches-fetch' into st... (diff)
parentspapr_cpu_core: rewrite machine type sanity check (diff)
downloadqemu-861cd431c99e56ddb5953ca1da164a9c32b477ca.tar.gz
qemu-861cd431c99e56ddb5953ca1da164a9c32b477ca.tar.xz
qemu-861cd431c99e56ddb5953ca1da164a9c32b477ca.zip
Merge remote-tracking branch 'remotes/dgibson/tags/ppc-for-2.11-20171017' into staging
ppc patch queue 2017-10-17 Here's the currently accumulated set of ppc patches for qemu. * The biggest set here is the ppc parts of Igor Mammedov's cleanups to cpu model handling * The above also includes a generic patches which are required as prerequisites for the ppc parts. They don't seem to have been merged by Eduardo yet, so I hope they're ok to include here. * Apart from that it's basically just assorted bug fixes and cleanups # gpg: Signature made Tue 17 Oct 2017 05:20:03 BST # gpg: using RSA key 0x6C38CACA20D9B392 # gpg: Good signature from "David Gibson <david@gibson.dropbear.id.au>" # gpg: aka "David Gibson (Red Hat) <dgibson@redhat.com>" # gpg: aka "David Gibson (ozlabs.org) <dgibson@ozlabs.org>" # gpg: aka "David Gibson (kernel.org) <dwg@kernel.org>" # Primary key fingerprint: 75F4 6586 AE61 A66C C44E 87DC 6C38 CACA 20D9 B392 * remotes/dgibson/tags/ppc-for-2.11-20171017: (34 commits) spapr_cpu_core: rewrite machine type sanity check spapr_pci: fail gracefully with non-pseries machine types spapr: Correct RAM size calculation for HPT resizing ppc: pnv: consolidate type definitions and batch register them ppc: pnv: drop PnvChipClass::cpu_model field ppc: pnv: define core types statically ppc: pnv: drop PnvCoreClass::cpu_oc field ppc: pnv: normalize core/chip type names ppc: pnv: use generic cpu_model parsing ppc: spapr: use generic cpu_model parsing ppc: move ppc_cpu_lookup_alias() before its first user ppc: spapr: use cpu model names as tcg defaults instead of aliases ppc: spapr: register 'host' core type along with the rest of core types ppc: spapr: use cpu type name directly ppc: spapr: define core types statically ppc: move '-cpu foo,compat=xxx' parsing into ppc_cpu_parse_featurestr() ppc: spapr: replace ppc_cpu_parse_features() with cpu_parse_cpu_model() ppc: 40p/prep: replace cpu_model with cpu_type ppc: virtex-ml507: replace cpu_model with cpu_type ppc: replace cpu_model with cpu_type on ref405ep,taihu boards ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--hw/ide/macio.c4
-rw-r--r--hw/ppc/e500.c8
-rw-r--r--hw/ppc/e500plat.c1
-rw-r--r--hw/ppc/mac_newworld.c15
-rw-r--r--hw/ppc/mac_oldworld.c6
-rw-r--r--hw/ppc/mpc8544ds.c2
-rw-r--r--hw/ppc/pnv.c134
-rw-r--r--hw/ppc/pnv_core.c67
-rw-r--r--hw/ppc/ppc.c25
-rw-r--r--hw/ppc/ppc405_uc.c6
-rw-r--r--hw/ppc/ppc440_bamboo.c7
-rw-r--r--hw/ppc/ppc4xx_devs.c4
-rw-r--r--hw/ppc/prep.c12
-rw-r--r--hw/ppc/spapr.c51
-rw-r--r--hw/ppc/spapr_cpu_core.c196
-rw-r--r--hw/ppc/spapr_hcall.c4
-rw-r--r--hw/ppc/spapr_pci.c12
-rw-r--r--hw/ppc/virtex_ml507.c11
-rw-r--r--include/hw/ppc/pnv.h12
-rw-r--r--include/hw/ppc/pnv_core.h4
-rw-r--r--include/hw/ppc/ppc.h2
-rw-r--r--include/hw/ppc/spapr.h2
-rw-r--r--include/hw/ppc/spapr_cpu_core.h7
-rw-r--r--include/qom/object.h46
-rw-r--r--qom/object.c9
-rw-r--r--target/ppc/cpu-models.c6
-rw-r--r--target/ppc/cpu-models.h1
-rw-r--r--target/ppc/cpu-qom.h1
-rw-r--r--target/ppc/cpu.h1
-rw-r--r--target/ppc/int_helper.c16
-rw-r--r--target/ppc/kvm.c22
-rw-r--r--target/ppc/translate.c12
-rw-r--r--target/ppc/translate_init.c286
33 files changed, 378 insertions, 614 deletions
diff --git a/hw/ide/macio.c b/hw/ide/macio.c
index ce194c6cec..2e043ef1ea 100644
--- a/hw/ide/macio.c
+++ b/hw/ide/macio.c
@@ -353,12 +353,14 @@ static const MemoryRegionOps pmac_ide_ops = {
static const VMStateDescription vmstate_pmac = {
.name = "ide",
- .version_id = 4,
+ .version_id = 5,
.minimum_version_id = 0,
.fields = (VMStateField[]) {
VMSTATE_IDE_BUS(bus, MACIOIDEState),
VMSTATE_IDE_DRIVES(bus.ifs, MACIOIDEState),
VMSTATE_BOOL(dma_active, MACIOIDEState),
+ VMSTATE_UINT32(timing_reg, MACIOIDEState),
+ VMSTATE_UINT32(irq_reg, MACIOIDEState),
VMSTATE_END_OF_LIST()
}
};
diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
index db0e49ab8f..9178e70132 100644
--- a/hw/ppc/e500.c
+++ b/hw/ppc/e500.c
@@ -803,11 +803,6 @@ void ppce500_init(MachineState *machine, PPCE500Params *params)
SysBusDevice *s;
PPCE500CCSRState *ccsr;
- /* Setup CPUs */
- if (machine->cpu_model == NULL) {
- machine->cpu_model = "e500v2_v30";
- }
-
irqs = g_malloc0(smp_cpus * sizeof(qemu_irq *));
irqs[0] = g_malloc0(smp_cpus * sizeof(qemu_irq) * OPENPIC_OUTPUT_NB);
for (i = 0; i < smp_cpus; i++) {
@@ -815,8 +810,7 @@ void ppce500_init(MachineState *machine, PPCE500Params *params)
CPUState *cs;
qemu_irq *input;
- cpu = POWERPC_CPU(cpu_generic_init(TYPE_POWERPC_CPU,
- machine->cpu_model));
+ cpu = POWERPC_CPU(cpu_create(machine->cpu_type));
env = &cpu->env;
cs = CPU(cpu);
diff --git a/hw/ppc/e500plat.c b/hw/ppc/e500plat.c
index 94b454551f..e59e80fb9e 100644
--- a/hw/ppc/e500plat.c
+++ b/hw/ppc/e500plat.c
@@ -64,6 +64,7 @@ static void e500plat_machine_init(MachineClass *mc)
mc->init = e500plat_init;
mc->max_cpus = 32;
mc->has_dynamic_sysbus = true;
+ mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("e500v2_v30");
}
DEFINE_MACHINE("ppce500", e500plat_machine_init)
diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c
index 6d0ace20ca..3fa7c429d5 100644
--- a/hw/ppc/mac_newworld.c
+++ b/hw/ppc/mac_newworld.c
@@ -174,16 +174,8 @@ static void ppc_core99_init(MachineState *machine)
linux_boot = (kernel_filename != NULL);
/* init CPUs */
- if (machine->cpu_model == NULL) {
-#ifdef TARGET_PPC64
- machine->cpu_model = "970fx";
-#else
- machine->cpu_model = "G4";
-#endif
- }
for (i = 0; i < smp_cpus; i++) {
- cpu = POWERPC_CPU(cpu_generic_init(TYPE_POWERPC_CPU,
- machine->cpu_model));
+ cpu = POWERPC_CPU(cpu_create(machine->cpu_type));
env = &cpu->env;
/* Set time-base frequency to 100 Mhz */
@@ -520,6 +512,11 @@ static void core99_machine_class_init(ObjectClass *oc, void *data)
mc->max_cpus = MAX_CPUS;
mc->default_boot_order = "cd";
mc->kvm_type = core99_kvm_type;
+#ifdef TARGET_PPC64
+ mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("970fx_v3.1");
+#else
+ mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("7400_v2.9");
+#endif
}
static const TypeInfo core99_machine_info = {
diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c
index bc7c8b7bd7..010ea36bf2 100644
--- a/hw/ppc/mac_oldworld.c
+++ b/hw/ppc/mac_oldworld.c
@@ -108,11 +108,8 @@ static void ppc_heathrow_init(MachineState *machine)
linux_boot = (kernel_filename != NULL);
/* init CPUs */
- if (machine->cpu_model == NULL)
- machine->cpu_model = "G3";
for (i = 0; i < smp_cpus; i++) {
- cpu = POWERPC_CPU(cpu_generic_init(TYPE_POWERPC_CPU,
- machine->cpu_model));
+ cpu = POWERPC_CPU(cpu_create(machine->cpu_type));
env = &cpu->env;
/* Set time-base frequency to 16.6 Mhz */
@@ -385,6 +382,7 @@ static void heathrow_class_init(ObjectClass *oc, void *data)
/* TOFIX "cad" when Mac floppy is implemented */
mc->default_boot_order = "cd";
mc->kvm_type = heathrow_kvm_type;
+ mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("750_v3.1");
}
static const TypeInfo ppc_heathrow_machine_info = {
diff --git a/hw/ppc/mpc8544ds.c b/hw/ppc/mpc8544ds.c
index 27b8289016..1717953ec7 100644
--- a/hw/ppc/mpc8544ds.c
+++ b/hw/ppc/mpc8544ds.c
@@ -16,6 +16,7 @@
#include "sysemu/device_tree.h"
#include "hw/ppc/openpic.h"
#include "qemu/error-report.h"
+#include "cpu.h"
static void mpc8544ds_fixup_devtree(PPCE500Params *params, void *fdt)
{
@@ -55,6 +56,7 @@ static void ppce500_machine_init(MachineClass *mc)
mc->desc = "mpc8544ds";
mc->init = mpc8544ds_init;
mc->max_cpus = 15;
+ mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("e500v2_v30");
}
DEFINE_MACHINE("mpc8544ds", ppce500_machine_init)
diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index d46d91c76f..c35c439d81 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -55,6 +55,16 @@
#define KERNEL_LOAD_ADDR 0x20000000
#define INITRD_LOAD_ADDR 0x40000000
+static const char *pnv_chip_core_typename(const PnvChip *o)
+{
+ const char *chip_type = object_class_get_name(object_get_class(OBJECT(o)));
+ int len = strlen(chip_type) - strlen(PNV_CHIP_TYPE_SUFFIX);
+ char *s = g_strdup_printf(PNV_CORE_TYPE_NAME("%.*s"), len, chip_type);
+ const char *core_type = object_class_get_name(object_class_by_name(s));
+ g_free(s);
+ return core_type;
+}
+
/*
* On Power Systems E880 (POWER8), the max cpus (threads) should be :
* 4 * 4 sockets * 12 cores * 8 threads = 1536
@@ -92,8 +102,7 @@ static int get_cpus_node(void *fdt)
int cpus_offset = fdt_path_offset(fdt, "/cpus");
if (cpus_offset < 0) {
- cpus_offset = fdt_add_subnode(fdt, fdt_path_offset(fdt, "/"),
- "cpus");
+ cpus_offset = fdt_add_subnode(fdt, 0, "cpus");
if (cpus_offset) {
_FDT((fdt_setprop_cell(fdt, cpus_offset, "#address-cells", 0x1)));
_FDT((fdt_setprop_cell(fdt, cpus_offset, "#size-cells", 0x0)));
@@ -270,8 +279,7 @@ static int pnv_chip_lpc_offset(PnvChip *chip, void *fdt)
static void powernv_populate_chip(PnvChip *chip, void *fdt)
{
- PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
- char *typename = pnv_core_typename(pcc->cpu_model);
+ const char *typename = pnv_chip_core_typename(chip);
size_t typesize = object_type_get_instance_size(typename);
int i;
@@ -301,7 +309,6 @@ static void powernv_populate_chip(PnvChip *chip, void *fdt)
powernv_populate_memory_node(fdt, chip->chip_id, chip->ram_start,
chip->ram_size);
}
- g_free(typename);
}
static void powernv_populate_rtc(ISADevice *d, void *fdt, int lpc_off)
@@ -607,16 +614,13 @@ static void ppc_powernv_init(MachineState *machine)
}
}
- /* We need some cpu model to instantiate the PnvChip class */
- if (machine->cpu_model == NULL) {
- machine->cpu_model = "POWER8";
- }
-
/* Create the processor chips */
- chip_typename = g_strdup_printf(TYPE_PNV_CHIP "-%s", machine->cpu_model);
+ i = strlen(machine->cpu_type) - strlen(POWERPC_CPU_TYPE_SUFFIX);
+ chip_typename = g_strdup_printf(PNV_CHIP_TYPE_NAME("%.*s"),
+ i, machine->cpu_type);
if (!object_class_by_name(chip_typename)) {
- error_report("invalid CPU model '%s' for %s machine",
- machine->cpu_model, MACHINE_GET_CLASS(machine)->name);
+ error_report("invalid CPU model '%.*s' for %s machine",
+ i, machine->cpu_type, MACHINE_GET_CLASS(machine)->name);
exit(1);
}
@@ -716,7 +720,6 @@ static void pnv_chip_power8e_class_init(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
PnvChipClass *k = PNV_CHIP_CLASS(klass);
- k->cpu_model = "POWER8E";
k->chip_type = PNV_CHIP_POWER8E;
k->chip_cfam_id = 0x221ef04980000000ull; /* P8 Murano DD2.1 */
k->cores_mask = POWER8E_CORE_MASK;
@@ -726,19 +729,11 @@ static void pnv_chip_power8e_class_init(ObjectClass *klass, void *data)
dc->desc = "PowerNV Chip POWER8E";
}
-static const TypeInfo pnv_chip_power8e_info = {
- .name = TYPE_PNV_CHIP_POWER8E,
- .parent = TYPE_PNV_CHIP,
- .instance_size = sizeof(PnvChip),
- .class_init = pnv_chip_power8e_class_init,
-};
-
static void pnv_chip_power8_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
PnvChipClass *k = PNV_CHIP_CLASS(klass);
- k->cpu_model = "POWER8";
k->chip_type = PNV_CHIP_POWER8;
k->chip_cfam_id = 0x220ea04980000000ull; /* P8 Venice DD2.0 */
k->cores_mask = POWER8_CORE_MASK;
@@ -748,19 +743,11 @@ static void pnv_chip_power8_class_init(ObjectClass *klass, void *data)
dc->desc = "PowerNV Chip POWER8";
}
-static const TypeInfo pnv_chip_power8_info = {
- .name = TYPE_PNV_CHIP_POWER8,
- .parent = TYPE_PNV_CHIP,
- .instance_size = sizeof(PnvChip),
- .class_init = pnv_chip_power8_class_init,
-};
-
static void pnv_chip_power8nvl_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
PnvChipClass *k = PNV_CHIP_CLASS(klass);
- k->cpu_model = "POWER8NVL";
k->chip_type = PNV_CHIP_POWER8NVL;
k->chip_cfam_id = 0x120d304980000000ull; /* P8 Naples DD1.0 */
k->cores_mask = POWER8_CORE_MASK;
@@ -770,19 +757,11 @@ static void pnv_chip_power8nvl_class_init(ObjectClass *klass, void *data)
dc->desc = "PowerNV Chip POWER8NVL";
}
-static const TypeInfo pnv_chip_power8nvl_info = {
- .name = TYPE_PNV_CHIP_POWER8NVL,
- .parent = TYPE_PNV_CHIP,
- .instance_size = sizeof(PnvChip),
- .class_init = pnv_chip_power8nvl_class_init,
-};
-
static void pnv_chip_power9_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
PnvChipClass *k = PNV_CHIP_CLASS(klass);
- k->cpu_model = "POWER9";
k->chip_type = PNV_CHIP_POWER9;
k->chip_cfam_id = 0x100d104980000000ull; /* P9 Nimbus DD1.0 */
k->cores_mask = POWER9_CORE_MASK;
@@ -792,13 +771,6 @@ static void pnv_chip_power9_class_init(ObjectClass *klass, void *data)
dc->desc = "PowerNV Chip POWER9";
}
-static const TypeInfo pnv_chip_power9_info = {
- .name = TYPE_PNV_CHIP_POWER9,
- .parent = TYPE_PNV_CHIP,
- .instance_size = sizeof(PnvChip),
- .class_init = pnv_chip_power9_class_init,
-};
-
static void pnv_chip_core_sanitize(PnvChip *chip, Error **errp)
{
PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
@@ -857,7 +829,7 @@ static void pnv_chip_init(Object *obj)
static void pnv_chip_icp_realize(PnvChip *chip, Error **errp)
{
PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
- char *typename = pnv_core_typename(pcc->cpu_model);
+ const char *typename = pnv_chip_core_typename(chip);
size_t typesize = object_type_get_instance_size(typename);
int i, j;
char *name;
@@ -882,8 +854,6 @@ static void pnv_chip_icp_realize(PnvChip *chip, Error **errp)
memory_region_add_subregion(&chip->icp_mmio, pir << 12, &icp->mmio);
}
}
-
- g_free(typename);
}
static void pnv_chip_realize(DeviceState *dev, Error **errp)
@@ -891,7 +861,7 @@ static void pnv_chip_realize(DeviceState *dev, Error **errp)
PnvChip *chip = PNV_CHIP(dev);
Error *error = NULL;
PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
- char *typename = pnv_core_typename(pcc->cpu_model);
+ const char *typename = pnv_chip_core_typename(chip);
size_t typesize = object_type_get_instance_size(typename);
int i, core_hwid;
@@ -950,7 +920,6 @@ static void pnv_chip_realize(DeviceState *dev, Error **errp)
&PNV_CORE(pnv_core)->xscom_regs);
i++;
}
- g_free(typename);
/* Create LPC controller */
object_property_set_bool(OBJECT(&chip->lpc), true, "realized",
@@ -1003,15 +972,6 @@ static void pnv_chip_class_init(ObjectClass *klass, void *data)
dc->desc = "PowerNV Chip";
}
-static const TypeInfo pnv_chip_info = {
- .name = TYPE_PNV_CHIP,
- .parent = TYPE_SYS_BUS_DEVICE,
- .class_init = pnv_chip_class_init,
- .instance_init = pnv_chip_init,
- .class_size = sizeof(PnvChipClass),
- .abstract = true,
-};
-
static ICSState *pnv_ics_get(XICSFabric *xi, int irq)
{
PnvMachineState *pnv = POWERNV_MACHINE(xi);
@@ -1133,6 +1093,7 @@ static void powernv_machine_class_init(ObjectClass *oc, void *data)
mc->init = ppc_powernv_init;
mc->reset = ppc_powernv_reset;
mc->max_cpus = MAX_CPUS;
+ mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0");
mc->block_default_type = IF_IDE; /* Pnv provides a AHCI device for
* storage */
mc->no_parallel = 1;
@@ -1146,27 +1107,40 @@ static void powernv_machine_class_init(ObjectClass *oc, void *data)
powernv_machine_class_props_init(oc);
}
-static const TypeInfo powernv_machine_info = {
- .name = TYPE_POWERNV_MACHINE,
- .parent = TYPE_MACHINE,
- .instance_size = sizeof(PnvMachineState),
- .instance_init = powernv_machine_initfn,
- .class_init = powernv_machine_class_init,
- .interfaces = (InterfaceInfo[]) {
- { TYPE_XICS_FABRIC },
- { TYPE_INTERRUPT_STATS_PROVIDER },
- { },
+#define DEFINE_PNV_CHIP_TYPE(type, class_initfn) \
+ { \
+ .name = type, \
+ .class_init = class_initfn, \
+ .parent = TYPE_PNV_CHIP, \
+ }
+
+static const TypeInfo types[] = {
+ {
+ .name = TYPE_POWERNV_MACHINE,
+ .parent = TYPE_MACHINE,
+ .instance_size = sizeof(PnvMachineState),
+ .instance_init = powernv_machine_initfn,
+ .class_init = powernv_machine_class_init,
+ .interfaces = (InterfaceInfo[]) {
+ { TYPE_XICS_FABRIC },
+ { TYPE_INTERRUPT_STATS_PROVIDER },
+ { },
+ },
+ },
+ {
+ .name = TYPE_PNV_CHIP,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .class_init = pnv_chip_class_init,
+ .instance_init = pnv_chip_init,
+ .instance_size = sizeof(PnvChip),
+ .class_size = sizeof(PnvChipClass),
+ .abstract = true,
},
+ DEFINE_PNV_CHIP_TYPE(TYPE_PNV_CHIP_POWER9, pnv_chip_power9_class_init),
+ DEFINE_PNV_CHIP_TYPE(TYPE_PNV_CHIP_POWER8, pnv_chip_power8_class_init),
+ DEFINE_PNV_CHIP_TYPE(TYPE_PNV_CHIP_POWER8E, pnv_chip_power8e_class_init),
+ DEFINE_PNV_CHIP_TYPE(TYPE_PNV_CHIP_POWER8NVL,
+ pnv_chip_power8nvl_class_init),
};
-static void powernv_machine_register_types(void)
-{
- type_register_static(&powernv_machine_info);
- type_register_static(&pnv_chip_info);
- type_register_static(&pnv_chip_power8e_info);
- type_register_static(&pnv_chip_power8_info);
- type_register_static(&pnv_chip_power8nvl_info);
- type_register_static(&pnv_chip_power9_info);
-}
-
-type_init(powernv_machine_register_types)
+DEFINE_TYPES(types)
diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c
index 67264830db..82ff440b33 100644
--- a/hw/ppc/pnv_core.c
+++ b/hw/ppc/pnv_core.c
@@ -27,6 +27,16 @@
#include "hw/ppc/pnv_xscom.h"
#include "hw/ppc/xics.h"
+static const char *pnv_core_cpu_typename(PnvCore *pc)
+{
+ const char *core_type = object_class_get_name(object_get_class(OBJECT(pc)));
+ int len = strlen(core_type) - strlen(PNV_CORE_TYPE_SUFFIX);
+ char *s = g_strdup_printf(POWERPC_CPU_TYPE_NAME("%.*s"), len, core_type);
+ const char *cpu_type = object_class_get_name(object_class_by_name(s));
+ g_free(s);
+ return cpu_type;
+}
+
static void powernv_cpu_reset(void *opaque)
{
PowerPCCPU *cpu = opaque;
@@ -148,8 +158,7 @@ static void pnv_core_realize(DeviceState *dev, Error **errp)
{
PnvCore *pc = PNV_CORE(OBJECT(dev));
CPUCore *cc = CPU_CORE(OBJECT(dev));
- PnvCoreClass *pcc = PNV_CORE_GET_CLASS(OBJECT(dev));
- const char *typename = object_class_get_name(pcc->cpu_oc);
+ const char *typename = pnv_core_cpu_typename(pc);
size_t size = object_type_get_instance_size(typename);
Error *local_err = NULL;
void *obj;
@@ -211,46 +220,30 @@ static Property pnv_core_properties[] = {
static void pnv_core_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
- PnvCoreClass *pcc = PNV_CORE_CLASS(oc);
dc->realize = pnv_core_realize;
dc->props = pnv_core_properties;
- pcc->cpu_oc = cpu_class_by_name(TYPE_POWERPC_CPU, data);
}
-static const TypeInfo pnv_core_info = {
- .name = TYPE_PNV_CORE,
- .parent = TYPE_CPU_CORE,
- .instance_size = sizeof(PnvCore),
- .class_size = sizeof(PnvCoreClass),
- .abstract = true,
-};
-
-static const char *pnv_core_models[] = {
- "POWER8E", "POWER8", "POWER8NVL", "POWER9"
-};
-
-static void pnv_core_register_types(void)
-{
- int i ;
-
- type_register_static(&pnv_core_info);
- for (i = 0; i < ARRAY_SIZE(pnv_core_models); ++i) {
- TypeInfo ti = {
- .parent = TYPE_PNV_CORE,
- .instance_size = sizeof(PnvCore),
- .class_init = pnv_core_class_init,
- .class_data = (void *) pnv_core_models[i],
- };
- ti.name = pnv_core_typename(pnv_core_models[i]);
- type_register(&ti);
- g_free((void *)ti.name);
+#define DEFINE_PNV_CORE_TYPE(cpu_model) \
+ { \
+ .parent = TYPE_PNV_CORE, \
+ .name = PNV_CORE_TYPE_NAME(cpu_model), \
}
-}
-type_init(pnv_core_register_types)
+static const TypeInfo pnv_core_infos[] = {
+ {
+ .name = TYPE_PNV_CORE,
+ .parent = TYPE_CPU_CORE,
+ .instance_size = sizeof(PnvCore),
+ .class_size = sizeof(PnvCoreClass),
+ .class_init = pnv_core_class_init,
+ .abstract = true,
+ },
+ DEFINE_PNV_CORE_TYPE("power8e_v2.1"),
+ DEFINE_PNV_CORE_TYPE("power8_v2.0"),
+ DEFINE_PNV_CORE_TYPE("power8nvl_v1.0"),
+ DEFINE_PNV_CORE_TYPE("power9_v2.0"),
+};
-char *pnv_core_typename(const char *model)
-{
- return g_strdup_printf(TYPE_PNV_CORE "-%s", model);
-}
+DEFINE_TYPES(pnv_core_infos)
diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c
index 05da316e0b..7ec35de5ae 100644
--- a/hw/ppc/ppc.c
+++ b/hw/ppc/ppc.c
@@ -1359,28 +1359,3 @@ void PPC_debug_write (void *opaque, uint32_t addr, uint32_t val)
break;
}
}
-
-void ppc_cpu_parse_features(const char *cpu_model)
-{
- CPUClass *cc;
- ObjectClass *oc;
- const char *typename;
- gchar **model_pieces;
-
- model_pieces = g_strsplit(cpu_model, ",", 2);
- if (!model_pieces[0]) {
- error_report("Invalid/empty CPU model name");
- exit(1);
- }
-
- oc = cpu_class_by_name(TYPE_POWERPC_CPU, model_pieces[0]);
- if (oc == NULL) {
- error_report("Unable to find CPU definition: %s", model_pieces[0]);
- exit(1);
- }
-
- typename = object_class_get_name(oc);
- cc = CPU_CLASS(oc);
- cc->parse_features(typename, model_pieces[1], &error_fatal);
- g_strfreev(model_pieces);
-}
diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
index 8e58065f5f..205ebcea93 100644
--- a/hw/ppc/ppc405_uc.c
+++ b/hw/ppc/ppc405_uc.c
@@ -1629,7 +1629,8 @@ CPUPPCState *ppc405cr_init(MemoryRegion *address_space_mem,
qemu_irq *pic, *irqs;
memset(clk_setup, 0, sizeof(clk_setup));
- cpu = ppc4xx_init("405cr", &clk_setup[PPC405CR_CPU_CLK],
+ cpu = ppc4xx_init(POWERPC_CPU_TYPE_NAME("405crc"),
+ &clk_setup[PPC405CR_CPU_CLK],
&clk_setup[PPC405CR_TMR_CLK], sysclk);
env = &cpu->env;
/* Memory mapped devices registers */
@@ -1981,7 +1982,8 @@ CPUPPCState *ppc405ep_init(MemoryRegion *address_space_mem,
memset(clk_setup, 0, sizeof(clk_setup));
/* init CPUs */
- cpu = ppc4xx_init("405ep", &clk_setup[PPC405EP_CPU_CLK],
+ cpu = ppc4xx_init(POWERPC_CPU_TYPE_NAME("405ep"),
+ &clk_setup[PPC405EP_CPU_CLK],
&tlb_clk_setup, sysclk);
env = &cpu->env;
clk_setup[PPC405EP_CPU_CLK].cb = tlb_clk_setup.cb;
diff --git a/hw/ppc/ppc440_bamboo.c b/hw/ppc/ppc440_bamboo.c
index f92d47f28d..693c215108 100644
--- a/hw/ppc/ppc440_bamboo.c
+++ b/hw/ppc/ppc440_bamboo.c
@@ -182,11 +182,7 @@ static void bamboo_init(MachineState *machine)
int success;
int i;
- /* Setup CPU. */
- if (machine->cpu_model == NULL) {
- machine->cpu_model = "440EP";
- }
- cpu = POWERPC_CPU(cpu_generic_init(TYPE_POWERPC_CPU, machine->cpu_model));
+ cpu = POWERPC_CPU(cpu_create(machine->cpu_type));
env = &cpu->env;
if (env->mmu_model != POWERPC_MMU_BOOKE) {
@@ -297,6 +293,7 @@ static void bamboo_machine_init(MachineClass *mc)
{
mc->desc = "bamboo";
mc->init = bamboo_init;
+ mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("440epb");
}
DEFINE_MACHINE("bamboo", bamboo_machine_init)
diff --git a/hw/ppc/ppc4xx_devs.c b/hw/ppc/ppc4xx_devs.c
index 6d7f7857fe..2e963894fe 100644
--- a/hw/ppc/ppc4xx_devs.c
+++ b/hw/ppc/ppc4xx_devs.c
@@ -48,7 +48,7 @@ static void ppc4xx_reset(void *opaque)
/*****************************************************************************/
/* Generic PowerPC 4xx processor instantiation */
-PowerPCCPU *ppc4xx_init(const char *cpu_model,
+PowerPCCPU *ppc4xx_init(const char *cpu_type,
clk_setup_t *cpu_clk, clk_setup_t *tb_clk,
uint32_t sysclk)
{
@@ -56,7 +56,7 @@ PowerPCCPU *ppc4xx_init(const char *cpu_model,
CPUPPCState *env;
/* init CPUs */
- cpu = POWERPC_CPU(cpu_generic_init(TYPE_POWERPC_CPU, cpu_model));
+ cpu = POWERPC_CPU(cpu_create(cpu_type));
env = &cpu->env;
cpu_clk->cb = NULL; /* We don't care about CPU clock frequency changes */
diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c
index 94138a4e8c..6f8accc397 100644
--- a/hw/ppc/prep.c
+++ b/hw/ppc/prep.c
@@ -517,11 +517,8 @@ static void ppc_prep_init(MachineState *machine)
linux_boot = (kernel_filename != NULL);
/* init CPUs */
- if (machine->cpu_model == NULL)
- machine->cpu_model = "602";
for (i = 0; i < smp_cpus; i++) {
- cpu = POWERPC_CPU(cpu_generic_init(TYPE_POWERPC_CPU,
- machine->cpu_model));
+ cpu = POWERPC_CPU(cpu_create(machine->cpu_type));
env = &cpu->env;
if (env->flags & POWERPC_FLAG_RTC_CLK) {
@@ -684,6 +681,7 @@ static void prep_machine_init(MachineClass *mc)
mc->block_default_type = IF_IDE;
mc->max_cpus = MAX_CPUS;
mc->default_boot_order = "cad";
+ mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("602");
}
static int prep_set_cmos_checksum(DeviceState *dev, void *opaque)
@@ -718,10 +716,7 @@ static void ibm_40p_init(MachineState *machine)
char boot_device;
/* init CPU */
- if (!machine->cpu_model) {
- machine->cpu_model = "604";
- }
- cpu = POWERPC_CPU(cpu_generic_init(TYPE_POWERPC_CPU, machine->cpu_model));
+ cpu = POWERPC_CPU(cpu_create(machine->cpu_type));
env = &cpu->env;
if (PPC_INPUT(env) != PPC_FLAGS_INPUT_6xx) {
error_report("only 6xx bus is supported on this machine");
@@ -894,6 +889,7 @@ static void ibm_40p_machine_init(MachineClass *mc)
mc->default_ram_size = 128 * M_BYTE;
mc->block_default_type = IF_SCSI;
mc->default_boot_order = "c";
+ mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("604");
}
DEFINE_MACHINE("40p", ibm_40p_machine_init)
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index ff87f155d5..d682f013d4 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -353,8 +353,7 @@ static int spapr_fixup_cpu_dt(void *fdt, sPAPRMachineState *spapr)
cpus_offset = fdt_path_offset(fdt, "/cpus");
if (cpus_offset < 0) {
- cpus_offset = fdt_add_subnode(fdt, fdt_path_offset(fdt, "/"),
- "cpus");
+ cpus_offset = fdt_add_subnode(fdt, 0, "cpus");
if (cpus_offset < 0) {
return cpus_offset;
}
@@ -820,6 +819,13 @@ int spapr_h_cas_compose_response(sPAPRMachineState *spapr,
return 1;
}
+ if (size < sizeof(hdr) || size > FW_MAX_SIZE) {
+ error_report("SLOF provided an unexpected CAS buffer size "
+ TARGET_FMT_lu " (min: %zu, max: %u)",
+ size, sizeof(hdr), FW_MAX_SIZE);
+ exit(EXIT_FAILURE);
+ }
+
size -= sizeof(hdr);
/* Create skeleton */
@@ -2123,7 +2129,7 @@ static void spapr_init_cpus(sPAPRMachineState *spapr)
{
MachineState *machine = MACHINE(spapr);
MachineClass *mc = MACHINE_GET_CLASS(machine);
- char *type = spapr_get_cpu_core_type(machine->cpu_model);
+ const char *type = spapr_get_cpu_core_type(machine->cpu_type);
int smt = kvmppc_smt_threads();
const CPUArchIdList *possible_cpus;
int boot_cores_nr = smp_cpus / smp_threads;
@@ -2178,7 +2184,6 @@ static void spapr_init_cpus(sPAPRMachineState *spapr)
object_property_set_bool(core, true, "realized", &error_fatal);
}
}
- g_free(type);
}
static void spapr_set_vsmt_mode(sPAPRMachineState *spapr, Error **errp)
@@ -2335,7 +2340,8 @@ static void ppc_spapr_init(MachineState *machine)
/* Set up Interrupt Controller before we create the VCPUs */
xics_system_init(machine, XICS_IRQS_SPAPR, &error_fatal);
- /* Set up containers for ibm,client-set-architecture negotiated options */
+ /* Set up containers for ibm,client-architecture-support negotiated options
+ */
spapr->ov5 = spapr_ovec_new();
spapr->ov5_cas = spapr_ovec_new();
@@ -2362,12 +2368,6 @@ static void ppc_spapr_init(MachineState *machine)
}
/* init CPUs */
- if (machine->cpu_model == NULL) {
- machine->cpu_model = kvm_enabled() ? "host" : smc->tcg_default_cpu;
- }
-
- spapr_cpu_parse_features(spapr);
-
spapr_set_vsmt_mode(spapr, &error_fatal);
spapr_init_cpus(spapr);
@@ -3054,14 +3054,13 @@ void spapr_lmb_release(DeviceState *dev)
return;
}
- spapr_pending_dimm_unplugs_remove(spapr, ds);
-
/*
* Now that all the LMBs have been removed by the guest, call the
* pc-dimm unplug handler to cleanup up the pc-dimm device.
*/
pc_dimm_memory_unplug(dev, &spapr->hotplug_memory, mr);
object_unparent(OBJECT(dev));
+ spapr_pending_dimm_unplugs_remove(spapr, ds);
}
static void spapr_memory_unplug_request(HotplugHandler *hotplug_dev,
@@ -3090,6 +3089,19 @@ static void spapr_memory_unplug_request(HotplugHandler *hotplug_dev,
goto out;
}
+ /*
+ * An existing pending dimm state for this DIMM means that there is an
+ * unplug operation in progress, waiting for the spapr_lmb_release
+ * callback to complete the job (BQL can't cover that far). In this case,
+ * bail out to avoid detaching DRCs that were already released.
+ */
+ if (spapr_pending_dimm_unplugs_find(spapr, dimm)) {
+ error_setg(&local_err,
+ "Memory unplug already in progress for device %s",
+ dev->id);
+ goto out;
+ }
+
spapr_pending_dimm_unplugs_add(spapr, nr_lmbs, dimm);
addr = addr_start;
@@ -3142,8 +3154,7 @@ void spapr_core_release(DeviceState *dev)
if (smc->pre_2_10_has_unused_icps) {
sPAPRCPUCore *sc = SPAPR_CPU_CORE(OBJECT(dev));
sPAPRCPUCoreClass *scc = SPAPR_CPU_CORE_GET_CLASS(OBJECT(cc));
- const char *typename = object_class_get_name(scc->cpu_class);
- size_t size = object_type_get_instance_size(typename);
+ size_t size = object_type_get_instance_size(scc->cpu_type);
int i;
for (i = 0; i < cc->nr_threads; i++) {
@@ -3239,8 +3250,7 @@ static void spapr_core_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
if (smc->pre_2_10_has_unused_icps) {
sPAPRCPUCoreClass *scc = SPAPR_CPU_CORE_GET_CLASS(OBJECT(cc));
- const char *typename = object_class_get_name(scc->cpu_class);
- size_t size = object_type_get_instance_size(typename);
+ size_t size = object_type_get_instance_size(scc->cpu_type);
int i;
for (i = 0; i < cc->nr_threads; i++) {
@@ -3260,7 +3270,7 @@ static void spapr_core_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
MachineClass *mc = MACHINE_GET_CLASS(hotplug_dev);
Error *local_err = NULL;
CPUCore *cc = CPU_CORE(dev);
- char *base_core_type = spapr_get_cpu_core_type(machine->cpu_model);
+ const char *base_core_type = spapr_get_cpu_core_type(machine->cpu_type);
const char *type = object_get_typename(OBJECT(dev));
CPUArchId *core_slot;
int index;
@@ -3306,7 +3316,6 @@ static void spapr_core_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
numa_cpu_pre_plug(core_slot, dev, &local_err);
out:
- g_free(base_core_type);
error_propagate(errp, local_err);
}
@@ -3605,7 +3614,7 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data)
hc->unplug_request = spapr_machine_device_unplug_request;
smc->dr_lmb_enabled = true;
- smc->tcg_default_cpu = "POWER8";
+ mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0");
mc->has_hotpluggable_cpus = true;
smc->resize_hpt_default = SPAPR_RESIZE_HPT_ENABLED;
fwc->get_dev_path = spapr_get_fw_dev_path;
@@ -3851,7 +3860,7 @@ static void spapr_machine_2_7_class_options(MachineClass *mc)
sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
spapr_machine_2_8_class_options(mc);
- smc->tcg_default_cpu = "POWER7";
+ mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power7_v2.3");
SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_7);
smc->phb_placement = phb_placement_2_7;
}
diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c
index 3e20b1d886..3a4c174012 100644
--- a/hw/ppc/spapr_cpu_core.c
+++ b/hw/ppc/spapr_cpu_core.c
@@ -21,57 +21,6 @@
#include "sysemu/hw_accel.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)
{
PowerPCCPU *cpu = opaque;
@@ -112,37 +61,26 @@ static void spapr_cpu_init(sPAPRMachineState *spapr, PowerPCCPU *cpu,
* Return the sPAPR CPU core type for @model which essentially is the CPU
* model specified with -cpu cmdline option.
*/
-char *spapr_get_cpu_core_type(const char *model)
+const char *spapr_get_cpu_core_type(const char *cpu_type)
{
- char *core_type;
- gchar **model_pieces = g_strsplit(model, ",", 2);
- gchar *cpu_model = g_ascii_strdown(model_pieces[0], -1);
- g_strfreev(model_pieces);
-
- core_type = g_strdup_printf("%s-" TYPE_SPAPR_CPU_CORE, cpu_model);
-
- /* Check whether it exists or whether we have to look up an alias name */
- if (!object_class_by_name(core_type)) {
- const char *realmodel;
-
- g_free(core_type);
- core_type = NULL;
- realmodel = ppc_cpu_lookup_alias(cpu_model);
- if (realmodel) {
- core_type = spapr_get_cpu_core_type(realmodel);
- }
+ int len = strlen(cpu_type) - strlen(POWERPC_CPU_TYPE_SUFFIX);
+ char *core_type = g_strdup_printf(SPAPR_CPU_CORE_TYPE_NAME("%.*s"),
+ len, cpu_type);
+ ObjectClass *oc = object_class_by_name(core_type);
+
+ g_free(core_type);
+ if (!oc) {
+ return NULL;
}
- g_free(cpu_model);
- return core_type;
+ return object_class_get_name(oc);
}
static void spapr_cpu_core_unrealizefn(DeviceState *dev, Error **errp)
{
sPAPRCPUCore *sc = SPAPR_CPU_CORE(OBJECT(dev));
sPAPRCPUCoreClass *scc = SPAPR_CPU_CORE_GET_CLASS(OBJECT(dev));
- const char *typename = object_class_get_name(scc->cpu_class);
- size_t size = object_type_get_instance_size(typename);
+ size_t size = object_type_get_instance_size(scc->cpu_type);
CPUCore *cc = CPU_CORE(dev);
int i;
@@ -199,22 +137,26 @@ error:
static void spapr_cpu_core_realize(DeviceState *dev, Error **errp)
{
- sPAPRMachineState *spapr;
+ /* We don't use SPAPR_MACHINE() in order to exit gracefully if the user
+ * tries to add a sPAPR CPU core to a non-pseries machine.
+ */
+ sPAPRMachineState *spapr =
+ (sPAPRMachineState *) object_dynamic_cast(qdev_get_machine(),
+ TYPE_SPAPR_MACHINE);
sPAPRCPUCore *sc = SPAPR_CPU_CORE(OBJECT(dev));
sPAPRCPUCoreClass *scc = SPAPR_CPU_CORE_GET_CLASS(OBJECT(dev));
CPUCore *cc = CPU_CORE(OBJECT(dev));
- const char *typename = object_class_get_name(scc->cpu_class);
- size_t size = object_type_get_instance_size(typename);
+ size_t size;
Error *local_err = NULL;
void *obj;
int i, j;
- spapr = (sPAPRMachineState *) qdev_get_machine();
- if (!object_dynamic_cast((Object *) spapr, TYPE_SPAPR_MACHINE)) {
- error_setg(errp, "spapr-cpu-core needs a pseries machine");
+ if (!spapr) {
+ error_setg(errp, TYPE_SPAPR_CPU_CORE " needs a pseries machine");
return;
}
+ size = object_type_get_instance_size(scc->cpu_type);
sc->threads = g_malloc0(size * cc->nr_threads);
for (i = 0; i < cc->nr_threads; i++) {
char id[32];
@@ -223,7 +165,7 @@ static void spapr_cpu_core_realize(DeviceState *dev, Error **errp)
obj = sc->threads + i * size;
- object_initialize(obj, size, typename);
+ object_initialize(obj, size, scc->cpu_type);
cs = CPU(obj);
cpu = POWERPC_CPU(cs);
cs->cpu_index = cc->core_id + i;
@@ -268,42 +210,12 @@ err:
error_propagate(errp, local_err);
}
-static const char *spapr_core_models[] = {
- /* 970 */
- "970_v2.2",
-
- /* 970MP variants */
- "970mp_v1.0",
- "970mp_v1.1",
-
- /* POWER5+ */
- "power5+_v2.1",
-
- /* POWER7 */
- "power7_v2.3",
-
- /* POWER7+ */
- "power7+_v2.1",
-
- /* POWER8 */
- "power8_v2.0",
-
- /* POWER8E */
- "power8e_v2.1",
-
- /* POWER8NVL */
- "power8nvl_v1.0",
-
- /* POWER9 */
- "power9_v1.0",
-};
-
static Property spapr_cpu_core_properties[] = {
DEFINE_PROP_INT32("node-id", sPAPRCPUCore, node_id, CPU_UNSET_NUMA_NODE_ID),
DEFINE_PROP_END_OF_LIST()
};
-void spapr_cpu_core_class_init(ObjectClass *oc, void *data)
+static void spapr_cpu_core_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
sPAPRCPUCoreClass *scc = SPAPR_CPU_CORE_CLASS(oc);
@@ -311,37 +223,39 @@ void spapr_cpu_core_class_init(ObjectClass *oc, void *data)
dc->realize = spapr_cpu_core_realize;
dc->unrealize = spapr_cpu_core_unrealizefn;
dc->props = spapr_cpu_core_properties;
- scc->cpu_class = cpu_class_by_name(TYPE_POWERPC_CPU, data);
- g_assert(scc->cpu_class);
+ scc->cpu_type = data;
}
-static const TypeInfo spapr_cpu_core_type_info = {
- .name = TYPE_SPAPR_CPU_CORE,
- .parent = TYPE_CPU_CORE,
- .abstract = true,
- .instance_size = sizeof(sPAPRCPUCore),
- .class_size = sizeof(sPAPRCPUCoreClass),
-};
-
-static void spapr_cpu_core_register_types(void)
-{
- int i;
-
- type_register_static(&spapr_cpu_core_type_info);
-
- for (i = 0; i < ARRAY_SIZE(spapr_core_models); i++) {
- TypeInfo type_info = {
- .parent = TYPE_SPAPR_CPU_CORE,
- .instance_size = sizeof(sPAPRCPUCore),
- .class_init = spapr_cpu_core_class_init,
- .class_data = (void *) spapr_core_models[i],
- };
-
- type_info.name = g_strdup_printf("%s-" TYPE_SPAPR_CPU_CORE,
- spapr_core_models[i]);
- type_register(&type_info);
- g_free((void *)type_info.name);
+#define DEFINE_SPAPR_CPU_CORE_TYPE(cpu_model) \
+ { \
+ .parent = TYPE_SPAPR_CPU_CORE, \
+ .class_data = (void *) POWERPC_CPU_TYPE_NAME(cpu_model), \
+ .class_init = spapr_cpu_core_class_init, \
+ .name = SPAPR_CPU_CORE_TYPE_NAME(cpu_model), \
}
-}
-type_init(spapr_cpu_core_register_types)
+static const TypeInfo spapr_cpu_core_type_infos[] = {
+ {
+ .name = TYPE_SPAPR_CPU_CORE,
+ .parent = TYPE_CPU_CORE,
+ .abstract = true,
+ .instance_size = sizeof(sPAPRCPUCore),
+ .class_size = sizeof(sPAPRCPUCoreClass),
+ },
+ DEFINE_SPAPR_CPU_CORE_TYPE("970_v2.2"),
+ DEFINE_SPAPR_CPU_CORE_TYPE("970mp_v1.0"),
+ DEFINE_SPAPR_CPU_CORE_TYPE("970mp_v1.1"),
+ DEFINE_SPAPR_CPU_CORE_TYPE("power5+_v2.1"),
+ DEFINE_SPAPR_CPU_CORE_TYPE("power7_v2.3"),
+ DEFINE_SPAPR_CPU_CORE_TYPE("power7+_v2.1"),
+ DEFINE_SPAPR_CPU_CORE_TYPE("power8_v2.0"),
+ DEFINE_SPAPR_CPU_CORE_TYPE("power8e_v2.1"),
+ DEFINE_SPAPR_CPU_CORE_TYPE("power8nvl_v1.0"),
+ DEFINE_SPAPR_CPU_CORE_TYPE("power9_v1.0"),
+ DEFINE_SPAPR_CPU_CORE_TYPE("power9_v2.0"),
+#ifdef CONFIG_KVM
+ DEFINE_SPAPR_CPU_CORE_TYPE("host"),
+#endif
+};
+
+DEFINE_TYPES(spapr_cpu_core_type_infos)
diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
index 8d72bb7c1c..0d59d1534d 100644
--- a/hw/ppc/spapr_hcall.c
+++ b/hw/ppc/spapr_hcall.c
@@ -472,7 +472,7 @@ static target_ulong h_resize_hpt_prepare(PowerPCCPU *cpu,
target_ulong flags = args[0];
int shift = args[1];
sPAPRPendingHPT *pending = spapr->pending_hpt;
- uint64_t current_ram_size = MACHINE(spapr)->ram_size;
+ uint64_t current_ram_size;
int rc;
if (spapr->resize_hpt == SPAPR_RESIZE_HPT_DISABLED) {
@@ -494,7 +494,7 @@ static target_ulong h_resize_hpt_prepare(PowerPCCPU *cpu,
return H_PARAMETER;
}
- current_ram_size = pc_existing_dimms_capacity(&error_fatal);
+ current_ram_size = MACHINE(spapr)->ram_size + get_plugged_memory_size();
/* We only allow the guest to allocate an HPT one order above what
* we'd normally give them (to stop a small guest claiming a huge
diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
index 5049ced4e8..5a3122a9f9 100644
--- a/hw/ppc/spapr_pci.c
+++ b/hw/ppc/spapr_pci.c
@@ -1507,7 +1507,12 @@ static void spapr_pci_unplug_request(HotplugHandler *plug_handler,
static void spapr_phb_realize(DeviceState *dev, Error **errp)
{
- sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
+ /* We don't use SPAPR_MACHINE() in order to exit gracefully if the user
+ * tries to add a sPAPR PHB to a non-pseries machine.
+ */
+ sPAPRMachineState *spapr =
+ (sPAPRMachineState *) object_dynamic_cast(qdev_get_machine(),
+ TYPE_SPAPR_MACHINE);
SysBusDevice *s = SYS_BUS_DEVICE(dev);
sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(s);
PCIHostState *phb = PCI_HOST_BRIDGE(s);
@@ -1519,6 +1524,11 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp)
const unsigned windows_supported =
sphb->ddw_enabled ? SPAPR_PCI_DMA_MAX_WINDOWS : 1;
+ if (!spapr) {
+ error_setg(errp, TYPE_SPAPR_PCI_HOST_BRIDGE " needs a pseries machine");
+ return;
+ }
+
if (sphb->index != (uint32_t)-1) {
sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
Error *local_err = NULL;
diff --git a/hw/ppc/virtex_ml507.c b/hw/ppc/virtex_ml507.c
index ed9b406fd3..5ac4f76613 100644
--- a/hw/ppc/virtex_ml507.c
+++ b/hw/ppc/virtex_ml507.c
@@ -89,14 +89,14 @@ static void mmubooke_create_initial_mapping(CPUPPCState *env,
static PowerPCCPU *ppc440_init_xilinx(ram_addr_t *ram_size,
int do_init,
- const char *cpu_model,
+ const char *cpu_type,
uint32_t sysclk)
{
PowerPCCPU *cpu;
CPUPPCState *env;
qemu_irq *irqs;
- cpu = POWERPC_CPU(cpu_generic_init(TYPE_POWERPC_CPU, cpu_model));
+ cpu = POWERPC_CPU(cpu_create(cpu_type));
env = &cpu->env;
ppc_booke_timers_init(cpu, sysclk, 0/* no flags */);
@@ -211,11 +211,7 @@ static void virtex_init(MachineState *machine)
int i;
/* init CPUs */
- if (machine->cpu_model == NULL) {
- machine->cpu_model = "440-Xilinx";
- }
-
- cpu = ppc440_init_xilinx(&ram_size, 1, machine->cpu_model, 400000000);
+ cpu = ppc440_init_xilinx(&ram_size, 1, machine->cpu_type, 400000000);
env = &cpu->env;
if (env->mmu_model != POWERPC_MMU_BOOKE) {
@@ -307,6 +303,7 @@ static void virtex_machine_init(MachineClass *mc)
{
mc->desc = "Xilinx Virtex ML507 reference design";
mc->init = virtex_init;
+ mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("440-xilinx");
}
DEFINE_MACHINE("virtex-ml507", virtex_machine_init)
diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h
index 9c5437dabc..59524cd42b 100644
--- a/include/hw/ppc/pnv.h
+++ b/include/hw/ppc/pnv.h
@@ -69,7 +69,6 @@ typedef struct PnvChipClass {
SysBusDeviceClass parent_class;
/*< public >*/
- const char *cpu_model;
PnvChipType chip_type;
uint64_t chip_cfam_id;
uint64_t cores_mask;
@@ -80,19 +79,22 @@ typedef struct PnvChipClass {
uint32_t (*core_pir)(PnvChip *chip, uint32_t core_id);
} PnvChipClass;
-#define TYPE_PNV_CHIP_POWER8E TYPE_PNV_CHIP "-POWER8E"
+#define PNV_CHIP_TYPE_SUFFIX "-" TYPE_PNV_CHIP
+#define PNV_CHIP_TYPE_NAME(cpu_model) cpu_model PNV_CHIP_TYPE_SUFFIX
+
+#define TYPE_PNV_CHIP_POWER8E PNV_CHIP_TYPE_NAME("power8e_v2.1")
#define PNV_CHIP_POWER8E(obj) \
OBJECT_CHECK(PnvChip, (obj), TYPE_PNV_CHIP_POWER8E)
-#define TYPE_PNV_CHIP_POWER8 TYPE_PNV_CHIP "-POWER8"
+#define TYPE_PNV_CHIP_POWER8 PNV_CHIP_TYPE_NAME("power8_v2.0")
#define PNV_CHIP_POWER8(obj) \
OBJECT_CHECK(PnvChip, (obj), TYPE_PNV_CHIP_POWER8)
-#define TYPE_PNV_CHIP_POWER8NVL TYPE_PNV_CHIP "-POWER8NVL"
+#define TYPE_PNV_CHIP_POWER8NVL PNV_CHIP_TYPE_NAME("power8nvl_v1.0")
#define PNV_CHIP_POWER8NVL(obj) \
OBJECT_CHECK(PnvChip, (obj), TYPE_PNV_CHIP_POWER8NVL)
-#define TYPE_PNV_CHIP_POWER9 TYPE_PNV_CHIP "-POWER9"
+#define TYPE_PNV_CHIP_POWER9 PNV_CHIP_TYPE_NAME("power9_v2.0")
#define PNV_CHIP_POWER9(obj) \
OBJECT_CHECK(PnvChip, (obj), TYPE_PNV_CHIP_POWER9)
diff --git a/include/hw/ppc/pnv_core.h b/include/hw/ppc/pnv_core.h
index 2955a41c90..e337af7a3a 100644
--- a/include/hw/ppc/pnv_core.h
+++ b/include/hw/ppc/pnv_core.h
@@ -42,9 +42,9 @@ typedef struct PnvCore {
typedef struct PnvCoreClass {
DeviceClass parent_class;
- ObjectClass *cpu_oc;
} PnvCoreClass;
-extern char *pnv_core_typename(const char *model);
+#define PNV_CORE_TYPE_SUFFIX "-" TYPE_PNV_CORE
+#define PNV_CORE_TYPE_NAME(cpu_model) cpu_model PNV_CORE_TYPE_SUFFIX
#endif /* _PPC_PNV_CORE_H */
diff --git a/include/hw/ppc/ppc.h b/include/hw/ppc/ppc.h
index 4e7fe110d6..ff0ac306be 100644
--- a/include/hw/ppc/ppc.h
+++ b/include/hw/ppc/ppc.h
@@ -105,6 +105,4 @@ enum {
/* ppc_booke.c */
void ppc_booke_timers_init(PowerPCCPU *cpu, uint32_t freq, uint32_t flags);
-
-void ppc_cpu_parse_features(const char *cpu_model);
#endif
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index c1b365f564..9d21ca9bde 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -60,7 +60,6 @@ struct sPAPRMachineClass {
/*< public >*/
bool dr_lmb_enabled; /* enable dynamic-reconfig/hotplug of LMBs */
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;
void (*phb_placement)(sPAPRMachineState *spapr, uint32_t index,
uint64_t *buid, hwaddr *pio,
@@ -659,7 +658,6 @@ void spapr_hotplug_req_add_by_count_indexed(sPAPRDRConnectorType drc_type,
uint32_t count, uint32_t index);
void spapr_hotplug_req_remove_by_count_indexed(sPAPRDRConnectorType drc_type,
uint32_t count, uint32_t index);
-void spapr_cpu_parse_features(sPAPRMachineState *spapr);
int spapr_hpt_shift_for_ramsize(uint64_t ramsize);
void spapr_reallocate_hpt(sPAPRMachineState *spapr, int shift,
Error **errp);
diff --git a/include/hw/ppc/spapr_cpu_core.h b/include/hw/ppc/spapr_cpu_core.h
index 93051e9ecf..f2d48d6a67 100644
--- a/include/hw/ppc/spapr_cpu_core.h
+++ b/include/hw/ppc/spapr_cpu_core.h
@@ -21,6 +21,8 @@
#define SPAPR_CPU_CORE_GET_CLASS(obj) \
OBJECT_GET_CLASS(sPAPRCPUCoreClass, (obj), TYPE_SPAPR_CPU_CORE)
+#define SPAPR_CPU_CORE_TYPE_NAME(model) model "-" TYPE_SPAPR_CPU_CORE
+
typedef struct sPAPRCPUCore {
/*< private >*/
CPUCore parent_obj;
@@ -32,9 +34,8 @@ typedef struct sPAPRCPUCore {
typedef struct sPAPRCPUCoreClass {
DeviceClass parent_class;
- ObjectClass *cpu_class;
+ const char *cpu_type;
} sPAPRCPUCoreClass;
-char *spapr_get_cpu_core_type(const char *model);
-void spapr_cpu_core_class_init(ObjectClass *oc, void *data);
+const char *spapr_get_cpu_core_type(const char *cpu_type);
#endif
diff --git a/include/qom/object.h b/include/qom/object.h
index a707b67781..dc73d59660 100644
--- a/include/qom/object.h
+++ b/include/qom/object.h
@@ -79,6 +79,28 @@ typedef struct InterfaceInfo InterfaceInfo;
* #TypeInfo describes information about the type including what it inherits
* from, the instance and class size, and constructor/destructor hooks.
*
+ * Alternatively several static types could be registered using helper macro
+ * DEFINE_TYPES()
+ *
+ * <example>
+ * <programlisting>
+ * static const TypeInfo device_types_info[] = {
+ * {
+ * .name = TYPE_MY_DEVICE_A,
+ * .parent = TYPE_DEVICE,
+ * .instance_size = sizeof(MyDeviceA),
+ * },
+ * {
+ * .name = TYPE_MY_DEVICE_B,
+ * .parent = TYPE_DEVICE,
+ * .instance_size = sizeof(MyDeviceB),
+ * },
+ * };
+ *
+ * DEFINE_TYPES(device_types_info)
+ * </programlisting>
+ * </example>
+ *
* Every type has an #ObjectClass associated with it. #ObjectClass derivatives
* are instantiated dynamically but there is only ever one instance for any
* given type. The #ObjectClass typically holds a table of function pointers
@@ -789,6 +811,30 @@ Type type_register_static(const TypeInfo *info);
Type type_register(const TypeInfo *info);
/**
+ * type_register_static_array:
+ * @infos: The array of the new type #TypeInfo structures.
+ * @nr_infos: number of entries in @infos
+ *
+ * @infos and all of the strings it points to should exist for the life time
+ * that the type is registered.
+ */
+void type_register_static_array(const TypeInfo *infos, int nr_infos);
+
+/**
+ * DEFINE_TYPES:
+ * @type_array: The array containing #TypeInfo structures to register
+ *
+ * @type_array should be static constant that exists for the life time
+ * that the type is registered.
+ */
+#define DEFINE_TYPES(type_array) \
+static void do_qemu_init_ ## type_array(void) \
+{ \
+ type_register_static_array(type_array, ARRAY_SIZE(type_array)); \
+} \
+type_init(do_qemu_init_ ## type_array)
+
+/**
* object_class_dynamic_cast_assert:
* @klass: The #ObjectClass to attempt to cast.
* @typename: The QOM typename of the class to cast to.
diff --git a/qom/object.c b/qom/object.c
index 6a7bd9257b..c58c52d518 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -151,6 +151,15 @@ TypeImpl *type_register_static(const TypeInfo *info)
return type_register(info);
}
+void type_register_static_array(const TypeInfo *infos, int nr_infos)
+{
+ int i;
+
+ for (i = 0; i < nr_infos; i++) {
+ type_register_static(&infos[i]);
+ }
+}
+
static TypeImpl *type_get_by_name(const char *name)
{
if (name == NULL) {
diff --git a/target/ppc/cpu-models.c b/target/ppc/cpu-models.c
index 9d45702843..6c9bfde2d2 100644
--- a/target/ppc/cpu-models.c
+++ b/target/ppc/cpu-models.c
@@ -756,8 +756,10 @@
POWERPC_DEF("970_v2.2", CPU_POWERPC_970_v22, 970,
"PowerPC 970 v2.2")
- POWERPC_DEF("power9_v1.0", CPU_POWERPC_POWER9_BASE, POWER9,
+ POWERPC_DEF("power9_v1.0", CPU_POWERPC_POWER9_DD1, POWER9,
"POWER9 v1.0")
+ POWERPC_DEF("power9_v2.0", CPU_POWERPC_POWER9_DD20, POWER9,
+ "POWER9 v2.0")
POWERPC_DEF("970fx_v1.0", CPU_POWERPC_970FX_v10, 970,
"PowerPC 970FX v1.0 (G5)")
@@ -945,7 +947,7 @@ PowerPCCPUAlias ppc_cpu_aliases[] = {
{ "power8e", "power8e_v2.1" },
{ "power8", "power8_v2.0" },
{ "power8nvl", "power8nvl_v1.0" },
- { "power9", "power9_v1.0" },
+ { "power9", "power9_v2.0" },
{ "970", "970_v2.2" },
{ "970fx", "970fx_v3.1" },
{ "970mp", "970mp_v1.1" },
diff --git a/target/ppc/cpu-models.h b/target/ppc/cpu-models.h
index 25ef372d4c..efdb2fa53c 100644
--- a/target/ppc/cpu-models.h
+++ b/target/ppc/cpu-models.h
@@ -372,6 +372,7 @@ enum {
CPU_POWERPC_POWER8NVL_v10 = 0x004C0100,
CPU_POWERPC_POWER9_BASE = 0x004E0000,
CPU_POWERPC_POWER9_DD1 = 0x004E0100,
+ CPU_POWERPC_POWER9_DD20 = 0x004E1200,
CPU_POWERPC_970_v22 = 0x00390202,
CPU_POWERPC_970FX_v10 = 0x00391100,
CPU_POWERPC_970FX_v20 = 0x003C0200,
diff --git a/target/ppc/cpu-qom.h b/target/ppc/cpu-qom.h
index d0cf6ca2a9..429b47f959 100644
--- a/target/ppc/cpu-qom.h
+++ b/target/ppc/cpu-qom.h
@@ -181,6 +181,7 @@ typedef struct PowerPCCPUClass {
DeviceRealize parent_realize;
DeviceUnrealize parent_unrealize;
void (*parent_reset)(CPUState *cpu);
+ void (*parent_parse_features)(const char *type, char *str, Error **errp);
uint32_t pvr;
bool (*pvr_match)(struct PowerPCCPUClass *pcc, uint32_t pvr);
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index 64aef17f6f..989761b795 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -1278,7 +1278,6 @@ extern const struct VMStateDescription vmstate_ppc_cpu;
/*****************************************************************************/
void ppc_translate_init(void);
-const char *ppc_cpu_lookup_alias(const char *alias);
/* you can call this signal handler from your SIGBUS and SIGSEGV
signal handlers to inform the virtual CPU of exceptions. non zero
is returned if the signal was handled by the virtual CPU. */
diff --git a/target/ppc/int_helper.c b/target/ppc/int_helper.c
index da4e1a62c9..1c013a0ee3 100644
--- a/target/ppc/int_helper.c
+++ b/target/ppc/int_helper.c
@@ -219,17 +219,17 @@ target_ulong helper_sraw(CPUPPCState *env, target_ulong value,
shift &= 0x1f;
ret = (int32_t)value >> shift;
if (likely(ret >= 0 || (value & ((1 << shift) - 1)) == 0)) {
- env->ca = 0;
+ env->ca32 = env->ca = 0;
} else {
- env->ca = 1;
+ env->ca32 = env->ca = 1;
}
} else {
ret = (int32_t)value;
- env->ca = 0;
+ env->ca32 = env->ca = 0;
}
} else {
ret = (int32_t)value >> 31;
- env->ca = (ret != 0);
+ env->ca32 = env->ca = (ret != 0);
}
return (target_long)ret;
}
@@ -245,17 +245,17 @@ target_ulong helper_srad(CPUPPCState *env, target_ulong value,
shift &= 0x3f;
ret = (int64_t)value >> shift;
if (likely(ret >= 0 || (value & ((1ULL << shift) - 1)) == 0)) {
- env->ca = 0;
+ env->ca32 = env->ca = 0;
} else {
- env->ca = 1;
+ env->ca32 = env->ca = 1;
}
} else {
ret = (int64_t)value;
- env->ca = 0;
+ env->ca32 = env->ca = 0;
}
} else {
ret = (int64_t)value >> 63;
- env->ca = (ret != 0);
+ env->ca32 = env->ca = (ret != 0);
}
return ret;
}
diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c
index 171d3d8040..9d57debf0e 100644
--- a/target/ppc/kvm.c
+++ b/target/ppc/kvm.c
@@ -123,7 +123,7 @@ static bool kvmppc_is_pr(KVMState *ks)
return kvm_vm_check_extension(ks, KVM_CAP_PPC_GET_PVINFO) != 0;
}
-static int kvm_ppc_register_host_cpu_type(void);
+static int kvm_ppc_register_host_cpu_type(MachineState *ms);
int kvm_arch_init(MachineState *ms, KVMState *s)
{
@@ -163,7 +163,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
"VM to stall at times!\n");
}
- kvm_ppc_register_host_cpu_type();
+ kvm_ppc_register_host_cpu_type(ms);
return 0;
}
@@ -2487,12 +2487,13 @@ PowerPCCPUClass *kvm_ppc_get_host_cpu_class(void)
return pvr_pcc;
}
-static int kvm_ppc_register_host_cpu_type(void)
+static int kvm_ppc_register_host_cpu_type(MachineState *ms)
{
TypeInfo type_info = {
.name = TYPE_HOST_POWERPC_CPU,
.class_init = kvmppc_host_cpu_class_init,
};
+ MachineClass *mc = MACHINE_GET_CLASS(ms);
PowerPCCPUClass *pvr_pcc;
ObjectClass *oc;
DeviceClass *dc;
@@ -2504,21 +2505,14 @@ static int kvm_ppc_register_host_cpu_type(void)
}
type_info.parent = object_class_get_name(OBJECT_CLASS(pvr_pcc));
type_register(&type_info);
+ if (object_dynamic_cast(OBJECT(ms), TYPE_SPAPR_MACHINE)) {
+ /* override TCG default cpu type with 'host' cpu model */
+ mc->default_cpu_type = TYPE_HOST_POWERPC_CPU;
+ }
oc = object_class_by_name(type_info.name);
g_assert(oc);
-#if defined(TARGET_PPC64)
- type_info.name = g_strdup_printf("%s-"TYPE_SPAPR_CPU_CORE, "host");
- type_info.parent = TYPE_SPAPR_CPU_CORE,
- type_info.instance_size = sizeof(sPAPRCPUCore);
- type_info.instance_init = NULL;
- type_info.class_init = spapr_cpu_core_class_init;
- type_info.class_data = (void *) "host";
- type_register(&type_info);
- g_free((void *)type_info.name);
-#endif
-
/*
* Update generic CPU family class alias (e.g. on a POWER8NVL host,
* we want "POWER8" to be a "family" alias that points to the current
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 606b605ba0..a81ff69d75 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -2181,6 +2181,9 @@ static void gen_srawi(DisasContext *ctx)
if (sh == 0) {
tcg_gen_ext32s_tl(dst, src);
tcg_gen_movi_tl(cpu_ca, 0);
+ if (is_isa300(ctx)) {
+ tcg_gen_movi_tl(cpu_ca32, 0);
+ }
} else {
TCGv t0;
tcg_gen_ext32s_tl(dst, src);
@@ -2190,6 +2193,9 @@ static void gen_srawi(DisasContext *ctx)
tcg_gen_and_tl(cpu_ca, cpu_ca, t0);
tcg_temp_free(t0);
tcg_gen_setcondi_tl(TCG_COND_NE, cpu_ca, cpu_ca, 0);
+ if (is_isa300(ctx)) {
+ tcg_gen_mov_tl(cpu_ca32, cpu_ca);
+ }
tcg_gen_sari_tl(dst, dst, sh);
}
if (unlikely(Rc(ctx->opcode) != 0)) {
@@ -2259,6 +2265,9 @@ static inline void gen_sradi(DisasContext *ctx, int n)
if (sh == 0) {
tcg_gen_mov_tl(dst, src);
tcg_gen_movi_tl(cpu_ca, 0);
+ if (is_isa300(ctx)) {
+ tcg_gen_movi_tl(cpu_ca32, 0);
+ }
} else {
TCGv t0;
tcg_gen_andi_tl(cpu_ca, src, (1ULL << sh) - 1);
@@ -2267,6 +2276,9 @@ static inline void gen_sradi(DisasContext *ctx, int n)
tcg_gen_and_tl(cpu_ca, cpu_ca, t0);
tcg_temp_free(t0);
tcg_gen_setcondi_tl(TCG_COND_NE, cpu_ca, cpu_ca, 0);
+ if (is_isa300(ctx)) {
+ tcg_gen_mov_tl(cpu_ca32, cpu_ca);
+ }
tcg_gen_sari_tl(dst, src, sh);
}
if (unlikely(Rc(ctx->opcode) != 0)) {
diff --git a/target/ppc/translate_init.c b/target/ppc/translate_init.c
index c6399a3a0d..7b9bf6a773 100644
--- a/target/ppc/translate_init.c
+++ b/target/ppc/translate_init.c
@@ -4176,223 +4176,6 @@ POWERPC_FAMILY(440x5wDFPU)(ObjectClass *oc, void *data)
POWERPC_FLAG_DE | POWERPC_FLAG_BUS_CLK;
}
-static void init_proc_460 (CPUPPCState *env)
-{
- /* Time base */
- gen_tbl(env);
- gen_spr_BookE(env, 0x000000000000FFFFULL);
- gen_spr_440(env);
- gen_spr_usprgh(env);
- /* Processor identification */
- spr_register(env, SPR_BOOKE_PIR, "PIR",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_pir,
- 0x00000000);
- /* XXX : not implemented */
- spr_register(env, SPR_BOOKE_IAC3, "IAC3",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
- 0x00000000);
- /* XXX : not implemented */
- spr_register(env, SPR_BOOKE_IAC4, "IAC4",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
- 0x00000000);
- /* XXX : not implemented */
- spr_register(env, SPR_BOOKE_DVC1, "DVC1",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
- 0x00000000);
- /* XXX : not implemented */
- spr_register(env, SPR_BOOKE_DVC2, "DVC2",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
- 0x00000000);
- /* XXX : not implemented */
- spr_register(env, SPR_BOOKE_MCSR, "MCSR",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
- 0x00000000);
- spr_register(env, SPR_BOOKE_MCSRR0, "MCSRR0",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
- 0x00000000);
- spr_register(env, SPR_BOOKE_MCSRR1, "MCSRR1",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
- 0x00000000);
- /* XXX : not implemented */
- spr_register(env, SPR_440_CCR1, "CCR1",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
- 0x00000000);
- /* XXX : not implemented */
- spr_register(env, SPR_DCRIPR, "SPR_DCRIPR",
- &spr_read_generic, &spr_write_generic,
- &spr_read_generic, &spr_write_generic,
- 0x00000000);
- /* Memory management */
-#if !defined(CONFIG_USER_ONLY)
- env->nb_tlb = 64;
- env->nb_ways = 1;
- env->id_tlbs = 0;
- env->tlb_type = TLB_EMB;
-#endif
- init_excp_BookE(env);
- env->dcache_line_size = 32;
- env->icache_line_size = 32;
- /* XXX: TODO: allocate internal IRQ controller */
-
- SET_FIT_PERIOD(12, 16, 20, 24);
- SET_WDT_PERIOD(20, 24, 28, 32);
-}
-
-POWERPC_FAMILY(460)(ObjectClass *oc, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(oc);
- PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
-
- dc->desc = "PowerPC 460 (guessed)";
- pcc->init_proc = init_proc_460;
- pcc->check_pow = check_pow_nocheck;
- pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING |
- PPC_DCR | PPC_DCRX | PPC_DCRUX |
- PPC_WRTEE | PPC_MFAPIDI | PPC_MFTB |
- PPC_CACHE | PPC_CACHE_ICBI |
- PPC_CACHE_DCBZ | PPC_CACHE_DCBA |
- PPC_MEM_TLBSYNC | PPC_TLBIVA |
- PPC_BOOKE | PPC_4xx_COMMON | PPC_405_MAC |
- PPC_440_SPEC;
- pcc->msr_mask = (1ull << MSR_POW) |
- (1ull << MSR_CE) |
- (1ull << MSR_EE) |
- (1ull << MSR_PR) |
- (1ull << MSR_FP) |
- (1ull << MSR_ME) |
- (1ull << MSR_FE0) |
- (1ull << MSR_DWE) |
- (1ull << MSR_DE) |
- (1ull << MSR_FE1) |
- (1ull << MSR_IR) |
- (1ull << MSR_DR);
- pcc->mmu_model = POWERPC_MMU_BOOKE;
- pcc->excp_model = POWERPC_EXCP_BOOKE;
- pcc->bus_model = PPC_FLAGS_INPUT_BookE;
- pcc->bfd_mach = bfd_mach_ppc_403;
- pcc->flags = POWERPC_FLAG_CE | POWERPC_FLAG_DWE |
- POWERPC_FLAG_DE | POWERPC_FLAG_BUS_CLK;
-}
-
-static void init_proc_460F(CPUPPCState *env)
-{
- /* Time base */
- gen_tbl(env);
- gen_spr_BookE(env, 0x000000000000FFFFULL);
- gen_spr_440(env);
- gen_spr_usprgh(env);
- /* Processor identification */
- spr_register(env, SPR_BOOKE_PIR, "PIR",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_pir,
- 0x00000000);
- /* XXX : not implemented */
- spr_register(env, SPR_BOOKE_IAC3, "IAC3",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
- 0x00000000);
- /* XXX : not implemented */
- spr_register(env, SPR_BOOKE_IAC4, "IAC4",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
- 0x00000000);
- /* XXX : not implemented */
- spr_register(env, SPR_BOOKE_DVC1, "DVC1",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
- 0x00000000);
- /* XXX : not implemented */
- spr_register(env, SPR_BOOKE_DVC2, "DVC2",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
- 0x00000000);
- /* XXX : not implemented */
- spr_register(env, SPR_BOOKE_MCSR, "MCSR",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
- 0x00000000);
- spr_register(env, SPR_BOOKE_MCSRR0, "MCSRR0",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
- 0x00000000);
- spr_register(env, SPR_BOOKE_MCSRR1, "MCSRR1",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
- 0x00000000);
- /* XXX : not implemented */
- spr_register(env, SPR_440_CCR1, "CCR1",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
- 0x00000000);
- /* XXX : not implemented */
- spr_register(env, SPR_DCRIPR, "SPR_DCRIPR",
- &spr_read_generic, &spr_write_generic,
- &spr_read_generic, &spr_write_generic,
- 0x00000000);
- /* Memory management */
-#if !defined(CONFIG_USER_ONLY)
- env->nb_tlb = 64;
- env->nb_ways = 1;
- env->id_tlbs = 0;
- env->tlb_type = TLB_EMB;
-#endif
- init_excp_BookE(env);
- env->dcache_line_size = 32;
- env->icache_line_size = 32;
- /* XXX: TODO: allocate internal IRQ controller */
-
- SET_FIT_PERIOD(12, 16, 20, 24);
- SET_WDT_PERIOD(20, 24, 28, 32);
-}
-
-POWERPC_FAMILY(460F)(ObjectClass *oc, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(oc);
- PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
-
- dc->desc = "PowerPC 460F (guessed)";
- pcc->init_proc = init_proc_460F;
- pcc->check_pow = check_pow_nocheck;
- pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING |
- PPC_FLOAT | PPC_FLOAT_FRES | PPC_FLOAT_FSEL |
- PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
- PPC_FLOAT_STFIWX | PPC_MFTB |
- PPC_DCR | PPC_DCRX | PPC_DCRUX |
- PPC_WRTEE | PPC_MFAPIDI |
- PPC_CACHE | PPC_CACHE_ICBI |
- PPC_CACHE_DCBZ | PPC_CACHE_DCBA |
- PPC_MEM_TLBSYNC | PPC_TLBIVA |
- PPC_BOOKE | PPC_4xx_COMMON | PPC_405_MAC |
- PPC_440_SPEC;
- pcc->msr_mask = (1ull << MSR_POW) |
- (1ull << MSR_CE) |
- (1ull << MSR_EE) |
- (1ull << MSR_PR) |
- (1ull << MSR_FP) |
- (1ull << MSR_ME) |
- (1ull << MSR_FE0) |
- (1ull << MSR_DWE) |
- (1ull << MSR_DE) |
- (1ull << MSR_FE1) |
- (1ull << MSR_IR) |
- (1ull << MSR_DR);
- pcc->mmu_model = POWERPC_MMU_BOOKE;
- pcc->excp_model = POWERPC_EXCP_BOOKE;
- pcc->bus_model = PPC_FLAGS_INPUT_BookE;
- pcc->bfd_mach = bfd_mach_ppc_403;
- pcc->flags = POWERPC_FLAG_CE | POWERPC_FLAG_DWE |
- POWERPC_FLAG_DE | POWERPC_FLAG_BUS_CLK;
-}
-
static void init_proc_MPC5xx(CPUPPCState *env)
{
/* Time base */
@@ -10277,6 +10060,19 @@ PowerPCCPUClass *ppc_cpu_class_by_pvr_mask(uint32_t pvr)
return pcc;
}
+static const char *ppc_cpu_lookup_alias(const char *alias)
+{
+ int ai;
+
+ for (ai = 0; ppc_cpu_aliases[ai].alias != NULL; ai++) {
+ if (strcmp(ppc_cpu_aliases[ai].alias, alias) == 0) {
+ return ppc_cpu_aliases[ai].model;
+ }
+ }
+
+ return NULL;
+}
+
static ObjectClass *ppc_cpu_class_by_name(const char *name)
{
char *cpu_model, *typename;
@@ -10314,17 +10110,59 @@ static ObjectClass *ppc_cpu_class_by_name(const char *name)
return NULL;
}
-const char *ppc_cpu_lookup_alias(const char *alias)
+static void ppc_cpu_parse_featurestr(const char *type, char *features,
+ Error **errp)
{
- int ai;
+ Object *machine = qdev_get_machine();
+ const PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(object_class_by_name(type));
- for (ai = 0; ppc_cpu_aliases[ai].alias != NULL; ai++) {
- if (strcmp(ppc_cpu_aliases[ai].alias, alias) == 0) {
- return ppc_cpu_aliases[ai].model;
+ if (!features) {
+ return;
+ }
+
+ if (object_property_find(machine, "max-cpu-compat", NULL)) {
+ int i;
+ char **inpieces;
+ char *s = features;
+ Error *local_err = NULL;
+ char *compat_str = NULL;
+
+ /*
+ * 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.
+ */
+ inpieces = g_strsplit(features, ",", 0);
+ *s = '\0';
+ for (i = 0; inpieces[i]; i++) {
+ if (g_str_has_prefix(inpieces[i], "compat=")) {
+ compat_str = inpieces[i];
+ continue;
+ }
+ if ((i != 0) && (s != features)) {
+ s = g_stpcpy(s, ",");
+ }
+ s = g_stpcpy(s, inpieces[i]);
+ }
+
+ if (compat_str) {
+ char *v = compat_str + strlen("compat=");
+ object_property_set_str(machine, v, "max-cpu-compat", &local_err);
+ }
+ g_strfreev(inpieces);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
}
}
- return NULL;
+ /* do property processing with generic handler */
+ pcc->parent_parse_features(type, features, errp);
}
PowerPCCPUClass *ppc_cpu_get_family_class(PowerPCCPUClass *pcc)
@@ -10706,6 +10544,8 @@ static void ppc_cpu_class_init(ObjectClass *oc, void *data)
cc->reset = ppc_cpu_reset;
cc->class_by_name = ppc_cpu_class_by_name;
+ pcc->parent_parse_features = cc->parse_features;
+ cc->parse_features = ppc_cpu_parse_featurestr;
cc->has_work = ppc_cpu_has_work;
cc->do_interrupt = ppc_cpu_do_interrupt;
cc->cpu_exec_interrupt = ppc_cpu_exec_interrupt;