Commit 0875816a authored by Heiko Carstens's avatar Heiko Carstens
Browse files

Merge branch 'warn-exception'

Heiko Carstens says:

====================

v2:
- Use generic WARN() implementation in case of gcc-8, which avoids the need
  to raise the minimum gcc version to gcc-9 for (only) s390

- Add couple of additional ifdef guards to avoid compile errors and
  warnings

v1 ([1]):
Use the generic infrastructure introduced by Peter Zijlstra [2] to implement
an exception based WARN() and WARN_ONCE() similar to x86.

Due to some compiler oddities on s390 this requires to raise the minimum gcc
version to 9. Maybe there are ways to avoid this, but I failed to find a
working solution. Details are in the patch descriptions.

Just posting this now to also get some compile bot testing, since I'm afraid
there might be some compiler version / config option around where even this
new approach breaks.

Peter, since you were wondering: your generic infrastructure pieces work very
nice. Looking at the x86 and s390 implementation: it might be possible to make
things even more generic since both __WARN_printf(), and WARN_ONCE() are
identical; it looks like only __WARN_print_arg() needs to be provided.

[1] https://lore.kernel.org/all/20251209121701.1856271-1-hca@linux.ibm.com/
[2] https://lore.kernel.org/all/20251110114633.202485143@infradead.org/



====================

Signed-off-by: default avatarHeiko Carstens <hca@linux.ibm.com>
parents 88303fb6 9f9d68c3
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -69,6 +69,12 @@ config CC_HAS_ASM_AOR_FORMAT_FLAGS
	  Clang versions before 19.1.0 do not support A,
	  O, and R inline assembly format flags.

config CC_HAS_ASM_IMMEDIATE_STRINGS
	def_bool !(CC_IS_GCC && GCC_VERSION < 90000)
	help
	  GCC versions before 9.0.0 cannot handle strings as immediate
	  input operands in inline assemblies.

config CC_HAS_STACKPROTECTOR_GLOBAL
	def_bool $(cc-option, -mstack-protector-guard=global -mstack-protector-guard-record)

+1 −0
Original line number Diff line number Diff line
@@ -3,6 +3,7 @@

#include <linux/kvm_host.h>
#include <linux/ftrace.h>
#include <asm/bug.h>
#include <asm/fpu.h>
#include <asm/nospec-branch.h>
#include <asm-generic/asm-prototypes.h>
+104 −37
Original line number Diff line number Diff line
@@ -2,60 +2,127 @@
#ifndef _ASM_S390_BUG_H
#define _ASM_S390_BUG_H

#include <linux/stringify.h>
#include <linux/compiler.h>
#include <linux/const.h>

#ifdef CONFIG_BUG
#define	MONCODE_BUG	_AC(0, U)
#define	MONCODE_BUG_ARG _AC(1, U)

#ifndef CONFIG_DEBUG_BUGVERBOSE
#define _BUGVERBOSE_LOCATION(file, line)
#ifndef __ASSEMBLER__
#if defined(CONFIG_BUG) && defined(CONFIG_CC_HAS_ASM_IMMEDIATE_STRINGS)

#ifdef CONFIG_DEBUG_BUGVERBOSE
#define __BUG_ENTRY_VERBOSE(format, file, line)				\
	"	.long	" format " - .	# bug_entry::format\n"		\
	"	.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(format, file, line)
#endif

#ifndef CONFIG_GENERIC_BUG
#define __BUG_ENTRY(cond_str, flags)
#ifdef CONFIG_DEBUG_BUGVERBOSE_DETAILED
#define WARN_CONDITION_STR(cond_str) cond_str
#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:
#define WARN_CONDITION_STR(cond_str) ""
#endif

#define ASM_BUG_FLAGS(cond_str, flags)				\
	__BUG_ENTRY(cond_str, flags)				\
	mc		0,0
#define __BUG_ENTRY(format, file, line, flags, size)			\
		"	.section __bug_table,\"aw\"\n"			\
		"1:	.long	0b - .	# bug_entry::bug_addr\n"	\
		__BUG_ENTRY_VERBOSE(format, file, line)			\
		"	.short	"flags"	# bug_entry::flags\n"		\
		"	.org	1b+"size"\n"				\
		"	.previous"

