Commit | Line | Data |
---|---|---|
b2441318 | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
1965aae3 PA |
2 | #ifndef _ASM_X86_BUG_H |
3 | #define _ASM_X86_BUG_H | |
68fdc55c | 4 | |
9a93848f | 5 | #include <linux/stringify.h> |
d19e789f | 6 | #include <linux/instrumentation.h> |
dca5da2a | 7 | #include <linux/objtool.h> |
68fdc55c | 8 | |
9a93848f | 9 | /* |
3b3a371c | 10 | * Despite that some emulators terminate on UD2, we use it for WARN(). |
9a93848f | 11 | */ |
9a93848f | 12 | #define ASM_UD2 ".byte 0x0f, 0x0b" |
9a93848f | 13 | #define INSN_UD2 0x0b0f |
3b3a371c | 14 | #define LEN_UD2 2 |
9a93848f | 15 | |
7424fc6b GN |
16 | /* |
17 | * In clang we have UD1s reporting UBSAN failures on X86, 64 and 32bit. | |
18 | */ | |
19 | #define INSN_ASOP 0x67 | |
029f718f | 20 | #define INSN_LOCK 0xf0 |
7424fc6b GN |
21 | #define OPCODE_ESCAPE 0x0f |
22 | #define SECOND_BYTE_OPCODE_UD1 0xb9 | |
23 | #define SECOND_BYTE_OPCODE_UD2 0x0b | |
24 | ||
25 | #define BUG_NONE 0xffff | |
c20ad96c PZ |
26 | #define BUG_UD2 0xfffe |
27 | #define BUG_UD1 0xfffd | |
28 | #define BUG_UD1_UBSAN 0xfffc | |
2e044911 | 29 | #define BUG_EA 0xffea |
029f718f | 30 | #define BUG_LOCK 0xfff0 |
7424fc6b | 31 | |
ffb61c63 IM |
32 | #ifdef CONFIG_GENERIC_BUG |
33 | ||
34 | #ifdef CONFIG_X86_32 | |
35 | # define __BUG_REL(val) ".long " __stringify(val) | |
36 | #else | |
69505e3d | 37 | # define __BUG_REL(val) ".long " __stringify(val) " - ." |
ffb61c63 IM |
38 | #endif |
39 | ||
40 | #ifdef CONFIG_DEBUG_BUGVERBOSE | |
41 | ||
bfb1a7c9 | 42 | #define _BUG_FLAGS(ins, flags, extra) \ |
ffb61c63 | 43 | do { \ |
32ee8230 | 44 | asm_inline volatile("1:\t" ins "\n" \ |
ffb61c63 IM |
45 | ".pushsection __bug_table,\"aw\"\n" \ |
46 | "2:\t" __BUG_REL(1b) "\t# bug_entry::bug_addr\n" \ | |
47 | "\t" __BUG_REL(%c0) "\t# bug_entry::file\n" \ | |
48 | "\t.word %c1" "\t# bug_entry::line\n" \ | |
49 | "\t.word %c2" "\t# bug_entry::flags\n" \ | |
50 | "\t.org 2b+%c3\n" \ | |
bfb1a7c9 ND |
51 | ".popsection\n" \ |
52 | extra \ | |
ffb61c63 IM |
53 | : : "i" (__FILE__), "i" (__LINE__), \ |
54 | "i" (flags), \ | |
55 | "i" (sizeof(struct bug_entry))); \ | |
56 | } while (0) | |
57 | ||
58 | #else /* !CONFIG_DEBUG_BUGVERBOSE */ | |
59 | ||
bfb1a7c9 | 60 | #define _BUG_FLAGS(ins, flags, extra) \ |
9a93848f | 61 | do { \ |
32ee8230 | 62 | asm_inline volatile("1:\t" ins "\n" \ |
ffb61c63 IM |
63 | ".pushsection __bug_table,\"aw\"\n" \ |
64 | "2:\t" __BUG_REL(1b) "\t# bug_entry::bug_addr\n" \ | |
65 | "\t.word %c0" "\t# bug_entry::flags\n" \ | |
66 | "\t.org 2b+%c1\n" \ | |
bfb1a7c9 ND |
67 | ".popsection\n" \ |
68 | extra \ | |
ffb61c63 | 69 | : : "i" (flags), \ |
9a93848f PZ |
70 | "i" (sizeof(struct bug_entry))); \ |
71 | } while (0) | |
72 | ||
ffb61c63 IM |
73 | #endif /* CONFIG_DEBUG_BUGVERBOSE */ |
74 | ||
75 | #else | |
76 | ||
bfb1a7c9 | 77 | #define _BUG_FLAGS(ins, flags, extra) asm volatile(ins) |
ffb61c63 IM |
78 | |
79 | #endif /* CONFIG_GENERIC_BUG */ | |
80 | ||
70579a86 | 81 | #define HAVE_ARCH_BUG |
86d8a086 JP |
82 | #define BUG() \ |
83 | do { \ | |
5916d5f9 | 84 | instrumentation_begin(); \ |
bfb1a7c9 ND |
85 | _BUG_FLAGS(ASM_UD2, 0, ""); \ |
86 | __builtin_unreachable(); \ | |
86d8a086 | 87 | } while (0) |
9a93848f | 88 | |
8e8bb06d PZ |
89 | /* |
90 | * This instrumentation_begin() is strictly speaking incorrect; but it | |
91 | * suppresses the complaints from WARN()s in noinstr code. If such a WARN() | |
92 | * were to trigger, we'd rather wreck the machine in an attempt to get the | |
93 | * message out than not know about it. | |
94 | */ | |
2b5db668 JP |
95 | #define __WARN_FLAGS(flags) \ |
96 | do { \ | |
9ce02f0f | 97 | __auto_type __flags = BUGFLAG_WARNING|(flags); \ |
5916d5f9 | 98 | instrumentation_begin(); \ |
87116ae6 | 99 | _BUG_FLAGS(ASM_UD2, __flags, ANNOTATE_REACHABLE(1b)); \ |
5916d5f9 | 100 | instrumentation_end(); \ |
2b5db668 | 101 | } while (0) |
9a93848f | 102 | |
68fdc55c | 103 | #include <asm-generic/bug.h> |
f05e798a | 104 | |
1965aae3 | 105 | #endif /* _ASM_X86_BUG_H */ |