summaryrefslogtreecommitdiff
path: root/arch/s390/include/asm/bug.h
blob: 59017fd3d9358d495fc06ec9775b12cbb4c27f37 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_S390_BUG_H
#define _ASM_S390_BUG_H

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

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

#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 __BUG_ENTRY_VERBOSE(format, file, line)
#endif

#ifdef CONFIG_DEBUG_BUGVERBOSE_DETAILED
#define WARN_CONDITION_STR(cond_str) cond_str
#else
#define WARN_CONDITION_STR(cond_str) ""
#endif

#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 __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()								\
do {									\
	__BUG_ASM("", 0);						\
	unreachable();							\
} while (0)

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

#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 {									\
	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 && CONFIG_CC_HAS_ASM_IMMEDIATE_STRINGS */
#endif /* __ASSEMBLER__ */

#include <asm-generic/bug.h>

#endif /* _ASM_S390_BUG_H */