diff options
author | Cédric Le Goater <clg@kaod.org> | 2019-12-05 19:44:51 +0100 |
---|---|---|
committer | David Gibson <david@gibson.dropbear.id.au> | 2019-12-17 10:39:48 +1100 |
commit | 2b548a4255ca07cf4d467b7fb3bdf2ab79b7dff5 (patch) | |
tree | cfb8f185a3887bb832f734af3a903c514491fd63 /hw/ppc | |
parent | 7d37b274ffd382d1d9e46164eca557b5f87383aa (diff) |
ppc/pnv: Introduce a POWER10 PnvChip and a powernv10 machine
This is an empty shell with the XSCOM bus and cores. The chip controllers
will come later.
Signed-off-by: Cédric Le Goater <clg@kaod.org>
Message-Id: <20191205184454.10722-3-clg@kaod.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Diffstat (limited to 'hw/ppc')
-rw-r--r-- | hw/ppc/pnv.c | 158 | ||||
-rw-r--r-- | hw/ppc/pnv_core.c | 10 | ||||
-rw-r--r-- | hw/ppc/pnv_xscom.c | 23 |
3 files changed, 180 insertions, 11 deletions
diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index fa656858b2..d99cd72840 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -317,6 +317,23 @@ static void pnv_chip_power9_dt_populate(PnvChip *chip, void *fdt) pnv_dt_lpc(chip, fdt, 0); } +static void pnv_chip_power10_dt_populate(PnvChip *chip, void *fdt) +{ + int i; + + pnv_dt_xscom(chip, fdt, 0); + + for (i = 0; i < chip->nr_cores; i++) { + PnvCore *pnv_core = chip->cores[i]; + + pnv_dt_core(chip, pnv_core, fdt); + } + + if (chip->ram_size) { + pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size); + } +} + static void pnv_dt_rtc(ISADevice *d, void *fdt, int lpc_off) { uint32_t io_base = d->ioport_id; @@ -467,6 +484,7 @@ static void *pnv_dt_create(MachineState *machine) { const char plat_compat8[] = "qemu,powernv8\0qemu,powernv\0ibm,powernv"; const char plat_compat9[] = "qemu,powernv9\0ibm,powernv"; + const char plat_compat10[] = "qemu,powernv10\0ibm,powernv"; PnvMachineState *pnv = PNV_MACHINE(machine); void *fdt; char *buf; @@ -484,7 +502,10 @@ static void *pnv_dt_create(MachineState *machine) _FDT((fdt_setprop_cell(fdt, 0, "#size-cells", 0x2))); _FDT((fdt_setprop_string(fdt, 0, "model", "IBM PowerNV (emulated by qemu)"))); - if (pnv_is_power9(pnv)) { + if (pnv_is_power10(pnv)) { + _FDT((fdt_setprop(fdt, 0, "compatible", plat_compat10, + sizeof(plat_compat10)))); + } else if (pnv_is_power9(pnv)) { _FDT((fdt_setprop(fdt, 0, "compatible", plat_compat9, sizeof(plat_compat9)))); } else { @@ -528,8 +549,8 @@ static void *pnv_dt_create(MachineState *machine) pnv_dt_bmc_sensors(pnv->bmc, fdt); } - /* Create an extra node for power management on Power9 */ - if (pnv_is_power9(pnv)) { + /* Create an extra node for power management on Power9 and Power10 */ + if (pnv_is_power9(pnv) || pnv_is_power10(pnv)) { pnv_dt_power_mgt(fdt); } @@ -578,6 +599,12 @@ static ISABus *pnv_chip_power9_isa_create(PnvChip *chip, Error **errp) return pnv_lpc_isa_create(&chip9->lpc, false, errp); } +static ISABus *pnv_chip_power10_isa_create(PnvChip *chip, Error **errp) +{ + error_setg(errp, "No ISA bus!"); + return NULL; +} + static ISABus *pnv_isa_create(PnvChip *chip, Error **errp) { return PNV_CHIP_GET_CLASS(chip)->isa_create(chip, errp); @@ -618,6 +645,13 @@ static void pnv_ipmi_bt_init(ISABus *bus, IPMIBmc *bmc, uint32_t irq) object_property_set_bool(obj, true, "realized", &error_fatal); } +static void pnv_chip_power10_pic_print_info(PnvChip *chip, Monitor *mon) +{ + /* + * No interrupt controller yet + */; +} + static void pnv_init(MachineState *machine) { PnvMachineState *pnv = PNV_MACHINE(machine); @@ -822,6 +856,11 @@ static uint32_t pnv_chip_core_pir_p9(PnvChip *chip, uint32_t core_id) return (chip->chip_id << 8) | (core_id << 2); } +static uint32_t pnv_chip_core_pir_p10(PnvChip *chip, uint32_t core_id) +{ + return (chip->chip_id << 8) | (core_id << 2); +} + static void pnv_chip_power9_intc_create(PnvChip *chip, PowerPCCPU *cpu, Error **errp) { @@ -859,6 +898,27 @@ static void pnv_chip_power9_intc_destroy(PnvChip *chip, PowerPCCPU *cpu) pnv_cpu->intc = NULL; } +static void pnv_chip_power10_intc_create(PnvChip *chip, PowerPCCPU *cpu, + Error **errp) +{ + PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); + + /* Will be defined when the interrupt controller is */ + pnv_cpu->intc = NULL; +} + +static void pnv_chip_power10_intc_reset(PnvChip *chip, PowerPCCPU *cpu) +{ + ; +} + +static void pnv_chip_power10_intc_destroy(PnvChip *chip, PowerPCCPU *cpu) +{ + PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); + + pnv_cpu->intc = NULL; +} + /* * Allowed core identifiers on a POWER8 Processor Chip : * @@ -886,6 +946,9 @@ static void pnv_chip_power9_intc_destroy(PnvChip *chip, PowerPCCPU *cpu) */ #define POWER9_CORE_MASK (0xffffffffffffffull) + +#define POWER10_CORE_MASK (0xffffffffffffffull) + static void pnv_chip_power8_instance_init(Object *obj) { Pnv8Chip *chip8 = PNV8_CHIP(obj); @@ -1246,6 +1309,56 @@ static void pnv_chip_power9_class_init(ObjectClass *klass, void *data) &k->parent_realize); } +static void pnv_chip_power10_instance_init(Object *obj) +{ + /* + * No controllers yet + */ + ; +} + +static void pnv_chip_power10_realize(DeviceState *dev, Error **errp) +{ + PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev); + PnvChip *chip = PNV_CHIP(dev); + Error *local_err = NULL; + + /* XSCOM bridge is first */ + pnv_xscom_realize(chip, PNV10_XSCOM_SIZE, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV10_XSCOM_BASE(chip)); + + pcc->parent_realize(dev, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } +} + +static void pnv_chip_power10_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + PnvChipClass *k = PNV_CHIP_CLASS(klass); + + k->chip_type = PNV_CHIP_POWER10; + k->chip_cfam_id = 0x120da04900008000ull; /* P10 DD1.0 (with NX) */ + k->cores_mask = POWER10_CORE_MASK; + k->core_pir = pnv_chip_core_pir_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->isa_create = pnv_chip_power10_isa_create; + k->dt_populate = pnv_chip_power10_dt_populate; + k->pic_print_info = pnv_chip_power10_pic_print_info; + dc->desc = "PowerNV Chip POWER10"; + + device_class_set_parent_realize(dc, pnv_chip_power10_realize, + &k->parent_realize); +} + static void pnv_chip_core_sanitize(PnvChip *chip, Error **errp) { PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); @@ -1327,10 +1440,12 @@ static void pnv_chip_core_realize(PnvChip *chip, Error **errp) &error_fatal); /* Each core has an XSCOM MMIO region */ - if (!pnv_chip_is_power9(chip)) { - xscom_core_base = PNV_XSCOM_EX_BASE(core_hwid); - } else { + if (pnv_chip_is_power10(chip)) { + xscom_core_base = PNV10_XSCOM_EC_BASE(core_hwid); + } else if (pnv_chip_is_power9(chip)) { xscom_core_base = PNV9_XSCOM_EC_BASE(core_hwid); + } else { + xscom_core_base = PNV_XSCOM_EX_BASE(core_hwid); } pnv_xscom_add_subregion(chip, xscom_core_base, @@ -1558,6 +1673,14 @@ static void pnv_machine_power9_class_init(ObjectClass *oc, void *data) mc->alias = "powernv"; } +static void pnv_machine_power10_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + + mc->desc = "IBM PowerNV (Non-Virtualized) POWER10"; + mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power10_v1.0"); +} + static void pnv_machine_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); @@ -1595,8 +1718,20 @@ static void pnv_machine_class_init(ObjectClass *oc, void *data) .parent = TYPE_PNV9_CHIP, \ } +#define DEFINE_PNV10_CHIP_TYPE(type, class_initfn) \ + { \ + .name = type, \ + .class_init = class_initfn, \ + .parent = TYPE_PNV10_CHIP, \ + } + static const TypeInfo types[] = { { + .name = MACHINE_TYPE_NAME("powernv10"), + .parent = TYPE_PNV_MACHINE, + .class_init = pnv_machine_power10_class_init, + }, + { .name = MACHINE_TYPE_NAME("powernv9"), .parent = TYPE_PNV_MACHINE, .class_init = pnv_machine_power9_class_init, @@ -1636,6 +1771,17 @@ static const TypeInfo types[] = { }, /* + * P10 chip and variants + */ + { + .name = TYPE_PNV10_CHIP, + .parent = TYPE_PNV_CHIP, + .instance_init = pnv_chip_power10_instance_init, + .instance_size = sizeof(Pnv10Chip), + }, + DEFINE_PNV10_CHIP_TYPE(TYPE_PNV_CHIP_POWER10, pnv_chip_power10_class_init), + + /* * P9 chip and variants */ { diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c index 5ab75bde6c..2651044278 100644 --- a/hw/ppc/pnv_core.c +++ b/hw/ppc/pnv_core.c @@ -247,6 +247,7 @@ static void pnv_core_realize(DeviceState *dev, Error **errp) } snprintf(name, sizeof(name), "xscom-core.%d", cc->core_id); + /* TODO: check PNV_XSCOM_EX_SIZE for p10 */ pnv_xscom_region_init(&pc->xscom_regs, OBJECT(dev), pcc->xscom_ops, pc, name, PNV_XSCOM_EX_SIZE); @@ -308,6 +309,14 @@ static void pnv_core_power9_class_init(ObjectClass *oc, void *data) pcc->xscom_ops = &pnv_core_power9_xscom_ops; } +static void pnv_core_power10_class_init(ObjectClass *oc, void *data) +{ + PnvCoreClass *pcc = PNV_CORE_CLASS(oc); + + /* TODO: Use the P9 XSCOMs for now on P10 */ + pcc->xscom_ops = &pnv_core_power9_xscom_ops; +} + static void pnv_core_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); @@ -337,6 +346,7 @@ static const TypeInfo pnv_core_infos[] = { DEFINE_PNV_CORE_TYPE(power8, "power8_v2.0"), DEFINE_PNV_CORE_TYPE(power8, "power8nvl_v1.0"), DEFINE_PNV_CORE_TYPE(power9, "power9_v2.0"), + DEFINE_PNV_CORE_TYPE(power10, "power10_v1.0"), }; DEFINE_TYPES(pnv_core_infos) diff --git a/hw/ppc/pnv_xscom.c b/hw/ppc/pnv_xscom.c index f01d788a65..b3d3b6e350 100644 --- a/hw/ppc/pnv_xscom.c +++ b/hw/ppc/pnv_xscom.c @@ -69,10 +69,16 @@ static uint32_t pnv_xscom_pcba(PnvChip *chip, uint64_t addr) { addr &= (PNV_XSCOM_SIZE - 1); - if (pnv_chip_is_power9(chip)) { - return addr >> 3; - } else { + switch (PNV_CHIP_GET_CLASS(chip)->chip_type) { + case PNV_CHIP_POWER8E: + case PNV_CHIP_POWER8: + case PNV_CHIP_POWER8NVL: return ((addr >> 4) & ~0xfull) | ((addr >> 3) & 0xf); + case PNV_CHIP_POWER9: + case PNV_CHIP_POWER10: + return addr >> 3; + default: + g_assert_not_reached(); } } @@ -307,6 +313,7 @@ static int xscom_dt_child(Object *child, void *opaque) static const char compat_p8[] = "ibm,power8-xscom\0ibm,xscom"; static const char compat_p9[] = "ibm,power9-xscom\0ibm,xscom"; +static const char compat_p10[] = "ibm,power10-xscom\0ibm,xscom"; int pnv_dt_xscom(PnvChip *chip, void *fdt, int root_offset) { @@ -315,7 +322,10 @@ int pnv_dt_xscom(PnvChip *chip, void *fdt, int root_offset) ForeachPopulateArgs args; char *name; - if (pnv_chip_is_power9(chip)) { + if (pnv_chip_is_power10(chip)) { + reg[0] = cpu_to_be64(PNV10_XSCOM_BASE(chip)); + reg[1] = cpu_to_be64(PNV10_XSCOM_SIZE); + } else if (pnv_chip_is_power9(chip)) { reg[0] = cpu_to_be64(PNV9_XSCOM_BASE(chip)); reg[1] = cpu_to_be64(PNV9_XSCOM_SIZE); } else { @@ -332,7 +342,10 @@ int pnv_dt_xscom(PnvChip *chip, void *fdt, int root_offset) _FDT((fdt_setprop_cell(fdt, xscom_offset, "#size-cells", 1))); _FDT((fdt_setprop(fdt, xscom_offset, "reg", reg, sizeof(reg)))); - if (pnv_chip_is_power9(chip)) { + if (pnv_chip_is_power10(chip)) { + _FDT((fdt_setprop(fdt, xscom_offset, "compatible", compat_p10, + sizeof(compat_p10)))); + } else if (pnv_chip_is_power9(chip)) { _FDT((fdt_setprop(fdt, xscom_offset, "compatible", compat_p9, sizeof(compat_p9)))); } else { |