]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
powerpc/xive: Use XIVE_BAD_IRQ instead of zero to catch non configured IPIs
authorCédric Le Goater <clg@kaod.org>
Fri, 6 Mar 2020 15:01:40 +0000 (16:01 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 17 Apr 2020 08:48:53 +0000 (10:48 +0200)
commit b1a504a6500df50e83b701b7946b34fce27ad8a3 upstream.

When a CPU is brought up, an IPI number is allocated and recorded
under the XIVE CPU structure. Invalid IPI numbers are tracked with
interrupt number 0x0.

On the PowerNV platform, the interrupt number space starts at 0x10 and
this works fine. However, on the sPAPR platform, it is possible to
allocate the interrupt number 0x0 and this raises an issue when CPU 0
is unplugged. The XIVE spapr driver tracks allocated interrupt numbers
in a bitmask and it is not correctly updated when interrupt number 0x0
is freed. It stays allocated and it is then impossible to reallocate.

Fix by using the XIVE_BAD_IRQ value instead of zero on both platforms.

Reported-by: David Gibson <david@gibson.dropbear.id.au>
Fixes: eac1e731b59e ("powerpc/xive: guest exploitation of the XIVE interrupt controller")
Cc: stable@vger.kernel.org # v4.14+
Signed-off-by: Cédric Le Goater <clg@kaod.org>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Tested-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20200306150143.5551-2-clg@kaod.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
arch/powerpc/sysdev/xive/common.c
arch/powerpc/sysdev/xive/native.c
arch/powerpc/sysdev/xive/spapr.c
arch/powerpc/sysdev/xive/xive-internal.h

index 3c939b9de488ec21c60ee9d32ef2eb6a16a5ccd8..1c31a08cdd54584250b64b14d759c6285b1e9e2c 100644 (file)
@@ -72,13 +72,6 @@ static u32 xive_ipi_irq;
 /* Xive state for each CPU */
 static DEFINE_PER_CPU(struct xive_cpu *, xive_cpu);
 
-/*
- * A "disabled" interrupt should never fire, to catch problems
- * we set its logical number to this
- */
-#define XIVE_BAD_IRQ           0x7fffffff
-#define XIVE_MAX_IRQ           (XIVE_BAD_IRQ - 1)
-
 /* An invalid CPU target */
 #define XIVE_INVALID_TARGET    (-1)
 
@@ -1074,7 +1067,7 @@ static int xive_setup_cpu_ipi(unsigned int cpu)
        xc = per_cpu(xive_cpu, cpu);
 
        /* Check if we are already setup */
-       if (xc->hw_ipi != 0)
+       if (xc->hw_ipi != XIVE_BAD_IRQ)
                return 0;
 
        /* Grab an IPI from the backend, this will populate xc->hw_ipi */
@@ -1111,7 +1104,7 @@ static void xive_cleanup_cpu_ipi(unsigned int cpu, struct xive_cpu *xc)
        /* Disable the IPI and free the IRQ data */
 
        /* Already cleaned up ? */
-       if (xc->hw_ipi == 0)
+       if (xc->hw_ipi == XIVE_BAD_IRQ)
                return;
 
        /* Mask the IPI */
@@ -1267,6 +1260,7 @@ static int xive_prepare_cpu(unsigned int cpu)
                if (np)
                        xc->chip_id = of_get_ibm_chip_id(np);
                of_node_put(np);
+               xc->hw_ipi = XIVE_BAD_IRQ;
 
                per_cpu(xive_cpu, cpu) = xc;
        }
index 6d5b2802245285a700924258dea315b7c3629a44..cb1f51ad48e40a3b62dc673aa5a35d17622d2f32 100644 (file)
@@ -311,7 +311,7 @@ static void xive_native_put_ipi(unsigned int cpu, struct xive_cpu *xc)
        s64 rc;
 
        /* Free the IPI */
-       if (!xc->hw_ipi)
+       if (xc->hw_ipi == XIVE_BAD_IRQ)
                return;
        for (;;) {
                rc = opal_xive_free_irq(xc->hw_ipi);
@@ -319,7 +319,7 @@ static void xive_native_put_ipi(unsigned int cpu, struct xive_cpu *xc)
                        msleep(OPAL_BUSY_DELAY_MS);
                        continue;
                }
-               xc->hw_ipi = 0;
+               xc->hw_ipi = XIVE_BAD_IRQ;
                break;
        }
 }
index e3ebf64693929f64da6248495a0297e980bcc1c6..5566bbc86f4afda058fc7ce77446baf11c2b07d7 100644 (file)
@@ -509,11 +509,11 @@ static int xive_spapr_get_ipi(unsigned int cpu, struct xive_cpu *xc)
 
 static void xive_spapr_put_ipi(unsigned int cpu, struct xive_cpu *xc)
 {
-       if (!xc->hw_ipi)
+       if (xc->hw_ipi == XIVE_BAD_IRQ)
                return;
 
        xive_irq_bitmap_free(xc->hw_ipi);
-       xc->hw_ipi = 0;
+       xc->hw_ipi = XIVE_BAD_IRQ;
 }
 #endif /* CONFIG_SMP */
 
index f34abed0c05fd3064bf0a2c45fb193b49079283f..48808dbb25dce60df08cf38ae7456619338c26cb 100644 (file)
@@ -9,6 +9,13 @@
 #ifndef __XIVE_INTERNAL_H
 #define __XIVE_INTERNAL_H
 
+/*
+ * A "disabled" interrupt should never fire, to catch problems
+ * we set its logical number to this
+ */
+#define XIVE_BAD_IRQ           0x7fffffff
+#define XIVE_MAX_IRQ           (XIVE_BAD_IRQ - 1)
+
 /* Each CPU carry one of these with various per-CPU state */
 struct xive_cpu {
 #ifdef CONFIG_SMP