aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndi Kleen <ak@suse.de>2005-07-29 00:15:49 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2005-07-29 00:46:02 -0400
commited6b676ca8b50e0b538e61c283d52fd04f007abf (patch)
tree753ea613ce334c41f835f6aac21074b137d24713
parent3829ee6b1be03d5aa3005fe7d19f30088b539836 (diff)
[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>
-rw-r--r--arch/x86_64/kernel/entry.S12
-rw-r--r--arch/x86_64/kernel/irq.c19
-rw-r--r--include/asm-x86_64/irq.h2
-rw-r--r--kernel/softirq.c4
4 files changed, 35 insertions, 2 deletions
diff --git a/arch/x86_64/kernel/entry.S b/arch/x86_64/kernel/entry.S
index 0696e025dce5..096d470e280f 100644
--- a/arch/x86_64/kernel/entry.S
+++ b/arch/x86_64/kernel/entry.S
@@ -918,3 +918,15 @@ ENTRY(machine_check)
918ENTRY(call_debug) 918ENTRY(call_debug)
919 zeroentry do_call_debug 919 zeroentry do_call_debug
920 920
921ENTRY(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
diff --git a/arch/x86_64/kernel/irq.c b/arch/x86_64/kernel/irq.c
index cc3fb85f5145..849a20aec7ca 100644
--- a/arch/x86_64/kernel/irq.c
+++ b/arch/x86_64/kernel/irq.c
@@ -135,3 +135,22 @@ void fixup_irqs(cpumask_t map)
135 local_irq_disable(); 135 local_irq_disable();
136} 136}
137#endif 137#endif
138
139extern void call_softirq(void);
140
141asmlinkage 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}
156EXPORT_SYMBOL(do_softirq);
diff --git a/include/asm-x86_64/irq.h b/include/asm-x86_64/irq.h
index eb3b7aa9eb9f..4482657777bb 100644
--- a/include/asm-x86_64/irq.h
+++ b/include/asm-x86_64/irq.h
@@ -57,4 +57,6 @@ int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *);
57extern void fixup_irqs(cpumask_t map); 57extern void fixup_irqs(cpumask_t map);
58#endif 58#endif
59 59
60#define __ARCH_HAS_DO_SOFTIRQ 1
61
60#endif /* _ASM_IRQ_H */ 62#endif /* _ASM_IRQ_H */
diff --git a/kernel/softirq.c b/kernel/softirq.c
index b4ab6af1dea8..31007d6542cc 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -86,7 +86,7 @@ restart:
86 /* Reset the pending bitmask before enabling irqs */ 86 /* Reset the pending bitmask before enabling irqs */
87 local_softirq_pending() = 0; 87 local_softirq_pending() = 0;
88 88
89 local_irq_enable(); 89 //local_irq_enable();
90 90
91 h = softirq_vec; 91 h = softirq_vec;
92 92
@@ -99,7 +99,7 @@ restart:
99 pending >>= 1; 99 pending >>= 1;
100 } while (pending); 100 } while (pending);
101 101
102 local_irq_disable(); 102 //local_irq_disable();
103 103
104 pending = local_softirq_pending(); 104 pending = local_softirq_pending();
105 if (pending && --max_restart) 105 if (pending && --max_restart)