x86/bug: Merge annotate_reachable() into _BUG_FLAGS() asm
In __WARN_FLAGS(), we had two asm statements (abbreviated): asm volatile("ud2"); asm volatile(".pushsection .discard.reachable"); These pair of statements are used to trigger an exception, but then help objtool understand that for warnings, control flow will be restored immediately afterwards. The problem is that volatile is not a compiler barrier. GCC explicitly documents this: > Note that the compiler can move even volatile asm instructions > relative to other code, including across jump instructions. Also, no clobbers are specified to prevent instructions from subsequent statements from being scheduled by compiler before the second asm statement. This can lead to instructions from subsequent statements being emitted by the compiler before the second asm statement. Providing a scheduling model such as via -march= options enables the compiler to better schedule instructions with known latencies to hide latencies from data hazards compared to inline asm statements in which latencies are not estimated. If an instruction gets scheduled by the compiler between the two asm statements, then objtool will think that it is not reachable, producing a warning. To prevent instructions from being scheduled in between the two asm statements, merge them. Also remove an unnecessary unreachable() asm annotation from BUG() in favor of __builtin_unreachable(). objtool is able to track that the ud2 from BUG() terminates control flow within the function. Link: https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#Volatile Link: https://github.com/ClangBuiltLinux/linux/issues/1483 Signed-off-by: Nick Desaulniers <ndesaulniers@google.com> Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com> Link: https://lore.kernel.org/r/20220202205557.2260694-1-ndesaulniers@google.com
This commit is contained in:
parent
82880283d7
commit
bfb1a7c91f
|
@ -22,7 +22,7 @@
|
|||
|
||||
#ifdef CONFIG_DEBUG_BUGVERBOSE
|
||||
|
||||
#define _BUG_FLAGS(ins, flags) \
|
||||
#define _BUG_FLAGS(ins, flags, extra) \
|
||||
do { \
|
||||
asm_inline volatile("1:\t" ins "\n" \
|
||||
".pushsection __bug_table,\"aw\"\n" \
|
||||
|
@ -31,7 +31,8 @@ do { \
|
|||
"\t.word %c1" "\t# bug_entry::line\n" \
|
||||
"\t.word %c2" "\t# bug_entry::flags\n" \
|
||||
"\t.org 2b+%c3\n" \
|
||||
".popsection" \
|
||||
".popsection\n" \
|
||||
extra \
|
||||
: : "i" (__FILE__), "i" (__LINE__), \
|
||||
"i" (flags), \
|
||||
"i" (sizeof(struct bug_entry))); \
|
||||
|
@ -39,14 +40,15 @@ do { \
|
|||
|
||||
#else /* !CONFIG_DEBUG_BUGVERBOSE */
|
||||
|
||||
#define _BUG_FLAGS(ins, flags) \
|
||||
#define _BUG_FLAGS(ins, flags, extra) \
|
||||
do { \
|
||||
asm_inline volatile("1:\t" ins "\n" \
|
||||
".pushsection __bug_table,\"aw\"\n" \
|
||||
"2:\t" __BUG_REL(1b) "\t# bug_entry::bug_addr\n" \
|
||||
"\t.word %c0" "\t# bug_entry::flags\n" \
|
||||
"\t.org 2b+%c1\n" \
|
||||
".popsection" \
|
||||
".popsection\n" \
|
||||
extra \
|
||||
: : "i" (flags), \
|
||||
"i" (sizeof(struct bug_entry))); \
|
||||
} while (0)
|
||||
|
@ -55,7 +57,7 @@ do { \
|
|||
|
||||
#else
|
||||
|
||||
#define _BUG_FLAGS(ins, flags) asm volatile(ins)
|
||||
#define _BUG_FLAGS(ins, flags, extra) asm volatile(ins)
|
||||
|
||||
#endif /* CONFIG_GENERIC_BUG */
|
||||
|
||||
|
@ -63,8 +65,8 @@ do { \
|
|||
#define BUG() \
|
||||
do { \
|
||||
instrumentation_begin(); \
|
||||
_BUG_FLAGS(ASM_UD2, 0); \
|
||||
unreachable(); \
|
||||
_BUG_FLAGS(ASM_UD2, 0, ""); \
|
||||
__builtin_unreachable(); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
|
@ -75,9 +77,9 @@ do { \
|
|||
*/
|
||||
#define __WARN_FLAGS(flags) \
|
||||
do { \
|
||||
__auto_type f = BUGFLAG_WARNING|(flags); \
|
||||
instrumentation_begin(); \
|
||||
_BUG_FLAGS(ASM_UD2, BUGFLAG_WARNING|(flags)); \
|
||||
annotate_reachable(); \
|
||||
_BUG_FLAGS(ASM_UD2, f, ASM_REACHABLE); \
|
||||
instrumentation_end(); \
|
||||
} while (0)
|
||||
|
||||
|
|
|
@ -117,14 +117,6 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val,
|
|||
*/
|
||||
#define __stringify_label(n) #n
|
||||
|
||||
#define __annotate_reachable(c) ({ \
|
||||
asm volatile(__stringify_label(c) ":\n\t" \
|
||||
".pushsection .discard.reachable\n\t" \
|
||||
".long " __stringify_label(c) "b - .\n\t" \
|
||||
".popsection\n\t" : : "i" (c)); \
|
||||
})
|
||||
#define annotate_reachable() __annotate_reachable(__COUNTER__)
|
||||
|
||||
#define __annotate_unreachable(c) ({ \
|
||||
asm volatile(__stringify_label(c) ":\n\t" \
|
||||
".pushsection .discard.unreachable\n\t" \
|
||||
|
@ -133,24 +125,21 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val,
|
|||
})
|
||||
#define annotate_unreachable() __annotate_unreachable(__COUNTER__)
|
||||
|
||||
#define ASM_UNREACHABLE \
|
||||
"999:\n\t" \
|
||||
".pushsection .discard.unreachable\n\t" \
|
||||
".long 999b - .\n\t" \
|
||||
#define ASM_REACHABLE \
|
||||
"998:\n\t" \
|
||||
".pushsection .discard.reachable\n\t" \
|
||||
".long 998b - .\n\t" \
|
||||
".popsection\n\t"
|
||||
|
||||
/* Annotate a C jump table to allow objtool to follow the code flow */
|
||||
#define __annotate_jump_table __section(".rodata..c_jump_table")
|
||||
|
||||
#else
|
||||
#define annotate_reachable()
|
||||
#define annotate_unreachable()
|
||||
# define ASM_REACHABLE
|
||||
#define __annotate_jump_table
|
||||
#endif
|
||||
|
||||
#ifndef ASM_UNREACHABLE
|
||||
# define ASM_UNREACHABLE
|
||||
#endif
|
||||
#ifndef unreachable
|
||||
# define unreachable() do { \
|
||||
annotate_unreachable(); \
|
||||
|
|
Loading…
Reference in New Issue