From aec58b48517c911fbdf2beebba46a347e5910072 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 15 May 2025 14:46:30 +0200 Subject: [PATCH 01/31] bugs/core: Extend __WARN_FLAGS() with the 'cond_str' parameter Push the new parameter down into every architecture that defines __WARN_FLAGS(): arm64 loongarch parisc powerpc riscv s390 sh x86 Don't pass anything substantial down yet, just propagate the new parameter with empty strings, without generating it or using it. ( The string is never NULL, so it can be concatenated at the preprocessor level. ) Signed-off-by: Ingo Molnar Acked-by: Peter Zijlstra Cc: Linus Torvalds Cc: linux-arch@vger.kernel.org Link: https://lore.kernel.org/r/20250515124644.2958810-2-mingo@kernel.org --- arch/arm64/include/asm/bug.h | 2 +- arch/loongarch/include/asm/bug.h | 2 +- arch/parisc/include/asm/bug.h | 4 ++-- arch/powerpc/include/asm/bug.h | 2 +- arch/riscv/include/asm/bug.h | 2 +- arch/s390/include/asm/bug.h | 2 +- arch/sh/include/asm/bug.h | 2 +- arch/x86/include/asm/bug.h | 2 +- include/asm-generic/bug.h | 7 ++++--- 9 files changed, 13 insertions(+), 12 deletions(-) diff --git a/arch/arm64/include/asm/bug.h b/arch/arm64/include/asm/bug.h index 28be048db3f6..bceeaec21fb9 100644 --- a/arch/arm64/include/asm/bug.h +++ b/arch/arm64/include/asm/bug.h @@ -19,7 +19,7 @@ unreachable(); \ } while (0) -#define __WARN_FLAGS(flags) __BUG_FLAGS(BUGFLAG_WARNING|(flags)) +#define __WARN_FLAGS(cond_str, flags) __BUG_FLAGS(BUGFLAG_WARNING|(flags)) #define HAVE_ARCH_BUG diff --git a/arch/loongarch/include/asm/bug.h b/arch/loongarch/include/asm/bug.h index f6f254f2c5db..51c2cb98d728 100644 --- a/arch/loongarch/include/asm/bug.h +++ b/arch/loongarch/include/asm/bug.h @@ -42,7 +42,7 @@ asm_inline volatile (__stringify(ASM_BUG_FLAGS(flags)) \ extra); -#define __WARN_FLAGS(flags) \ +#define __WARN_FLAGS(cond_str, flags) \ do { \ instrumentation_begin(); \ __BUG_FLAGS(BUGFLAG_WARNING|(flags), ANNOTATE_REACHABLE(10001b));\ diff --git a/arch/parisc/include/asm/bug.h b/arch/parisc/include/asm/bug.h index 833555f74ffa..1a87cf80ec3c 100644 --- a/arch/parisc/include/asm/bug.h +++ b/arch/parisc/include/asm/bug.h @@ -50,7 +50,7 @@ #endif #ifdef CONFIG_DEBUG_BUGVERBOSE -#define __WARN_FLAGS(flags) \ +#define __WARN_FLAGS(cond_str, flags) \ do { \ asm volatile("\n" \ "1:\t" PARISC_BUG_BREAK_ASM "\n" \ @@ -66,7 +66,7 @@ "i" (sizeof(struct bug_entry)) ); \ } while(0) #else -#define __WARN_FLAGS(flags) \ +#define __WARN_FLAGS(cond_str, flags) \ do { \ asm volatile("\n" \ "1:\t" PARISC_BUG_BREAK_ASM "\n" \ diff --git a/arch/powerpc/include/asm/bug.h b/arch/powerpc/include/asm/bug.h index 1db485aacbd9..34d39ec79720 100644 --- a/arch/powerpc/include/asm/bug.h +++ b/arch/powerpc/include/asm/bug.h @@ -72,7 +72,7 @@ } while (0) #define HAVE_ARCH_BUG -#define __WARN_FLAGS(flags) BUG_ENTRY("twi 31, 0, 0", BUGFLAG_WARNING | (flags)) +#define __WARN_FLAGS(cond_str, flags) BUG_ENTRY("twi 31, 0, 0", BUGFLAG_WARNING | (flags)) #ifdef CONFIG_PPC64 #define BUG_ON(x) do { \ diff --git a/arch/riscv/include/asm/bug.h b/arch/riscv/include/asm/bug.h index 1aaea81fb141..b22ee4d2c882 100644 --- a/arch/riscv/include/asm/bug.h +++ b/arch/riscv/include/asm/bug.h @@ -76,7 +76,7 @@ do { \ unreachable(); \ } while (0) -#define __WARN_FLAGS(flags) __BUG_FLAGS(BUGFLAG_WARNING|(flags)) +#define __WARN_FLAGS(cond_str, flags) __BUG_FLAGS(BUGFLAG_WARNING|(flags)) #define HAVE_ARCH_BUG diff --git a/arch/s390/include/asm/bug.h b/arch/s390/include/asm/bug.h index c500d45fb465..ef3e495ec1e3 100644 --- a/arch/s390/include/asm/bug.h +++ b/arch/s390/include/asm/bug.h @@ -46,7 +46,7 @@ unreachable(); \ } while (0) -#define __WARN_FLAGS(flags) do { \ +#define __WARN_FLAGS(cond_str, flags) do { \ __EMIT_BUG(BUGFLAG_WARNING|(flags)); \ } while (0) diff --git a/arch/sh/include/asm/bug.h b/arch/sh/include/asm/bug.h index 05a485c4fabc..834c621ab249 100644 --- a/arch/sh/include/asm/bug.h +++ b/arch/sh/include/asm/bug.h @@ -52,7 +52,7 @@ do { \ unreachable(); \ } while (0) -#define __WARN_FLAGS(flags) \ +#define __WARN_FLAGS(cond_str, flags) \ do { \ __asm__ __volatile__ ( \ "1:\t.short %O0\n" \ diff --git a/arch/x86/include/asm/bug.h b/arch/x86/include/asm/bug.h index f0e9acf72547..413b86b876d9 100644 --- a/arch/x86/include/asm/bug.h +++ b/arch/x86/include/asm/bug.h @@ -92,7 +92,7 @@ do { \ * were to trigger, we'd rather wreck the machine in an attempt to get the * message out than not know about it. */ -#define __WARN_FLAGS(flags) \ +#define __WARN_FLAGS(cond_str, flags) \ do { \ __auto_type __flags = BUGFLAG_WARNING|(flags); \ instrumentation_begin(); \ diff --git a/include/asm-generic/bug.h b/include/asm-generic/bug.h index 387720933973..af76e4a04b16 100644 --- a/include/asm-generic/bug.h +++ b/include/asm-generic/bug.h @@ -100,17 +100,18 @@ extern __printf(1, 2) void __warn_printk(const char *fmt, ...); instrumentation_end(); \ } while (0) #else -#define __WARN() __WARN_FLAGS(BUGFLAG_TAINT(TAINT_WARN)) +#define __WARN() __WARN_FLAGS("", BUGFLAG_TAINT(TAINT_WARN)) #define __WARN_printf(taint, arg...) do { \ instrumentation_begin(); \ __warn_printk(arg); \ - __WARN_FLAGS(BUGFLAG_NO_CUT_HERE | BUGFLAG_TAINT(taint));\ + __WARN_FLAGS("", BUGFLAG_NO_CUT_HERE | BUGFLAG_TAINT(taint));\ instrumentation_end(); \ } while (0) #define WARN_ON_ONCE(condition) ({ \ int __ret_warn_on = !!(condition); \ if (unlikely(__ret_warn_on)) \ - __WARN_FLAGS(BUGFLAG_ONCE | \ + __WARN_FLAGS("", \ + BUGFLAG_ONCE | \ BUGFLAG_TAINT(TAINT_WARN)); \ unlikely(__ret_warn_on); \ }) From 3bc3c9c3ab6df45a3a3389f74000f8bec1bc96e3 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 15 May 2025 14:46:31 +0200 Subject: [PATCH 02/31] bugs/core: Pass down the condition string of WARN_ON_ONCE(cond) warnings to __WARN_FLAGS() Doing this will allow architecture code to store and print out this information as part of the WARN_ON and BUG_ON facilities. The format of the string is '[condition]', for example: WARN_ON_ONCE(idx < 0 && ptr); Will get the '[idx < 0 && ptr]' string literal passed down as 'cond_str' in __WARN_FLAGS(). Signed-off-by: Ingo Molnar Acked-by: Peter Zijlstra Cc: Linus Torvalds Cc: linux-arch@vger.kernel.org Link: https://lore.kernel.org/r/20250515124644.2958810-3-mingo@kernel.org --- include/asm-generic/bug.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/asm-generic/bug.h b/include/asm-generic/bug.h index af76e4a04b16..c8e7126bc26e 100644 --- a/include/asm-generic/bug.h +++ b/include/asm-generic/bug.h @@ -110,7 +110,7 @@ extern __printf(1, 2) void __warn_printk(const char *fmt, ...); #define WARN_ON_ONCE(condition) ({ \ int __ret_warn_on = !!(condition); \ if (unlikely(__ret_warn_on)) \ - __WARN_FLAGS("", \ + __WARN_FLAGS("["#condition"] ", \ BUGFLAG_ONCE | \ BUGFLAG_TAINT(TAINT_WARN)); \ unlikely(__ret_warn_on); \ From 687fac9d1b00fb10421fdd455d60543cc46e42d0 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 15 May 2025 14:46:32 +0200 Subject: [PATCH 03/31] bugs/core: Introduce the CONFIG_DEBUG_BUGVERBOSE_DETAILED Kconfig switch Allow configurability of the inclusion of more detailed WARN_ON() strings, to be implemented in subsequent commits. Since the full cost will be around 100K more memory on an x86 defconfig, disable it by default. Provide the WARN_CONDITION_STR() macro to allow the conditional passing of extra strings to lower level BUG/WARN handlers. Signed-off-by: Ingo Molnar Acked-by: Peter Zijlstra Cc: Linus Torvalds Cc: linux-arch@vger.kernel.org Link: https://lore.kernel.org/r/20250515124644.2958810-4-mingo@kernel.org --- include/asm-generic/bug.h | 6 ++++++ lib/Kconfig.debug | 10 ++++++++++ 2 files changed, 16 insertions(+) diff --git a/include/asm-generic/bug.h b/include/asm-generic/bug.h index c8e7126bc26e..2d9f61346dab 100644 --- a/include/asm-generic/bug.h +++ b/include/asm-generic/bug.h @@ -17,6 +17,12 @@ #define BUG_GET_TAINT(bug) ((bug)->flags >> 8) #endif +#ifdef CONFIG_DEBUG_BUGVERBOSE_DETAILED +# define WARN_CONDITION_STR(cond_str) cond_str +#else +# define WARN_CONDITION_STR(cond_str) +#endif + #ifndef __ASSEMBLY__ #include #include diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index ebe33181b6e6..ef00752a2b67 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -206,6 +206,16 @@ config DEBUG_BUGVERBOSE of the BUG call as well as the EIP and oops trace. This aids debugging but costs about 70-100K of memory. +config DEBUG_BUGVERBOSE_DETAILED + bool "Verbose WARN_ON_ONCE() reporting (adds 100K)" if DEBUG_BUGVERBOSE + help + Say Y here to make WARN_ON_ONCE() output the condition string of the + warning, in addition to the file name and line number. + This helps debugging, but costs about 100K of memory. + + Say N if unsure. + + endmenu # "printk and dmesg options" config DEBUG_KERNEL From 407b9076c147669318a58bbd54185b03055dc9a6 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 15 May 2025 14:46:33 +0200 Subject: [PATCH 04/31] bugs/x86: Extend _BUG_FLAGS() with the 'cond_str' parameter Just pass down the parameter, don't do anything with it yet. Signed-off-by: Ingo Molnar Acked-by: Peter Zijlstra Cc: Linus Torvalds Cc: linux-arch@vger.kernel.org Link: https://lore.kernel.org/r/20250515124644.2958810-5-mingo@kernel.org --- arch/x86/include/asm/bug.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/x86/include/asm/bug.h b/arch/x86/include/asm/bug.h index 413b86b876d9..aff1c6b7a7f3 100644 --- a/arch/x86/include/asm/bug.h +++ b/arch/x86/include/asm/bug.h @@ -39,7 +39,7 @@ #ifdef CONFIG_DEBUG_BUGVERBOSE -#define _BUG_FLAGS(ins, flags, extra) \ +#define _BUG_FLAGS(cond_str, ins, flags, extra) \ do { \ asm_inline volatile("1:\t" ins "\n" \ ".pushsection __bug_table,\"aw\"\n" \ @@ -57,7 +57,7 @@ do { \ #else /* !CONFIG_DEBUG_BUGVERBOSE */ -#define _BUG_FLAGS(ins, flags, extra) \ +#define _BUG_FLAGS(cond_str, ins, flags, extra) \ do { \ asm_inline volatile("1:\t" ins "\n" \ ".pushsection __bug_table,\"aw\"\n" \ @@ -74,7 +74,7 @@ do { \ #else -#define _BUG_FLAGS(ins, flags, extra) asm volatile(ins) +#define _BUG_FLAGS(cond_str, ins, flags, extra) asm volatile(ins) #endif /* CONFIG_GENERIC_BUG */ @@ -82,7 +82,7 @@ do { \ #define BUG() \ do { \ instrumentation_begin(); \ - _BUG_FLAGS(ASM_UD2, 0, ""); \ + _BUG_FLAGS("", ASM_UD2, 0, ""); \ __builtin_unreachable(); \ } while (0) @@ -96,7 +96,7 @@ do { \ do { \ __auto_type __flags = BUGFLAG_WARNING|(flags); \ instrumentation_begin(); \ - _BUG_FLAGS(ASM_UD2, __flags, ANNOTATE_REACHABLE(1b)); \ + _BUG_FLAGS(cond_str, ASM_UD2, __flags, ANNOTATE_REACHABLE(1b)); \ instrumentation_end(); \ } while (0) From 48ede5be5c07c8b9fe896bfcb18a78c0d72651de Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 15 May 2025 14:46:34 +0200 Subject: [PATCH 05/31] bugs/x86: Augment warnings output by concatenating 'cond_str' with the regular __FILE__ string in _BUG_FLAGS() This allows the reuse of the UD2 based 'struct bug_entry' low-overhead _BUG_FLAGS() implementation and string-printing backend, without having to add a new field. An example: If we have the following WARN_ON_ONCE() in kernel/sched/core.c: WARN_ON_ONCE(idx < 0 && ptr); Then previously _BUG_FLAGS() would store this string in bug_entry::file: "kernel/sched/core.c" After this patch, it would store and print: "[idx < 0 && ptr] kernel/sched/core.c" Which is an extended string that will be printed in warnings. Suggested-by: Linus Torvalds Signed-off-by: Ingo Molnar Acked-by: Peter Zijlstra Cc: linux-arch@vger.kernel.org Link: https://lore.kernel.org/r/20250515124644.2958810-6-mingo@kernel.org --- arch/x86/include/asm/bug.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/include/asm/bug.h b/arch/x86/include/asm/bug.h index aff1c6b7a7f3..8593976b32cb 100644 --- a/arch/x86/include/asm/bug.h +++ b/arch/x86/include/asm/bug.h @@ -50,7 +50,7 @@ do { \ "\t.org 2b+%c3\n" \ ".popsection\n" \ extra \ - : : "i" (__FILE__), "i" (__LINE__), \ + : : "i" (WARN_CONDITION_STR(cond_str) __FILE__), "i" (__LINE__), \ "i" (flags), \ "i" (sizeof(struct bug_entry))); \ } while (0) From 1c59c2b284cbbae0a67b3e0d4ef8e5659055f085 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 15 May 2025 14:46:35 +0200 Subject: [PATCH 06/31] bugs/powerpc: Pass in 'cond_str' to BUG_ENTRY() Pass in the condition string from __WARN_FLAGS(), WARN_ON() and BUG_ON(), but don't use it yet. Signed-off-by: Ingo Molnar Acked-by: Peter Zijlstra Cc: Christophe Leroy Cc: Linus Torvalds Cc: Madhavan Srinivasan Cc: Michael Ellerman Cc: Naveen N Rao Cc: Nicholas Piggin Cc: linux-arch@vger.kernel.org Cc: linuxppc-dev@lists.ozlabs.org Link: https://lore.kernel.org/r/20250515124644.2958810-7-mingo@kernel.org --- arch/powerpc/include/asm/bug.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/powerpc/include/asm/bug.h b/arch/powerpc/include/asm/bug.h index 34d39ec79720..b5537ba176b5 100644 --- a/arch/powerpc/include/asm/bug.h +++ b/arch/powerpc/include/asm/bug.h @@ -51,7 +51,7 @@ ".previous\n" #endif -#define BUG_ENTRY(insn, flags, ...) \ +#define BUG_ENTRY(cond_str, insn, flags, ...) \ __asm__ __volatile__( \ "1: " insn "\n" \ _EMIT_BUG_ENTRY \ @@ -67,12 +67,12 @@ */ #define BUG() do { \ - BUG_ENTRY("twi 31, 0, 0", 0); \ + BUG_ENTRY("", "twi 31, 0, 0", 0); \ unreachable(); \ } while (0) #define HAVE_ARCH_BUG -#define __WARN_FLAGS(cond_str, flags) BUG_ENTRY("twi 31, 0, 0", BUGFLAG_WARNING | (flags)) +#define __WARN_FLAGS(cond_str, flags) BUG_ENTRY(cond_str, "twi 31, 0, 0", BUGFLAG_WARNING | (flags)) #ifdef CONFIG_PPC64 #define BUG_ON(x) do { \ @@ -80,7 +80,7 @@ if (x) \ BUG(); \ } else { \ - BUG_ENTRY(PPC_TLNEI " %4, 0", 0, "r" ((__force long)(x))); \ + BUG_ENTRY(#x, PPC_TLNEI " %4, 0", 0, "r" ((__force long)(x))); \ } \ } while (0) @@ -90,7 +90,7 @@ if (__ret_warn_on) \ __WARN(); \ } else { \ - BUG_ENTRY(PPC_TLNEI " %4, 0", \ + BUG_ENTRY(#x, PPC_TLNEI " %4, 0", \ BUGFLAG_WARNING | BUGFLAG_TAINT(TAINT_WARN), \ "r" (__ret_warn_on)); \ } \ From 1284579a7f4949fee0b5bda13eff380de734928f Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 15 May 2025 14:46:36 +0200 Subject: [PATCH 07/31] bugs/powerpc: Concatenate 'cond_str' with '__FILE__' in BUG_ENTRY(), to extend WARN_ON/BUG_ON output Extend WARN_ON and BUG_ON style output from: WARNING: CPU: 0 PID: 0 at kernel/sched/core.c:8511 sched_init+0x20/0x410 to: WARNING: CPU: 0 PID: 0 at [idx < 0 && ptr] kernel/sched/core.c:8511 sched_init+0x20/0x410 Note that the output will be further reorganized later in this series. Signed-off-by: Ingo Molnar Acked-by: Peter Zijlstra Cc: Christophe Leroy Cc: Linus Torvalds Cc: Madhavan Srinivasan Cc: Michael Ellerman Cc: Naveen N Rao Cc: Nicholas Piggin Cc: linux-arch@vger.kernel.org Cc: linuxppc-dev@lists.ozlabs.org Link: https://lore.kernel.org/r/20250515124644.2958810-8-mingo@kernel.org --- arch/powerpc/include/asm/bug.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/include/asm/bug.h b/arch/powerpc/include/asm/bug.h index b5537ba176b5..171b6b2ba100 100644 --- a/arch/powerpc/include/asm/bug.h +++ b/arch/powerpc/include/asm/bug.h @@ -55,7 +55,7 @@ __asm__ __volatile__( \ "1: " insn "\n" \ _EMIT_BUG_ENTRY \ - : : "i" (__FILE__), "i" (__LINE__), \ + : : "i" (WARN_CONDITION_STR(cond_str) __FILE__), "i" (__LINE__), \ "i" (flags), \ "i" (sizeof(struct bug_entry)), \ ##__VA_ARGS__) From 66e94df0dd272b057899b8cdbca906ea1306d7a1 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 15 May 2025 14:46:37 +0200 Subject: [PATCH 08/31] bugs/LoongArch: Pass in 'cond_str' to __BUG_ENTRY() Pass in the condition string from __WARN_FLAGS(), but don't use it yet. Signed-off-by: Ingo Molnar Acked-by: Peter Zijlstra Cc: Huacai Chen Cc: Josh Poimboeuf Cc: Linus Torvalds Cc: WANG Xuerui Cc: linux-arch@vger.kernel.org Link: https://lore.kernel.org/r/20250515124644.2958810-9-mingo@kernel.org --- arch/loongarch/include/asm/bug.h | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/arch/loongarch/include/asm/bug.h b/arch/loongarch/include/asm/bug.h index 51c2cb98d728..3c377984457d 100644 --- a/arch/loongarch/include/asm/bug.h +++ b/arch/loongarch/include/asm/bug.h @@ -20,39 +20,38 @@ #endif #ifndef CONFIG_GENERIC_BUG -#define __BUG_ENTRY(flags) +#define __BUG_ENTRY(cond_str, flags) #else -#define __BUG_ENTRY(flags) \ +#define __BUG_ENTRY(cond_str, flags) \ .pushsection __bug_table, "aw"; \ .align 2; \ 10000: .long 10001f - .; \ _BUGVERBOSE_LOCATION(__FILE__, __LINE__) \ - .short flags; \ + .short flags; \ .popsection; \ 10001: #endif -#define ASM_BUG_FLAGS(flags) \ - __BUG_ENTRY(flags) \ +#define ASM_BUG_FLAGS(cond_str, flags) \ + __BUG_ENTRY(cond_str, flags) \ break BRK_BUG; -#define ASM_BUG() ASM_BUG_FLAGS(0) +#define ASM_BUG() ASM_BUG_FLAGS("", 0) -#define __BUG_FLAGS(flags, extra) \ - asm_inline volatile (__stringify(ASM_BUG_FLAGS(flags)) \ - extra); +#define __BUG_FLAGS(cond_str, flags, extra) \ + asm_inline volatile (__stringify(ASM_BUG_FLAGS(cond_str, flags)) extra); #define __WARN_FLAGS(cond_str, flags) \ do { \ instrumentation_begin(); \ - __BUG_FLAGS(BUGFLAG_WARNING|(flags), ANNOTATE_REACHABLE(10001b));\ + __BUG_FLAGS(cond_str, BUGFLAG_WARNING|(flags), ANNOTATE_REACHABLE(10001b));\ instrumentation_end(); \ } while (0) #define BUG() \ do { \ instrumentation_begin(); \ - __BUG_FLAGS(0, ""); \ + __BUG_FLAGS("", 0, ""); \ unreachable(); \ } while (0) From d6b894cbfa4b91e2a7eaf5bc0a91cac48c5f4311 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 15 May 2025 14:46:38 +0200 Subject: [PATCH 09/31] bugs/LoongArch: Concatenate 'cond_str' with '__FILE__' in __BUG_ENTRY(), to extend WARN_ON/BUG_ON output Extend WARN_ON and BUG_ON style output from: WARNING: CPU: 0 PID: 0 at kernel/sched/core.c:8511 sched_init+0x20/0x410 to: WARNING: CPU: 0 PID: 0 at [idx < 0 && ptr] kernel/sched/core.c:8511 sched_init+0x20/0x410 Note that the output will be further reorganized later in this series. [ peterz: backmerge fix from Nathan ] Fixed-by: Nathan Chancellor Signed-off-by: Ingo Molnar Signed-off-by: Peter Zijlstra Signed-off-by: Ingo Molnar # Cleaned up tags section Cc: Huacai Chen Cc: Josh Poimboeuf Cc: Linus Torvalds Cc: WANG Xuerui Cc: linux-arch@vger.kernel.org Link: https://lore.kernel.org/r/20250515124644.2958810-10-mingo@kernel.org Link: https://lore.kernel.org/r/20250616-loongarch-fix-warn-cond-llvm-ias-v1-1-6c6d90bb4466@kernel.org --- arch/loongarch/include/asm/bug.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/loongarch/include/asm/bug.h b/arch/loongarch/include/asm/bug.h index 3c377984457d..d090a5bec5eb 100644 --- a/arch/loongarch/include/asm/bug.h +++ b/arch/loongarch/include/asm/bug.h @@ -11,7 +11,7 @@ #else #define __BUGVERBOSE_LOCATION(file, line) \ .pushsection .rodata.str, "aMS", @progbits, 1; \ - 10002: .string file; \ + 10002: .ascii file "\0"; \ .popsection; \ \ .long 10002b - .; \ @@ -26,7 +26,7 @@ .pushsection __bug_table, "aw"; \ .align 2; \ 10000: .long 10001f - .; \ - _BUGVERBOSE_LOCATION(__FILE__, __LINE__) \ + _BUGVERBOSE_LOCATION(WARN_CONDITION_STR(cond_str) __FILE__, __LINE__) \ .short flags; \ .popsection; \ 10001: From 7ce0f693cb0e0a9f374a422d2e5696e377ebc300 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 27 Mar 2025 09:00:13 +0100 Subject: [PATCH 10/31] bugs/s390: Pass in 'cond_str' to __EMIT_BUG() Pass in the condition string from __WARN_FLAGS(), but do not concatenate it with __FILE__, because it results in s390 assembler build errors that are beyond my s390-asm-fu. Signed-off-by: Ingo Molnar Acked-by: Peter Zijlstra Cc: Linus Torvalds Cc: Heiko Carstens Cc: Vasily Gorbik Cc: Alexander Gordeev Cc: Christian Borntraeger Cc: Sven Schnelle Cc: linux-s390@vger.kernel.org Cc: Link: https://lore.kernel.org/r/20250515124644.2958810-11-mingo@kernel.org --- arch/s390/include/asm/bug.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/s390/include/asm/bug.h b/arch/s390/include/asm/bug.h index ef3e495ec1e3..30f8785a01f5 100644 --- a/arch/s390/include/asm/bug.h +++ b/arch/s390/include/asm/bug.h @@ -8,7 +8,7 @@ #ifdef CONFIG_DEBUG_BUGVERBOSE -#define __EMIT_BUG(x) do { \ +#define __EMIT_BUG(cond_str, x) do { \ asm_inline volatile( \ "0: mc 0,0\n" \ ".section .rodata.str,\"aMS\",@progbits,1\n" \ @@ -27,7 +27,7 @@ #else /* CONFIG_DEBUG_BUGVERBOSE */ -#define __EMIT_BUG(x) do { \ +#define __EMIT_BUG(cond_str, x) do { \ asm_inline volatile( \ "0: mc 0,0\n" \ ".section __bug_table,\"aw\"\n" \ @@ -42,12 +42,12 @@ #endif /* CONFIG_DEBUG_BUGVERBOSE */ #define BUG() do { \ - __EMIT_BUG(0); \ + __EMIT_BUG("", 0); \ unreachable(); \ } while (0) #define __WARN_FLAGS(cond_str, flags) do { \ - __EMIT_BUG(BUGFLAG_WARNING|(flags)); \ + __EMIT_BUG(cond_str, BUGFLAG_WARNING|(flags)); \ } while (0) #define WARN_ON(x) ({ \ From 6584ff203aecff4bbda2f4e15f7579e57f1d5f40 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Tue, 20 May 2025 15:39:27 +0200 Subject: [PATCH 11/31] bugs/s390: Use 'cond_str' in __EMIT_BUG() The simple thing would be to add the string as an assembly immediate input operand. Some older gcc variants cannot handle strings as immediate input operands for inline assemblies. Doing so may result in compile errors. Rewrite the s390 generic bug support very similar to arm64 and loongarch, and get rid of all input operands to fix this. [ peterz: backmerge fix and massage changelog ] [ bp: clang integrated assembler concatenates only .ascii strings: https://lore.kernel.org/r/202507020528.N0LtekXt-lkp@intel.com ] Signed-off-by: Heiko Carstens Signed-off-by: Ingo Molnar Signed-off-by: Peter Zijlstra Signed-off-by: Borislav Petkov (AMD) Signed-off-by: Ingo Molnar # Fixed the tags section Acked-by: Alexander Gordeev Cc: Linus Torvalds Cc: linux-arch@vger.kernel.org Cc: Vasily Gorbik Cc: Christian Borntraeger Cc: Sven Schnelle Cc: linux-s390@vger.kernel.org Link: https://lore.kernel.org/r/20250520133927.7932C19-hca@linux.ibm.com Link: https://lore.kernel.org/r/20250617135042.1878068-3-hca@linux.ibm.com --- arch/s390/include/asm/bug.h | 83 ++++++++++++++++++------------------- 1 file changed, 41 insertions(+), 42 deletions(-) diff --git a/arch/s390/include/asm/bug.h b/arch/s390/include/asm/bug.h index 30f8785a01f5..c39500eec300 100644 --- a/arch/s390/include/asm/bug.h +++ b/arch/s390/include/asm/bug.h @@ -2,52 +2,52 @@ #ifndef _ASM_S390_BUG_H #define _ASM_S390_BUG_H -#include +#include -#ifdef CONFIG_BUG +#ifndef CONFIG_DEBUG_BUGVERBOSE +#define _BUGVERBOSE_LOCATION(file, line) +#else +#define __BUGVERBOSE_LOCATION(file, line) \ + .pushsection .rodata.str, "aMS", @progbits, 1; \ + 10002: .ascii file "\0"; \ + .popsection; \ + \ + .long 10002b - .; \ + .short line; +#define _BUGVERBOSE_LOCATION(file, line) __BUGVERBOSE_LOCATION(file, line) +#endif -#ifdef CONFIG_DEBUG_BUGVERBOSE +#ifndef CONFIG_GENERIC_BUG +#define __BUG_ENTRY(cond_str, flags) +#else +#define __BUG_ENTRY(cond_str, flags) \ + .pushsection __bug_table, "aw"; \ + .align 4; \ + 10000: .long 10001f - .; \ + _BUGVERBOSE_LOCATION(WARN_CONDITION_STR(cond_str) __FILE__, __LINE__) \ + .short flags; \ + .popsection; \ + 10001: +#endif -#define __EMIT_BUG(cond_str, x) do { \ - asm_inline volatile( \ - "0: mc 0,0\n" \ - ".section .rodata.str,\"aMS\",@progbits,1\n" \ - "1: .asciz \""__FILE__"\"\n" \ - ".previous\n" \ - ".section __bug_table,\"aw\"\n" \ - "2: .long 0b-.\n" \ - " .long 1b-.\n" \ - " .short %0,%1\n" \ - " .org 2b+%2\n" \ - ".previous\n" \ - : : "i" (__LINE__), \ - "i" (x), \ - "i" (sizeof(struct bug_entry))); \ +#define ASM_BUG_FLAGS(cond_str, flags) \ + __BUG_ENTRY(cond_str, flags) \ + mc 0,0 + +#define ASM_BUG() ASM_BUG_FLAGS("", 0) + +#define __BUG_FLAGS(cond_str, flags) \ + asm_inline volatile(__stringify(ASM_BUG_FLAGS(cond_str, flags))); + +#define __WARN_FLAGS(cond_str, flags) \ +do { \ + __BUG_FLAGS(cond_str, BUGFLAG_WARNING|(flags)); \ } while (0) -#else /* CONFIG_DEBUG_BUGVERBOSE */ - -#define __EMIT_BUG(cond_str, x) do { \ - asm_inline volatile( \ - "0: mc 0,0\n" \ - ".section __bug_table,\"aw\"\n" \ - "1: .long 0b-.\n" \ - " .short %0\n" \ - " .org 1b+%1\n" \ - ".previous\n" \ - : : "i" (x), \ - "i" (sizeof(struct bug_entry))); \ -} while (0) - -#endif /* CONFIG_DEBUG_BUGVERBOSE */ - -#define BUG() do { \ - __EMIT_BUG("", 0); \ - unreachable(); \ -} while (0) - -#define __WARN_FLAGS(cond_str, flags) do { \ - __EMIT_BUG(cond_str, BUGFLAG_WARNING|(flags)); \ +#define BUG() \ +do { \ + __BUG_FLAGS("", 0); \ + unreachable(); \ } while (0) #define WARN_ON(x) ({ \ @@ -64,7 +64,6 @@ #define HAVE_ARCH_BUG #define HAVE_ARCH_WARN_ON -#endif /* CONFIG_BUG */ #include From 7e8c292692fd7bcaad09beb8501a55e9be833d50 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 15 May 2025 14:46:40 +0200 Subject: [PATCH 12/31] bugs/riscv: Pass in 'cond_str' to __BUG_FLAGS() Pass in the condition string from __WARN_FLAGS() to __BUG_FLAGS(), but don't use it yet. Signed-off-by: Ingo Molnar Signed-off-by: Borislav Petkov (AMD) Signed-off-by: Ingo Molnar # Rebased ancestor commits Acked-by: Peter Zijlstra Cc: Albert Ou Cc: Alexandre Ghiti Cc: Linus Torvalds Cc: Palmer Dabbelt Cc: Paul Walmsley Cc: linux-arch@vger.kernel.org Cc: linux-riscv@lists.infradead.org Link: https://lore.kernel.org/r/20250515124644.2958810-12-mingo@kernel.org --- arch/riscv/include/asm/bug.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/riscv/include/asm/bug.h b/arch/riscv/include/asm/bug.h index b22ee4d2c882..feaf456d465b 100644 --- a/arch/riscv/include/asm/bug.h +++ b/arch/riscv/include/asm/bug.h @@ -50,7 +50,7 @@ typedef u32 bug_insn_t; #endif #ifdef CONFIG_GENERIC_BUG -#define __BUG_FLAGS(flags) \ +#define __BUG_FLAGS(cond_str, flags) \ do { \ __asm__ __volatile__ ( \ "1:\n\t" \ @@ -66,17 +66,17 @@ do { \ "i" (sizeof(struct bug_entry))); \ } while (0) #else /* CONFIG_GENERIC_BUG */ -#define __BUG_FLAGS(flags) do { \ +#define __BUG_FLAGS(cond_str, flags) do { \ __asm__ __volatile__ ("ebreak\n"); \ } while (0) #endif /* CONFIG_GENERIC_BUG */ #define BUG() do { \ - __BUG_FLAGS(0); \ + __BUG_FLAGS("", 0); \ unreachable(); \ } while (0) -#define __WARN_FLAGS(cond_str, flags) __BUG_FLAGS(BUGFLAG_WARNING|(flags)) +#define __WARN_FLAGS(cond_str, flags) __BUG_FLAGS(cond_str, BUGFLAG_WARNING|(flags)) #define HAVE_ARCH_BUG From bb39faa71d87cbf2eef89ebddec0bf22a3b1a157 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 15 May 2025 14:46:41 +0200 Subject: [PATCH 13/31] bugs/riscv: Concatenate 'cond_str' with '__FILE__' in __BUG_FLAGS(), to extend WARN_ON/BUG_ON output Extend WARN_ON and BUG_ON style output from: WARNING: CPU: 0 PID: 0 at kernel/sched/core.c:8511 sched_init+0x20/0x410 to: WARNING: CPU: 0 PID: 0 at [idx < 0 && ptr] kernel/sched/core.c:8511 sched_init+0x20/0x410 Note that the output will be further reorganized later in this series. Signed-off-by: Ingo Molnar Signed-off-by: Borislav Petkov (AMD) Signed-off-by: Ingo Molnar # Rebased ancestor commits Acked-by: Peter Zijlstra Cc: Albert Ou Cc: Alexandre Ghiti Cc: Linus Torvalds Cc: Palmer Dabbelt Cc: Paul Walmsley Cc: linux-arch@vger.kernel.org Cc: linux-riscv@lists.infradead.org Link: https://lore.kernel.org/r/20250515124644.2958810-13-mingo@kernel.org --- arch/riscv/include/asm/bug.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/riscv/include/asm/bug.h b/arch/riscv/include/asm/bug.h index feaf456d465b..da9b8e83934d 100644 --- a/arch/riscv/include/asm/bug.h +++ b/arch/riscv/include/asm/bug.h @@ -61,7 +61,7 @@ do { \ ".org 2b + %3\n\t" \ ".popsection" \ : \ - : "i" (__FILE__), "i" (__LINE__), \ + : "i" (WARN_CONDITION_STR(cond_str) __FILE__), "i" (__LINE__), \ "i" (flags), \ "i" (sizeof(struct bug_entry))); \ } while (0) From f40484925b93001c2aee56d1f1704ef7a9a82fbe Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 15 May 2025 14:46:42 +0200 Subject: [PATCH 14/31] bugs/parisc: Concatenate 'cond_str' with '__FILE__' in __WARN_FLAGS(), to extend WARN_ON/BUG_ON output Extend WARN_ON and BUG_ON style output from: WARNING: CPU: 0 PID: 0 at kernel/sched/core.c:8511 sched_init+0x20/0x410 to: WARNING: CPU: 0 PID: 0 at [idx < 0 && ptr] kernel/sched/core.c:8511 sched_init+0x20/0x410 Note that the output will be further reorganized later in this series. Signed-off-by: Ingo Molnar Signed-off-by: Borislav Petkov (AMD) Signed-off-by: Ingo Molnar # Rebased ancestor commits Acked-by: Peter Zijlstra Cc: Helge Deller Cc: James E.J. Bottomley Cc: Linus Torvalds Cc: linux-arch@vger.kernel.org Cc: linux-parisc@vger.kernel.org Link: https://lore.kernel.org/r/20250515124644.2958810-14-mingo@kernel.org --- arch/parisc/include/asm/bug.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/parisc/include/asm/bug.h b/arch/parisc/include/asm/bug.h index 1a87cf80ec3c..5aa1623e4f2f 100644 --- a/arch/parisc/include/asm/bug.h +++ b/arch/parisc/include/asm/bug.h @@ -61,7 +61,7 @@ "\t.short %1, %2\n" \ "\t.blockz %3-2*4-2*2\n" \ "\t.popsection" \ - : : "i" (__FILE__), "i" (__LINE__), \ + : : "i" (WARN_CONDITION_STR(cond_str) __FILE__), "i" (__LINE__), \ "i" (BUGFLAG_WARNING|(flags)), \ "i" (sizeof(struct bug_entry)) ); \ } while(0) From be2ba2fef1676861b295053c2a567b057e9031b9 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 15 May 2025 14:46:43 +0200 Subject: [PATCH 15/31] bugs/sh: Concatenate 'cond_str' with '__FILE__' in __WARN_FLAGS(), to extend WARN_ON/BUG_ON output Extend WARN_ON and BUG_ON style output from: WARNING: CPU: 0 PID: 0 at kernel/sched/core.c:8511 sched_init+0x20/0x410 to: WARNING: CPU: 0 PID: 0 at [idx < 0 && ptr] kernel/sched/core.c:8511 sched_init+0x20/0x410 Note that the output will be further reorganized later in this series. Signed-off-by: Ingo Molnar Signed-off-by: Borislav Petkov (AMD) Signed-off-by: Ingo Molnar # Rebased ancestor commits Acked-by: Peter Zijlstra Cc: John Paul Adrian Glaubitz Cc: Linus Torvalds Cc: Rich Felker Cc: Yoshinori Sato Cc: linux-arch@vger.kernel.org Cc: linux-sh@vger.kernel.org Link: https://lore.kernel.org/r/20250515124644.2958810-15-mingo@kernel.org --- arch/sh/include/asm/bug.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sh/include/asm/bug.h b/arch/sh/include/asm/bug.h index 834c621ab249..891276687355 100644 --- a/arch/sh/include/asm/bug.h +++ b/arch/sh/include/asm/bug.h @@ -59,7 +59,7 @@ do { \ _EMIT_BUG_ENTRY \ : \ : "n" (TRAPA_BUG_OPCODE), \ - "i" (__FILE__), \ + "i" (WARN_CONDITION_STR(cond_str) __FILE__), \ "i" (__LINE__), \ "i" (BUGFLAG_WARNING|(flags)), \ "i" (sizeof(struct bug_entry))); \ From 28ea295f941e39965c562097d5de0e66a373f19d Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 15 May 2025 14:46:44 +0200 Subject: [PATCH 16/31] bugs/core: Reorganize fields in the first line of WARNING output, add ->comm[] output With the introduction of the condition string as part of the 'file' string output of kernel warnings, the first line has become a bit harder to read: WARNING: CPU: 0 PID: 0 at [ptr == 0 && 1] kernel/sched/core.c:8511 sched_init+0x20/0x410 Re-order the fields by importance (higher to lower), make the 'at' meaningful again, and add '->comm[]' output which is often more valuable than a PID. Also, remove the 'PID' prefix - in combination with comm it's clear what it is. These changes make the output only slightly longer: WARNING: [ptr == 0 && 1] kernel/sched/core.c:8511 at sched_init+0x20/0x410 CPU#0: swapper/0 While adding more information and making it better organized. Signed-off-by: Ingo Molnar Signed-off-by: Borislav Petkov (AMD) Signed-off-by: Ingo Molnar # Rebased ancestor commits Acked-by: Peter Zijlstra Cc: Linus Torvalds Cc: linux-arch@vger.kernel.org Link: https://lore.kernel.org/r/20250515124644.2958810-16-mingo@kernel.org --- kernel/panic.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/kernel/panic.c b/kernel/panic.c index b0b9a8bf4560..8cb3649a79b6 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -753,13 +753,15 @@ void __warn(const char *file, int line, void *caller, unsigned taint, disable_trace_on_warning(); - if (file) - pr_warn("WARNING: CPU: %d PID: %d at %s:%d %pS\n", - raw_smp_processor_id(), current->pid, file, line, - caller); - else - pr_warn("WARNING: CPU: %d PID: %d at %pS\n", - raw_smp_processor_id(), current->pid, caller); + if (file) { + pr_warn("WARNING: %s:%d at %pS, CPU#%d: %s/%d\n", + file, line, caller, + raw_smp_processor_id(), current->comm, current->pid); + } else { + pr_warn("WARNING: at %pS, CPU#%d: %s/%d\n", + caller, + raw_smp_processor_id(), current->comm, current->pid); + } #pragma GCC diagnostic push #ifndef __clang__ From ed845c363d8c93eeaad4ce48bb7d5f81b6a75b61 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Tue, 17 Jun 2025 15:50:41 +0200 Subject: [PATCH 17/31] bugs/s390: Remove private WARN_ON() implementation Besides an odd __builtin_constant_p() optimization the s390 specific WARN_ON() implementation is identical to the generic variant. Drop the s390 variant in favor of the generic variant. Signed-off-by: Heiko Carstens Signed-off-by: Peter Zijlstra (Intel) Signed-off-by: Borislav Petkov (AMD) Signed-off-by: Ingo Molnar # Rebased ancestor commits Reviewed-by: Alexander Gordeev Link: https://lore.kernel.org/r/20250617135042.1878068-2-hca@linux.ibm.com --- arch/s390/include/asm/bug.h | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/arch/s390/include/asm/bug.h b/arch/s390/include/asm/bug.h index c39500eec300..acb4b13d98c5 100644 --- a/arch/s390/include/asm/bug.h +++ b/arch/s390/include/asm/bug.h @@ -50,20 +50,7 @@ do { \ unreachable(); \ } while (0) -#define WARN_ON(x) ({ \ - int __ret_warn_on = !!(x); \ - if (__builtin_constant_p(__ret_warn_on)) { \ - if (__ret_warn_on) \ - __WARN(); \ - } else { \ - if (unlikely(__ret_warn_on)) \ - __WARN(); \ - } \ - unlikely(__ret_warn_on); \ -}) - #define HAVE_ARCH_BUG -#define HAVE_ARCH_WARN_ON #include From 1be1fac648fe6184ef3d9a4b60a95eb53bffb0ee Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Mon, 7 Oct 2024 10:16:56 +0200 Subject: [PATCH 18/31] x86: Rework __bug_table helpers Rework the __bug_table helpers such that extension becomes easier. Signed-off-by: Peter Zijlstra (Intel) Link: https://patch.msgid.link/20251110115757.111187573@infradead.org --- arch/x86/include/asm/bug.h | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/arch/x86/include/asm/bug.h b/arch/x86/include/asm/bug.h index 3910db28e2f5..27e3861cf984 100644 --- a/arch/x86/include/asm/bug.h +++ b/arch/x86/include/asm/bug.h @@ -37,39 +37,42 @@ #ifdef CONFIG_GENERIC_BUG #ifdef CONFIG_X86_32 -# define __BUG_REL(val) ".long " val +#define __BUG_REL(val) ".long " val #else -# define __BUG_REL(val) ".long " val " - ." +#define __BUG_REL(val) ".long " val " - ." #endif #ifdef CONFIG_DEBUG_BUGVERBOSE -#define __BUG_ENTRY(file, line, flags) \ - "2:\t" __BUG_REL("1b") "\t# bug_entry::bug_addr\n" \ +#define __BUG_ENTRY_VERBOSE(file, line) \ "\t" __BUG_REL(file) "\t# bug_entry::file\n" \ - "\t.word " line "\t# bug_entry::line\n" \ - "\t.word " flags "\t# bug_entry::flags\n" + "\t.word " line "\t# bug_entry::line\n" #else -#define __BUG_ENTRY(file, line, flags) \ - "2:\t" __BUG_REL("1b") "\t# bug_entry::bug_addr\n" \ - "\t.word " flags "\t# bug_entry::flags\n" +#define __BUG_ENTRY_VERBOSE(file, line) #endif +#define __BUG_ENTRY(file, line, flags) \ + __BUG_REL("1b") "\t# bug_entry::bug_addr\n" \ + __BUG_ENTRY_VERBOSE(file, line) \ + "\t.word " flags "\t# bug_entry::flags\n" + #define _BUG_FLAGS_ASM(ins, file, line, flags, size, extra) \ "1:\t" ins "\n" \ - ".pushsection __bug_table,\"aw\"\n" \ + ".pushsection __bug_table,\"aw\"\n\t" \ ANNOTATE_DATA_SPECIAL \ + "2:\n\t" \ __BUG_ENTRY(file, line, flags) \ "\t.org 2b + " size "\n" \ ".popsection\n" \ extra -#define _BUG_FLAGS(cond_str, ins, flags, extra) \ -do { \ - asm_inline volatile(_BUG_FLAGS_ASM(ins, "%c0", \ - "%c1", "%c2", "%c3", extra) \ - : : "i" (WARN_CONDITION_STR(cond_str) __FILE__), "i" (__LINE__), \ - "i" (flags), \ - "i" (sizeof(struct bug_entry))); \ +#define _BUG_FLAGS(cond_str, ins, flags, extra) \ +do { \ + asm_inline volatile(_BUG_FLAGS_ASM(ins, "%c0", \ + "%c1", "%c2", "%c3", extra) \ + : : "i" (WARN_CONDITION_STR(cond_str) __FILE__), \ + "i" (__LINE__), \ + "i" (flags), \ + "i" (sizeof(struct bug_entry))); \ } while (0) #define ARCH_WARN_ASM(file, line, flags, size) \ From d292dbb5640c5b73b5ad889ae31fe889a2bf3137 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Mon, 2 Jun 2025 14:59:32 +0200 Subject: [PATCH 19/31] bug: Add BUG_FORMAT infrastructure Add BUG_FORMAT; an architecture opt-in feature that allows adding the WARN_printf() format string to the bug_entry table. Signed-off-by: Peter Zijlstra (Intel) Link: https://patch.msgid.link/20251110115757.223371452@infradead.org --- include/asm-generic/bug.h | 7 +++++++ lib/bug.c | 39 ++++++++++++++++++++++++++++++++------- 2 files changed, 39 insertions(+), 7 deletions(-) diff --git a/include/asm-generic/bug.h b/include/asm-generic/bug.h index 2d9f61346dab..c7a1407b8669 100644 --- a/include/asm-generic/bug.h +++ b/include/asm-generic/bug.h @@ -42,6 +42,13 @@ struct bug_entry { #else signed int bug_addr_disp; #endif +#ifdef HAVE_ARCH_BUG_FORMAT +#ifndef CONFIG_GENERIC_BUG_RELATIVE_POINTERS + const char *format; +#else + signed int format_disp; +#endif +#endif #ifdef CONFIG_DEBUG_BUGVERBOSE #ifndef CONFIG_GENERIC_BUG_RELATIVE_POINTERS const char *file; diff --git a/lib/bug.c b/lib/bug.c index b1f07459c2ee..6e57199ed1f7 100644 --- a/lib/bug.c +++ b/lib/bug.c @@ -139,6 +139,19 @@ void bug_get_file_line(struct bug_entry *bug, const char **file, #endif } +static const char *bug_get_format(struct bug_entry *bug) +{ + const char *format = NULL; +#ifdef HAVE_ARCH_BUG_FORMAT +#ifdef CONFIG_GENERIC_BUG_RELATIVE_POINTERS + format = (const char *)&bug->format_disp + bug->format_disp; +#else + format = bug->format; +#endif +#endif + return format; +} + struct bug_entry *find_bug(unsigned long bugaddr) { struct bug_entry *bug; @@ -150,11 +163,19 @@ struct bug_entry *find_bug(unsigned long bugaddr) return module_find_bug(bugaddr); } +static void __warn_printf(const char *fmt) +{ + if (!fmt) + return; + + printk("%s", fmt); +} + static enum bug_trap_type __report_bug(unsigned long bugaddr, struct pt_regs *regs) { - struct bug_entry *bug; - const char *file; - unsigned line, warning, once, done; + bool warning, once, done, no_cut, has_args; + const char *file, *fmt; + unsigned line; if (!is_valid_bugaddr(bugaddr)) return BUG_TRAP_TYPE_NONE; @@ -166,10 +187,12 @@ static enum bug_trap_type __report_bug(unsigned long bugaddr, struct pt_regs *re disable_trace_on_warning(); bug_get_file_line(bug, &file, &line); + fmt = bug_get_format(bug); - warning = (bug->flags & BUGFLAG_WARNING) != 0; - once = (bug->flags & BUGFLAG_ONCE) != 0; - done = (bug->flags & BUGFLAG_DONE) != 0; + warning = bug->flags & BUGFLAG_WARNING; + once = bug->flags & BUGFLAG_ONCE; + done = bug->flags & BUGFLAG_DONE; + no_cut = bug->flags & BUGFLAG_NO_CUT_HERE; if (warning && once) { if (done) @@ -187,8 +210,10 @@ static enum bug_trap_type __report_bug(unsigned long bugaddr, struct pt_regs *re * "cut here" line now. WARN() issues its own "cut here" before the * extra debugging message it writes before triggering the handler. */ - if ((bug->flags & BUGFLAG_NO_CUT_HERE) == 0) + if (!no_cut) { printk(KERN_DEFAULT CUT_HERE); + __warn_printf(fmt); + } if (warning) { /* this is a WARN_ON rather than BUG/BUG_ON */ From 30b82568b04e279d0d99482db036f1bdfecac522 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Mon, 2 Jun 2025 15:01:38 +0200 Subject: [PATCH 20/31] bug: Clean up CONFIG_GENERIC_BUG_RELATIVE_POINTERS Three repeated CONFIG_GENERIC_BUG_RELATIVE_POINTERS #ifdefs right after one another yields unreadable code. Add a helper. Signed-off-by: Peter Zijlstra (Intel) Link: https://patch.msgid.link/20251110115757.341703850@infradead.org --- include/asm-generic/bug.h | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/include/asm-generic/bug.h b/include/asm-generic/bug.h index c7a1407b8669..9ee622ae0c9a 100644 --- a/include/asm-generic/bug.h +++ b/include/asm-generic/bug.h @@ -35,26 +35,20 @@ void __warn(const char *file, int line, void *caller, unsigned taint, #ifdef CONFIG_BUG +#ifndef CONFIG_GENERIC_BUG_RELATIVE_POINTERS +#define BUG_REL(type, name) type name +#else +#define BUG_REL(type, name) signed int name##_disp +#endif + #ifdef CONFIG_GENERIC_BUG struct bug_entry { -#ifndef CONFIG_GENERIC_BUG_RELATIVE_POINTERS - unsigned long bug_addr; -#else - signed int bug_addr_disp; -#endif + BUG_REL(unsigned long, bug_addr); #ifdef HAVE_ARCH_BUG_FORMAT -#ifndef CONFIG_GENERIC_BUG_RELATIVE_POINTERS - const char *format; -#else - signed int format_disp; -#endif + BUG_REL(const char *, format); #endif #ifdef CONFIG_DEBUG_BUGVERBOSE -#ifndef CONFIG_GENERIC_BUG_RELATIVE_POINTERS - const char *file; -#else - signed int file_disp; -#endif + BUG_REL(const char *, file); unsigned short line; #endif unsigned short flags; From 5c47b7f3d1a9d7589026a201abb8ad445f029246 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Sat, 7 Jun 2025 10:51:24 +0200 Subject: [PATCH 21/31] bug: Add BUG_FORMAT_ARGS infrastructure Add BUG_FORMAT_ARGS; when an architecture is able to provide a va_list given pt_regs, use this to print format arguments. Signed-off-by: Peter Zijlstra (Intel) Link: https://patch.msgid.link/20251110115757.457339417@infradead.org --- include/asm-generic/bug.h | 1 + lib/bug.c | 17 +++++++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/include/asm-generic/bug.h b/include/asm-generic/bug.h index 9ee622ae0c9a..228873e13b95 100644 --- a/include/asm-generic/bug.h +++ b/include/asm-generic/bug.h @@ -13,6 +13,7 @@ #define BUGFLAG_ONCE (1 << 1) #define BUGFLAG_DONE (1 << 2) #define BUGFLAG_NO_CUT_HERE (1 << 3) /* CUT_HERE already sent */ +#define BUGFLAG_ARGS (1 << 4) #define BUGFLAG_TAINT(taint) ((taint) << 8) #define BUG_GET_TAINT(bug) ((bug)->flags >> 8) #endif diff --git a/lib/bug.c b/lib/bug.c index 6e57199ed1f7..8100258a2004 100644 --- a/lib/bug.c +++ b/lib/bug.c @@ -163,11 +163,23 @@ struct bug_entry *find_bug(unsigned long bugaddr) return module_find_bug(bugaddr); } -static void __warn_printf(const char *fmt) +static void __warn_printf(const char *fmt, struct pt_regs *regs) { if (!fmt) return; +#ifdef HAVE_ARCH_BUG_FORMAT_ARGS + if (regs) { + struct arch_va_list _args; + va_list *args = __warn_args(&_args, regs); + + if (args) { + vprintk(fmt, *args); + return; + } + } +#endif + printk("%s", fmt); } @@ -193,6 +205,7 @@ static enum bug_trap_type __report_bug(unsigned long bugaddr, struct pt_regs *re once = bug->flags & BUGFLAG_ONCE; done = bug->flags & BUGFLAG_DONE; no_cut = bug->flags & BUGFLAG_NO_CUT_HERE; + has_args = bug->flags & BUGFLAG_ARGS; if (warning && once) { if (done) @@ -212,7 +225,7 @@ static enum bug_trap_type __report_bug(unsigned long bugaddr, struct pt_regs *re */ if (!no_cut) { printk(KERN_DEFAULT CUT_HERE); - __warn_printf(fmt); + __warn_printf(fmt, has_args ? regs : NULL); } if (warning) { From 7d2c27a0ec5ecec980b623ded45758918c00b164 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Sat, 7 Jun 2025 10:52:28 +0200 Subject: [PATCH 22/31] bug: Add report_bug_entry() Add a report_bug() variant where the bug_entry is already known. This is useful when the exception instruction is not instantiated per-site. But instead has a single instance. In such a case the bug_entry address might be passed along in a known register or something. Signed-off-by: Peter Zijlstra (Intel) Link: https://patch.msgid.link/20251110115757.575795595@infradead.org --- include/linux/bug.h | 8 ++++++++ lib/bug.c | 28 +++++++++++++++++++++------- 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/include/linux/bug.h b/include/linux/bug.h index a9948a9f1093..17a4933c611b 100644 --- a/include/linux/bug.h +++ b/include/linux/bug.h @@ -42,6 +42,7 @@ void bug_get_file_line(struct bug_entry *bug, const char **file, struct bug_entry *find_bug(unsigned long bugaddr); enum bug_trap_type report_bug(unsigned long bug_addr, struct pt_regs *regs); +enum bug_trap_type report_bug_entry(struct bug_entry *bug, struct pt_regs *regs); /* These are defined by the architecture */ int is_valid_bugaddr(unsigned long addr); @@ -62,6 +63,13 @@ static inline enum bug_trap_type report_bug(unsigned long bug_addr, } struct bug_entry; + +static inline enum bug_trap_type +report_bug_entry(struct bug_entry *bug, struct pt_regs *regs) +{ + return BUG_TRAP_TYPE_BUG; +} + static inline void bug_get_file_line(struct bug_entry *bug, const char **file, unsigned int *line) { diff --git a/lib/bug.c b/lib/bug.c index 8100258a2004..581a66b88c5c 100644 --- a/lib/bug.c +++ b/lib/bug.c @@ -183,18 +183,20 @@ static void __warn_printf(const char *fmt, struct pt_regs *regs) printk("%s", fmt); } -static enum bug_trap_type __report_bug(unsigned long bugaddr, struct pt_regs *regs) +static enum bug_trap_type __report_bug(struct bug_entry *bug, unsigned long bugaddr, struct pt_regs *regs) { bool warning, once, done, no_cut, has_args; const char *file, *fmt; unsigned line; - if (!is_valid_bugaddr(bugaddr)) - return BUG_TRAP_TYPE_NONE; + if (!bug) { + if (!is_valid_bugaddr(bugaddr)) + return BUG_TRAP_TYPE_NONE; - bug = find_bug(bugaddr); - if (!bug) - return BUG_TRAP_TYPE_NONE; + bug = find_bug(bugaddr); + if (!bug) + return BUG_TRAP_TYPE_NONE; + } disable_trace_on_warning(); @@ -244,13 +246,25 @@ static enum bug_trap_type __report_bug(unsigned long bugaddr, struct pt_regs *re return BUG_TRAP_TYPE_BUG; } +enum bug_trap_type report_bug_entry(struct bug_entry *bug, struct pt_regs *regs) +{ + enum bug_trap_type ret; + bool rcu = false; + + rcu = warn_rcu_enter(); + ret = __report_bug(bug, 0, regs); + warn_rcu_exit(rcu); + + return ret; +} + enum bug_trap_type report_bug(unsigned long bugaddr, struct pt_regs *regs) { enum bug_trap_type ret; bool rcu = false; rcu = warn_rcu_enter(); - ret = __report_bug(bugaddr, regs); + ret = __report_bug(NULL, bugaddr, regs); warn_rcu_exit(rcu); return ret; From 3fd45b871fde00f4fac96318a136bd256ec0b90b Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Mon, 10 Nov 2025 11:58:37 +0100 Subject: [PATCH 23/31] bug: Implement WARN_ON() using __WARN_FLAGS() This completes 3bc3c9c3ab6d ("bugs/core: Pass down the condition string of WARN_ON_ONCE(cond) warnings to __WARN_FLAGS()") and makes WARN_ON() and WARN_ON_ONCE() behaviour consistent. Signed-off-by: Peter Zijlstra (Intel) Link: https://patch.msgid.link/20251110115757.690999560@infradead.org --- include/asm-generic/bug.h | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/include/asm-generic/bug.h b/include/asm-generic/bug.h index 228873e13b95..4bfbeae30c42 100644 --- a/include/asm-generic/bug.h +++ b/include/asm-generic/bug.h @@ -109,22 +109,36 @@ extern __printf(1, 2) void __warn_printk(const char *fmt, ...); } while (0) #else #define __WARN() __WARN_FLAGS("", BUGFLAG_TAINT(TAINT_WARN)) + #define __WARN_printf(taint, arg...) do { \ instrumentation_begin(); \ __warn_printk(arg); \ __WARN_FLAGS("", BUGFLAG_NO_CUT_HERE | BUGFLAG_TAINT(taint));\ instrumentation_end(); \ } while (0) -#define WARN_ON_ONCE(condition) ({ \ - int __ret_warn_on = !!(condition); \ - if (unlikely(__ret_warn_on)) \ - __WARN_FLAGS("["#condition"] ", \ - BUGFLAG_ONCE | \ - BUGFLAG_TAINT(TAINT_WARN)); \ - unlikely(__ret_warn_on); \ + +#ifndef WARN_ON +#define WARN_ON(condition) ({ \ + int __ret_warn_on = !!(condition); \ + if (unlikely(__ret_warn_on)) \ + __WARN_FLAGS("["#condition"] ", \ + BUGFLAG_TAINT(TAINT_WARN)); \ + unlikely(__ret_warn_on); \ }) #endif +#ifndef WARN_ON_ONCE +#define WARN_ON_ONCE(condition) ({ \ + int __ret_warn_on = !!(condition); \ + if (unlikely(__ret_warn_on)) \ + __WARN_FLAGS("["#condition"] ", \ + BUGFLAG_ONCE | \ + BUGFLAG_TAINT(TAINT_WARN)); \ + unlikely(__ret_warn_on); \ +}) +#endif +#endif /* __WARN_FLAGS */ + /* used internally by panic.c */ #ifndef WARN_ON From b9b2c455f462b67954bee5f17c3d68355d37586f Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Mon, 2 Jun 2025 15:08:36 +0200 Subject: [PATCH 24/31] bug: Allow architectures to provide __WARN_printf() In addition to providing __WARN_FLAGS(), allow an architecture to also provide __WARN_printf(). Signed-off-by: Peter Zijlstra (Intel) Link: https://patch.msgid.link/20251110115757.807154591@infradead.org --- include/asm-generic/bug.h | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/include/asm-generic/bug.h b/include/asm-generic/bug.h index 4bfbeae30c42..21d2c8f88d49 100644 --- a/include/asm-generic/bug.h +++ b/include/asm-generic/bug.h @@ -100,23 +100,9 @@ void warn_slowpath_fmt(const char *file, const int line, unsigned taint, const char *fmt, ...); extern __printf(1, 2) void __warn_printk(const char *fmt, ...); -#ifndef __WARN_FLAGS -#define __WARN() __WARN_printf(TAINT_WARN, NULL) -#define __WARN_printf(taint, arg...) do { \ - instrumentation_begin(); \ - warn_slowpath_fmt(__FILE__, __LINE__, taint, arg); \ - instrumentation_end(); \ - } while (0) -#else +#ifdef __WARN_FLAGS #define __WARN() __WARN_FLAGS("", BUGFLAG_TAINT(TAINT_WARN)) -#define __WARN_printf(taint, arg...) do { \ - instrumentation_begin(); \ - __warn_printk(arg); \ - __WARN_FLAGS("", BUGFLAG_NO_CUT_HERE | BUGFLAG_TAINT(taint));\ - instrumentation_end(); \ - } while (0) - #ifndef WARN_ON #define WARN_ON(condition) ({ \ int __ret_warn_on = !!(condition); \ @@ -139,6 +125,27 @@ extern __printf(1, 2) void __warn_printk(const char *fmt, ...); #endif #endif /* __WARN_FLAGS */ +#if defined(__WARN_FLAGS) && !defined(__WARN_printf) +#define __WARN_printf(taint, arg...) do { \ + instrumentation_begin(); \ + __warn_printk(arg); \ + __WARN_FLAGS("", BUGFLAG_NO_CUT_HERE | BUGFLAG_TAINT(taint));\ + instrumentation_end(); \ + } while (0) +#endif + +#ifndef __WARN_printf +#define __WARN_printf(taint, arg...) do { \ + instrumentation_begin(); \ + warn_slowpath_fmt(__FILE__, __LINE__, taint, arg); \ + instrumentation_end(); \ + } while (0) +#endif + +#ifndef __WARN +#define __WARN() __WARN_printf(TAINT_WARN, NULL) +#endif + /* used internally by panic.c */ #ifndef WARN_ON From 0a52d339d35df80d65706263dc55542dd795a115 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Mon, 2 Jun 2025 15:08:34 +0200 Subject: [PATCH 25/31] x86/bug: Add BUG_FORMAT basics Opt-in to BUG_FORMAT for x86_64, adjust the BUGTABLE helper and for now, just store NULL pointers. Signed-off-by: Peter Zijlstra (Intel) Link: https://patch.msgid.link/20251110115757.980264454@infradead.org --- arch/x86/include/asm/bug.h | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/arch/x86/include/asm/bug.h b/arch/x86/include/asm/bug.h index 27e3861cf984..5e63f9952a0c 100644 --- a/arch/x86/include/asm/bug.h +++ b/arch/x86/include/asm/bug.h @@ -50,33 +50,44 @@ #define __BUG_ENTRY_VERBOSE(file, line) #endif -#define __BUG_ENTRY(file, line, flags) \ +#if defined(CONFIG_X86_64) || defined(CONFIG_DEBUG_BUGVERBOSE_DETAILED) +#define HAVE_ARCH_BUG_FORMAT +#define __BUG_ENTRY_FORMAT(format) \ + "\t" __BUG_REL(format) "\t# bug_entry::format\n" +#else +#define __BUG_ENTRY_FORMAT(format) +#endif + +#define __BUG_ENTRY(format, file, line, flags) \ __BUG_REL("1b") "\t# bug_entry::bug_addr\n" \ + __BUG_ENTRY_FORMAT(format) \ __BUG_ENTRY_VERBOSE(file, line) \ "\t.word " flags "\t# bug_entry::flags\n" -#define _BUG_FLAGS_ASM(ins, file, line, flags, size, extra) \ +#define _BUG_FLAGS_ASM(ins, format, file, line, flags, size, extra) \ "1:\t" ins "\n" \ ".pushsection __bug_table,\"aw\"\n\t" \ ANNOTATE_DATA_SPECIAL \ "2:\n\t" \ - __BUG_ENTRY(file, line, flags) \ + __BUG_ENTRY(format, file, line, flags) \ "\t.org 2b + " size "\n" \ ".popsection\n" \ extra #define _BUG_FLAGS(cond_str, ins, flags, extra) \ do { \ - asm_inline volatile(_BUG_FLAGS_ASM(ins, "%c0", \ - "%c1", "%c2", "%c3", extra) \ - : : "i" (WARN_CONDITION_STR(cond_str) __FILE__), \ - "i" (__LINE__), \ - "i" (flags), \ - "i" (sizeof(struct bug_entry))); \ + asm_inline volatile(_BUG_FLAGS_ASM(ins, "%c[fmt]", "%c[file]", \ + "%c[line]", "%c[fl]", \ + "%c[size]", extra) \ + : : [fmt] "i" (NULL), \ + [file] "i" (WARN_CONDITION_STR(cond_str) __FILE__), \ + [line] "i" (__LINE__), \ + [fl] "i" (flags), \ + [size] "i" (sizeof(struct bug_entry))); \ } while (0) #define ARCH_WARN_ASM(file, line, flags, size) \ - _BUG_FLAGS_ASM(ASM_UD2, file, line, flags, size, "") + _BUG_FLAGS_ASM(ASM_UD2, "0", file, line, flags, size, "") #else From 4f1b701f24bea0900e349aa1c860db24ba0150aa Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Mon, 10 Nov 2025 10:24:09 +0100 Subject: [PATCH 26/31] x86/bug: Use BUG_FORMAT for DEBUG_BUGVERBOSE_DETAILED Since we have an explicit format string, use it for the condition string instead of frobbing it in the file string. Signed-off-by: Peter Zijlstra (Intel) Link: https://patch.msgid.link/20251110115758.097401406@infradead.org --- arch/x86/include/asm/bug.h | 10 ++++++++-- include/asm-generic/bug.h | 8 +++++--- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/arch/x86/include/asm/bug.h b/arch/x86/include/asm/bug.h index 5e63f9952a0c..50b802169a4b 100644 --- a/arch/x86/include/asm/bug.h +++ b/arch/x86/include/asm/bug.h @@ -74,13 +74,19 @@ ".popsection\n" \ extra +#ifdef CONFIG_DEBUG_BUGVERBOSE_DETAILED +#define WARN_CONDITION_STR(cond_str) cond_str +#else +#define WARN_CONDITION_STR(cond_str) NULL +#endif + #define _BUG_FLAGS(cond_str, ins, flags, extra) \ do { \ asm_inline volatile(_BUG_FLAGS_ASM(ins, "%c[fmt]", "%c[file]", \ "%c[line]", "%c[fl]", \ "%c[size]", extra) \ - : : [fmt] "i" (NULL), \ - [file] "i" (WARN_CONDITION_STR(cond_str) __FILE__), \ + : : [fmt] "i" (WARN_CONDITION_STR(cond_str)), \ + [file] "i" (__FILE__), \ [line] "i" (__LINE__), \ [fl] "i" (flags), \ [size] "i" (sizeof(struct bug_entry))); \ diff --git a/include/asm-generic/bug.h b/include/asm-generic/bug.h index 21d2c8f88d49..e512071216be 100644 --- a/include/asm-generic/bug.h +++ b/include/asm-generic/bug.h @@ -18,11 +18,13 @@ #define BUG_GET_TAINT(bug) ((bug)->flags >> 8) #endif +#ifndef WARN_CONDITION_STR #ifdef CONFIG_DEBUG_BUGVERBOSE_DETAILED -# define WARN_CONDITION_STR(cond_str) cond_str +# define WARN_CONDITION_STR(cond_str) "[" cond_str "] " #else # define WARN_CONDITION_STR(cond_str) #endif +#endif /* WARN_CONDITION_STR */ #ifndef __ASSEMBLY__ #include @@ -107,7 +109,7 @@ extern __printf(1, 2) void __warn_printk(const char *fmt, ...); #define WARN_ON(condition) ({ \ int __ret_warn_on = !!(condition); \ if (unlikely(__ret_warn_on)) \ - __WARN_FLAGS("["#condition"] ", \ + __WARN_FLAGS(#condition, \ BUGFLAG_TAINT(TAINT_WARN)); \ unlikely(__ret_warn_on); \ }) @@ -117,7 +119,7 @@ extern __printf(1, 2) void __warn_printk(const char *fmt, ...); #define WARN_ON_ONCE(condition) ({ \ int __ret_warn_on = !!(condition); \ if (unlikely(__ret_warn_on)) \ - __WARN_FLAGS("["#condition"] ", \ + __WARN_FLAGS(#condition, \ BUGFLAG_ONCE | \ BUGFLAG_TAINT(TAINT_WARN)); \ unlikely(__ret_warn_on); \ From 5b472b6e5bd951b208fbbe373892891398eb5ad1 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Mon, 2 Jun 2025 15:08:32 +0200 Subject: [PATCH 27/31] x86_64/bug: Implement __WARN_printf() The basic idea is to have __WARN_printf() be a vararg function such that the compiler can do the optimal calling convention for us. This function body will be a #UD and then set up a va_list in the exception from pt_regs. But because the trap will be in a called function, the bug_entry must be passed in. Have that be the first argument, with the format tucked away inside the bug_entry. The comments should clarify the real fun details. The big downside is that all WARNs will now show: RIP: 0010:__WARN_trap:+0 One possible solution is to simply discard the top frame when unwinding. A follow up patch takes care of this slightly differently by abusing the x86 static_call implementation. This changes (with the next patches): WARN_ONCE(preempt_count() != 2*PREEMPT_DISABLE_OFFSET, "corrupted preempt_count: %s/%d/0x%x\n", from: cmpl $2, %ecx #, _7 jne .L1472 ... .L1472: cmpb $0, __already_done.11(%rip) je .L1513 ... .L1513 movb $1, __already_done.11(%rip) movl 1424(%r14), %edx # _15->pid, _15->pid leaq 1912(%r14), %rsi #, _17 movq $.LC43, %rdi #, call __warn_printk # ud2 .pushsection __bug_table,"aw" 2: .long 1b - . # bug_entry::bug_addr .long .LC1 - . # bug_entry::file .word 5093 # bug_entry::line .word 2313 # bug_entry::flags .org 2b + 12 .popsection .pushsection .discard.annotate_insn,"M", @progbits, 8 .long 1b - . .long 8 # ANNOTYPE_REACHABLE .popsection into: cmpl $2, %ecx #, _7 jne .L1442 #, ... .L1442: lea (2f)(%rip), %rdi 1: .pushsection __bug_table,"aw" 2: .long 1b - . # bug_entry::bug_addr .long .LC43 - . # bug_entry::format .long .LC1 - . # bug_entry::file .word 5093 # bug_entry::line .word 2323 # bug_entry::flags .org 2b + 16 .popsection movl 1424(%r14), %edx # _19->pid, _19->pid leaq 1912(%r14), %rsi #, _13 ud1 (%edx), %rdi Notably, by pushing everything into the exception handler it can take care of the ONCE thing. Signed-off-by: Peter Zijlstra (Intel) Link: https://patch.msgid.link/20251110115758.213813530@infradead.org --- arch/x86/entry/entry.S | 8 +++ arch/x86/include/asm/bug.h | 62 ++++++++++++++++++-- arch/x86/kernel/traps.c | 117 +++++++++++++++++++++++++++++++++---- 3 files changed, 171 insertions(+), 16 deletions(-) diff --git a/arch/x86/entry/entry.S b/arch/x86/entry/entry.S index 8e9a0cc20a4a..772c64ed4523 100644 --- a/arch/x86/entry/entry.S +++ b/arch/x86/entry/entry.S @@ -32,6 +32,14 @@ SYM_FUNC_END(write_ibpb) /* For KVM */ EXPORT_SYMBOL_GPL(write_ibpb); +SYM_FUNC_START(__WARN_trap) + ANNOTATE_NOENDBR + ANNOTATE_REACHABLE + ud1 (%edx), %_ASM_ARG1 + RET +SYM_FUNC_END(__WARN_trap) +EXPORT_SYMBOL(__WARN_trap) + .popsection /* diff --git a/arch/x86/include/asm/bug.h b/arch/x86/include/asm/bug.h index 50b802169a4b..b5474603460b 100644 --- a/arch/x86/include/asm/bug.h +++ b/arch/x86/include/asm/bug.h @@ -7,6 +7,11 @@ #include #include +#ifndef __ASSEMBLY__ +struct bug_entry; +extern void __WARN_trap(struct bug_entry *bug, ...); +#endif + /* * Despite that some emulators terminate on UD2, we use it for WARN(). */ @@ -31,6 +36,7 @@ #define BUG_UD2 0xfffe #define BUG_UD1 0xfffd #define BUG_UD1_UBSAN 0xfffc +#define BUG_UD1_WARN 0xfffb #define BUG_UDB 0xffd6 #define BUG_LOCK 0xfff0 @@ -58,14 +64,17 @@ #define __BUG_ENTRY_FORMAT(format) #endif +#ifdef CONFIG_X86_64 +#define HAVE_ARCH_BUG_FORMAT_ARGS +#endif + #define __BUG_ENTRY(format, file, line, flags) \ __BUG_REL("1b") "\t# bug_entry::bug_addr\n" \ __BUG_ENTRY_FORMAT(format) \ __BUG_ENTRY_VERBOSE(file, line) \ "\t.word " flags "\t# bug_entry::flags\n" -#define _BUG_FLAGS_ASM(ins, format, file, line, flags, size, extra) \ - "1:\t" ins "\n" \ +#define _BUG_FLAGS_ASM(format, file, line, flags, size, extra) \ ".pushsection __bug_table,\"aw\"\n\t" \ ANNOTATE_DATA_SPECIAL \ "2:\n\t" \ @@ -82,7 +91,8 @@ #define _BUG_FLAGS(cond_str, ins, flags, extra) \ do { \ - asm_inline volatile(_BUG_FLAGS_ASM(ins, "%c[fmt]", "%c[file]", \ + asm_inline volatile("1:\t" ins "\n" \ + _BUG_FLAGS_ASM("%c[fmt]", "%c[file]", \ "%c[line]", "%c[fl]", \ "%c[size]", extra) \ : : [fmt] "i" (WARN_CONDITION_STR(cond_str)), \ @@ -93,7 +103,8 @@ do { \ } while (0) #define ARCH_WARN_ASM(file, line, flags, size) \ - _BUG_FLAGS_ASM(ASM_UD2, "0", file, line, flags, size, "") + "1:\t " ASM_UD2 "\n" \ + _BUG_FLAGS_ASM("0", file, line, flags, size, "") #else @@ -126,6 +137,49 @@ do { \ instrumentation_end(); \ } while (0) +#ifdef HAVE_ARCH_BUG_FORMAT_ARGS + +#ifndef __ASSEMBLY__ +struct pt_regs; +struct sysv_va_list { /* from AMD64 System V ABI */ + unsigned int gp_offset; + unsigned int fp_offset; + void *overflow_arg_area; + void *reg_save_area; +}; +struct arch_va_list { + unsigned long regs[6]; + struct sysv_va_list args; +}; +extern void *__warn_args(struct arch_va_list *args, struct pt_regs *regs); +#endif /* __ASSEMBLY__ */ + +#define __WARN_bug_entry(flags, format) ({ \ + struct bug_entry *bug; \ + asm_inline volatile("lea (2f)(%%rip), %[addr]\n1:\n" \ + _BUG_FLAGS_ASM("%c[fmt]", "%c[file]", \ + "%c[line]", "%c[fl]", \ + "%c[size]", "") \ + : [addr] "=r" (bug) \ + : [fmt] "i" (format), \ + [file] "i" (__FILE__), \ + [line] "i" (__LINE__), \ + [fl] "i" (flags), \ + [size] "i" (sizeof(struct bug_entry))); \ + bug; }) + +#define __WARN_print_arg(flags, format, arg...) \ +do { \ + int __flags = (flags) | BUGFLAG_WARNING | BUGFLAG_ARGS ; \ + __WARN_trap(__WARN_bug_entry(__flags, format), ## arg); \ + asm (""); /* inhibit tail-call optimization */ \ +} while (0) + +#define __WARN_printf(taint, fmt, arg...) \ + __WARN_print_arg(BUGFLAG_TAINT(taint), fmt, ## arg) + +#endif /* HAVE_ARCH_BUG_FORMAT_ARGS */ + #include #endif /* _ASM_X86_BUG_H */ diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index 6b22611e69cc..fbbe3ab145a7 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -102,25 +102,37 @@ __always_inline int is_valid_bugaddr(unsigned long addr) * UBSan{0}: 67 0f b9 00 ud1 (%eax),%eax * UBSan{10}: 67 0f b9 40 10 ud1 0x10(%eax),%eax * static_call: 0f b9 cc ud1 %esp,%ecx + * __WARN_trap: 67 48 0f b9 3a ud1 (%edx),%reg * - * Notably UBSAN uses EAX, static_call uses ECX. + * Notable, since __WARN_trap can use all registers, the distinction between + * UD1 users is through R/M. */ __always_inline int decode_bug(unsigned long addr, s32 *imm, int *len) { unsigned long start = addr; + u8 v, reg, rm, rex = 0; + int type = BUG_UD1; bool lock = false; - u8 v; if (addr < TASK_SIZE_MAX) return BUG_NONE; - v = *(u8 *)(addr++); - if (v == INSN_ASOP) + for (;;) { v = *(u8 *)(addr++); + if (v == INSN_ASOP) + continue; - if (v == INSN_LOCK) { - lock = true; - v = *(u8 *)(addr++); + if (v == INSN_LOCK) { + lock = true; + continue; + } + + if ((v & 0xf0) == 0x40) { + rex = v; + continue; + } + + break; } switch (v) { @@ -156,18 +168,33 @@ __always_inline int decode_bug(unsigned long addr, s32 *imm, int *len) if (X86_MODRM_MOD(v) != 3 && X86_MODRM_RM(v) == 4) addr++; /* SIB */ + reg = X86_MODRM_REG(v) + 8*!!X86_REX_R(rex); + rm = X86_MODRM_RM(v) + 8*!!X86_REX_B(rex); + /* Decode immediate, if present */ switch (X86_MODRM_MOD(v)) { case 0: if (X86_MODRM_RM(v) == 5) - addr += 4; /* RIP + disp32 */ + addr += 4; /* RIP + disp32 */ + + if (rm == 0) /* (%eax) */ + type = BUG_UD1_UBSAN; + + if (rm == 2) { /* (%edx) */ + *imm = reg; + type = BUG_UD1_WARN; + } break; case 1: *imm = *(s8 *)addr; addr += 1; + if (rm == 0) /* (%eax) */ + type = BUG_UD1_UBSAN; break; case 2: *imm = *(s32 *)addr; addr += 4; + if (rm == 0) /* (%eax) */ + type = BUG_UD1_UBSAN; break; case 3: break; @@ -176,12 +203,73 @@ __always_inline int decode_bug(unsigned long addr, s32 *imm, int *len) /* record instruction length */ *len = addr - start; - if (X86_MODRM_REG(v) == 0) /* EAX */ - return BUG_UD1_UBSAN; - - return BUG_UD1; + return type; } +static inline unsigned long pt_regs_val(struct pt_regs *regs, int nr) +{ + int offset = pt_regs_offset(regs, nr); + if (WARN_ON_ONCE(offset < -0)) + return 0; + return *((unsigned long *)((void *)regs + offset)); +} + +#ifdef HAVE_ARCH_BUG_FORMAT_ARGS +/* + * Create a va_list from an exception context. + */ +void *__warn_args(struct arch_va_list *args, struct pt_regs *regs) +{ + /* + * Register save area; populate with function call argument registers + */ + args->regs[0] = regs->di; + args->regs[1] = regs->si; + args->regs[2] = regs->dx; + args->regs[3] = regs->cx; + args->regs[4] = regs->r8; + args->regs[5] = regs->r9; + + /* + * From the ABI document: + * + * @gp_offset - the element holds the offset in bytes from + * reg_save_area to the place where the next available general purpose + * argument register is saved. In case all argument registers have + * been exhausted, it is set to the value 48 (6*8). + * + * @fp_offset - the element holds the offset in bytes from + * reg_save_area to the place where the next available floating point + * argument is saved. In case all argument registers have been + * exhausted, it is set to the value 176 (6*8 + 8*16) + * + * @overflow_arg_area - this pointer is used to fetch arguments passed + * on the stack. It is initialized with the address of the first + * argument passed on the stack, if any, and then always updated to + * point to the start of the next argument on the stack. + * + * @reg_save_area - the element points to the start of the register + * save area. + * + * Notably the vararg starts with the second argument and there are no + * floating point arguments in the kernel. + */ + args->args.gp_offset = 1*8; + args->args.fp_offset = 6*8 + 8*16; + args->args.reg_save_area = &args->regs; + args->args.overflow_arg_area = (void *)regs->sp; + + /* + * If the exception came from __WARN_trap, there is a return + * address on the stack, skip that. This is why any __WARN_trap() + * caller must inhibit tail-call optimization. + */ + if ((void *)regs->ip == &__WARN_trap) + args->args.overflow_arg_area += 8; + + return &args->args; +} +#endif /* HAVE_ARCH_BUG_FORMAT */ static nokprobe_inline int do_trap_no_signal(struct task_struct *tsk, int trapnr, const char *str, @@ -334,6 +422,11 @@ static noinstr bool handle_bug(struct pt_regs *regs) raw_local_irq_enable(); switch (ud_type) { + case BUG_UD1_WARN: + if (report_bug_entry((void *)pt_regs_val(regs, ud_imm), regs) == BUG_TRAP_TYPE_WARN) + handled = true; + break; + case BUG_UD2: if (report_bug(regs->ip, regs) == BUG_TRAP_TYPE_WARN) { handled = true; From 11bb4944f014d756f35261f5afcb346901ef1efa Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Mon, 2 Jun 2025 15:08:30 +0200 Subject: [PATCH 28/31] x86/bug: Implement WARN_ONCE() Implement WARN_ONCE like WARN using BUGFLAG_ONCE. Signed-off-by: Peter Zijlstra (Intel) Link: https://patch.msgid.link/20251110115758.339309119@infradead.org --- arch/x86/include/asm/bug.h | 9 +++++++++ include/asm-generic/bug.h | 2 ++ 2 files changed, 11 insertions(+) diff --git a/arch/x86/include/asm/bug.h b/arch/x86/include/asm/bug.h index b5474603460b..87199e6633f9 100644 --- a/arch/x86/include/asm/bug.h +++ b/arch/x86/include/asm/bug.h @@ -178,6 +178,15 @@ do { \ #define __WARN_printf(taint, fmt, arg...) \ __WARN_print_arg(BUGFLAG_TAINT(taint), fmt, ## arg) +#define WARN_ONCE(cond, format, arg...) ({ \ + int __ret_warn_on = !!(cond); \ + if (unlikely(__ret_warn_on)) { \ + __WARN_print_arg(BUGFLAG_ONCE|BUGFLAG_TAINT(TAINT_WARN),\ + format, ## arg); \ + } \ + __ret_warn_on; \ +}) + #endif /* HAVE_ARCH_BUG_FORMAT_ARGS */ #include diff --git a/include/asm-generic/bug.h b/include/asm-generic/bug.h index e512071216be..09e8eccee8ed 100644 --- a/include/asm-generic/bug.h +++ b/include/asm-generic/bug.h @@ -180,8 +180,10 @@ extern __printf(1, 2) void __warn_printk(const char *fmt, ...); DO_ONCE_LITE_IF(condition, WARN_ON, 1) #endif +#ifndef WARN_ONCE #define WARN_ONCE(condition, format...) \ DO_ONCE_LITE_IF(condition, WARN, 1, format) +#endif #define WARN_TAINT_ONCE(condition, taint, format...) \ DO_ONCE_LITE_IF(condition, WARN_TAINT, 1, taint, format) From 860238af7a3348225de228dc0f33a7d631638333 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Sat, 7 Jun 2025 10:06:40 +0200 Subject: [PATCH 29/31] x86_64/bug: Inline the UD1 (Ab)use the static_call infrastructure to convert all: call __WARN_trap instances into the desired: ud1 (%edx), %rdi eliminating the CALL/RET, but more importantly, fixing the fact that all WARNs will have: RIP: 0010:__WARN_trap+0 Basically, by making it a static_call trampoline call, objtool will collect the callsites, and then the inline rewrite will hit the special case and replace the code with the magic instruction. Signed-off-by: Peter Zijlstra (Intel) Link: https://patch.msgid.link/20251110115758.456717741@infradead.org --- arch/x86/include/asm/bug.h | 5 ++++- arch/x86/kernel/static_call.c | 13 +++++++++++-- arch/x86/kernel/traps.c | 4 ++++ 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/arch/x86/include/asm/bug.h b/arch/x86/include/asm/bug.h index 87199e6633f9..d0a96ff5c02c 100644 --- a/arch/x86/include/asm/bug.h +++ b/arch/x86/include/asm/bug.h @@ -140,6 +140,9 @@ do { \ #ifdef HAVE_ARCH_BUG_FORMAT_ARGS #ifndef __ASSEMBLY__ +#include +DECLARE_STATIC_CALL(WARN_trap, __WARN_trap); + struct pt_regs; struct sysv_va_list { /* from AMD64 System V ABI */ unsigned int gp_offset; @@ -171,7 +174,7 @@ extern void *__warn_args(struct arch_va_list *args, struct pt_regs *regs); #define __WARN_print_arg(flags, format, arg...) \ do { \ int __flags = (flags) | BUGFLAG_WARNING | BUGFLAG_ARGS ; \ - __WARN_trap(__WARN_bug_entry(__flags, format), ## arg); \ + static_call_mod(WARN_trap)(__WARN_bug_entry(__flags, format), ## arg); \ asm (""); /* inhibit tail-call optimization */ \ } while (0) diff --git a/arch/x86/kernel/static_call.c b/arch/x86/kernel/static_call.c index 378c388d1b31..2892cdb14563 100644 --- a/arch/x86/kernel/static_call.c +++ b/arch/x86/kernel/static_call.c @@ -26,6 +26,11 @@ static const u8 xor5rax[] = { 0x2e, 0x2e, 0x2e, 0x31, 0xc0 }; static const u8 retinsn[] = { RET_INSN_OPCODE, 0xcc, 0xcc, 0xcc, 0xcc }; +/* + * ud1 (%edx),%rdi -- see __WARN_trap() / decode_bug() + */ +static const u8 warninsn[] = { 0x67, 0x48, 0x0f, 0xb9, 0x3a }; + static u8 __is_Jcc(u8 *insn) /* Jcc.d32 */ { u8 ret = 0; @@ -69,7 +74,10 @@ static void __ref __static_call_transform(void *insn, enum insn_type type, emulate = code; code = &xor5rax; } - + if (func == &__WARN_trap) { + emulate = code; + code = &warninsn; + } break; case NOP: @@ -128,7 +136,8 @@ static void __static_call_validate(u8 *insn, bool tail, bool tramp) } else { if (opcode == CALL_INSN_OPCODE || !memcmp(insn, x86_nops[5], 5) || - !memcmp(insn, xor5rax, 5)) + !memcmp(insn, xor5rax, 5) || + !memcmp(insn, warninsn, 5)) return; } diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index fbbe3ab145a7..cb324cc1fd99 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -215,6 +216,9 @@ static inline unsigned long pt_regs_val(struct pt_regs *regs, int nr) } #ifdef HAVE_ARCH_BUG_FORMAT_ARGS +DEFINE_STATIC_CALL(WARN_trap, __WARN_trap); +EXPORT_STATIC_CALL_TRAMP(WARN_trap); + /* * Create a va_list from an exception context. */ From d62e4f2b9542d25d183f068033558e87e81a00a8 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Wed, 26 Nov 2025 10:55:17 +0100 Subject: [PATCH 30/31] x86/bug: Fix BUG_FORMAT vs KASLR Encoding a relative NULL pointer doesn't work for KASLR, when the whole kernel image gets shifted, the __bug_table and the target string get shifted by the same amount and the relative offset is preserved. However when the target is an absolute 0 value and the __bug_table gets moved about, the end result in a pointer equivalent to kaslr_offset(), not NULL. Notably, this will generate SHN_UNDEF relocations, and Ard would really like to not have those at all. Use the empty string to denote no-string. Suggested-by: Linus Torvalds Cc: Ard Biesheuvel Signed-off-by: Peter Zijlstra (Intel) --- arch/x86/include/asm/bug.h | 8 ++++++-- lib/bug.c | 12 +++++++++++- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/arch/x86/include/asm/bug.h b/arch/x86/include/asm/bug.h index d0a96ff5c02c..4b5ab56903bb 100644 --- a/arch/x86/include/asm/bug.h +++ b/arch/x86/include/asm/bug.h @@ -86,7 +86,7 @@ extern void __WARN_trap(struct bug_entry *bug, ...); #ifdef CONFIG_DEBUG_BUGVERBOSE_DETAILED #define WARN_CONDITION_STR(cond_str) cond_str #else -#define WARN_CONDITION_STR(cond_str) NULL +#define WARN_CONDITION_STR(cond_str) "" #endif #define _BUG_FLAGS(cond_str, ins, flags, extra) \ @@ -103,8 +103,12 @@ do { \ } while (0) #define ARCH_WARN_ASM(file, line, flags, size) \ + ".pushsection .rodata.str1.1, \"aMS\", @progbits, 1\n" \ + "99:\n" \ + "\t.string \"\"\n" \ + ".popsection\n" \ "1:\t " ASM_UD2 "\n" \ - _BUG_FLAGS_ASM("0", file, line, flags, size, "") + _BUG_FLAGS_ASM("99b", file, line, flags, size, "") #else diff --git a/lib/bug.c b/lib/bug.c index 581a66b88c5c..edd9041f89f3 100644 --- a/lib/bug.c +++ b/lib/bug.c @@ -144,7 +144,17 @@ static const char *bug_get_format(struct bug_entry *bug) const char *format = NULL; #ifdef HAVE_ARCH_BUG_FORMAT #ifdef CONFIG_GENERIC_BUG_RELATIVE_POINTERS - format = (const char *)&bug->format_disp + bug->format_disp; + /* + * Allow an architecture to: + * - relative encode NULL (difficult vs KASLR); + * - use a literal 0 (there are no valid objects inside + * the __bug_table itself to refer to after all); + * - use an empty string. + */ + if (bug->format_disp) + format = (const char *)&bug->format_disp + bug->format_disp; + if (format && format[0] == '\0') + format = NULL; #else format = bug->format; #endif From b0a848f4a47a91a6b4d9a9fd739d047254df5a91 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Wed, 26 Nov 2025 11:57:06 +0100 Subject: [PATCH 31/31] x86/bugs: Make i386 use GENERIC_BUG_RELATIVE_POINTERS Linus figured less #ifdef is more better and making x86-32 use GENERIC_BUG_RELATIVE_POINTERS removes one layer of macro magic from the bug.h bits. Suggested-by: Linus Torvalds Signed-off-by: Peter Zijlstra (Intel) --- arch/x86/Kconfig | 2 +- arch/x86/include/asm/bug.h | 14 ++++---------- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index ac9692093215..31c54d6480e0 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -380,7 +380,7 @@ config GENERIC_CSUM config GENERIC_BUG def_bool y depends on BUG - select GENERIC_BUG_RELATIVE_POINTERS if X86_64 + select GENERIC_BUG_RELATIVE_POINTERS config GENERIC_BUG_RELATIVE_POINTERS bool diff --git a/arch/x86/include/asm/bug.h b/arch/x86/include/asm/bug.h index 4b5ab56903bb..ab5bba6cf7f5 100644 --- a/arch/x86/include/asm/bug.h +++ b/arch/x86/include/asm/bug.h @@ -42,16 +42,10 @@ extern void __WARN_trap(struct bug_entry *bug, ...); #ifdef CONFIG_GENERIC_BUG -#ifdef CONFIG_X86_32 -#define __BUG_REL(val) ".long " val -#else -#define __BUG_REL(val) ".long " val " - ." -#endif - #ifdef CONFIG_DEBUG_BUGVERBOSE #define __BUG_ENTRY_VERBOSE(file, line) \ - "\t" __BUG_REL(file) "\t# bug_entry::file\n" \ - "\t.word " line "\t# bug_entry::line\n" + "\t.long " file " - .\t# bug_entry::file\n" \ + "\t.word " line "\t# bug_entry::line\n" #else #define __BUG_ENTRY_VERBOSE(file, line) #endif @@ -59,7 +53,7 @@ extern void __WARN_trap(struct bug_entry *bug, ...); #if defined(CONFIG_X86_64) || defined(CONFIG_DEBUG_BUGVERBOSE_DETAILED) #define HAVE_ARCH_BUG_FORMAT #define __BUG_ENTRY_FORMAT(format) \ - "\t" __BUG_REL(format) "\t# bug_entry::format\n" + "\t.long " format " - .\t# bug_entry::format\n" #else #define __BUG_ENTRY_FORMAT(format) #endif @@ -69,7 +63,7 @@ extern void __WARN_trap(struct bug_entry *bug, ...); #endif #define __BUG_ENTRY(format, file, line, flags) \ - __BUG_REL("1b") "\t# bug_entry::bug_addr\n" \ + "\t.long 1b - ." "\t# bug_entry::bug_addr\n" \ __BUG_ENTRY_FORMAT(format) \ __BUG_ENTRY_VERBOSE(file, line) \ "\t.word " flags "\t# bug_entry::flags\n"