The CAM line matching sequence in the pseries machine does not change much apart from the use of the new QOM interfaces.
Fixes: af53dbf6227a ("ppc/xive: introduce a simplified XIVE presenter") Signed-off-by: Cédric Le Goater <c...@kaod.org> --- include/hw/ppc/spapr_irq.h | 6 ++++++ hw/intc/spapr_xive.c | 41 ++++++++++++++++++++++++++++++++++++++ hw/ppc/spapr.c | 34 +++++++++++++++++++++++++++++++ hw/ppc/spapr_irq.c | 25 +++++++++++++++++++++++ 4 files changed, 106 insertions(+) diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h index f965a58f8954..8c99b0680f97 100644 --- a/include/hw/ppc/spapr_irq.h +++ b/include/hw/ppc/spapr_irq.h @@ -30,6 +30,8 @@ int spapr_irq_msi_alloc(SpaprMachineState *spapr, uint32_t num, bool align, void spapr_irq_msi_free(SpaprMachineState *spapr, int irq, uint32_t num); void spapr_irq_msi_reset(SpaprMachineState *spapr); +struct XiveTCTXMatch; + typedef struct SpaprIrq { uint32_t nr_irqs; uint32_t nr_msis; @@ -49,6 +51,10 @@ typedef struct SpaprIrq { void (*set_irq)(void *opaque, int srcno, int val); const char *(*get_nodename)(SpaprMachineState *spapr); void (*init_kvm)(SpaprMachineState *spapr, Error **errp); + int (*match_nvt)(SpaprMachineState *spapr, uint8_t format, + uint8_t nvt_blk, uint32_t nvt_idx, + bool cam_ignore, uint8_t priority, + uint32_t logic_serv, struct XiveTCTXMatch *match); } SpaprIrq; extern SpaprIrq spapr_irq_xics; diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c index ba012c7b0fdc..beb5049ad9da 100644 --- a/hw/intc/spapr_xive.c +++ b/hw/intc/spapr_xive.c @@ -419,6 +419,44 @@ static XiveTCTX *spapr_xive_get_tctx(XiveRouter *xrtr, CPUState *cs) return spapr_cpu_state(cpu)->tctx; } +static int spapr_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) +{ + CPUState *cs; + int count = 0; + + CPU_FOREACH(cs) { + PowerPCCPU *cpu = POWERPC_CPU(cs); + XiveTCTX *tctx = spapr_cpu_state(cpu)->tctx; + int ring; + + /* + * Check the thread context CAM lines and record matches. + */ + ring = xive_presenter_tctx_match(xptr, tctx, format, nvt_blk, nvt_idx, + cam_ignore, logic_serv); + /* + * Save the matching thread interrupt context and follow on to + * check for duplicates which are invalid. + */ + 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 const VMStateDescription vmstate_spapr_xive_end = { .name = TYPE_SPAPR_XIVE "/end", .version_id = 1, @@ -496,6 +534,7 @@ static void spapr_xive_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); XiveRouterClass *xrc = XIVE_ROUTER_CLASS(klass); + XivePresenterClass *xpc = XIVE_PRESENTER_CLASS(klass); dc->desc = "sPAPR XIVE Interrupt Controller"; dc->props = spapr_xive_properties; @@ -508,6 +547,8 @@ static void spapr_xive_class_init(ObjectClass *klass, void *data) xrc->get_nvt = spapr_xive_get_nvt; xrc->write_nvt = spapr_xive_write_nvt; xrc->get_tctx = spapr_xive_get_tctx; + + xpc->match_nvt = spapr_xive_match_nvt; } static const TypeInfo spapr_xive_info = { diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 115bbfb0e788..631db719f41f 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -4302,6 +4302,37 @@ static void spapr_pic_print_info(InterruptStatsProvider *obj, spapr->irq->print_info(spapr, mon); } +static int spapr_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) +{ + SpaprMachineState *spapr = SPAPR_MACHINE(xfb); + int count; + + count = spapr->irq->match_nvt(spapr, format, nvt_blk, nvt_idx, cam_ignore, + priority, logic_serv, match); + if (count < 0) { + return count; + } + + /* + * When we implement the save and restore of the thread interrupt + * contexts in the enter/exit CPU handlers of the machine and the + * escalations in QEMU, we should be able to handle non dispatched + * vCPUs. + * + * Until this is done, the sPAPR machine should find at least one + * matching context always. + */ + if (count == 0) { + qemu_log_mask(LOG_GUEST_ERROR, "XIVE: NVT %x/%x is not dispatched\n", + nvt_blk, nvt_idx); + } + + return count; +} + int spapr_get_vcpu_id(PowerPCCPU *cpu) { return cpu->vcpu_id; @@ -4398,6 +4429,7 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data) PPCVirtualHypervisorClass *vhc = PPC_VIRTUAL_HYPERVISOR_CLASS(oc); XICSFabricClass *xic = XICS_FABRIC_CLASS(oc); InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc); + XiveFabricClass *xfc = XIVE_FABRIC_CLASS(oc); mc->desc = "pSeries Logical Partition (PAPR compliant)"; mc->ignore_boot_device_suffixes = true; @@ -4456,6 +4488,7 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data) */ mc->numa_mem_align_shift = 28; mc->numa_mem_supported = true; + xfc->match_nvt = spapr_xive_match_nvt; smc->default_caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_OFF; smc->default_caps.caps[SPAPR_CAP_VSX] = SPAPR_CAP_ON; @@ -4488,6 +4521,7 @@ static const TypeInfo spapr_machine_info = { { TYPE_PPC_VIRTUAL_HYPERVISOR }, { TYPE_XICS_FABRIC }, { TYPE_INTERRUPT_STATS_PROVIDER }, + { TYPE_XIVE_FABRIC }, { } }, }; diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c index ff3df0bbd8cf..ff824d950f05 100644 --- a/hw/ppc/spapr_irq.c +++ b/hw/ppc/spapr_irq.c @@ -262,6 +262,7 @@ SpaprIrq spapr_irq_xics = { .set_irq = spapr_irq_set_irq_xics, .get_nodename = spapr_irq_get_nodename_xics, .init_kvm = spapr_irq_init_kvm_xics, + .match_nvt = NULL, /* should not be used */ }; /* @@ -411,6 +412,18 @@ static void spapr_irq_init_kvm_xive(SpaprMachineState *spapr, Error **errp) } } +static int spapr_irq_match_nvt_xive(SpaprMachineState *spapr, uint8_t format, + uint8_t nvt_blk, uint32_t nvt_idx, + bool cam_ignore, uint8_t priority, + uint32_t logic_serv, XiveTCTXMatch *match) +{ + XivePresenter *xptr = XIVE_PRESENTER(spapr->xive); + XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr); + + return xpc->match_nvt(xptr, format, nvt_blk, nvt_idx, cam_ignore, + priority, logic_serv, match); +} + /* * XIVE uses the full IRQ number space. Set it to 8K to be compatible * with XICS. @@ -436,6 +449,7 @@ SpaprIrq spapr_irq_xive = { .set_irq = spapr_irq_set_irq_xive, .get_nodename = spapr_irq_get_nodename_xive, .init_kvm = spapr_irq_init_kvm_xive, + .match_nvt = spapr_irq_match_nvt_xive, }; /* @@ -590,6 +604,15 @@ static const char *spapr_irq_get_nodename_dual(SpaprMachineState *spapr) return spapr_irq_current(spapr)->get_nodename(spapr); } +static int spapr_irq_match_nvt_dual(SpaprMachineState *spapr, uint8_t format, + uint8_t nvt_blk, uint32_t nvt_idx, + bool cam_ignore, uint8_t priority, + uint32_t logic_serv, XiveTCTXMatch *match) +{ + return spapr_irq_current(spapr)->match_nvt(spapr, format, nvt_blk, nvt_idx, + cam_ignore, priority, logic_serv, match); +} + /* * Define values in sync with the XIVE and XICS backend */ @@ -613,6 +636,7 @@ SpaprIrq spapr_irq_dual = { .set_irq = spapr_irq_set_irq_dual, .get_nodename = spapr_irq_get_nodename_dual, .init_kvm = NULL, /* should not be used */ + .match_nvt = spapr_irq_match_nvt_dual, }; @@ -828,4 +852,5 @@ SpaprIrq spapr_irq_xics_legacy = { .set_irq = spapr_irq_set_irq_xics, .get_nodename = spapr_irq_get_nodename_xics, .init_kvm = spapr_irq_init_kvm_xics, + .match_nvt = NULL, /* should not be used */ }; -- 2.21.0