Jan Kiszka <[email protected]> writes:
> On 07.09.20 15:09, Philippe Gerum wrote: >> 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 >> > > This practically only affected us with GPIOs so far, right? > To my knowledge, yes. -- Philippe.
