|
@@ -36,18 +36,35 @@ EXPORT_PER_CPU_SYMBOL(irq_regs);
|
|
static inline void stack_overflow_check(struct pt_regs *regs)
|
|
static inline void stack_overflow_check(struct pt_regs *regs)
|
|
{
|
|
{
|
|
#ifdef CONFIG_DEBUG_STACKOVERFLOW
|
|
#ifdef CONFIG_DEBUG_STACKOVERFLOW
|
|
|
|
+ struct orig_ist *oist;
|
|
|
|
+ u64 irq_stack_top, irq_stack_bottom;
|
|
|
|
+ u64 estack_top, estack_bottom;
|
|
u64 curbase = (u64)task_stack_page(current);
|
|
u64 curbase = (u64)task_stack_page(current);
|
|
|
|
|
|
if (user_mode_vm(regs))
|
|
if (user_mode_vm(regs))
|
|
return;
|
|
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 &&
|
|
|
|
+ regs->sp <= curbase + THREAD_SIZE &&
|
|
|
|
+ regs->sp >= curbase + sizeof(struct thread_info) +
|
|
|
|
+ sizeof(struct pt_regs) + 128)
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ irq_stack_top = (u64)__get_cpu_var(irq_stack_union.irq_stack);
|
|
|
|
+ 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;
|
|
|
|
+ estack_bottom = (u64)oist->ist[N_EXCEPTION_STACKS - 1];
|
|
|
|
+ if (regs->sp >= estack_top && regs->sp <= estack_bottom)
|
|
|
|
+ return;
|
|
|
|
|
|
- "do_IRQ: %s near stack overflow (cur:%Lx,sp:%lx)\n",
|
|
|
|
- current->comm, curbase, regs->sp);
|
|
|
|
|
|
+ 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);
|
|
#endif
|
|
#endif
|
|
}
|
|
}
|
|
|
|
|