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
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEEdfRlhq5hpmzETofcbDjKyiDZs5IFAlnlhPMACgkQbDjKyiDZ
 s5KiJBAAqYjaecPkh24mKGTXsyCkG2hq0Pmlg2CDRSxLQZICZOaE4zO26jGFvPSE
 1Y6zcyjhzQ75xg8uJeuD8i9L04u9XPkLzgQ42ZwxNggLaM+yf8av+7B6pXLhi/3q
 yMXOWR4VdSde9EYus6H58jSTmhUBjp3LlbTsfVLviN4Pw/EgZ+Jg1zVQu5SUwRoP
 U1bHnzN3L3BoEEN/QnCx05FI8Le9b4WJl4YNyivqZKGI9+xsztVSOEhe30fZYQX6
 erbaVICBGpLJziS4F90h0H8I3eUlW6YF2HgCRVolCeUXPQo0kNCrxfPyw7+ct+yJ
 Mr7fsng+grhKsY6LKL0+oZM5mUJD79ZviAd7Q1cmdwZrWcNwBXnuAhDehJJGzekM
 q6I9vv7Lq9a+Bqx0APBNOThFCK8+zHcdMPfwnlSCaR/jSwxd7ZzFxSNgqqVoPGtN
 gE/gYgq91g1+kBNZNf5J5n6QSobL7RpkCrjZVVN8z1EE/aqsK2i2Goav7gwLJF0C
 zVGGNdpqhn76EeXqMVrTOFO1hyfvE+dH7vdlUtqWqxbfm0ndQZH/cOV/Uqrx3D42
 jA7lb0Y/IAVrVY784Q+o54vFmD1k1zIOXLsjG/1QfcT9urA9ghuwn97Tbyms1PnC
 wYHIg3PuKb3CaM//hEp+iM+p+UWqxPMQOh0BFNzvVpOZNlZ1k/4=
 =aRCf
 -----END PGP SIGNATURE-----

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>
This commit is contained in:
Peter Maydell 2017-10-17 15:26:51 +01:00
commit 861cd431c9
33 changed files with 377 additions and 613 deletions

View File

@ -353,12 +353,14 @@ static const MemoryRegionOps pmac_ide_ops = {
static const VMStateDescription vmstate_pmac = { static const VMStateDescription vmstate_pmac = {
.name = "ide", .name = "ide",
.version_id = 4, .version_id = 5,
.minimum_version_id = 0, .minimum_version_id = 0,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_IDE_BUS(bus, MACIOIDEState), VMSTATE_IDE_BUS(bus, MACIOIDEState),
VMSTATE_IDE_DRIVES(bus.ifs, MACIOIDEState), VMSTATE_IDE_DRIVES(bus.ifs, MACIOIDEState),
VMSTATE_BOOL(dma_active, MACIOIDEState), VMSTATE_BOOL(dma_active, MACIOIDEState),
VMSTATE_UINT32(timing_reg, MACIOIDEState),
VMSTATE_UINT32(irq_reg, MACIOIDEState),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
} }
}; };

View File

@ -803,11 +803,6 @@ void ppce500_init(MachineState *machine, PPCE500Params *params)
SysBusDevice *s; SysBusDevice *s;
PPCE500CCSRState *ccsr; PPCE500CCSRState *ccsr;
/* Setup CPUs */
if (machine->cpu_model == NULL) {
machine->cpu_model = "e500v2_v30";
}
irqs = g_malloc0(smp_cpus * sizeof(qemu_irq *)); irqs = g_malloc0(smp_cpus * sizeof(qemu_irq *));
irqs[0] = g_malloc0(smp_cpus * sizeof(qemu_irq) * OPENPIC_OUTPUT_NB); irqs[0] = g_malloc0(smp_cpus * sizeof(qemu_irq) * OPENPIC_OUTPUT_NB);
for (i = 0; i < smp_cpus; i++) { for (i = 0; i < smp_cpus; i++) {
@ -815,8 +810,7 @@ void ppce500_init(MachineState *machine, PPCE500Params *params)
CPUState *cs; CPUState *cs;
qemu_irq *input; qemu_irq *input;
cpu = POWERPC_CPU(cpu_generic_init(TYPE_POWERPC_CPU, cpu = POWERPC_CPU(cpu_create(machine->cpu_type));
machine->cpu_model));
env = &cpu->env; env = &cpu->env;
cs = CPU(cpu); cs = CPU(cpu);

View File

@ -64,6 +64,7 @@ static void e500plat_machine_init(MachineClass *mc)
mc->init = e500plat_init; mc->init = e500plat_init;
mc->max_cpus = 32; mc->max_cpus = 32;
mc->has_dynamic_sysbus = true; mc->has_dynamic_sysbus = true;
mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("e500v2_v30");
} }
DEFINE_MACHINE("ppce500", e500plat_machine_init) DEFINE_MACHINE("ppce500", e500plat_machine_init)

View File

