aboutsummaryrefslogtreecommitdiffstats
path: root/arch/parisc/kernel/irq.c
diff options
context:
space:
mode:
authorHelge Deller <deller@gmx.de>2013-05-07 15:28:52 -0400
committerHelge Deller <deller@gmx.de>2013-05-07 15:34:07 -0400
commit9372450cc22d185f708e5cc3557cf991be4b7dc5 (patch)
treef537999c1134549b14fce04a020e6e4d23d03d4c /arch/parisc/kernel/irq.c
parentc207a76bf155cb5cf24cf849c08f6555e9180594 (diff)
parisc: add kernel stack overflow check
Add the CONFIG_DEBUG_STACKOVERFLOW config option to enable checks to detect kernel stack overflows. Stack overflows can not be detected reliable since we do not want to introduce too much overhead. Instead, during irq processing in do_cpu_irq_mask() we check kernel stack usage of the interrupted kernel process. Kernel threads can be easily detected by checking the value of space register 7 (sr7) which is zero when running inside the kernel. Since THREAD_SIZE is 16k and PAGE_SIZE is 4k, reduce the alignment of the init thread to the lower value (PAGE_SIZE) in the kernel vmlinux.ld.S linker script. Signed-off-by: Helge Deller <deller@gmx.de>
Diffstat (limited to 'arch/parisc/kernel/irq.c')
-rw-r--r--arch/parisc/kernel/irq.c31
1 files changed, 29 insertions, 2 deletions
diff --git a/arch/parisc/kernel/irq.c b/arch/parisc/kernel/irq.c
index 8094d3ed3b64..61e51ac85659 100644
--- a/arch/parisc/kernel/irq.c
+++ b/arch/parisc/kernel/irq.c
@@ -330,6 +330,34 @@ static inline int eirr_to_irq(unsigned long eirr)
330 return (BITS_PER_LONG - bit) + TIMER_IRQ; 330 return (BITS_PER_LONG - bit) + TIMER_IRQ;
331} 331}
332 332
333int sysctl_panic_on_stackoverflow = 1;
334
335static inline void stack_overflow_check(struct pt_regs *regs)
336{
337#ifdef CONFIG_DEBUG_STACKOVERFLOW
338 #define STACK_MARGIN (256*6)
339
340 /* Our stack starts directly behind the thread_info struct. */
341 unsigned long stack_start = (unsigned long) current_thread_info();
342 unsigned long sp = regs->gr[30];
343
344 /* 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. */
346 if (regs->sr[7])
347 return;
348
349 if (likely((sp - stack_start) < (THREAD_SIZE - STACK_MARGIN)))
350 return;
351
352 pr_emerg("stackcheck: %s will most likely overflow kernel stack "
353 "(sp:%lx, stk bottom-top:%lx-%lx)\n",
354 current->comm, sp, stack_start, stack_start + THREAD_SIZE);
355
356 if (sysctl_panic_on_stackoverflow)
357 panic("low stack detected by irq handler - check messages\n");
358#endif
359}
360
333/* ONLY called from entry.S:intr_extint() */ 361/* ONLY called from entry.S:intr_extint() */
334void do_cpu_irq_mask(struct pt_regs *regs) 362void do_cpu_irq_mask(struct pt_regs *regs)
335{ 363{
@@ -364,6 +392,7 @@ void do_cpu_irq_mask(struct pt_regs *regs)
364 goto set_out; 392 goto set_out;
365 } 393 }
366#endif 394#endif
395 stack_overflow_check(regs);
367 generic_handle_irq(irq); 396 generic_handle_irq(irq);
368 397
369 out: 398 out:
@@ -420,6 +449,4 @@ void __init init_IRQ(void)
420 cpu_eiem = EIEM_MASK(TIMER_IRQ); 449 cpu_eiem = EIEM_MASK(TIMER_IRQ);
421#endif 450#endif
422 set_eiem(cpu_eiem); /* EIEM : enable all external intr */ 451 set_eiem(cpu_eiem); /* EIEM : enable all external intr */
423
424} 452}
425