diff options
author | Jeremy Fitzhardinge <jeremy@goop.org> | 2009-02-06 17:09:40 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-02-09 06:15:57 -0500 |
commit | 9b2b76a3344146c4d8d300874e73af8161204f87 (patch) | |
tree | 13c22f62ac7610f07b93fe9f4a75e0f57ebb450d /arch/x86/kernel/irq_32.c | |
parent | cc6c50066ec1ac98bef97117e2f078bb89bbccc7 (diff) |
x86: add handle_irq() to allow interrupt injection
Xen uses a different interrupt path, so introduce handle_irq() to
allow interrupts to be inserted into the normal interrupt path. This
is handled slightly differently on 32 and 64-bit.
Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel/irq_32.c')
-rw-r--r-- | arch/x86/kernel/irq_32.c | 34 |
1 files changed, 21 insertions, 13 deletions
diff --git a/arch/x86/kernel/irq_32.c b/arch/x86/kernel/irq_32.c index d802c844991e..61f09fb969ee 100644 --- a/arch/x86/kernel/irq_32.c +++ b/arch/x86/kernel/irq_32.c | |||
@@ -191,6 +191,26 @@ static inline int | |||
191 | execute_on_irq_stack(int overflow, struct irq_desc *desc, int irq) { return 0; } | 191 | execute_on_irq_stack(int overflow, struct irq_desc *desc, int irq) { return 0; } |
192 | #endif | 192 | #endif |
193 | 193 | ||
194 | bool handle_irq(unsigned irq, struct pt_regs *regs) | ||
195 | { | ||
196 | struct irq_desc *desc; | ||
197 | int overflow; | ||
198 | |||
199 | overflow = check_stack_overflow(); | ||
200 | |||
201 | desc = irq_to_desc(irq); | ||
202 | if (unlikely(!desc)) | ||
203 | return false; | ||
204 | |||
205 | if (!execute_on_irq_stack(overflow, desc, irq)) { | ||
206 | if (unlikely(overflow)) | ||
207 | print_stack_overflow(); | ||
208 | desc->handle_irq(irq, desc); | ||
209 | } | ||
210 | |||
211 | return true; | ||
212 | } | ||
213 | |||
194 | /* | 214 | /* |
195 | * do_IRQ handles all normal device IRQ's (the special | 215 | * do_IRQ handles all normal device IRQ's (the special |
196 | * SMP cross-CPU interrupts have their own specific | 216 | * SMP cross-CPU interrupts have their own specific |
@@ -200,31 +220,19 @@ unsigned int do_IRQ(struct pt_regs *regs) | |||
200 | { | 220 | { |
201 | struct pt_regs *old_regs; | 221 | struct pt_regs *old_regs; |
202 | /* high bit used in ret_from_ code */ | 222 | /* high bit used in ret_from_ code */ |
203 | int overflow; | ||
204 | unsigned vector = ~regs->orig_ax; | 223 | unsigned vector = ~regs->orig_ax; |
205 | struct irq_desc *desc; | ||
206 | unsigned irq; | 224 | unsigned irq; |
207 | 225 | ||
208 | |||
209 | old_regs = set_irq_regs(regs); | 226 | old_regs = set_irq_regs(regs); |
210 | irq_enter(); | 227 | irq_enter(); |
211 | irq = __get_cpu_var(vector_irq)[vector]; | 228 | irq = __get_cpu_var(vector_irq)[vector]; |
212 | 229 | ||
213 | overflow = check_stack_overflow(); | 230 | if (!handle_irq(irq, regs)) { |
214 | |||
215 | desc = irq_to_desc(irq); | ||
216 | if (unlikely(!desc)) { | ||
217 | printk(KERN_EMERG "%s: cannot handle IRQ %d vector %#x cpu %d\n", | 231 | printk(KERN_EMERG "%s: cannot handle IRQ %d vector %#x cpu %d\n", |
218 | __func__, irq, vector, smp_processor_id()); | 232 | __func__, irq, vector, smp_processor_id()); |
219 | BUG(); | 233 | BUG(); |
220 | } | 234 | } |
221 | 235 | ||
222 | if (!execute_on_irq_stack(overflow, desc, irq)) { | ||
223 | if (unlikely(overflow)) | ||
224 | print_stack_overflow(); | ||
225 | desc->handle_irq(irq, desc); | ||
226 | } | ||
227 | |||
228 | irq_exit(); | 236 | irq_exit(); |
229 | set_irq_regs(old_regs); | 237 | set_irq_regs(old_regs); |
230 | return 1; | 238 | return 1; |