[PATCH] arm64: set __exception_irq_entry with __irq_entry as a default

Mark Rutland mark.rutland at arm.com
Tue Apr 25 06:39:51 PDT 2023


On Tue, Apr 25, 2023 at 11:31:31AM +0900, Youngmin Nam wrote:
> On Mon, Apr 24, 2023 at 02:08:14PM +0100, Mark Rutland wrote:
> > On Mon, Apr 24, 2023 at 02:09:05PM +0200, Dmitry Vyukov wrote:
> > > On Mon, 24 Apr 2023 at 13:01, Mark Rutland <mark.rutland at arm.com> wrote:
> > > >
> > > > On Mon, Apr 24, 2023 at 10:04:36AM +0900, Youngmin Nam wrote:
> > > > > filter_irq_stacks() is supposed to cut entries which are related irq entries
> > > > > from its call stack.
> > > > > And in_irqentry_text() which is called by filter_irq_stacks()
> > > > > uses __irqentry_text_start/end symbol to find irq entries in callstack.
> > > > >
> > > > > But it doesn't work correctly as without "CONFIG_FUNCTION_GRAPH_TRACER",
> > > > > arm64 kernel doesn't include gic_handle_irq which is entry point of arm64 irq
> > > > > between __irqentry_text_start and __irqentry_text_end as we discussed in below link.
> > > >
> > > > TBH, the __irqentry_text annotations don't make much sense, and I'd love to
> > > > remove them.
> > > >
> > > > The irqchip handlers are not the actual exception entry points, and we invoke a
> > > > fair amount of code between those and the actual IRQ handlers (e.g. to map from
> > > > the irq domain to the actual hander, which might involve poking chained irqchip
> > > > handlers), so it doesn't make much sense for the irqchip handlers to be
> > > > special.
> > > >
> > > > > https://lore.kernel.org/all/CACT4Y+aReMGLYua2rCLHgFpS9io5cZC04Q8GLs-uNmrn1ezxYQ@mail.gmail.com/#t
> > > > >
> > > > > This problem can makes unintentional deep call stack entries especially
> > > > > in KASAN enabled situation as below.
> > > >
> > > > What exactly does KASAN need here? Is this just to limit the depth of the
> > > > trace?
> > > 
> > > No, it's not just depth. Any uses of stack depot need stable
> > > repeatable traces, so that they are deduplicated well. For irq stacks
> > > it means removing the random part where the interrupt is delivered.
> > > Otherwise stack depot grows without limits and overflows.
> 
> Hi Dmitry Vyukov.
> Thanks for your additional comments.
> 
> > 
> > Sure -- you want to filter out the non-deterministic context that the interrupt
> > was taken *from*.
> > 
> > > We don't need the exact entry point for this. A frame "close enough"
> > > may work well if there are no memory allocations/frees skipped.
> > 
> > With that in mind, I think what we should do is cut this at the instant we
> > enter the exception; for the trace below that would be el1h_64_irq. I've added
> > some line spacing there to make it stand out.
> > 
> > That would mean that we'd have three entry points that an interrupt trace might
> > start from:
> > 
> > * el1h_64_irq()
> > * el0t_64_irq()
> > * el0t_32_irq()
> >
> 
> Hi Mark.
> Thanks for your kind review.
> 
> If I understand your intention corretly, I should add "__irq_entry"
> to C function of irq_handler as below.

I'd meant something like the below, marking the assembly (as x86 does) rather
than the C code. I'll try to sort that out and send a proper patch series after
-rc1.

Thanks,
Mark.

---->8----
>From 7e54be3ea2420af348c710afab743b94ced72881 Mon Sep 17 00:00:00 2001
From: Mark Rutland <mark.rutland at arm.com>
Date: Tue, 25 Apr 2023 14:13:39 +0100
Subject: [PATCH] WIP: arm64: entry: handle irqentry consistently

Follow the example of x86 in commit:

  f0178fc01fe46bab ("x86/entry: Unbreak __irqentry_text_start/end magic")

... and consistently treat the asm IRQ/FIQ entry points as irqentry, and
nothing else.

TODO:
* Explain stackdepot details
* Explain why dropping __kprobes is fine
* Explain why placing entry asm in .irqentry.text is fine.
* Explain why we don't need to mark ret_to_* or the actual vector
* Check how this works for ftrace

Signed-off-by: Mark Rutland <mark.rutland at arm.com>
---
 arch/arm64/include/asm/exception.h | 10 +++++-----
 arch/arm64/include/asm/irq.h       |  6 ++++++
 arch/arm64/kernel/entry.S          | 20 +++++++++++---------
 drivers/irqchip/irq-dw-apb-ictl.c  |  4 +++-
 4 files changed, 25 insertions(+), 15 deletions(-)

