diff options
author | Cédric Le Goater <clg@kaod.org> | 2019-08-14 11:47:53 -0400 |
---|---|---|
committer | Michael Ellerman <mpe@ellerman.id.au> | 2019-08-18 23:20:24 -0400 |
commit | b4868ff55d082bc66b0c287a41e4888f6d3e5f87 (patch) | |
tree | 1433205cf4e23a07497bebeacac7ec7b599822ca | |
parent | c3e0dbd7f780a58c4695f1cd8fc8afde80376737 (diff) |
powerpc/xive: Fix dump of XIVE interrupt under pseries
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
-rw-r--r-- | arch/powerpc/include/asm/xive.h | 2 | ||||
-rw-r--r-- | arch/powerpc/sysdev/xive/common.c | 7 | ||||
-rw-r--r-- | arch/powerpc/sysdev/xive/native.c | 15 | ||||
-rw-r--r-- | arch/powerpc/sysdev/xive/spapr.c | 51 | ||||
-rw-r--r-- | arch/powerpc/sysdev/xive/xive-internal.h | 2 | ||||
-rw-r--r-- | arch/powerpc/xmon/xmon.c | 12 |
6 files changed, 83 insertions, 6 deletions
diff --git a/arch/powerpc/include/asm/xive.h b/arch/powerpc/include/asm/xive.h index efb0e597b272..967d6ab3c977 100644 --- a/arch/powerpc/include/asm/xive.h +++ b/arch/powerpc/include/asm/xive.h | |||
@@ -99,6 +99,8 @@ extern void xive_flush_interrupt(void); | |||
99 | 99 | ||
100 | /* xmon hook */ | 100 | /* xmon hook */ |
101 | extern void xmon_xive_do_dump(int cpu); | 101 | extern void xmon_xive_do_dump(int cpu); |
102 | extern int xmon_xive_get_irq_config(u32 irq, u32 *target, u8 *prio, | ||
103 | u32 *sw_irq); | ||
102 | 104 | ||
103 | /* APIs used by KVM */ | 105 | /* APIs used by KVM */ |
104 | extern u32 xive_native_default_eq_shift(void); | 106 | extern u32 xive_native_default_eq_shift(void); |
diff --git a/arch/powerpc/sysdev/xive/common.c b/arch/powerpc/sysdev/xive/common.c index 6b973b7cdd8a..f75a660365e5 100644 --- a/arch/powerpc/sysdev/xive/common.c +++ b/arch/powerpc/sysdev/xive/common.c | |||
@@ -257,6 +257,13 @@ notrace void xmon_xive_do_dump(int cpu) | |||
257 | } | 257 | } |
258 | #endif | 258 | #endif |
259 | } | 259 | } |
260 | |||
261 | int xmon_xive_get_irq_config(u32 irq, u32 *target, u8 *prio, | ||
262 | u32 *sw_irq) | ||
263 | { | ||
264 | return xive_ops->get_irq_config(irq, target, prio, sw_irq); | ||
265 | } | ||
266 | |||
260 | #endif /* CONFIG_XMON */ | 267 | #endif /* CONFIG_XMON */ |
261 | 268 | ||
262 | static unsigned int xive_get_irq(void) | 269 | static unsigned int xive_get_irq(void) |
diff --git a/arch/powerpc/sysdev/xive/native.c b/arch/powerpc/sysdev/xive/native.c index 2f26b74f6cfa..4b61e44f0171 100644 --- a/arch/powerpc/sysdev/xive/native.c +++ b/arch/powerpc/sysdev/xive/native.c | |||
@@ -111,6 +111,20 @@ int xive_native_configure_irq(u32 hw_irq, u32 target, u8 prio, u32 sw_irq) | |||
111 | } | 111 | } |
112 | EXPORT_SYMBOL_GPL(xive_native_configure_irq); | 112 | EXPORT_SYMBOL_GPL(xive_native_configure_irq); |
113 | 113 | ||
114 | static int xive_native_get_irq_config(u32 hw_irq, u32 *target, u8 *prio, | ||
115 | u32 *sw_irq) | ||
116 | { | ||
117 | s64 rc; | ||
118 | __be64 vp; | ||
119 | __be32 lirq; | ||
120 | |||
121 | rc = opal_xive_get_irq_config(hw_irq, &vp, prio, &lirq); | ||
122 | |||
123 | *target = be64_to_cpu(vp); | ||
124 | *sw_irq = be32_to_cpu(lirq); | ||
125 | |||
126 | return rc == 0 ? 0 : -ENXIO; | ||
127 | } | ||
114 | 128 | ||
115 | /* This can be called multiple time to change a queue configuration */ | 129 | /* This can be called multiple time to change a queue configuration */ |
116 | int xive_native_configure_queue(u32 vp_id, struct xive_q *q, u8 prio, | 130 | 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); | |||
442 | static const struct xive_ops xive_native_ops = { | 456 | static const struct xive_ops xive_native_ops = { |
443 | .populate_irq_data = xive_native_populate_irq_data, | 457 | .populate_irq_data = xive_native_populate_irq_data, |
444 | .configure_irq = xive_native_configure_irq, | 458 | .configure_irq = xive_native_configure_irq, |
459 | .get_irq_config = xive_native_get_irq_config, | ||
445 | .setup_queue = xive_native_setup_queue, | 460 | .setup_queue = xive_native_setup_queue, |
446 | .cleanup_queue = xive_native_cleanup_queue, | 461 | .cleanup_queue = xive_native_cleanup_queue, |
447 | .match = xive_native_match, | 462 | .match = xive_native_match, |
diff --git a/arch/powerpc/sysdev/xive/spapr.c b/arch/powerpc/sysdev/xive/spapr.c index 52198131c75e..33c10749edec 100644 --- a/arch/powerpc/sysdev/xive/spapr.c +++ b/arch/powerpc/sysdev/xive/spapr.c | |||
@@ -215,6 +215,38 @@ static long plpar_int_set_source_config(unsigned long flags, | |||
215 | return 0; | 215 | return 0; |
216 | } | 216 | } |
217 | 217 | ||
218 | static long plpar_int_get_source_config(unsigned long flags, | ||
219 | unsigned long lisn, | ||
220 | unsigned long *target, | ||
221 | unsigned long *prio, | ||
222 | unsigned long *sw_irq) | ||
223 | { | ||
224 | unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; | ||
225 | long rc; | ||
226 | |||
227 | pr_devel("H_INT_GET_SOURCE_CONFIG flags=%lx lisn=%lx\n", flags, lisn); | ||
228 | |||
229 | do { | ||
230 | rc = plpar_hcall(H_INT_GET_SOURCE_CONFIG, retbuf, flags, lisn, | ||
231 | target, prio, sw_irq); | ||
232 | } while (plpar_busy_delay(rc)); | ||
233 | |||
234 | if (rc) { | ||
235 | pr_err("H_INT_GET_SOURCE_CONFIG lisn=%ld failed %ld\n", | ||
236 | lisn, rc); | ||
237 | return rc; | ||
238 | } | ||
239 | |||
240 | *target = retbuf[0]; | ||
241 | *prio = retbuf[1]; | ||
242 | *sw_irq = retbuf[2]; | ||
243 | |||
244 | pr_devel("H_INT_GET_SOURCE_CONFIG target=%lx prio=%lx sw_irq=%lx\n", | ||
245 | retbuf[0], retbuf[1], retbuf[2]); | ||
246 | |||
247 | return 0; | ||
248 | } | ||
249 | |||
218 | static long plpar_int_get_queue_info(unsigned long flags, | 250 | static long plpar_int_get_queue_info(unsigned long flags, |
219 | unsigned long target, | 251 | unsigned long target, |
220 | unsigned long priority, | 252 | unsigned long priority, |
@@ -398,6 +430,24 @@ static int xive_spapr_configure_irq(u32 hw_irq, u32 target, u8 prio, u32 sw_irq) | |||
398 | return rc == 0 ? 0 : -ENXIO; | 430 | return rc == 0 ? 0 : -ENXIO; |
399 | } | 431 | } |
400 | 432 | ||
433 | static int xive_spapr_get_irq_config(u32 hw_irq, u32 *target, u8 *prio, | ||
434 | u32 *sw_irq) | ||
435 | { | ||
436 | long rc; | ||
437 | unsigned long h_target; | ||
438 | unsigned long h_prio; | ||
439 | unsigned long h_sw_irq; | ||
440 | |||
441 | rc = plpar_int_get_source_config(0, hw_irq, &h_target, &h_prio, | ||
442 | &h_sw_irq); | ||
443 | |||
444 | *target = h_target; | ||
445 | *prio = h_prio; | ||
446 | *sw_irq = h_sw_irq; | ||
447 | |||
448 | return rc == 0 ? 0 : -ENXIO; | ||
449 | } | ||
450 | |||
401 | /* This can be called multiple time to change a queue configuration */ | 451 | /* This can be called multiple time to change a queue configuration */ |
402 | static int xive_spapr_configure_queue(u32 target, struct xive_q *q, u8 prio, | 452 | static int xive_spapr_configure_queue(u32 target, struct xive_q *q, u8 prio, |
403 | __be32 *qpage, u32 order) | 453 | __be32 *qpage, u32 order) |
@@ -590,6 +640,7 @@ static void xive_spapr_sync_source(u32 hw_irq) | |||
590 | static const struct xive_ops xive_spapr_ops = { | 640 | static const struct xive_ops xive_spapr_ops = { |
591 | .populate_irq_data = xive_spapr_populate_irq_data, | 641 | .populate_irq_data = xive_spapr_populate_irq_data, |
592 | .configure_irq = xive_spapr_configure_irq, | 642 | .configure_irq = xive_spapr_configure_irq, |
643 | .get_irq_config = xive_spapr_get_irq_config, | ||
593 | .setup_queue = xive_spapr_setup_queue, | 644 | .setup_queue = xive_spapr_setup_queue, |
594 | .cleanup_queue = xive_spapr_cleanup_queue, | 645 | .cleanup_queue = xive_spapr_cleanup_queue, |
595 | .match = xive_spapr_match, | 646 | .match = xive_spapr_match, |
diff --git a/arch/powerpc/sysdev/xive/xive-internal.h b/arch/powerpc/sysdev/xive/xive-internal.h index 211725dbf364..59cd366e7933 100644 --- a/arch/powerpc/sysdev/xive/xive-internal.h +++ b/arch/powerpc/sysdev/xive/xive-internal.h | |||
@@ -33,6 +33,8 @@ struct xive_cpu { | |||
33 | struct xive_ops { | 33 | struct xive_ops { |
34 | int (*populate_irq_data)(u32 hw_irq, struct xive_irq_data *data); | 34 | int (*populate_irq_data)(u32 hw_irq, struct xive_irq_data *data); |
35 | int (*configure_irq)(u32 hw_irq, u32 target, u8 prio, u32 sw_irq); | 35 | int (*configure_irq)(u32 hw_irq, u32 target, u8 prio, u32 sw_irq); |
36 | int (*get_irq_config)(u32 hw_irq, u32 *target, u8 *prio, | ||
37 | u32 *sw_irq); | ||
36 | int (*setup_queue)(unsigned int cpu, struct xive_cpu *xc, u8 prio); | 38 | int (*setup_queue)(unsigned int cpu, struct xive_cpu *xc, u8 prio); |
37 | void (*cleanup_queue)(unsigned int cpu, struct xive_cpu *xc, u8 prio); | 39 | void (*cleanup_queue)(unsigned int cpu, struct xive_cpu *xc, u8 prio); |
38 | void (*setup_cpu)(unsigned int cpu, struct xive_cpu *xc); | 40 | void (*setup_cpu)(unsigned int cpu, struct xive_cpu *xc); |
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index 25d4adccf750..4ea53e05053f 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c | |||
@@ -2574,14 +2574,14 @@ static void dump_all_xives(void) | |||
2574 | 2574 | ||
2575 | static void dump_one_xive_irq(u32 num) | 2575 | static void dump_one_xive_irq(u32 num) |
2576 | { | 2576 | { |
2577 | s64 rc; | 2577 | int rc; |
2578 | __be64 vp; | 2578 | u32 target; |
2579 | u8 prio; | 2579 | u8 prio; |
2580 | __be32 lirq; | 2580 | u32 lirq; |
2581 | 2581 | ||
2582 | rc = opal_xive_get_irq_config(num, &vp, &prio, &lirq); | 2582 | rc = xmon_xive_get_irq_config(num, &target, &prio, &lirq); |
2583 | xmon_printf("IRQ 0x%x config: vp=0x%llx prio=%d lirq=0x%x (rc=%lld)\n", | 2583 | xmon_printf("IRQ 0x%08x : target=0x%x prio=%d lirq=0x%x (rc=%d)\n", |
2584 | num, be64_to_cpu(vp), prio, be32_to_cpu(lirq), rc); | 2584 | num, target, prio, lirq, rc); |
2585 | } | 2585 | } |
2586 | 2586 | ||
2587 | static void dump_xives(void) | 2587 | static void dump_xives(void) |