Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[PATCH] x86_64: Switch to the interrupt stack when running a softirq in local_bh_enable()

This avoids some potential stack overflows with very deep softirq callchains.
i386 does this too.

TOADD CFI annotation

Signed-off-by: Andi Kleen <ak@suse.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by

Andi Kleen and committed by
Linus Torvalds
ed6b676c 3829ee6b

+35 -2
+12
arch/x86_64/kernel/entry.S
··· 918 918 ENTRY(call_debug) 919 919 zeroentry do_call_debug 920 920 921 + ENTRY(call_softirq) 922 + movq %gs:pda_irqstackptr,%rax 923 + pushq %r15 924 + movq %rsp,%r15 925 + incl %gs:pda_irqcount 926 + cmove %rax,%rsp 927 + call __do_softirq 928 + movq %r15,%rsp 929 + decl %gs:pda_irqcount 930 + popq %r15 931 + ret 932 +
+19
arch/x86_64/kernel/irq.c
··· 135 135 local_irq_disable(); 136 136 } 137 137 #endif 138 + 139 + extern void call_softirq(void); 140 + 141 + asmlinkage void do_softirq(void) 142 + { 143 + __u32 pending; 144 + unsigned long flags; 145 + 146 + if (in_interrupt()) 147 + return; 148 + 149 + local_irq_save(flags); 150 + pending = local_softirq_pending(); 151 + /* Switch to interrupt stack */ 152 + if (pending) 153 + call_softirq(); 154 + local_irq_restore(flags); 155 + } 156 + EXPORT_SYMBOL(do_softirq);
+2
include/asm-x86_64/irq.h
··· 57 57 extern void fixup_irqs(cpumask_t map); 58 58 #endif 59 59 60 + #define __ARCH_HAS_DO_SOFTIRQ 1 61 + 60 62 #endif /* _ASM_IRQ_H */
+2 -2
kernel/softirq.c
··· 86 86 /* Reset the pending bitmask before enabling irqs */ 87 87 local_softirq_pending() = 0; 88 88 89 - local_irq_enable(); 89 + //local_irq_enable(); 90 90 91 91 h = softirq_vec; 92 92 ··· 99 99 pending >>= 1; 100 100 } while (pending); 101 101 102 - local_irq_disable(); 102 + //local_irq_disable(); 103 103 104 104 pending = local_softirq_pending(); 105 105 if (pending && --max_restart)