1 #ifndef __X86_BUG_H__
2 #define __X86_BUG_H__
3 
4 #define BUG_DISP_WIDTH    24
5 #define BUG_LINE_LO_WIDTH (31 - BUG_DISP_WIDTH)
6 #define BUG_LINE_HI_WIDTH (31 - BUG_DISP_WIDTH)
7 
8 #define BUGFRAME_run_fn 0
9 #define BUGFRAME_warn   1
10 #define BUGFRAME_bug    2
11 #define BUGFRAME_assert 3
12 
13 #define BUGFRAME_NR     4
14 
15 #ifndef __ASSEMBLY__
16 
17 struct bug_frame {
18     signed int loc_disp:BUG_DISP_WIDTH;
19     unsigned int line_hi:BUG_LINE_HI_WIDTH;
20     signed int ptr_disp:BUG_DISP_WIDTH;
21     unsigned int line_lo:BUG_LINE_LO_WIDTH;
22     signed int msg_disp[];
23 };
24 
25 #define bug_loc(b) ((const void *)(b) + (b)->loc_disp)
26 #define bug_ptr(b) ((const void *)(b) + (b)->ptr_disp)
27 #define bug_line(b) (((((b)->line_hi + ((b)->loc_disp < 0)) &                \
28                        ((1 << BUG_LINE_HI_WIDTH) - 1)) <<                    \
29                       BUG_LINE_LO_WIDTH) +                                   \
30                      (((b)->line_lo + ((b)->ptr_disp < 0)) &                 \
31                       ((1 << BUG_LINE_LO_WIDTH) - 1)))
32 #define bug_msg(b) ((const char *)(b) + (b)->msg_disp[1])
33 
34 #define _ASM_BUGFRAME_TEXT(second_frame)                                     \
35     ".Lbug%=: ud2\n"                                                         \
36     ".pushsection .bug_frames.%c[bf_type], \"a\", @progbits\n"               \
37     ".p2align 2\n"                                                           \
38     ".Lfrm%=:\n"                                                             \
39     ".long (.Lbug%= - .Lfrm%=) + %c[bf_line_hi]\n"                           \
40     ".long (%c[bf_ptr] - .Lfrm%=) + %c[bf_line_lo]\n"                        \
41     ".if " #second_frame "\n"                                                \
42     ".long 0, %c[bf_msg] - .Lfrm%=\n"                                        \
43     ".endif\n"                                                               \
44     ".popsection\n"                                                          \
45 
46 #define _ASM_BUGFRAME_INFO(type, line, ptr, msg)                             \
47     [bf_type]    "i" (type),                                                 \
48     [bf_ptr]     "i" (ptr),                                                  \
49     [bf_msg]     "i" (msg),                                                  \
50     [bf_line_lo] "i" ((line & ((1 << BUG_LINE_LO_WIDTH) - 1))                \
51                       << BUG_DISP_WIDTH),                                    \
52     [bf_line_hi] "i" (((line) >> BUG_LINE_LO_WIDTH) << BUG_DISP_WIDTH)
53 
54 #define BUG_FRAME(type, line, ptr, second_frame, msg) do {                   \
55     BUILD_BUG_ON((line) >> (BUG_LINE_LO_WIDTH + BUG_LINE_HI_WIDTH));         \
56     BUILD_BUG_ON((type) >= BUGFRAME_NR);                                     \
57     asm volatile ( _ASM_BUGFRAME_TEXT(second_frame)                          \
58                    :: _ASM_BUGFRAME_INFO(type, line, ptr, msg) );            \
59 } while (0)
60 
61 
62 #define WARN() BUG_FRAME(BUGFRAME_warn, __LINE__, __FILE__, 0, NULL)
63 #define BUG() do {                                              \
64     BUG_FRAME(BUGFRAME_bug,  __LINE__, __FILE__, 0, NULL);      \
65     unreachable();                                              \
66 } while (0)
67 
68 #define run_in_exception_handler(fn) BUG_FRAME(BUGFRAME_run_fn, 0, fn, 0, NULL)
69 
70 #define assert_failed(msg) do {                                 \
71     BUG_FRAME(BUGFRAME_assert, __LINE__, __FILE__, 1, msg);     \
72     unreachable();                                              \
73 } while (0)
74 
75 extern const struct bug_frame __start_bug_frames[],
76                               __stop_bug_frames_0[],
77                               __stop_bug_frames_1[],
78                               __stop_bug_frames_2[],
79                               __stop_bug_frames_3[];
80 
81 #else  /* !__ASSEMBLY__ */
82 
83 /*
84  * Construct a bugframe, suitable for using in assembly code.  Should always
85  * match the C version above.  One complication is having to stash the strings
86  * in .rodata
87  */
88     .macro BUG_FRAME type, line, file_str, second_frame, msg
89 
90     .if \type >= BUGFRAME_NR
91         .error "Invalid BUGFRAME index"
92     .endif
93 
94     .L\@ud: ud2a
95 
96     .pushsection .rodata.str1, "aMS", @progbits, 1
97          .L\@s1: .asciz "\file_str"
98     .popsection
99 
100     .pushsection .bug_frames.\type, "a", @progbits
101         .p2align 2
102         .L\@bf:
103         .long (.L\@ud - .L\@bf) + \
104                ((\line >> BUG_LINE_LO_WIDTH) << BUG_DISP_WIDTH)
105         .long (.L\@s1 - .L\@bf) + \
106                ((\line & ((1 << BUG_LINE_LO_WIDTH) - 1)) << BUG_DISP_WIDTH)
107 
108         .if \second_frame
109             .pushsection .rodata.str1, "aMS", @progbits, 1
110                 .L\@s2: .asciz "\msg"
111             .popsection
112             .long 0, (.L\@s2 - .L\@bf)
113         .endif
114     .popsection
115     .endm
116 
117 #define WARN BUG_FRAME BUGFRAME_warn, __LINE__, __FILE__, 0, 0
118 #define BUG  BUG_FRAME BUGFRAME_bug,  __LINE__, __FILE__, 0, 0
119 
120 #define ASSERT_FAILED(msg)                                      \
121      BUG_FRAME BUGFRAME_assert, __LINE__, __FILE__, 1, msg
122 
123 #endif /* !__ASSEMBLY__ */
124 
125 #endif /* __X86_BUG_H__ */
126