diff --git a/arch/arm64/include/asm/exception.h b/arch/arm64/include/asm/exception.h
index 92963f98afece..6c74a8a3aad99 100644
--- a/arch/arm64/include/asm/exception.h
+++ b/arch/arm64/include/asm/exception.h
@@ -13,11 +13,11 @@
 
 #include <linux/interrupt.h>
 
-#ifdef CONFIG_FUNCTION_GRAPH_TRACER
-#define __exception_irq_entry	__irq_entry
-#else
-#define __exception_irq_entry	__kprobes
-#endif
+/*
+ * irqchip drivers shared with arch/arm mark IRQ handlers with
+ * __exception_irq_entry. Make this a NOP for arm64.
+ */
+#define __exception_irq_entry
 
 static inline unsigned long disr_to_esr(u64 disr)
 {
diff --git a/arch/arm64/include/asm/irq.h b/arch/arm64/include/asm/irq.h
index fac08e18bcd51..a1af8fafc6cb5 100644
--- a/arch/arm64/include/asm/irq.h
+++ b/arch/arm64/include/asm/irq.h
@@ -6,6 +6,12 @@
 
 #include <asm-generic/irq.h>
 
+/*
+ * The irq entry code is in assembly. Make the build fail if
+ * something moves a C function into the __irq_entry section.
+ */
+#define __irq_entry __invalid_section
+
 struct pt_regs;
 
 int set_handle_irq(void (*handle_irq)(struct pt_regs *));
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index ab2a6e33c0528..a66cd0ce79956 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -562,7 +562,8 @@ SYM_CODE_END(__bad_stack)
 #endif /* CONFIG_VMAP_STACK */
 
 
-	.macro entry_handler el:req, ht:req, regsize:req, label:req
+	.macro entry_handler el:req, ht:req, regsize:req, label:req, section = ".entry.text"
+	.pushsection \section, "ax"
 SYM_CODE_START_LOCAL(el\el\ht\()_\regsize\()_\label)
 	kernel_entry \el, \regsize
 	mov	x0, sp
@@ -573,29 +574,30 @@ SYM_CODE_START_LOCAL(el\el\ht\()_\regsize\()_\label)
 	b	ret_to_kernel
 	.endif
 SYM_CODE_END(el\el\ht\()_\regsize\()_\label)
+	.popsection
 	.endm
 
 /*
  * Early exception handlers
  */
 	entry_handler	1, t, 64, sync
-	entry_handler	1, t, 64, irq
-	entry_handler	1, t, 64, fiq
+	entry_handler	1, t, 64, irq,	".irqentry.text"
+	entry_handler	1, t, 64, fiq,	".irqentry.text"
 	entry_handler	1, t, 64, error
 
 	entry_handler	1, h, 64, sync
-	entry_handler	1, h, 64, irq
-	entry_handler	1, h, 64, fiq
+	entry_handler	1, h, 64, irq,	".irqentry.text"
+	entry_handler	1, h, 64, fiq,	".irqentry.text"
 	entry_handler	1, h, 64, error
 
 	entry_handler	0, t, 64, sync
-	entry_handler	0, t, 64, irq
-	entry_handler	0, t, 64, fiq
+	entry_handler	0, t, 64, irq,	".irqentry.text"
+	entry_handler	0, t, 64, fiq,	".irqentry.text"
 	entry_handler	0, t, 64, error
 
 	entry_handler	0, t, 32, sync
-	entry_handler	0, t, 32, irq
-	entry_handler	0, t, 32, fiq
+	entry_handler	0, t, 32, irq,	".irqentry.text"
+	entry_handler	0, t, 32, fiq,	".irqentry.text"
 	entry_handler	0, t, 32, error
 
 SYM_CODE_START_LOCAL(ret_to_kernel)
diff --git a/drivers/irqchip/irq-dw-apb-ictl.c b/drivers/irqchip/irq-dw-apb-ictl.c
index d5c1c750c8d2d..ad315bdfc3ef6 100644
--- a/drivers/irqchip/irq-dw-apb-ictl.c
+++ b/drivers/irqchip/irq-dw-apb-ictl.c
@@ -19,6 +19,8 @@
 #include <linux/of_irq.h>
 #include <linux/interrupt.h>
 
+#include <asm/exception.h>
+
 #define APB_INT_ENABLE_L	0x00
 #define APB_INT_ENABLE_H	0x04
 #define APB_INT_MASK_L		0x08
@@ -30,7 +32,7 @@
 /* irq domain of the primary interrupt controller. */
 static struct irq_domain *dw_apb_ictl_irq_domain;
 
-static void __irq_entry dw_apb_ictl_handle_irq(struct pt_regs *regs)
+static void __exception_irq_entry dw_apb_ictl_handle_irq(struct pt_regs *regs)
 {
 	struct irq_domain *d = dw_apb_ictl_irq_domain;
 	int n;
-- 
2.30.2




More information about the linux-arm-kernel mailing list