aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorNicholas Piggin <npiggin@gmail.com>2025-05-12 13:10:55 +1000
committerCédric Le Goater <clg@redhat.com>2025-07-21 08:03:53 +0200
commit6ef77843603b89b1e48a06ca0644e74e45297839 (patch)
tree9ca0122b13068352e5760a0da496a7a80169f6e4 /hw
parent6936d2f561759c00993217a424ddeb1554c5f1ff (diff)
downloadqemu-6ef77843603b89b1e48a06ca0644e74e45297839.zip
qemu-6ef77843603b89b1e48a06ca0644e74e45297839.tar.gz
qemu-6ef77843603b89b1e48a06ca0644e74e45297839.tar.bz2
ppc/xive2: Implement set_os_pending TIMA op
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 <npiggin@gmail.com> Reviewed-by: Glenn Miles <milesg@linux.ibm.com> Reviewed-by: Michael Kowal <kowal@linux.ibm.com> Tested-by: Gautam Menghani <gautam@linux.ibm.com> Link: https://lore.kernel.org/qemu-devel/20250512031100.439842-47-npiggin@gmail.com Signed-off-by: Cédric Le Goater <clg@redhat.com>
Diffstat (limited to 'hw')
-rw-r--r--hw/intc/xive.c2
-rw-r--r--hw/intc/xive2.c28
2 files changed, 30 insertions, 0 deletions
diff --git a/hw/intc/xive.c b/hw/intc/xive.c
index e7f77be..25cb387 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 23eb85b..f9eaea1 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];