#define ASM_BUG()	ASM_BUG_FLAGS("", 0)
#define __BUG_ASM(cond_str, flags)					\
do {									\
	asm_inline volatile("\n"					\
		"0:	mc	%[monc](%%r0),0\n"			\
		__BUG_ENTRY("%[frmt]", "%[file]", "%[line]",		\
			    "%[flgs]", "%[size]")			\
		:							\
		: [monc] "i" (MONCODE_BUG),				\
		  [frmt] "i" (WARN_CONDITION_STR(cond_str)),		\
		  [file] "i" (__FILE__),				\
		  [line] "i" (__LINE__),				\
		  [flgs] "i" (flags),					\
		  [size] "i" (sizeof(struct bug_entry)));		\
} while (0)

#define __BUG_FLAGS(cond_str, flags)				\
	asm_inline volatile(__stringify(ASM_BUG_FLAGS(cond_str, flags)));
#define BUG()								\
do {									\
	__BUG_ASM("", 0);						\
	unreachable();							\
} while (0)

#define __WARN_FLAGS(cond_str, flags)					\
do {									\
	__BUG_FLAGS(cond_str, BUGFLAG_WARNING|(flags));		\
	__BUG_ASM(cond_str, BUGFLAG_WARNING | (flags));			\
} while (0)

#define BUG()							\
#define __WARN_bug_entry(flags, format)					\
({									\
	struct bug_entry *bug;						\
									\
	asm_inline volatile("\n"					\
		"0:	larl	%[bug],1f\n"				\
		__BUG_ENTRY("%[frmt]", "%[file]", "%[line]",		\
			    "%[flgs]", "%[size]")			\
		: [bug] "=d" (bug)					\
		: [frmt] "i" (format),					\
		  [file] "i" (__FILE__),				\
		  [line] "i" (__LINE__),				\
		  [flgs] "i" (flags),					\
		  [size] "i" (sizeof(struct bug_entry)));		\
	bug;								\
})

/*
 * Variable Argument List (va_list) as defined in ELF Application
 * Binary Interface s390x Supplement documentation.
 */
struct arch_va_list {
	long __gpr;
	long __fpr;
	void *__overflow_arg_area;
	void *__reg_save_area;
};

struct bug_entry;
struct pt_regs;

void *__warn_args(struct arch_va_list *args, struct pt_regs *regs);
void __WARN_trap(struct bug_entry *bug, ...);

#define __WARN_print_arg(flags, format, arg...)				\
do {									\
	__BUG_FLAGS("", 0);					\
	unreachable();						\
	int __flags = (flags) | BUGFLAG_WARNING | BUGFLAG_ARGS;		\
									\
	__WARN_trap(__WARN_bug_entry(__flags, format), ## arg);		\
	/* prevent tail-call optimization */				\
	asm("");							\
} while (0)

#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;							\
})

#define HAVE_ARCH_BUG
#define HAVE_ARCH_BUG_FORMAT
#define HAVE_ARCH_BUG_FORMAT_ARGS

#endif /* CONFIG_BUG */
#endif /* CONFIG_BUG && CONFIG_CC_HAS_ASM_IMMEDIATE_STRINGS */
#endif /* __ASSEMBLER__ */

#include <asm-generic/bug.h>

+4 −1
Original line number Diff line number Diff line
@@ -120,7 +120,10 @@ struct pt_regs {
			unsigned long gprs[NUM_GPRS];
		};
	};
	union {
		unsigned long orig_gpr2;
		unsigned long monitor_code;
	};
	union {
		struct {
			unsigned int int_code;
+11 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
#include <asm/unistd.h>
#include <asm/page.h>
#include <asm/sigp.h>
#include <asm/bug.h>
#include <asm/irq.h>
#include <asm/fpu-insn.h>
#include <asm/setup.h>
@@ -173,6 +174,16 @@ SYM_FUNC_START(__switch_to_asm)
	BR_EX	%r14
SYM_FUNC_END(__switch_to_asm)

#if defined(CONFIG_BUG) && defined(CONFIG_CC_HAS_ASM_IMMEDIATE_STRINGS)

SYM_FUNC_START(__WARN_trap)
	mc	MONCODE_BUG_ARG(%r0),0
	BR_EX	%r14
SYM_FUNC_END(__WARN_trap)
EXPORT_SYMBOL(__WARN_trap)

#endif /* CONFIG_BUG && CONFIG_CC_HAS_ASM_IMMEDIATE_STRINGS */

#if IS_ENABLED(CONFIG_KVM)
/*
 * __sie64a calling convention:
Loading