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:
commit
861cd431c9
@ -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()
|
||||
}
|
||||
};
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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 = {
|
||||
|
@ -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 = {
|
||||
|
@ -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)
|
||||
|
134
hw/ppc/pnv.c
134
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)
|
||||
|
@ -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)
|
||||
|
25
hw/ppc/ppc.c
25
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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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 */
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
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),
|
||||
#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,
|
||||
.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
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
type_init(spapr_cpu_core_register_types)
|
||||
DEFINE_TYPES(spapr_cpu_core_type_infos)
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
@ -788,6 +810,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.
|
||||
|
@ -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) {
|
||||
|
@ -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" },
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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. */
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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)) {
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user