aboutsummaryrefslogtreecommitdiff
path: root/hw/ppc
diff options
context:
space:
mode:
Diffstat (limited to 'hw/ppc')
-rw-r--r--hw/ppc/pnv.c227
-rw-r--r--hw/ppc/pnv_homer.c64
-rw-r--r--hw/ppc/pnv_occ.c16
-rw-r--r--hw/ppc/pnv_psi.c38
-rw-r--r--hw/ppc/spapr.c31
-rw-r--r--hw/ppc/spapr_caps.c22
-rw-r--r--hw/ppc/spapr_drc.c47
-rw-r--r--hw/ppc/spapr_numa.c16
-rw-r--r--hw/ppc/spapr_pci_nvlink2.c10
-rw-r--r--hw/ppc/spapr_rtas.c25
-rw-r--r--hw/ppc/spapr_vio.c6
11 files changed, 387 insertions, 115 deletions
diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index 837146a2fb..0ac86e104f 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -380,9 +380,12 @@ static void pnv_dt_serial(ISADevice *d, void *fdt, int lpc_off)
cpu_to_be32(io_base),
cpu_to_be32(8)
};
+ uint32_t irq;
char *name;
int node;
+ irq = object_property_get_uint(OBJECT(d), "irq", &error_fatal);
+
name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base);
node = fdt_add_subnode(fdt, lpc_off, name);
_FDT(node);
@@ -394,7 +397,7 @@ static void pnv_dt_serial(ISADevice *d, void *fdt, int lpc_off)
_FDT((fdt_setprop_cell(fdt, node, "clock-frequency", 1843200)));
_FDT((fdt_setprop_cell(fdt, node, "current-speed", 115200)));
- _FDT((fdt_setprop_cell(fdt, node, "interrupts", d->isairq[0])));
+ _FDT((fdt_setprop_cell(fdt, node, "interrupts", irq)));
_FDT((fdt_setprop_cell(fdt, node, "interrupt-parent",
fdt_get_phandle(fdt, lpc_off))));
@@ -722,7 +725,11 @@ static void pnv_chip_power10_pic_print_info(PnvChip *chip, Monitor *mon)
{
Pnv10Chip *chip10 = PNV10_CHIP(chip);
+ pnv_xive2_pic_print_info(&chip10->xive, mon);
pnv_psi_pic_print_info(&chip10->psi, mon);
+
+ object_child_foreach_recursive(OBJECT(chip),
+ pnv_chip_power9_pic_print_info_child, mon);
}
/* Always give the first 1GB to chip 0 else we won't boot */
@@ -1044,27 +1051,45 @@ static void pnv_chip_power9_intc_print_info(PnvChip *chip, PowerPCCPU *cpu,
static void pnv_chip_power10_intc_create(PnvChip *chip, PowerPCCPU *cpu,
Error **errp)
{
+ Pnv10Chip *chip10 = PNV10_CHIP(chip);
+ Error *local_err = NULL;
+ Object *obj;
PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
- /* Will be defined when the interrupt controller is */
- pnv_cpu->intc = NULL;
+ /*
+ * The core creates its interrupt presenter but the XIVE2 interrupt
+ * controller object is initialized afterwards. Hopefully, it's
+ * only used at runtime.
+ */
+ obj = xive_tctx_create(OBJECT(cpu), XIVE_PRESENTER(&chip10->xive),
+ &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
+
+ pnv_cpu->intc = obj;
}
static void pnv_chip_power10_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
{
- ;
+ PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
+
+ xive_tctx_reset(XIVE_TCTX(pnv_cpu->intc));
}
static void pnv_chip_power10_intc_destroy(PnvChip *chip, PowerPCCPU *cpu)
{
PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
+ xive_tctx_destroy(XIVE_TCTX(pnv_cpu->intc));
pnv_cpu->intc = NULL;
}
static void pnv_chip_power10_intc_print_info(PnvChip *chip, PowerPCCPU *cpu,
Monitor *mon)
{
+ xive_tctx_pic_print_info(XIVE_TCTX(pnv_cpu_state(cpu)->intc), mon);
}
/*
@@ -1366,6 +1391,21 @@ static void pnv_chip_power9_instance_init(Object *obj)
}
}
+static void pnv_chip_quad_realize_one(PnvChip *chip, PnvQuad *eq,
+ PnvCore *pnv_core)
+{
+ char eq_name[32];
+ int core_id = CPU_CORE(pnv_core)->core_id;
+
+ snprintf(eq_name, sizeof(eq_name), "eq[%d]", core_id);
+ object_initialize_child_with_props(OBJECT(chip), eq_name, eq,
+ sizeof(*eq), TYPE_PNV_QUAD,
+ &error_fatal, NULL);
+
+ object_property_set_int(OBJECT(eq), "quad-id", core_id, &error_fatal);
+ qdev_realize(DEVICE(eq), NULL, &error_fatal);
+}
+
static void pnv_chip_quad_realize(Pnv9Chip *chip9, Error **errp)
{
PnvChip *chip = PNV_CHIP(chip9);
@@ -1375,18 +1415,9 @@ static void pnv_chip_quad_realize(Pnv9Chip *chip9, Error **errp)
chip9->quads = g_new0(PnvQuad, chip9->nr_quads);
for (i = 0; i < chip9->nr_quads; i++) {
- char eq_name[32];
PnvQuad *eq = &chip9->quads[i];
- PnvCore *pnv_core = chip->cores[i * 4];
- int core_id = CPU_CORE(pnv_core)->core_id;
- snprintf(eq_name, sizeof(eq_name), "eq[%d]", core_id);
- object_initialize_child_with_props(OBJECT(chip), eq_name, eq,
- sizeof(*eq), TYPE_PNV_QUAD,
- &error_fatal, NULL);
-
- object_property_set_int(OBJECT(eq), "quad-id", core_id, &error_fatal);
- qdev_realize(DEVICE(eq), NULL, &error_fatal);
+ pnv_chip_quad_realize_one(chip, eq, chip->cores[i * 4]);
pnv_xscom_add_subregion(chip, PNV9_XSCOM_EQ_BASE(eq->quad_id),
&eq->xscom_regs);
@@ -1469,6 +1500,9 @@ static void pnv_chip_power9_realize(DeviceState *dev, Error **errp)
/* Processor Service Interface (PSI) Host Bridge */
object_property_set_int(OBJECT(&chip9->psi), "bar", PNV9_PSIHB_BASE(chip),
&error_fatal);
+ /* This is the only device with 4k ESB pages */
+ object_property_set_int(OBJECT(&chip9->psi), "shift", XIVE_ESB_4K,
+ &error_fatal);
if (!qdev_realize(DEVICE(&chip9->psi), NULL, errp)) {
return;
}
@@ -1553,10 +1587,73 @@ static void pnv_chip_power9_class_init(ObjectClass *klass, void *data)
static void pnv_chip_power10_instance_init(Object *obj)
{
+ PnvChip *chip = PNV_CHIP(obj);
Pnv10Chip *chip10 = PNV10_CHIP(obj);
+ PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj);
+ int i;
+ object_initialize_child(obj, "xive", &chip10->xive, TYPE_PNV_XIVE2);
+ object_property_add_alias(obj, "xive-fabric", OBJECT(&chip10->xive),
+ "xive-fabric");
object_initialize_child(obj, "psi", &chip10->psi, TYPE_PNV10_PSI);
object_initialize_child(obj, "lpc", &chip10->lpc, TYPE_PNV10_LPC);
+ object_initialize_child(obj, "occ", &chip10->occ, TYPE_PNV10_OCC);
+ object_initialize_child(obj, "homer", &chip10->homer, TYPE_PNV10_HOMER);
+
+ if (defaults_enabled()) {
+ chip->num_pecs = pcc->num_pecs;
+ }
+
+ for (i = 0; i < chip->num_pecs; i++) {
+ object_initialize_child(obj, "pec[*]", &chip10->pecs[i],
+ TYPE_PNV_PHB5_PEC);
+ }
+}
+
+static void pnv_chip_power10_quad_realize(Pnv10Chip *chip10, Error **errp)
+{
+ PnvChip *chip = PNV_CHIP(chip10);
+ int i;
+
+ chip10->nr_quads = DIV_ROUND_UP(chip->nr_cores, 4);
+ chip10->quads = g_new0(PnvQuad, chip10->nr_quads);
+
+ for (i = 0; i < chip10->nr_quads; i++) {
+ PnvQuad *eq = &chip10->quads[i];
+
+ pnv_chip_quad_realize_one(chip, eq, chip->cores[i * 4]);
+
+ pnv_xscom_add_subregion(chip, PNV10_XSCOM_EQ_BASE(eq->quad_id),
+ &eq->xscom_regs);
+ }
+}
+
+static void pnv_chip_power10_phb_realize(PnvChip *chip, Error **errp)
+{
+ Pnv10Chip *chip10 = PNV10_CHIP(chip);
+ int i;
+
+ for (i = 0; i < chip->num_pecs; i++) {
+ PnvPhb4PecState *pec = &chip10->pecs[i];
+ PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec);
+ uint32_t pec_nest_base;
+ uint32_t pec_pci_base;
+
+ object_property_set_int(OBJECT(pec), "index", i, &error_fatal);
+ object_property_set_int(OBJECT(pec), "chip-id", chip->chip_id,
+ &error_fatal);
+ object_property_set_link(OBJECT(pec), "chip", OBJECT(chip),
+ &error_fatal);
+ if (!qdev_realize(DEVICE(pec), NULL, errp)) {
+ return;
+ }
+
+ pec_nest_base = pecc->xscom_nest_base(pec);
+ pec_pci_base = pecc->xscom_pci_base(pec);
+
+ pnv_xscom_add_subregion(chip, pec_nest_base, &pec->nest_regs_mr);
+ pnv_xscom_add_subregion(chip, pec_pci_base, &pec->pci_regs_mr);
+ }
}
static void pnv_chip_power10_realize(DeviceState *dev, Error **errp)
@@ -1580,9 +1677,39 @@ static void pnv_chip_power10_realize(DeviceState *dev, Error **errp)
return;
}
+ pnv_chip_power10_quad_realize(chip10, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
+
+ /* XIVE2 interrupt controller (POWER10) */
+ object_property_set_int(OBJECT(&chip10->xive), "ic-bar",
+ PNV10_XIVE2_IC_BASE(chip), &error_fatal);
+ object_property_set_int(OBJECT(&chip10->xive), "esb-bar",
+ PNV10_XIVE2_ESB_BASE(chip), &error_fatal);
+ object_property_set_int(OBJECT(&chip10->xive), "end-bar",
+ PNV10_XIVE2_END_BASE(chip), &error_fatal);
+ object_property_set_int(OBJECT(&chip10->xive), "nvpg-bar",
+ PNV10_XIVE2_NVPG_BASE(chip), &error_fatal);
+ object_property_set_int(OBJECT(&chip10->xive), "nvc-bar",
+ PNV10_XIVE2_NVC_BASE(chip), &error_fatal);
+ object_property_set_int(OBJECT(&chip10->xive), "tm-bar",
+ PNV10_XIVE2_TM_BASE(chip), &error_fatal);
+ object_property_set_link(OBJECT(&chip10->xive), "chip", OBJECT(chip),
+ &error_abort);
+ if (!sysbus_realize(SYS_BUS_DEVICE(&chip10->xive), errp)) {
+ return;
+ }
+ pnv_xscom_add_subregion(chip, PNV10_XSCOM_XIVE2_BASE,
+ &chip10->xive.xscom_regs);
+
/* Processor Service Interface (PSI) Host Bridge */
object_property_set_int(OBJECT(&chip10->psi), "bar",
PNV10_PSIHB_BASE(chip), &error_fatal);
+ /* PSI can now be configured to use 64k ESB pages on POWER10 */
+ object_property_set_int(OBJECT(&chip10->psi), "shift", XIVE_ESB_64K,
+ &error_fatal);
if (!qdev_realize(DEVICE(&chip10->psi), NULL, errp)) {
return;
}
@@ -1601,6 +1728,41 @@ static void pnv_chip_power10_realize(DeviceState *dev, Error **errp)
chip->fw_mr = &chip10->lpc.isa_fw;
chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0",
(uint64_t) PNV10_LPCM_BASE(chip));
+
+ /* Create the simplified OCC model */
+ object_property_set_link(OBJECT(&chip10->occ), "psi", OBJECT(&chip10->psi),
+ &error_abort);
+ if (!qdev_realize(DEVICE(&chip10->occ), NULL, errp)) {
+ return;
+ }
+ pnv_xscom_add_subregion(chip, PNV10_XSCOM_OCC_BASE,
+ &chip10->occ.xscom_regs);
+
+ /* OCC SRAM model */
+ memory_region_add_subregion(get_system_memory(),
+ PNV10_OCC_SENSOR_BASE(chip),
+ &chip10->occ.sram_regs);
+
+ /* HOMER */
+ object_property_set_link(OBJECT(&chip10->homer), "chip", OBJECT(chip),
+ &error_abort);
+ if (!qdev_realize(DEVICE(&chip10->homer), NULL, errp)) {
+ return;
+ }
+ /* Homer Xscom region */
+ pnv_xscom_add_subregion(chip, PNV10_XSCOM_PBA_BASE,
+ &chip10->homer.pba_regs);
+
+ /* Homer mmio region */
+ memory_region_add_subregion(get_system_memory(), PNV10_HOMER_BASE(chip),
+ &chip10->homer.regs);
+
+ /* PHBs */
+ pnv_chip_power10_phb_realize(chip, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
}
static uint32_t pnv_chip_power10_xscom_pcba(PnvChip *chip, uint64_t addr)
@@ -1627,6 +1789,7 @@ static void pnv_chip_power10_class_init(ObjectClass *klass, void *data)
k->xscom_core_base = pnv_chip_power10_xscom_core_base;
k->xscom_pcba = pnv_chip_power10_xscom_pcba;
dc->desc = "PowerNV Chip POWER10";
+ k->num_pecs = PNV10_CHIP_MAX_PEC;
device_class_set_parent_realize(dc, pnv_chip_power10_realize,
&k->parent_realize);
@@ -1924,6 +2087,35 @@ static int pnv_match_nvt(XiveFabric *xfb, uint8_t format,
return total_count;
}
+static int pnv10_xive_match_nvt(XiveFabric *xfb, uint8_t format,
+ uint8_t nvt_blk, uint32_t nvt_idx,
+ bool cam_ignore, uint8_t priority,
+ uint32_t logic_serv,
+ XiveTCTXMatch *match)
+{
+ PnvMachineState *pnv = PNV_MACHINE(xfb);
+ int total_count = 0;
+ int i;
+
+ for (i = 0; i < pnv->num_chips; i++) {
+ Pnv10Chip *chip10 = PNV10_CHIP(pnv->chips[i]);
+ XivePresenter *xptr = XIVE_PRESENTER(&chip10->xive);
+ XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr);
+ int count;
+
+ count = xpc->match_nvt(xptr, format, nvt_blk, nvt_idx, cam_ignore,
+ priority, logic_serv, match);
+
+ if (count < 0) {
+ return count;
+ }
+
+ total_count += count;
+ }
+
+ return total_count;
+}
+
static void pnv_machine_power8_class_init(ObjectClass *oc, void *data)
{
MachineClass *mc = MACHINE_CLASS(oc);
@@ -1968,6 +2160,7 @@ static void pnv_machine_power10_class_init(ObjectClass *oc, void *data)
{
MachineClass *mc = MACHINE_CLASS(oc);
PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc);
+ XiveFabricClass *xfc = XIVE_FABRIC_CLASS(oc);
static const char compat[] = "qemu,powernv10\0ibm,powernv";
mc->desc = "IBM PowerNV (Non-Virtualized) POWER10";
@@ -1976,6 +2169,8 @@ static void pnv_machine_power10_class_init(ObjectClass *oc, void *data)
pmc->compat = compat;
pmc->compat_size = sizeof(compat);
pmc->dt_power_mgt = pnv_dt_power_mgt;
+
+ xfc->match_nvt = pnv10_xive_match_nvt;
}
static bool pnv_machine_get_hb(Object *obj, Error **errp)
@@ -2087,6 +2282,10 @@ static const TypeInfo types[] = {
.name = MACHINE_TYPE_NAME("powernv10"),
.parent = TYPE_PNV_MACHINE,
.class_init = pnv_machine_power10_class_init,
+ .interfaces = (InterfaceInfo[]) {
+ { TYPE_XIVE_FABRIC },
+ { },
+ },
},
{
.name = MACHINE_TYPE_NAME("powernv9"),
diff --git a/hw/ppc/pnv_homer.c b/hw/ppc/pnv_homer.c
index 9a262629b7..ea73919e54 100644
--- a/hw/ppc/pnv_homer.c
+++ b/hw/ppc/pnv_homer.c
@@ -332,6 +332,69 @@ static const TypeInfo pnv_homer_power9_type_info = {
.class_init = pnv_homer_power9_class_init,
};
+static uint64_t pnv_homer_power10_pba_read(void *opaque, hwaddr addr,
+ unsigned size)
+{
+ PnvHomer *homer = PNV_HOMER(opaque);
+ PnvChip *chip = homer->chip;
+ uint32_t reg = addr >> 3;
+ uint64_t val = 0;
+
+ switch (reg) {
+ case PBA_BAR0:
+ val = PNV10_HOMER_BASE(chip);
+ break;
+ case PBA_BARMASK0: /* P10 homer region mask */
+ val = (PNV10_HOMER_SIZE - 1) & 0x300000;
+ break;
+ case PBA_BAR2: /* P10 occ common area */
+ val = PNV10_OCC_COMMON_AREA_BASE;
+ break;
+ case PBA_BARMASK2: /* P10 occ common area size */
+ val = (PNV10_OCC_COMMON_AREA_SIZE - 1) & 0x700000;
+ break;
+ default:
+ qemu_log_mask(LOG_UNIMP, "PBA: read to unimplemented register: Ox%"
+ HWADDR_PRIx "\n", addr >> 3);
+ }
+ return val;
+}
+
+static void pnv_homer_power10_pba_write(void *opaque, hwaddr addr,
+ uint64_t val, unsigned size)
+{
+ qemu_log_mask(LOG_UNIMP, "PBA: write to unimplemented register: Ox%"
+ HWADDR_PRIx "\n", addr >> 3);
+}
+
+static const MemoryRegionOps pnv_homer_power10_pba_ops = {
+ .read = pnv_homer_power10_pba_read,
+ .write = pnv_homer_power10_pba_write,
+ .valid.min_access_size = 8,
+ .valid.max_access_size = 8,
+ .impl.min_access_size = 8,
+ .impl.max_access_size = 8,
+ .endianness = DEVICE_BIG_ENDIAN,
+};
+
+static void pnv_homer_power10_class_init(ObjectClass *klass, void *data)
+{
+ PnvHomerClass *homer = PNV_HOMER_CLASS(klass);
+
+ homer->pba_size = PNV10_XSCOM_PBA_SIZE;
+ homer->pba_ops = &pnv_homer_power10_pba_ops;
+ homer->homer_size = PNV10_HOMER_SIZE;
+ homer->homer_ops = &pnv_power9_homer_ops; /* TODO */
+ homer->core_max_base = PNV9_CORE_MAX_BASE;
+}
+
+static const TypeInfo pnv_homer_power10_type_info = {
+ .name = TYPE_PNV10_HOMER,
+ .parent = TYPE_PNV_HOMER,
+ .instance_size = sizeof(PnvHomer),
+ .class_init = pnv_homer_power10_class_init,
+};
+
static void pnv_homer_realize(DeviceState *dev, Error **errp)
{
PnvHomer *homer = PNV_HOMER(dev);
@@ -377,6 +440,7 @@ static void pnv_homer_register_types(void)
type_register_static(&pnv_homer_type_info);
type_register_static(&pnv_homer_power8_type_info);
type_register_static(&pnv_homer_power9_type_info);
+ type_register_static(&pnv_homer_power10_type_info);
}
type_init(pnv_homer_register_types);
diff --git a/hw/ppc/pnv_occ.c b/hw/ppc/pnv_occ.c
index 5a716c256e..4ed66f5e1f 100644
--- a/hw/ppc/pnv_occ.c
+++ b/hw/ppc/pnv_occ.c
@@ -236,7 +236,9 @@ static const MemoryRegionOps pnv_occ_power9_xscom_ops = {
static void pnv_occ_power9_class_init(ObjectClass *klass, void *data)
{
PnvOCCClass *poc = PNV_OCC_CLASS(klass);
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ dc->desc = "PowerNV OCC Controller (POWER9)";
poc->xscom_size = PNV9_XSCOM_OCC_SIZE;
poc->xscom_ops = &pnv_occ_power9_xscom_ops;
poc->psi_irq = PSIHB9_IRQ_OCC;
@@ -249,6 +251,19 @@ static const TypeInfo pnv_occ_power9_type_info = {
.class_init = pnv_occ_power9_class_init,
};
+static void pnv_occ_power10_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->desc = "PowerNV OCC Controller (POWER10)";
+}
+
+static const TypeInfo pnv_occ_power10_type_info = {
+ .name = TYPE_PNV10_OCC,
+ .parent = TYPE_PNV9_OCC,
+ .class_init = pnv_occ_power10_class_init,
+};
+
static void pnv_occ_realize(DeviceState *dev, Error **errp)
{
PnvOCC *occ = PNV_OCC(dev);
@@ -297,6 +312,7 @@ static void pnv_occ_register_types(void)
type_register_static(&pnv_occ_type_info);
type_register_static(&pnv_occ_power8_type_info);
type_register_static(&pnv_occ_power9_type_info);
+ type_register_static(&pnv_occ_power10_type_info);
}
type_init(pnv_occ_register_types);
diff --git a/hw/ppc/pnv_psi.c b/hw/ppc/pnv_psi.c
index cd9a2c5952..466fb79798 100644
--- a/hw/ppc/pnv_psi.c
+++ b/hw/ppc/pnv_psi.c
@@ -601,7 +601,6 @@ static const TypeInfo pnv_psi_power8_info = {
#define PSIHB9_IRQ_METHOD PPC_BIT(0)
#define PSIHB9_IRQ_RESET PPC_BIT(1)
#define PSIHB9_ESB_CI_BASE 0x60
-#define PSIHB9_ESB_CI_64K PPC_BIT(1)
#define PSIHB9_ESB_CI_ADDR_MASK PPC_BITMASK(8, 47)
#define PSIHB9_ESB_CI_VALID PPC_BIT(63)
#define PSIHB9_ESB_NOTIF_ADDR 0x68
@@ -646,7 +645,15 @@ static const TypeInfo pnv_psi_power8_info = {
#define PSIHB9_IRQ_STAT_DIO PPC_BIT(12)
#define PSIHB9_IRQ_STAT_PSU PPC_BIT(13)
-static void pnv_psi_notify(XiveNotifier *xf, uint32_t srcno)
+/* P10 register extensions */
+
+#define PSIHB10_CR PSIHB9_CR
+#define PSIHB10_CR_STORE_EOI PPC_BIT(12)
+
+#define PSIHB10_ESB_CI_BASE PSIHB9_ESB_CI_BASE
+#define PSIHB10_ESB_CI_64K PPC_BIT(1)
+
+static void pnv_psi_notify(XiveNotifier *xf, uint32_t srcno, bool pq_checked)
{
PnvPsi *psi = PNV_PSI(xf);
uint64_t notif_port = psi->regs[PSIHB_REG(PSIHB9_ESB_NOTIF_ADDR)];
@@ -655,9 +662,13 @@ static void pnv_psi_notify(XiveNotifier *xf, uint32_t srcno)
uint32_t offset =
(psi->regs[PSIHB_REG(PSIHB9_IVT_OFFSET)] >> PSIHB9_IVT_OFF_SHIFT);
- uint64_t data = XIVE_TRIGGER_PQ | offset | srcno;
+ uint64_t data = offset | srcno;
MemTxResult result;
+ if (pq_checked) {
+ data |= XIVE_TRIGGER_PQ;
+ }
+
if (!valid) {
return;
}
@@ -704,6 +715,13 @@ static void pnv_psi_p9_mmio_write(void *opaque, hwaddr addr,
switch (addr) {
case PSIHB9_CR:
+ if (val & PSIHB10_CR_STORE_EOI) {
+ psi9->source.esb_flags |= XIVE_SRC_STORE_EOI;
+ } else {
+ psi9->source.esb_flags &= ~XIVE_SRC_STORE_EOI;
+ }
+ break;
+
case PSIHB9_SEMR:
/* FSP stuff */
break;
@@ -715,15 +733,20 @@ static void pnv_psi_p9_mmio_write(void *opaque, hwaddr addr,
break;
case PSIHB9_ESB_CI_BASE:
+ if (val & PSIHB10_ESB_CI_64K) {
+ psi9->source.esb_shift = XIVE_ESB_64K;
+ } else {
+ psi9->source.esb_shift = XIVE_ESB_4K;
+ }
if (!(val & PSIHB9_ESB_CI_VALID)) {
if (psi->regs[reg] & PSIHB9_ESB_CI_VALID) {
memory_region_del_subregion(sysmem, &psi9->source.esb_mmio);
}
} else {
if (!(psi->regs[reg] & PSIHB9_ESB_CI_VALID)) {
- memory_region_add_subregion(sysmem,
- val & ~PSIHB9_ESB_CI_VALID,
- &psi9->source.esb_mmio);
+ hwaddr addr = val & ~(PSIHB9_ESB_CI_VALID | PSIHB10_ESB_CI_64K);
+ memory_region_add_subregion(sysmem, addr,
+ &psi9->source.esb_mmio);
}
}
psi->regs[reg] = val;
@@ -831,6 +854,7 @@ static void pnv_psi_power9_instance_init(Object *obj)
Pnv9Psi *psi = PNV9_PSI(obj);
object_initialize_child(obj, "source", &psi->source, TYPE_XIVE_SOURCE);
+ object_property_add_alias(obj, "shift", OBJECT(&psi->source), "shift");
}
static void pnv_psi_power9_realize(DeviceState *dev, Error **errp)
@@ -839,8 +863,6 @@ static void pnv_psi_power9_realize(DeviceState *dev, Error **errp)
XiveSource *xsrc = &PNV9_PSI(psi)->source;
int i;
- /* This is the only device with 4k ESB pages */
- object_property_set_int(OBJECT(xsrc), "shift", XIVE_ESB_4K, &error_fatal);
object_property_set_int(OBJECT(xsrc), "nr-irqs", PSIHB9_NUM_IRQS,
&error_fatal);
object_property_set_link(OBJECT(xsrc), "xive", OBJECT(psi), &error_abort);
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index f0b75b22bb..4cc204f90d 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -1018,9 +1018,9 @@ static void spapr_dt_chosen(SpaprMachineState *spapr, void *fdt, bool reset)
if (reset) {
const char *boot_device = spapr->boot_device;
- char *stdout_path = spapr_vio_stdout_path(spapr->vio_bus);
+ g_autofree char *stdout_path = spapr_vio_stdout_path(spapr->vio_bus);
size_t cb = 0;
- char *bootlist = get_boot_devices_list(&cb);
+ g_autofree char *bootlist = get_boot_devices_list(&cb);
if (machine->kernel_cmdline && machine->kernel_cmdline[0]) {
_FDT(fdt_setprop_string(fdt, chosen, "bootargs",
@@ -1087,9 +1087,6 @@ static void spapr_dt_chosen(SpaprMachineState *spapr, void *fdt, bool reset)
}
spapr_dt_ov5_platform_support(spapr, fdt, chosen);
-
- g_free(stdout_path);
- g_free(bootlist);
}
_FDT(spapr_dt_ovec(fdt, chosen, spapr->ov5_cas, "ibm,architecture-vec-5"));
@@ -2710,15 +2707,25 @@ static void spapr_machine_init(MachineState *machine)
MachineClass *mc = MACHINE_GET_CLASS(machine);
const char *bios_default = spapr->vof ? FW_FILE_NAME_VOF : FW_FILE_NAME;
const char *bios_name = machine->firmware ?: bios_default;
+ g_autofree char *filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
const char *kernel_filename = machine->kernel_filename;
const char *initrd_filename = machine->initrd_filename;
PCIHostState *phb;
int i;
MemoryRegion *sysmem = get_system_memory();
long load_limit, fw_size;
- char *filename;
Error *resize_hpt_err = NULL;
+ if (!filename) {
+ error_report("Could not find LPAR firmware '%s'", bios_name);
+ exit(1);
+ }
+ fw_size = load_image_targphys(filename, 0, FW_MAX_SIZE);
+ if (fw_size <= 0) {
+ error_report("Could not load LPAR firmware '%s'", filename);
+ exit(1);
+ }
+
/*
* if Secure VM (PEF) support is configured, then initialize it
*/
@@ -2999,18 +3006,6 @@ static void spapr_machine_init(MachineState *machine)
}
}
- filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
- if (!filename) {
- error_report("Could not find LPAR firmware '%s'", bios_name);
- exit(1);
- }
- fw_size = load_image_targphys(filename, 0, FW_MAX_SIZE);
- if (fw_size <= 0) {
- error_report("Could not load LPAR firmware '%s'", filename);
- exit(1);
- }
- g_free(filename);
-
/* FIXME: Should register things through the MachineState's qdev
* interface, this is a legacy from the sPAPREnvironment structure
* which predated MachineState but had a similar function */
diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c
index 6167431271..655ab856a0 100644
--- a/hw/ppc/spapr_caps.c
+++ b/hw/ppc/spapr_caps.c
@@ -95,12 +95,12 @@ static void spapr_cap_set_bool(Object *obj, Visitor *v, const char *name,
}
-static void spapr_cap_get_string(Object *obj, Visitor *v, const char *name,
- void *opaque, Error **errp)
+static void spapr_cap_get_string(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
{
SpaprCapabilityInfo *cap = opaque;
SpaprMachineState *spapr = SPAPR_MACHINE(obj);
- char *val = NULL;
+ g_autofree char *val = NULL;
uint8_t value = spapr_get_cap(spapr, cap->index);
if (value >= cap->possible->num) {
@@ -111,7 +111,6 @@ static void spapr_cap_get_string(Object *obj, Visitor *v, const char *name,
val = g_strdup(cap->possible->vals[value]);
visit_type_str(v, name, &val, errp);
- g_free(val);
}
static void spapr_cap_set_string(Object *obj, Visitor *v, const char *name,
@@ -120,7 +119,7 @@ static void spapr_cap_set_string(Object *obj, Visitor *v, const char *name,
SpaprCapabilityInfo *cap = opaque;
SpaprMachineState *spapr = SPAPR_MACHINE(obj);
uint8_t i;
- char *val;
+ g_autofree char *val = NULL;
if (!visit_type_str(v, name, &val, errp)) {
return;
@@ -128,20 +127,18 @@ static void spapr_cap_set_string(Object *obj, Visitor *v, const char *name,
if (!strcmp(val, "?")) {
error_setg(errp, "%s", cap->possible->help);
- goto out;
+ return;
}
for (i = 0; i < cap->possible->num; i++) {
if (!strcasecmp(val, cap->possible->vals[i])) {
spapr->cmd_line_caps[cap->index] = true;
spapr->eff.caps[cap->index] = i;
- goto out;
+ return;
}
}
error_setg(errp, "Invalid capability mode \"%s\" for cap-%s", val,
cap->name);
-out:
- g_free(val);
}
static void spapr_cap_get_pagesize(Object *obj, Visitor *v, const char *name,
@@ -933,16 +930,13 @@ void spapr_caps_add_properties(SpaprMachineClass *smc)
for (i = 0; i < ARRAY_SIZE(capability_table); i++) {
SpaprCapabilityInfo *cap = &capability_table[i];
- char *name = g_strdup_printf("cap-%s", cap->name);
- char *desc;
+ g_autofree char *name = g_strdup_printf("cap-%s", cap->name);
+ g_autofree char *desc = g_strdup_printf("%s", cap->description);
object_class_property_add(klass, name, cap->type,
cap->get, cap->set,
NULL, cap);
- desc = g_strdup_printf("%s", cap->description);
object_class_property_set_description(klass, name, desc);
- g_free(name);
- g_free(desc);
}
}
diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c
index f8ac0a10df..76bc5d42a0 100644
--- a/hw/ppc/spapr_drc.c
+++ b/hw/ppc/spapr_drc.c
@@ -519,8 +519,8 @@ static const VMStateDescription vmstate_spapr_drc = {
static void drc_realize(DeviceState *d, Error **errp)
{
SpaprDrc *drc = SPAPR_DR_CONNECTOR(d);
+ g_autofree gchar *link_name = g_strdup_printf("%x", spapr_drc_index(drc));
Object *root_container;
- gchar *link_name;
const char *child_name;
trace_spapr_drc_realize(spapr_drc_index(drc));
@@ -532,12 +532,10 @@ static void drc_realize(DeviceState *d, Error **errp)
* existing in the composition tree
*/
root_container = container_get(object_get_root(), DRC_CONTAINER_PATH);
- link_name = g_strdup_printf("%x", spapr_drc_index(drc));
child_name = object_get_canonical_path_component(OBJECT(drc));
trace_spapr_drc_realize_child(spapr_drc_index(drc), child_name);
object_property_add_alias(root_container, link_name,
drc->owner, child_name);
- g_free(link_name);
vmstate_register(VMSTATE_IF(drc), spapr_drc_index(drc), &vmstate_spapr_drc,
drc);
trace_spapr_drc_realize_complete(spapr_drc_index(drc));
@@ -546,22 +544,20 @@ static void drc_realize(DeviceState *d, Error **errp)
static void drc_unrealize(DeviceState *d)
{
SpaprDrc *drc = SPAPR_DR_CONNECTOR(d);
+ g_autofree gchar *name = g_strdup_printf("%x", spapr_drc_index(drc));
Object *root_container;
- gchar *name;
trace_spapr_drc_unrealize(spapr_drc_index(drc));
vmstate_unregister(VMSTATE_IF(drc), &vmstate_spapr_drc, drc);
root_container = container_get(object_get_root(), DRC_CONTAINER_PATH);
- name = g_strdup_printf("%x", spapr_drc_index(drc));
object_property_del(root_container, name);
- g_free(name);
}
SpaprDrc *spapr_dr_connector_new(Object *owner, const char *type,
uint32_t id)
{
SpaprDrc *drc = SPAPR_DR_CONNECTOR(object_new(type));
- char *prop_name;
+ g_autofree char *prop_name = NULL;
drc->id = id;
drc->owner = owner;
@@ -570,7 +566,6 @@ SpaprDrc *spapr_dr_connector_new(Object *owner, const char *type,
object_property_add_child(owner, prop_name, OBJECT(drc));
object_unref(OBJECT(drc));
qdev_realize(DEVICE(drc), NULL, NULL);
- g_free(prop_name);
return drc;
}
@@ -803,11 +798,9 @@ static const TypeInfo spapr_drc_pmem_info = {
SpaprDrc *spapr_drc_by_index(uint32_t index)
{
Object *obj;
- gchar *name;
-
- name = g_strdup_printf("%s/%x", DRC_CONTAINER_PATH, index);
+ g_autofree gchar *name = g_strdup_printf("%s/%x", DRC_CONTAINER_PATH,
+ index);
obj = object_resolve_path(name, NULL);
- g_free(name);
return !obj ? NULL : SPAPR_DR_CONNECTOR(obj);
}
@@ -841,8 +834,14 @@ int spapr_dt_drc(void *fdt, int offset, Object *owner, uint32_t drc_type_mask)
ObjectProperty *prop;
ObjectPropertyIterator iter;
uint32_t drc_count = 0;
- GArray *drc_indexes, *drc_power_domains;
- GString *drc_names, *drc_types;
+ g_autoptr(GArray) drc_indexes = g_array_new(false, true,
+ sizeof(uint32_t));
+ g_autoptr(GArray) drc_power_domains = g_array_new(false, true,
+ sizeof(uint32_t));
+ g_autoptr(GString) drc_names = g_string_set_size(g_string_new(NULL),
+ sizeof(uint32_t));
+ g_autoptr(GString) drc_types = g_string_set_size(g_string_new(NULL),
+ sizeof(uint32_t));
int ret;
/*
@@ -857,12 +856,8 @@ int spapr_dt_drc(void *fdt, int offset, Object *owner, uint32_t drc_type_mask)
* reserve the space now and set the offsets accordingly so we
* can fill them in later.
*/
- drc_indexes = g_array_new(false, true, sizeof(uint32_t));
drc_indexes = g_array_set_size(drc_indexes, 1);
- drc_power_domains = g_array_new(false, true, sizeof(uint32_t));
drc_power_domains = g_array_set_size(drc_power_domains, 1);
- drc_names = g_string_set_size(g_string_new(NULL), sizeof(uint32_t));
- drc_types = g_string_set_size(g_string_new(NULL), sizeof(uint32_t));
/* aliases for all DRConnector objects will be rooted in QOM
* composition tree at DRC_CONTAINER_PATH
@@ -874,7 +869,7 @@ int spapr_dt_drc(void *fdt, int offset, Object *owner, uint32_t drc_type_mask)
Object *obj;
SpaprDrc *drc;
SpaprDrcClass *drck;
- char *drc_name = NULL;
+ g_autofree char *drc_name = NULL;
uint32_t drc_index, drc_power_domain;
if (!strstart(prop->type, "link<", NULL)) {
@@ -908,7 +903,6 @@ int spapr_dt_drc(void *fdt, int offset, Object *owner, uint32_t drc_type_mask)
drc_name = spapr_drc_name(drc);
drc_names = g_string_append(drc_names, drc_name);
drc_names = g_string_insert_len(drc_names, -1, "\0", 1);
- g_free(drc_name);
/* ibm,drc-types */
drc_types = g_string_append(drc_types, drck->typename);
@@ -928,7 +922,7 @@ int spapr_dt_drc(void *fdt, int offset, Object *owner, uint32_t drc_type_mask)
drc_indexes->len * sizeof(uint32_t));
if (ret) {
error_report("Couldn't create ibm,drc-indexes property");
- goto out;
+ return ret;
}
ret = fdt_setprop(fdt, offset, "ibm,drc-power-domains",
@@ -936,29 +930,22 @@ int spapr_dt_drc(void *fdt, int offset, Object *owner, uint32_t drc_type_mask)
drc_power_domains->len * sizeof(uint32_t));
if (ret) {
error_report("Couldn't finalize ibm,drc-power-domains property");
- goto out;
+ return ret;
}
ret = fdt_setprop(fdt, offset, "ibm,drc-names",
drc_names->str, drc_names->len);
if (ret) {
error_report("Couldn't finalize ibm,drc-names property");
- goto out;
+ return ret;
}
ret = fdt_setprop(fdt, offset, "ibm,drc-types",
drc_types->str, drc_types->len);
if (ret) {
error_report("Couldn't finalize ibm,drc-types property");
- goto out;
}
-out:
- g_array_free(drc_indexes, true);
- g_array_free(drc_power_domains, true);
- g_string_free(drc_names, true);
- g_string_free(drc_types, true);
-
return ret;
}
diff --git a/hw/ppc/spapr_numa.c b/hw/ppc/spapr_numa.c
index e9ef7e7646..4f93bdefec 100644
--- a/hw/ppc/spapr_numa.c
+++ b/hw/ppc/spapr_numa.c
@@ -431,12 +431,14 @@ int spapr_numa_write_assoc_lookup_arrays(SpaprMachineState *spapr, void *fdt,
int max_distance_ref_points = get_max_dist_ref_points(spapr);
int nb_numa_nodes = machine->numa_state->num_nodes;
int nr_nodes = nb_numa_nodes ? nb_numa_nodes : 1;
- uint32_t *int_buf, *cur_index, buf_len;
- int ret, i;
+ g_autofree uint32_t *int_buf = NULL;
+ uint32_t *cur_index;
+ int i;
/* ibm,associativity-lookup-arrays */
- buf_len = (nr_nodes * max_distance_ref_points + 2) * sizeof(uint32_t);
- cur_index = int_buf = g_malloc0(buf_len);
+ int_buf = g_malloc0((nr_nodes * max_distance_ref_points + 2) *
+ sizeof(uint32_t));
+ cur_index = int_buf;
int_buf[0] = cpu_to_be32(nr_nodes);
/* Number of entries per associativity list */
int_buf[1] = cpu_to_be32(max_distance_ref_points);
@@ -451,11 +453,9 @@ int spapr_numa_write_assoc_lookup_arrays(SpaprMachineState *spapr, void *fdt,
sizeof(uint32_t) * max_distance_ref_points);
cur_index += max_distance_ref_points;
}
- ret = fdt_setprop(fdt, offset, "ibm,associativity-lookup-arrays", int_buf,
- (cur_index - int_buf) * sizeof(uint32_t));
- g_free(int_buf);
- return ret;
+ return fdt_setprop(fdt, offset, "ibm,associativity-lookup-arrays",
+ int_buf, (cur_index - int_buf) * sizeof(uint32_t));
}
static void spapr_numa_FORM1_write_rtas_dt(SpaprMachineState *spapr,
diff --git a/hw/ppc/spapr_pci_nvlink2.c b/hw/ppc/spapr_pci_nvlink2.c
index 7fb0cf4d04..4678c79235 100644
--- a/hw/ppc/spapr_pci_nvlink2.c
+++ b/hw/ppc/spapr_pci_nvlink2.c
@@ -320,7 +320,7 @@ void spapr_phb_nvgpu_populate_dt(SpaprPhbState *sphb, void *fdt, int bus_off,
void spapr_phb_nvgpu_ram_populate_dt(SpaprPhbState *sphb, void *fdt)
{
int i, j, linkidx, npuoff;
- char *npuname;
+ g_autofree char *npuname = NULL;
if (!sphb->nvgpus) {
return;
@@ -333,11 +333,10 @@ void spapr_phb_nvgpu_ram_populate_dt(SpaprPhbState *sphb, void *fdt)
_FDT(fdt_setprop_cell(fdt, npuoff, "#size-cells", 0));
/* Advertise NPU as POWER9 so the guest can enable NPU2 contexts */
_FDT((fdt_setprop_string(fdt, npuoff, "compatible", "ibm,power9-npu")));
- g_free(npuname);
for (i = 0, linkidx = 0; i < sphb->nvgpus->num; ++i) {
for (j = 0; j < sphb->nvgpus->slots[i].linknum; ++j) {
- char *linkname = g_strdup_printf("link@%d", linkidx);
+ g_autofree char *linkname = g_strdup_printf("link@%d", linkidx);
int off = fdt_add_subnode(fdt, npuoff, linkname);
_FDT(off);
@@ -347,7 +346,6 @@ void spapr_phb_nvgpu_ram_populate_dt(SpaprPhbState *sphb, void *fdt)
_FDT((fdt_setprop_cell(fdt, off, "phandle",
PHANDLE_NVLINK(sphb, i, j))));
_FDT((fdt_setprop_cell(fdt, off, "ibm,npu-link-index", linkidx)));
- g_free(linkname);
++linkidx;
}
}
@@ -360,7 +358,8 @@ void spapr_phb_nvgpu_ram_populate_dt(SpaprPhbState *sphb, void *fdt)
&error_abort);
uint64_t size = object_property_get_uint(nv_mrobj, "size", NULL);
uint64_t mem_reg[2] = { cpu_to_be64(nvslot->gpa), cpu_to_be64(size) };
- char *mem_name = g_strdup_printf("memory@%"PRIx64, nvslot->gpa);
+ g_autofree char *mem_name = g_strdup_printf("memory@%"PRIx64,
+ nvslot->gpa);
int off = fdt_add_subnode(fdt, 0, mem_name);
_FDT(off);
@@ -378,7 +377,6 @@ void spapr_phb_nvgpu_ram_populate_dt(SpaprPhbState *sphb, void *fdt)
sizeof(mem_reg))));
_FDT((fdt_setprop_cell(fdt, off, "phandle",
PHANDLE_GPURAM(sphb, i))));
- g_free(mem_name);
}
}
diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c
index b476382ae6..d7c04237fe 100644
--- a/hw/ppc/spapr_rtas.c
+++ b/hw/ppc/spapr_rtas.c
@@ -279,30 +279,29 @@ static void rtas_ibm_get_system_parameter(PowerPCCPU *cpu,
switch (parameter) {
case RTAS_SYSPARM_SPLPAR_CHARACTERISTICS: {
- char *param_val = g_strdup_printf("MaxEntCap=%d,"
- "DesMem=%" PRIu64 ","
- "DesProcs=%d,"
- "MaxPlatProcs=%d",
- ms->smp.max_cpus,
- ms->ram_size / MiB,
- ms->smp.cpus,
- ms->smp.max_cpus);
+ g_autofree char *param_val = g_strdup_printf("MaxEntCap=%d,"
+ "DesMem=%" PRIu64 ","
+ "DesProcs=%d,"
+ "MaxPlatProcs=%d",
+ ms->smp.max_cpus,
+ ms->ram_size / MiB,
+ ms->smp.cpus,
+ ms->smp.max_cpus);
if (pcc->n_host_threads > 0) {
- char *hostthr_val, *old = param_val;
-
/*
* Add HostThrs property. This property is not present in PAPR but
* is expected by some guests to communicate the number of physical
* host threads per core on the system so that they can scale
* information which varies based on the thread configuration.
*/
- hostthr_val = g_strdup_printf(",HostThrs=%d", pcc->n_host_threads);
+ g_autofree char *hostthr_val = g_strdup_printf(",HostThrs=%d",
+ pcc->n_host_threads);
+ char *old = param_val;
+
param_val = g_strconcat(param_val, hostthr_val, NULL);
- g_free(hostthr_val);
g_free(old);
}
ret = sysparm_st(buffer, length, param_val, strlen(param_val) + 1);
- g_free(param_val);
break;
}
case RTAS_SYSPARM_DIAGNOSTICS_RUN_MODE: {
diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c
index b975ed29ca..9d4fec2c04 100644
--- a/hw/ppc/spapr_vio.c
+++ b/hw/ppc/spapr_vio.c
@@ -726,7 +726,7 @@ void spapr_dt_vdevice(SpaprVioBus *bus, void *fdt)
gchar *spapr_vio_stdout_path(SpaprVioBus *bus)
{
SpaprVioDevice *dev;
- char *name, *path;
+ g_autofree char *name = NULL;
dev = spapr_vty_get_default(bus);
if (!dev) {
@@ -734,8 +734,6 @@ gchar *spapr_vio_stdout_path(SpaprVioBus *bus)
}
name = spapr_vio_get_dev_name(DEVICE(dev));
- path = g_strdup_printf("/vdevice/%s", name);
- g_free(name);
- return path;
+ return g_strdup_printf("/vdevice/%s", name);
}