xref: /linux/arch/s390/include/asm/bug.h (revision 69050f8d6d075dc01af7a5f2f550a8067510366f)
1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef _ASM_S390_BUG_H
3 #define _ASM_S390_BUG_H
4 
5 #include <linux/compiler.h>
6 #include <linux/const.h>
7 
8 #define	MONCODE_BUG	_AC(0, U)
9 #define	MONCODE_BUG_ARG _AC(1, U)
10 
11 #ifndef __ASSEMBLER__
12 #if defined(CONFIG_BUG) && defined(CONFIG_CC_HAS_ASM_IMMEDIATE_STRINGS)
13 
14 #ifdef CONFIG_DEBUG_BUGVERBOSE
15 #define __BUG_ENTRY_VERBOSE(format, file, line)				\
16 	"	.long	" format " - .	# bug_entry::format\n"		\
17 	"	.long	" file " - .	# bug_entry::file\n"		\
18 	"	.short	" line "	# bug_entry::line\n"
19 #else
20 #define __BUG_ENTRY_VERBOSE(format, file, line)
21 #endif
22 
23 #ifdef CONFIG_DEBUG_BUGVERBOSE_DETAILED
24 #define WARN_CONDITION_STR(cond_str) cond_str
25 #else
26 #define WARN_CONDITION_STR(cond_str) ""
27 #endif
28 
29 #define __BUG_ENTRY(format, file, line, flags, size)			\
30 		"	.section __bug_table,\"aw\"\n"			\
31 		"1:	.long	0b - .	# bug_entry::bug_addr\n"	\
32 		__BUG_ENTRY_VERBOSE(format, file, line)			\
33 		"	.short	"flags"	# bug_entry::flags\n"		\
34 		"	.org	1b+"size"\n"				\
35 		"	.previous"
36 
37 #define __BUG_ASM(cond_str, flags)					\
38 do {									\
39 	asm_inline volatile("\n"					\
40 		"0:	mc	%[monc](%%r0),0\n"			\
41 		__BUG_ENTRY("%[frmt]", "%[file]", "%[line]",		\
42 			    "%[flgs]", "%[size]")			\
43 		:							\
44 		: [monc] "i" (MONCODE_BUG),				\
45 		  [frmt] "i" (WARN_CONDITION_STR(cond_str)),		\
46 		  [file] "i" (__FILE__),				\
47 		  [line] "i" (__LINE__),				\
48 		  [flgs] "i" (flags),					\
49 		  [size] "i" (sizeof(struct bug_entry)));		\
50 } while (0)
51 
52 #define BUG()								\
53 do {									\
54 	__BUG_ASM("", 0);						\
55 	unreachable();							\
56 } while (0)
57 
58 #define __WARN_FLAGS(cond_str, flags)					\
59 do {									\
60 	__BUG_ASM(cond_str, BUGFLAG_WARNING | (flags));			\
61 } while (0)
62 
63 #define __WARN_bug_entry(flags, format)					\
64 ({									\
65 	struct bug_entry *bug;						\
66 									\
67 	asm_inline volatile("\n"					\
68 		"0:	larl	%[bug],1f\n"				\
69 		__BUG_ENTRY("%[frmt]", "%[file]", "%[line]",		\
70 			    "%[flgs]", "%[size]")			\
71 		: [bug] "=d" (bug)					\
72 		: [frmt] "i" (format),					\
73 		  [file] "i" (__FILE__),				\
74 		  [line] "i" (__LINE__),				\
75 		  [flgs] "i" (flags),					\
76 		  [size] "i" (sizeof(struct bug_entry)));		\
77 	bug;								\
78 })
79 
80 /*
81  * Variable Argument List (va_list) as defined in ELF Application
82  * Binary Interface s390x Supplement documentation.
83  */
84 struct arch_va_list {
85 	long __gpr;
86 	long __fpr;
87 	void *__overflow_arg_area;
88 	void *__reg_save_area;
89 };
90 
91 struct bug_entry;
92 struct pt_regs;
93 
94 void *__warn_args(struct arch_va_list *args, struct pt_regs *regs);
95 void __WARN_trap(struct bug_entry *bug, ...);
96 
97 #define __WARN_print_arg(flags, format, arg...)				\
98 do {									\
99 	int __flags = (flags) | BUGFLAG_WARNING | BUGFLAG_ARGS;		\
100 									\
101 	__WARN_trap(__WARN_bug_entry(__flags, format), ## arg);		\
102 	/* prevent tail-call optimization */				\
103 	asm("");							\
104 } while (0)
105 
106 #define __WARN_printf(taint, fmt, arg...) \
107 	__WARN_print_arg(BUGFLAG_TAINT(taint), fmt, ## arg)
108 
109 #define WARN_ONCE(cond, format, arg...)					\
110 ({									\
111 	int __ret_warn_on = !!(cond);					\
112 									\
113 	if (unlikely(__ret_warn_on)) {					\
114 		__WARN_print_arg(BUGFLAG_ONCE|BUGFLAG_TAINT(TAINT_WARN),\
115 				format, ## arg);			\
116 	}								\
117 	__ret_warn_on;							\
118 })
119 
120 #define HAVE_ARCH_BUG
121 #define HAVE_ARCH_BUG_FORMAT
122 #define HAVE_ARCH_BUG_FORMAT_ARGS
123 
124 #endif /* CONFIG_BUG && CONFIG_CC_HAS_ASM_IMMEDIATE_STRINGS */
125 #endif /* __ASSEMBLER__ */
126 
127 #include <asm-generic/bug.h>
128 
129 #endif /* _ASM_S390_BUG_H */
130