[PATCH 3/6] x86/ipipe: fix chained irq handling
Philippe Gerum
rpm at xenomai.org
Mon Sep 7 17:17:35 CEST 2020
Jan Kiszka <jan.kiszka at siemens.com> writes:
> On 07.09.20 15:09, Philippe Gerum wrote:
>> From: Philippe Gerum <rpm at xenomai.org>
>>
>> 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 <rpm at xenomai.org>
>> ---
>> 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.
More information about the Xenomai
mailing list