From: "Andi Kleen" This avoids some potential stack overflows with very deep softirq callchains. i386 does this too. TOADD CFI annotation Signed-off-by: Andi Kleen Signed-off-by: Andrew Morton --- arch/x86_64/kernel/entry.S | 12 ++++++++++++ arch/x86_64/kernel/irq.c | 19 +++++++++++++++++++ include/asm-x86_64/irq.h | 2 ++ kernel/softirq.c | 4 ++-- 4 files changed, 35 insertions(+), 2 deletions(-) diff -puN arch/x86_64/kernel/entry.S~x86_64-switch-to-the-interrupt-stack-when-running-a arch/x86_64/kernel/entry.S --- devel/arch/x86_64/kernel/entry.S~x86_64-switch-to-the-interrupt-stack-when-running-a 2005-07-27 12:36:52.000000000 -0700 +++ devel-akpm/arch/x86_64/kernel/entry.S 2005-07-27 12:36:52.000000000 -0700 @@ -918,3 +918,15 @@ ENTRY(machine_check) ENTRY(call_debug) zeroentry do_call_debug +ENTRY(call_softirq) + movq %gs:pda_irqstackptr,%rax + pushq %r15 + movq %rsp,%r15 + incl %gs:pda_irqcount + cmove %rax,%rsp + call __do_softirq + movq %r15,%rsp + decl %gs:pda_irqcount + popq %r15 + ret + diff -puN arch/x86_64/kernel/irq.c~x86_64-switch-to-the-interrupt-stack-when-running-a arch/x86_64/kernel/irq.c --- devel/arch/x86_64/kernel/irq.c~x86_64-switch-to-the-interrupt-stack-when-running-a 2005-07-27 12:36:52.000000000 -0700 +++ devel-akpm/arch/x86_64/kernel/irq.c 2005-07-27 12:36:52.000000000 -0700 @@ -135,3 +135,22 @@ void fixup_irqs(cpumask_t map) local_irq_disable(); } #endif + +extern void call_softirq(void); + +asmlinkage void do_softirq(void) +{ + __u32 pending; + unsigned long flags; + + if (in_interrupt()) + return; + + local_irq_save(flags); + pending = local_softirq_pending(); + /* Switch to interrupt stack */ + if (pending) + call_softirq(); + local_irq_restore(flags); +} +EXPORT_SYMBOL(do_softirq); diff -puN include/asm-x86_64/irq.h~x86_64-switch-to-the-interrupt-stack-when-running-a include/asm-x86_64/irq.h --- devel/include/asm-x86_64/irq.h~x86_64-switch-to-the-interrupt-stack-when-running-a 2005-07-27 12:36:52.000000000 -0700 +++ devel-akpm/include/asm-x86_64/irq.h 2005-07-27 12:36:52.000000000 -0700 @@ -57,4 +57,6 @@ int handle_IRQ_event(unsigned int, struc extern void fixup_irqs(cpumask_t map); #endif +#define __ARCH_HAS_DO_SOFTIRQ 1 + #endif /* _ASM_IRQ_H */ diff -puN kernel/softirq.c~x86_64-switch-to-the-interrupt-stack-when-running-a kernel/softirq.c --- devel/kernel/softirq.c~x86_64-switch-to-the-interrupt-stack-when-running-a 2005-07-27 12:36:52.000000000 -0700 +++ devel-akpm/kernel/softirq.c 2005-07-27 12:36:52.000000000 -0700 @@ -86,7 +86,7 @@ restart: /* Reset the pending bitmask before enabling irqs */ local_softirq_pending() = 0; - local_irq_enable(); + //local_irq_enable(); h = softirq_vec; @@ -99,7 +99,7 @@ restart: pending >>= 1; } while (pending); - local_irq_disable(); + //local_irq_disable(); pending = local_softirq_pending(); if (pending && --max_restart) _