@ -174,16 +174,8 @@ static void ppc_core99_init(MachineState *machine)
linux_boot = (kernel_filename != NULL); linux_boot = (kernel_filename != NULL);
/* init CPUs */ /* 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++) { for (i = 0; i < smp_cpus; i++) {
cpu = POWERPC_CPU(cpu_generic_init(TYPE_POWERPC_CPU, cpu = POWERPC_CPU(cpu_create(machine->cpu_type));
machine->cpu_model));
env = &cpu->env; env = &cpu->env;
/* Set time-base frequency to 100 Mhz */ /* 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->max_cpus = MAX_CPUS;
mc->default_boot_order = "cd"; mc->default_boot_order = "cd";
mc->kvm_type = core99_kvm_type; 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 = { static const TypeInfo core99_machine_info = {

View File

@ -108,11 +108,8 @@ static void ppc_heathrow_init(MachineState *machine)
linux_boot = (kernel_filename != NULL); linux_boot = (kernel_filename != NULL);
/* init CPUs */ /* init CPUs */
if (machine->cpu_model == NULL)
machine->cpu_model = "G3";
for (i = 0; i < smp_cpus; i++) { for (i = 0; i < smp_cpus; i++) {
cpu = POWERPC_CPU(cpu_generic_init(TYPE_POWERPC_CPU, cpu = POWERPC_CPU(cpu_create(machine->cpu_type));
machine->cpu_model));
env = &cpu->env; env = &cpu->env;
/* Set time-base frequency to 16.6 Mhz */ /* 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 */ /* TOFIX "cad" when Mac floppy is implemented */
mc->default_boot_order = "cd"; mc->default_boot_order = "cd";
mc->kvm_type = heathrow_kvm_type; mc->kvm_type = heathrow_kvm_type;
mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("750_v3.1");
} }
static const TypeInfo ppc_heathrow_machine_info = { static const TypeInfo ppc_heathrow_machine_info = {

View File

@ -16,6 +16,7 @@
#include "sysemu/device_tree.h" #include "sysemu/device_tree.h"
#include "hw/ppc/openpic.h" #include "hw/ppc/openpic.h"
#include "qemu/error-report.h" #include "qemu/error-report.h"
#include "cpu.h"
static void mpc8544ds_fixup_devtree(PPCE500Params *params, void *fdt) static void mpc8544ds_fixup_devtree(PPCE500Params *params, void *fdt)
{ {
@ -55,6 +56,7 @@ static void ppce500_machine_init(MachineClass *mc)
mc->desc = "mpc8544ds"; mc->desc = "mpc8544ds";
mc->init = mpc8544ds_init; mc->init = mpc8544ds_init;
mc->max_cpus = 15; mc->max_cpus = 15;
mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("e500v2_v30");
} }
DEFINE_MACHINE("mpc8544ds", ppce500_machine_init) DEFINE_MACHINE("mpc8544ds", ppce500_machine_init)

View File

@ -55,6 +55,16 @@
#define KERNEL_LOAD_ADDR 0x20000000 #define KERNEL_LOAD_ADDR 0x20000000
#define INITRD_LOAD_ADDR 0x40000000 #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 : * On Power Systems E880 (POWER8), the max cpus (threads) should be :
* 4 * 4 sockets * 12 cores * 8 threads = 1536 * 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"); int cpus_offset = fdt_path_offset(fdt, "/cpus");
if (cpus_offset < 0) { if (cpus_offset < 0) {
cpus_offset = fdt_add_subnode(fdt, fdt_path_offset(fdt, "/"), cpus_offset = fdt_add_subnode(fdt, 0, "cpus");
"cpus");
if (cpus_offset) { if (cpus_offset) {
_FDT((fdt_setprop_cell(fdt, cpus_offset, "#address-cells", 0x1))); _FDT((fdt_setprop_cell(fdt, cpus_offset, "#address-cells", 0x1)));
_FDT((fdt_setprop_cell(fdt, cpus_offset, "#size-cells", 0x0))); _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) static void powernv_populate_chip(PnvChip *chip, void *fdt)
{ {
PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); const char *typename = pnv_chip_core_typename(chip);
char *typename = pnv_core_typename(pcc->cpu_model);
size_t typesize = object_type_get_instance_size(typename); size_t typesize = object_type_get_instance_size(typename);
int i; 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, powernv_populate_memory_node(fdt, chip->chip_id, chip->ram_start,
chip->ram_size); chip->ram_size);
} }
g_free(typename);
} }
static void powernv_populate_rtc(ISADevice *d, void *fdt, int lpc_off) 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 */ /* 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)) { if (!object_class_by_name(chip_typename)) {
error_report("invalid CPU model '%s' for %s machine", error_report("invalid CPU model '%.*s' for %s machine",
machine->cpu_model, MACHINE_GET_CLASS(machine)->name); i, machine->cpu_type, MACHINE_GET_CLASS(machine)->name);
exit(1); exit(1);
} }
@ -716,7 +720,6 @@ static void pnv_chip_power8e_class_init(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass);
PnvChipClass *k = PNV_CHIP_CLASS(klass); PnvChipClass *k = PNV_CHIP_CLASS(klass);
k->cpu_model = "POWER8E";
k->chip_type = PNV_CHIP_POWER8E; k->chip_type = PNV_CHIP_POWER8E;
k->chip_cfam_id = 0x221ef04980000000ull; /* P8 Murano DD2.1 */ k->chip_cfam_id = 0x221ef04980000000ull; /* P8 Murano DD2.1 */
k->cores_mask = POWER8E_CORE_MASK; 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"; 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) static void pnv_chip_power8_class_init(ObjectClass *klass, void *data)
{ {
DeviceClass *dc = DEVICE_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass);
PnvChipClass *k = PNV_CHIP_CLASS(klass); PnvChipClass *k = PNV_CHIP_CLASS(klass);
k->cpu_model = "POWER8";
k->chip_type = PNV_CHIP_POWER8; k->chip_type = PNV_CHIP_POWER8;
k->chip_cfam_id = 0x220ea04980000000ull; /* P8 Venice DD2.0 */ k->chip_cfam_id = 0x220ea04980000000ull; /* P8 Venice DD2.0 */
k->cores_mask = POWER8_CORE_MASK; 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"; 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) static void pnv_chip_power8nvl_class_init(ObjectClass *klass, void *data)
{ {
DeviceClass *dc = DEVICE_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass);
PnvChipClass *k = PNV_CHIP_CLASS(klass); PnvChipClass *k = PNV_CHIP_CLASS(klass);
k->cpu_model = "POWER8NVL";
k->chip_type = PNV_CHIP_POWER8NVL; k->chip_type = PNV_CHIP_POWER8NVL;
k->chip_cfam_id = 0x120d304980000000ull; /* P8 Naples DD1.0 */ k->chip_cfam_id = 0x120d304980000000ull; /* P8 Naples DD1.0 */
k->cores_mask = POWER8_CORE_MASK; 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"; 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) static void pnv_chip_power9_class_init(ObjectClass *klass, void *data)
{ {
DeviceClass *dc = DEVICE_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass);
PnvChipClass *k = PNV_CHIP_CLASS(klass); PnvChipClass *k = PNV_CHIP_CLASS(klass);
k->cpu_model = "POWER9";
k->chip_type = PNV_CHIP_POWER9; k->chip_type = PNV_CHIP_POWER9;
k->chip_cfam_id = 0x100d104980000000ull; /* P9 Nimbus DD1.0 */ k->chip_cfam_id = 0x100d104980000000ull; /* P9 Nimbus DD1.0 */
k->cores_mask = POWER9_CORE_MASK; 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"; 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) static void pnv_chip_core_sanitize(PnvChip *chip, Error **errp)
{ {
PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); 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) static void pnv_chip_icp_realize(PnvChip *chip, Error **errp)
{ {
PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); 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); size_t typesize = object_type_get_instance_size(typename);
int i, j; int i, j;
char *name; 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); memory_region_add_subregion(&chip->icp_mmio, pir << 12, &icp->mmio);
} }
} }
g_free(typename);
} }
static void pnv_chip_realize(DeviceState *dev, Error **errp) 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); PnvChip *chip = PNV_CHIP(dev);
Error *error = NULL; Error *error = NULL;
PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); 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); size_t typesize = object_type_get_instance_size(typename);
int i, core_hwid; int i, core_hwid;
@ -950,7 +920,6 @@ static void pnv_chip_realize(DeviceState *dev, Error **errp)
&PNV_CORE(pnv_core)->xscom_regs); &PNV_CORE(pnv_core)->xscom_regs);
i++; i++;
} }
g_free(typename);
/* Create LPC controller */ /* Create LPC controller */
object_property_set_bool(OBJECT(&chip->lpc), true, "realized", 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"; 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) static ICSState *pnv_ics_get(XICSFabric *xi, int irq)
{ {
PnvMachineState *pnv = POWERNV_MACHINE(xi); 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->init = ppc_powernv_init;
mc->reset = ppc_powernv_reset; mc->reset = ppc_powernv_reset;
mc->max_cpus = MAX_CPUS; 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 mc->block_default_type = IF_IDE; /* Pnv provides a AHCI device for
* storage */ * storage */
mc->no_parallel = 1; mc->no_parallel = 1;
@ -1146,7 +1107,15 @@ static void powernv_machine_class_init(ObjectClass *oc, void *data)
powernv_machine_class_props_init(oc); powernv_machine_class_props_init(oc);
} }
static const TypeInfo powernv_machine_info = { #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, .name = TYPE_POWERNV_MACHINE,
.parent = TYPE_MACHINE, .parent = TYPE_MACHINE,
.instance_size = sizeof(PnvMachineState), .instance_size = sizeof(PnvMachineState),
@ -1157,16 +1126,21 @@ static const TypeInfo powernv_machine_info = {
{ TYPE_INTERRUPT_STATS_PROVIDER }, { 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) DEFINE_TYPES(types)
{
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)

View File

@ -27,6 +27,16 @@
#include "hw/ppc/pnv_xscom.h" #include "hw/ppc/pnv_xscom.h"
#include "hw/ppc/xics.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) static void powernv_cpu_reset(void *opaque)
{ {
PowerPCCPU *cpu = opaque; PowerPCCPU *cpu = opaque;
@ -148,8 +158,7 @@ static void pnv_core_realize(DeviceState *dev, Error **errp)
{ {
PnvCore *pc = PNV_CORE(OBJECT(dev)); PnvCore *pc = PNV_CORE(OBJECT(dev));
CPUCore *cc = CPU_CORE(OBJECT(dev)); CPUCore *cc = CPU_CORE(OBJECT(dev));
PnvCoreClass *pcc = PNV_CORE_GET_CLASS(OBJECT(dev)); const char *typename = pnv_core_cpu_typename(pc);
const char *typename = object_class_get_name(pcc->cpu_oc);
size_t size = object_type_get_instance_size(typename); size_t size = object_type_get_instance_size(typename);
Error *local_err = NULL; Error *local_err = NULL;
void *obj; void *obj;
@ -211,46 +220,30 @@ static Property pnv_core_properties[] = {
static void pnv_core_class_init(ObjectClass *oc, void *data) static void pnv_core_class_init(ObjectClass *oc, void *data)
{ {
DeviceClass *dc = DEVICE_CLASS(oc); DeviceClass *dc = DEVICE_CLASS(oc);
PnvCoreClass *pcc = PNV_CORE_CLASS(oc);
dc->realize = pnv_core_realize; dc->realize = pnv_core_realize;
dc->props = pnv_core_properties; dc->props = pnv_core_properties;
pcc->cpu_oc = cpu_class_by_name(TYPE_POWERPC_CPU, data);
} }
static const TypeInfo pnv_core_info = { #define DEFINE_PNV_CORE_TYPE(cpu_model) \
{ \
.parent = TYPE_PNV_CORE, \
.name = PNV_CORE_TYPE_NAME(cpu_model), \
}
static const TypeInfo pnv_core_infos[] = {
{
.name = TYPE_PNV_CORE, .name = TYPE_PNV_CORE,
.parent = TYPE_CPU_CORE, .parent = TYPE_CPU_CORE,
.instance_size = sizeof(PnvCore), .instance_size = sizeof(PnvCore),
.class_size = sizeof(PnvCoreClass), .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_init = pnv_core_class_init,
.class_data = (void *) pnv_core_models[i], .abstract = true,
}; },
ti.name = pnv_core_typename(pnv_core_models[i]); DEFINE_PNV_CORE_TYPE("power8e_v2.1"),
type_register(&ti); DEFINE_PNV_CORE_TYPE("power8_v2.0"),
g_free((void *)ti.name); DEFINE_PNV_CORE_TYPE("power8nvl_v1.0"),
} DEFINE_PNV_CORE_TYPE("power9_v2.0"),
} };
type_init(pnv_core_register_types) DEFINE_TYPES(pnv_core_infos)
char *pnv_core_typename(const char *model)
{
return g_strdup_printf(TYPE_PNV_CORE "-%s", model);
}

View File

@ -1359,28 +1359,3 @@ void PPC_debug_write (void *opaque, uint32_t addr, uint32_t val)
break; 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);
}

View File

@ -1629,7 +1629,8 @@ CPUPPCState *ppc405cr_init(MemoryRegion *address_space_mem,
qemu_irq *pic, *irqs; qemu_irq *pic, *irqs;
memset(clk_setup, 0, sizeof(clk_setup)); 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); &clk_setup[PPC405CR_TMR_CLK], sysclk);
env = &cpu->env; env = &cpu->env;
/* Memory mapped devices registers */ /* Memory mapped devices registers */
@ -1981,7 +1982,8 @@ CPUPPCState *ppc405ep_init(MemoryRegion *address_space_mem,
memset(clk_setup, 0, sizeof(clk_setup)); memset(clk_setup, 0, sizeof(clk_setup));
/* init CPUs */ /* 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); &tlb_clk_setup, sysclk);
env = &cpu->env; env = &cpu->env;
clk_setup[PPC405EP_CPU_CLK].cb = tlb_clk_setup.cb; clk_setup[PPC405EP_CPU_CLK].cb = tlb_clk_setup.cb;

View File

@ -182,11 +182,7 @@ static void bamboo_init(MachineState *machine)
int success; int success;
int i; int i;
/* Setup CPU. */ cpu = POWERPC_CPU(cpu_create(machine->cpu_type));
if (machine->cpu_model == NULL) {
machine->cpu_model = "440EP";
}
cpu = POWERPC_CPU(cpu_generic_init(TYPE_POWERPC_CPU, machine->cpu_model));
env = &cpu->env; env = &cpu->env;
if (env->mmu_model != POWERPC_MMU_BOOKE) { if (env->mmu_model != POWERPC_MMU_BOOKE) {
@ -297,6 +293,7 @@ static void bamboo_machine_init(MachineClass *mc)
{ {
mc->desc = "bamboo"; mc->desc = "bamboo";
mc->init = bamboo_init; mc->init = bamboo_init;
mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("440epb");
} }
DEFINE_MACHINE("bamboo", bamboo_machine_init) DEFINE_MACHINE("bamboo", bamboo_machine_init)

View File

@ -48,7 +48,7 @@ static void ppc4xx_reset(void *opaque)
/*****************************************************************************/ /*****************************************************************************/
/* Generic PowerPC 4xx processor instantiation */ /* 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, clk_setup_t *cpu_clk, clk_setup_t *tb_clk,
uint32_t sysclk) uint32_t sysclk)
{ {
@ -56,7 +56,7 @@ PowerPCCPU *ppc4xx_init(const char *cpu_model,
CPUPPCState *env; CPUPPCState *env;
/* init CPUs */ /* init CPUs */
cpu = POWERPC_CPU(cpu_generic_init(TYPE_POWERPC_CPU, cpu_model)); cpu = POWERPC_CPU(cpu_create(cpu_type));
env = &cpu->env; env = &cpu->env;
cpu_clk->cb = NULL; /* We don't care about CPU clock frequency changes */ cpu_clk->cb = NULL; /* We don't care about CPU clock frequency changes */

View File

@ -517,11 +517,8 @@ static void ppc_prep_init(MachineState *machine)
linux_boot = (kernel_filename != NULL); linux_boot = (kernel_filename != NULL);
/* init CPUs */ /* init CPUs */
if (machine->cpu_model == NULL)
machine->cpu_model = "602";
for (i = 0; i < smp_cpus; i++) { for (i = 0; i < smp_cpus; i++) {
cpu = POWERPC_CPU(cpu_generic_init(TYPE_POWERPC_CPU, cpu = POWERPC_CPU(cpu_create(machine->cpu_type));
machine->cpu_model));
env = &cpu->env; env = &cpu->env;
if (env->flags & POWERPC_FLAG_RTC_CLK) { 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->block_default_type = IF_IDE;
mc->max_cpus = MAX_CPUS; mc->max_cpus = MAX_CPUS;
mc->default_boot_order = "cad"; mc->default_boot_order = "cad";
mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("602");
} }
static int prep_set_cmos_checksum(DeviceState *dev, void *opaque) static int prep_set_cmos_checksum(DeviceState *dev, void *opaque)
@ -718,10 +716,7 @@ static void ibm_40p_init(MachineState *machine)
char boot_device; char boot_device;
/* init CPU */ /* init CPU */
if (!machine->cpu_model) { cpu = POWERPC_CPU(cpu_create(machine->cpu_type));
machine->cpu_model = "604";
}
cpu = POWERPC_CPU(cpu_generic_init(TYPE_POWERPC_CPU, machine->cpu_model));
env = &cpu->env; env = &cpu->env;
if (PPC_INPUT(env) != PPC_FLAGS_INPUT_6xx) { if (PPC_INPUT(env) != PPC_FLAGS_INPUT_6xx) {
error_report("only 6xx bus is supported on this machine"); 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->default_ram_size = 128 * M_BYTE;
mc->block_default_type = IF_SCSI; mc->block_default_type = IF_SCSI;
mc->default_boot_order = "c"; mc->default_boot_order = "c";
mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("604");
} }
DEFINE_MACHINE("40p", ibm_40p_machine_init) DEFINE_MACHINE("40p", ibm_40p_machine_init)

View File

@ -353,8 +353,7 @@ static int spapr_fixup_cpu_dt(void *fdt, sPAPRMachineState *spapr)
cpus_offset = fdt_path_offset(fdt, "/cpus"); cpus_offset = fdt_path_offset(fdt, "/cpus");
if (cpus_offset < 0) { if (cpus_offset < 0) {
cpus_offset = fdt_add_subnode(fdt, fdt_path_offset(fdt, "/"), cpus_offset = fdt_add_subnode(fdt, 0, "cpus");
"cpus");
if (cpus_offset < 0) { if (cpus_offset < 0) {
return cpus_offset; return cpus_offset;
} }
@ -820,6 +819,13 @@ int spapr_h_cas_compose_response(sPAPRMachineState *spapr,
return 1; 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); size -= sizeof(hdr);
/* Create skeleton */ /* Create skeleton */
@ -2123,7 +2129,7 @@ static void spapr_init_cpus(sPAPRMachineState *spapr)
{ {
MachineState *machine = MACHINE(spapr); MachineState *machine = MACHINE(spapr);
MachineClass *mc = MACHINE_GET_CLASS(machine); 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(); int smt = kvmppc_smt_threads();
const CPUArchIdList *possible_cpus; const CPUArchIdList *possible_cpus;
int boot_cores_nr = smp_cpus / smp_threads; 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); object_property_set_bool(core, true, "realized", &error_fatal);
} }
} }
g_free(type);
} }
static void spapr_set_vsmt_mode(sPAPRMachineState *spapr, Error **errp) 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 */ /* Set up Interrupt Controller before we create the VCPUs */
xics_system_init(machine, XICS_IRQS_SPAPR, &error_fatal); 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 = spapr_ovec_new();
spapr->ov5_cas = spapr_ovec_new(); spapr->ov5_cas = spapr_ovec_new();
@ -2362,12 +2368,6 @@ static void ppc_spapr_init(MachineState *machine)
} }
/* init CPUs */ /* 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_set_vsmt_mode(spapr, &error_fatal);
spapr_init_cpus(spapr); spapr_init_cpus(spapr);
@ -3054,14 +3054,13 @@ void spapr_lmb_release(DeviceState *dev)
return; return;
} }
spapr_pending_dimm_unplugs_remove(spapr, ds);
/* /*
* Now that all the LMBs have been removed by the guest, call the * 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 unplug handler to cleanup up the pc-dimm device.
*/ */
pc_dimm_memory_unplug(dev, &spapr->hotplug_memory, mr); pc_dimm_memory_unplug(dev, &spapr->hotplug_memory, mr);
object_unparent(OBJECT(dev)); object_unparent(OBJECT(dev));
spapr_pending_dimm_unplugs_remove(spapr, ds);
} }
static void spapr_memory_unplug_request(HotplugHandler *hotplug_dev, static void spapr_memory_unplug_request(HotplugHandler *hotplug_dev,
@ -3090,6 +3089,19 @@ static void spapr_memory_unplug_request(HotplugHandler *hotplug_dev,
goto out; 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); spapr_pending_dimm_unplugs_add(spapr, nr_lmbs, dimm);
addr = addr_start; addr = addr_start;
@ -3142,8 +3154,7 @@ void spapr_core_release(DeviceState *dev)
if (smc->pre_2_10_has_unused_icps) { if (smc->pre_2_10_has_unused_icps) {
sPAPRCPUCore *sc = SPAPR_CPU_CORE(OBJECT(dev)); sPAPRCPUCore *sc = SPAPR_CPU_CORE(OBJECT(dev));
sPAPRCPUCoreClass *scc = SPAPR_CPU_CORE_GET_CLASS(OBJECT(cc)); 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(scc->cpu_type);
size_t size = object_type_get_instance_size(typename);
int i; int i;
for (i = 0; i < cc->nr_threads; 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) { if (smc->pre_2_10_has_unused_icps) {
sPAPRCPUCoreClass *scc = SPAPR_CPU_CORE_GET_CLASS(OBJECT(cc)); 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(scc->cpu_type);
size_t size = object_type_get_instance_size(typename);
int i; int i;
for (i = 0; i < cc->nr_threads; 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); MachineClass *mc = MACHINE_GET_CLASS(hotplug_dev);
Error *local_err = NULL; Error *local_err = NULL;
CPUCore *cc = CPU_CORE(dev); 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)); const char *type = object_get_typename(OBJECT(dev));
CPUArchId *core_slot; CPUArchId *core_slot;
int index; 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); numa_cpu_pre_plug(core_slot, dev, &local_err);
out: out:
g_free(base_core_type);
error_propagate(errp, local_err); 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; hc->unplug_request = spapr_machine_device_unplug_request;
smc->dr_lmb_enabled = true; 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; mc->has_hotpluggable_cpus = true;
smc->resize_hpt_default = SPAPR_RESIZE_HPT_ENABLED; smc->resize_hpt_default = SPAPR_RESIZE_HPT_ENABLED;
fwc->get_dev_path = spapr_get_fw_dev_path; 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); sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
spapr_machine_2_8_class_options(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); SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_7);
smc->phb_placement = phb_placement_2_7; smc->phb_placement = phb_placement_2_7;
} }

