diff options
author | Andi Kleen <ak@suse.de> | 2005-07-29 00:15:49 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-07-29 00:46:02 -0400 |
commit | ed6b676ca8b50e0b538e61c283d52fd04f007abf (patch) | |
tree | 753ea613ce334c41f835f6aac21074b137d24713 /arch/x86_64/kernel | |
parent | 3829ee6b1be03d5aa3005fe7d19f30088b539836 (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>
Diffstat (limited to 'arch/x86_64/kernel')
-rw-r--r-- | arch/x86_64/kernel/entry.S | 12 | ||||
-rw-r--r-- | arch/x86_64/kernel/irq.c | 19 |
2 files changed, 31 insertions, 0 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) | |||
918 | ENTRY(call_debug) | 918 | ENTRY(call_debug) |
919 | zeroentry do_call_debug | 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 | |||
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 | |||
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); | ||