]> git.ipfire.org Git - thirdparty/qemu.git/commitdiff
ppc/xive2: Enable lower level contexts on VP push
authorNicholas Piggin <npiggin@gmail.com>
Mon, 12 May 2025 03:10:59 +0000 (13:10 +1000)
committerCédric Le Goater <clg@redhat.com>
Mon, 21 Jul 2025 06:03:53 +0000 (08:03 +0200)
When pushing a context, the lower-level context becomes valid if it
had V=1, and so on. Iterate lower level contexts and send them
pending interrupts if they become enabled.

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-51-npiggin@gmail.com
Signed-off-by: Cédric Le Goater <clg@redhat.com>
hw/intc/xive2.c

index c3c6871e91b35924e0c48c0c6fdc2b21ffa5b3b3..ee5fa261784978842c951b29d67f1547569fb463 100644 (file)
@@ -995,6 +995,12 @@ static void xive2_tm_push_ctx(XivePresenter *xptr, XiveTCTX *tctx,
     bool v;
     bool do_restore;
 
+    if (xive_ring_valid(tctx, ring)) {
+        qemu_log_mask(LOG_GUEST_ERROR, "XIVE: Attempt to push VP to enabled"
+                                       " ring 0x%02x\n", ring);
+        return;
+    }
+
     /* First update the thead context */
     switch (size) {
     case 1:
@@ -1021,19 +1027,32 @@ static void xive2_tm_push_ctx(XivePresenter *xptr, XiveTCTX *tctx,
     /* Check the interrupt pending bits */
     if (v) {
         Xive2Router *xrtr = XIVE2_ROUTER(xptr);
-        uint8_t *sig_regs = xive_tctx_signal_regs(tctx, ring);
-        uint8_t nsr = sig_regs[TM_NSR];
+        uint8_t cur_ring;
 
         xive2_tctx_restore_nvp(xrtr, tctx, ring,
                                nvp_blk, nvp_idx, do_restore);
 
-        if (xive_nsr_indicates_group_exception(ring, nsr)) {
-            /* redistribute precluded active grp interrupt */
-            g_assert(ring == TM_QW2_HV_POOL); /* PHYS ring has the interrupt */
-            xive2_redistribute(xrtr, tctx, xive_nsr_exception_ring(ring, nsr));
+        for (cur_ring = TM_QW1_OS; cur_ring <= ring;
+             cur_ring += XIVE_TM_RING_SIZE) {
+            uint8_t *sig_regs = xive_tctx_signal_regs(tctx, cur_ring);
+            uint8_t nsr = sig_regs[TM_NSR];
+
+            if (!xive_ring_valid(tctx, cur_ring)) {
+                continue;
+            }
+
+            if (cur_ring == TM_QW2_HV_POOL) {
+                if (xive_nsr_indicates_exception(cur_ring, nsr)) {
+                    g_assert(xive_nsr_exception_ring(cur_ring, nsr) ==
+                                                               TM_QW3_HV_PHYS);
+                    xive2_redistribute(xrtr, tctx,
+                                       xive_nsr_exception_ring(ring, nsr));
+                }
+                xive2_tctx_process_pending(tctx, TM_QW3_HV_PHYS);
+                break;
+            }
+            xive2_tctx_process_pending(tctx, cur_ring);
         }
-        xive2_tctx_process_pending(tctx, ring == TM_QW2_HV_POOL ?
-                                                 TM_QW3_HV_PHYS : ring);
     }
 }
 
@@ -1159,6 +1178,7 @@ static void xive2_tctx_process_pending(XiveTCTX *tctx, uint8_t sig_ring)
     int rc;
 
     g_assert(sig_ring == TM_QW3_HV_PHYS || sig_ring == TM_QW1_OS);
+    g_assert(sig_regs[TM_WORD2] & 0x80);
     g_assert(!xive_nsr_indicates_group_exception(sig_ring, sig_regs[TM_NSR]));
 
     /*