Commit 4ab7674f authored by Josh Poimboeuf's avatar Josh Poimboeuf Committed by Peter Zijlstra

objtool: Make jump label hack optional

Objtool secretly does a jump label hack to overcome the limitations of
the toolchain.  Make the hack explicit (and optional for other arches)
by turning it into a cmdline option and kernel config option.
Signed-off-by: default avatarJosh Poimboeuf <jpoimboe@redhat.com>
Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: default avatarMiroslav Benes <mbenes@suse.cz>
Link: https://lkml.kernel.org/r/3bdcbfdd27ecb01ddec13c04bdf756a583b13d24.1650300597.git.jpoimboe@redhat.com
parent 26e17689
...@@ -46,6 +46,7 @@ config JUMP_LABEL ...@@ -46,6 +46,7 @@ config JUMP_LABEL
bool "Optimize very unlikely/likely branches" bool "Optimize very unlikely/likely branches"
depends on HAVE_ARCH_JUMP_LABEL depends on HAVE_ARCH_JUMP_LABEL
depends on CC_HAS_ASM_GOTO depends on CC_HAS_ASM_GOTO
select OBJTOOL if HAVE_JUMP_LABEL_HACK
help help
This option enables a transparent branch optimization that This option enables a transparent branch optimization that
makes certain almost-always-true or almost-always-false branch makes certain almost-always-true or almost-always-false branch
...@@ -1031,6 +1032,9 @@ config ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT ...@@ -1031,6 +1032,9 @@ config ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT
config HAVE_OBJTOOL config HAVE_OBJTOOL
bool bool
config HAVE_JUMP_LABEL_HACK
bool
config HAVE_STACK_VALIDATION config HAVE_STACK_VALIDATION
bool bool
help help
......
...@@ -212,6 +212,7 @@ config X86 ...@@ -212,6 +212,7 @@ config X86
select HAVE_IOREMAP_PROT select HAVE_IOREMAP_PROT
select HAVE_IRQ_EXIT_ON_IRQ_STACK if X86_64 select HAVE_IRQ_EXIT_ON_IRQ_STACK if X86_64
select HAVE_IRQ_TIME_ACCOUNTING select HAVE_IRQ_TIME_ACCOUNTING
select HAVE_JUMP_LABEL_HACK if HAVE_OBJTOOL
select HAVE_KERNEL_BZIP2 select HAVE_KERNEL_BZIP2
select HAVE_KERNEL_GZIP select HAVE_KERNEL_GZIP
select HAVE_KERNEL_LZ4 select HAVE_KERNEL_LZ4
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
_ASM_PTR "%c0 + %c1 - .\n\t" \ _ASM_PTR "%c0 + %c1 - .\n\t" \
".popsection \n\t" ".popsection \n\t"
#ifdef CONFIG_OBJTOOL #ifdef CONFIG_HAVE_JUMP_LABEL_HACK
static __always_inline bool arch_static_branch(struct static_key *key, bool branch) static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
{ {
...@@ -34,7 +34,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran ...@@ -34,7 +34,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
return true; return true;
} }
#else /* !CONFIG_OBJTOOL */ #else /* !CONFIG_HAVE_JUMP_LABEL_HACK */
static __always_inline bool arch_static_branch(struct static_key * const key, const bool branch) static __always_inline bool arch_static_branch(struct static_key * const key, const bool branch)
{ {
...@@ -48,7 +48,7 @@ static __always_inline bool arch_static_branch(struct static_key * const key, co ...@@ -48,7 +48,7 @@ static __always_inline bool arch_static_branch(struct static_key * const key, co
return true; return true;
} }
#endif /* CONFIG_OBJTOOL */ #endif /* CONFIG_HAVE_JUMP_LABEL_HACK */
static __always_inline bool arch_static_branch_jump(struct static_key * const key, const bool branch) static __always_inline bool arch_static_branch_jump(struct static_key * const key, const bool branch)
{ {
......
...@@ -227,6 +227,7 @@ ifdef CONFIG_OBJTOOL ...@@ -227,6 +227,7 @@ ifdef CONFIG_OBJTOOL
objtool := $(objtree)/tools/objtool/objtool objtool := $(objtree)/tools/objtool/objtool
objtool_args = \ objtool_args = \
$(if $(CONFIG_HAVE_JUMP_LABEL_HACK), --hacks=jump_label) \
$(if $(CONFIG_X86_KERNEL_IBT), --lto --ibt) \ $(if $(CONFIG_X86_KERNEL_IBT), --lto --ibt) \
$(if $(CONFIG_FTRACE_MCOUNT_USE_OBJTOOL), --mcount) \ $(if $(CONFIG_FTRACE_MCOUNT_USE_OBJTOOL), --mcount) \
$(if $(CONFIG_UNWINDER_ORC), --orc) \ $(if $(CONFIG_UNWINDER_ORC), --orc) \
......
...@@ -117,6 +117,10 @@ objtool_link() ...@@ -117,6 +117,10 @@ objtool_link()
# Don't perform vmlinux validation unless explicitly requested, # Don't perform vmlinux validation unless explicitly requested,
# but run objtool on vmlinux.o now that we have an object file. # but run objtool on vmlinux.o now that we have an object file.
if is_enabled CONFIG_HAVE_JUMP_LABEL_HACK; then
objtoolopt="${objtoolopt} --hacks=jump_label"
fi
if is_enabled CONFIG_X86_KERNEL_IBT; then if is_enabled CONFIG_X86_KERNEL_IBT; then
objtoolopt="${objtoolopt} --ibt" objtoolopt="${objtoolopt} --ibt"
fi fi
......
...@@ -31,8 +31,28 @@ static int parse_dump(const struct option *opt, const char *str, int unset) ...@@ -31,8 +31,28 @@ static int parse_dump(const struct option *opt, const char *str, int unset)
return -1; return -1;
} }
static int parse_hacks(const struct option *opt, const char *str, int unset)
{
bool found = false;
/*
* Use strstr() as a lazy method of checking for comma-separated
* options.
*
* No string provided == enable all options.
*/
if (!str || strstr(str, "jump_label")) {
opts.hack_jump_label = true;
found = true;
}
return found ? 0 : -1;
}
const struct option check_options[] = { const struct option check_options[] = {
OPT_GROUP("Actions:"), OPT_GROUP("Actions:"),
OPT_CALLBACK_OPTARG('h', "hacks", NULL, NULL, "jump_label", "patch toolchain bugs/limitations", parse_hacks),
OPT_BOOLEAN('i', "ibt", &opts.ibt, "validate and annotate IBT"), OPT_BOOLEAN('i', "ibt", &opts.ibt, "validate and annotate IBT"),
OPT_BOOLEAN('m', "mcount", &opts.mcount, "annotate mcount/fentry calls for ftrace"), OPT_BOOLEAN('m', "mcount", &opts.mcount, "annotate mcount/fentry calls for ftrace"),
OPT_BOOLEAN('n', "noinstr", &opts.noinstr, "validate noinstr rules"), OPT_BOOLEAN('n', "noinstr", &opts.noinstr, "validate noinstr rules"),
...@@ -87,14 +107,15 @@ int cmd_parse_options(int argc, const char **argv, const char * const usage[]) ...@@ -87,14 +107,15 @@ int cmd_parse_options(int argc, const char **argv, const char * const usage[])
static bool opts_valid(void) static bool opts_valid(void)
{ {
if (opts.ibt || if (opts.hack_jump_label ||
opts.mcount || opts.ibt ||
opts.noinstr || opts.mcount ||
opts.orc || opts.noinstr ||
opts.retpoline || opts.orc ||
opts.sls || opts.retpoline ||
opts.stackval || opts.sls ||
opts.static_call || opts.stackval ||
opts.static_call ||
opts.uaccess) { opts.uaccess) {
if (opts.dump_orc) { if (opts.dump_orc) {
fprintf(stderr, "--dump can't be combined with other options\n"); fprintf(stderr, "--dump can't be combined with other options\n");
......
...@@ -1592,7 +1592,7 @@ static int handle_jump_alt(struct objtool_file *file, ...@@ -1592,7 +1592,7 @@ static int handle_jump_alt(struct objtool_file *file,
return -1; return -1;
} }
if (special_alt->key_addend & 2) { if (opts.hack_jump_label && special_alt->key_addend & 2) {
struct reloc *reloc = insn_reloc(file, orig_insn); struct reloc *reloc = insn_reloc(file, orig_insn);
if (reloc) { if (reloc) {
......
...@@ -12,6 +12,7 @@ extern const struct option check_options[]; ...@@ -12,6 +12,7 @@ extern const struct option check_options[];
struct opts { struct opts {
/* actions: */ /* actions: */
bool dump_orc; bool dump_orc;
bool hack_jump_label;
bool ibt; bool ibt;
bool mcount; bool mcount;
bool noinstr; bool noinstr;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment