xref: /openbmc/linux/arch/powerpc/include/asm/bug.h (revision 47010c04)
1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef _ASM_POWERPC_BUG_H
3 #define _ASM_POWERPC_BUG_H
4 #ifdef __KERNEL__
5 
6 #include <asm/asm-compat.h>
7 #include <asm/extable.h>
8 
9 #ifdef CONFIG_BUG
10 
11 #ifdef __ASSEMBLY__
12 #include <asm/asm-offsets.h>
13 #ifdef CONFIG_DEBUG_BUGVERBOSE
14 .macro __EMIT_BUG_ENTRY addr,file,line,flags
15 	 .section __bug_table,"aw"
16 5001:	 .4byte \addr - 5001b, 5002f - 5001b
17 	 .short \line, \flags
18 	 .org 5001b+BUG_ENTRY_SIZE
19 	 .previous
20 	 .section .rodata,"a"
21 5002:	 .asciz "\file"
22 	 .previous
23 .endm
24 #else
25 .macro __EMIT_BUG_ENTRY addr,file,line,flags
26 	 .section __bug_table,"aw"
27 5001:	 .4byte \addr - 5001b
28 	 .short \flags
29 	 .org 5001b+BUG_ENTRY_SIZE
30 	 .previous
31 .endm
32 #endif /* verbose */
33 
34 .macro EMIT_WARN_ENTRY addr,file,line,flags
35 	EX_TABLE(\addr,\addr+4)
36 	__EMIT_BUG_ENTRY \addr,\file,\line,\flags
37 .endm
38 
39 .macro EMIT_BUG_ENTRY addr,file,line,flags
40 	.if \flags & 1 /* BUGFLAG_WARNING */
41 	.err /* Use EMIT_WARN_ENTRY for warnings */
42 	.endif
43 	__EMIT_BUG_ENTRY \addr,\file,\line,\flags
44 .endm
45 
46 #else /* !__ASSEMBLY__ */
47 /* _EMIT_BUG_ENTRY expects args %0,%1,%2,%3 to be FILE, LINE, flags and
48    sizeof(struct bug_entry), respectively */
49 #ifdef CONFIG_DEBUG_BUGVERBOSE
50 #define _EMIT_BUG_ENTRY				\
51 	".section __bug_table,\"aw\"\n"		\
52 	"2:\t.4byte 1b - 2b, %0 - 2b\n"		\
53 	"\t.short %1, %2\n"			\
54 	".org 2b+%3\n"				\
55 	".previous\n"
56 #else
57 #define _EMIT_BUG_ENTRY				\
58 	".section __bug_table,\"aw\"\n"		\
59 	"2:\t.4byte 1b - 2b\n"			\
60 	"\t.short %2\n"				\
61 	".org 2b+%3\n"				\
62 	".previous\n"
63 #endif
64 
65 #define BUG_ENTRY(insn, flags, ...)			\
66 	__asm__ __volatile__(				\
67 		"1:	" insn "\n"			\
68 		_EMIT_BUG_ENTRY				\
69 		: : "i" (__FILE__), "i" (__LINE__),	\
70 		  "i" (flags),				\
71 		  "i" (sizeof(struct bug_entry)),	\
72 		  ##__VA_ARGS__)
73 
74 #define WARN_ENTRY(insn, flags, label, ...)		\
75 	asm_volatile_goto(				\
76 		"1:	" insn "\n"			\
77 		EX_TABLE(1b, %l[label])			\
78 		_EMIT_BUG_ENTRY				\
79 		: : "i" (__FILE__), "i" (__LINE__),	\
80 		  "i" (flags),				\
81 		  "i" (sizeof(struct bug_entry)),	\
82 		  ##__VA_ARGS__ : : label)
83 
84 /*
85  * BUG_ON() and WARN_ON() do their best to cooperate with compile-time
86  * optimisations. However depending on the complexity of the condition
87  * some compiler versions may not produce optimal results.
88  */
89 
90 #define BUG() do {						\
91 	BUG_ENTRY("twi 31, 0, 0", 0);				\
92 	unreachable();						\
93 } while (0)
94 #define HAVE_ARCH_BUG
95 
96 #define __WARN_FLAGS(flags) do {				\
97 	__label__ __label_warn_on;				\
98 								\
99 	WARN_ENTRY("twi 31, 0, 0", BUGFLAG_WARNING | (flags), __label_warn_on); \
100 	unreachable();						\
101 								\
102 __label_warn_on:						\
103 	break;							\
104 } while (0)
105 
106 #ifdef CONFIG_PPC64
107 #define BUG_ON(x) do {						\
108 	if (__builtin_constant_p(x)) {				\
109 		if (x)						\
110 			BUG();					\
111 	} else {						\
112 		BUG_ENTRY(PPC_TLNEI " %4, 0", 0, "r" ((__force long)(x)));	\
113 	}							\
114 } while (0)
115 
116 #define WARN_ON(x) ({						\
117 	bool __ret_warn_on = false;				\
118 	do {							\
119 		if (__builtin_constant_p((x))) {		\
120 			if (!(x)) 				\
121 				break; 				\
122 			__WARN();				\
123 			__ret_warn_on = true;			\
124 		} else {					\
125 			__label__ __label_warn_on;		\
126 								\
127 			WARN_ENTRY(PPC_TLNEI " %4, 0",		\
128 				   BUGFLAG_WARNING | BUGFLAG_TAINT(TAINT_WARN),	\
129 				   __label_warn_on,		\
130 				   "r" ((__force long)(x)));	\
131 			break;					\
132 __label_warn_on:						\
133 			__ret_warn_on = true;			\
134 		}						\
135 	} while (0);						\
136 	unlikely(__ret_warn_on);				\
137 })
138 
139 #define HAVE_ARCH_BUG_ON
140 #define HAVE_ARCH_WARN_ON
141 #endif
142 
143 #endif /* __ASSEMBLY __ */
144 #else
145 #ifdef __ASSEMBLY__
146 .macro EMIT_BUG_ENTRY addr,file,line,flags
147 .endm
148 .macro EMIT_WARN_ENTRY addr,file,line,flags
149 .endm
150 #else /* !__ASSEMBLY__ */
151 #define _EMIT_BUG_ENTRY
152 #define _EMIT_WARN_ENTRY
153 #endif
154 #endif /* CONFIG_BUG */
155 
156 #include <asm-generic/bug.h>
157 
158 #ifndef __ASSEMBLY__
159 
160 struct pt_regs;
161 void hash__do_page_fault(struct pt_regs *);
162 void bad_page_fault(struct pt_regs *, int);
163 extern void _exception(int, struct pt_regs *, int, unsigned long);
164 extern void _exception_pkey(struct pt_regs *, unsigned long, int);
165 extern void die(const char *, struct pt_regs *, long);
166 void die_mce(const char *str, struct pt_regs *regs, long err);
167 extern bool die_will_crash(void);
168 extern void panic_flush_kmsg_start(void);
169 extern void panic_flush_kmsg_end(void);
170 #endif /* !__ASSEMBLY__ */
171 
172 #endif /* __KERNEL__ */
173 #endif /* _ASM_POWERPC_BUG_H */
174