Message ID | 20250308205141.3219333-8-adityag@linux.ibm.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | Power11 support for QEMU [PowerNV] | expand |
On 3/8/25 21:51, Aditya Gupta wrote: > Power11 core is same as Power10. Introduce a Power11 chip and machine, > with Power10 chip as parent of Power11 chip. > > Due to Power10 chip being declared as Power11 chip, all functions can > cast 'Pnv11Chip' as 'Pnv10Chip' thus allowing it to reuse Power10's > functionality, such as in PHB. Homer code > > PowerNV11 declares a separate class_init and instance_init to be able to > declare correct CFAM, and initialise Power11 specific child objects such > as Homer, OCC etc. Other functionalities will use the Power10's codepath > in Power11 for most cases. > > Cc: Cédric Le Goater <clg@kaod.org> > Cc: Frédéric Barrat <fbarrat@linux.ibm.com> > Cc: Mahesh J Salgaonkar <mahesh@linux.ibm.com> > Cc: Madhavan Srinivasan <maddy@linux.ibm.com> > Cc: Nicholas Piggin <npiggin@gmail.com> > Signed-off-by: Aditya Gupta <adityag@linux.ibm.com> > --- > docs/system/ppc/powernv.rst | 9 +- > hw/ppc/pnv.c | 177 +++++++++++++++++++++++++++++++++++- > hw/ppc/pnv_core.c | 11 +++ I would introduce the pnv_core changes in their own patch. > include/hw/ppc/pnv.h | 5 + > include/hw/ppc/pnv_chip.h | 7 ++ > include/hw/ppc/pnv_core.h | 1 + > 6 files changed, 201 insertions(+), 9 deletions(-) > > diff --git a/docs/system/ppc/powernv.rst b/docs/system/ppc/powernv.rst > index de7a807ac762..366da9bc371c 100644 > --- a/docs/system/ppc/powernv.rst > +++ b/docs/system/ppc/powernv.rst > @@ -1,5 +1,5 @@ > -PowerNV family boards (``powernv8``, ``powernv9``, ``powernv10``) > -================================================================== > +PowerNV family boards (``powernv8``, ``powernv9``, ``powernv10``, ``powernv11``) > +================================================================================ > > PowerNV (as Non-Virtualized) is the "bare metal" platform using the > OPAL firmware. It runs Linux on IBM and OpenPOWER systems and it can > @@ -15,11 +15,12 @@ beyond the scope of what QEMU addresses today. > Supported devices > ----------------- > > - * Multi processor support for POWER8, POWER8NVL and POWER9. > + * Multi processor support for POWER8, POWER8NVL, POWER9, Power10 and Power11. > * XSCOM, serial communication sideband bus to configure chiplets. > * Simple LPC Controller. > * Processor Service Interface (PSI) Controller. > - * Interrupt Controller, XICS (POWER8) and XIVE (POWER9) and XIVE2 (Power10). > + * Interrupt Controller, XICS (POWER8) and XIVE (POWER9) and XIVE2 (Power10 & > + Power11). > * POWER8 PHB3 PCIe Host bridge and POWER9 PHB4 PCIe Host bridge. > * Simple OCC is an on-chip micro-controller used for power management tasks. > * iBT device to handle BMC communication, with the internal BMC simulator > diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c > index 87607508c768..1c4dc4ed1764 100644 > --- a/hw/ppc/pnv.c > +++ b/hw/ppc/pnv.c > @@ -22,6 +22,7 @@ > #include "qemu/units.h" > #include "qemu/cutils.h" > #include "qapi/error.h" > +#include "qom/object.h" > #include "system/qtest.h" > #include "system/system.h" > #include "system/numa.h" > @@ -486,6 +487,33 @@ static void pnv_chip_power10_dt_populate(PnvChip *chip, void *fdt) > pnv_dt_lpc(chip, fdt, 0, PNV10_LPCM_BASE(chip), PNV10_LPCM_SIZE); > } > > +static void pnv_chip_power11_dt_populate(PnvChip *chip, void *fdt) > +{ > + static const char compat[] = "ibm,power11-xscom\0ibm,xscom"; > + int i; > + > + pnv_dt_xscom(chip, fdt, 0, > + cpu_to_be64(PNV10_XSCOM_BASE(chip)), > + cpu_to_be64(PNV10_XSCOM_SIZE), > + compat, sizeof(compat)); > + > + for (i = 0; i < chip->nr_cores; i++) { > + PnvCore *pnv_core = chip->cores[i]; > + int offset; > + > + offset = pnv_dt_core(chip, pnv_core, fdt); > + > + _FDT((fdt_setprop(fdt, offset, "ibm,pa-features", > + pa_features_31, sizeof(pa_features_31)))); > + } > + > + if (chip->ram_size) { > + pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size); > + } > + > + pnv_dt_lpc(chip, fdt, 0, PNV10_LPCM_BASE(chip), PNV10_LPCM_SIZE); > +} > + > static void pnv_dt_rtc(ISADevice *d, void *fdt, int lpc_off) > { > uint32_t io_base = d->ioport_id; > @@ -1435,6 +1463,8 @@ static void pnv_chip_power10_intc_print_info(PnvChip *chip, PowerPCCPU *cpu, > > #define POWER10_CORE_MASK (0xffffffffffffffull) > > +#define POWER11_CORE_MASK (0xffffffffffffffull) > + > static void pnv_chip_power8_instance_init(Object *obj) > { > Pnv8Chip *chip8 = PNV8_CHIP(obj); > @@ -1966,6 +1996,20 @@ static void pnv_chip_power10_instance_init(Object *obj) > PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj); > int i; > > + /* > + * Power11 declares Power10 as it's parent class, to be able to reuse > + * most of the Power10 code. > + * But this causes Power10 and Power11's both instance init to be > + * called for PowerNV11 chip > + * > + * Skip initialising Power10 specific child objects, if the chip is > + * Power11 chip, in which case power11's instance init will initialise > + * the child objects > + */ > + if (!strcmp(object_get_typename(obj), TYPE_PNV_CHIP_POWER11)) { > + return; > + } > + This is a hack ! Please duplicate the code like done for other chips. > object_initialize_child(obj, "adu", &chip10->adu, TYPE_PNV_ADU); > object_initialize_child(obj, "xive", &chip10->xive, TYPE_PNV_XIVE2); > object_property_add_alias(obj, "xive-fabric", OBJECT(&chip10->xive), > @@ -1997,7 +2041,8 @@ static void pnv_chip_power10_instance_init(Object *obj) > } > } > > -static void pnv_chip_power10_quad_realize(Pnv10Chip *chip10, Error **errp) > +static void pnv_chip_power10_quad_realize(Pnv10Chip *chip10, Error **errp, > + const char *cpu_model) this belongs to another patch modifying P10 first. > { > PnvChip *chip = PNV_CHIP(chip10); > int i; > @@ -2007,9 +2052,10 @@ static void pnv_chip_power10_quad_realize(Pnv10Chip *chip10, Error **errp) > > for (i = 0; i < chip10->nr_quads; i++) { > PnvQuad *eq = &chip10->quads[i]; > + g_autofree char *type_name = PNV_QUAD_TYPE_NAME_DYN(cpu_model); > > pnv_chip_quad_realize_one(chip, eq, chip->cores[i * 4], > - PNV_QUAD_TYPE_NAME("power10")); > + type_name); > > pnv_xscom_add_subregion(chip, PNV10_XSCOM_EQ_BASE(eq->quad_id), > &eq->xscom_regs); > @@ -2047,7 +2093,8 @@ static void pnv_chip_power10_phb_realize(PnvChip *chip, Error **errp) > } > } > > -static void pnv_chip_power10_realize(DeviceState *dev, Error **errp) > +static void pnv_chip_power10_common_realize(DeviceState *dev, Error **errp, > + const char *cpu_model) this belongs to another patch modifying P10 first. > { > PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev); > PnvChip *chip = PNV_CHIP(dev); > @@ -2073,7 +2120,7 @@ static void pnv_chip_power10_realize(DeviceState *dev, Error **errp) > pnv_xscom_add_subregion(chip, PNV10_XSCOM_ADU_BASE, > &chip10->adu.xscom_regs); > > - pnv_chip_power10_quad_realize(chip10, &local_err); > + pnv_chip_power10_quad_realize(chip10, &local_err, cpu_model); > if (local_err) { > error_propagate(errp, local_err); > return; > @@ -2235,6 +2282,54 @@ static void pnv_chip_power10_realize(DeviceState *dev, Error **errp) > } > } > > +static void pnv_chip_power10_realize(DeviceState *dev, Error **errp) > +{ > + pnv_chip_power10_common_realize(dev, errp, "power10"); > +} > + > +static void pnv_chip_power11_instance_init(Object *obj) > +{ > + PnvChip *chip = PNV_CHIP(obj); > + Pnv11Chip *chip11 = PNV11_CHIP(obj); > + PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj); > + int i; > + > + object_initialize_child(obj, "adu", &chip11->adu, TYPE_PNV_ADU); > + object_initialize_child(obj, "xive", &chip11->xive, TYPE_PNV_XIVE2); > + object_property_add_alias(obj, "xive-fabric", OBJECT(&chip11->xive), > + "xive-fabric"); > + object_initialize_child(obj, "psi", &chip11->psi, TYPE_PNV11_PSI); > + object_initialize_child(obj, "lpc", &chip11->lpc, TYPE_PNV11_LPC); > + object_initialize_child(obj, "chiptod", &chip11->chiptod, > + TYPE_PNV11_CHIPTOD); > + object_initialize_child(obj, "occ", &chip11->occ, TYPE_PNV11_OCC); > + object_initialize_child(obj, "sbe", &chip11->sbe, TYPE_PNV11_SBE); > + object_initialize_child(obj, "homer", &chip11->homer, TYPE_PNV11_HOMER); > + object_initialize_child(obj, "n1-chiplet", &chip11->n1_chiplet, > + TYPE_PNV_N1_CHIPLET); > + > + chip->num_pecs = pcc->num_pecs; > + > + for (i = 0; i < chip->num_pecs; i++) { > + object_initialize_child(obj, "pec[*]", &chip11->pecs[i], > + TYPE_PNV_PHB5_PEC); > + } > + > + for (i = 0; i < pcc->i2c_num_engines; i++) { > + object_initialize_child(obj, "i2c[*]", &chip11->i2c[i], TYPE_PNV_I2C); > + } > + > + for (i = 0; i < PNV10_CHIP_MAX_PIB_SPIC; i++) { > + object_initialize_child(obj, "pib_spic[*]", &chip11->pib_spic[i], > + TYPE_PNV_SPI); > + } > +} > + > +static void pnv_chip_power11_realize(DeviceState *dev, Error **errp) > +{ > + pnv_chip_power10_common_realize(dev, errp, "power11"); > +} > + > static void pnv_rainier_i2c_init(PnvMachineState *pnv) > { > int i; > @@ -2300,6 +2395,34 @@ static void pnv_chip_power10_class_init(ObjectClass *klass, void *data) > &k->parent_realize); > } > > +static void pnv_chip_power11_class_init(ObjectClass *klass, void *data) > +{ > + DeviceClass *dc = DEVICE_CLASS(klass); > + PnvChipClass *k = PNV_CHIP_CLASS(klass); > + > + static const int i2c_ports_per_engine[PNV10_CHIP_MAX_I2C] = {14, 14, 2, 16}; > + > + k->chip_cfam_id = 0x220da04980000000ull; /* P11 DD2.0 (with NX) */ > + k->cores_mask = POWER11_CORE_MASK; > + k->get_pir_tir = pnv_get_pir_tir_p10; > + k->intc_create = pnv_chip_power10_intc_create; > + k->intc_reset = pnv_chip_power10_intc_reset; > + k->intc_destroy = pnv_chip_power10_intc_destroy; > + k->intc_print_info = pnv_chip_power10_intc_print_info; > + k->isa_create = pnv_chip_power10_isa_create; > + k->dt_populate = pnv_chip_power11_dt_populate; > + k->pic_print_info = pnv_chip_power10_pic_print_info; > + k->xscom_core_base = pnv_chip_power10_xscom_core_base; > + k->xscom_pcba = pnv_chip_power10_xscom_pcba; > + dc->desc = "PowerNV Chip POWER11"; > + k->num_pecs = PNV10_CHIP_MAX_PEC; > + k->i2c_num_engines = PNV10_CHIP_MAX_I2C; > + k->i2c_ports_per_engine = i2c_ports_per_engine; > + > + device_class_set_parent_realize(dc, pnv_chip_power11_realize, > + &k->parent_realize); > +} > + > static void pnv_chip_core_sanitize(PnvMachineState *pnv, PnvChip *chip, > Error **errp) > { > @@ -2757,7 +2880,6 @@ static void pnv_machine_p10_common_class_init(ObjectClass *oc, void *data) > { TYPE_PNV_PHB_ROOT_PORT, "version", "5" }, > }; > > - mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power10_v2.0"); This belongs to another patch. > compat_props_add(mc->compat_props, phb_compat, G_N_ELEMENTS(phb_compat)); > > mc->alias = "powernv"; > @@ -2780,6 +2902,7 @@ static void pnv_machine_power10_class_init(ObjectClass *oc, void *data) > > pnv_machine_p10_common_class_init(oc, data); > mc->desc = "IBM PowerNV (Non-Virtualized) POWER10"; > + mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power10_v2.0"); ditto > > /* > * This is the parent of POWER10 Rainier class, so properies go here > @@ -2806,9 +2929,26 @@ static void pnv_machine_p10_rainier_class_init(ObjectClass *oc, void *data) > > pnv_machine_p10_common_class_init(oc, data); > mc->desc = "IBM PowerNV (Non-Virtualized) POWER10 Rainier"; > + mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power10_v2.0"); ditto > pmc->i2c_init = pnv_rainier_i2c_init; > } > > +static void pnv_machine_power11_class_init(ObjectClass *oc, void *data) > +{ > + MachineClass *mc = MACHINE_CLASS(oc); > + PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc); > + static const char compat[] = "qemu,powernv11\0ibm,powernv"; > + > + /* do power10_class_init as p11 core is same as p10 */ > + pnv_machine_p10_common_class_init(oc, data); > + > + mc->desc = "IBM PowerNV (Non-Virtualized) POWER11"; > + mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power11_v2.0"); > + > + pmc->compat = compat; > + pmc->compat_size = sizeof(compat); > +} > + > static void pnv_cpu_do_nmi_on_cpu(CPUState *cs, run_on_cpu_data arg) > { > CPUPPCState *env = cpu_env(cs); > @@ -2914,7 +3054,23 @@ static void pnv_machine_class_init(ObjectClass *oc, void *data) > .parent = TYPE_PNV10_CHIP, \ > } > > +#define DEFINE_PNV11_CHIP_TYPE(type, class_initfn) \ > + { \ > + .name = type, \ > + .class_init = class_initfn, \ > + .parent = TYPE_PNV11_CHIP, \ > + } > + > static const TypeInfo types[] = { > + { > + .name = MACHINE_TYPE_NAME("powernv11"), > + .parent = TYPE_PNV_MACHINE, > + .class_init = pnv_machine_power11_class_init, > + .interfaces = (InterfaceInfo[]) { > + { TYPE_XIVE_FABRIC }, > + { }, > + }, > + }, > { > .name = MACHINE_TYPE_NAME("powernv10-rainier"), > .parent = MACHINE_TYPE_NAME("powernv10"), > @@ -2969,6 +3125,17 @@ static const TypeInfo types[] = { > .abstract = true, > }, > > + /* > + * P11 chip and variants > + */ > + { > + .name = TYPE_PNV11_CHIP, > + .parent = TYPE_PNV10_CHIP, why is the parent not TYPE_PNV_CHIP like the other chips ? This is a hack which can be easily avoided with more work :) > + .instance_init = pnv_chip_power11_instance_init, > + .instance_size = sizeof(Pnv11Chip), > + }, > + DEFINE_PNV11_CHIP_TYPE(TYPE_PNV_CHIP_POWER11, pnv_chip_power11_class_init), > + > /* > * P10 chip and variants > */ > diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c > index 99d9644ee38e..12916b15aa3b 100644 > --- a/hw/ppc/pnv_core.c > +++ b/hw/ppc/pnv_core.c > @@ -469,6 +469,11 @@ static void pnv_core_power10_class_init(ObjectClass *oc, void *data) > pcc->xscom_size = PNV10_XSCOM_EC_SIZE; > } > > +static void pnv_core_power11_class_init(ObjectClass *oc, void *data) > +{ > + pnv_core_power10_class_init(oc, data); > +} > + > static void pnv_core_class_init(ObjectClass *oc, void *data) > { > DeviceClass *dc = DEVICE_CLASS(oc); > @@ -500,6 +505,7 @@ static const TypeInfo pnv_core_infos[] = { > DEFINE_PNV_CORE_TYPE(power8, "power8nvl_v1.0"), > DEFINE_PNV_CORE_TYPE(power9, "power9_v2.2"), > DEFINE_PNV_CORE_TYPE(power10, "power10_v2.0"), > + DEFINE_PNV_CORE_TYPE(power11, "power11_v2.0"), > }; > > DEFINE_TYPES(pnv_core_infos) > @@ -748,6 +754,11 @@ static const TypeInfo pnv_quad_infos[] = { > .name = PNV_QUAD_TYPE_NAME("power10"), > .class_init = pnv_quad_power10_class_init, > }, > + { > + .parent = PNV_QUAD_TYPE_NAME("power10"), why not TYPE_PNV_QUAD ? Thanks, C. > + .name = PNV_QUAD_TYPE_NAME("power11"), > + .class_init = pnv_quad_power10_class_init, > + }, > }; > > DEFINE_TYPES(pnv_quad_infos); > diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h > index fcb6699150c8..ac960aa0fda9 100644 > --- a/include/hw/ppc/pnv.h > +++ b/include/hw/ppc/pnv.h > @@ -33,6 +33,7 @@ typedef struct PnvChip PnvChip; > typedef struct Pnv8Chip Pnv8Chip; > typedef struct Pnv9Chip Pnv9Chip; > typedef struct Pnv10Chip Pnv10Chip; > +typedef struct Pnv10Chip Pnv11Chip; > > #define PNV_CHIP_TYPE_SUFFIX "-" TYPE_PNV_CHIP > #define PNV_CHIP_TYPE_NAME(cpu_model) cpu_model PNV_CHIP_TYPE_SUFFIX > @@ -57,6 +58,10 @@ DECLARE_INSTANCE_CHECKER(PnvChip, PNV_CHIP_POWER9, > DECLARE_INSTANCE_CHECKER(PnvChip, PNV_CHIP_POWER10, > TYPE_PNV_CHIP_POWER10) > > +#define TYPE_PNV_CHIP_POWER11 PNV_CHIP_TYPE_NAME("power11_v2.0") > +DECLARE_INSTANCE_CHECKER(PnvChip, PNV_CHIP_POWER11, > + TYPE_PNV_CHIP_POWER11) > + > PnvCore *pnv_chip_find_core(PnvChip *chip, uint32_t core_id); > PowerPCCPU *pnv_chip_find_cpu(PnvChip *chip, uint32_t pir); > > diff --git a/include/hw/ppc/pnv_chip.h b/include/hw/ppc/pnv_chip.h > index 24ce37a9c8e4..6bd930f8b439 100644 > --- a/include/hw/ppc/pnv_chip.h > +++ b/include/hw/ppc/pnv_chip.h > @@ -141,6 +141,13 @@ struct Pnv10Chip { > #define PNV10_PIR2CHIP(pir) (((pir) >> 8) & 0x7f) > #define PNV10_PIR2THREAD(pir) (((pir) & 0x7f)) > > +#define TYPE_PNV11_CHIP "pnv11-chip" > +DECLARE_INSTANCE_CHECKER(Pnv11Chip, PNV11_CHIP, > + TYPE_PNV11_CHIP) > + > +/* Power11 core is same as Power10 */ > +typedef struct Pnv10Chip Pnv11Chip; > + > struct PnvChipClass { > /*< private >*/ > SysBusDeviceClass parent_class; > diff --git a/include/hw/ppc/pnv_core.h b/include/hw/ppc/pnv_core.h > index d8afb4f95f92..febe940a9af5 100644 > --- a/include/hw/ppc/pnv_core.h > +++ b/include/hw/ppc/pnv_core.h > @@ -104,6 +104,7 @@ struct PnvQuadClass { > > #define PNV_QUAD_TYPE_SUFFIX "-" TYPE_PNV_QUAD > #define PNV_QUAD_TYPE_NAME(cpu_model) cpu_model PNV_QUAD_TYPE_SUFFIX > +#define PNV_QUAD_TYPE_NAME_DYN(cpu) g_strconcat(cpu, PNV_QUAD_TYPE_SUFFIX, NULL) > > OBJECT_DECLARE_TYPE(PnvQuad, PnvQuadClass, PNV_QUAD) >
Hi Cédric, Thanks for the reviews. On 09/03/25 19:38, Cédric Le Goater wrote: > On 3/8/25 21:51, Aditya Gupta wrote: >> >> <...snip...> >> >> docs/system/ppc/powernv.rst | 9 +- >> hw/ppc/pnv.c | 177 +++++++++++++++++++++++++++++++++++- >> hw/ppc/pnv_core.c | 11 +++ > > I would introduce the pnv_core changes in their own patch. Sure, will do that in v6. > >> include/hw/ppc/pnv.h | 5 + >> include/hw/ppc/pnv_chip.h | 7 ++ >> include/hw/ppc/pnv_core.h | 1 + >> 6 files changed, 201 insertions(+), 9 deletions(-) >> >> diff --git a/docs/system/ppc/powernv.rst b/docs/system/ppc/powernv.rst >> index de7a807ac762..366da9bc371c 100644 >> >> <...snip...> >> >> + /* >> + * Power11 declares Power10 as it's parent class, to be able to >> reuse >> + * most of the Power10 code. >> + * But this causes Power10 and Power11's both instance init to be >> + * called for PowerNV11 chip >> + * >> + * Skip initialising Power10 specific child objects, if the chip is >> + * Power11 chip, in which case power11's instance init will >> initialise >> + * the child objects >> + */ >> + if (!strcmp(object_get_typename(obj), TYPE_PNV_CHIP_POWER11)) { >> + return; >> + } >> + > > This is a hack ! Please duplicate the code like done for other chips. > Agreed it's hacky. Okay, I will duplicate the code. > >> object_initialize_child(obj, "adu", &chip10->adu, TYPE_PNV_ADU); >> object_initialize_child(obj, "xive", &chip10->xive, >> TYPE_PNV_XIVE2); >> object_property_add_alias(obj, "xive-fabric", >> OBJECT(&chip10->xive), >> @@ -1997,7 +2041,8 @@ static void >> pnv_chip_power10_instance_init(Object *obj) >> } >> } >> -static void pnv_chip_power10_quad_realize(Pnv10Chip *chip10, Error >> **errp) >> +static void pnv_chip_power10_quad_realize(Pnv10Chip *chip10, Error >> **errp, >> + const char *cpu_model) > > > this belongs to another patch modifying P10 first. > Okay, will put changes modifying p10 functions in diff patch. >> { >> PnvChip *chip = PNV_CHIP(chip10); >> int i; >> @@ -2007,9 +2052,10 @@ static void >> pnv_chip_power10_quad_realize(Pnv10Chip *chip10, Error **errp) >> for (i = 0; i < chip10->nr_quads; i++) { >> PnvQuad *eq = &chip10->quads[i]; >> + g_autofree char *type_name = PNV_QUAD_TYPE_NAME_DYN(cpu_model); >> pnv_chip_quad_realize_one(chip, eq, chip->cores[i * 4], >> - PNV_QUAD_TYPE_NAME("power10")); >> + type_name); >> pnv_xscom_add_subregion(chip, >> PNV10_XSCOM_EQ_BASE(eq->quad_id), >> &eq->xscom_regs); >> @@ -2047,7 +2093,8 @@ static void >> pnv_chip_power10_phb_realize(PnvChip *chip, Error **errp) >> } >> } >> -static void pnv_chip_power10_realize(DeviceState *dev, Error **errp) >> +static void pnv_chip_power10_common_realize(DeviceState *dev, Error >> **errp, >> + const char *cpu_model) > > this belongs to another patch modifying P10 first. Sure > >> <...snip...> >> >> @@ -2757,7 +2880,6 @@ static void >> pnv_machine_p10_common_class_init(ObjectClass *oc, void *data) >> { TYPE_PNV_PHB_ROOT_PORT, "version", "5" }, >> }; >> - mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power10_v2.0"); > > This belongs to another patch. > Sure, will move it another patch. >> compat_props_add(mc->compat_props, phb_compat, >> G_N_ELEMENTS(phb_compat)); >> mc->alias = "powernv"; >> @@ -2780,6 +2902,7 @@ static void >> pnv_machine_power10_class_init(ObjectClass *oc, void *data) >> pnv_machine_p10_common_class_init(oc, data); >> mc->desc = "IBM PowerNV (Non-Virtualized) POWER10"; >> + mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power10_v2.0"); > > ditto Sure >> /* >> * This is the parent of POWER10 Rainier class, so properies go >> here >> @@ -2806,9 +2929,26 @@ static void >> pnv_machine_p10_rainier_class_init(ObjectClass *oc, void *data) >> pnv_machine_p10_common_class_init(oc, data); >> mc->desc = "IBM PowerNV (Non-Virtualized) POWER10 Rainier"; >> + mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power10_v2.0"); > > ditto Okay will move to different patch > >> <...snip...> >> >> @@ -2969,6 +3125,17 @@ static const TypeInfo types[] = { >> .abstract = true, >> }, >> + /* >> + * P11 chip and variants >> + */ >> + { >> + .name = TYPE_PNV11_CHIP, >> + .parent = TYPE_PNV10_CHIP, > > why is the parent not TYPE_PNV_CHIP like the other chips ? > > This is a hack which can be easily avoided with more work :) I kept it that way so that for most things p11 could simply fall back to p10 functions. Many of these functions cast the chip object to PNV10_CHIP, and since QEMU allows casting to parent class, I made PNV10_CHIP the parent of PNV11_CHIP. Duplicating the code, or something allowing this cast the ways I think. Will duplicate. > >> + .instance_init = pnv_chip_power11_instance_init, >> + .instance_size = sizeof(Pnv11Chip), >> + }, >> + DEFINE_PNV11_CHIP_TYPE(TYPE_PNV_CHIP_POWER11, >> pnv_chip_power11_class_init), >> + >> /* >> * P10 chip and variants >> */ >> diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c >> index 99d9644ee38e..12916b15aa3b 100644 >> --- a/hw/ppc/pnv_core.c >> +++ b/hw/ppc/pnv_core.c >> @@ -469,6 +469,11 @@ static void >> pnv_core_power10_class_init(ObjectClass *oc, void *data) >> pcc->xscom_size = PNV10_XSCOM_EC_SIZE; >> } >> +static void pnv_core_power11_class_init(ObjectClass *oc, void *data) >> +{ >> + pnv_core_power10_class_init(oc, data); >> +} >> + >> static void pnv_core_class_init(ObjectClass *oc, void *data) >> { >> DeviceClass *dc = DEVICE_CLASS(oc); >> @@ -500,6 +505,7 @@ static const TypeInfo pnv_core_infos[] = { >> DEFINE_PNV_CORE_TYPE(power8, "power8nvl_v1.0"), >> DEFINE_PNV_CORE_TYPE(power9, "power9_v2.2"), >> DEFINE_PNV_CORE_TYPE(power10, "power10_v2.0"), >> + DEFINE_PNV_CORE_TYPE(power11, "power11_v2.0"), >> }; >> DEFINE_TYPES(pnv_core_infos) >> @@ -748,6 +754,11 @@ static const TypeInfo pnv_quad_infos[] = { >> .name = PNV_QUAD_TYPE_NAME("power10"), >> .class_init = pnv_quad_power10_class_init, >> }, >> + { >> + .parent = PNV_QUAD_TYPE_NAME("power10"), > > why not TYPE_PNV_QUAD ? > I wanted it to use Power10 quad's '_class_init' & '_realize'. Will make it's parent PNV_QUAD, and create separate class_init and realize for Power11 then. Thanks, - Aditya Gupta > > Thanks, > > C. >
Hi Cedric, On 09/03/25 19:38, Cédric Le Goater wrote: > On 3/8/25 21:51, Aditya Gupta wrote: >> <...snip...> >> >> static void pnv_chip_power8_instance_init(Object *obj) >> { >> Pnv8Chip *chip8 = PNV8_CHIP(obj); >> @@ -1966,6 +1996,20 @@ static void >> pnv_chip_power10_instance_init(Object *obj) >> PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj); >> int i; >> + /* >> + * Power11 declares Power10 as it's parent class, to be able to >> reuse >> + * most of the Power10 code. >> + * But this causes Power10 and Power11's both instance init to be >> + * called for PowerNV11 chip >> + * >> + * Skip initialising Power10 specific child objects, if the chip is >> + * Power11 chip, in which case power11's instance init will >> initialise >> + * the child objects >> + */ >> + if (!strcmp(object_get_typename(obj), TYPE_PNV_CHIP_POWER11)) { >> + return; >> + } >> + > > This is a hack ! Please duplicate the code like done for other chips. > > >> <...snip...> >> >> + /* >> + * P11 chip and variants >> + */ >> + { >> + .name = TYPE_PNV11_CHIP, >> + .parent = TYPE_PNV10_CHIP, > > why is the parent not TYPE_PNV_CHIP like the other chips ? > > This is a hack which can be easily avoided with more work :) When I do this, every function using Pnv10Chip* will need to be duplicated to use Pnv11Chip*. I will do that. But what do you say about changing Pnv10 chip to Pnv1x chip ? It may only be used by Pnv10 and Pnv11, not future chips. But is that unnecessary for just two versions of the chip ? Just tried to think of some ways to reduce duplication, or having different files such as pnv10.c, pnv11.c ? I am not sure because these might be unnecessary things too. Thanks, - Aditya G
On 3/24/25 08:13, Aditya Gupta wrote: > Hi Cedric, > > On 09/03/25 19:38, Cédric Le Goater wrote: >> On 3/8/25 21:51, Aditya Gupta wrote: >>> <...snip...> >>> >>> static void pnv_chip_power8_instance_init(Object *obj) >>> { >>> Pnv8Chip *chip8 = PNV8_CHIP(obj); >>> @@ -1966,6 +1996,20 @@ static void pnv_chip_power10_instance_init(Object *obj) >>> PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj); >>> int i; >>> + /* >>> + * Power11 declares Power10 as it's parent class, to be able to reuse >>> + * most of the Power10 code. >>> + * But this causes Power10 and Power11's both instance init to be >>> + * called for PowerNV11 chip >>> + * >>> + * Skip initialising Power10 specific child objects, if the chip is >>> + * Power11 chip, in which case power11's instance init will initialise >>> + * the child objects >>> + */ >>> + if (!strcmp(object_get_typename(obj), TYPE_PNV_CHIP_POWER11)) { >>> + return; >>> + } >>> + >> >> This is a hack ! Please duplicate the code like done for other chips. >> >> >>> <...snip...> >>> >>> + /* >>> + * P11 chip and variants >>> + */ >>> + { >>> + .name = TYPE_PNV11_CHIP, >>> + .parent = TYPE_PNV10_CHIP, >> >> why is the parent not TYPE_PNV_CHIP like the other chips ? >> >> This is a hack which can be easily avoided with more work :) > > > When I do this, every function using Pnv10Chip* will need to be duplicated to use Pnv11Chip*. > > I will do that. > > But what do you say about changing Pnv10 chip to Pnv1x chip ? It may only be used by Pnv10 and Pnv11, not future chips. But is that unnecessary for just two versions of the chip ? > > Just tried to think of some ways to reduce duplication, or having different files such as pnv10.c, pnv11.c ? I am not sure because these might be unnecessary things too. Please open code (and duplicate) first. Then we will see how we can make things common. Checking the typename in the instance_init handleris a hack not for upstream. Thanks, C.
On 24/03/25 13:05, Cédric Le Goater wrote: > On 3/24/25 08:13, Aditya Gupta wrote: >> Hi Cedric, >> >> <...snip...> >> >> When I do this, every function using Pnv10Chip* will need to be >> duplicated to use Pnv11Chip*. >> >> I will do that. >> >> But what do you say about changing Pnv10 chip to Pnv1x chip ? It may >> only be used by Pnv10 and Pnv11, not future chips. But is that >> unnecessary for just two versions of the chip ? >> >> Just tried to think of some ways to reduce duplication, or having >> different files such as pnv10.c, pnv11.c ? I am not sure because >> these might be unnecessary things too. > > Please open code (and duplicate) first. Then we will see how we > can make things common. Checking the typename in the instance_init > handleris a hack not for upstream. Sure Cedric, will duplicate it then. Thanks, - Aditya Gupta > > Thanks, > > C. > >
diff --git a/docs/system/ppc/powernv.rst b/docs/system/ppc/powernv.rst index de7a807ac762..366da9bc371c 100644 --- a/docs/system/ppc/powernv.rst +++ b/docs/system/ppc/powernv.rst @@ -1,5 +1,5 @@ -PowerNV family boards (``powernv8``, ``powernv9``, ``powernv10``) -================================================================== +PowerNV family boards (``powernv8``, ``powernv9``, ``powernv10``, ``powernv11``) +================================================================================ PowerNV (as Non-Virtualized) is the "bare metal" platform using the OPAL firmware. It runs Linux on IBM and OpenPOWER systems and it can @@ -15,11 +15,12 @@ beyond the scope of what QEMU addresses today. Supported devices ----------------- - * Multi processor support for POWER8, POWER8NVL and POWER9. + * Multi processor support for POWER8, POWER8NVL, POWER9, Power10 and Power11. * XSCOM, serial communication sideband bus to configure chiplets. * Simple LPC Controller. * Processor Service Interface (PSI) Controller. - * Interrupt Controller, XICS (POWER8) and XIVE (POWER9) and XIVE2 (Power10). + * Interrupt Controller, XICS (POWER8) and XIVE (POWER9) and XIVE2 (Power10 & + Power11). * POWER8 PHB3 PCIe Host bridge and POWER9 PHB4 PCIe Host bridge. * Simple OCC is an on-chip micro-controller used for power management tasks. * iBT device to handle BMC communication, with the internal BMC simulator diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index 87607508c768..1c4dc4ed1764 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -22,6 +22,7 @@ #include "qemu/units.h" #include "qemu/cutils.h" #include "qapi/error.h" +#include "qom/object.h" #include "system/qtest.h" #include "system/system.h" #include "system/numa.h" @@ -486,6 +487,33 @@ static void pnv_chip_power10_dt_populate(PnvChip *chip, void *fdt) pnv_dt_lpc(chip, fdt, 0, PNV10_LPCM_BASE(chip), PNV10_LPCM_SIZE); } +static void pnv_chip_power11_dt_populate(PnvChip *chip, void *fdt) +{ + static const char compat[] = "ibm,power11-xscom\0ibm,xscom"; + int i; + + pnv_dt_xscom(chip, fdt, 0, + cpu_to_be64(PNV10_XSCOM_BASE(chip)), + cpu_to_be64(PNV10_XSCOM_SIZE), + compat, sizeof(compat)); + + for (i = 0; i < chip->nr_cores; i++) { + PnvCore *pnv_core = chip->cores[i]; + int offset; + + offset = pnv_dt_core(chip, pnv_core, fdt); + + _FDT((fdt_setprop(fdt, offset, "ibm,pa-features", + pa_features_31, sizeof(pa_features_31)))); + } + + if (chip->ram_size) { + pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size); + } + + pnv_dt_lpc(chip, fdt, 0, PNV10_LPCM_BASE(chip), PNV10_LPCM_SIZE); +} + static void pnv_dt_rtc(ISADevice *d, void *fdt, int lpc_off) { uint32_t io_base = d->ioport_id; @@ -1435,6 +1463,8 @@ static void pnv_chip_power10_intc_print_info(PnvChip *chip, PowerPCCPU *cpu, #define POWER10_CORE_MASK (0xffffffffffffffull) +#define POWER11_CORE_MASK (0xffffffffffffffull) + static void pnv_chip_power8_instance_init(Object *obj) { Pnv8Chip *chip8 = PNV8_CHIP(obj); @@ -1966,6 +1996,20 @@ static void pnv_chip_power10_instance_init(Object *obj) PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj); int i; + /* + * Power11 declares Power10 as it's parent class, to be able to reuse + * most of the Power10 code. + * But this causes Power10 and Power11's both instance init to be + * called for PowerNV11 chip + * + * Skip initialising Power10 specific child objects, if the chip is + * Power11 chip, in which case power11's instance init will initialise + * the child objects + */ + if (!strcmp(object_get_typename(obj), TYPE_PNV_CHIP_POWER11)) { + return; + } + object_initialize_child(obj, "adu", &chip10->adu, TYPE_PNV_ADU); object_initialize_child(obj, "xive", &chip10->xive, TYPE_PNV_XIVE2); object_property_add_alias(obj, "xive-fabric", OBJECT(&chip10->xive), @@ -1997,7 +2041,8 @@ static void pnv_chip_power10_instance_init(Object *obj) } } -static void pnv_chip_power10_quad_realize(Pnv10Chip *chip10, Error **errp) +static void pnv_chip_power10_quad_realize(Pnv10Chip *chip10, Error **errp, + const char *cpu_model) { PnvChip *chip = PNV_CHIP(chip10); int i; @@ -2007,9 +2052,10 @@ static void pnv_chip_power10_quad_realize(Pnv10Chip *chip10, Error **errp) for (i = 0; i < chip10->nr_quads; i++) { PnvQuad *eq = &chip10->quads[i]; + g_autofree char *type_name = PNV_QUAD_TYPE_NAME_DYN(cpu_model); pnv_chip_quad_realize_one(chip, eq, chip->cores[i * 4], - PNV_QUAD_TYPE_NAME("power10")); + type_name); pnv_xscom_add_subregion(chip, PNV10_XSCOM_EQ_BASE(eq->quad_id), &eq->xscom_regs); @@ -2047,7 +2093,8 @@ static void pnv_chip_power10_phb_realize(PnvChip *chip, Error **errp) } } -static void pnv_chip_power10_realize(DeviceState *dev, Error **errp) +static void pnv_chip_power10_common_realize(DeviceState *dev, Error **errp, + const char *cpu_model) { PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev); PnvChip *chip = PNV_CHIP(dev); @@ -2073,7 +2120,7 @@ static void pnv_chip_power10_realize(DeviceState *dev, Error **errp) pnv_xscom_add_subregion(chip, PNV10_XSCOM_ADU_BASE, &chip10->adu.xscom_regs); - pnv_chip_power10_quad_realize(chip10, &local_err); + pnv_chip_power10_quad_realize(chip10, &local_err, cpu_model); if (local_err) { error_propagate(errp, local_err); return; @@ -2235,6 +2282,54 @@ static void pnv_chip_power10_realize(DeviceState *dev, Error **errp) } } +static void pnv_chip_power10_realize(DeviceState *dev, Error **errp) +{ + pnv_chip_power10_common_realize(dev, errp, "power10"); +} + +static void pnv_chip_power11_instance_init(Object *obj) +{ + PnvChip *chip = PNV_CHIP(obj); + Pnv11Chip *chip11 = PNV11_CHIP(obj); + PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj); + int i; + + object_initialize_child(obj, "adu", &chip11->adu, TYPE_PNV_ADU); + object_initialize_child(obj, "xive", &chip11->xive, TYPE_PNV_XIVE2); + object_property_add_alias(obj, "xive-fabric", OBJECT(&chip11->xive), + "xive-fabric"); + object_initialize_child(obj, "psi", &chip11->psi, TYPE_PNV11_PSI); + object_initialize_child(obj, "lpc", &chip11->lpc, TYPE_PNV11_LPC); + object_initialize_child(obj, "chiptod", &chip11->chiptod, + TYPE_PNV11_CHIPTOD); + object_initialize_child(obj, "occ", &chip11->occ, TYPE_PNV11_OCC); + object_initialize_child(obj, "sbe", &chip11->sbe, TYPE_PNV11_SBE); + object_initialize_child(obj, "homer", &chip11->homer, TYPE_PNV11_HOMER); + object_initialize_child(obj, "n1-chiplet", &chip11->n1_chiplet, + TYPE_PNV_N1_CHIPLET); + + chip->num_pecs = pcc->num_pecs; + + for (i = 0; i < chip->num_pecs; i++) { + object_initialize_child(obj, "pec[*]", &chip11->pecs[i], + TYPE_PNV_PHB5_PEC); + } + + for (i = 0; i < pcc->i2c_num_engines; i++) { + object_initialize_child(obj, "i2c[*]", &chip11->i2c[i], TYPE_PNV_I2C); + } + + for (i = 0; i < PNV10_CHIP_MAX_PIB_SPIC; i++) { + object_initialize_child(obj, "pib_spic[*]", &chip11->pib_spic[i], + TYPE_PNV_SPI); + } +} + +static void pnv_chip_power11_realize(DeviceState *dev, Error **errp) +{ + pnv_chip_power10_common_realize(dev, errp, "power11"); +} + static void pnv_rainier_i2c_init(PnvMachineState *pnv) { int i; @@ -2300,6 +2395,34 @@ static void pnv_chip_power10_class_init(ObjectClass *klass, void *data) &k->parent_realize); } +static void pnv_chip_power11_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + PnvChipClass *k = PNV_CHIP_CLASS(klass); + + static const int i2c_ports_per_engine[PNV10_CHIP_MAX_I2C] = {14, 14, 2, 16}; + + k->chip_cfam_id = 0x220da04980000000ull; /* P11 DD2.0 (with NX) */ + k->cores_mask = POWER11_CORE_MASK; + k->get_pir_tir = pnv_get_pir_tir_p10; + k->intc_create = pnv_chip_power10_intc_create; + k->intc_reset = pnv_chip_power10_intc_reset; + k->intc_destroy = pnv_chip_power10_intc_destroy; + k->intc_print_info = pnv_chip_power10_intc_print_info; + k->isa_create = pnv_chip_power10_isa_create; + k->dt_populate = pnv_chip_power11_dt_populate; + k->pic_print_info = pnv_chip_power10_pic_print_info; + k->xscom_core_base = pnv_chip_power10_xscom_core_base; + k->xscom_pcba = pnv_chip_power10_xscom_pcba; + dc->desc = "PowerNV Chip POWER11"; + k->num_pecs = PNV10_CHIP_MAX_PEC; + k->i2c_num_engines = PNV10_CHIP_MAX_I2C; + k->i2c_ports_per_engine = i2c_ports_per_engine; + + device_class_set_parent_realize(dc, pnv_chip_power11_realize, + &k->parent_realize); +} + static void pnv_chip_core_sanitize(PnvMachineState *pnv, PnvChip *chip, Error **errp) { @@ -2757,7 +2880,6 @@ static void pnv_machine_p10_common_class_init(ObjectClass *oc, void *data) { TYPE_PNV_PHB_ROOT_PORT, "version", "5" }, }; - mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power10_v2.0"); compat_props_add(mc->compat_props, phb_compat, G_N_ELEMENTS(phb_compat)); mc->alias = "powernv"; @@ -2780,6 +2902,7 @@ static void pnv_machine_power10_class_init(ObjectClass *oc, void *data) pnv_machine_p10_common_class_init(oc, data); mc->desc = "IBM PowerNV (Non-Virtualized) POWER10"; + mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power10_v2.0"); /* * This is the parent of POWER10 Rainier class, so properies go here @@ -2806,9 +2929,26 @@ static void pnv_machine_p10_rainier_class_init(ObjectClass *oc, void *data) pnv_machine_p10_common_class_init(oc, data); mc->desc = "IBM PowerNV (Non-Virtualized) POWER10 Rainier"; + mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power10_v2.0"); pmc->i2c_init = pnv_rainier_i2c_init; } +static void pnv_machine_power11_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc); + static const char compat[] = "qemu,powernv11\0ibm,powernv"; + + /* do power10_class_init as p11 core is same as p10 */ + pnv_machine_p10_common_class_init(oc, data); + + mc->desc = "IBM PowerNV (Non-Virtualized) POWER11"; + mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power11_v2.0"); + + pmc->compat = compat; + pmc->compat_size = sizeof(compat); +} + static void pnv_cpu_do_nmi_on_cpu(CPUState *cs, run_on_cpu_data arg) { CPUPPCState *env = cpu_env(cs); @@ -2914,7 +3054,23 @@ static void pnv_machine_class_init(ObjectClass *oc, void *data) .parent = TYPE_PNV10_CHIP, \ } +#define DEFINE_PNV11_CHIP_TYPE(type, class_initfn) \ + { \ + .name = type, \ + .class_init = class_initfn, \ + .parent = TYPE_PNV11_CHIP, \ + } + static const TypeInfo types[] = { + { + .name = MACHINE_TYPE_NAME("powernv11"), + .parent = TYPE_PNV_MACHINE, + .class_init = pnv_machine_power11_class_init, + .interfaces = (InterfaceInfo[]) { + { TYPE_XIVE_FABRIC }, + { }, + }, + }, { .name = MACHINE_TYPE_NAME("powernv10-rainier"), .parent = MACHINE_TYPE_NAME("powernv10"), @@ -2969,6 +3125,17 @@ static const TypeInfo types[] = { .abstract = true, }, + /* + * P11 chip and variants + */ + { + .name = TYPE_PNV11_CHIP, + .parent = TYPE_PNV10_CHIP, + .instance_init = pnv_chip_power11_instance_init, + .instance_size = sizeof(Pnv11Chip), + }, + DEFINE_PNV11_CHIP_TYPE(TYPE_PNV_CHIP_POWER11, pnv_chip_power11_class_init), + /* * P10 chip and variants */ diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c index 99d9644ee38e..12916b15aa3b 100644 --- a/hw/ppc/pnv_core.c +++ b/hw/ppc/pnv_core.c @@ -469,6 +469,11 @@ static void pnv_core_power10_class_init(ObjectClass *oc, void *data) pcc->xscom_size = PNV10_XSCOM_EC_SIZE; } +static void pnv_core_power11_class_init(ObjectClass *oc, void *data) +{ + pnv_core_power10_class_init(oc, data); +} + static void pnv_core_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); @@ -500,6 +505,7 @@ static const TypeInfo pnv_core_infos[] = { DEFINE_PNV_CORE_TYPE(power8, "power8nvl_v1.0"), DEFINE_PNV_CORE_TYPE(power9, "power9_v2.2"), DEFINE_PNV_CORE_TYPE(power10, "power10_v2.0"), + DEFINE_PNV_CORE_TYPE(power11, "power11_v2.0"), }; DEFINE_TYPES(pnv_core_infos) @@ -748,6 +754,11 @@ static const TypeInfo pnv_quad_infos[] = { .name = PNV_QUAD_TYPE_NAME("power10"), .class_init = pnv_quad_power10_class_init, }, + { + .parent = PNV_QUAD_TYPE_NAME("power10"), + .name = PNV_QUAD_TYPE_NAME("power11"), + .class_init = pnv_quad_power10_class_init, + }, }; DEFINE_TYPES(pnv_quad_infos); diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h index fcb6699150c8..ac960aa0fda9 100644 --- a/include/hw/ppc/pnv.h +++ b/include/hw/ppc/pnv.h @@ -33,6 +33,7 @@ typedef struct PnvChip PnvChip; typedef struct Pnv8Chip Pnv8Chip; typedef struct Pnv9Chip Pnv9Chip; typedef struct Pnv10Chip Pnv10Chip; +typedef struct Pnv10Chip Pnv11Chip; #define PNV_CHIP_TYPE_SUFFIX "-" TYPE_PNV_CHIP #define PNV_CHIP_TYPE_NAME(cpu_model) cpu_model PNV_CHIP_TYPE_SUFFIX @@ -57,6 +58,10 @@ DECLARE_INSTANCE_CHECKER(PnvChip, PNV_CHIP_POWER9, DECLARE_INSTANCE_CHECKER(PnvChip, PNV_CHIP_POWER10, TYPE_PNV_CHIP_POWER10) +#define TYPE_PNV_CHIP_POWER11 PNV_CHIP_TYPE_NAME("power11_v2.0") +DECLARE_INSTANCE_CHECKER(PnvChip, PNV_CHIP_POWER11, + TYPE_PNV_CHIP_POWER11) + PnvCore *pnv_chip_find_core(PnvChip *chip, uint32_t core_id); PowerPCCPU *pnv_chip_find_cpu(PnvChip *chip, uint32_t pir); diff --git a/include/hw/ppc/pnv_chip.h b/include/hw/ppc/pnv_chip.h index 24ce37a9c8e4..6bd930f8b439 100644 --- a/include/hw/ppc/pnv_chip.h +++ b/include/hw/ppc/pnv_chip.h @@ -141,6 +141,13 @@ struct Pnv10Chip { #define PNV10_PIR2CHIP(pir) (((pir) >> 8) & 0x7f) #define PNV10_PIR2THREAD(pir) (((pir) & 0x7f)) +#define TYPE_PNV11_CHIP "pnv11-chip" +DECLARE_INSTANCE_CHECKER(Pnv11Chip, PNV11_CHIP, + TYPE_PNV11_CHIP) + +/* Power11 core is same as Power10 */ +typedef struct Pnv10Chip Pnv11Chip; + struct PnvChipClass { /*< private >*/ SysBusDeviceClass parent_class; diff --git a/include/hw/ppc/pnv_core.h b/include/hw/ppc/pnv_core.h index d8afb4f95f92..febe940a9af5 100644 --- a/include/hw/ppc/pnv_core.h +++ b/include/hw/ppc/pnv_core.h @@ -104,6 +104,7 @@ struct PnvQuadClass { #define PNV_QUAD_TYPE_SUFFIX "-" TYPE_PNV_QUAD #define PNV_QUAD_TYPE_NAME(cpu_model) cpu_model PNV_QUAD_TYPE_SUFFIX +#define PNV_QUAD_TYPE_NAME_DYN(cpu) g_strconcat(cpu, PNV_QUAD_TYPE_SUFFIX, NULL) OBJECT_DECLARE_TYPE(PnvQuad, PnvQuadClass, PNV_QUAD)
Power11 core is same as Power10. Introduce a Power11 chip and machine, with Power10 chip as parent of Power11 chip. Due to Power10 chip being declared as Power11 chip, all functions can cast 'Pnv11Chip' as 'Pnv10Chip' thus allowing it to reuse Power10's functionality, such as in PHB. Homer code PowerNV11 declares a separate class_init and instance_init to be able to declare correct CFAM, and initialise Power11 specific child objects such as Homer, OCC etc. Other functionalities will use the Power10's codepath in Power11 for most cases. Cc: Cédric Le Goater <clg@kaod.org> Cc: Frédéric Barrat <fbarrat@linux.ibm.com> Cc: Mahesh J Salgaonkar <mahesh@linux.ibm.com> Cc: Madhavan Srinivasan <maddy@linux.ibm.com> Cc: Nicholas Piggin <npiggin@gmail.com> Signed-off-by: Aditya Gupta <adityag@linux.ibm.com> --- docs/system/ppc/powernv.rst | 9 +- hw/ppc/pnv.c | 177 +++++++++++++++++++++++++++++++++++- hw/ppc/pnv_core.c | 11 +++ include/hw/ppc/pnv.h | 5 + include/hw/ppc/pnv_chip.h | 7 ++ include/hw/ppc/pnv_core.h | 1 + 6 files changed, 201 insertions(+), 9 deletions(-)