From: Peter Zijlstra <peterz@infradead.org>
To: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: tglx@linutronix.de, linux-kernel@vger.kernel.org, x86@kernel.org,
mhiramat@kernel.org, mbenes@suse.cz
Subject: Re: [PATCH v4 01/13] objtool: Remove CFI save/restore special case
Date: Thu, 26 Mar 2020 20:57:18 +0100 [thread overview]
Message-ID: <20200326195718.GD2452@worktop.programming.kicks-ass.net> (raw)
In-Reply-To: <20200326154938.GO20713@hirez.programming.kicks-ass.net>
On Thu, Mar 26, 2020 at 04:49:38PM +0100, Peter Zijlstra wrote:
> > The 'insn == first' check isn't ideal, but at least it works (I think?).
>
> It works, yes, for exactly this one case.
How's this? Ignore the ignore_cfi bits, that's a 'failed' experiment.
---
arch/x86/include/asm/orc_types.h | 2 +
arch/x86/include/asm/processor.h | 6 +-
arch/x86/include/asm/unwind_hints.h | 4 ++
tools/arch/x86/include/asm/orc_types.h | 2 +
tools/objtool/check.c | 109 +++++++++++++++++++--------------
tools/objtool/check.h | 3 +-
6 files changed, 75 insertions(+), 51 deletions(-)
diff --git a/arch/x86/include/asm/orc_types.h b/arch/x86/include/asm/orc_types.h
index 6e060907c163..82b5c685341a 100644
--- a/arch/x86/include/asm/orc_types.h
+++ b/arch/x86/include/asm/orc_types.h
@@ -60,6 +60,8 @@
#define ORC_TYPE_REGS_IRET 2
#define UNWIND_HINT_TYPE_SAVE 3
#define UNWIND_HINT_TYPE_RESTORE 4
+#define UNWIND_HINT_TYPE_IGNORE 5
+#define UNWIND_HINT_TYPE_IRET_CONT 6
#ifndef __ASSEMBLY__
/*
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index 94789db550df..45c74cbc0a83 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -728,8 +728,8 @@ static inline void sync_core(void)
unsigned int tmp;
asm volatile (
- UNWIND_HINT_SAVE
"mov %%ss, %0\n\t"
+ UNWIND_HINT_SAVE
"pushq %q0\n\t"
"pushq %%rsp\n\t"
"addq $8, (%%rsp)\n\t"
@@ -737,9 +737,9 @@ static inline void sync_core(void)
"mov %%cs, %0\n\t"
"pushq %q0\n\t"
"pushq $1f\n\t"
+ UNWIND_HINT_IRET_CONT
"iretq\n\t"
- UNWIND_HINT_RESTORE
- "1:"
+ "1:\n\t"
: "=&r" (tmp), ASM_CALL_CONSTRAINT : : "cc", "memory");
#endif
}
diff --git a/arch/x86/include/asm/unwind_hints.h b/arch/x86/include/asm/unwind_hints.h
index f5e2eb12cb71..d8a07749c323 100644
--- a/arch/x86/include/asm/unwind_hints.h
+++ b/arch/x86/include/asm/unwind_hints.h
@@ -112,6 +112,10 @@
#define UNWIND_HINT_RESTORE UNWIND_HINT(0, 0, UNWIND_HINT_TYPE_RESTORE, 0)
+#define UNWIND_HINT_IGNORE UNWIND_HINT(0, 0, UNWIND_HINT_TYPE_IGNORE, 0)
+
+#define UNWIND_HINT_IRET_CONT UNWIND_HINT(0, 0, UNWIND_HINT_TYPE_IRET_CONT, 0)
+
#endif /* __ASSEMBLY__ */
#endif /* _ASM_X86_UNWIND_HINTS_H */
diff --git a/tools/arch/x86/include/asm/orc_types.h b/tools/arch/x86/include/asm/orc_types.h
index 6e060907c163..82b5c685341a 100644
--- a/tools/arch/x86/include/asm/orc_types.h
+++ b/tools/arch/x86/include/asm/orc_types.h
@@ -60,6 +60,8 @@
#define ORC_TYPE_REGS_IRET 2
#define UNWIND_HINT_TYPE_SAVE 3
#define UNWIND_HINT_TYPE_RESTORE 4
+#define UNWIND_HINT_TYPE_IGNORE 5
+#define UNWIND_HINT_TYPE_IRET_CONT 6
#ifndef __ASSEMBLY__
/*
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index e637a4a38d2a..03bac6cb313c 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -1259,14 +1259,25 @@ static int read_unwind_hints(struct objtool_file *file)
cfa = &insn->state.cfa;
- if (hint->type == UNWIND_HINT_TYPE_SAVE) {
+ switch (hint->type) {
+ case UNWIND_HINT_TYPE_SAVE:
insn->save = true;
continue;
- } else if (hint->type == UNWIND_HINT_TYPE_RESTORE) {
+ case UNWIND_HINT_TYPE_RESTORE:
insn->restore = true;
- insn->hint = true;
continue;
+
+ case UNWIND_HINT_TYPE_IGNORE:
+ insn->ignore_cfi = true;
+ continue;
+
+ case UNWIND_HINT_TYPE_IRET_CONT:
+ insn->iret_cont = true;
+ continue;
+
+ default:
+ break;
}
insn->hint = true;
@@ -1558,6 +1569,9 @@ static int update_insn_state(struct instruction *insn, struct insn_state *state)
struct cfi_reg *cfa = &state->cfa;
struct cfi_reg *regs = state->regs;
+ if (insn->ignore_cfi)
+ return 0;
+
/* stack operations don't make sense with an undefined CFA */
if (cfa->base == CFI_UNDEFINED) {
if (insn->func) {
@@ -1993,6 +2007,37 @@ static int validate_sibling_call(struct instruction *insn, struct insn_state *st
return validate_call(insn, state);
}
+static int insn_hint_restore(struct objtool_file *file, struct section *sec,
+ struct symbol *func, struct instruction *insn,
+ struct insn_state *state)
+{
+ struct instruction *save_insn, *i;
+
+ i = insn;
+ save_insn = NULL;
+ func_for_each_insn_continue_reverse(file, func, i) {
+ if (i->save) {
+ save_insn = i;
+ break;
+ }
+ }
+
+ if (!save_insn) {
+ WARN_FUNC("no corresponding CFI save for CFI restore",
+ sec, insn->offset);
+ return 1;
+ }
+
+ if (!save_insn->visited) {
+ WARN_FUNC("objtool isn't smart enough to handle this CFI save/restore combo",
+ sec, insn->offset);
+ return 1;
+ }
+
+ *state = save_insn->state;
+ return 0;
+}
+
/*
* Follow the branch starting at the given instruction, and recursively follow
* any other branches (jumps). Meanwhile, track the frame pointer state at
@@ -2000,15 +2045,14 @@ static int validate_sibling_call(struct instruction *insn, struct insn_state *st
* tools/objtool/Documentation/stack-validation.txt.
*/
static int validate_branch(struct objtool_file *file, struct symbol *func,
- struct instruction *first, struct insn_state state)
+ struct instruction *insn, struct insn_state state)
{
+ struct instruction *next_insn;
struct alternative *alt;
- struct instruction *insn, *next_insn;
struct section *sec;
u8 visited;
int ret;
- insn = first;
sec = insn->sec;
if (insn->alt_group && list_empty(&insn->alts)) {
@@ -2034,7 +2078,7 @@ static int validate_branch(struct objtool_file *file, struct symbol *func,
visited = 1 << state.uaccess;
if (insn->visited) {
- if (!insn->hint && !insn_state_match(insn, &state))
+ if ((!insn->hint && !insn->restore) && !insn_state_match(insn, &state))
return 1;
if (insn->visited & visited)
@@ -2042,47 +2086,12 @@ static int validate_branch(struct objtool_file *file, struct symbol *func,
}
if (insn->hint) {
- if (insn->restore) {
- struct instruction *save_insn, *i;
-
- i = insn;
- save_insn = NULL;
- func_for_each_insn_continue_reverse(file, func, i) {
- if (i->save) {
- save_insn = i;
- break;
- }
- }
-
- if (!save_insn) {
- WARN_FUNC("no corresponding CFI save for CFI restore",
- sec, insn->offset);
- return 1;
- }
-
- if (!save_insn->visited) {
- /*
- * Oops, no state to copy yet.
- * Hopefully we can reach this
- * instruction from another branch
- * after the save insn has been
- * visited.
- */
- if (insn == first)
- return 0;
-
- WARN_FUNC("objtool isn't smart enough to handle this CFI save/restore combo",
- sec, insn->offset);
- return 1;
- }
-
- insn->state = save_insn->state;
- }
-
state = insn->state;
-
- } else
+ } else {
+ if (insn->restore)
+ insn_hint_restore(file, sec, func, insn, &state);
insn->state = state;
+ }
insn->visited |= visited;
@@ -2191,11 +2200,17 @@ static int validate_branch(struct objtool_file *file, struct symbol *func,
break;
case INSN_CONTEXT_SWITCH:
- if (func && (!next_insn || !next_insn->hint)) {
+ if (insn->iret_cont) {
+ insn_hint_restore(file, sec, func, insn, &state);
+ break;
+ }
+
+ if (func) {
WARN_FUNC("unsupported instruction in callable function",
sec, insn->offset);
return 1;
}
+
return 0;
case INSN_STACK:
diff --git a/tools/objtool/check.h b/tools/objtool/check.h
index 6d875ca6fce0..f2b6172e119b 100644
--- a/tools/objtool/check.h
+++ b/tools/objtool/check.h
@@ -33,7 +33,8 @@ struct instruction {
unsigned int len;
enum insn_type type;
unsigned long immediate;
- bool alt_group, dead_end, ignore, hint, save, restore, ignore_alts;
+ bool alt_group, dead_end, ignore, ignore_alts;
+ bool hint, save, restore, ignore_cfi, iret_cont;
bool retpoline_safe;
u8 visited;
struct symbol *call_dest;
next prev parent reply other threads:[~2020-03-26 19:57 UTC|newest]
Thread overview: 63+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-03-25 17:45 [PATCH v4 00/13] objtool: vmlinux.o and moinstr validation Peter Zijlstra
2020-03-25 17:45 ` [PATCH v4 01/13] objtool: Remove CFI save/restore special case Peter Zijlstra
2020-03-26 11:30 ` Peter Zijlstra
2020-03-26 12:58 ` Peter Zijlstra
2020-03-26 13:44 ` Josh Poimboeuf
2020-03-26 15:38 ` Peter Zijlstra
2020-03-27 4:19 ` Josh Poimboeuf
2020-03-26 14:44 ` Miroslav Benes
2020-03-26 15:04 ` Miroslav Benes
2020-03-26 13:00 ` Peter Zijlstra
2020-03-26 13:56 ` Josh Poimboeuf
2020-03-26 15:49 ` Peter Zijlstra
2020-03-26 19:57 ` Peter Zijlstra [this message]
2020-03-27 1:00 ` Josh Poimboeuf
2020-03-30 17:02 ` Peter Zijlstra
2020-03-30 19:02 ` Josh Poimboeuf
2020-03-30 20:02 ` Peter Zijlstra
2020-03-30 20:29 ` Peter Zijlstra
2020-03-31 11:16 ` [RFC][PATCH] objtool,ftrace: Implement UNWIND_HINT_RET_OFFSET Peter Zijlstra
2020-03-31 15:31 ` Steven Rostedt
2020-03-31 16:06 ` [RFC][PATCH] x86,ftrace: Shrink ftrace_regs_caller() by one byte Peter Zijlstra
2020-03-31 19:58 ` [RFC][PATCH] objtool,ftrace: Implement UNWIND_HINT_RET_OFFSET Peter Zijlstra
2020-03-31 20:26 ` Josh Poimboeuf
2020-03-31 20:23 ` Josh Poimboeuf
2020-03-31 20:40 ` Peter Zijlstra
2020-03-31 21:07 ` Peter Zijlstra
2020-03-31 21:17 ` Josh Poimboeuf
2020-03-31 21:20 ` Josh Poimboeuf
2020-03-31 22:27 ` [PATCH v2] " Peter Zijlstra
2020-04-01 14:14 ` Josh Poimboeuf
2020-04-01 14:22 ` Peter Zijlstra
2020-04-01 14:39 ` Josh Poimboeuf
2020-04-01 15:38 ` Peter Zijlstra
2020-04-01 15:39 ` Steven Rostedt
2020-04-01 15:43 ` Julien Thierry
2020-04-01 17:09 ` Peter Zijlstra
2020-04-01 17:33 ` Steven Rostedt
2020-04-01 17:45 ` Peter Zijlstra
2020-04-01 18:20 ` Steven Rostedt
2020-04-01 20:20 ` Peter Zijlstra
2020-04-01 17:37 ` Josh Poimboeuf
2020-04-02 6:41 ` Julien Thierry
2020-04-02 6:56 ` Julien Thierry
2020-04-02 7:50 ` Peter Zijlstra
2020-04-02 8:16 ` Julien Thierry
2020-04-02 8:17 ` Peter Zijlstra
2020-04-02 8:29 ` Julien Thierry
2020-04-02 8:58 ` Miroslav Benes
2020-03-25 17:45 ` [PATCH v4 02/13] objtool: Factor out CFI hints Peter Zijlstra
2020-03-25 18:26 ` Miroslav Benes
2020-03-25 19:41 ` Peter Zijlstra
2020-03-25 17:45 ` [PATCH v4 03/13] objtool: Rename struct cfi_state Peter Zijlstra
2020-03-25 17:45 ` [PATCH v4 04/13] objtool: Fix !CFI insn_state propagation Peter Zijlstra
2020-03-25 17:45 ` [PATCH v4 05/13] objtool: Implement noinstr validation Peter Zijlstra
2020-03-25 17:45 ` [PATCH v4 06/13] objtool: Optimize !vmlinux.o again Peter Zijlstra
2020-03-25 17:45 ` [PATCH v4 07/13] objtool: Use sec_offset_hash() for insn_hash Peter Zijlstra
2020-03-25 17:45 ` [PATCH v4 08/13] objtool: Detect loading function pointers across noinstr Peter Zijlstra
2020-03-25 17:45 ` [PATCH v4 09/13] kbuild/objtool: Add objtool-vmlinux.o pass Peter Zijlstra
2020-03-25 17:45 ` [PATCH v4 10/13] objtool: Avoid iterating !text section symbols Peter Zijlstra
2020-03-25 17:45 ` [PATCH v4 11/13] objtool: Rearrange validate_section() Peter Zijlstra
2020-03-25 17:45 ` [PATCH v4 12/13] objtool: Add STT_NOTYPE noinstr validation Peter Zijlstra
2020-03-25 17:45 ` [PATCH v4 13/13] objtool: Also consider .entry.text as noinstr Peter Zijlstra
2020-03-25 19:03 ` [PATCH v4 00/13] objtool: vmlinux.o and moinstr validation Miroslav Benes
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200326195718.GD2452@worktop.programming.kicks-ass.net \
--to=peterz@infradead.org \
--cc=jpoimboe@redhat.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mbenes@suse.cz \
--cc=mhiramat@kernel.org \
--cc=tglx@linutronix.de \
--cc=x86@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.