[RFC] rust: kernel: Add KUnit tests for ARCH_WARN_ASM bug table emission

Peter Zijlstra peterz at infradead.org
Thu Sep 24 04:15:57 PDT 2026


On Wed, Sep 23, 2026 at 11:58:13AM +0530, Mukesh Kumar Chaurasiya wrote:
> On Tue, Sep 22, 2026 at 08:47:35AM +0200, Peter Zijlstra wrote:
> > On Tue, Sep 22, 2026 at 11:20:00AM +0530, Mukesh Kumar Chaurasiya (IBM) wrote:
> > > Verify that the __bug_table entry emitted by ARCH_WARN_ASM has a correct
> > > bug_addr displacement — i.e. the arch's trap label reference resolves to
> > > the trap instruction — by calling find_bug() with the exact virtual address
> > > of the trap, mirroring what the real trap handler does.
> > > 
> > > To support all architectures, each arch that implements ARCH_WARN_ASM now
> > > defines ARCH_WARN_ASM_TRAP_LABEL, a string constant naming the local label
> > > at which the trap instruction is placed:
> > > 
> > >   x86       "1"     (ud2 at label 1:)
> > >   powerpc   "1"     (twi at label 1:)
> > >   riscv     "1"     (ebreak at label 1:)
> > >   arm64     "14471" (brk placed at 14471: by __BUG_ENTRY_END)
> > >   s390      "0"     (mc at label 0:)
> > > 
> > > The label is used consistently: in ARCH_WARN_ASM itself, in the
> > > bug_addr back-reference inside __BUG_ENTRY / _EMIT_BUG_ENTRY, 
> > 
> > 
> > > diff --git a/arch/x86/include/asm/bug.h b/arch/x86/include/asm/bug.h
> > > index 23ab05438269..6cca8880660e 100644
> > > --- a/arch/x86/include/asm/bug.h
> > > +++ b/arch/x86/include/asm/bug.h
> > > @@ -62,8 +62,9 @@ extern void __WARN_trap(struct bug_entry *bug, ...);
> > >  #define HAVE_ARCH_BUG_FORMAT_ARGS
> > >  #endif
> > >  
> > > +#define ARCH_WARN_ASM_TRAP_LABEL "1"
> > >  #define __BUG_ENTRY(format, file, line, flags)				\
> > > -	"\t.long 1b - ."	"\t# bug_entry::bug_addr\n"		\
> > > +	"\t.long " ARCH_WARN_ASM_TRAP_LABEL "b - ." "\t# bug_entry::bug_addr\n" \
> > >  	__BUG_ENTRY_FORMAT(format)					\
> > >  	__BUG_ENTRY_VERBOSE(file, line)					\
> > >  	"\t.word " flags	"\t# bug_entry::flags\n"
> > > @@ -101,7 +102,7 @@ do {									\
> > >  	"99:\n"								\
> > >  	"\t.string \"\"\n"						\
> > >  	".popsection\n"							\
> > > -	"1:\t " ASM_UD2 "\n"						\
> > > +	ARCH_WARN_ASM_TRAP_LABEL ":\t " ASM_UD2 "\n"			\
> > >  	_BUG_FLAGS_ASM("99b", file, line, flags, size, "")
> > >  
> > >  #else
> > 
> > Not really a fan of that. And I can't really tell what you're doing with
> > it either. The kunit is in Rust and thus unreadable :-(
> > 
> > I would rather you fix up is_valid_bugaddr(), some architectures seem to
> > have an always true stub because of the callchains always being from the
> > break instruction.
> 
> Hey Peter,
> 
> thanks for the suggestion. I will fix up the is_valid_bugaddr for
> powerpc. I am not very good with other archs asm but i can do it for
> ppc32 and ppc64.

Untested thingies for arm64 and s390x.

diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
index 914282016069..3d8a969eab5f 100644
--- a/arch/arm64/kernel/traps.c
+++ b/arch/arm64/kernel/traps.c
@@ -987,14 +987,13 @@ void do_serror(struct pt_regs *regs, unsigned long esr)
 #ifdef CONFIG_GENERIC_BUG
 int is_valid_bugaddr(unsigned long addr)
 {
-	/*
-	 * bug_brk_handler() only called for BRK #BUG_BRK_IMM.
-	 * So the answer is trivial -- any spurious instances with no
-	 * bug table entry will be rejected by report_bug() and passed
-	 * back to the debug-monitors code and handled as a fatal
-	 * unexpected debug exception.
-	 */
-	return 1;
+	u32 insn;
+
+	if (aarch64_insn_read((u32 *)addr, &insn))
+		return 0;
+
+	/* Match ASM_BUG_FLAGS() / BUG() instructions. */
+	return insn == (0xd4200000 | (BUG_BRK_IMM << 5));
 }
 #endif
 
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
index b6ba4465f59d..8bbb082fd5e3 100644
--- a/arch/s390/kernel/traps.c
+++ b/arch/s390/kernel/traps.c
@@ -26,6 +26,7 @@
 #include <linux/entry-common.h>
 #include <linux/kmsan.h>
 #include <linux/bug.h>
+#include <linux/uaccess.h>
 #include <asm/entry-percpu.h>
 #include <asm/asm-extable.h>
 #include <asm/irqflags.h>
@@ -55,7 +56,12 @@ static inline void __user *get_trap_ip(struct pt_regs *regs)
 #ifdef CONFIG_GENERIC_BUG
 int is_valid_bugaddr(unsigned long addr)
 {
-	return 1;
+	u16 insn;
+
+	if (get_kernel_nofault(insn, (u16 *)addr))
+		return 0;
+
+	return insn == 0x0001 || insn == 0x000e;
 }
 #endif
 



More information about the linux-riscv mailing list