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 
8 /*
9  * Define an illegal instr to trap on the bug.
10  * We don't use 0 because that marks the end of a function
11  * in the ELF ABI.  That's "Boo Boo" in case you wonder...
12  */
13 #define BUG_OPCODE .long 0x00b00b00  /* For asm */
14 #define BUG_ILLEGAL_INSTR "0x00b00b00" /* For BUG macro */
15 
16 #ifdef CONFIG_BUG
17 
18 #ifdef __ASSEMBLY__
19 #include <asm/asm-offsets.h>
20 #ifdef CONFIG_DEBUG_BUGVERBOSE
21 .macro EMIT_BUG_ENTRY addr,file,line,flags
22 	 .section __bug_table,"aw"
23 5001:	 PPC_LONG \addr, 5002f
24 	 .short \line, \flags
25 	 .org 5001b+BUG_ENTRY_SIZE
26 	 .previous
27 	 .section .rodata,"a"
28 5002:	 .asciz "\file"
29 	 .previous
30 .endm
31 #else
32 .macro EMIT_BUG_ENTRY addr,file,line,flags
33 	 .section __bug_table,"aw"
34 5001:	 PPC_LONG \addr
35 	 .short \flags
36 	 .org 5001b+BUG_ENTRY_SIZE
37 	 .previous
38 .endm
39 #endif /* verbose */
40 
41 #else /* !__ASSEMBLY__ */
42 /* _EMIT_BUG_ENTRY expects args %0,%1,%2,%3 to be FILE, LINE, flags and
43    sizeof(struct bug_entry), respectively */
44 #ifdef CONFIG_DEBUG_BUGVERBOSE
45 #define _EMIT_BUG_ENTRY				\
46 	".section __bug_table,\"aw\"\n"		\
47 	"2:\t" PPC_LONG "1b, %0\n"		\
48 	"\t.short %1, %2\n"			\
49 	".org 2b+%3\n"				\
50 	".previous\n"
51 #else
52 #define _EMIT_BUG_ENTRY				\
53 	".section __bug_table,\"aw\"\n"		\
54 	"2:\t" PPC_LONG "1b\n"			\
55 	"\t.short %2\n"				\
56 	".org 2b+%3\n"				\
57 	".previous\n"
58 #endif
59 
60 /*
61  * BUG_ON() and WARN_ON() do their best to cooperate with compile-time
62  * optimisations. However depending on the complexity of the condition
63  * some compiler versions may not produce optimal results.
64  */
65 
66 #define BUG() do {						\
67 	__asm__ __volatile__(					\
68 		"1:	twi 31,0,0\n"				\
69 		_EMIT_BUG_ENTRY					\
70 		: : "i" (__FILE__), "i" (__LINE__),		\
71 		    "i" (0), "i"  (sizeof(struct bug_entry)));	\
72 	unreachable();						\
73 } while (0)
74 
75 #define BUG_ON(x) do {						\
76 	if (__builtin_constant_p(x)) {				\
77 		if (x)						\
78 			BUG();					\
79 	} else {						\
80 		__asm__ __volatile__(				\
81 		"1:	"PPC_TLNEI"	%4,0\n"			\
82 		_EMIT_BUG_ENTRY					\
83 		: : "i" (__FILE__), "i" (__LINE__), "i" (0),	\
84 		  "i" (sizeof(struct bug_entry)),		\
85 		  "r" ((__force long)(x)));			\
86 	}							\
87 } while (0)
88 
89 #define __WARN_FLAGS(flags) do {				\
90 	__asm__ __volatile__(					\
91 		"1:	twi 31,0,0\n"				\
92 		_EMIT_BUG_ENTRY					\
93 		: : "i" (__FILE__), "i" (__LINE__),		\
94 		  "i" (BUGFLAG_WARNING|(flags)),		\
95 		  "i" (sizeof(struct bug_entry)));		\
96 } while (0)
97 
98 #define WARN_ON(x) ({						\
99 	int __ret_warn_on = !!(x);				\
100 	if (__builtin_constant_p(__ret_warn_on)) {		\
101 		if (__ret_warn_on)				\
102 			__WARN();				\
103 	} else {						\
104 		__asm__ __volatile__(				\
105 		"1:	"PPC_TLNEI"	%4,0\n"			\
106 		_EMIT_BUG_ENTRY					\
107 		: : "i" (__FILE__), "i" (__LINE__),		\
108 		  "i" (BUGFLAG_WARNING|BUGFLAG_TAINT(TAINT_WARN)),\
109 		  "i" (sizeof(struct bug_entry)),		\
110 		  "r" (__ret_warn_on));				\
111 	}							\
112 	unlikely(__ret_warn_on);				\
113 })
114 
115 #define HAVE_ARCH_BUG
116 #define HAVE_ARCH_BUG_ON
117 #define HAVE_ARCH_WARN_ON
118 #endif /* __ASSEMBLY __ */
119 #else
120 #ifdef __ASSEMBLY__
121 .macro EMIT_BUG_ENTRY addr,file,line,flags
122 .endm
123 #else /* !__ASSEMBLY__ */
124 #define _EMIT_BUG_ENTRY
125 #endif
126 #endif /* CONFIG_BUG */
127 
128 #include <asm-generic/bug.h>
129 
130 #ifndef __ASSEMBLY__
131 
132 struct pt_regs;
133 extern int do_page_fault(struct pt_regs *, unsigned long, unsigned long);
134 extern void bad_page_fault(struct pt_regs *, unsigned long, int);
135 extern void _exception(int, struct pt_regs *, int, unsigned long);
136 extern void _exception_pkey(int, struct pt_regs *, int, unsigned long, int);
137 extern void die(const char *, struct pt_regs *, long);
138 extern bool die_will_crash(void);
139 extern void panic_flush_kmsg_start(void);
140 extern void panic_flush_kmsg_end(void);
141 #endif /* !__ASSEMBLY__ */
142 
143 #endif /* __KERNEL__ */
144 #endif /* _ASM_POWERPC_BUG_H */
145