1 #ifndef __XEN_BUG_H__
2 #define __XEN_BUG_H__
3
4 #define BUGFRAME_run_fn 0
5 #define BUGFRAME_warn 1
6 #define BUGFRAME_bug 2
7 #define BUGFRAME_assert 3
8
9 #define BUGFRAME_NR 4
10
11 #define BUG_DISP_WIDTH 24
12 #define BUG_LINE_LO_WIDTH (31 - BUG_DISP_WIDTH)
13 #define BUG_LINE_HI_WIDTH (31 - BUG_DISP_WIDTH)
14
15 #include <asm/bug.h>
16
17 #ifndef __ASSEMBLY__
18
19 #include <xen/compiler.h>
20 #include <xen/macros.h>
21 #include <xen/types.h>
22
23 #ifndef BUG_FRAME_STRUCT
24
25 struct bug_frame {
26 signed int loc_disp:BUG_DISP_WIDTH;
27 unsigned int line_hi:BUG_LINE_HI_WIDTH;
28 signed int ptr_disp:BUG_DISP_WIDTH;
29 unsigned int line_lo:BUG_LINE_LO_WIDTH;
30 signed int msg_disp[];
31 };
32
33 #define bug_loc(b) ((unsigned long)(b) + (b)->loc_disp)
34
35 #define bug_ptr(b) ((const void *)(b) + (b)->ptr_disp)
36
37 #define bug_line(b) (((((b)->line_hi + ((b)->loc_disp < 0)) & \
38 ((1 << BUG_LINE_HI_WIDTH) - 1)) << \
39 BUG_LINE_LO_WIDTH) + \
40 (((b)->line_lo + ((b)->ptr_disp < 0)) & \
41 ((1 << BUG_LINE_LO_WIDTH) - 1)))
42
43 #define bug_msg(b) ((const char *)(b) + (b)->msg_disp[1])
44
45 #define BUG_CHECK_LINE_WIDTH(line) \
46 BUILD_BUG_ON((line) >> (BUG_LINE_LO_WIDTH + BUG_LINE_HI_WIDTH))
47
48 #elif !defined(BUG_CHECK_LINE_WIDTH)
49
50 #define BUG_CHECK_LINE_WIDTH(line) ((void)(line))
51
52 #endif /* BUG_FRAME_STRUCT */
53
54
55 /*
56 * Some architectures mark immediate instruction operands in a special way.
57 * In such cases the special marking may need omitting when specifying
58 * directive operands. Allow architectures to specify a suitable
59 * modifier.
60 */
61 #ifndef BUG_ASM_CONST
62 #define BUG_ASM_CONST ""
63 #endif
64
65 #ifndef _ASM_BUGFRAME_TEXT
66
67 #define _ASM_BUGFRAME_TEXT(second_frame) \
68 ".Lbug%=:"BUG_INSTR"\n" \
69 " .pushsection .bug_frames.%"BUG_ASM_CONST"[bf_type], \"a\", %%progbits\n" \
70 " .p2align 2\n" \
71 ".Lfrm%=:\n" \
72 " .long (.Lbug%= - .Lfrm%=) + %"BUG_ASM_CONST"[bf_line_hi]\n" \
73 " .long (%"BUG_ASM_CONST"[bf_ptr] - .Lfrm%=) + %"BUG_ASM_CONST"[bf_line_lo]\n"\
74 " .if " #second_frame "\n" \
75 " .long 0, %"BUG_ASM_CONST"[bf_msg] - .Lfrm%=\n" \
76 " .endif\n" \
77 " .popsection\n"
78
79 #define _ASM_BUGFRAME_INFO(type, line, ptr, msg) \
80 [bf_type] "i" (type), \
81 [bf_ptr] "i" (ptr), \
82 [bf_msg] "i" (msg), \
83 [bf_line_lo] "i" (((line) & ((1 << BUG_LINE_LO_WIDTH) - 1)) \
84 << BUG_DISP_WIDTH), \
85 [bf_line_hi] "i" (((line) >> BUG_LINE_LO_WIDTH) << BUG_DISP_WIDTH)
86
87 #endif /* _ASM_BUGFRAME_TEXT */
88
89 #ifndef BUG_FRAME
90
91 #define BUG_FRAME(type, line, ptr, second_frame, msg) do { \
92 BUG_CHECK_LINE_WIDTH(line); \
93 BUILD_BUG_ON((type) >= BUGFRAME_NR); \
94 asm_inline volatile ( \
95 _ASM_BUGFRAME_TEXT(second_frame) \
96 :: _ASM_BUGFRAME_INFO(type, line, ptr, msg) ); \
97 } while ( false )
98
99 #endif
100
101 struct cpu_user_regs;
102 typedef void bug_fn_t(const struct cpu_user_regs *regs);
103
104 #ifndef run_in_exception_handler
105
run_in_exception_handler(bug_fn_t * fn)106 static void always_inline run_in_exception_handler(bug_fn_t *fn)
107 {
108 BUG_FRAME(BUGFRAME_run_fn, 0, fn, 0, NULL);
109 }
110
111 #endif /* run_in_exception_handler */
112
113 #ifndef WARN
114 #define WARN() BUG_FRAME(BUGFRAME_warn, __LINE__, __FILE__, 0, NULL)
115 #endif
116
117 #ifndef BUG
118 #define BUG() do { \
119 BUG_FRAME(BUGFRAME_bug, __LINE__, __FILE__, 0, NULL); \
120 unreachable(); \
121 } while ( false )
122 #endif
123
124 #ifndef assert_failed
125 #define assert_failed(msg) do { \
126 BUG_FRAME(BUGFRAME_assert, __LINE__, __FILE__, 1, msg); \
127 unreachable(); \
128 } while ( false )
129 #endif
130
131 #define BUG_ON(p) do { if (unlikely(p)) BUG(); } while (0)
132 #define WARN_ON(p) ({ \
133 bool ret_warn_on_ = (p); \
134 \
135 if ( unlikely(ret_warn_on_) ) \
136 WARN(); \
137 unlikely(ret_warn_on_); \
138 })
139
140 #ifndef NDEBUG
141 #define ASSERT(p) \
142 do { if ( unlikely(!(p)) ) assert_failed(#p); } while (0)
143 #define ASSERT_UNREACHABLE() assert_failed("unreachable")
144 #else
145 #define ASSERT(p) do { if ( 0 && (p) ) {} } while (0)
146 #define ASSERT_UNREACHABLE() do { } while (0)
147 #endif
148
149 #ifdef CONFIG_GENERIC_BUG_FRAME
150
151 /*
152 * Returns a negative value in case of an error otherwise
153 * BUGFRAME_{run_fn, warn, bug, assert}
154 */
155 int do_bug_frame(const struct cpu_user_regs *regs, unsigned long pc);
156
157 #endif /* CONFIG_GENERIC_BUG_FRAME */
158
159 #endif /* !__ASSEMBLY__ */
160
161 #endif /* __XEN_BUG_H__ */
162 /*
163 * Local variables:
164 * mode: C
165 * c-file-style: "BSD"
166 * c-basic-offset: 4
167 * indent-tabs-mode: nil
168 * End:
169 */
170