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
This commit is contained in:

committed by
Michael Ellerman

parent
c3e0dbd7f7
commit
b4868ff55d
@@ -99,6 +99,8 @@ extern void xive_flush_interrupt(void);
|
|||||||
|
|
||||||
/* xmon hook */
|
/* xmon hook */
|
||||||
extern void xmon_xive_do_dump(int cpu);
|
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 */
|
/* APIs used by KVM */
|
||||||
extern u32 xive_native_default_eq_shift(void);
|
extern u32 xive_native_default_eq_shift(void);
|
||||||
|
@@ -257,6 +257,13 @@ notrace void xmon_xive_do_dump(int cpu)
|
|||||||
}
|
}
|
||||||
#endif
|
#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 */
|
#endif /* CONFIG_XMON */
|
||||||
|
|
||||||
static unsigned int xive_get_irq(void)
|
static unsigned int xive_get_irq(void)
|
||||||
|
@@ -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);
|
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 */
|
/* 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,
|
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 = {
|
static const struct xive_ops xive_native_ops = {
|
||||||
.populate_irq_data = xive_native_populate_irq_data,
|
.populate_irq_data = xive_native_populate_irq_data,
|
||||||
.configure_irq = xive_native_configure_irq,
|
.configure_irq = xive_native_configure_irq,
|
||||||
|
.get_irq_config = xive_native_get_irq_config,
|
||||||
.setup_queue = xive_native_setup_queue,
|
.setup_queue = xive_native_setup_queue,
|
||||||
.cleanup_queue = xive_native_cleanup_queue,
|
.cleanup_queue = xive_native_cleanup_queue,
|
||||||
.match = xive_native_match,
|
.match = xive_native_match,
|
||||||
|
@@ -215,6 +215,38 @@ static long plpar_int_set_source_config(unsigned long flags,
|
|||||||
return 0;
|
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,
|
static long plpar_int_get_queue_info(unsigned long flags,
|
||||||
unsigned long target,
|
unsigned long target,
|
||||||
unsigned long priority,
|
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;
|
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 */
|
/* 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,
|
static int xive_spapr_configure_queue(u32 target, struct xive_q *q, u8 prio,
|
||||||
__be32 *qpage, u32 order)
|
__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 = {
|
static const struct xive_ops xive_spapr_ops = {
|
||||||
.populate_irq_data = xive_spapr_populate_irq_data,
|
.populate_irq_data = xive_spapr_populate_irq_data,
|
||||||
.configure_irq = xive_spapr_configure_irq,
|
.configure_irq = xive_spapr_configure_irq,
|
||||||
|
.get_irq_config = xive_spapr_get_irq_config,
|
||||||
.setup_queue = xive_spapr_setup_queue,
|
.setup_queue = xive_spapr_setup_queue,
|
||||||
.cleanup_queue = xive_spapr_cleanup_queue,
|
.cleanup_queue = xive_spapr_cleanup_queue,
|
||||||
.match = xive_spapr_match,
|
.match = xive_spapr_match,
|
||||||
|
@@ -33,6 +33,8 @@ struct xive_cpu {
|
|||||||
struct xive_ops {
|
struct xive_ops {
|
||||||
int (*populate_irq_data)(u32 hw_irq, struct xive_irq_data *data);
|
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 (*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);
|
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 (*cleanup_queue)(unsigned int cpu, struct xive_cpu *xc, u8 prio);
|
||||||
void (*setup_cpu)(unsigned int cpu, struct xive_cpu *xc);
|
void (*setup_cpu)(unsigned int cpu, struct xive_cpu *xc);
|
||||||
|
@@ -2574,14 +2574,14 @@ static void dump_all_xives(void)
|
|||||||
|
|
||||||
static void dump_one_xive_irq(u32 num)
|
static void dump_one_xive_irq(u32 num)
|
||||||
{
|
{
|
||||||
s64 rc;
|
int rc;
|
||||||
__be64 vp;
|
u32 target;
|
||||||
u8 prio;
|
u8 prio;
|
||||||
__be32 lirq;
|
u32 lirq;
|
||||||
|
|
||||||
rc = opal_xive_get_irq_config(num, &vp, &prio, &lirq);
|
rc = xmon_xive_get_irq_config(num, &target, &prio, &lirq);
|
||||||
xmon_printf("IRQ 0x%x config: vp=0x%llx prio=%d lirq=0x%x (rc=%lld)\n",
|
xmon_printf("IRQ 0x%08x : target=0x%x prio=%d lirq=0x%x (rc=%d)\n",
|
||||||
num, be64_to_cpu(vp), prio, be32_to_cpu(lirq), rc);
|
num, target, prio, lirq, rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dump_xives(void)
|
static void dump_xives(void)
|
||||||
|
Reference in New Issue
Block a user