powerpc/xive: Add a debugfs file to dump internal XIVE state
As does XMON, the debugfs file /sys/kernel/debug/powerpc/xive exposes the XIVE internal state of the machine CPUs and interrupts. Available on the PowerNV and sPAPR platforms. Signed-off-by: Cédric Le Goater <clg@kaod.org> [mpe: Make the debugfs file 0400] Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Link: https://lore.kernel.org/r/20200306150143.5551-5-clg@kaod.org
This commit is contained in:
parent
5191e0ba51
commit
930914b7d5
|
@ -20,6 +20,7 @@
|
|||
#include <linux/spinlock.h>
|
||||
#include <linux/msi.h>
|
||||
|
||||
#include <asm/debugfs.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/smp.h>
|
||||
|
@ -1555,3 +1556,107 @@ static int __init xive_off(char *arg)
|
|||
return 0;
|
||||
}
|
||||
__setup("xive=off", xive_off);
|
||||
|
||||
void xive_debug_show_cpu(struct seq_file *m, int cpu)
|
||||
{
|
||||
struct xive_cpu *xc = per_cpu(xive_cpu, cpu);
|
||||
|
||||
seq_printf(m, "CPU %d:", cpu);
|
||||
if (xc) {
|
||||
seq_printf(m, "pp=%02x CPPR=%02x ", xc->pending_prio, xc->cppr);
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
{
|
||||
u64 val = xive_esb_read(&xc->ipi_data, XIVE_ESB_GET);
|
||||
|
||||
seq_printf(m, "IPI=0x%08x PQ=%c%c ", xc->hw_ipi,
|
||||
val & XIVE_ESB_VAL_P ? 'P' : '-',
|
||||
val & XIVE_ESB_VAL_Q ? 'Q' : '-');
|
||||
}
|
||||
#endif
|
||||
{
|
||||
struct xive_q *q = &xc->queue[xive_irq_priority];
|
||||
u32 i0, i1, idx;
|
||||
|
||||
if (q->qpage) {
|
||||
idx = q->idx;
|
||||
i0 = be32_to_cpup(q->qpage + idx);
|
||||
idx = (idx + 1) & q->msk;
|
||||
i1 = be32_to_cpup(q->qpage + idx);
|
||||
seq_printf(m, "EQ idx=%d T=%d %08x %08x ...",
|
||||
q->idx, q->toggle, i0, i1);
|
||||
}
|
||||
}
|
||||
}
|
||||
seq_puts(m, "\n");
|
||||
}
|
||||
|
||||
void xive_debug_show_irq(struct seq_file *m, u32 hw_irq, struct irq_data *d)
|
||||
{
|
||||
struct irq_chip *chip = irq_data_get_irq_chip(d);
|
||||
int rc;
|
||||
u32 target;
|
||||
u8 prio;
|
||||
u32 lirq;
|
||||
|
||||
if (!is_xive_irq(chip))
|
||||
return;
|
||||
|
||||
rc = xive_ops->get_irq_config(hw_irq, &target, &prio, &lirq);
|
||||
if (rc) {
|
||||
seq_printf(m, "IRQ 0x%08x : no config rc=%d\n", hw_irq, rc);
|
||||
return;
|
||||
}
|
||||
|
||||
seq_printf(m, "IRQ 0x%08x : target=0x%x prio=%02x lirq=0x%x ",
|
||||
hw_irq, target, prio, lirq);
|
||||
|
||||
if (d) {
|
||||
struct xive_irq_data *xd = irq_data_get_irq_handler_data(d);
|
||||
u64 val = xive_esb_read(xd, XIVE_ESB_GET);
|
||||
|
||||
seq_printf(m, "flags=%c%c%c PQ=%c%c",
|
||||
xd->flags & XIVE_IRQ_FLAG_STORE_EOI ? 'S' : ' ',
|
||||
xd->flags & XIVE_IRQ_FLAG_LSI ? 'L' : ' ',
|
||||
xd->flags & XIVE_IRQ_FLAG_H_INT_ESB ? 'H' : ' ',
|
||||
val & XIVE_ESB_VAL_P ? 'P' : '-',
|
||||
val & XIVE_ESB_VAL_Q ? 'Q' : '-');
|
||||
}
|
||||
seq_puts(m, "\n");
|
||||
}
|
||||
|
||||
static int xive_core_debug_show(struct seq_file *m, void *private)
|
||||
{
|
||||
unsigned int i;
|
||||
struct irq_desc *desc;
|
||||
int cpu;
|
||||
|
||||
if (xive_ops->debug_show)
|
||||
xive_ops->debug_show(m, private);
|
||||
|
||||
for_each_possible_cpu(cpu)
|
||||
xive_debug_show_cpu(m, cpu);
|
||||
|
||||
for_each_irq_desc(i, desc) {
|
||||
struct irq_data *d = irq_desc_get_irq_data(desc);
|
||||
unsigned int hw_irq;
|
||||
|
||||
if (!d)
|
||||
continue;
|
||||
|
||||
hw_irq = (unsigned int)irqd_to_hwirq(d);
|
||||
|
||||
/* IPIs are special (HW number 0) */
|
||||
if (hw_irq)
|
||||
xive_debug_show_irq(m, hw_irq, d);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
DEFINE_SHOW_ATTRIBUTE(xive_core_debug);
|
||||
|
||||
int xive_core_debug_init(void)
|
||||
{
|
||||
debugfs_create_file("xive", 0400, powerpc_debugfs_root,
|
||||
NULL, &xive_core_debug_fops);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <linux/cpumask.h>
|
||||
#include <linux/mm.h>
|
||||
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/smp.h>
|
||||
|
@ -850,3 +851,5 @@ int xive_native_get_vp_state(u32 vp_id, u64 *out_state)
|
|||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xive_native_get_vp_state);
|
||||
|
||||
machine_arch_initcall(powernv, xive_core_debug_init);
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <linux/delay.h>
|
||||
#include <linux/libfdt.h>
|
||||
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/smp.h>
|
||||
|
@ -645,6 +646,21 @@ static void xive_spapr_sync_source(u32 hw_irq)
|
|||
plpar_int_sync(0, hw_irq);
|
||||
}
|
||||
|
||||
static int xive_spapr_debug_show(struct seq_file *m, void *private)
|
||||
{
|
||||
struct xive_irq_bitmap *xibm;
|
||||
char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
|
||||
|
||||
list_for_each_entry(xibm, &xive_irq_bitmaps, list) {
|
||||
memset(buf, 0, PAGE_SIZE);
|
||||
bitmap_print_to_pagebuf(true, buf, xibm->bitmap, xibm->count);
|
||||
seq_printf(m, "bitmap #%d: %s", xibm->count, buf);
|
||||
}
|
||||
kfree(buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct xive_ops xive_spapr_ops = {
|
||||
.populate_irq_data = xive_spapr_populate_irq_data,
|
||||
.configure_irq = xive_spapr_configure_irq,
|
||||
|
@ -662,6 +678,7 @@ static const struct xive_ops xive_spapr_ops = {
|
|||
#ifdef CONFIG_SMP
|
||||
.get_ipi = xive_spapr_get_ipi,
|
||||
.put_ipi = xive_spapr_put_ipi,
|
||||
.debug_show = xive_spapr_debug_show,
|
||||
#endif /* CONFIG_SMP */
|
||||
.name = "spapr",
|
||||
};
|
||||
|
@ -839,3 +856,5 @@ bool __init xive_spapr_init(void)
|
|||
pr_info("Using %dkB queues\n", 1 << (xive_queue_shift - 10));
|
||||
return true;
|
||||
}
|
||||
|
||||
machine_arch_initcall(pseries, xive_core_debug_init);
|
||||
|
|
|
@ -57,12 +57,14 @@ struct xive_ops {
|
|||
int (*get_ipi)(unsigned int cpu, struct xive_cpu *xc);
|
||||
void (*put_ipi)(unsigned int cpu, struct xive_cpu *xc);
|
||||
#endif
|
||||
int (*debug_show)(struct seq_file *m, void *private);
|
||||
const char *name;
|
||||
};
|
||||
|
||||
bool xive_core_init(const struct xive_ops *ops, void __iomem *area, u32 offset,
|
||||
u8 max_prio);
|
||||
__be32 *xive_queue_page_alloc(unsigned int cpu, u32 queue_shift);
|
||||
int xive_core_debug_init(void);
|
||||
|
||||
static inline u32 xive_alloc_order(u32 queue_shift)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue