On Mon May 12, 2025 at 1:10 PM AEST, Nicholas Piggin wrote: > From: Glenn Miles <mil...@linux.ibm.com> > > Booting AIX in a PowerVM partition requires the use of the "Acknowledge > O/S Interrupt to even O/S reporting line" special operation provided by > the IBM XIVE interrupt controller. This operation is invoked by writing > a byte (data is irrelevant) to offset 0xC10 of the Thread Interrupt > Management Area (TIMA). It can be used by software to notify the XIVE > logic that the interrupt was received.
Reviewed-by: Nicholas Piggin <npig...@gmail.com> > > Signed-off-by: Glenn Miles <mil...@linux.ibm.com> > --- > hw/intc/xive.c | 8 ++++--- > hw/intc/xive2.c | 50 ++++++++++++++++++++++++++++++++++++++++++ > include/hw/ppc/xive.h | 1 + > include/hw/ppc/xive2.h | 3 ++- > 4 files changed, 58 insertions(+), 4 deletions(-) > > diff --git a/hw/intc/xive.c b/hw/intc/xive.c > index 7461dbecb8..9ec1193dfc 100644 > --- a/hw/intc/xive.c > +++ b/hw/intc/xive.c > @@ -80,7 +80,7 @@ static qemu_irq xive_tctx_output(XiveTCTX *tctx, uint8_t > ring) > } > } > > -static uint64_t xive_tctx_accept(XiveTCTX *tctx, uint8_t ring) > +uint64_t xive_tctx_accept(XiveTCTX *tctx, uint8_t ring) > { > uint8_t *regs = &tctx->regs[ring]; > uint8_t nsr = regs[TM_NSR]; > @@ -340,14 +340,14 @@ static uint64_t xive_tm_vt_poll(XivePresenter *xptr, > XiveTCTX *tctx, > > static const uint8_t xive_tm_hw_view[] = { > 3, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 0, 0, 0, /* QW-0 User */ > - 3, 3, 3, 3, 3, 3, 0, 2, 3, 3, 3, 3, 0, 0, 0, 0, /* QW-1 OS */ > + 3, 3, 3, 3, 3, 3, 0, 2, 3, 3, 3, 3, 0, 0, 0, 3, /* QW-1 OS */ > 0, 0, 3, 3, 0, 3, 3, 0, 3, 3, 3, 3, 0, 0, 0, 0, /* QW-2 POOL */ > 3, 3, 3, 3, 0, 3, 0, 2, 3, 0, 0, 3, 3, 3, 3, 0, /* QW-3 PHYS */ > }; > > static const uint8_t xive_tm_hv_view[] = { > 3, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 0, 0, 0, /* QW-0 User */ > - 3, 3, 3, 3, 3, 3, 0, 2, 3, 3, 3, 3, 0, 0, 0, 0, /* QW-1 OS */ > + 3, 3, 3, 3, 3, 3, 0, 2, 3, 3, 3, 3, 0, 0, 0, 3, /* QW-1 OS */ > 0, 0, 3, 3, 0, 3, 3, 0, 0, 3, 3, 3, 0, 0, 0, 0, /* QW-2 POOL */ > 3, 3, 3, 3, 0, 3, 0, 2, 3, 0, 0, 3, 0, 0, 0, 0, /* QW-3 PHYS */ > }; > @@ -718,6 +718,8 @@ static const XiveTmOp xive2_tm_operations[] = { > xive_tm_pull_phys_ctx }, > { XIVE_TM_HV_PAGE, TM_SPC_PULL_PHYS_CTX_OL, 1, > xive2_tm_pull_phys_ctx_ol, > NULL }, > + { XIVE_TM_OS_PAGE, TM_SPC_ACK_OS_EL, 1, xive2_tm_ack_os_el, > + NULL }, > }; > > static const XiveTmOp *xive_tm_find_op(XivePresenter *xptr, hwaddr offset, > diff --git a/hw/intc/xive2.c b/hw/intc/xive2.c > index ec4b9320b4..68be138335 100644 > --- a/hw/intc/xive2.c > +++ b/hw/intc/xive2.c > @@ -1009,6 +1009,56 @@ static int xive2_tctx_get_nvp_indexes(XiveTCTX *tctx, > uint8_t ring, > return 0; > } > > +static void xive2_tctx_accept_el(XivePresenter *xptr, XiveTCTX *tctx, > + uint8_t ring, uint8_t cl_ring) > +{ > + uint64_t rd; > + Xive2Router *xrtr = XIVE2_ROUTER(xptr); > + uint32_t nvp_blk, nvp_idx, xive2_cfg; > + Xive2Nvp nvp; > + uint64_t phys_addr; > + uint8_t OGen = 0; > + > + xive2_tctx_get_nvp_indexes(tctx, cl_ring, &nvp_blk, &nvp_idx); > + > + if (xive2_router_get_nvp(xrtr, (uint8_t)nvp_blk, nvp_idx, &nvp)) { > + qemu_log_mask(LOG_GUEST_ERROR, "XIVE: No NVP %x/%x\n", > + nvp_blk, nvp_idx); > + return; > + } > + > + if (!xive2_nvp_is_valid(&nvp)) { > + qemu_log_mask(LOG_GUEST_ERROR, "XIVE: invalid NVP %x/%x\n", > + nvp_blk, nvp_idx); > + return; > + } > + > + > + rd = xive_tctx_accept(tctx, ring); > + > + if (ring == TM_QW1_OS) { > + OGen = tctx->regs[ring + TM_OGEN]; > + } > + xive2_cfg = xive2_router_get_config(xrtr); > + phys_addr = xive2_nvp_reporting_addr(&nvp); > + uint8_t report_data[REPORT_LINE_GEN1_SIZE]; > + memset(report_data, 0xff, sizeof(report_data)); > + if ((OGen == 1) || (xive2_cfg & XIVE2_GEN1_TIMA_OS)) { > + report_data[8] = (rd >> 8) & 0xff; > + report_data[9] = rd & 0xff; > + } else { > + report_data[0] = (rd >> 8) & 0xff; > + report_data[1] = rd & 0xff; > + } > + cpu_physical_memory_write(phys_addr, report_data, REPORT_LINE_GEN1_SIZE); > +} > + > +void xive2_tm_ack_os_el(XivePresenter *xptr, XiveTCTX *tctx, > + hwaddr offset, uint64_t value, unsigned size) > +{ > + xive2_tctx_accept_el(xptr, tctx, TM_QW1_OS, TM_QW1_OS); > +} > + > static void xive2_tctx_set_cppr(XiveTCTX *tctx, uint8_t ring, uint8_t cppr) > { > uint8_t *regs = &tctx->regs[ring]; > diff --git a/include/hw/ppc/xive.h b/include/hw/ppc/xive.h > index 28f0f1b79a..46d05d74fb 100644 > --- a/include/hw/ppc/xive.h > +++ b/include/hw/ppc/xive.h > @@ -561,6 +561,7 @@ void xive_tctx_pipr_update(XiveTCTX *tctx, uint8_t ring, > uint8_t priority, > uint8_t group_level); > void xive_tctx_reset_signal(XiveTCTX *tctx, uint8_t ring); > void xive_tctx_notify(XiveTCTX *tctx, uint8_t ring, uint8_t group_level); > +uint64_t xive_tctx_accept(XiveTCTX *tctx, uint8_t ring); > > /* > * KVM XIVE device helpers > diff --git a/include/hw/ppc/xive2.h b/include/hw/ppc/xive2.h > index 760b94a962..ff02ce2549 100644 > --- a/include/hw/ppc/xive2.h > +++ b/include/hw/ppc/xive2.h > @@ -142,5 +142,6 @@ void xive2_tm_set_hv_target(XivePresenter *xptr, XiveTCTX > *tctx, > hwaddr offset, uint64_t value, unsigned size); > void xive2_tm_pull_phys_ctx_ol(XivePresenter *xptr, XiveTCTX *tctx, > hwaddr offset, uint64_t value, unsigned size); > - > +void xive2_tm_ack_os_el(XivePresenter *xptr, XiveTCTX *tctx, > + hwaddr offset, uint64_t value, unsigned size); > #endif /* PPC_XIVE2_H */