As we are going to switch to IRQ stack immediately in the exception
handler, it won't be possible anymore to check stack overflow by
reading stack pointer.

Do the verification on regs->gpr[1] which contains the stack pointer
at the time the IRQ happended, and move it to __do_irq() so that the
verification is also done when calling __do_irq() directly once the
exception entry does the stack switch.

Signed-off-by: Christophe Leroy <christophe.le...@c-s.fr>
---
 arch/powerpc/kernel/irq.c | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 28414c6665cc..4df49f6e9987 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -596,15 +596,16 @@ u64 arch_irq_stat_cpu(unsigned int cpu)
        return sum;
 }
 
-static inline void check_stack_overflow(void)
+static inline void check_stack_overflow(struct pt_regs *regs)
 {
 #ifdef CONFIG_DEBUG_STACKOVERFLOW
+       bool is_user = user_mode(regs);
        long sp;
 
-       sp = current_stack_pointer() & (THREAD_SIZE-1);
+       sp = regs->gpr[1] & (THREAD_SIZE - 1);
 
        /* check for stack overflow: is there less than 2KB free? */
-       if (unlikely(sp < 2048)) {
+       if (unlikely(!is_user && sp < 2048)) {
                pr_err("do_IRQ: stack overflow: %ld\n", sp);
                dump_stack();
        }
@@ -654,6 +655,8 @@ void __do_irq(struct pt_regs *regs)
 
        trace_irq_entry(regs);
 
+       check_stack_overflow(regs);
+
        /*
         * Query the platform PIC for the interrupt & ack it.
         *
@@ -685,8 +688,6 @@ void do_IRQ(struct pt_regs *regs)
        irqsp = hardirq_ctx[raw_smp_processor_id()];
        sirqsp = softirq_ctx[raw_smp_processor_id()];
 
-       check_stack_overflow();
-
        /* Already there ? Otherwise switch stack and call */
        if (unlikely(cursp == irqsp || cursp == sirqsp))
                __do_irq(regs);
-- 
2.13.3

Reply via email to