* [PATCH] x86: add handle_irq() to allow interrupt injection
@ 2008-12-16 20:34 Jeremy Fitzhardinge
2008-12-16 20:49 ` Ingo Molnar
0 siblings, 1 reply; 4+ messages in thread
From: Jeremy Fitzhardinge @ 2008-12-16 20:34 UTC (permalink / raw)
To: Ingo Molnar; +Cc: the arch/x86 maintainers, Linux Kernel Mailing List
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>
---
arch/x86/include/asm/irq.h | 1 +
arch/x86/kernel/irq_32.c | 34 +++++++++++++++++++++-------------
arch/x86/kernel/irq_64.c | 23 ++++++++++++++++-------
3 files changed, 38 insertions(+), 20 deletions(-)
===================================================================
--- a/arch/x86/include/asm/irq.h
+++ b/arch/x86/include/asm/irq.h
@@ -39,6 +39,7 @@
extern unsigned int do_IRQ(struct pt_regs *regs);
extern void init_IRQ(void);
extern void native_init_IRQ(void);
+extern bool handle_irq(unsigned irq, struct pt_regs *regs);
/* Interrupt vector management */
extern DECLARE_BITMAP(used_vectors, NR_VECTORS);
===================================================================
--- a/arch/x86/kernel/irq_32.c
+++ b/arch/x86/kernel/irq_32.c
@@ -191,6 +191,26 @@
execute_on_irq_stack(int overflow, struct irq_desc *desc, int irq) { return 0; }
#endif
+bool handle_irq(unsigned irq, struct pt_regs *regs)
+{
+ struct irq_desc *desc;
+ int overflow;
+
+ overflow = check_stack_overflow();
+
+ desc = irq_to_desc(irq);
+ if (unlikely(!desc))
+ return false;
+
+ if (!execute_on_irq_stack(overflow, desc, irq)) {
+ if (unlikely(overflow))
+ print_stack_overflow();
+ desc->handle_irq(irq, desc);
+ }
+
+ return true;
+}
+
/*
* do_IRQ handles all normal device IRQ's (the special
* SMP cross-CPU interrupts have their own specific
@@ -200,31 +220,19 @@
{
struct pt_regs *old_regs;
/* high bit used in ret_from_ code */
- int overflow;
unsigned vector = ~regs->orig_ax;
- struct irq_desc *desc;
unsigned irq;
-
old_regs = set_irq_regs(regs);
irq_enter();
irq = __get_cpu_var(vector_irq)[vector];
- overflow = check_stack_overflow();
-
- desc = irq_to_desc(irq);
- if (unlikely(!desc)) {
+ if (!handle_irq(irq, regs)) {
printk(KERN_EMERG "%s: cannot handle IRQ %d vector %#x cpu %d\n",
__func__, irq, vector, smp_processor_id());
BUG();
}
- if (!execute_on_irq_stack(overflow, desc, irq)) {
- if (unlikely(overflow))
- print_stack_overflow();
- desc->handle_irq(irq, desc);
- }
-
irq_exit();
set_irq_regs(old_regs);
return 1;
===================================================================
--- a/arch/x86/kernel/irq_64.c
+++ b/arch/x86/kernel/irq_64.c
@@ -40,6 +40,20 @@
#endif
}
+bool handle_irq(unsigned irq, struct pt_regs *regs)
+{
+ struct irq_desc *desc;
+
+ stack_overflow_check(regs);
+
+ desc = irq_to_desc(irq);
+ if (unlikely(!desc))
+ return false;
+
+ generic_handle_irq_desc(irq, desc);
+ return true;
+}
+
/*
* do_IRQ handles all normal device IRQ's (the special
* SMP cross-CPU interrupts have their own specific
@@ -48,7 +62,6 @@
asmlinkage unsigned int do_IRQ(struct pt_regs *regs)
{
struct pt_regs *old_regs = set_irq_regs(regs);
- struct irq_desc *desc;
/* high bit used in ret_from_ code */
unsigned vector = ~regs->orig_ax;
@@ -56,14 +69,10 @@
exit_idle();
irq_enter();
+
irq = __get_cpu_var(vector_irq)[vector];
- stack_overflow_check(regs);
-
- desc = irq_to_desc(irq);
- if (likely(desc))
- generic_handle_irq_desc(irq, desc);
- else {
+ if (!handle_irq(irq, regs)) {
if (!disable_apic)
ack_APIC_irq();
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: [PATCH] x86: add handle_irq() to allow interrupt injection 2008-12-16 20:34 [PATCH] x86: add handle_irq() to allow interrupt injection Jeremy Fitzhardinge @ 2008-12-16 20:49 ` Ingo Molnar 2008-12-17 23:06 ` Jeremy Fitzhardinge 0 siblings, 1 reply; 4+ messages in thread From: Ingo Molnar @ 2008-12-16 20:49 UTC (permalink / raw) To: Jeremy Fitzhardinge; +Cc: the arch/x86 maintainers, Linux Kernel Mailing List * Jeremy Fitzhardinge <jeremy@goop.org> wrote: > 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> > --- > arch/x86/include/asm/irq.h | 1 + > arch/x86/kernel/irq_32.c | 34 +++++++++++++++++++++------------- > arch/x86/kernel/irq_64.c | 23 ++++++++++++++++------- > 3 files changed, 38 insertions(+), 20 deletions(-) > > =================================================================== > --- a/arch/x86/include/asm/irq.h > +++ b/arch/x86/include/asm/irq.h > @@ -39,6 +39,7 @@ > extern unsigned int do_IRQ(struct pt_regs *regs); > extern void init_IRQ(void); > extern void native_init_IRQ(void); > +extern bool handle_irq(unsigned irq, struct pt_regs *regs); > > /* Interrupt vector management */ > extern DECLARE_BITMAP(used_vectors, NR_VECTORS); > =================================================================== > --- a/arch/x86/kernel/irq_32.c > +++ b/arch/x86/kernel/irq_32.c > @@ -191,6 +191,26 @@ > execute_on_irq_stack(int overflow, struct irq_desc *desc, int irq) { return 0; } > #endif > > +bool handle_irq(unsigned irq, struct pt_regs *regs) > +{ > + struct irq_desc *desc; > + int overflow; > + > + overflow = check_stack_overflow(); > + > + desc = irq_to_desc(irq); > + if (unlikely(!desc)) > + return false; > + > + if (!execute_on_irq_stack(overflow, desc, irq)) { > + if (unlikely(overflow)) > + print_stack_overflow(); > + desc->handle_irq(irq, desc); > + } > + > + return true; > +} > + > /* > * do_IRQ handles all normal device IRQ's (the special > * SMP cross-CPU interrupts have their own specific > @@ -200,31 +220,19 @@ > { > struct pt_regs *old_regs; > /* high bit used in ret_from_ code */ > - int overflow; > unsigned vector = ~regs->orig_ax; > - struct irq_desc *desc; > unsigned irq; > > - > old_regs = set_irq_regs(regs); > irq_enter(); > irq = __get_cpu_var(vector_irq)[vector]; > > - overflow = check_stack_overflow(); > - > - desc = irq_to_desc(irq); > - if (unlikely(!desc)) { > + if (!handle_irq(irq, regs)) { > printk(KERN_EMERG "%s: cannot handle IRQ %d vector %#x cpu %d\n", > __func__, irq, vector, smp_processor_id()); > BUG(); > } > > - if (!execute_on_irq_stack(overflow, desc, irq)) { > - if (unlikely(overflow)) > - print_stack_overflow(); > - desc->handle_irq(irq, desc); > - } > - > irq_exit(); > set_irq_regs(old_regs); > return 1; > =================================================================== > --- a/arch/x86/kernel/irq_64.c > +++ b/arch/x86/kernel/irq_64.c > @@ -40,6 +40,20 @@ > #endif > } > > +bool handle_irq(unsigned irq, struct pt_regs *regs) > +{ > + struct irq_desc *desc; > + > + stack_overflow_check(regs); > + > + desc = irq_to_desc(irq); > + if (unlikely(!desc)) > + return false; > + > + generic_handle_irq_desc(irq, desc); > + return true; > +} > + > /* > * do_IRQ handles all normal device IRQ's (the special > * SMP cross-CPU interrupts have their own specific > @@ -48,7 +62,6 @@ > asmlinkage unsigned int do_IRQ(struct pt_regs *regs) > { > struct pt_regs *old_regs = set_irq_regs(regs); > - struct irq_desc *desc; > > /* high bit used in ret_from_ code */ > unsigned vector = ~regs->orig_ax; > @@ -56,14 +69,10 @@ > > exit_idle(); > irq_enter(); > + > irq = __get_cpu_var(vector_irq)[vector]; > > - stack_overflow_check(regs); > - > - desc = irq_to_desc(irq); > - if (likely(desc)) > - generic_handle_irq_desc(irq, desc); > - else { > + if (!handle_irq(irq, regs)) { > if (!disable_apic) > ack_APIC_irq(); > the changes look rather similar. Could you please look into unifying irq_*.c before adding more logic to it? Ingo ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] x86: add handle_irq() to allow interrupt injection 2008-12-16 20:49 ` Ingo Molnar @ 2008-12-17 23:06 ` Jeremy Fitzhardinge 2008-12-18 5:28 ` Cyrill Gorcunov 0 siblings, 1 reply; 4+ messages in thread From: Jeremy Fitzhardinge @ 2008-12-17 23:06 UTC (permalink / raw) To: Ingo Molnar; +Cc: the arch/x86 maintainers, Linux Kernel Mailing List Ingo Molnar wrote: > * Jeremy Fitzhardinge <jeremy@goop.org> wrote: > > >> 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> >> --- >> arch/x86/include/asm/irq.h | 1 + >> arch/x86/kernel/irq_32.c | 34 +++++++++++++++++++++------------- >> arch/x86/kernel/irq_64.c | 23 ++++++++++++++++------- >> 3 files changed, 38 insertions(+), 20 deletions(-) >> >> =================================================================== >> --- a/arch/x86/include/asm/irq.h >> +++ b/arch/x86/include/asm/irq.h >> @@ -39,6 +39,7 @@ >> extern unsigned int do_IRQ(struct pt_regs *regs); >> extern void init_IRQ(void); >> extern void native_init_IRQ(void); >> +extern bool handle_irq(unsigned irq, struct pt_regs *regs); >> >> /* Interrupt vector management */ >> extern DECLARE_BITMAP(used_vectors, NR_VECTORS); >> =================================================================== >> --- a/arch/x86/kernel/irq_32.c >> +++ b/arch/x86/kernel/irq_32.c >> @@ -191,6 +191,26 @@ >> execute_on_irq_stack(int overflow, struct irq_desc *desc, int irq) { return 0; } >> #endif >> >> +bool handle_irq(unsigned irq, struct pt_regs *regs) >> +{ >> + struct irq_desc *desc; >> + int overflow; >> + >> + overflow = check_stack_overflow(); >> + >> + desc = irq_to_desc(irq); >> + if (unlikely(!desc)) >> + return false; >> + >> + if (!execute_on_irq_stack(overflow, desc, irq)) { >> + if (unlikely(overflow)) >> + print_stack_overflow(); >> + desc->handle_irq(irq, desc); >> + } >> + >> + return true; >> +} >> + >> /* >> * do_IRQ handles all normal device IRQ's (the special >> * SMP cross-CPU interrupts have their own specific >> @@ -200,31 +220,19 @@ >> { >> struct pt_regs *old_regs; >> /* high bit used in ret_from_ code */ >> - int overflow; >> unsigned vector = ~regs->orig_ax; >> - struct irq_desc *desc; >> unsigned irq; >> >> - >> old_regs = set_irq_regs(regs); >> irq_enter(); >> irq = __get_cpu_var(vector_irq)[vector]; >> >> - overflow = check_stack_overflow(); >> - >> - desc = irq_to_desc(irq); >> - if (unlikely(!desc)) { >> + if (!handle_irq(irq, regs)) { >> printk(KERN_EMERG "%s: cannot handle IRQ %d vector %#x cpu %d\n", >> __func__, irq, vector, smp_processor_id()); >> BUG(); >> } >> >> - if (!execute_on_irq_stack(overflow, desc, irq)) { >> - if (unlikely(overflow)) >> - print_stack_overflow(); >> - desc->handle_irq(irq, desc); >> - } >> - >> irq_exit(); >> set_irq_regs(old_regs); >> return 1; >> =================================================================== >> --- a/arch/x86/kernel/irq_64.c >> +++ b/arch/x86/kernel/irq_64.c >> @@ -40,6 +40,20 @@ >> #endif >> } >> >> +bool handle_irq(unsigned irq, struct pt_regs *regs) >> +{ >> + struct irq_desc *desc; >> + >> + stack_overflow_check(regs); >> + >> + desc = irq_to_desc(irq); >> + if (unlikely(!desc)) >> + return false; >> + >> + generic_handle_irq_desc(irq, desc); >> + return true; >> +} >> + >> /* >> * do_IRQ handles all normal device IRQ's (the special >> * SMP cross-CPU interrupts have their own specific >> @@ -48,7 +62,6 @@ >> asmlinkage unsigned int do_IRQ(struct pt_regs *regs) >> { >> struct pt_regs *old_regs = set_irq_regs(regs); >> - struct irq_desc *desc; >> >> /* high bit used in ret_from_ code */ >> unsigned vector = ~regs->orig_ax; >> @@ -56,14 +69,10 @@ >> >> exit_idle(); >> irq_enter(); >> + >> irq = __get_cpu_var(vector_irq)[vector]; >> >> - stack_overflow_check(regs); >> - >> - desc = irq_to_desc(irq); >> - if (likely(desc)) >> - generic_handle_irq_desc(irq, desc); >> - else { >> + if (!handle_irq(irq, regs)) { >> if (!disable_apic) >> ack_APIC_irq(); >> >> > > the changes look rather similar. Could you please look into unifying > irq_*.c before adding more logic to it? > I didn't really add more logic - I just hoisted some existing code into a new function. It does make do_IRQ() itself trivial to unify now. But the rest looks non-trivial: fixup_irqs() is quite different, as is the interrupt stack stuff. Hm, what does asmlinkage do on x86-64? J Subject: x86: unify do_IRQ() With the differences in interrupt handling hoisted into handle_irq(), do_IRQ is more or less identical between 32 and 64 bit, so unify it. Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com> --- arch/x86/include/asm/irq.h | 1 - arch/x86/kernel/irq.c | 41 +++++++++++++++++++++++++++++++++++++++++ arch/x86/kernel/irq_32.c | 27 --------------------------- arch/x86/kernel/irq_64.c | 33 --------------------------------- 4 files changed, 41 insertions(+), 61 deletions(-) =================================================================== --- a/arch/x86/include/asm/irq.h +++ b/arch/x86/include/asm/irq.h @@ -36,7 +36,6 @@ extern void fixup_irqs(cpumask_t map); #endif -extern unsigned int do_IRQ(struct pt_regs *regs); extern void init_IRQ(void); extern void native_init_IRQ(void); extern bool handle_irq(unsigned irq, struct pt_regs *regs); =================================================================== --- a/arch/x86/kernel/irq.c +++ b/arch/x86/kernel/irq.c @@ -5,10 +5,12 @@ #include <linux/interrupt.h> #include <linux/kernel_stat.h> #include <linux/seq_file.h> +#include <linux/ftrace.h> #include <asm/apic.h> #include <asm/io_apic.h> #include <asm/smp.h> +#include <asm/idle.h> atomic_t irq_err_count; @@ -195,3 +197,42 @@ #endif return sum; } + + +/* + * do_IRQ handles all normal device IRQ's (the special + * SMP cross-CPU interrupts have their own specific + * handlers). + */ +#ifdef CONFIG_X86_64 +asmlinkage +#endif +unsigned int __irq_entry do_IRQ(struct pt_regs *regs) +{ + struct pt_regs *old_regs = set_irq_regs(regs); + + /* high bit used in ret_from_ code */ + unsigned vector = ~regs->orig_ax; + unsigned irq; + + exit_idle(); + irq_enter(); + + irq = __get_cpu_var(vector_irq)[vector]; + + if (!handle_irq(irq, regs)) { +#ifdef CONFIG_X86_64 + if (!disable_apic) + ack_APIC_irq(); +#endif + + if (printk_ratelimit()) + printk(KERN_EMERG "%s: %d.%d No irq handler for vector (irq %d)\n", + __func__, smp_processor_id(), vector, irq); + } + + irq_exit(); + + set_irq_regs(old_regs); + return 1; +} =================================================================== --- a/arch/x86/kernel/irq_32.c +++ b/arch/x86/kernel/irq_32.c @@ -211,33 +211,6 @@ return true; } -/* - * do_IRQ handles all normal device IRQ's (the special - * SMP cross-CPU interrupts have their own specific - * handlers). - */ -unsigned int do_IRQ(struct pt_regs *regs) -{ - struct pt_regs *old_regs; - /* high bit used in ret_from_ code */ - unsigned vector = ~regs->orig_ax; - unsigned irq; - - old_regs = set_irq_regs(regs); - irq_enter(); - irq = __get_cpu_var(vector_irq)[vector]; - - if (!handle_irq(irq, regs)) { - printk(KERN_EMERG "%s: cannot handle IRQ %d vector %#x cpu %d\n", - __func__, irq, vector, smp_processor_id()); - BUG(); - } - - irq_exit(); - set_irq_regs(old_regs); - return 1; -} - #ifdef CONFIG_HOTPLUG_CPU #include <mach_apic.h> =================================================================== --- a/arch/x86/kernel/irq_64.c +++ b/arch/x86/kernel/irq_64.c @@ -55,39 +55,6 @@ return true; } -/* - * do_IRQ handles all normal device IRQ's (the special - * SMP cross-CPU interrupts have their own specific - * handlers). - */ -asmlinkage unsigned int __irq_entry do_IRQ(struct pt_regs *regs) -{ - struct pt_regs *old_regs = set_irq_regs(regs); - - /* high bit used in ret_from_ code */ - unsigned vector = ~regs->orig_ax; - unsigned irq; - - exit_idle(); - irq_enter(); - - irq = __get_cpu_var(vector_irq)[vector]; - - if (!handle_irq(irq, regs)) { - if (!disable_apic) - ack_APIC_irq(); - - if (printk_ratelimit()) - printk(KERN_EMERG "%s: %d.%d No irq handler for vector\n", - __func__, smp_processor_id(), vector); - } - - irq_exit(); - - set_irq_regs(old_regs); - return 1; -} - #ifdef CONFIG_HOTPLUG_CPU void fixup_irqs(cpumask_t map) { ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] x86: add handle_irq() to allow interrupt injection 2008-12-17 23:06 ` Jeremy Fitzhardinge @ 2008-12-18 5:28 ` Cyrill Gorcunov 0 siblings, 0 replies; 4+ messages in thread From: Cyrill Gorcunov @ 2008-12-18 5:28 UTC (permalink / raw) To: Jeremy Fitzhardinge Cc: Ingo Molnar, the arch/x86 maintainers, Linux Kernel Mailing List On Thu, Dec 18, 2008 at 2:06 AM, Jeremy Fitzhardinge <jeremy@goop.org> wrote: ... > +#ifdef CONFIG_X86_64 > +asmlinkage > +#endif > +unsigned int __irq_entry do_IRQ(struct pt_regs *regs) > +{ ... iirc asmlinkage is "none" on x86-64 so you could safely save it here without CONFIG. i hope I didn't miss anything :) ^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2008-12-18 5:28 UTC | newest] Thread overview: 4+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2008-12-16 20:34 [PATCH] x86: add handle_irq() to allow interrupt injection Jeremy Fitzhardinge 2008-12-16 20:49 ` Ingo Molnar 2008-12-17 23:06 ` Jeremy Fitzhardinge 2008-12-18 5:28 ` Cyrill Gorcunov
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox