From 764eef4b109ae11e6c987de9c14fc7c482041be0 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Fri, 1 Mar 2019 11:19:03 +0100 Subject: [PATCH] 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) Acked-by: Josh Poimboeuf Cc: Borislav Petkov Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Signed-off-by: Ingo Molnar --- tools/objtool/check.c | 16 ++++++++++------ 1 file 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) { -- 2.39.5