diff options
Diffstat (limited to 'arch/parisc/kernel')
-rw-r--r-- | arch/parisc/kernel/irq.c | 31 | ||||
-rw-r--r-- | arch/parisc/kernel/vmlinux.lds.S | 2 |
2 files changed, 30 insertions, 3 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 | ||
333 | int sysctl_panic_on_stackoverflow = 1; | ||
334 | |||
335 | static 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() */ |
334 | void do_cpu_irq_mask(struct pt_regs *regs) | 362 | void 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 | |||
diff --git a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S index 64a999882e4f..4bb095a2f6fc 100644 --- a/arch/parisc/kernel/vmlinux.lds.S +++ b/arch/parisc/kernel/vmlinux.lds.S | |||
@@ -95,7 +95,7 @@ SECTIONS | |||
95 | NOTES | 95 | NOTES |
96 | 96 | ||
97 | /* Data */ | 97 | /* Data */ |
98 | RW_DATA_SECTION(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE) | 98 | RW_DATA_SECTION(L1_CACHE_BYTES, PAGE_SIZE, PAGE_SIZE) |
99 | 99 | ||
100 | /* PA-RISC locks requires 16-byte alignment */ | 100 | /* PA-RISC locks requires 16-byte alignment */ |
101 | . = ALIGN(16); | 101 | . = ALIGN(16); |