View File

@ -21,57 +21,6 @@
#include "sysemu/hw_accel.h" #include "sysemu/hw_accel.h"
#include "qemu/error-report.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) static void spapr_cpu_reset(void *opaque)
{ {
PowerPCCPU *cpu = 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 * Return the sPAPR CPU core type for @model which essentially is the CPU
* model specified with -cpu cmdline option. * 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; int len = strlen(cpu_type) - strlen(POWERPC_CPU_TYPE_SUFFIX);
gchar **model_pieces = g_strsplit(model, ",", 2); char *core_type = g_strdup_printf(SPAPR_CPU_CORE_TYPE_NAME("%.*s"),
gchar *cpu_model = g_ascii_strdown(model_pieces[0], -1); len, cpu_type);
g_strfreev(model_pieces); ObjectClass *oc = object_class_by_name(core_type);
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); g_free(core_type);
core_type = NULL; if (!oc) {
realmodel = ppc_cpu_lookup_alias(cpu_model); return NULL;
if (realmodel) {
core_type = spapr_get_cpu_core_type(realmodel);
} }
}
g_free(cpu_model);
return core_type; return object_class_get_name(oc);
} }
static void spapr_cpu_core_unrealizefn(DeviceState *dev, Error **errp) static void spapr_cpu_core_unrealizefn(DeviceState *dev, Error **errp)
{ {
sPAPRCPUCore *sc = SPAPR_CPU_CORE(OBJECT(dev)); sPAPRCPUCore *sc = SPAPR_CPU_CORE(OBJECT(dev));
sPAPRCPUCoreClass *scc = SPAPR_CPU_CORE_GET_CLASS(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(scc->cpu_type);
size_t size = object_type_get_instance_size(typename);
CPUCore *cc = CPU_CORE(dev); CPUCore *cc = CPU_CORE(dev);
int i; int i;
@ -199,22 +137,26 @@ error:
static void spapr_cpu_core_realize(DeviceState *dev, Error **errp) 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)); sPAPRCPUCore *sc = SPAPR_CPU_CORE(OBJECT(dev));
sPAPRCPUCoreClass *scc = SPAPR_CPU_CORE_GET_CLASS(OBJECT(dev)); sPAPRCPUCoreClass *scc = SPAPR_CPU_CORE_GET_CLASS(OBJECT(dev));
CPUCore *cc = CPU_CORE(OBJECT(dev)); CPUCore *cc = CPU_CORE(OBJECT(dev));
const char *typename = object_class_get_name(scc->cpu_class); size_t size;
size_t size = object_type_get_instance_size(typename);
Error *local_err = NULL; Error *local_err = NULL;
void *obj; void *obj;
int i, j; int i, j;
spapr = (sPAPRMachineState *) qdev_get_machine(); if (!spapr) {
if (!object_dynamic_cast((Object *) spapr, TYPE_SPAPR_MACHINE)) { error_setg(errp, TYPE_SPAPR_CPU_CORE " needs a pseries machine");
error_setg(errp, "spapr-cpu-core needs a pseries machine");
return; return;
} }
size = object_type_get_instance_size(scc->cpu_type);
sc->threads = g_malloc0(size * cc->nr_threads); sc->threads = g_malloc0(size * cc->nr_threads);
for (i = 0; i < cc->nr_threads; i++) { for (i = 0; i < cc->nr_threads; i++) {
char id[32]; char id[32];
@ -223,7 +165,7 @@ static void spapr_cpu_core_realize(DeviceState *dev, Error **errp)
obj = sc->threads + i * size; obj = sc->threads + i * size;
object_initialize(obj, size, typename); object_initialize(obj, size, scc->cpu_type);
cs = CPU(obj); cs = CPU(obj);
cpu = POWERPC_CPU(cs); cpu = POWERPC_CPU(cs);
cs->cpu_index = cc->core_id + i; cs->cpu_index = cc->core_id + i;
@ -268,42 +210,12 @@ err:
error_propagate(errp, local_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[] = { static Property spapr_cpu_core_properties[] = {
DEFINE_PROP_INT32("node-id", sPAPRCPUCore, node_id, CPU_UNSET_NUMA_NODE_ID), DEFINE_PROP_INT32("node-id", sPAPRCPUCore, node_id, CPU_UNSET_NUMA_NODE_ID),
DEFINE_PROP_END_OF_LIST() 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); DeviceClass *dc = DEVICE_CLASS(oc);
sPAPRCPUCoreClass *scc = SPAPR_CPU_CORE_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->realize = spapr_cpu_core_realize;
dc->unrealize = spapr_cpu_core_unrealizefn; dc->unrealize = spapr_cpu_core_unrealizefn;
dc->props = spapr_cpu_core_properties; dc->props = spapr_cpu_core_properties;
scc->cpu_class = cpu_class_by_name(TYPE_POWERPC_CPU, data); scc->cpu_type = data;
g_assert(scc->cpu_class);
} }
static const TypeInfo spapr_cpu_core_type_info = { #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), \
}
static const TypeInfo spapr_cpu_core_type_infos[] = {
{
.name = TYPE_SPAPR_CPU_CORE, .name = TYPE_SPAPR_CPU_CORE,
.parent = TYPE_CPU_CORE, .parent = TYPE_CPU_CORE,
.abstract = true, .abstract = true,
.instance_size = sizeof(sPAPRCPUCore), .instance_size = sizeof(sPAPRCPUCore),
.class_size = sizeof(sPAPRCPUCoreClass), .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
}; };
static void spapr_cpu_core_register_types(void) DEFINE_TYPES(spapr_cpu_core_type_infos)
{
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);
}
}
type_init(spapr_cpu_core_register_types)

View File

@ -472,7 +472,7 @@ static target_ulong h_resize_hpt_prepare(PowerPCCPU *cpu,
target_ulong flags = args[0]; target_ulong flags = args[0];
int shift = args[1]; int shift = args[1];
sPAPRPendingHPT *pending = spapr->pending_hpt; sPAPRPendingHPT *pending = spapr->pending_hpt;
uint64_t current_ram_size = MACHINE(spapr)->ram_size; uint64_t current_ram_size;
int rc; int rc;
if (spapr->resize_hpt == SPAPR_RESIZE_HPT_DISABLED) { if (spapr->resize_hpt == SPAPR_RESIZE_HPT_DISABLED) {
@ -494,7 +494,7 @@ static target_ulong h_resize_hpt_prepare(PowerPCCPU *cpu,
return H_PARAMETER; 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 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 * we'd normally give them (to stop a small guest claiming a huge

View File

@ -1507,7 +1507,12 @@ static void spapr_pci_unplug_request(HotplugHandler *plug_handler,
static void spapr_phb_realize(DeviceState *dev, Error **errp) 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); SysBusDevice *s = SYS_BUS_DEVICE(dev);
sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(s); sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(s);
PCIHostState *phb = 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 = const unsigned windows_supported =
sphb->ddw_enabled ? SPAPR_PCI_DMA_MAX_WINDOWS : 1; 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) { if (sphb->index != (uint32_t)-1) {
sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
Error *local_err = NULL; Error *local_err = NULL;

View File

@ -89,14 +89,14 @@ static void mmubooke_create_initial_mapping(CPUPPCState *env,
static PowerPCCPU *ppc440_init_xilinx(ram_addr_t *ram_size, static PowerPCCPU *ppc440_init_xilinx(ram_addr_t *ram_size,
int do_init, int do_init,
const char *cpu_model, const char *cpu_type,
uint32_t sysclk) uint32_t sysclk)
{ {
PowerPCCPU *cpu; PowerPCCPU *cpu;
CPUPPCState *env; CPUPPCState *env;
qemu_irq *irqs; qemu_irq *irqs;
cpu = POWERPC_CPU(cpu_generic_init(TYPE_POWERPC_CPU, cpu_model)); cpu = POWERPC_CPU(cpu_create(cpu_type));
env = &cpu->env; env = &cpu->env;
ppc_booke_timers_init(cpu, sysclk, 0/* no flags */); ppc_booke_timers_init(cpu, sysclk, 0/* no flags */);
@ -211,11 +211,7 @@ static void virtex_init(MachineState *machine)
int i; int i;
/* init CPUs */ /* init CPUs */
if (machine->cpu_model == NULL) { cpu = ppc440_init_xilinx(&ram_size, 1, machine->cpu_type, 400000000);
machine->cpu_model = "440-Xilinx";
}
cpu = ppc440_init_xilinx(&ram_size, 1, machine->cpu_model, 400000000);
env = &cpu->env; env = &cpu->env;
if (env->mmu_model != POWERPC_MMU_BOOKE) { 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->desc = "Xilinx Virtex ML507 reference design";
mc->init = virtex_init; mc->init = virtex_init;
mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("440-xilinx");
} }
DEFINE_MACHINE("virtex-ml507", virtex_machine_init) DEFINE_MACHINE("virtex-ml507", virtex_machine_init)

View File

@ -69,7 +69,6 @@ typedef struct PnvChipClass {
SysBusDeviceClass parent_class; SysBusDeviceClass parent_class;
/*< public >*/ /*< public >*/
const char *cpu_model;
PnvChipType chip_type; PnvChipType chip_type;
uint64_t chip_cfam_id; uint64_t chip_cfam_id;
uint64_t cores_mask; uint64_t cores_mask;
@ -80,19 +79,22 @@ typedef struct PnvChipClass {
uint32_t (*core_pir)(PnvChip *chip, uint32_t core_id); uint32_t (*core_pir)(PnvChip *chip, uint32_t core_id);
} PnvChipClass; } 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) \ #define PNV_CHIP_POWER8E(obj) \
OBJECT_CHECK(PnvChip, (obj), TYPE_PNV_CHIP_POWER8E) 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) \ #define PNV_CHIP_POWER8(obj) \
OBJECT_CHECK(PnvChip, (obj), TYPE_PNV_CHIP_POWER8) 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) \ #define PNV_CHIP_POWER8NVL(obj) \
OBJECT_CHECK(PnvChip, (obj), TYPE_PNV_CHIP_POWER8NVL) 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) \ #define PNV_CHIP_POWER9(obj) \
OBJECT_CHECK(PnvChip, (obj), TYPE_PNV_CHIP_POWER9) OBJECT_CHECK(PnvChip, (obj), TYPE_PNV_CHIP_POWER9)

View File

@ -42,9 +42,9 @@ typedef struct PnvCore {
typedef struct PnvCoreClass { typedef struct PnvCoreClass {
DeviceClass parent_class; DeviceClass parent_class;
ObjectClass *cpu_oc;
} PnvCoreClass; } 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 */ #endif /* _PPC_PNV_CORE_H */

View File

@ -105,6 +105,4 @@ enum {
/* ppc_booke.c */ /* ppc_booke.c */
void ppc_booke_timers_init(PowerPCCPU *cpu, uint32_t freq, uint32_t flags); void ppc_booke_timers_init(PowerPCCPU *cpu, uint32_t freq, uint32_t flags);
void ppc_cpu_parse_features(const char *cpu_model);
#endif #endif

View File

@ -60,7 +60,6 @@ struct sPAPRMachineClass {
/*< public >*/ /*< public >*/
bool dr_lmb_enabled; /* enable dynamic-reconfig/hotplug of LMBs */ bool dr_lmb_enabled; /* enable dynamic-reconfig/hotplug of LMBs */
bool use_ohci_by_default; /* use USB-OHCI instead of XHCI */ 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 pre_2_10_has_unused_icps;
void (*phb_placement)(sPAPRMachineState *spapr, uint32_t index, void (*phb_placement)(sPAPRMachineState *spapr, uint32_t index,
uint64_t *buid, hwaddr *pio, 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); uint32_t count, uint32_t index);
void spapr_hotplug_req_remove_by_count_indexed(sPAPRDRConnectorType drc_type, void spapr_hotplug_req_remove_by_count_indexed(sPAPRDRConnectorType drc_type,
uint32_t count, uint32_t index); uint32_t count, uint32_t index);
void spapr_cpu_parse_features(sPAPRMachineState *spapr);
int spapr_hpt_shift_for_ramsize(uint64_t ramsize); int spapr_hpt_shift_for_ramsize(uint64_t ramsize);
void spapr_reallocate_hpt(sPAPRMachineState *spapr, int shift, void spapr_reallocate_hpt(sPAPRMachineState *spapr, int shift,
Error **errp); Error **errp);

View File

@ -21,6 +21,8 @@
#define SPAPR_CPU_CORE_GET_CLASS(obj) \ #define SPAPR_CPU_CORE_GET_CLASS(obj) \
OBJECT_GET_CLASS(sPAPRCPUCoreClass, (obj), TYPE_SPAPR_CPU_CORE) OBJECT_GET_CLASS(sPAPRCPUCoreClass, (obj), TYPE_SPAPR_CPU_CORE)
#define SPAPR_CPU_CORE_TYPE_NAME(model) model "-" TYPE_SPAPR_CPU_CORE
typedef struct sPAPRCPUCore { typedef struct sPAPRCPUCore {
/*< private >*/ /*< private >*/
CPUCore parent_obj; CPUCore parent_obj;
@ -32,9 +34,8 @@ typedef struct sPAPRCPUCore {
typedef struct sPAPRCPUCoreClass { typedef struct sPAPRCPUCoreClass {
DeviceClass parent_class; DeviceClass parent_class;
ObjectClass *cpu_class; const char *cpu_type;
} sPAPRCPUCoreClass; } sPAPRCPUCoreClass;
char *spapr_get_cpu_core_type(const char *model); const char *spapr_get_cpu_core_type(const char *cpu_type);
void spapr_cpu_core_class_init(ObjectClass *oc, void *data);
#endif #endif

View File

@ -79,6 +79,28 @@ typedef struct InterfaceInfo InterfaceInfo;
* #TypeInfo describes information about the type including what it inherits * #TypeInfo describes information about the type including what it inherits
* from, the instance and class size, and constructor/destructor hooks. * 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 * Every type has an #ObjectClass associated with it. #ObjectClass derivatives
* are instantiated dynamically but there is only ever one instance for any * are instantiated dynamically but there is only ever one instance for any
* given type. The #ObjectClass typically holds a table of function pointers * given type. The #ObjectClass typically holds a table of function pointers
@ -788,6 +810,30 @@ Type type_register_static(const TypeInfo *info);
*/ */
Type type_register(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: * object_class_dynamic_cast_assert:
* @klass: The #ObjectClass to attempt to cast. * @klass: The #ObjectClass to attempt to cast.

View File

@ -151,6 +151,15 @@ TypeImpl *type_register_static(const TypeInfo *info)
return type_register(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) static TypeImpl *type_get_by_name(const char *name)
{ {
if (name == NULL) { if (name == NULL) {

View File

@ -756,8 +756,10 @@
POWERPC_DEF("970_v2.2", CPU_POWERPC_970_v22, 970, POWERPC_DEF("970_v2.2", CPU_POWERPC_970_v22, 970,
"PowerPC 970 v2.2") "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") "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_DEF("970fx_v1.0", CPU_POWERPC_970FX_v10, 970,
"PowerPC 970FX v1.0 (G5)") "PowerPC 970FX v1.0 (G5)")
@ -945,7 +947,7 @@ PowerPCCPUAlias ppc_cpu_aliases[] = {
{ "power8e", "power8e_v2.1" }, { "power8e", "power8e_v2.1" },
{ "power8", "power8_v2.0" }, { "power8", "power8_v2.0" },
{ "power8nvl", "power8nvl_v1.0" }, { "power8nvl", "power8nvl_v1.0" },
{ "power9", "power9_v1.0" }, { "power9", "power9_v2.0" },
{ "970", "970_v2.2" }, { "970", "970_v2.2" },
{ "970fx", "970fx_v3.1" }, { "970fx", "970fx_v3.1" },
{ "970mp", "970mp_v1.1" }, { "970mp", "970mp_v1.1" },

View File

@ -372,6 +372,7 @@ enum {
CPU_POWERPC_POWER8NVL_v10 = 0x004C0100, CPU_POWERPC_POWER8NVL_v10 = 0x004C0100,
CPU_POWERPC_POWER9_BASE = 0x004E0000, CPU_POWERPC_POWER9_BASE = 0x004E0000,
CPU_POWERPC_POWER9_DD1 = 0x004E0100, CPU_POWERPC_POWER9_DD1 = 0x004E0100,
CPU_POWERPC_POWER9_DD20 = 0x004E1200,
CPU_POWERPC_970_v22 = 0x00390202, CPU_POWERPC_970_v22 = 0x00390202,
CPU_POWERPC_970FX_v10 = 0x00391100, CPU_POWERPC_970FX_v10 = 0x00391100,
CPU_POWERPC_970FX_v20 = 0x003C0200, CPU_POWERPC_970FX_v20 = 0x003C0200,

View File

@ -181,6 +181,7 @@ typedef struct PowerPCCPUClass {
DeviceRealize parent_realize; DeviceRealize parent_realize;
DeviceUnrealize parent_unrealize; DeviceUnrealize parent_unrealize;
void (*parent_reset)(CPUState *cpu); void (*parent_reset)(CPUState *cpu);
void (*parent_parse_features)(const char *type, char *str, Error **errp);
uint32_t pvr; uint32_t pvr;
bool (*pvr_match)(struct PowerPCCPUClass *pcc, uint32_t pvr); bool (*pvr_match)(struct PowerPCCPUClass *pcc, uint32_t pvr);

View File

@ -1278,7 +1278,6 @@ extern const struct VMStateDescription vmstate_ppc_cpu;
/*****************************************************************************/ /*****************************************************************************/
void ppc_translate_init(void); 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 /* you can call this signal handler from your SIGBUS and SIGSEGV
signal handlers to inform the virtual CPU of exceptions. non zero signal handlers to inform the virtual CPU of exceptions. non zero
is returned if the signal was handled by the virtual CPU. */ is returned if the signal was handled by the virtual CPU. */

View File

@ -219,17 +219,17 @@ target_ulong helper_sraw(CPUPPCState *env, target_ulong value,
shift &= 0x1f; shift &= 0x1f;
ret = (int32_t)value >> shift; ret = (int32_t)value >> shift;
if (likely(ret >= 0 || (value & ((1 << shift) - 1)) == 0)) { if (likely(ret >= 0 || (value & ((1 << shift) - 1)) == 0)) {
env->ca = 0; env->ca32 = env->ca = 0;
} else { } else {
env->ca = 1; env->ca32 = env->ca = 1;
} }
} else { } else {
ret = (int32_t)value; ret = (int32_t)value;
env->ca = 0; env->ca32 = env->ca = 0;
} }
} else { } else {
ret = (int32_t)value >> 31; ret = (int32_t)value >> 31;
env->ca = (ret != 0); env->ca32 = env->ca = (ret != 0);
} }
return (target_long)ret; return (target_long)ret;
} }
@ -245,17 +245,17 @@ target_ulong helper_srad(CPUPPCState *env, target_ulong value,
shift &= 0x3f; shift &= 0x3f;
ret = (int64_t)value >> shift; ret = (int64_t)value >> shift;
if (likely(ret >= 0 || (value & ((1ULL << shift) - 1)) == 0)) { if (likely(ret >= 0 || (value & ((1ULL << shift) - 1)) == 0)) {
env->ca = 0; env->ca32 = env->ca = 0;
} else { } else {
env->ca = 1; env->ca32 = env->ca = 1;
} }
} else { } else {
ret = (int64_t)value; ret = (int64_t)value;
env->ca = 0; env->ca32 = env->ca = 0;
} }
} else { } else {
ret = (int64_t)value >> 63; ret = (int64_t)value >> 63;
env->ca = (ret != 0); env->ca32 = env->ca = (ret != 0);
} }
return ret; return ret;
} }

View File

@ -123,7 +123,7 @@ static bool kvmppc_is_pr(KVMState *ks)
return kvm_vm_check_extension(ks, KVM_CAP_PPC_GET_PVINFO) != 0; 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) 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"); "VM to stall at times!\n");
} }
kvm_ppc_register_host_cpu_type(); kvm_ppc_register_host_cpu_type(ms);
return 0; return 0;
} }
@ -2487,12 +2487,13 @@ PowerPCCPUClass *kvm_ppc_get_host_cpu_class(void)
return pvr_pcc; 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 = { TypeInfo type_info = {
.name = TYPE_HOST_POWERPC_CPU, .name = TYPE_HOST_POWERPC_CPU,
.class_init = kvmppc_host_cpu_class_init, .class_init = kvmppc_host_cpu_class_init,
}; };
MachineClass *mc = MACHINE_GET_CLASS(ms);
PowerPCCPUClass *pvr_pcc; PowerPCCPUClass *pvr_pcc;
ObjectClass *oc; ObjectClass *oc;
DeviceClass *dc; 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_info.parent = object_class_get_name(OBJECT_CLASS(pvr_pcc));
type_register(&type_info); 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); oc = object_class_by_name(type_info.name);
g_assert(oc); 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, * 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 * we want "POWER8" to be a "family" alias that points to the current

