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