The CAM line matching on the PowerNV machine now scans all chips of the system and all CPUs of a chip to find a dispatched NVT in the thread contexts.
As there is now easy way to loop on the CPUs belonging to a chip, the PowerNV handler loops on all CPUs and filter out the external CPUs. Fixes: af53dbf6227a ("ppc/xive: introduce a simplified XIVE presenter") Signed-off-by: Cédric Le Goater <c...@kaod.org> --- hw/intc/pnv_xive.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++ hw/ppc/pnv.c | 32 +++++++++++++++++++ 2 files changed, 108 insertions(+) diff --git a/hw/intc/pnv_xive.c b/hw/intc/pnv_xive.c index ff1226485983..183798b81496 100644 --- a/hw/intc/pnv_xive.c +++ b/hw/intc/pnv_xive.c @@ -390,6 +390,80 @@ static int pnv_xive_get_eas(XiveRouter *xrtr, uint8_t blk, uint32_t idx, return pnv_xive_vst_read(xive, VST_TSEL_IVT, blk, idx, eas); } +static int cpu_pir(PowerPCCPU *cpu) +{ + CPUPPCState *env = &cpu->env; + return env->spr_cb[SPR_PIR].default_value; +} + +static int cpu_chip_id(PowerPCCPU *cpu) +{ + int pir = cpu_pir(cpu); + return (pir >> 8) & 0x7f; +} + +static bool pnv_xive_is_cpu_enabled(PnvXive *xive, PowerPCCPU *cpu) +{ + int pir = cpu_pir(cpu); + int thrd_id = pir & 0x7f; + + return xive->regs[PC_THREAD_EN_REG0 >> 3] & PPC_BIT(thrd_id); +} + +static bool pnv_xive_is_ignored(PnvChip *chip, CPUState *cs) +{ + return chip->chip_id != cpu_chip_id(POWERPC_CPU(cs)); +} + +#define PNV_CHIP_CPU_FOREACH(chip, cs) \ + CPU_FOREACH(cs) \ + if (pnv_xive_is_ignored(chip, cs)) {} else + +static int pnv_xive_match_nvt(XivePresenter *xptr, uint8_t format, + uint8_t nvt_blk, uint32_t nvt_idx, + bool cam_ignore, uint8_t priority, + uint32_t logic_serv, XiveTCTXMatch *match) +{ + PnvXive *xive = PNV_XIVE(xptr); + CPUState *cs; + int count = 0; + + /* + * Loop on all CPUs of the machine and filter out the CPUs + * belonging to another chip. + */ + PNV_CHIP_CPU_FOREACH(xive->chip, cs) { + PowerPCCPU *cpu = POWERPC_CPU(cs); + XiveTCTX *tctx = XIVE_TCTX(pnv_cpu_state(cpu)->intc); + int ring; + + if (!pnv_xive_is_cpu_enabled(xive, cpu)) { + continue; + } + + ring = xive_presenter_tctx_match(xptr, tctx, format, nvt_blk, nvt_idx, + cam_ignore, logic_serv); + /* + * Save the context and follow on to catch duplicates, that we + * don't support yet. + */ + if (ring != -1) { + if (match->tctx) { + qemu_log_mask(LOG_GUEST_ERROR, "XIVE: already found a " + "thread context NVT %x/%x\n", + nvt_blk, nvt_idx); + return -1; + } + + match->ring = ring; + match->tctx = tctx; + count++; + } + } + + return count; +} + static XiveTCTX *pnv_xive_get_tctx(XiveRouter *xrtr, CPUState *cs) { PowerPCCPU *cpu = POWERPC_CPU(cs); @@ -1795,6 +1869,7 @@ static void pnv_xive_class_init(ObjectClass *klass, void *data) PnvXScomInterfaceClass *xdc = PNV_XSCOM_INTERFACE_CLASS(klass); XiveRouterClass *xrc = XIVE_ROUTER_CLASS(klass); XiveNotifierClass *xnc = XIVE_NOTIFIER_CLASS(klass); + XivePresenterClass *xpc = XIVE_PRESENTER_CLASS(klass); xdc->dt_xscom = pnv_xive_dt_xscom; @@ -1810,6 +1885,7 @@ static void pnv_xive_class_init(ObjectClass *klass, void *data) xrc->get_tctx = pnv_xive_get_tctx; xnc->notify = pnv_xive_notify; + xpc->match_nvt = pnv_xive_match_nvt; }; static const TypeInfo pnv_xive_info = { diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index 18602b9e9bcd..3f6796831b68 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -1322,6 +1322,35 @@ static void pnv_pic_print_info(InterruptStatsProvider *obj, } } +static int pnv_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++) { + Pnv9Chip *chip9 = PNV9_CHIP(pnv->chips[i]); + XivePresenter *xptr = XIVE_PRESENTER(&chip9->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_get_num_chips(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { @@ -1385,9 +1414,11 @@ static void pnv_machine_power8_class_init(ObjectClass *oc, void *data) static void pnv_machine_power9_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); + XiveFabricClass *xfc = XIVE_FABRIC_CLASS(oc); mc->desc = "IBM PowerNV (Non-Virtualized) POWER9"; mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power9_v2.0"); + xfc->match_nvt = pnv_xive_match_nvt; mc->alias = "powernv"; } @@ -1435,6 +1466,7 @@ static void pnv_machine_class_init(ObjectClass *oc, void *data) .interfaces = (InterfaceInfo[]) { \ { TYPE_XICS_FABRIC }, \ { TYPE_INTERRUPT_STATS_PROVIDER }, \ + { TYPE_XIVE_FABRIC }, \ { }, \ }, \ } -- 2.21.0