From 2f312da35fe72073e32c4ac41a069878633382db Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Fri, 20 Feb 2026 17:09:20 +0800 Subject: [PATCH 1/3] vmlinux.lds.h: add _handle_arch_irq RUNTIME_CONST section We will use the runtime constant to optimize the handle_arch_irq accessing. This is preparation patch. Signed-off-by: Jisheng Zhang Signed-off-by: Linux RISC-V bot --- include/asm-generic/vmlinux.lds.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index eeb070f330bdb8..c4af2c7d0eedf7 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -973,7 +973,8 @@ RUNTIME_CONST(shift, d_hash_shift) \ RUNTIME_CONST(ptr, dentry_hashtable) \ RUNTIME_CONST(ptr, __dentry_cache) \ - RUNTIME_CONST(ptr, __names_cache) + RUNTIME_CONST(ptr, __names_cache) \ + RUNTIME_CONST(ptr, _handle_arch_irq) /* Alignment must be consistent with (kunit_suite *) in include/kunit/test.h */ #define KUNIT_TABLE() \ From e777f677562a617b15511c4ab78de6e4eaa7cb3c Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Fri, 20 Feb 2026 17:09:21 +0800 Subject: [PATCH 2/3] genirq: use runtime constant to optimize handle_arch_irq access Currently, on GENERIC_IRQ_MULTI_HANDLER platforms, the handle_arch_irq is a pointer which is set during booting, and every irq processing needs to access it, so it sits in hot code path. We can use the runtime constant mechanism which was introduced by Linus to speed up its accessing. Tested on Sipeed Lichee Pi 4A (riscv64) board, the perf sched benchmark is improved by ~5.8% Signed-off-by: Jisheng Zhang Signed-off-by: Linux RISC-V bot --- include/linux/irq.h | 4 +++- kernel/irq/handle.c | 8 +++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/include/linux/irq.h b/include/linux/irq.h index 951acbdb9f8457..2ba4a8afb71e33 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -1274,6 +1274,7 @@ void ipi_mux_process(void); int ipi_mux_create(unsigned int nr_ipi, void (*mux_send)(unsigned int cpu)); #ifdef CONFIG_GENERIC_IRQ_MULTI_HANDLER +#include /* * Registers a generic IRQ handling function as the top-level IRQ handler in * the system, which is generally the first C code called from an assembly @@ -1288,7 +1289,8 @@ int __init set_handle_irq(void (*handle_irq)(struct pt_regs *)); * Allows interrupt handlers to find the irqchip that's been registered as the * top-level IRQ handler. */ -extern void (*handle_arch_irq)(struct pt_regs *) __ro_after_init; +extern void (*_handle_arch_irq)(struct pt_regs *) __ro_after_init; +#define handle_arch_irq runtime_const_ptr(_handle_arch_irq) asmlinkage void generic_handle_arch_irq(struct pt_regs *regs); #else #ifndef set_handle_irq diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c index b7d52821837bc3..aac9e7b1301e3f 100644 --- a/kernel/irq/handle.c +++ b/kernel/irq/handle.c @@ -15,13 +15,14 @@ #include #include +#include #include #include "internals.h" #ifdef CONFIG_GENERIC_IRQ_MULTI_HANDLER -void (*handle_arch_irq)(struct pt_regs *) __ro_after_init; +void (*_handle_arch_irq)(struct pt_regs *) __ro_after_init; #endif /** @@ -270,10 +271,11 @@ irqreturn_t handle_irq_event(struct irq_desc *desc) #ifdef CONFIG_GENERIC_IRQ_MULTI_HANDLER int __init set_handle_irq(void (*handle_irq)(struct pt_regs *)) { - if (handle_arch_irq) + if (_handle_arch_irq) return -EBUSY; - handle_arch_irq = handle_irq; + _handle_arch_irq = handle_irq; + runtime_const_init(ptr, _handle_arch_irq); return 0; } From 7fa3cf53fe8eda5a9b990930272ead93342a30cc Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Fri, 20 Feb 2026 17:09:22 +0800 Subject: [PATCH 3/3] arm64: use runtime constant to optimize handle_arch_irq access Currently, on arm64 platforms, the handle_arch_irq is a pointer which is set during booting, and every irq processing needs to access it, so it sits in hot code path. We can use the runtime constant mechanism which was introduced by Linus to speed up its accessing. Tested on Quad CA55 platform, the perf sched benchmark is improved by ~6.5% Signed-off-by: Jisheng Zhang Signed-off-by: Linux RISC-V bot --- arch/arm64/kernel/entry-common.c | 4 +++- arch/arm64/kernel/irq.c | 9 ++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c index 3625797e9ee8f9..46a4c012e15f27 100644 --- a/arch/arm64/kernel/entry-common.c +++ b/arch/arm64/kernel/entry-common.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -139,7 +140,8 @@ static void do_interrupt_handler(struct pt_regs *regs, set_irq_regs(old_regs); } -extern void (*handle_arch_irq)(struct pt_regs *); +extern void (*_handle_arch_irq)(struct pt_regs *); +#define handle_arch_irq runtime_const_ptr(_handle_arch_irq) extern void (*handle_arch_fiq)(struct pt_regs *); static void noinstr __panic_unhandled(struct pt_regs *regs, const char *vector, diff --git a/arch/arm64/kernel/irq.c b/arch/arm64/kernel/irq.c index 15dedb385b9e4c..30629c183606b2 100644 --- a/arch/arm64/kernel/irq.c +++ b/arch/arm64/kernel/irq.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -84,15 +85,17 @@ static void default_handle_fiq(struct pt_regs *regs) panic("FIQ taken without a root FIQ handler\n"); } -void (*handle_arch_irq)(struct pt_regs *) __ro_after_init = default_handle_irq; +void (*_handle_arch_irq)(struct pt_regs *) __ro_after_init = default_handle_irq; +#define handle_arch_irq runtime_const_ptr(_handle_arch_irq) void (*handle_arch_fiq)(struct pt_regs *) __ro_after_init = default_handle_fiq; int __init set_handle_irq(void (*handle_irq)(struct pt_regs *)) { - if (handle_arch_irq != default_handle_irq) + if (_handle_arch_irq != default_handle_irq) return -EBUSY; - handle_arch_irq = handle_irq; + _handle_arch_irq = handle_irq; + runtime_const_init(ptr, _handle_arch_irq); pr_info("Root IRQ handler: %ps\n", handle_irq); return 0; }