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