irq: add a (temporary) CONFIG_HANDLE_DOMAIN_IRQ_IRQENTRY
Going forward we want architecture/entry code to perform all the necessary work to enter/exit IRQ context, with irqchip code merely handling the mapping of the interrupt to any handler(s). Among other reasons, this is necessary to consistently fix some longstanding issues with the ordering of lockdep/RCU/tracing instrumentation which many architectures get wrong today in their entry code. Importantly, rcu_irq_{enter,exit}() must be called precisely once per IRQ exception, so that rcu_is_cpu_rrupt_from_idle() can correctly identify when an interrupt was taken from an idle context which must be explicitly preempted. Currently handle_domain_irq() calls rcu_irq_{enter,exit}() via irq_{enter,exit}(), but entry code needs to be able to call rcu_irq_{enter,exit}() earlier for correct ordering across lockdep/RCU/tracing updates for sequences such as: lockdep_hardirqs_off(CALLER_ADDR0); rcu_irq_enter(); trace_hardirqs_off_finish(); To permit each architecture to be converted to the new style in turn, this patch adds a new CONFIG_HANDLE_DOMAIN_IRQ_IRQENTRY selected by all current users of HANDLE_DOMAIN_IRQ, which gates the existing behaviour. When CONFIG_HANDLE_DOMAIN_IRQ_IRQENTRY is not selected, handle_domain_irq() requires entry code to perform the irq_{enter,exit}() work, with an explicit check for this matching the style of handle_domain_nmi(). Subsequent patches will: 1) Add the necessary IRQ entry accounting to each architecture in turn, dropping CONFIG_HANDLE_DOMAIN_IRQ_IRQENTRY from that architecture's Kconfig. 2) Remove CONFIG_HANDLE_DOMAIN_IRQ_IRQENTRY once it is no longer selected. 3) Convert irqchip drivers to consistently use generic_handle_domain_irq() rather than handle_domain_irq(). 4) Remove handle_domain_irq() and CONFIG_HANDLE_DOMAIN_IRQ. ... which should leave us with a clear split of responsiblity across the entry and irqchip code, making it possible to perform additional cleanups and fixes for the aforementioned longstanding issues with entry code. There should be no functional change as a result of this patch. Signed-off-by: Mark Rutland <mark.rutland@arm.com> Reviewed-by: Marc Zyngier <maz@kernel.org> Cc: Thomas Gleixner <tglx@linutronix.de>
This commit is contained in:
parent
6f877e13c2
commit
2fe35f8ee7
|
@ -65,6 +65,7 @@ config ARM
|
|||
select GENERIC_SCHED_CLOCK
|
||||
select GENERIC_SMP_IDLE_THREAD
|
||||
select HANDLE_DOMAIN_IRQ
|
||||
select HANDLE_DOMAIN_IRQ_IRQENTRY
|
||||
select HARDIRQS_SW_RESEND
|
||||
select HAVE_ARCH_AUDITSYSCALL if AEABI && !OABI_COMPAT
|
||||
select HAVE_ARCH_BITREVERSE if (CPU_32v7M || CPU_32v7) && !CPU_32v6
|
||||
|
|
|
@ -134,6 +134,7 @@ config ARM64
|
|||
select GENERIC_GETTIMEOFDAY
|
||||
select GENERIC_VDSO_TIME_NS
|
||||
select HANDLE_DOMAIN_IRQ
|
||||
select HANDLE_DOMAIN_IRQ_IRQENTRY
|
||||
select HARDIRQS_SW_RESEND
|
||||
select HAVE_MOVE_PMD
|
||||
select HAVE_MOVE_PUD
|
||||
|
|
|
@ -18,6 +18,7 @@ config CSKY
|
|||
select DMA_DIRECT_REMAP
|
||||
select IRQ_DOMAIN
|
||||
select HANDLE_DOMAIN_IRQ
|
||||
select HANDLE_DOMAIN_IRQ_IRQENTRY
|
||||
select DW_APB_TIMER_OF
|
||||
select GENERIC_IOREMAP
|
||||
select GENERIC_LIB_ASHLDI3
|
||||
|
|
|
@ -14,6 +14,7 @@ config OPENRISC
|
|||
select OF_EARLY_FLATTREE
|
||||
select IRQ_DOMAIN
|
||||
select HANDLE_DOMAIN_IRQ
|
||||
select HANDLE_DOMAIN_IRQ_IRQENTRY
|
||||
select GPIOLIB
|
||||
select HAVE_ARCH_TRACEHOOK
|
||||
select SPARSE_IRQ
|
||||
|
|
|
@ -63,6 +63,7 @@ config RISCV
|
|||
select GENERIC_SMP_IDLE_THREAD
|
||||
select GENERIC_TIME_VSYSCALL if MMU && 64BIT
|
||||
select HANDLE_DOMAIN_IRQ
|
||||
select HANDLE_DOMAIN_IRQ_IRQENTRY
|
||||
select HAVE_ARCH_AUDITSYSCALL
|
||||
select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL
|
||||
select HAVE_ARCH_JUMP_LABEL_RELATIVE if !XIP_KERNEL
|
||||
|
|
|
@ -100,6 +100,10 @@ config IRQ_MSI_IOMMU
|
|||
config HANDLE_DOMAIN_IRQ
|
||||
bool
|
||||
|
||||
# Legacy behaviour; architectures should call irq_{enter,exit}() themselves
|
||||
config HANDLE_DOMAIN_IRQ_IRQENTRY
|
||||
bool
|
||||
|
||||
config IRQ_TIMINGS
|
||||
bool
|
||||
|
||||
|
|
|
@ -676,6 +676,7 @@ int generic_handle_domain_irq(struct irq_domain *domain, unsigned int hwirq)
|
|||
EXPORT_SYMBOL_GPL(generic_handle_domain_irq);
|
||||
|
||||
#ifdef CONFIG_HANDLE_DOMAIN_IRQ
|
||||
#ifdef CONFIG_HANDLE_DOMAIN_IRQ_IRQENTRY
|
||||
/**
|
||||
* handle_domain_irq - Invoke the handler for a HW irq belonging to a domain,
|
||||
* usually for a root interrupt controller
|
||||
|
@ -699,6 +700,35 @@ int handle_domain_irq(struct irq_domain *domain,
|
|||
set_irq_regs(old_regs);
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
/**
|
||||
* handle_domain_irq - Invoke the handler for a HW irq belonging to a domain,
|
||||
* usually for a root interrupt controller
|
||||
* @domain: The domain where to perform the lookup
|
||||
* @hwirq: The HW irq number to convert to a logical one
|
||||
* @regs: Register file coming from the low-level handling code
|
||||
*
|
||||
* This function must be called from an IRQ context.
|
||||
*
|
||||
* Returns: 0 on success, or -EINVAL if conversion has failed
|
||||
*/
|
||||
int handle_domain_irq(struct irq_domain *domain,
|
||||
unsigned int hwirq, struct pt_regs *regs)
|
||||
{
|
||||
struct pt_regs *old_regs = set_irq_regs(regs);
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* IRQ context needs to be setup earlier.
|
||||
*/
|
||||
WARN_ON(!in_irq());
|
||||
|
||||
ret = generic_handle_domain_irq(domain, hwirq);
|
||||
|
||||
set_irq_regs(old_regs);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* handle_domain_nmi - Invoke the handler for a HW irq belonging to a domain
|
||||
|
|
Loading…
Reference in New Issue