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 | |
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>
-rw-r--r-- | arch/x86_64/kernel/entry.S | 12 | ||||
-rw-r--r-- | arch/x86_64/kernel/irq.c | 19 | ||||
-rw-r--r-- | include/asm-x86_64/irq.h | 2 | ||||
-rw-r--r-- | kernel/softirq.c | 4 |
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) | |||
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); | ||
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 *); | |||
57 | extern void fixup_irqs(cpumask_t map); | 57 | extern 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) |