From: Philippe Gerum <[email protected]>

IRQs chained from a parent interrupt (e.g. cascaded interrupts from
chained GPIO irqchips) do not have any assigned vector. Therefore, we
cannot expect __ipipe_get_ioapic_irq_vector() to return anything
sensible for those chained IRQs.

As a result, the interrupt trampoline (__ipipe_do_IRQ()) for the root
stage cannot fix up regs->orig_ax with the proper vector number which
do_IRQ() would use in turn to fetch the corresponding interrupt
descriptor.

Since we already know the IRQ number on entry to __ipipe_do_IRQ(),
rewrite the latter as a variant of do_IRQ() which either retrieves the
descriptor using irq_to_desc() for all device interrupts in order to
fetch the flow handler, or invokes the naked handler of special APIC
vectors directly.

Signed-off-by: Philippe Gerum <[email protected]>
---
 arch/x86/kernel/ipipe.c  | 13 ++-----------
 arch/x86/kernel/irq_64.c | 29 +++++++++++++++++++++++++++++
 2 files changed, 31 insertions(+), 11 deletions(-)

diff --git a/arch/x86/kernel/ipipe.c b/arch/x86/kernel/ipipe.c
index 4b0955c3ff49..3f3afcecc1b9 100644
--- a/arch/x86/kernel/ipipe.c
+++ b/arch/x86/kernel/ipipe.c
@@ -73,6 +73,8 @@ void smp_reboot_interrupt(void);
 void smp_thermal_interrupt(struct pt_regs *regs);
 void smp_threshold_interrupt(struct pt_regs *regs);
 
+void __ipipe_do_IRQ(unsigned int irq, void *cookie);
+
 DEFINE_PER_CPU(unsigned long, __ipipe_cr2);
 EXPORT_PER_CPU_SYMBOL_GPL(__ipipe_cr2);
 
@@ -88,17 +90,6 @@ int ipipe_get_sysinfo(struct ipipe_sysinfo *info)
 }
 EXPORT_SYMBOL_GPL(ipipe_get_sysinfo);
 
-static void __ipipe_do_IRQ(unsigned int irq, void *cookie)
-{
-       void (*handler)(struct pt_regs *regs);
-       struct pt_regs *regs;
-
-       regs = raw_cpu_ptr(&ipipe_percpu.tick_regs);
-       regs->orig_ax = ~__ipipe_get_irq_vector(irq);
-       handler = (typeof(handler))cookie;
-       handler(regs);
-}
-
 #ifdef CONFIG_X86_LOCAL_APIC
 
 static void __ipipe_noack_apic(struct irq_desc *desc)
diff --git a/arch/x86/kernel/irq_64.c b/arch/x86/kernel/irq_64.c
index b2b2a3f41daf..7fc8ad19940c 100644
--- a/arch/x86/kernel/irq_64.c
+++ b/arch/x86/kernel/irq_64.c
@@ -89,3 +89,32 @@ bool handle_irq(struct irq_desc *desc, struct pt_regs *regs)
        generic_handle_irq_desc(desc);
        return true;
 }
+
+#ifdef CONFIG_IPIPE
+
+void __ipipe_do_IRQ(unsigned int irq, void *cookie)
+{
+       struct pt_regs *regs = raw_cpu_ptr(&ipipe_percpu.tick_regs);
+       struct pt_regs *old_regs = set_irq_regs(regs);
+       unsigned int (*handler)(struct pt_regs *regs);
+       struct irq_desc *desc;
+
+       handler = (typeof(handler))cookie;
+
+       entering_irq();
+
+       stack_overflow_check(regs);
+
+       if (handler == do_IRQ) {
+               desc = irq_to_desc(irq);
+               generic_handle_irq_desc(desc);
+       } else {
+               handler(regs);
+       }
+
+       exiting_irq();
+
+       set_irq_regs(old_regs);
+}
+
+#endif
-- 
2.26.2


Reply via email to