]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
s390/bug: Convert to inline assembly with input operands
authorHeiko Carstens <hca@linux.ibm.com>
Fri, 9 Jan 2026 15:31:37 +0000 (16:31 +0100)
committerHeiko Carstens <hca@linux.ibm.com>
Tue, 27 Jan 2026 11:16:15 +0000 (12:16 +0100)
Rewrite the bug inline assembly so it uses input operands again instead of
pure macro replacements. This more or less reverts the conversion done when
'cond_str' support was added [1].

Reason for this is that the upcoming __WARN_printf() implementation
requires an inline assembly with an output operand. At the same time input
strings (format specifier and condition string) may contain the special '%'
character. As soon as an inline assembly is specified to have input/output
operands the '%' has a special meaning: e.g. converting the existing

 #define __BUG_FLAGS(cond_str, flags) \
   asm_inline volatile(__stringify(ASM_BUG_FLAGS(cond_str, flags)));

to

 #define __BUG_FLAGS(cond_str, flags) \
   asm_inline volatile(__stringify(ASM_BUG_FLAGS(cond_str, flags))::);

will result in a compile error as soon as 'cond_str' contains a '%'
character:

net/core/neighbour.c: In function ‘neigh_table_init’:
././include/linux/compiler_types.h:546:20: error: invalid 'asm': invalid %-code
...
net/core/neighbour.c:1838:17: note: in expansion of macro ‘WARN_ON’
 1838 |                 WARN_ON(tbl->entry_size % NEIGH_PRIV_ALIGN);
      |                 ^~~~~~~

Convert the code, use immediate operands, and also add comments similar to
x86 which are emitted to the generated assembly file, which makes debugging
much easier.

Note: since gcc-8 does not support strings as immediate input operands,
guard the new implementation with CC_HAS_ASM_IMMEDIATE_STRINGS and fallback
to the generic non-exception based warning implementation for incompatible
compilers.

[1] 6584ff203aec ("bugs/s390: Use 'cond_str' in __EMIT_BUG()")

Reviewed-by: Sven Schnelle <svens@linux.ibm.com>
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
arch/s390/include/asm/bug.h

index ee9221bb5d18095844b55f48cbcfa28b638800c6..73f65d91da500135bf490328c18a2380985ad1b4 100644 (file)
@@ -2,60 +2,49 @@
 #ifndef _ASM_S390_BUG_H
 #define _ASM_S390_BUG_H
 
-#include <linux/stringify.h>
+#include <linux/compiler.h>
 
-#ifdef CONFIG_BUG
+#if defined(CONFIG_BUG) && defined(CONFIG_CC_HAS_ASM_IMMEDIATE_STRINGS)
 
-#ifndef CONFIG_DEBUG_BUGVERBOSE
-#define _BUGVERBOSE_LOCATION(file, line)
+#ifdef CONFIG_DEBUG_BUGVERBOSE
+#define __BUG_ENTRY_VERBOSE(file, line)                                        \
+       "       .long   " file " - .    # bug_entry::file\n"            \
+       "       .short  " line "        # bug_entry::line\n"
 #else
-#define __BUGVERBOSE_LOCATION(file, line)                      \
-               .pushsection .rodata.str, "aMS", @progbits, 1;  \
-               .align 2;                                       \
-       10002:  .ascii file "\0";                               \
-               .popsection;                                    \
-                                                               \
-               .long 10002b - .;                               \
-               .short line;
-#define _BUGVERBOSE_LOCATION(file, line) __BUGVERBOSE_LOCATION(file, line)
+#define __BUG_ENTRY_VERBOSE(file, line)
 #endif
 
-#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 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 __BUG_ASM(cond_str, flags)                                     \
+do {                                                                   \
+       asm_inline volatile("\n"                                        \
+               "0:     mc      0,0\n"                                  \
+               "       .section __bug_table,\"aw\"\n"                  \
+               "1:     .long   0b - .  # bug_entry::bug_addr\n"        \
+               __BUG_ENTRY_VERBOSE("%[file]", "%[line]")               \
+               "       .short  %[flgs] # bug_entry::flags\n"           \
+               "       .org    1b+%[size]\n"                           \
+               "       .previous"                                      \
+               :                                                       \
+               : [file] "i" (WARN_CONDITION_STR(cond_str) __FILE__),   \
+                 [line] "i" (__LINE__),                                \
+                 [flgs] "i" (flags),                                   \
+                 [size] "i" (sizeof(struct bug_entry)));               \
+} while (0)
 
-#define __WARN_FLAGS(cond_str, flags)                          \
-do {                                                           \
-       __BUG_FLAGS(cond_str, BUGFLAG_WARNING|(flags));         \
+#define BUG()                                                          \
+do {                                                                   \
+       __BUG_ASM("", 0);                                               \
+       unreachable();                                                  \
 } while (0)
 
-#define BUG()                                                  \
-do {                                                           \
-       __BUG_FLAGS("", 0);                                     \
-       unreachable();                                          \
+#define __WARN_FLAGS(cond_str, flags)                                  \
+do {                                                                   \
+       __BUG_ASM(cond_str, BUGFLAG_WARNING | (flags));                 \
 } while (0)
 
 #define HAVE_ARCH_BUG
 
-#endif /* CONFIG_BUG */
+#endif /* CONFIG_BUG && CONFIG_CC_HAS_ASM_IMMEDIATE_STRINGS */
 
 #include <asm-generic/bug.h>