diff options
author | Helge Deller <deller@gmx.de> | 2013-05-06 19:20:26 +0000 |
---|---|---|
committer | Helge Deller <deller@gmx.de> | 2013-05-07 22:39:22 +0200 |
commit | cd85d5514d5c4d7e78abac923fc032457d0c5091 (patch) | |
tree | b8a9ce478be624481fa8ec7341dd0ab96e7fb7ca /arch/parisc/kernel | |
parent | 200c880420a2c02a0899120ce52d801fad705b90 (diff) |
parisc: more irq statistics in /proc/interrupts
Add framework and initial values for more fine grained statistics in
/proc/interrupts.
Signed-off-by: Helge Deller <deller@gmx.de>
Diffstat (limited to 'arch/parisc/kernel')
-rw-r--r-- | arch/parisc/kernel/irq.c | 48 | ||||
-rw-r--r-- | arch/parisc/kernel/smp.c | 3 |
2 files changed, 49 insertions, 2 deletions
diff --git a/arch/parisc/kernel/irq.c b/arch/parisc/kernel/irq.c index 810f9cf89e48..a237e32ede19 100644 --- a/arch/parisc/kernel/irq.c +++ b/arch/parisc/kernel/irq.c @@ -152,6 +152,40 @@ static struct irq_chip cpu_interrupt_type = { .irq_retrigger = NULL, }; +DEFINE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat); +#define irq_stats(x) (&per_cpu(irq_stat, x)) + +/* + * /proc/interrupts printing for arch specific interrupts + */ +int arch_show_interrupts(struct seq_file *p, int prec) +{ + int j; + +#ifdef CONFIG_DEBUG_STACKOVERFLOW + seq_printf(p, "%*s: ", prec, "STK"); + for_each_online_cpu(j) + seq_printf(p, "%10u ", irq_stats(j)->kernel_stack_usage); + seq_printf(p, " Kernel stack usage\n"); +#endif +#ifdef CONFIG_SMP + seq_printf(p, "%*s: ", prec, "RES"); + for_each_online_cpu(j) + seq_printf(p, "%10u ", irq_stats(j)->irq_resched_count); + seq_printf(p, " Rescheduling interrupts\n"); + seq_printf(p, "%*s: ", prec, "CAL"); + for_each_online_cpu(j) + seq_printf(p, "%10u ", irq_stats(j)->irq_call_count - + irq_stats(j)->irq_tlb_count); + seq_printf(p, " Function call interrupts\n"); + seq_printf(p, "%*s: ", prec, "TLB"); + for_each_online_cpu(j) + seq_printf(p, "%10u ", irq_stats(j)->irq_tlb_count); + seq_printf(p, " TLB shootdowns\n"); +#endif + return 0; +} + int show_interrupts(struct seq_file *p, void *v) { int i = *(loff_t *) v, j; @@ -219,6 +253,9 @@ int show_interrupts(struct seq_file *p, void *v) raw_spin_unlock_irqrestore(&desc->lock, flags); } + if (i == NR_IRQS) + arch_show_interrupts(p, 3); + return 0; } @@ -340,13 +377,22 @@ static inline void stack_overflow_check(struct pt_regs *regs) /* Our stack starts directly behind the thread_info struct. */ unsigned long stack_start = (unsigned long) current_thread_info(); unsigned long sp = regs->gr[30]; + unsigned long stack_usage; + unsigned int *last_usage; /* if sr7 != 0, we interrupted a userspace process which we do not want * to check for stack overflow. We will only check the kernel stack. */ if (regs->sr[7]) return; - if (likely((sp - stack_start) < (THREAD_SIZE - STACK_MARGIN))) + /* calculate kernel stack usage */ + stack_usage = sp - stack_start; + last_usage = &per_cpu(irq_stat.kernel_stack_usage, smp_processor_id()); + + if (unlikely(stack_usage > *last_usage)) + *last_usage = stack_usage; + + if (likely(stack_usage < (THREAD_SIZE - STACK_MARGIN))) return; pr_emerg("stackcheck: %s will most likely overflow kernel stack " diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c index fd1bb1519c2b..218e20bff9d2 100644 --- a/arch/parisc/kernel/smp.c +++ b/arch/parisc/kernel/smp.c @@ -127,7 +127,7 @@ ipi_interrupt(int irq, void *dev_id) unsigned long flags; /* Count this now; we may make a call that never returns. */ - p->ipi_count++; + inc_irq_stat(irq_call_count); mb(); /* Order interrupt and bit testing. */ @@ -155,6 +155,7 @@ ipi_interrupt(int irq, void *dev_id) case IPI_RESCHEDULE: smp_debug(100, KERN_DEBUG "CPU%d IPI_RESCHEDULE\n", this_cpu); + inc_irq_stat(irq_resched_count); scheduler_ipi(); break; |