powerpc/xive: Fix dump of XIVE interrupt under pseries
authorCédric Le Goater <clg@kaod.org>
Wed, 14 Aug 2019 15:47:53 +0000 (17:47 +0200)
committerMichael Ellerman <mpe@ellerman.id.au>
Mon, 19 Aug 2019 03:20:24 +0000 (13:20 +1000)
The xmon 'dxi' command calls OPAL to query the XIVE configuration of a
interrupt. This can only be done on baremetal (PowerNV) and it will
crash a pseries machine.

Introduce a new XIVE get_irq_config() operation which implements a
different query depending on the platform, PowerNV or pseries, and
modify xmon to use a top level wrapper.

Signed-off-by: Cédric Le Goater <clg@kaod.org>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20190814154754.23682-3-clg@kaod.org
arch/powerpc/include/asm/xive.h
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
arch/powerpc/xmon/xmon.c

index efb0e597b272554abeae16aa4b2c0450078542a5..967d6ab3c97734f711d76e8e791e9250142d05bf 100644 (file)
@@ -99,6 +99,8 @@ extern void xive_flush_interrupt(void);
 
 /* xmon hook */
 extern void xmon_xive_do_dump(int cpu);
+extern int xmon_xive_get_irq_config(u32 irq, u32 *target, u8 *prio,
+                                   u32 *sw_irq);
 
 /* APIs used by KVM */
 extern u32 xive_native_default_eq_shift(void);
index 6b973b7cdd8a9a34d8b4ad78f45227fe997b5737..f75a660365e5a11cb2b8e8a60da95de1458ee2b6 100644 (file)
@@ -257,6 +257,13 @@ notrace void xmon_xive_do_dump(int cpu)
        }
 #endif
 }
+
+int xmon_xive_get_irq_config(u32 irq, u32 *target, u8 *prio,
+                            u32 *sw_irq)
+{
+       return xive_ops->get_irq_config(irq, target, prio, sw_irq);
+}
+
 #endif /* CONFIG_XMON */
 
 static unsigned int xive_get_irq(void)
index 2f26b74f6cfa66093b4e8aeb4a0cca6d257a154a..4b61e44f0171a7d8c0af05a5d1ada933068f1175 100644 (file)
@@ -111,6 +111,20 @@ int xive_native_configure_irq(u32 hw_irq, u32 target, u8 prio, u32 sw_irq)
 }
 EXPORT_SYMBOL_GPL(xive_native_configure_irq);
 