View File

@ -2181,6 +2181,9 @@ static void gen_srawi(DisasContext *ctx)
if (sh == 0) { if (sh == 0) {
tcg_gen_ext32s_tl(dst, src); tcg_gen_ext32s_tl(dst, src);
tcg_gen_movi_tl(cpu_ca, 0); tcg_gen_movi_tl(cpu_ca, 0);
if (is_isa300(ctx)) {
tcg_gen_movi_tl(cpu_ca32, 0);
}
} else { } else {
TCGv t0; TCGv t0;
tcg_gen_ext32s_tl(dst, src); 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_gen_and_tl(cpu_ca, cpu_ca, t0);
tcg_temp_free(t0); tcg_temp_free(t0);
tcg_gen_setcondi_tl(TCG_COND_NE, cpu_ca, cpu_ca, 0); 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); tcg_gen_sari_tl(dst, dst, sh);
} }
if (unlikely(Rc(ctx->opcode) != 0)) { if (unlikely(Rc(ctx->opcode) != 0)) {
@ -2259,6 +2265,9 @@ static inline void gen_sradi(DisasContext *ctx, int n)
if (sh == 0) { if (sh == 0) {
tcg_gen_mov_tl(dst, src); tcg_gen_mov_tl(dst, src);
tcg_gen_movi_tl(cpu_ca, 0); tcg_gen_movi_tl(cpu_ca, 0);
if (is_isa300(ctx)) {
tcg_gen_movi_tl(cpu_ca32, 0);
}
} else { } else {
TCGv t0; TCGv t0;
tcg_gen_andi_tl(cpu_ca, src, (1ULL << sh) - 1); 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_gen_and_tl(cpu_ca, cpu_ca, t0);
tcg_temp_free(t0); tcg_temp_free(t0);
tcg_gen_setcondi_tl(TCG_COND_NE, cpu_ca, cpu_ca, 0); 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); tcg_gen_sari_tl(dst, src, sh);
} }
if (unlikely(Rc(ctx->opcode) != 0)) { if (unlikely(Rc(ctx->opcode) != 0)) {

View File

@ -4176,223 +4176,6 @@ POWERPC_FAMILY(440x5wDFPU)(ObjectClass *oc, void *data)
POWERPC_FLAG_DE | POWERPC_FLAG_BUS_CLK; 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) static void init_proc_MPC5xx(CPUPPCState *env)
{ {
/* Time base */ /* Time base */
@ -10277,6 +10060,19 @@ PowerPCCPUClass *ppc_cpu_class_by_pvr_mask(uint32_t pvr)
return pcc; 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) static ObjectClass *ppc_cpu_class_by_name(const char *name)
{ {
char *cpu_model, *typename; char *cpu_model, *typename;
@ -10314,17 +10110,59 @@ static ObjectClass *ppc_cpu_class_by_name(const char *name)
return NULL; 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 (!features) {
if (strcmp(ppc_cpu_aliases[ai].alias, alias) == 0) { return;
return ppc_cpu_aliases[ai].model; }
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) 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->reset = ppc_cpu_reset;
cc->class_by_name = ppc_cpu_class_by_name; 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->has_work = ppc_cpu_has_work;
cc->do_interrupt = ppc_cpu_do_interrupt; cc->do_interrupt = ppc_cpu_do_interrupt;
cc->cpu_exec_interrupt = ppc_cpu_exec_interrupt; cc->cpu_exec_interrupt = ppc_cpu_exec_interrupt;