diff options
author | Peter Zijlstra <peterz@infradead.org> | 2019-03-01 11:19:03 +0100 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2019-04-03 11:02:24 +0200 |
commit | 764eef4b109ae11e6c987de9c14fc7c482041be0 (patch) | |
tree | a8fb2c0f135a10ad6b6d4f9478348b6a82199ca3 /tools/objtool | |
parent | 7697eee3ddd768a1fd78c1e687afaa6c5aa5072d (diff) |
objtool: Rewrite alt->skip_orig
Really skip the original instruction flow, instead of letting it
continue with NOPs.
Since the alternative code flow already continues after the original
instructions, only the alt-original is skipped.
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools/objtool')
-rw-r--r-- | tools/objtool/check.c | 16 |
1 files changed, 10 insertions, 6 deletions
diff --git a/tools/objtool/check.c b/tools/objtool/check.c index ccc66af5907f..5264a305d658 100644 --- a/tools/objtool/check.c +++ b/tools/objtool/check.c @@ -31,6 +31,7 @@ struct alternative { struct list_head list; struct instruction *insn; + bool skip_orig; }; const char *objname; @@ -623,9 +624,6 @@ static int add_call_destinations(struct objtool_file *file) * conditionally jumps to the _end_ of the entry. We have to modify these * jumps' destinations to point back to .text rather than the end of the * entry in .altinstr_replacement. - * - * 4. It has been requested that we don't validate the !POPCNT feature path - * which is a "very very small percentage of machines". */ static int handle_group_alt(struct objtool_file *file, struct special_alt *special_alt, @@ -641,9 +639,6 @@ static int handle_group_alt(struct objtool_file *file, if (insn->offset >= special_alt->orig_off + special_alt->orig_len) break; - if (special_alt->skip_orig) - insn->type = INSN_NOP; - insn->alt_group = true; last_orig_insn = insn; } @@ -808,6 +803,7 @@ static int add_special_section_alts(struct objtool_file *file) } alt->insn = new_insn; + alt->skip_orig = special_alt->skip_orig; list_add_tail(&alt->list, &orig_insn->alts); list_del(&special_alt->list); @@ -1883,7 +1879,12 @@ static int validate_branch(struct objtool_file *file, struct instruction *first, insn->visited = true; if (!insn->ignore_alts) { + bool skip_orig = false; + list_for_each_entry(alt, &insn->alts, list) { + if (alt->skip_orig) + skip_orig = true; + ret = validate_branch(file, alt->insn, state); if (ret) { if (backtrace) @@ -1891,6 +1892,9 @@ static int validate_branch(struct objtool_file *file, struct instruction *first, return ret; } } + + if (skip_orig) + return 0; } switch (insn->type) { |