Skip to content

Commit

Permalink
irq: arm: perform irqentry in entry code
Browse files Browse the repository at this point in the history
In preparation for removing HANDLE_DOMAIN_IRQ_IRQENTRY, have arch/arm
perform all the irqentry accounting in its entry code.

For configurations with CONFIG_GENERIC_IRQ_MULTI_HANDLER, we can use
generic_handle_arch_irq(). Other than asm_do_IRQ(), all C calls to
handle_IRQ() are from irqchip handlers which will be called from
generic_handle_arch_irq(), so to avoid double accounting IRQ entry, the
entry logic is moved from handle_IRQ() into asm_do_IRQ().

For ARMv7M the entry assembly is tightly coupled with the NVIC irqchip, and
while the entry code should logically live under arch/arm/, moving the
entry logic there makes things more convoluted. So for now, place the
entry logic in the NVIC irqchip, but separated into a separate
function to make the split of responsibility clear.

For all other configurations without CONFIG_GENERIC_IRQ_MULTI_HANDLER,
IRQ entry is already handled in arch code, and requires no changes.

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>
Tested-by: Vladimir Murzin <vladimir.murzin@arm.com> # ARMv7M
Cc: Russell King <linux@armlinux.org.uk>
Cc: Thomas Gleixner <tglx@linutronix.de>
  • Loading branch information
Mark Rutland committed Oct 25, 2021
1 parent 2fe35f8 commit a7b0872
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 12 deletions.
1 change: 0 additions & 1 deletion arch/arm/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ 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
Expand Down
5 changes: 1 addition & 4 deletions arch/arm/kernel/entry-armv.S
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,11 @@
*/
.macro irq_handler
#ifdef CONFIG_GENERIC_IRQ_MULTI_HANDLER
ldr r1, =handle_arch_irq
mov r0, sp
badr lr, 9997f
ldr pc, [r1]
bl generic_handle_arch_irq
#else
arch_irq_handler_default
#endif
9997:
.endm

.macro pabt_helper
Expand Down
14 changes: 8 additions & 6 deletions arch/arm/kernel/irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,8 @@ int arch_show_interrupts(struct seq_file *p, int prec)
*/
void handle_IRQ(unsigned int irq, struct pt_regs *regs)
{
struct pt_regs *old_regs = set_irq_regs(regs);
struct irq_desc *desc;

irq_enter();

/*
* Some hardware gives randomly wrong interrupts. Rather
* than crashing, do something sensible.
Expand All @@ -81,9 +78,6 @@ void handle_IRQ(unsigned int irq, struct pt_regs *regs)
handle_irq_desc(desc);
else
ack_bad_irq(irq);

irq_exit();
set_irq_regs(old_regs);
}

/*
Expand All @@ -92,7 +86,15 @@ void handle_IRQ(unsigned int irq, struct pt_regs *regs)
asmlinkage void __exception_irq_entry
asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
{
struct pt_regs *old_regs;

irq_enter();
old_regs = set_irq_regs(regs);

handle_IRQ(irq, regs);

set_irq_regs(old_regs);
irq_exit();
}

void __init init_IRQ(void)
Expand Down
17 changes: 16 additions & 1 deletion drivers/irqchip/irq-nvic.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,25 @@

static struct irq_domain *nvic_irq_domain;

static void __nvic_handle_irq(irq_hw_number_t hwirq, struct pt_regs *regs)
{
handle_domain_irq(nvic_irq_domain, hwirq, regs);
}

/*
* TODO: restructure the ARMv7M entry logic so that this entry logic can live
* in arch code.
*/
asmlinkage void __exception_irq_entry
nvic_handle_irq(irq_hw_number_t hwirq, struct pt_regs *regs)
{
handle_domain_irq(nvic_irq_domain, hwirq, regs);
struct pt_regs *old_regs;

irq_enter();
old_regs = set_irq_regs(regs);
__nvic_handle_irq(hwirq, regs);
set_irq_regs(old_regs);
irq_exit();
}

static int nvic_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
Expand Down

0 comments on commit a7b0872

Please sign in to comment.