diff options
author | Helge Deller <deller@gmx.de> | 2013-05-06 15:20:26 -0400 |
---|---|---|
committer | Helge Deller <deller@gmx.de> | 2013-05-07 16:39:22 -0400 |
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 = { | |||
152 | .irq_retrigger = NULL, | 152 | .irq_retrigger = NULL, |
153 | }; | 153 | }; |
154 | 154 | ||
155 | DEFINE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat); | ||
156 | #define irq_stats(x) (&per_cpu(irq_stat, x)) | ||
157 | |||
158 | /* | ||
159 | * /proc/interrupts printing for arch specific interrupts | ||
160 | */ | ||
161 | int arch_show_interrupts(struct seq_file *p, int prec) | ||
162 | { | ||
163 | int j; | ||
164 | |||
165 | #ifdef CONFIG_DEBUG_STACKOVERFLOW | ||
166 | seq_printf(p, "%*s: ", prec, "STK"); | ||
167 | for_each_online_cpu(j) | ||
168 | seq_printf(p, "%10u ", irq_stats(j)->kernel_stack_usage); | ||
169 | seq_printf(p, " Kernel stack usage\n"); | ||
170 | #endif | ||
171 | #ifdef CONFIG_SMP | ||
172 | seq_printf(p, "%*s: ", prec, "RES"); | ||
173 | for_each_online_cpu(j) | ||
174 | seq_printf(p, "%10u ", irq_stats(j)->irq_resched_count); | ||
175 | seq_printf(p, " Rescheduling interrupts\n"); | ||
176 | seq_printf(p, "%*s: ", prec, "CAL"); | ||
177 | for_each_online_cpu(j) | ||
178 | seq_printf(p, "%10u ", irq_stats(j)->irq_call_count - | ||
179 | irq_stats(j)->irq_tlb_count); | ||
180 | seq_printf(p, " Function call interrupts\n"); | ||
181 | seq_printf(p, "%*s: ", prec, "TLB"); | ||
182 | for_each_online_cpu(j) | ||
183 | seq_printf(p, "%10u ", irq_stats(j)->irq_tlb_count); | ||
184 | seq_printf(p, " TLB shootdowns\n"); | ||
185 | #endif | ||
186 | return 0; | ||
187 | } | ||
188 | |||
155 | int show_interrupts(struct seq_file *p, void *v) | 189 | int show_interrupts(struct seq_file *p, void *v) |
156 | { | 190 | { |
157 | int i = *(loff_t *) v, j; | 191 | int i = *(loff_t *) v, j; |
@@ -219,6 +253,9 @@ int show_interrupts(struct seq_file *p, void *v) | |||
219 | raw_spin_unlock_irqrestore(&desc->lock, flags); | 253 | raw_spin_unlock_irqrestore(&desc->lock, flags); |
220 | } | 254 | } |
221 | 255 | ||
256 | if (i == NR_IRQS) | ||
257 | arch_show_interrupts(p, 3); | ||
258 | |||
222 | return 0; | 259 | return 0; |
223 | } | 260 | } |
224 | 261 | ||
@@ -340,13 +377,22 @@ static inline void stack_overflow_check(struct pt_regs *regs) | |||
340 | /* Our stack starts directly behind the thread_info struct. */ | 377 | /* Our stack starts directly behind the thread_info struct. */ |
341 | unsigned long stack_start = (unsigned long) current_thread_info(); | 378 | unsigned long stack_start = (unsigned long) current_thread_info(); |
342 | unsigned long sp = regs->gr[30]; | 379 | unsigned long sp = regs->gr[30]; |
380 | unsigned long stack_usage; | ||
381 | unsigned int *last_usage; | ||
343 | 382 | ||
344 | /* if sr7 != 0, we interrupted a userspace process which we do not want | 383 | /* if sr7 != 0, we interrupted a userspace process which we do not want |
345 | * to check for stack overflow. We will only check the kernel stack. */ | 384 | * to check for stack overflow. We will only check the kernel stack. */ |
346 | if (regs->sr[7]) | 385 | if (regs->sr[7]) |
347 | return; | 386 | return; |
348 | 387 | ||
349 | if (likely((sp - stack_start) < (THREAD_SIZE - STACK_MARGIN))) | 388 | /* calculate kernel stack usage */ |
389 | stack_usage = sp - stack_start; | ||
390 | last_usage = &per_cpu(irq_stat.kernel_stack_usage, smp_processor_id()); | ||
391 | |||
392 | if (unlikely(stack_usage > *last_usage)) | ||
393 | *last_usage = stack_usage; | ||
394 | |||
395 | if (likely(stack_usage < (THREAD_SIZE - STACK_MARGIN))) | ||
350 | return; | 396 | return; |
351 | 397 | ||
352 | pr_emerg("stackcheck: %s will most likely overflow kernel stack " | 398 | 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) | |||
127 | unsigned long flags; | 127 | unsigned long flags; |
128 | 128 | ||
129 | /* Count this now; we may make a call that never returns. */ | 129 | /* Count this now; we may make a call that never returns. */ |
130 | p->ipi_count++; | 130 | inc_irq_stat(irq_call_count); |
131 | 131 | ||
132 | mb(); /* Order interrupt and bit testing. */ | 132 | mb(); /* Order interrupt and bit testing. */ |
133 | 133 | ||
@@ -155,6 +155,7 @@ ipi_interrupt(int irq, void *dev_id) | |||
155 | 155 | ||
156 | case IPI_RESCHEDULE: | 156 | case IPI_RESCHEDULE: |
157 | smp_debug(100, KERN_DEBUG "CPU%d IPI_RESCHEDULE\n", this_cpu); | 157 | smp_debug(100, KERN_DEBUG "CPU%d IPI_RESCHEDULE\n", this_cpu); |
158 | inc_irq_stat(irq_resched_count); | ||
158 | scheduler_ipi(); | 159 | scheduler_ipi(); |
159 | break; | 160 | break; |
160 | 161 | ||