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