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