diff options
Diffstat (limited to 'hw/intc')
-rw-r--r-- | hw/intc/pnv_xive.c | 37 | ||||
-rw-r--r-- | hw/intc/pnv_xive2.c | 37 | ||||
-rw-r--r-- | hw/intc/spapr_xive.c | 25 | ||||
-rw-r--r-- | hw/intc/xive.c | 48 | ||||
-rw-r--r-- | hw/intc/xive2.c | 42 |
5 files changed, 175 insertions, 14 deletions
diff --git a/hw/intc/pnv_xive.c b/hw/intc/pnv_xive.c index 621b20a03f..1ce1d7b07d 100644 --- a/hw/intc/pnv_xive.c +++ b/hw/intc/pnv_xive.c @@ -403,6 +403,34 @@ 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 pnv_xive_get_pq(XiveRouter *xrtr, uint8_t blk, uint32_t idx, + uint8_t *pq) +{ + PnvXive *xive = PNV_XIVE(xrtr); + + if (pnv_xive_block_id(xive) != blk) { + xive_error(xive, "VST: EAS %x is remote !?", XIVE_EAS(blk, idx)); + return -1; + } + + *pq = xive_source_esb_get(&xive->ipi_source, idx); + return 0; +} + +static int pnv_xive_set_pq(XiveRouter *xrtr, uint8_t blk, uint32_t idx, + uint8_t *pq) +{ + PnvXive *xive = PNV_XIVE(xrtr); + + if (pnv_xive_block_id(xive) != blk) { + xive_error(xive, "VST: EAS %x is remote !?", XIVE_EAS(blk, idx)); + return -1; + } + + *pq = xive_source_esb_set(&xive->ipi_source, idx, *pq); + return 0; +} + /* * One bit per thread id. The first register PC_THREAD_EN_REG0 covers * the first cores 0-15 (normal) of the chip or 0-7 (fused). The @@ -499,12 +527,12 @@ static PnvXive *pnv_xive_tm_get_xive(PowerPCCPU *cpu) * event notification to the Router. This is required on a multichip * system. */ -static void pnv_xive_notify(XiveNotifier *xn, uint32_t srcno) +static void pnv_xive_notify(XiveNotifier *xn, uint32_t srcno, bool pq_checked) { PnvXive *xive = PNV_XIVE(xn); uint8_t blk = pnv_xive_block_id(xive); - xive_router_notify(xn, XIVE_EAS(blk, srcno)); + xive_router_notify(xn, XIVE_EAS(blk, srcno), pq_checked); } /* @@ -1351,7 +1379,8 @@ static void pnv_xive_ic_hw_trigger(PnvXive *xive, hwaddr addr, uint64_t val) blk = XIVE_EAS_BLOCK(val); idx = XIVE_EAS_INDEX(val); - xive_router_notify(XIVE_NOTIFIER(xive), XIVE_EAS(blk, idx)); + xive_router_notify(XIVE_NOTIFIER(xive), XIVE_EAS(blk, idx), + !!(val & XIVE_TRIGGER_PQ)); } static void pnv_xive_ic_notify_write(void *opaque, hwaddr addr, uint64_t val, @@ -1971,6 +2000,8 @@ static void pnv_xive_class_init(ObjectClass *klass, void *data) device_class_set_props(dc, pnv_xive_properties); xrc->get_eas = pnv_xive_get_eas; + xrc->get_pq = pnv_xive_get_pq; + xrc->set_pq = pnv_xive_set_pq; xrc->get_end = pnv_xive_get_end; xrc->write_end = pnv_xive_write_end; xrc->get_nvt = pnv_xive_get_nvt; diff --git a/hw/intc/pnv_xive2.c b/hw/intc/pnv_xive2.c index 35a7f7ae4d..1fa89c7792 100644 --- a/hw/intc/pnv_xive2.c +++ b/hw/intc/pnv_xive2.c @@ -285,6 +285,34 @@ static int pnv_xive2_vst_write(PnvXive2 *xive, uint32_t type, uint8_t blk, return 0; } +static int pnv_xive2_get_pq(Xive2Router *xrtr, uint8_t blk, uint32_t idx, + uint8_t *pq) +{ + PnvXive2 *xive = PNV_XIVE2(xrtr); + + if (pnv_xive2_block_id(xive) != blk) { + xive2_error(xive, "VST: EAS %x is remote !?", XIVE_EAS(blk, idx)); + return -1; + } + + *pq = xive_source_esb_get(&xive->ipi_source, idx); + return 0; +} + +static int pnv_xive2_set_pq(Xive2Router *xrtr, uint8_t blk, uint32_t idx, + uint8_t *pq) +{ + PnvXive2 *xive = PNV_XIVE2(xrtr); + + if (pnv_xive2_block_id(xive) != blk) { + xive2_error(xive, "VST: EAS %x is remote !?", XIVE_EAS(blk, idx)); + return -1; + } + + *pq = xive_source_esb_set(&xive->ipi_source, idx, *pq); + return 0; +} + static int pnv_xive2_get_end(Xive2Router *xrtr, uint8_t blk, uint32_t idx, Xive2End *end) { @@ -487,12 +515,12 @@ static PnvXive2 *pnv_xive2_tm_get_xive(PowerPCCPU *cpu) * source interrupt number before forwarding the source event * notification to the Router. This is required on a multichip system. */ -static void pnv_xive2_notify(XiveNotifier *xn, uint32_t srcno) +static void pnv_xive2_notify(XiveNotifier *xn, uint32_t srcno, bool pq_checked) { PnvXive2 *xive = PNV_XIVE2(xn); uint8_t blk = pnv_xive2_block_id(xive); - xive2_router_notify(xn, XIVE_EAS(blk, srcno)); + xive2_router_notify(xn, XIVE_EAS(blk, srcno), pq_checked); } /* @@ -1381,7 +1409,8 @@ static void pnv_xive2_ic_hw_trigger(PnvXive2 *xive, hwaddr addr, blk = XIVE_EAS_BLOCK(val); idx = XIVE_EAS_INDEX(val); - xive2_router_notify(XIVE_NOTIFIER(xive), XIVE_EAS(blk, idx)); + xive2_router_notify(XIVE_NOTIFIER(xive), XIVE_EAS(blk, idx), + !!(val & XIVE_TRIGGER_PQ)); } static void pnv_xive2_ic_notify_write(void *opaque, hwaddr offset, @@ -1880,6 +1909,8 @@ static void pnv_xive2_class_init(ObjectClass *klass, void *data) device_class_set_props(dc, pnv_xive2_properties); xrc->get_eas = pnv_xive2_get_eas; + xrc->get_pq = pnv_xive2_get_pq; + xrc->set_pq = pnv_xive2_set_pq; xrc->get_end = pnv_xive2_get_end; xrc->write_end = pnv_xive2_write_end; xrc->get_nvp = pnv_xive2_get_nvp; diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c index eae95c716f..dc641cc604 100644 --- a/hw/intc/spapr_xive.c +++ b/hw/intc/spapr_xive.c @@ -480,6 +480,29 @@ static uint8_t spapr_xive_get_block_id(XiveRouter *xrtr) return SPAPR_XIVE_BLOCK_ID; } +static int spapr_xive_get_pq(XiveRouter *xrtr, uint8_t blk, uint32_t idx, + uint8_t *pq) +{ + SpaprXive *xive = SPAPR_XIVE(xrtr); + + assert(SPAPR_XIVE_BLOCK_ID == blk); + + *pq = xive_source_esb_get(&xive->source, idx); + return 0; +} + +static int spapr_xive_set_pq(XiveRouter *xrtr, uint8_t blk, uint32_t idx, + uint8_t *pq) +{ + SpaprXive *xive = SPAPR_XIVE(xrtr); + + assert(SPAPR_XIVE_BLOCK_ID == blk); + + *pq = xive_source_esb_set(&xive->source, idx, *pq); + return 0; +} + + static const VMStateDescription vmstate_spapr_xive_end = { .name = TYPE_SPAPR_XIVE "/end", .version_id = 1, @@ -788,6 +811,8 @@ static void spapr_xive_class_init(ObjectClass *klass, void *data) dc->vmsd = &vmstate_spapr_xive; xrc->get_eas = spapr_xive_get_eas; + xrc->get_pq = spapr_xive_get_pq; + xrc->set_pq = spapr_xive_set_pq; xrc->get_end = spapr_xive_get_end; xrc->write_end = spapr_xive_write_end; xrc->get_nvt = spapr_xive_get_nvt; diff --git a/hw/intc/xive.c b/hw/intc/xive.c index 0d98b9539c..deb0db21e0 100644 --- a/hw/intc/xive.c +++ b/hw/intc/xive.c @@ -938,7 +938,7 @@ static void xive_source_notify(XiveSource *xsrc, int srcno) XiveNotifierClass *xnc = XIVE_NOTIFIER_GET_CLASS(xsrc->xive); if (xnc->notify) { - xnc->notify(xsrc->xive, srcno); + xnc->notify(xsrc->xive, srcno, true); } } @@ -1370,6 +1370,24 @@ int xive_router_get_eas(XiveRouter *xrtr, uint8_t eas_blk, uint32_t eas_idx, return xrc->get_eas(xrtr, eas_blk, eas_idx, eas); } +static +int xive_router_get_pq(XiveRouter *xrtr, uint8_t eas_blk, uint32_t eas_idx, + uint8_t *pq) +{ + XiveRouterClass *xrc = XIVE_ROUTER_GET_CLASS(xrtr); + + return xrc->get_pq(xrtr, eas_blk, eas_idx, pq); +} + +static +int xive_router_set_pq(XiveRouter *xrtr, uint8_t eas_blk, uint32_t eas_idx, + uint8_t *pq) +{ + XiveRouterClass *xrc = XIVE_ROUTER_GET_CLASS(xrtr); + + return xrc->set_pq(xrtr, eas_blk, eas_idx, pq); +} + int xive_router_get_end(XiveRouter *xrtr, uint8_t end_blk, uint32_t end_idx, XiveEND *end) { @@ -1721,7 +1739,7 @@ do_escalation: xive_get_field32(END_W5_ESC_END_DATA, end.w5)); } -void xive_router_notify(XiveNotifier *xn, uint32_t lisn) +void xive_router_notify(XiveNotifier *xn, uint32_t lisn, bool pq_checked) { XiveRouter *xrtr = XIVE_ROUTER(xn); uint8_t eas_blk = XIVE_EAS_BLOCK(lisn); @@ -1734,11 +1752,27 @@ void xive_router_notify(XiveNotifier *xn, uint32_t lisn) return; } - /* - * The IVRE checks the State Bit Cache at this point. We skip the - * SBC lookup because the state bits of the sources are modeled - * internally in QEMU. - */ + if (!pq_checked) { + bool notify; + uint8_t pq; + + /* PQ cache lookup */ + if (xive_router_get_pq(xrtr, eas_blk, eas_idx, &pq)) { + /* Set FIR */ + g_assert_not_reached(); + } + + notify = xive_esb_trigger(&pq); + + if (xive_router_set_pq(xrtr, eas_blk, eas_idx, &pq)) { + /* Set FIR */ + g_assert_not_reached(); + } + + if (!notify) { + return; + } + } if (!xive_eas_is_valid(&eas)) { qemu_log_mask(LOG_GUEST_ERROR, "XIVE: invalid LISN %x\n", lisn); diff --git a/hw/intc/xive2.c b/hw/intc/xive2.c index 2836bbdc83..3720e70422 100644 --- a/hw/intc/xive2.c +++ b/hw/intc/xive2.c @@ -171,6 +171,24 @@ int xive2_router_get_eas(Xive2Router *xrtr, uint8_t eas_blk, uint32_t eas_idx, return xrc->get_eas(xrtr, eas_blk, eas_idx, eas); } +static +int xive2_router_get_pq(Xive2Router *xrtr, uint8_t eas_blk, uint32_t eas_idx, + uint8_t *pq) +{ + Xive2RouterClass *xrc = XIVE2_ROUTER_GET_CLASS(xrtr); + + return xrc->get_pq(xrtr, eas_blk, eas_idx, pq); +} + +static +int xive2_router_set_pq(Xive2Router *xrtr, uint8_t eas_blk, uint32_t eas_idx, + uint8_t *pq) +{ + Xive2RouterClass *xrc = XIVE2_ROUTER_GET_CLASS(xrtr); + + return xrc->set_pq(xrtr, eas_blk, eas_idx, pq); +} + int xive2_router_get_end(Xive2Router *xrtr, uint8_t end_blk, uint32_t end_idx, Xive2End *end) { @@ -480,7 +498,7 @@ do_escalation: xive_get_field32(END2_W5_ESC_END_DATA, end.w5)); } -void xive2_router_notify(XiveNotifier *xn, uint32_t lisn) +void xive2_router_notify(XiveNotifier *xn, uint32_t lisn, bool pq_checked) { Xive2Router *xrtr = XIVE2_ROUTER(xn); uint8_t eas_blk = XIVE_EAS_BLOCK(lisn); @@ -493,6 +511,28 @@ void xive2_router_notify(XiveNotifier *xn, uint32_t lisn) return; } + if (!pq_checked) { + bool notify; + uint8_t pq; + + /* PQ cache lookup */ + if (xive2_router_get_pq(xrtr, eas_blk, eas_idx, &pq)) { + /* Set FIR */ + g_assert_not_reached(); + } + + notify = xive_esb_trigger(&pq); + + if (xive2_router_set_pq(xrtr, eas_blk, eas_idx, &pq)) { + /* Set FIR */ + g_assert_not_reached(); + } + + if (!notify) { + return; + } + } + if (!xive2_eas_is_valid(&eas)) { qemu_log_mask(LOG_GUEST_ERROR, "XIVE: Invalid LISN %x\n", lisn); return; |