aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86
diff options
context:
space:
mode:
authorJeremy Fitzhardinge <jeremy@goop.org>2009-02-06 17:09:40 -0500
committerIngo Molnar <mingo@elte.hu>2009-02-09 06:15:57 -0500
commit9b2b76a3344146c4d8d300874e73af8161204f87 (patch)
tree13c22f62ac7610f07b93fe9f4a75e0f57ebb450d /arch/x86
parentcc6c50066ec1ac98bef97117e2f078bb89bbccc7 (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')
-rw-r--r--arch/x86/include/asm/irq.h1
-rw-r--r--arch/x86/kernel/irq_32.c34
-rw-r--r--arch/x86/kernel/irq_64.c23
3 files changed, 38 insertions, 20 deletions
diff --git a/arch/x86/include/asm/irq.h b/arch/x86/include/asm/irq.h
index 592688ed04d3..d0f6f7d1771c 100644
--- a/arch/x86/include/asm/irq.h
+++ b/arch/x86/include/asm/irq.h
@@ -39,6 +39,7 @@ extern void fixup_irqs(void);
39extern unsigned int do_IRQ(struct pt_regs *regs); 39extern unsigned int do_IRQ(struct pt_regs *regs);
40extern void init_IRQ(void); 40extern void init_IRQ(void);
41extern void native_init_IRQ(void); 41extern void native_init_IRQ(void);
42extern bool handle_irq(unsigned irq, struct pt_regs *regs);
42 43
43/* Interrupt vector management */ 44/* Interrupt vector management */
44extern DECLARE_BITMAP(used_vectors, NR_VECTORS); 45extern DECLARE_BITMAP(used_vectors, NR_VECTORS);
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
191execute_on_irq_stack(int overflow, struct irq_desc *desc, int irq) { return 0; } 191execute_on_irq_stack(int overflow, struct irq_desc *desc, int irq) { return 0; }
192#endif 192#endif
193 193
194bool 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;
diff --git a/arch/x86/kernel/irq_64.c b/arch/x86/kernel/irq_64.c
index 018963aa6ee3..a93f3b0dc7f2 100644
--- a/arch/x86/kernel/irq_64.c
+++ b/arch/x86/kernel/irq_64.c
@@ -48,6 +48,20 @@ static inline void stack_overflow_check(struct pt_regs *regs)
48#endif 48#endif
49} 49}
50 50
51bool handle_irq(unsigned irq, struct pt_regs *regs)
52{
53 struct irq_desc *desc;
54
55 stack_overflow_check(regs);
56
57 desc = irq_to_desc(irq);
58 if (unlikely(!desc))
59 return false;
60
61 generic_handle_irq_desc(irq, desc);
62 return true;
63}
64
51/* 65/*
52 * do_IRQ handles all normal device IRQ's (the special 66 * do_IRQ handles all normal device IRQ's (the special
53 * SMP cross-CPU interrupts have their own specific 67 * SMP cross-CPU interrupts have their own specific
@@ -56,7 +70,6 @@ static inline void stack_overflow_check(struct pt_regs *regs)
56asmlinkage unsigned int __irq_entry do_IRQ(struct pt_regs *regs) 70asmlinkage unsigned int __irq_entry do_IRQ(struct pt_regs *regs)
57{ 71{
58 struct pt_regs *old_regs = set_irq_regs(regs); 72 struct pt_regs *old_regs = set_irq_regs(regs);
59 struct irq_desc *desc;
60 73
61 /* high bit used in ret_from_ code */ 74 /* high bit used in ret_from_ code */
62 unsigned vector = ~regs->orig_ax; 75 unsigned vector = ~regs->orig_ax;
@@ -64,14 +77,10 @@ asmlinkage unsigned int __irq_entry do_IRQ(struct pt_regs *regs)
64 77
65 exit_idle(); 78 exit_idle();
66 irq_enter(); 79 irq_enter();
67 irq = __get_cpu_var(vector_irq)[vector];
68 80
69 stack_overflow_check(regs); 81 irq = __get_cpu_var(vector_irq)[vector];
70 82
71 desc = irq_to_desc(irq); 83 if (!handle_irq(irq, regs)) {
72 if (likely(desc))
73 generic_handle_irq_desc(irq, desc);
74 else {
75 if (!disable_apic) 84 if (!disable_apic)
76 ack_APIC_irq(); 85 ack_APIC_irq();
77 86