+static int xive_native_get_irq_config(u32 hw_irq, u32 *target, u8 *prio,
+                                     u32 *sw_irq)
+{
+       s64 rc;
+       __be64 vp;
+       __be32 lirq;
+
+       rc = opal_xive_get_irq_config(hw_irq, &vp, prio, &lirq);
+
+       *target = be64_to_cpu(vp);
+       *sw_irq = be32_to_cpu(lirq);
+
+       return rc == 0 ? 0 : -ENXIO;
+}
 
 /* This can be called multiple time to change a queue configuration */
 int xive_native_configure_queue(u32 vp_id, struct xive_q *q, u8 prio,
@@ -442,6 +456,7 @@ EXPORT_SYMBOL_GPL(xive_native_sync_queue);
 static const struct xive_ops xive_native_ops = {
        .populate_irq_data      = xive_native_populate_irq_data,
        .configure_irq          = xive_native_configure_irq,
+       .get_irq_config         = xive_native_get_irq_config,
        .setup_queue            = xive_native_setup_queue,
        .cleanup_queue          = xive_native_cleanup_queue,
        .match                  = xive_native_match,
index 52198131c75ee1e9b22c2f4eba07eca3d3d3a3e3..33c10749edec993e3cd7fcdcf6102b5e3e6e8575 100644 (file)
@@ -215,6 +215,38 @@ static long plpar_int_set_source_config(unsigned long flags,
        return 0;
 }
 
+static long plpar_int_get_source_config(unsigned long flags,
+                                       unsigned long lisn,
+                                       unsigned long *target,
+                                       unsigned long *prio,
+                                       unsigned long *sw_irq)
+{
+       unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
+       long rc;
+
+       pr_devel("H_INT_GET_SOURCE_CONFIG flags=%lx lisn=%lx\n", flags, lisn);
+
+       do {
+               rc = plpar_hcall(H_INT_GET_SOURCE_CONFIG, retbuf, flags, lisn,
+                                target, prio, sw_irq);
+       } while (plpar_busy_delay(rc));
+
+       if (rc) {
+               pr_err("H_INT_GET_SOURCE_CONFIG lisn=%ld failed %ld\n",
+                      lisn, rc);
+               return rc;
+       }
+
+       *target = retbuf[0];
+       *prio   = retbuf[1];
+       *sw_irq = retbuf[2];
+
+       pr_devel("H_INT_GET_SOURCE_CONFIG target=%lx prio=%lx sw_irq=%lx\n",
+               retbuf[0], retbuf[1], retbuf[2]);
+
+       return 0;
+}
+
 static long plpar_int_get_queue_info(unsigned long flags,
                                     unsigned long target,
                                     unsigned long priority,
@@ -398,6 +430,24 @@ static int xive_spapr_configure_irq(u32 hw_irq, u32 target, u8 prio, u32 sw_irq)
        return rc == 0 ? 0 : -ENXIO;
 }
 
+static int xive_spapr_get_irq_config(u32 hw_irq, u32 *target, u8 *prio,
+                                    u32 *sw_irq)
+{
+       long rc;
+       unsigned long h_target;
+       unsigned long h_prio;
+       unsigned long h_sw_irq;
+
+       rc = plpar_int_get_source_config(0, hw_irq, &h_target, &h_prio,
+                                        &h_sw_irq);
+
+       *target = h_target;
+       *prio = h_prio;
+       *sw_irq = h_sw_irq;
+
+       return rc == 0 ? 0 : -ENXIO;
+}
+
 /* This can be called multiple time to change a queue configuration */
 static int xive_spapr_configure_queue(u32 target, struct xive_q *q, u8 prio,
                                   __be32 *qpage, u32 order)
@@ -590,6 +640,7 @@ static void xive_spapr_sync_source(u32 hw_irq)
 static const struct xive_ops xive_spapr_ops = {
        .populate_irq_data      = xive_spapr_populate_irq_data,
        .configure_irq          = xive_spapr_configure_irq,
+       .get_irq_config         = xive_spapr_get_irq_config,
        .setup_queue            = xive_spapr_setup_queue,
        .cleanup_queue          = xive_spapr_cleanup_queue,
        .match                  = xive_spapr_match,
index 211725dbf364ca6bcda6f615969af6e3dbac2c70..59cd366e7933a7233cc63a32daf3a04a5426ad4d 100644 (file)
@@ -33,6 +33,8 @@ struct xive_cpu {
 struct xive_ops {
        int     (*populate_irq_data)(u32 hw_irq, struct xive_irq_data *data);
        int     (*configure_irq)(u32 hw_irq, u32 target, u8 prio, u32 sw_irq);
+       int     (*get_irq_config)(u32 hw_irq, u32 *target, u8 *prio,
+                                 u32 *sw_irq);
        int     (*setup_queue)(unsigned int cpu, struct xive_cpu *xc, u8 prio);
        void    (*cleanup_queue)(unsigned int cpu, struct xive_cpu *xc, u8 prio);
        void    (*setup_cpu)(unsigned int cpu, struct xive_cpu *xc);
index 25d4adccf750f1fa74b28d37af1789c634866964..4ea53e05053f74ae975d6560c801cae839467964 100644 (file)
@@ -2574,14 +2574,14 @@ static void dump_all_xives(void)
 
 static void dump_one_xive_irq(u32 num)
 {
-       s64 rc;
-       __be64 vp;
+       int rc;
+       u32 target;
        u8 prio;
-       __be32 lirq;
+       u32 lirq;
 
-       rc = opal_xive_get_irq_config(num, &vp, &prio, &lirq);
-       xmon_printf("IRQ 0x%x config: vp=0x%llx prio=%d lirq=0x%x (rc=%lld)\n",
-                   num, be64_to_cpu(vp), prio, be32_to_cpu(lirq), rc);
+       rc = xmon_xive_get_irq_config(num, &target, &prio, &lirq);
+       xmon_printf("IRQ 0x%08x : target=0x%x prio=%d lirq=0x%x (rc=%d)\n",
+                   num, target, prio, lirq, rc);
 }
 
 static void dump_xives(void)