aboutsummaryrefslogtreecommitdiff
path: root/hw/ppc/pnv.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/ppc/pnv.c')
-rw-r--r--hw/ppc/pnv.c85
1 files changed, 82 insertions, 3 deletions
diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index 441bf958ca..f486fdfb5c 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -725,6 +725,7 @@ 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);
}
@@ -1047,27 +1048,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);
}
/*
@@ -1558,6 +1577,9 @@ static void pnv_chip_power10_instance_init(Object *obj)
{
Pnv10Chip *chip10 = PNV10_CHIP(obj);
+ 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);
}
@@ -1583,6 +1605,27 @@ static void pnv_chip_power10_realize(DeviceState *dev, Error **errp)
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);
@@ -1927,6 +1970,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);
@@ -1971,6 +2043,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";
@@ -1979,6 +2052,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)
@@ -2090,6 +2165,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"),