xive2 must take into account redistribution of group interrupts if the VP directed priority exceeds the group interrupt priority after this operation. The xive1 code is not group aware so implement this for xive2.
Signed-off-by: Nicholas Piggin <npig...@gmail.com> --- hw/intc/xive.c | 2 ++ hw/intc/xive2.c | 28 ++++++++++++++++++++++++++++ include/hw/ppc/xive2.h | 2 ++ 3 files changed, 32 insertions(+) diff --git a/hw/intc/xive.c b/hw/intc/xive.c index 979031a587..dc64edf13d 100644 --- a/hw/intc/xive.c +++ b/hw/intc/xive.c @@ -747,6 +747,8 @@ static const XiveTmOp xive2_tm_operations[] = { /* MMIOs above 2K : special operations with side effects */ { XIVE_TM_OS_PAGE, TM_SPC_ACK_OS_REG, 2, true, false, NULL, xive_tm_ack_os_reg }, + { XIVE_TM_OS_PAGE, TM_SPC_SET_OS_PENDING, 1, true, false, + xive2_tm_set_os_pending, NULL }, { XIVE_TM_HV_PAGE, TM_SPC_PULL_OS_CTX_G2, 4, true, false, NULL, xive2_tm_pull_os_ctx }, { XIVE_TM_HV_PAGE, TM_SPC_PULL_OS_CTX, 4, true, false, diff --git a/hw/intc/xive2.c b/hw/intc/xive2.c index 392ac6077e..de1ccad685 100644 --- a/hw/intc/xive2.c +++ b/hw/intc/xive2.c @@ -1323,6 +1323,34 @@ void xive2_tm_set_os_cppr(XivePresenter *xptr, XiveTCTX *tctx, xive2_tctx_set_cppr(tctx, TM_QW1_OS, value & 0xff); } +/* + * Adjust the IPB to allow a CPU to process event queues of other + * priorities during one physical interrupt cycle. + */ +void xive2_tm_set_os_pending(XivePresenter *xptr, XiveTCTX *tctx, + hwaddr offset, uint64_t value, unsigned size) +{ + Xive2Router *xrtr = XIVE2_ROUTER(xptr); + uint8_t ring = TM_QW1_OS; + uint8_t *regs = &tctx->regs[ring]; + uint8_t priority = value & 0xff; + + /* + * XXX: should this simply set a bit in IPB and wait for it to be picked + * up next cycle, or is it supposed to present it now? We implement the + * latter here. + */ + regs[TM_IPB] |= xive_priority_to_ipb(priority); + if (xive_ipb_to_pipr(regs[TM_IPB]) >= regs[TM_PIPR]) { + return; + } + if (xive_nsr_indicates_group_exception(ring, regs[TM_NSR])) { + xive2_redistribute(xrtr, tctx, ring); + } + + xive_tctx_pipr_present(tctx, ring, priority, 0); +} + static void xive2_tctx_set_target(XiveTCTX *tctx, uint8_t ring, uint8_t target) { uint8_t *regs = &tctx->regs[ring]; diff --git a/include/hw/ppc/xive2.h b/include/hw/ppc/xive2.h index c1ab06a55a..45266c2a8b 100644 --- a/include/hw/ppc/xive2.h +++ b/include/hw/ppc/xive2.h @@ -130,6 +130,8 @@ void xive2_tm_set_hv_cppr(XivePresenter *xptr, XiveTCTX *tctx, hwaddr offset, uint64_t value, unsigned size); void xive2_tm_set_os_cppr(XivePresenter *xptr, XiveTCTX *tctx, hwaddr offset, uint64_t value, unsigned size); +void xive2_tm_set_os_pending(XivePresenter *xptr, XiveTCTX *tctx, + hwaddr offset, uint64_t value, unsigned size); void xive2_tm_push_os_ctx(XivePresenter *xptr, XiveTCTX *tctx, hwaddr offset, uint64_t value, unsigned size); uint64_t xive2_tm_pull_os_ctx(XivePresenter *xptr, XiveTCTX *tctx, -- 2.47.1