diff options
| author | Russell King <rmk+kernel@arm.linux.org.uk> | 2012-01-13 15:00:22 +0000 | 
|---|---|---|
| committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2012-01-13 15:00:22 +0000 | 
| commit | 4de3a8e101150feaefa1139611a50ff37467f33e (patch) | |
| tree | daada742542518b02d7db7c5d32e715eaa5f166d /arch/x86/kernel/irq_64.c | |
| parent | 294064f58953f9964e5945424b09c51800330a83 (diff) | |
| parent | 099469502f62fbe0d7e4f0b83a2f22538367f734 (diff) | |
| download | olio-linux-3.10-4de3a8e101150feaefa1139611a50ff37467f33e.tar.xz olio-linux-3.10-4de3a8e101150feaefa1139611a50ff37467f33e.zip  | |
Merge branch 'master' into fixes
Diffstat (limited to 'arch/x86/kernel/irq_64.c')
| -rw-r--r-- | arch/x86/kernel/irq_64.c | 35 | 
1 files changed, 29 insertions, 6 deletions
diff --git a/arch/x86/kernel/irq_64.c b/arch/x86/kernel/irq_64.c index 69bca468c47..d04d3ecded6 100644 --- a/arch/x86/kernel/irq_64.c +++ b/arch/x86/kernel/irq_64.c @@ -26,6 +26,8 @@ EXPORT_PER_CPU_SYMBOL(irq_stat);  DEFINE_PER_CPU(struct pt_regs *, irq_regs);  EXPORT_PER_CPU_SYMBOL(irq_regs); +int sysctl_panic_on_stackoverflow; +  /*   * Probabilistic stack overflow check:   * @@ -36,18 +38,39 @@ EXPORT_PER_CPU_SYMBOL(irq_regs);  static inline void stack_overflow_check(struct pt_regs *regs)  {  #ifdef CONFIG_DEBUG_STACKOVERFLOW +#define STACK_TOP_MARGIN	128 +	struct orig_ist *oist; +	u64 irq_stack_top, irq_stack_bottom; +	u64 estack_top, estack_bottom;  	u64 curbase = (u64)task_stack_page(current);  	if (user_mode_vm(regs))  		return; -	WARN_ONCE(regs->sp >= curbase && -		  regs->sp <= curbase + THREAD_SIZE && -		  regs->sp <  curbase + sizeof(struct thread_info) + -					sizeof(struct pt_regs) + 128, +	if (regs->sp >= curbase + sizeof(struct thread_info) + +				  sizeof(struct pt_regs) + STACK_TOP_MARGIN && +	    regs->sp <= curbase + THREAD_SIZE) +		return; + +	irq_stack_top = (u64)__get_cpu_var(irq_stack_union.irq_stack) + +			STACK_TOP_MARGIN; +	irq_stack_bottom = (u64)__get_cpu_var(irq_stack_ptr); +	if (regs->sp >= irq_stack_top && regs->sp <= irq_stack_bottom) +		return; + +	oist = &__get_cpu_var(orig_ist); +	estack_top = (u64)oist->ist[0] - EXCEPTION_STKSZ + STACK_TOP_MARGIN; +	estack_bottom = (u64)oist->ist[N_EXCEPTION_STACKS - 1]; +	if (regs->sp >= estack_top && regs->sp <= estack_bottom) +		return; + +	WARN_ONCE(1, "do_IRQ(): %s has overflown the kernel stack (cur:%Lx,sp:%lx,irq stk top-bottom:%Lx-%Lx,exception stk top-bottom:%Lx-%Lx)\n", +		current->comm, curbase, regs->sp, +		irq_stack_top, irq_stack_bottom, +		estack_top, estack_bottom); -		  "do_IRQ: %s near stack overflow (cur:%Lx,sp:%lx)\n", -			current->comm, curbase, regs->sp); +	if (sysctl_panic_on_stackoverflow) +		panic("low stack detected by irq handler - check messages\n");  #endif  }  |