1 | /* SPDX-License-Identifier: GPL-2.0 */ |
2 | #ifndef _ASM_X86_BUG_H |
3 | #define _ASM_X86_BUG_H |
4 | |
5 | #include <linux/stringify.h> |
6 | #include <linux/instrumentation.h> |
7 | #include <linux/objtool.h> |
8 | |
9 | /* |
10 | * Despite that some emulators terminate on UD2, we use it for WARN(). |
11 | */ |
12 | #define ASM_UD2 ".byte 0x0f, 0x0b" |
13 | #define INSN_UD2 0x0b0f |
14 | #define LEN_UD2 2 |
15 | |
16 | #ifdef CONFIG_GENERIC_BUG |
17 | |
18 | #ifdef CONFIG_X86_32 |
19 | # define __BUG_REL(val) ".long " __stringify(val) |
20 | #else |
21 | # define __BUG_REL(val) ".long " __stringify(val) " - ." |
22 | #endif |
23 | |
24 | #ifdef CONFIG_DEBUG_BUGVERBOSE |
25 | |
26 | #define _BUG_FLAGS(ins, flags, extra) \ |
27 | do { \ |
28 | asm_inline volatile("1:\t" ins "\n" \ |
29 | ".pushsection __bug_table,\"aw\"\n" \ |
30 | "2:\t" __BUG_REL(1b) "\t# bug_entry::bug_addr\n" \ |
31 | "\t" __BUG_REL(%c0) "\t# bug_entry::file\n" \ |
32 | "\t.word %c1" "\t# bug_entry::line\n" \ |
33 | "\t.word %c2" "\t# bug_entry::flags\n" \ |
34 | "\t.org 2b+%c3\n" \ |
35 | ".popsection\n" \ |
36 | extra \ |
37 | : : "i" (__FILE__), "i" (__LINE__), \ |
38 | "i" (flags), \ |
39 | "i" (sizeof(struct bug_entry))); \ |
40 | } while (0) |
41 | |
42 | #else /* !CONFIG_DEBUG_BUGVERBOSE */ |
43 | |
44 | #define _BUG_FLAGS(ins, flags, extra) \ |
45 | do { \ |
46 | asm_inline volatile("1:\t" ins "\n" \ |
47 | ".pushsection __bug_table,\"aw\"\n" \ |
48 | "2:\t" __BUG_REL(1b) "\t# bug_entry::bug_addr\n" \ |
49 | "\t.word %c0" "\t# bug_entry::flags\n" \ |
50 | "\t.org 2b+%c1\n" \ |
51 | ".popsection\n" \ |
52 | extra \ |
53 | : : "i" (flags), \ |
54 | "i" (sizeof(struct bug_entry))); \ |
55 | } while (0) |
56 | |
57 | #endif /* CONFIG_DEBUG_BUGVERBOSE */ |
58 | |
59 | #else |
60 | |
61 | #define _BUG_FLAGS(ins, flags, extra) asm volatile(ins) |
62 | |
63 | #endif /* CONFIG_GENERIC_BUG */ |
64 | |
65 | #define HAVE_ARCH_BUG |
66 | #define BUG() \ |
67 | do { \ |
68 | instrumentation_begin(); \ |
69 | _BUG_FLAGS(ASM_UD2, 0, ""); \ |
70 | __builtin_unreachable(); \ |
71 | } while (0) |
72 | |
73 | /* |
74 | * This instrumentation_begin() is strictly speaking incorrect; but it |
75 | * suppresses the complaints from WARN()s in noinstr code. If such a WARN() |
76 | * were to trigger, we'd rather wreck the machine in an attempt to get the |
77 | * message out than not know about it. |
78 | */ |
79 | #define __WARN_FLAGS(flags) \ |
80 | do { \ |
81 | __auto_type __flags = BUGFLAG_WARNING|(flags); \ |
82 | instrumentation_begin(); \ |
83 | _BUG_FLAGS(ASM_UD2, __flags, ASM_REACHABLE); \ |
84 | instrumentation_end(); \ |
85 | } while (0) |
86 | |
87 | #include <asm-generic/bug.h> |
88 | |
89 | #endif /* _ASM_X86_BUG_H */ |
90 | |