* [PATCH 00/11] x86/kvm/emulate: Avoid RET for FASTOPs
@ 2023-12-04 9:37 Peter Zijlstra
2023-12-04 9:37 ` [PATCH 01/11] objtool: Generic annotation infrastructure Peter Zijlstra
` (10 more replies)
0 siblings, 11 replies; 20+ messages in thread
From: Peter Zijlstra @ 2023-12-04 9:37 UTC (permalink / raw)
To: Sean Christopherson, Paolo Bonzini, Josh Poimboeuf,
Thomas Gleixner
Cc: linux-kernel, peterz, x86, kvm
Hi!
Because I needed a new objtool annotation, and I'd promised Josh I'd clean all
that up a while ago, now with a healy sprinking of objtool patches...
Anyway... FASTOP is special in that it relies on RET to preserve FLAGS, while
normal C calling convention does not. This has been a problem before, see
ba5ca5e5e6a1 ("x86/retpoline: Don't clobber RFLAGS during srso_safe_ret()") but
is also a problem for call depth tracking.
Fixing the call-depth tracking return thunk would be significantly harder (and
more expensive), so instead change fastops to not use return.
There are two separate instances, test_cc() and fastop(). The first is
basically a SETCC wrapper, which seems like a very complicated (and somewhat
expensive) way to read FLAGS. Instead use the code we already have to emulate
JCC to fully emulate the instruction.
That then leaves fastop(), which when marked noinline is guaranteed to exist
only once. As such, CALL+RET isn't needed, because we'll always be RETurning to
the same location, as such replace with JMP+JMP.
---
arch/x86/include/asm/alternative.h | 14 +-
arch/x86/include/asm/nospec-branch.h | 45 ++++--
arch/x86/include/asm/text-patching.h | 20 ++-
arch/x86/kvm/emulate.c | 54 +++----
include/linux/instrumentation.h | 11 +-
include/linux/objtool.h | 62 +++++----
include/linux/objtool_types.h | 12 ++
tools/include/linux/objtool_types.h | 12 ++
tools/objtool/check.c | 263 +++++++++++------------------------
9 files changed, 208 insertions(+), 285 deletions(-)
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 01/11] objtool: Generic annotation infrastructure
2023-12-04 9:37 [PATCH 00/11] x86/kvm/emulate: Avoid RET for FASTOPs Peter Zijlstra
@ 2023-12-04 9:37 ` Peter Zijlstra
2024-11-08 14:16 ` Peter Zijlstra
2023-12-04 9:37 ` [PATCH 02/11] objtool: Convert ANNOTATE_NOENDBR to ANNOTATE Peter Zijlstra
` (9 subsequent siblings)
10 siblings, 1 reply; 20+ messages in thread
From: Peter Zijlstra @ 2023-12-04 9:37 UTC (permalink / raw)
To: Sean Christopherson, Paolo Bonzini, Josh Poimboeuf,
Thomas Gleixner
Cc: linux-kernel, peterz, x86, kvm
Avoid endless .discard.foo sections for each annotation, create a
single .discard.annotate section that takes an annotation type along
with the instruction.
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
---
--- a/include/linux/objtool.h
+++ b/include/linux/objtool.h
@@ -57,6 +57,13 @@
".long 998b\n\t" \
".popsection\n\t"
+#define ASM_ANNOTATE(x) \
+ "911:\n\t" \
+ ".pushsection .discard.annotate,\"M\",@progbits,8\n\t" \
+ ".long 911b - .\n\t" \
+ ".long " __stringify(x) "\n\t" \
+ ".popsection\n\t"
+
#else /* __ASSEMBLY__ */
/*
@@ -146,6 +153,14 @@
.popsection
.endm
+.macro ANNOTATE type:req
+.Lhere_\@:
+ .pushsection .discard.annotate,"M",@progbits,8
+ .long .Lhere_\@ - .
+ .long \type
+ .popsection
+.endm
+
#endif /* __ASSEMBLY__ */
#else /* !CONFIG_OBJTOOL */
@@ -167,6 +182,8 @@
.endm
.macro REACHABLE
.endm
+.macro ANNOTATE
+.endm
#endif
#endif /* CONFIG_OBJTOOL */
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -2308,6 +2308,41 @@ static int read_unwind_hints(struct objt
return 0;
}
+static int read_annotate(struct objtool_file *file, void (*func)(int type, struct instruction *insn))
+{
+ struct section *rsec, *sec;
+ struct instruction *insn;
+ struct reloc *reloc;
+ int type;
+
+ rsec = find_section_by_name(file->elf, ".rela.discard.annotate");
+ if (!rsec)
+ return 0;
+
+ sec = find_section_by_name(file->elf, ".discard.annotate");
+ if (!sec)
+ return 0;
+
+ for_each_reloc(rsec, reloc) {
+ insn = find_insn(file, reloc->sym->sec,
+ reloc->sym->offset + reloc_addend(reloc));
+ if (!insn) {
+ WARN("bad .discard.annotate entry: %d", reloc_idx(reloc));
+ return -1;
+ }
+
+ type = *(u32 *)(sec->data->d_buf + (reloc_idx(reloc) * sec->sh.sh_entsize) + 4);
+
+ func(type, insn);
+ }
+
+ return 0;
+}
+
+static void __annotate_nop(int type, struct instruction *insn)
+{
+}
+
static int read_noendbr_hints(struct objtool_file *file)
{
struct instruction *insn;
@@ -2602,6 +2637,8 @@ static int decode_sections(struct objtoo
if (ret)
return ret;
+ ret = read_annotate(file, __annotate_nop);
+
/*
* Must be before read_unwind_hints() since that needs insn->noendbr.
*/
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 02/11] objtool: Convert ANNOTATE_NOENDBR to ANNOTATE
2023-12-04 9:37 [PATCH 00/11] x86/kvm/emulate: Avoid RET for FASTOPs Peter Zijlstra
2023-12-04 9:37 ` [PATCH 01/11] objtool: Generic annotation infrastructure Peter Zijlstra
@ 2023-12-04 9:37 ` Peter Zijlstra
2023-12-04 9:37 ` [PATCH 03/11] objtool: Convert ANNOTATE_RETPOLINE_SAFE " Peter Zijlstra
` (8 subsequent siblings)
10 siblings, 0 replies; 20+ messages in thread
From: Peter Zijlstra @ 2023-12-04 9:37 UTC (permalink / raw)
To: Sean Christopherson, Paolo Bonzini, Josh Poimboeuf,
Thomas Gleixner
Cc: linux-kernel, peterz, x86, kvm
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
---
include/linux/objtool.h | 17 ++++-------------
include/linux/objtool_types.h | 5 +++++
tools/include/linux/objtool_types.h | 5 +++++
tools/objtool/check.c | 32 +++++---------------------------
4 files changed, 19 insertions(+), 40 deletions(-)
--- a/include/linux/objtool.h
+++ b/include/linux/objtool.h
@@ -45,12 +45,6 @@
#define STACK_FRAME_NON_STANDARD_FP(func)
#endif
-#define ANNOTATE_NOENDBR \
- "986: \n\t" \
- ".pushsection .discard.noendbr\n\t" \
- ".long 986b\n\t" \
- ".popsection\n\t"
-
#define ASM_REACHABLE \
"998:\n\t" \
".pushsection .discard.reachable\n\t" \
@@ -64,6 +58,8 @@
".long " __stringify(x) "\n\t" \
".popsection\n\t"
+#define ANNOTATE_NOENDBR ASM_ANNOTATE(ANNOTYPE_NOENDBR)
+
#else /* __ASSEMBLY__ */
/*
@@ -122,13 +118,6 @@
#endif
.endm
-.macro ANNOTATE_NOENDBR
-.Lhere_\@:
- .pushsection .discard.noendbr
- .long .Lhere_\@
- .popsection
-.endm
-
/*
* Use objtool to validate the entry requirement that all code paths do
* VALIDATE_UNRET_END before RET.
@@ -161,6 +150,8 @@
.popsection
.endm
+#define ANNOTATE_NOENDBR ANNOTATE type=ANNOTYPE_NOENDBR
+
#endif /* __ASSEMBLY__ */
#else /* !CONFIG_OBJTOOL */
--- a/include/linux/objtool_types.h
+++ b/include/linux/objtool_types.h
@@ -54,4 +54,9 @@ struct unwind_hint {
#define UNWIND_HINT_TYPE_SAVE 6
#define UNWIND_HINT_TYPE_RESTORE 7
+/*
+ * Annotate types
+ */
+#define ANNOTYPE_NOENDBR 1
+
#endif /* _LINUX_OBJTOOL_TYPES_H */
--- a/tools/include/linux/objtool_types.h
+++ b/tools/include/linux/objtool_types.h
@@ -54,4 +54,9 @@ struct unwind_hint {
#define UNWIND_HINT_TYPE_SAVE 6
#define UNWIND_HINT_TYPE_RESTORE 7
+/*
+ * Annotate types
+ */
+#define ANNOTYPE_NOENDBR 1
+
#endif /* _LINUX_OBJTOOL_TYPES_H */
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -2339,32 +2339,12 @@ static int read_annotate(struct objtool_
return 0;
}
-static void __annotate_nop(int type, struct instruction *insn)
+static void __annotate_noendbr(int type, struct instruction *insn)
{
-}
-
-static int read_noendbr_hints(struct objtool_file *file)
-{
- struct instruction *insn;
- struct section *rsec;
- struct reloc *reloc;
-
- rsec = find_section_by_name(file->elf, ".rela.discard.noendbr");
- if (!rsec)
- return 0;
+ if (type != ANNOTYPE_NOENDBR)
+ return;
- for_each_reloc(rsec, reloc) {
- insn = find_insn(file, reloc->sym->sec,
- reloc->sym->offset + reloc_addend(reloc));
- if (!insn) {
- WARN("bad .discard.noendbr entry");
- return -1;
- }
-
- insn->noendbr = 1;
- }
-
- return 0;
+ insn->noendbr = 1;
}
static int read_retpoline_hints(struct objtool_file *file)
@@ -2637,12 +2617,10 @@ static int decode_sections(struct objtoo
if (ret)
return ret;
- ret = read_annotate(file, __annotate_nop);
-
/*
* Must be before read_unwind_hints() since that needs insn->noendbr.
*/
- ret = read_noendbr_hints(file);
+ ret = read_annotate(file, __annotate_noendbr);
if (ret)
return ret;
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 03/11] objtool: Convert ANNOTATE_RETPOLINE_SAFE to ANNOTATE
2023-12-04 9:37 [PATCH 00/11] x86/kvm/emulate: Avoid RET for FASTOPs Peter Zijlstra
2023-12-04 9:37 ` [PATCH 01/11] objtool: Generic annotation infrastructure Peter Zijlstra
2023-12-04 9:37 ` [PATCH 02/11] objtool: Convert ANNOTATE_NOENDBR to ANNOTATE Peter Zijlstra
@ 2023-12-04 9:37 ` Peter Zijlstra
2023-12-06 23:31 ` Sean Christopherson
2023-12-04 9:37 ` [PATCH 04/11] objtool: Convert instrumentation_{begin,end}() " Peter Zijlstra
` (7 subsequent siblings)
10 siblings, 1 reply; 20+ messages in thread
From: Peter Zijlstra @ 2023-12-04 9:37 UTC (permalink / raw)
To: Sean Christopherson, Paolo Bonzini, Josh Poimboeuf,
Thomas Gleixner
Cc: linux-kernel, peterz, x86, kvm
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
---
arch/x86/include/asm/nospec-branch.h | 13 +-------
include/linux/objtool_types.h | 1
tools/include/linux/objtool_types.h | 1
tools/objtool/check.c | 52 ++++++++++++-----------------------
4 files changed, 22 insertions(+), 45 deletions(-)
--- a/arch/x86/include/asm/nospec-branch.h
+++ b/arch/x86/include/asm/nospec-branch.h
@@ -193,12 +193,7 @@
* objtool the subsequent indirect jump/call is vouched safe for retpoline
* builds.
*/
-.macro ANNOTATE_RETPOLINE_SAFE
-.Lhere_\@:
- .pushsection .discard.retpoline_safe
- .long .Lhere_\@
- .popsection
-.endm
+#define ANNOTATE_RETPOLINE_SAFE ANNOTATE type=ANNOTYPE_RETPOLINE_SAFE
/*
* (ab)use RETPOLINE_SAFE on RET to annotate away 'bare' RET instructions
@@ -317,11 +312,7 @@
#else /* __ASSEMBLY__ */
-#define ANNOTATE_RETPOLINE_SAFE \
- "999:\n\t" \
- ".pushsection .discard.retpoline_safe\n\t" \
- ".long 999b\n\t" \
- ".popsection\n\t"
+#define ANNOTATE_RETPOLINE_SAFE ASM_ANNOTATE(ANNOTYPE_RETPOLINE_SAFE)
typedef u8 retpoline_thunk_t[RETPOLINE_THUNK_SIZE];
extern retpoline_thunk_t __x86_indirect_thunk_array[];
--- a/include/linux/objtool_types.h
+++ b/include/linux/objtool_types.h
@@ -58,5 +58,6 @@ struct unwind_hint {
* Annotate types
*/
#define ANNOTYPE_NOENDBR 1
+#define ANNOTYPE_RETPOLINE_SAFE 2
#endif /* _LINUX_OBJTOOL_TYPES_H */
--- a/tools/include/linux/objtool_types.h
+++ b/tools/include/linux/objtool_types.h
@@ -58,5 +58,6 @@ struct unwind_hint {
* Annotate types
*/
#define ANNOTYPE_NOENDBR 1
+#define ANNOTYPE_RETPOLINE_SAFE 2
#endif /* _LINUX_OBJTOOL_TYPES_H */
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -2308,12 +2308,12 @@ static int read_unwind_hints(struct objt
return 0;
}
-static int read_annotate(struct objtool_file *file, void (*func)(int type, struct instruction *insn))
+static int read_annotate(struct objtool_file *file, int (*func)(int type, struct instruction *insn))
{
struct section *rsec, *sec;
struct instruction *insn;
struct reloc *reloc;
- int type;
+ int type, ret;
rsec = find_section_by_name(file->elf, ".rela.discard.annotate");
if (!rsec)
@@ -2333,53 +2333,37 @@ static int read_annotate(struct objtool_
type = *(u32 *)(sec->data->d_buf + (reloc_idx(reloc) * sec->sh.sh_entsize) + 4);
- func(type, insn);
+ ret = func(type, insn);
+ if (ret < 0)
+ return ret;
}
return 0;
}
-static void __annotate_noendbr(int type, struct instruction *insn)
+static int __annotate_noendbr(int type, struct instruction *insn)
{
if (type != ANNOTYPE_NOENDBR)
- return;
+ return 0;
insn->noendbr = 1;
+ return 0;
}
-static int read_retpoline_hints(struct objtool_file *file)
+static int __annotate_retpoline_safe(int type, struct instruction *insn)
{
- struct section *rsec;
- struct instruction *insn;
- struct reloc *reloc;
-
- rsec = find_section_by_name(file->elf, ".rela.discard.retpoline_safe");
- if (!rsec)
+ if (type != ANNOTYPE_RETPOLINE_SAFE)
return 0;
- for_each_reloc(rsec, reloc) {
- if (reloc->sym->type != STT_SECTION) {
- WARN("unexpected relocation symbol type in %s", rsec->name);
- return -1;
- }
-
- insn = find_insn(file, reloc->sym->sec, reloc_addend(reloc));
- if (!insn) {
- WARN("bad .discard.retpoline_safe entry");
- return -1;
- }
-
- if (insn->type != INSN_JUMP_DYNAMIC &&
- insn->type != INSN_CALL_DYNAMIC &&
- insn->type != INSN_RETURN &&
- insn->type != INSN_NOP) {
- WARN_INSN(insn, "retpoline_safe hint not an indirect jump/call/ret/nop");
- return -1;
- }
-
- insn->retpoline_safe = true;
+ if (insn->type != INSN_JUMP_DYNAMIC &&
+ insn->type != INSN_CALL_DYNAMIC &&
+ insn->type != INSN_RETURN &&
+ insn->type != INSN_NOP) {
+ WARN_INSN(insn, "retpoline_safe hint not an indirect jump/call/ret/nop");
+ return -1;
}
+ insn->retpoline_safe = true;
return 0;
}
@@ -2666,7 +2650,7 @@ static int decode_sections(struct objtoo
if (ret)
return ret;
- ret = read_retpoline_hints(file);
+ ret = read_annotate(file, __annotate_retpoline_safe);
if (ret)
return ret;
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 04/11] objtool: Convert instrumentation_{begin,end}() to ANNOTATE
2023-12-04 9:37 [PATCH 00/11] x86/kvm/emulate: Avoid RET for FASTOPs Peter Zijlstra
` (2 preceding siblings ...)
2023-12-04 9:37 ` [PATCH 03/11] objtool: Convert ANNOTATE_RETPOLINE_SAFE " Peter Zijlstra
@ 2023-12-04 9:37 ` Peter Zijlstra
2023-12-04 9:37 ` [PATCH 05/11] objtool: Convert VALIDATE_UNRET_BEGIN " Peter Zijlstra
` (6 subsequent siblings)
10 siblings, 0 replies; 20+ messages in thread
From: Peter Zijlstra @ 2023-12-04 9:37 UTC (permalink / raw)
To: Sean Christopherson, Paolo Bonzini, Josh Poimboeuf,
Thomas Gleixner
Cc: linux-kernel, peterz, x86, kvm
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
---
include/linux/instrumentation.h | 11 +++-----
include/linux/objtool.h | 9 ++++--
include/linux/objtool_types.h | 2 +
tools/include/linux/objtool_types.h | 2 +
tools/objtool/check.c | 49 +++++++-----------------------------
5 files changed, 25 insertions(+), 48 deletions(-)
--- a/include/linux/instrumentation.h
+++ b/include/linux/instrumentation.h
@@ -4,14 +4,14 @@
#ifdef CONFIG_NOINSTR_VALIDATION
+#include <linux/objtool.h>
#include <linux/stringify.h>
/* Begin/end of an instrumentation safe region */
#define __instrumentation_begin(c) ({ \
asm volatile(__stringify(c) ": nop\n\t" \
- ".pushsection .discard.instr_begin\n\t" \
- ".long " __stringify(c) "b - .\n\t" \
- ".popsection\n\t" : : "i" (c)); \
+ __ASM_ANNOTATE(c, ANNOTYPE_INSTR_BEGIN) \
+ : : "i" (c)); \
})
#define instrumentation_begin() __instrumentation_begin(__COUNTER__)
@@ -48,9 +48,8 @@
*/
#define __instrumentation_end(c) ({ \
asm volatile(__stringify(c) ": nop\n\t" \
- ".pushsection .discard.instr_end\n\t" \
- ".long " __stringify(c) "b - .\n\t" \
- ".popsection\n\t" : : "i" (c)); \
+ __ASM_ANNOTATE(c, ANNOTYPE_INSTR_END) \
+ : : "i" (c)); \
})
#define instrumentation_end() __instrumentation_end(__COUNTER__)
#else /* !CONFIG_NOINSTR_VALIDATION */
--- a/include/linux/objtool.h
+++ b/include/linux/objtool.h
@@ -51,13 +51,16 @@
".long 998b\n\t" \
".popsection\n\t"
-#define ASM_ANNOTATE(x) \
- "911:\n\t" \
+#define __ASM_ANNOTATE(s, x) \
".pushsection .discard.annotate,\"M\",@progbits,8\n\t" \
- ".long 911b - .\n\t" \
+ ".long " __stringify(s) "b - .\n\t" \
".long " __stringify(x) "\n\t" \
".popsection\n\t"
+#define ASM_ANNOTATE(x) \
+ "911:\n\t" \
+ __ASM_ANNOTATE(911, x)
+
#define ANNOTATE_NOENDBR ASM_ANNOTATE(ANNOTYPE_NOENDBR)
#else /* __ASSEMBLY__ */
--- a/include/linux/objtool_types.h
+++ b/include/linux/objtool_types.h
@@ -59,5 +59,7 @@ struct unwind_hint {
*/
#define ANNOTYPE_NOENDBR 1
#define ANNOTYPE_RETPOLINE_SAFE 2
+#define ANNOTYPE_INSTR_BEGIN 3
+#define ANNOTYPE_INSTR_END 4
#endif /* _LINUX_OBJTOOL_TYPES_H */
--- a/tools/include/linux/objtool_types.h
+++ b/tools/include/linux/objtool_types.h
@@ -59,5 +59,7 @@ struct unwind_hint {
*/
#define ANNOTYPE_NOENDBR 1
#define ANNOTYPE_RETPOLINE_SAFE 2
+#define ANNOTYPE_INSTR_BEGIN 3
+#define ANNOTYPE_INSTR_END 4
#endif /* _LINUX_OBJTOOL_TYPES_H */
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -2367,48 +2367,19 @@ static int __annotate_retpoline_safe(int
return 0;
}
-static int read_instr_hints(struct objtool_file *file)
+static int __annotate_instr(int type, struct instruction *insn)
{
- struct section *rsec;
- struct instruction *insn;
- struct reloc *reloc;
-
- rsec = find_section_by_name(file->elf, ".rela.discard.instr_end");
- if (!rsec)
- return 0;
-
- for_each_reloc(rsec, reloc) {
- if (reloc->sym->type != STT_SECTION) {
- WARN("unexpected relocation symbol type in %s", rsec->name);
- return -1;
- }
-
- insn = find_insn(file, reloc->sym->sec, reloc_addend(reloc));
- if (!insn) {
- WARN("bad .discard.instr_end entry");
- return -1;
- }
+ switch (type) {
+ case ANNOTYPE_INSTR_BEGIN:
+ insn->instr++;
+ break;
+ case ANNOTYPE_INSTR_END:
insn->instr--;
- }
-
- rsec = find_section_by_name(file->elf, ".rela.discard.instr_begin");
- if (!rsec)
- return 0;
+ break;
- for_each_reloc(rsec, reloc) {
- if (reloc->sym->type != STT_SECTION) {
- WARN("unexpected relocation symbol type in %s", rsec->name);
- return -1;
- }
-
- insn = find_insn(file, reloc->sym->sec, reloc_addend(reloc));
- if (!insn) {
- WARN("bad .discard.instr_begin entry");
- return -1;
- }
-
- insn->instr++;
+ default:
+ break;
}
return 0;
@@ -2654,7 +2625,7 @@ static int decode_sections(struct objtoo
if (ret)
return ret;
- ret = read_instr_hints(file);
+ ret = read_annotate(file, __annotate_instr);
if (ret)
return ret;
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 05/11] objtool: Convert VALIDATE_UNRET_BEGIN to ANNOTATE
2023-12-04 9:37 [PATCH 00/11] x86/kvm/emulate: Avoid RET for FASTOPs Peter Zijlstra
` (3 preceding siblings ...)
2023-12-04 9:37 ` [PATCH 04/11] objtool: Convert instrumentation_{begin,end}() " Peter Zijlstra
@ 2023-12-04 9:37 ` Peter Zijlstra
2023-12-04 9:37 ` [PATCH 06/11] objtool: Convert ANNOTATE_IGNORE_ALTERNATIVE " Peter Zijlstra
` (5 subsequent siblings)
10 siblings, 0 replies; 20+ messages in thread
From: Peter Zijlstra @ 2023-12-04 9:37 UTC (permalink / raw)
To: Sean Christopherson, Paolo Bonzini, Josh Poimboeuf,
Thomas Gleixner
Cc: linux-kernel, peterz, x86, kvm
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
---
include/linux/objtool.h | 9 +++------
include/linux/objtool_types.h | 1 +
tools/include/linux/objtool_types.h | 1 +
tools/objtool/check.c | 28 +++++-----------------------
4 files changed, 10 insertions(+), 29 deletions(-)
--- a/include/linux/objtool.h
+++ b/include/linux/objtool.h
@@ -128,15 +128,12 @@
* NOTE: The macro must be used at the beginning of a global symbol, otherwise
* it will be ignored.
*/
-.macro VALIDATE_UNRET_BEGIN
#if defined(CONFIG_NOINSTR_VALIDATION) && \
(defined(CONFIG_CPU_UNRET_ENTRY) || defined(CONFIG_CPU_SRSO))
-.Lhere_\@:
- .pushsection .discard.validate_unret
- .long .Lhere_\@ - .
- .popsection
+#define VALIDATE_UNRET_BEGIN ANNOTATE type=ANNOTYPE_UNRET_BEGIN
+#else
+#define VALIDATE_UNRET_BEGIN
#endif
-.endm
.macro REACHABLE
.Lhere_\@:
--- a/include/linux/objtool_types.h
+++ b/include/linux/objtool_types.h
@@ -61,5 +61,6 @@ struct unwind_hint {
#define ANNOTYPE_RETPOLINE_SAFE 2
#define ANNOTYPE_INSTR_BEGIN 3
#define ANNOTYPE_INSTR_END 4
+#define ANNOTYPE_UNRET_BEGIN 5
#endif /* _LINUX_OBJTOOL_TYPES_H */
--- a/tools/include/linux/objtool_types.h
+++ b/tools/include/linux/objtool_types.h
@@ -61,5 +61,6 @@ struct unwind_hint {
#define ANNOTYPE_RETPOLINE_SAFE 2
#define ANNOTYPE_INSTR_BEGIN 3
#define ANNOTYPE_INSTR_END 4
+#define ANNOTYPE_UNRET_BEGIN 5
#endif /* _LINUX_OBJTOOL_TYPES_H */
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -2385,33 +2385,15 @@ static int __annotate_instr(int type, st
return 0;
}
-static int read_validate_unret_hints(struct objtool_file *file)
+static int __annotate_unret(int type, struct instruction *insn)
{
- struct section *rsec;
- struct instruction *insn;
- struct reloc *reloc;
-
- rsec = find_section_by_name(file->elf, ".rela.discard.validate_unret");
- if (!rsec)
+ if (type != ANNOTYPE_UNRET_BEGIN)
return 0;
- for_each_reloc(rsec, reloc) {
- if (reloc->sym->type != STT_SECTION) {
- WARN("unexpected relocation symbol type in %s", rsec->name);
- return -1;
- }
-
- insn = find_insn(file, reloc->sym->sec, reloc_addend(reloc));
- if (!insn) {
- WARN("bad .discard.instr_end entry");
- return -1;
- }
- insn->unret = 1;
- }
-
+ insn->unret = 1;
return 0;
-}
+}
static int read_intra_function_calls(struct objtool_file *file)
{
@@ -2629,7 +2611,7 @@ static int decode_sections(struct objtoo
if (ret)
return ret;
- ret = read_validate_unret_hints(file);
+ ret = read_annotate(file, __annotate_unret);
if (ret)
return ret;
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 06/11] objtool: Convert ANNOTATE_IGNORE_ALTERNATIVE to ANNOTATE
2023-12-04 9:37 [PATCH 00/11] x86/kvm/emulate: Avoid RET for FASTOPs Peter Zijlstra
` (4 preceding siblings ...)
2023-12-04 9:37 ` [PATCH 05/11] objtool: Convert VALIDATE_UNRET_BEGIN " Peter Zijlstra
@ 2023-12-04 9:37 ` Peter Zijlstra
2023-12-04 9:37 ` [PATCH 07/11] objtool: Convert ANNOTATE_INTRA_FUNCTION_CALLS " Peter Zijlstra
` (4 subsequent siblings)
10 siblings, 0 replies; 20+ messages in thread
From: Peter Zijlstra @ 2023-12-04 9:37 UTC (permalink / raw)
To: Sean Christopherson, Paolo Bonzini, Josh Poimboeuf,
Thomas Gleixner
Cc: linux-kernel, peterz, x86, kvm
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
---
arch/x86/include/asm/alternative.h | 14 ++---------
include/linux/objtool_types.h | 1
tools/include/linux/objtool_types.h | 1
tools/objtool/check.c | 45 ++++++++----------------------------
4 files changed, 15 insertions(+), 46 deletions(-)
--- a/arch/x86/include/asm/alternative.h
+++ b/arch/x86/include/asm/alternative.h
@@ -4,6 +4,7 @@
#include <linux/types.h>
#include <linux/stringify.h>
+#include <linux/objtool.h>
#include <asm/asm.h>
#define ALT_FLAGS_SHIFT 16
@@ -55,11 +56,7 @@
* objtool annotation to ignore the alternatives and only consider the original
* instruction(s).
*/
-#define ANNOTATE_IGNORE_ALTERNATIVE \
- "999:\n\t" \
- ".pushsection .discard.ignore_alts\n\t" \
- ".long 999b\n\t" \
- ".popsection\n\t"
+#define ANNOTATE_IGNORE_ALTERNATIVE ASM_ANNOTATE(ANNOTYPE_IGNORE_ALTS)
/*
* The patching flags are part of the upper bits of the @ft_flags parameter when
@@ -349,12 +346,7 @@ static inline int alternatives_text_rese
* objtool annotation to ignore the alternatives and only consider the original
* instruction(s).
*/
-.macro ANNOTATE_IGNORE_ALTERNATIVE
- .Lannotate_\@:
- .pushsection .discard.ignore_alts
- .long .Lannotate_\@
- .popsection
-.endm
+#define ANNOTATE_IGNORE_ALTERNATIVE ANNOTATE type=ANNOTYPE_IGNORE_ALTS
/*
* Issue one struct alt_instr descriptor entry (need to put it into
--- a/include/linux/objtool_types.h
+++ b/include/linux/objtool_types.h
@@ -62,5 +62,6 @@ struct unwind_hint {
#define ANNOTYPE_INSTR_BEGIN 3
#define ANNOTYPE_INSTR_END 4
#define ANNOTYPE_UNRET_BEGIN 5
+#define ANNOTYPE_IGNORE_ALTS 6
#endif /* _LINUX_OBJTOOL_TYPES_H */
--- a/tools/include/linux/objtool_types.h
+++ b/tools/include/linux/objtool_types.h
@@ -62,5 +62,6 @@ struct unwind_hint {
#define ANNOTYPE_INSTR_BEGIN 3
#define ANNOTYPE_INSTR_END 4
#define ANNOTYPE_UNRET_BEGIN 5
+#define ANNOTYPE_IGNORE_ALTS 6
#endif /* _LINUX_OBJTOOL_TYPES_H */
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -1255,40 +1255,6 @@ static void add_uaccess_safe(struct objt
}
/*
- * FIXME: For now, just ignore any alternatives which add retpolines. This is
- * a temporary hack, as it doesn't allow ORC to unwind from inside a retpoline.
- * But it at least allows objtool to understand the control flow *around* the
- * retpoline.
- */
-static int add_ignore_alternatives(struct objtool_file *file)
-{
- struct section *rsec;
- struct reloc *reloc;
- struct instruction *insn;
-
- rsec = find_section_by_name(file->elf, ".rela.discard.ignore_alts");
- if (!rsec)
- return 0;
-
- for_each_reloc(rsec, reloc) {
- if (reloc->sym->type != STT_SECTION) {
- WARN("unexpected relocation symbol type in %s", rsec->name);
- return -1;
- }
-
- insn = find_insn(file, reloc->sym->sec, reloc_addend(reloc));
- if (!insn) {
- WARN("bad .discard.ignore_alts entry");
- return -1;
- }
-
- insn->ignore_alts = true;
- }
-
- return 0;
-}
-
-/*
* Symbols that replace INSN_CALL_DYNAMIC, every (tail) call to such a symbol
* will be added to the .retpoline_sites section.
*/
@@ -2341,6 +2307,15 @@ static int read_annotate(struct objtool_
return 0;
}
+static int __annotate_ignore_alts(int type, struct instruction *insn)
+{
+ if (type != ANNOTYPE_IGNORE_ALTS)
+ return 0;
+
+ insn->ignore_alts = true;
+ return 0;
+}
+
static int __annotate_noendbr(int type, struct instruction *insn)
{
if (type != ANNOTYPE_NOENDBR)
@@ -2550,7 +2525,7 @@ static int decode_sections(struct objtoo
add_ignores(file);
add_uaccess_safe(file);
- ret = add_ignore_alternatives(file);
+ ret = read_annotate(file, __annotate_ignore_alts);
if (ret)
return ret;
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 07/11] objtool: Convert ANNOTATE_INTRA_FUNCTION_CALLS to ANNOTATE
2023-12-04 9:37 [PATCH 00/11] x86/kvm/emulate: Avoid RET for FASTOPs Peter Zijlstra
` (5 preceding siblings ...)
2023-12-04 9:37 ` [PATCH 06/11] objtool: Convert ANNOTATE_IGNORE_ALTERNATIVE " Peter Zijlstra
@ 2023-12-04 9:37 ` Peter Zijlstra
2023-12-04 9:37 ` [PATCH 08/11] objtool: Collapse annotate sequences Peter Zijlstra
` (3 subsequent siblings)
10 siblings, 0 replies; 20+ messages in thread
From: Peter Zijlstra @ 2023-12-04 9:37 UTC (permalink / raw)
To: Sean Christopherson, Paolo Bonzini, Josh Poimboeuf,
Thomas Gleixner
Cc: linux-kernel, peterz, x86, kvm
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
---
include/linux/objtool.h | 16 ++----
include/linux/objtool_types.h | 1
tools/include/linux/objtool_types.h | 1
tools/objtool/check.c | 96 ++++++++++++++----------------------
4 files changed, 47 insertions(+), 67 deletions(-)
--- a/include/linux/objtool.h
+++ b/include/linux/objtool.h
@@ -66,16 +66,6 @@
#else /* __ASSEMBLY__ */
/*
- * This macro indicates that the following intra-function call is valid.
- * Any non-annotated intra-function call will cause objtool to issue a warning.
- */
-#define ANNOTATE_INTRA_FUNCTION_CALL \
- 999: \
- .pushsection .discard.intra_function_calls; \
- .long 999b; \
- .popsection;
-
-/*
* In asm, there are two kinds of code: normal C-type callable functions and
* the rest. The normal callable functions can be called by other code, and
* don't do anything unusual with the stack. Such normal callable functions
@@ -152,6 +142,12 @@
#define ANNOTATE_NOENDBR ANNOTATE type=ANNOTYPE_NOENDBR
+/*
+ * This macro indicates that the following intra-function call is valid.
+ * Any non-annotated intra-function call will cause objtool to issue a warning.
+ */
+#define ANNOTATE_INTRA_FUNCTION_CALL ANNOTATE type=ANNOTYPE_INTRA_FUNCTION_CALLS
+
#endif /* __ASSEMBLY__ */
#else /* !CONFIG_OBJTOOL */
--- a/include/linux/objtool_types.h
+++ b/include/linux/objtool_types.h
@@ -63,5 +63,6 @@ struct unwind_hint {
#define ANNOTYPE_INSTR_END 4
#define ANNOTYPE_UNRET_BEGIN 5
#define ANNOTYPE_IGNORE_ALTS 6
+#define ANNOTYPE_INTRA_FUNCTION_CALLS 7
#endif /* _LINUX_OBJTOOL_TYPES_H */
--- a/tools/include/linux/objtool_types.h
+++ b/tools/include/linux/objtool_types.h
@@ -63,5 +63,6 @@ struct unwind_hint {
#define ANNOTYPE_INSTR_END 4
#define ANNOTYPE_UNRET_BEGIN 5
#define ANNOTYPE_IGNORE_ALTS 6
+#define ANNOTYPE_INTRA_FUNCTION_CALLS 7
#endif /* _LINUX_OBJTOOL_TYPES_H */
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -2274,7 +2274,8 @@ static int read_unwind_hints(struct objt
return 0;
}
-static int read_annotate(struct objtool_file *file, int (*func)(int type, struct instruction *insn))
+static int read_annotate(struct objtool_file *file,
+ int (*func)(struct objtool_file *file, int type, struct instruction *insn))
{
struct section *rsec, *sec;
struct instruction *insn;
@@ -2299,7 +2300,7 @@ static int read_annotate(struct objtool_
type = *(u32 *)(sec->data->d_buf + (reloc_idx(reloc) * sec->sh.sh_entsize) + 4);
- ret = func(type, insn);
+ ret = func(file, type, insn);
if (ret < 0)
return ret;
}
@@ -2307,7 +2308,7 @@ static int read_annotate(struct objtool_
return 0;
}
-static int __annotate_ignore_alts(int type, struct instruction *insn)
+static int __annotate_ignore_alts(struct objtool_file *file, int type, struct instruction *insn)
{
if (type != ANNOTYPE_IGNORE_ALTS)
return 0;
@@ -2316,7 +2317,7 @@ static int __annotate_ignore_alts(int ty
return 0;
}
-static int __annotate_noendbr(int type, struct instruction *insn)
+static int __annotate_noendbr(struct objtool_file *file, int type, struct instruction *insn)
{
if (type != ANNOTYPE_NOENDBR)
return 0;
@@ -2325,7 +2326,37 @@ static int __annotate_noendbr(int type,
return 0;
}
-static int __annotate_retpoline_safe(int type, struct instruction *insn)
+static int __annotate_ifc(struct objtool_file *file, int type, struct instruction *insn)
+{
+ unsigned long dest_off;
+
+ if (type != ANNOTYPE_INTRA_FUNCTION_CALLS)
+ return 0;
+
+ if (insn->type != INSN_CALL) {
+ WARN_INSN(insn, "intra_function_call not a direct call");
+ return -1;
+ }
+
+ /*
+ * Treat intra-function CALLs as JMPs, but with a stack_op.
+ * See add_call_destinations(), which strips stack_ops from
+ * normal CALLs.
+ */
+ insn->type = INSN_JUMP_UNCONDITIONAL;
+
+ dest_off = arch_jump_destination(insn);
+ insn->jump_dest = find_insn(file, insn->sec, dest_off);
+ if (!insn->jump_dest) {
+ WARN_INSN(insn, "can't find call dest at %s+0x%lx",
+ insn->sec->name, dest_off);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int __annotate_retpoline_safe(struct objtool_file *file, int type, struct instruction *insn)
{
if (type != ANNOTYPE_RETPOLINE_SAFE)
return 0;
@@ -2342,7 +2373,7 @@ static int __annotate_retpoline_safe(int
return 0;
}
-static int __annotate_instr(int type, struct instruction *insn)
+static int __annotate_instr(struct objtool_file *file, int type, struct instruction *insn)
{
switch (type) {
case ANNOTYPE_INSTR_BEGIN:
@@ -2360,7 +2391,7 @@ static int __annotate_instr(int type, st
return 0;
}
-static int __annotate_unret(int type, struct instruction *insn)
+static int __annotate_unret(struct objtool_file *file, int type, struct instruction *insn)
{
if (type != ANNOTYPE_UNRET_BEGIN)
return 0;
@@ -2370,55 +2401,6 @@ static int __annotate_unret(int type, st
}
-static int read_intra_function_calls(struct objtool_file *file)
-{
- struct instruction *insn;
- struct section *rsec;
- struct reloc *reloc;
-
- rsec = find_section_by_name(file->elf, ".rela.discard.intra_function_calls");
- if (!rsec)
- return 0;
-
- for_each_reloc(rsec, reloc) {
- unsigned long dest_off;
-
- if (reloc->sym->type != STT_SECTION) {
- WARN("unexpected relocation symbol type in %s",
- rsec->name);
- return -1;
- }
-
- insn = find_insn(file, reloc->sym->sec, reloc_addend(reloc));
- if (!insn) {
- WARN("bad .discard.intra_function_call entry");
- return -1;
- }
-
- if (insn->type != INSN_CALL) {
- WARN_INSN(insn, "intra_function_call not a direct call");
- return -1;
- }
-
- /*
- * Treat intra-function CALLs as JMPs, but with a stack_op.
- * See add_call_destinations(), which strips stack_ops from
- * normal CALLs.
- */
- insn->type = INSN_JUMP_UNCONDITIONAL;
-
- dest_off = arch_jump_destination(insn);
- insn->jump_dest = find_insn(file, insn->sec, dest_off);
- if (!insn->jump_dest) {
- WARN_INSN(insn, "can't find call dest at %s+0x%lx",
- insn->sec->name, dest_off);
- return -1;
- }
- }
-
- return 0;
-}
-
/*
* Return true if name matches an instrumentation function, where calls to that
* function from noinstr code can safely be removed, but compilers won't do so.
@@ -2554,7 +2536,7 @@ static int decode_sections(struct objtoo
* Must be before add_call_destination(); it changes INSN_CALL to
* INSN_JUMP.
*/
- ret = read_intra_function_calls(file);
+ ret = read_annotate(file, __annotate_ifc);
if (ret)
return ret;
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 08/11] objtool: Collapse annotate sequences
2023-12-04 9:37 [PATCH 00/11] x86/kvm/emulate: Avoid RET for FASTOPs Peter Zijlstra
` (6 preceding siblings ...)
2023-12-04 9:37 ` [PATCH 07/11] objtool: Convert ANNOTATE_INTRA_FUNCTION_CALLS " Peter Zijlstra
@ 2023-12-04 9:37 ` Peter Zijlstra
2023-12-04 9:37 ` [PATCH 09/11] x86/kvm/emulate: Implement test_cc() in C Peter Zijlstra
` (2 subsequent siblings)
10 siblings, 0 replies; 20+ messages in thread
From: Peter Zijlstra @ 2023-12-04 9:37 UTC (permalink / raw)
To: Sean Christopherson, Paolo Bonzini, Josh Poimboeuf,
Thomas Gleixner
Cc: linux-kernel, peterz, x86, kvm
Reduce read_annotate() runs by collapsing subsequent runs into a
single call.
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
---
tools/objtool/check.c | 87 ++++++++++++++++++--------------------------------
1 file changed, 32 insertions(+), 55 deletions(-)
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -2308,21 +2308,24 @@ static int read_annotate(struct objtool_
return 0;
}
-static int __annotate_ignore_alts(struct objtool_file *file, int type, struct instruction *insn)
+static int __annotate_early(struct objtool_file *file, int type, struct instruction *insn)
{
- if (type != ANNOTYPE_IGNORE_ALTS)
- return 0;
+ switch (type) {
+ case ANNOTYPE_IGNORE_ALTS:
+ insn->ignore_alts = true;
+ break;
- insn->ignore_alts = true;
- return 0;
-}
+ /*
+ * Must be before read_unwind_hints() since that needs insn->noendbr.
+ */
+ case ANNOTYPE_NOENDBR:
+ insn->noendbr = 1;
+ break;
-static int __annotate_noendbr(struct objtool_file *file, int type, struct instruction *insn)
-{
- if (type != ANNOTYPE_NOENDBR)
- return 0;
+ default:
+ break;
+ }
- insn->noendbr = 1;
return 0;
}
@@ -2356,26 +2359,21 @@ static int __annotate_ifc(struct objtool
return 0;
}
-static int __annotate_retpoline_safe(struct objtool_file *file, int type, struct instruction *insn)
+static int __annotate_late(struct objtool_file *file, int type, struct instruction *insn)
{
- if (type != ANNOTYPE_RETPOLINE_SAFE)
- return 0;
-
- if (insn->type != INSN_JUMP_DYNAMIC &&
- insn->type != INSN_CALL_DYNAMIC &&
- insn->type != INSN_RETURN &&
- insn->type != INSN_NOP) {
- WARN_INSN(insn, "retpoline_safe hint not an indirect jump/call/ret/nop");
- return -1;
- }
+ switch (type) {
+ case ANNOTYPE_RETPOLINE_SAFE:
+ if (insn->type != INSN_JUMP_DYNAMIC &&
+ insn->type != INSN_CALL_DYNAMIC &&
+ insn->type != INSN_RETURN &&
+ insn->type != INSN_NOP) {
+ WARN_INSN(insn, "retpoline_safe hint not an indirect jump/call/ret/nop");
+ return -1;
+ }
- insn->retpoline_safe = true;
- return 0;
-}
+ insn->retpoline_safe = true;
+ break;
-static int __annotate_instr(struct objtool_file *file, int type, struct instruction *insn)
-{
- switch (type) {
case ANNOTYPE_INSTR_BEGIN:
insn->instr++;
break;
@@ -2384,6 +2382,10 @@ static int __annotate_instr(struct objto
insn->instr--;
break;
+ case ANNOTYPE_UNRET_BEGIN:
+ insn->unret = 1;
+ break;
+
default:
break;
}
@@ -2391,16 +2393,6 @@ static int __annotate_instr(struct objto
return 0;
}
-static int __annotate_unret(struct objtool_file *file, int type, struct instruction *insn)
-{
- if (type != ANNOTYPE_UNRET_BEGIN)
- return 0;
-
- insn->unret = 1;
- return 0;
-
-}
-
/*
* Return true if name matches an instrumentation function, where calls to that
* function from noinstr code can safely be removed, but compilers won't do so.
@@ -2507,14 +2499,7 @@ static int decode_sections(struct objtoo
add_ignores(file);
add_uaccess_safe(file);
- ret = read_annotate(file, __annotate_ignore_alts);
- if (ret)
- return ret;
-
- /*
- * Must be before read_unwind_hints() since that needs insn->noendbr.
- */
- ret = read_annotate(file, __annotate_noendbr);
+ ret = read_annotate(file, __annotate_early);
if (ret)
return ret;
@@ -2560,15 +2545,7 @@ static int decode_sections(struct objtoo
if (ret)
return ret;
- ret = read_annotate(file, __annotate_retpoline_safe);
- if (ret)
- return ret;
-
- ret = read_annotate(file, __annotate_instr);
- if (ret)
- return ret;
-
- ret = read_annotate(file, __annotate_unret);
+ ret = read_annotate(file, __annotate_late);
if (ret)
return ret;
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 09/11] x86/kvm/emulate: Implement test_cc() in C
2023-12-04 9:37 [PATCH 00/11] x86/kvm/emulate: Avoid RET for FASTOPs Peter Zijlstra
` (7 preceding siblings ...)
2023-12-04 9:37 ` [PATCH 08/11] objtool: Collapse annotate sequences Peter Zijlstra
@ 2023-12-04 9:37 ` Peter Zijlstra
2023-12-04 9:37 ` [PATCH 10/11] x86/nospec: JMP_NOSPEC Peter Zijlstra
2023-12-04 9:37 ` [PATCH 11/11] x86/kvm/emulate: Avoid RET for fastops Peter Zijlstra
10 siblings, 0 replies; 20+ messages in thread
From: Peter Zijlstra @ 2023-12-04 9:37 UTC (permalink / raw)
To: Sean Christopherson, Paolo Bonzini, Josh Poimboeuf,
Thomas Gleixner
Cc: linux-kernel, peterz, x86, kvm
Current test_cc() uses the fastop infrastructure to test flags using
SETcc instructions. However, int3_emulate_jcc() already fully
implements the flags->CC mapping, use that.
Removes a pile of gnarly asm.
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
---
arch/x86/include/asm/text-patching.h | 20 +++++++++++++-------
arch/x86/kvm/emulate.c | 34 ++--------------------------------
2 files changed, 15 insertions(+), 39 deletions(-)
--- a/arch/x86/include/asm/text-patching.h
+++ b/arch/x86/include/asm/text-patching.h
@@ -186,9 +186,9 @@ void int3_emulate_ret(struct pt_regs *re
}
static __always_inline
-void int3_emulate_jcc(struct pt_regs *regs, u8 cc, unsigned long ip, unsigned long disp)
+bool __emulate_cc(unsigned long flags, u8 cc)
{
- static const unsigned long jcc_mask[6] = {
+ static const unsigned long cc_mask[6] = {
[0] = X86_EFLAGS_OF,
[1] = X86_EFLAGS_CF,
[2] = X86_EFLAGS_ZF,
@@ -201,15 +201,21 @@ void int3_emulate_jcc(struct pt_regs *re
bool match;
if (cc < 0xc) {
- match = regs->flags & jcc_mask[cc >> 1];
+ match = flags & cc_mask[cc >> 1];
} else {
- match = ((regs->flags & X86_EFLAGS_SF) >> X86_EFLAGS_SF_BIT) ^
- ((regs->flags & X86_EFLAGS_OF) >> X86_EFLAGS_OF_BIT);
+ match = ((flags & X86_EFLAGS_SF) >> X86_EFLAGS_SF_BIT) ^
+ ((flags & X86_EFLAGS_OF) >> X86_EFLAGS_OF_BIT);
if (cc >= 0xe)
- match = match || (regs->flags & X86_EFLAGS_ZF);
+ match = match || (flags & X86_EFLAGS_ZF);
}
- if ((match && !invert) || (!match && invert))
+ return (match && !invert) || (!match && invert);
+}
+
+static __always_inline
+void int3_emulate_jcc(struct pt_regs *regs, u8 cc, unsigned long ip, unsigned long disp)
+{
+ if (__emulate_cc(regs->flags, cc))
ip += disp;
int3_emulate_jmp(regs, ip);
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -26,6 +26,7 @@
#include <asm/debugreg.h>
#include <asm/nospec-branch.h>
#include <asm/ibt.h>
+#include <asm/text-patching.h>
#include "x86.h"
#include "tss.h"
@@ -416,31 +417,6 @@ static int fastop(struct x86_emulate_ctx
ON64(FOP3E(op##q, rax, rdx, cl)) \
FOP_END
-/* Special case for SETcc - 1 instruction per cc */
-#define FOP_SETCC(op) \
- FOP_FUNC(op) \
- #op " %al \n\t" \
- FOP_RET(op)
-
-FOP_START(setcc)
-FOP_SETCC(seto)
-FOP_SETCC(setno)
-FOP_SETCC(setc)
-FOP_SETCC(setnc)
-FOP_SETCC(setz)
-FOP_SETCC(setnz)
-FOP_SETCC(setbe)
-FOP_SETCC(setnbe)
-FOP_SETCC(sets)
-FOP_SETCC(setns)
-FOP_SETCC(setp)
-FOP_SETCC(setnp)
-FOP_SETCC(setl)
-FOP_SETCC(setnl)
-FOP_SETCC(setle)
-FOP_SETCC(setnle)
-FOP_END;
-
FOP_START(salc)
FOP_FUNC(salc)
"pushf; sbb %al, %al; popf \n\t"
@@ -1063,13 +1039,7 @@ static int em_bsr_c(struct x86_emulate_c
static __always_inline u8 test_cc(unsigned int condition, unsigned long flags)
{
- u8 rc;
- void (*fop)(void) = (void *)em_setcc + FASTOP_SIZE * (condition & 0xf);
-
- flags = (flags & EFLAGS_MASK) | X86_EFLAGS_IF;
- asm("push %[flags]; popf; " CALL_NOSPEC
- : "=a"(rc) : [thunk_target]"r"(fop), [flags]"r"(flags));
- return rc;
+ return __emulate_cc(flags, condition & 0xf);
}
static void fetch_register_operand(struct operand *op)
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 10/11] x86/nospec: JMP_NOSPEC
2023-12-04 9:37 [PATCH 00/11] x86/kvm/emulate: Avoid RET for FASTOPs Peter Zijlstra
` (8 preceding siblings ...)
2023-12-04 9:37 ` [PATCH 09/11] x86/kvm/emulate: Implement test_cc() in C Peter Zijlstra
@ 2023-12-04 9:37 ` Peter Zijlstra
2023-12-04 9:37 ` [PATCH 11/11] x86/kvm/emulate: Avoid RET for fastops Peter Zijlstra
10 siblings, 0 replies; 20+ messages in thread
From: Peter Zijlstra @ 2023-12-04 9:37 UTC (permalink / raw)
To: Sean Christopherson, Paolo Bonzini, Josh Poimboeuf,
Thomas Gleixner
Cc: linux-kernel, peterz, x86, kvm
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
---
arch/x86/include/asm/nospec-branch.h | 32 ++++++++++++++++++++++++++++++++
1 file changed, 32 insertions(+)
--- a/arch/x86/include/asm/nospec-branch.h
+++ b/arch/x86/include/asm/nospec-branch.h
@@ -403,6 +403,17 @@ static inline void call_depth_return_thu
"call *%[thunk_target]\n", \
X86_FEATURE_RETPOLINE_LFENCE)
+# define JMP_NOSPEC \
+ ALTERNATIVE_2( \
+ ANNOTATE_RETPOLINE_SAFE \
+ "jmp *%[thunk_target]\n", \
+ "jmp __x86_indirect_thunk_%V[thunk_target]\n", \
+ X86_FEATURE_RETPOLINE, \
+ "lfence;\n" \
+ ANNOTATE_RETPOLINE_SAFE \
+ "jmp *%[thunk_target]\n", \
+ X86_FEATURE_RETPOLINE_LFENCE)
+
# define THUNK_TARGET(addr) [thunk_target] "r" (addr)
#else /* CONFIG_X86_32 */
@@ -433,10 +444,31 @@ static inline void call_depth_return_thu
"call *%[thunk_target]\n", \
X86_FEATURE_RETPOLINE_LFENCE)
+# define JMP_NOSPEC \
+ ALTERNATIVE_2( \
+ ANNOTATE_RETPOLINE_SAFE \
+ "jmp *%[thunk_target]\n", \
+ " jmp 901f;\n" \
+ " .align 16\n" \
+ "901: call 903f;\n" \
+ "902: pause;\n" \
+ " lfence;\n" \
+ " jmp 902b;\n" \
+ " .align 16\n" \
+ "903: lea 4(%%esp), %%esp;\n" \
+ " pushl %[thunk_target];\n" \
+ " ret;\n" \
+ X86_FEATURE_RETPOLINE, \
+ "lfence;\n" \
+ ANNOTATE_RETPOLINE_SAFE \
+ "jmp *%[thunk_target]\n", \
+ X86_FEATURE_RETPOLINE_LFENCE)
+
# define THUNK_TARGET(addr) [thunk_target] "rm" (addr)
#endif
#else /* No retpoline for C / inline asm */
# define CALL_NOSPEC "call *%[thunk_target]\n"
+# define JMP_NOSPEC "jmp *%[thunk_target]\n"
# define THUNK_TARGET(addr) [thunk_target] "rm" (addr)
#endif
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 11/11] x86/kvm/emulate: Avoid RET for fastops
2023-12-04 9:37 [PATCH 00/11] x86/kvm/emulate: Avoid RET for FASTOPs Peter Zijlstra
` (9 preceding siblings ...)
2023-12-04 9:37 ` [PATCH 10/11] x86/nospec: JMP_NOSPEC Peter Zijlstra
@ 2023-12-04 9:37 ` Peter Zijlstra
10 siblings, 0 replies; 20+ messages in thread
From: Peter Zijlstra @ 2023-12-04 9:37 UTC (permalink / raw)
To: Sean Christopherson, Paolo Bonzini, Josh Poimboeuf,
Thomas Gleixner
Cc: linux-kernel, peterz, x86, kvm
Since there is only a single fastop() function, convert the FASTOP
stuff from CALL_NOSPEC+RET to JMP_NOSPEC+JMP, avoiding the return
thunks and all that jazz.
Specifically FASTOPs rely on the return thunk to preserve EFLAGS,
which not all of them can trivially do (call depth tracing suffers
here).
Objtool strenuously complains about this:
- indirect call without a .rodata, fails to determine JUMP_TABLE,
annotate
- fastop functions fall through, exception
- unreachable instruction after fastop_return, save/restore
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
---
arch/x86/kvm/emulate.c | 20 +++++++++++++++-----
include/linux/objtool_types.h | 1 +
tools/include/linux/objtool_types.h | 1 +
tools/objtool/check.c | 11 ++++++++++-
4 files changed, 27 insertions(+), 6 deletions(-)
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -285,8 +285,8 @@ static void invalidate_registers(struct
* different operand sizes can be reached by calculation, rather than a jump
* table (which would be bigger than the code).
*
- * The 16 byte alignment, considering 5 bytes for the RET thunk, 3 for ENDBR
- * and 1 for the straight line speculation INT3, leaves 7 bytes for the
+ * The 16 byte alignment, considering 5 bytes for the JMP, 4 for ENDBR
+ * and 1 for the straight line speculation INT3, leaves 6 bytes for the
* body of the function. Currently none is larger than 4.
*/
static int fastop(struct x86_emulate_ctxt *ctxt, fastop_t fop);
@@ -304,7 +304,7 @@ static int fastop(struct x86_emulate_ctx
__FOP_FUNC(#name)
#define __FOP_RET(name) \
- "11: " ASM_RET \
+ "11: jmp fastop_return; int3 \n\t" \
".size " name ", .-" name "\n\t"
#define FOP_RET(name) \
@@ -5071,14 +5071,24 @@ static void fetch_possible_mmx_operand(s
kvm_read_mmx_reg(op->addr.mm, &op->mm_val);
}
-static int fastop(struct x86_emulate_ctxt *ctxt, fastop_t fop)
+/*
+ * All the FASTOP magic above relies on there being *one* instance of this
+ * so it can JMP back, avoiding RET and it's various thunks.
+ */
+static noinline int fastop(struct x86_emulate_ctxt *ctxt, fastop_t fop)
{
ulong flags = (ctxt->eflags & EFLAGS_MASK) | X86_EFLAGS_IF;
if (!(ctxt->d & ByteOp))
fop += __ffs(ctxt->dst.bytes) * FASTOP_SIZE;
- asm("push %[flags]; popf; " CALL_NOSPEC " ; pushf; pop %[flags]\n"
+ asm("push %[flags]; popf \n\t"
+ UNWIND_HINT(UNWIND_HINT_TYPE_SAVE, 0, 0, 0)
+ ASM_ANNOTATE(ANNOTYPE_JUMP_TABLE)
+ JMP_NOSPEC
+ "fastop_return: \n\t"
+ UNWIND_HINT(UNWIND_HINT_TYPE_RESTORE, 0, 0, 0)
+ "pushf; pop %[flags]\n"
: "+a"(ctxt->dst.val), "+d"(ctxt->src.val), [flags]"+D"(flags),
[thunk_target]"+S"(fop), ASM_CALL_CONSTRAINT
: "c"(ctxt->src2.val));
--- a/include/linux/objtool_types.h
+++ b/include/linux/objtool_types.h
@@ -64,5 +64,6 @@ struct unwind_hint {
#define ANNOTYPE_UNRET_BEGIN 5
#define ANNOTYPE_IGNORE_ALTS 6
#define ANNOTYPE_INTRA_FUNCTION_CALLS 7
+#define ANNOTYPE_JUMP_TABLE 8
#endif /* _LINUX_OBJTOOL_TYPES_H */
--- a/tools/include/linux/objtool_types.h
+++ b/tools/include/linux/objtool_types.h
@@ -64,5 +64,6 @@ struct unwind_hint {
#define ANNOTYPE_UNRET_BEGIN 5
#define ANNOTYPE_IGNORE_ALTS 6
#define ANNOTYPE_INTRA_FUNCTION_CALLS 7
+#define ANNOTYPE_JUMP_TABLE 8
#endif /* _LINUX_OBJTOOL_TYPES_H */
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -2386,6 +2386,14 @@ static int __annotate_late(struct objtoo
insn->unret = 1;
break;
+ /*
+ * Must be after add_jump_table(); for it doesn't set a sane
+ * _jump_table value.
+ */
+ case ANNOTYPE_JUMP_TABLE:
+ insn->_jump_table = (void *)1;
+ break;
+
default:
break;
}
@@ -3459,7 +3467,8 @@ static int validate_branch(struct objtoo
if (func && insn_func(insn) && func != insn_func(insn)->pfunc) {
/* Ignore KCFI type preambles, which always fall through */
if (!strncmp(func->name, "__cfi_", 6) ||
- !strncmp(func->name, "__pfx_", 6))
+ !strncmp(func->name, "__pfx_", 6) ||
+ !strcmp(insn_func(insn)->name, "fastop"))
return 0;
WARN("%s() falls through to next function %s()",
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 03/11] objtool: Convert ANNOTATE_RETPOLINE_SAFE to ANNOTATE
2023-12-04 9:37 ` [PATCH 03/11] objtool: Convert ANNOTATE_RETPOLINE_SAFE " Peter Zijlstra
@ 2023-12-06 23:31 ` Sean Christopherson
2024-09-13 20:47 ` James Houghton
0 siblings, 1 reply; 20+ messages in thread
From: Sean Christopherson @ 2023-12-06 23:31 UTC (permalink / raw)
To: Peter Zijlstra
Cc: Paolo Bonzini, Josh Poimboeuf, Thomas Gleixner, linux-kernel, x86,
kvm
On Mon, Dec 04, 2023, Peter Zijlstra wrote:
>
> --- a/arch/x86/include/asm/nospec-branch.h
> +++ b/arch/x86/include/asm/nospec-branch.h
> @@ -193,12 +193,7 @@
> * objtool the subsequent indirect jump/call is vouched safe for retpoline
> * builds.
> */
> -.macro ANNOTATE_RETPOLINE_SAFE
> -.Lhere_\@:
> - .pushsection .discard.retpoline_safe
> - .long .Lhere_\@
> - .popsection
> -.endm
> +#define ANNOTATE_RETPOLINE_SAFE ANNOTATE type=ANNOTYPE_RETPOLINE_SAFE
>
> /*
> * (ab)use RETPOLINE_SAFE on RET to annotate away 'bare' RET instructions
> @@ -317,11 +312,7 @@
>
> #else /* __ASSEMBLY__ */
>
> -#define ANNOTATE_RETPOLINE_SAFE \
> - "999:\n\t" \
> - ".pushsection .discard.retpoline_safe\n\t" \
> - ".long 999b\n\t" \
> - ".popsection\n\t"
> +#define ANNOTATE_RETPOLINE_SAFE ASM_ANNOTATE(ANNOTYPE_RETPOLINE_SAFE)
This fails for some of my builds that end up with CONFIG_OBJTOOl=n. Adding a
stub for ASM_ANNOTATE() gets me past that:
@@ -156,6 +171,7 @@
#define STACK_FRAME_NON_STANDARD(func)
#define STACK_FRAME_NON_STANDARD_FP(func)
#define ANNOTATE_NOENDBR
+#define ASM_ANNOTATE(x)
#define ASM_REACHABLE
#else
#define ANNOTATE_INTRA_FUNCTION_CALL
but then I run into other issues:
arch/x86/kernel/relocate_kernel_32.S: Assembler messages:
arch/x86/kernel/relocate_kernel_32.S:96: Error: Parameter named `type' does not exist for macro `annotate'
arch/x86/kernel/relocate_kernel_32.S:166: Error: Parameter named `type' does not exist for macro `annotate'
arch/x86/kernel/relocate_kernel_32.S:174: Error: Parameter named `type' does not exist for macro `annotate'
arch/x86/kernel/relocate_kernel_32.S:200: Error: Parameter named `type' does not exist for macro `annotate'
arch/x86/kernel/relocate_kernel_32.S:220: Error: Parameter named `type' does not exist for macro `annotate'
arch/x86/kernel/relocate_kernel_32.S:285: Error: Parameter named `type' does not exist for macro `annotate'
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 03/11] objtool: Convert ANNOTATE_RETPOLINE_SAFE to ANNOTATE
2023-12-06 23:31 ` Sean Christopherson
@ 2024-09-13 20:47 ` James Houghton
2024-10-30 20:08 ` James Houghton
0 siblings, 1 reply; 20+ messages in thread
From: James Houghton @ 2024-09-13 20:47 UTC (permalink / raw)
To: peterz; +Cc: seanjc, jpoimboe, kvm, linux-kernel, pbonzini, tglx, x86
Hi Peter,
On Wed, 6 Dec 2023, Sean Christopherson wrote:
> On Mon, Dec 04, 2023, Peter Zijlstra wrote:
> >
> > --- a/arch/x86/include/asm/nospec-branch.h
> > +++ b/arch/x86/include/asm/nospec-branch.h
> > @@ -193,12 +193,7 @@
> > * objtool the subsequent indirect jump/call is vouched safe for retpoline
> > * builds.
> > */
> > -.macro ANNOTATE_RETPOLINE_SAFE
> > -.Lhere_\@:
> > - .pushsection .discard.retpoline_safe
> > - .long .Lhere_\@
> > - .popsection
> > -.endm
> > +#define ANNOTATE_RETPOLINE_SAFE ANNOTATE type=ANNOTYPE_RETPOLINE_SAFE
> >
> > /*
> > * (ab)use RETPOLINE_SAFE on RET to annotate away 'bare' RET instructions
> > @@ -317,11 +312,7 @@
> >
> > #else /* __ASSEMBLY__ */
> >
> > -#define ANNOTATE_RETPOLINE_SAFE \
> > - "999:\n\t" \
> > - ".pushsection .discard.retpoline_safe\n\t" \
> > - ".long 999b\n\t" \
> > - ".popsection\n\t"
> > +#define ANNOTATE_RETPOLINE_SAFE ASM_ANNOTATE(ANNOTYPE_RETPOLINE_SAFE)
>
> This fails for some of my builds that end up with CONFIG_OBJTOOl=n. Adding a
> stub for ASM_ANNOTATE() gets me past that:
>
> @@ -156,6 +171,7 @@
> #define STACK_FRAME_NON_STANDARD(func)
> #define STACK_FRAME_NON_STANDARD_FP(func)
> #define ANNOTATE_NOENDBR
> +#define ASM_ANNOTATE(x)
> #define ASM_REACHABLE
> #else
> #define ANNOTATE_INTRA_FUNCTION_CALL
>
> but then I run into other issues:
>
> arch/x86/kernel/relocate_kernel_32.S: Assembler messages:
> arch/x86/kernel/relocate_kernel_32.S:96: Error: Parameter named `type' does not exist for macro `annotate'
> arch/x86/kernel/relocate_kernel_32.S:166: Error: Parameter named `type' does not exist for macro `annotate'
> arch/x86/kernel/relocate_kernel_32.S:174: Error: Parameter named `type' does not exist for macro `annotate'
> arch/x86/kernel/relocate_kernel_32.S:200: Error: Parameter named `type' does not exist for macro `annotate'
> arch/x86/kernel/relocate_kernel_32.S:220: Error: Parameter named `type' does not exist for macro `annotate'
> arch/x86/kernel/relocate_kernel_32.S:285: Error: Parameter named `type' does not exist for macro `annotate'
Sean pointed me at this series recently. It seems like these compile errors
(and some others) go away with the following diff:
diff --git a/arch/x86/include/asm/nospec-branch.h b/arch/x86/include/asm/nospec-branch.h
index 0bebdcad7ba1..036ab199859a 100644
--- a/arch/x86/include/asm/nospec-branch.h
+++ b/arch/x86/include/asm/nospec-branch.h
@@ -489,7 +489,7 @@ static inline void call_depth_return_thunk(void) {}
" .align 16\n" \
"903: lea 4(%%esp), %%esp;\n" \
" pushl %[thunk_target];\n" \
- " ret;\n" \
+ " ret;\n", \
X86_FEATURE_RETPOLINE, \
"lfence;\n" \
ANNOTATE_RETPOLINE_SAFE \
diff --git a/include/linux/objtool.h b/include/linux/objtool.h
index f6f80bfefe3b..e811b2ff3a9c 100644
--- a/include/linux/objtool.h
+++ b/include/linux/objtool.h
@@ -159,6 +159,7 @@
#define STACK_FRAME_NON_STANDARD_FP(func)
#define ANNOTATE_NOENDBR
#define ASM_REACHABLE
+#define ASM_ANNOTATE(x)
#else
#define ANNOTATE_INTRA_FUNCTION_CALL
.macro UNWIND_HINT type:req sp_reg=0 sp_offset=0 signal=0
@@ -169,7 +170,7 @@
.endm
.macro REACHABLE
.endm
-.macro ANNOTATE
+.macro ANNOTATE type:req
.endm
#endif
This series applies on top of the latest kvm-x86/next with only a few trivial
conflicts, so I hope you are able to send a new version.
I could send one for you, but I have no idea how to properly test it.
^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH 03/11] objtool: Convert ANNOTATE_RETPOLINE_SAFE to ANNOTATE
2024-09-13 20:47 ` James Houghton
@ 2024-10-30 20:08 ` James Houghton
2024-11-06 17:42 ` Peter Zijlstra
0 siblings, 1 reply; 20+ messages in thread
From: James Houghton @ 2024-10-30 20:08 UTC (permalink / raw)
To: peterz; +Cc: seanjc, jpoimboe, kvm, linux-kernel, pbonzini, tglx, x86
On Fri, Sep 13, 2024 at 1:47 PM James Houghton <jthoughton@google.com> wrote:
>
> On Wed, 6 Dec 2023, Sean Christopherson wrote:
> > On Mon, Dec 04, 2023, Peter Zijlstra wrote:
> > >
> > > --- a/arch/x86/include/asm/nospec-branch.h
> > > +++ b/arch/x86/include/asm/nospec-branch.h
> > > @@ -193,12 +193,7 @@
> > > * objtool the subsequent indirect jump/call is vouched safe for retpoline
> > > * builds.
> > > */
> > > -.macro ANNOTATE_RETPOLINE_SAFE
> > > -.Lhere_\@:
> > > - .pushsection .discard.retpoline_safe
> > > - .long .Lhere_\@
> > > - .popsection
> > > -.endm
> > > +#define ANNOTATE_RETPOLINE_SAFE ANNOTATE type=ANNOTYPE_RETPOLINE_SAFE
> > >
> > > /*
> > > * (ab)use RETPOLINE_SAFE on RET to annotate away 'bare' RET instructions
> > > @@ -317,11 +312,7 @@
> > >
> > > #else /* __ASSEMBLY__ */
> > >
> > > -#define ANNOTATE_RETPOLINE_SAFE \
> > > - "999:\n\t" \
> > > - ".pushsection .discard.retpoline_safe\n\t" \
> > > - ".long 999b\n\t" \
> > > - ".popsection\n\t"
> > > +#define ANNOTATE_RETPOLINE_SAFE ASM_ANNOTATE(ANNOTYPE_RETPOLINE_SAFE)
> >
> > This fails for some of my builds that end up with CONFIG_OBJTOOl=n. Adding a
> > stub for ASM_ANNOTATE() gets me past that:
> >
> > @@ -156,6 +171,7 @@
> > #define STACK_FRAME_NON_STANDARD(func)
> > #define STACK_FRAME_NON_STANDARD_FP(func)
> > #define ANNOTATE_NOENDBR
> > +#define ASM_ANNOTATE(x)
> > #define ASM_REACHABLE
> > #else
> > #define ANNOTATE_INTRA_FUNCTION_CALL
> >
> > but then I run into other issues:
> >
> > arch/x86/kernel/relocate_kernel_32.S: Assembler messages:
> > arch/x86/kernel/relocate_kernel_32.S:96: Error: Parameter named `type' does not exist for macro `annotate'
> > arch/x86/kernel/relocate_kernel_32.S:166: Error: Parameter named `type' does not exist for macro `annotate'
> > arch/x86/kernel/relocate_kernel_32.S:174: Error: Parameter named `type' does not exist for macro `annotate'
> > arch/x86/kernel/relocate_kernel_32.S:200: Error: Parameter named `type' does not exist for macro `annotate'
> > arch/x86/kernel/relocate_kernel_32.S:220: Error: Parameter named `type' does not exist for macro `annotate'
> > arch/x86/kernel/relocate_kernel_32.S:285: Error: Parameter named `type' does not exist for macro `annotate'
>
> Sean pointed me at this series recently. It seems like these compile errors
> (and some others) go away with the following diff:
>
> diff --git a/arch/x86/include/asm/nospec-branch.h b/arch/x86/include/asm/nospec-branch.h
> index 0bebdcad7ba1..036ab199859a 100644
> --- a/arch/x86/include/asm/nospec-branch.h
> +++ b/arch/x86/include/asm/nospec-branch.h
> @@ -489,7 +489,7 @@ static inline void call_depth_return_thunk(void) {}
> " .align 16\n" \
> "903: lea 4(%%esp), %%esp;\n" \
> " pushl %[thunk_target];\n" \
> - " ret;\n" \
> + " ret;\n", \
> X86_FEATURE_RETPOLINE, \
> "lfence;\n" \
> ANNOTATE_RETPOLINE_SAFE \
> diff --git a/include/linux/objtool.h b/include/linux/objtool.h
> index f6f80bfefe3b..e811b2ff3a9c 100644
> --- a/include/linux/objtool.h
> +++ b/include/linux/objtool.h
> @@ -159,6 +159,7 @@
> #define STACK_FRAME_NON_STANDARD_FP(func)
> #define ANNOTATE_NOENDBR
> #define ASM_REACHABLE
> +#define ASM_ANNOTATE(x)
> #else
> #define ANNOTATE_INTRA_FUNCTION_CALL
> .macro UNWIND_HINT type:req sp_reg=0 sp_offset=0 signal=0
> @@ -169,7 +170,7 @@
> .endm
> .macro REACHABLE
> .endm
> -.macro ANNOTATE
> +.macro ANNOTATE type:req
> .endm
> #endif
>
> This series applies on top of the latest kvm-x86/next with only a few trivial
> conflicts, so I hope you are able to send a new version.
>
> I could send one for you, but I have no idea how to properly test it.
Hi Peter,
I'll go ahead and repost this series soon unless you tell me otherwise. :)
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 03/11] objtool: Convert ANNOTATE_RETPOLINE_SAFE to ANNOTATE
2024-10-30 20:08 ` James Houghton
@ 2024-11-06 17:42 ` Peter Zijlstra
0 siblings, 0 replies; 20+ messages in thread
From: Peter Zijlstra @ 2024-11-06 17:42 UTC (permalink / raw)
To: James Houghton; +Cc: seanjc, jpoimboe, kvm, linux-kernel, pbonzini, tglx, x86
On Wed, Oct 30, 2024 at 01:08:28PM -0700, James Houghton wrote:
> Hi Peter,
>
> I'll go ahead and repost this series soon unless you tell me otherwise. :)
Thanks for your persistent poking. I've refreshed the queue:x86/kvm
branch, and provided the robots don't scream, I'll go and post it.
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 01/11] objtool: Generic annotation infrastructure
2023-12-04 9:37 ` [PATCH 01/11] objtool: Generic annotation infrastructure Peter Zijlstra
@ 2024-11-08 14:16 ` Peter Zijlstra
2024-11-08 14:57 ` Nathan Chancellor
2024-11-08 19:03 ` Peter Zijlstra
0 siblings, 2 replies; 20+ messages in thread
From: Peter Zijlstra @ 2024-11-08 14:16 UTC (permalink / raw)
To: Sean Christopherson, Paolo Bonzini, Josh Poimboeuf,
Thomas Gleixner
Cc: linux-kernel, x86, kvm, nathan, ndesaulniers, morbo, justinstitt,
llvm
On Mon, Dec 04, 2023 at 10:37:03AM +0100, Peter Zijlstra wrote:
> Avoid endless .discard.foo sections for each annotation, create a
> single .discard.annotate section that takes an annotation type along
> with the instruction.
>
> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
> ---
> --- a/include/linux/objtool.h
> +++ b/include/linux/objtool.h
> @@ -57,6 +57,13 @@
> ".long 998b\n\t" \
> ".popsection\n\t"
>
> +#define ASM_ANNOTATE(x) \
> + "911:\n\t" \
> + ".pushsection .discard.annotate,\"M\",@progbits,8\n\t" \
> + ".long 911b - .\n\t" \
> + ".long " __stringify(x) "\n\t" \
> + ".popsection\n\t"
> +
> #else /* __ASSEMBLY__ */
>
> /*
> @@ -146,6 +153,14 @@
> .popsection
> .endm
>
> +.macro ANNOTATE type:req
> +.Lhere_\@:
> + .pushsection .discard.annotate,"M",@progbits,8
> + .long .Lhere_\@ - .
> + .long \type
> + .popsection
> +.endm
> +
> #endif /* __ASSEMBLY__ */
>
> #else /* !CONFIG_OBJTOOL */
> @@ -167,6 +182,8 @@
> .endm
> .macro REACHABLE
> .endm
> +.macro ANNOTATE
> +.endm
> #endif
>
> #endif /* CONFIG_OBJTOOL */
> --- a/tools/objtool/check.c
> +++ b/tools/objtool/check.c
> @@ -2308,6 +2308,41 @@ static int read_unwind_hints(struct objt
> return 0;
> }
>
> +static int read_annotate(struct objtool_file *file, void (*func)(int type, struct instruction *insn))
> +{
> + struct section *rsec, *sec;
> + struct instruction *insn;
> + struct reloc *reloc;
> + int type;
> +
> + rsec = find_section_by_name(file->elf, ".rela.discard.annotate");
> + if (!rsec)
> + return 0;
> +
> + sec = find_section_by_name(file->elf, ".discard.annotate");
> + if (!sec)
> + return 0;
> +
> + for_each_reloc(rsec, reloc) {
> + insn = find_insn(file, reloc->sym->sec,
> + reloc->sym->offset + reloc_addend(reloc));
> + if (!insn) {
> + WARN("bad .discard.annotate entry: %d", reloc_idx(reloc));
> + return -1;
> + }
> +
> + type = *(u32 *)(sec->data->d_buf + (reloc_idx(reloc) * sec->sh.sh_entsize) + 4);
> +
> + func(type, insn);
> + }
> +
> + return 0;
> +}
So... ld.lld hates this :-(
From an LLVM=-19 build we can see that:
$ readelf -WS tmp-build/arch/x86/kvm/vmx/vmenter.o | grep annotate
[13] .discard.annotate PROGBITS 0000000000000000 00028c 000018 08 M 0 0 1
$ readelf -WS tmp-build/arch/x86/kvm/kvm-intel.o | grep annotate
[ 3] .discard.annotate PROGBITS 0000000000000000 069fe0 0089d0 00 M 0 0 1
Which tells us that the translation unit itself has a sh_entsize of 8,
while the linked object has sh_entsize of 0.
This then completely messes up the indexing objtool does, which relies
on it being a sane number.
GCC/binutils very much does not do this, it retains the 8.
Dear clang folks, help?
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 01/11] objtool: Generic annotation infrastructure
2024-11-08 14:16 ` Peter Zijlstra
@ 2024-11-08 14:57 ` Nathan Chancellor
2024-11-08 15:13 ` Peter Zijlstra
2024-11-08 19:03 ` Peter Zijlstra
1 sibling, 1 reply; 20+ messages in thread
From: Nathan Chancellor @ 2024-11-08 14:57 UTC (permalink / raw)
To: Peter Zijlstra, Fangrui Song
Cc: Sean Christopherson, Paolo Bonzini, Josh Poimboeuf,
Thomas Gleixner, linux-kernel, x86, kvm, ndesaulniers, morbo,
justinstitt, llvm
On Fri, Nov 08, 2024 at 03:16:00PM +0100, Peter Zijlstra wrote:
> On Mon, Dec 04, 2023 at 10:37:03AM +0100, Peter Zijlstra wrote:
> > Avoid endless .discard.foo sections for each annotation, create a
> > single .discard.annotate section that takes an annotation type along
> > with the instruction.
> >
> > Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
> > ---
> > --- a/include/linux/objtool.h
> > +++ b/include/linux/objtool.h
> > @@ -57,6 +57,13 @@
> > ".long 998b\n\t" \
> > ".popsection\n\t"
> >
> > +#define ASM_ANNOTATE(x) \
> > + "911:\n\t" \
> > + ".pushsection .discard.annotate,\"M\",@progbits,8\n\t" \
> > + ".long 911b - .\n\t" \
> > + ".long " __stringify(x) "\n\t" \
> > + ".popsection\n\t"
> > +
> > #else /* __ASSEMBLY__ */
> >
> > /*
> > @@ -146,6 +153,14 @@
> > .popsection
> > .endm
> >
> > +.macro ANNOTATE type:req
> > +.Lhere_\@:
> > + .pushsection .discard.annotate,"M",@progbits,8
> > + .long .Lhere_\@ - .
> > + .long \type
> > + .popsection
> > +.endm
> > +
> > #endif /* __ASSEMBLY__ */
> >
> > #else /* !CONFIG_OBJTOOL */
> > @@ -167,6 +182,8 @@
> > .endm
> > .macro REACHABLE
> > .endm
> > +.macro ANNOTATE
> > +.endm
> > #endif
> >
> > #endif /* CONFIG_OBJTOOL */
> > --- a/tools/objtool/check.c
> > +++ b/tools/objtool/check.c
> > @@ -2308,6 +2308,41 @@ static int read_unwind_hints(struct objt
> > return 0;
> > }
> >
> > +static int read_annotate(struct objtool_file *file, void (*func)(int type, struct instruction *insn))
> > +{
> > + struct section *rsec, *sec;
> > + struct instruction *insn;
> > + struct reloc *reloc;
> > + int type;
> > +
> > + rsec = find_section_by_name(file->elf, ".rela.discard.annotate");
> > + if (!rsec)
> > + return 0;
> > +
> > + sec = find_section_by_name(file->elf, ".discard.annotate");
> > + if (!sec)
> > + return 0;
> > +
> > + for_each_reloc(rsec, reloc) {
> > + insn = find_insn(file, reloc->sym->sec,
> > + reloc->sym->offset + reloc_addend(reloc));
> > + if (!insn) {
> > + WARN("bad .discard.annotate entry: %d", reloc_idx(reloc));
> > + return -1;
> > + }
> > +
> > + type = *(u32 *)(sec->data->d_buf + (reloc_idx(reloc) * sec->sh.sh_entsize) + 4);
> > +
> > + func(type, insn);
> > + }
> > +
> > + return 0;
> > +}
>
> So... ld.lld hates this :-(
>
> From an LLVM=-19 build we can see that:
>
> $ readelf -WS tmp-build/arch/x86/kvm/vmx/vmenter.o | grep annotate
> [13] .discard.annotate PROGBITS 0000000000000000 00028c 000018 08 M 0 0 1
>
> $ readelf -WS tmp-build/arch/x86/kvm/kvm-intel.o | grep annotate
> [ 3] .discard.annotate PROGBITS 0000000000000000 069fe0 0089d0 00 M 0 0 1
>
> Which tells us that the translation unit itself has a sh_entsize of 8,
> while the linked object has sh_entsize of 0.
>
> This then completely messes up the indexing objtool does, which relies
> on it being a sane number.
>
> GCC/binutils very much does not do this, it retains the 8.
>
> Dear clang folks, help?
Perhaps Fangrui has immediate thoughts, since this appears to be an
ld.lld thing? Otherwise, I will see if I can dig into this in the next
couple of weeks (I have an LF webinar on Wednesday that I am still
prepping for). Is this reproducible with just defconfig or something
else?
Cheers,
Nathan
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 01/11] objtool: Generic annotation infrastructure
2024-11-08 14:57 ` Nathan Chancellor
@ 2024-11-08 15:13 ` Peter Zijlstra
0 siblings, 0 replies; 20+ messages in thread
From: Peter Zijlstra @ 2024-11-08 15:13 UTC (permalink / raw)
To: Nathan Chancellor
Cc: Fangrui Song, Sean Christopherson, Paolo Bonzini, Josh Poimboeuf,
Thomas Gleixner, linux-kernel, x86, kvm, ndesaulniers, morbo,
justinstitt, llvm
On Fri, Nov 08, 2024 at 07:57:16AM -0700, Nathan Chancellor wrote:
> On Fri, Nov 08, 2024 at 03:16:00PM +0100, Peter Zijlstra wrote:
> > On Mon, Dec 04, 2023 at 10:37:03AM +0100, Peter Zijlstra wrote:
> > > Avoid endless .discard.foo sections for each annotation, create a
> > > single .discard.annotate section that takes an annotation type along
> > > with the instruction.
> > >
> > > Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
> > > ---
> > > --- a/include/linux/objtool.h
> > > +++ b/include/linux/objtool.h
> > > @@ -57,6 +57,13 @@
> > > ".long 998b\n\t" \
> > > ".popsection\n\t"
> > >
> > > +#define ASM_ANNOTATE(x) \
> > > + "911:\n\t" \
> > > + ".pushsection .discard.annotate,\"M\",@progbits,8\n\t" \
> > > + ".long 911b - .\n\t" \
> > > + ".long " __stringify(x) "\n\t" \
> > > + ".popsection\n\t"
> > > +
> > > #else /* __ASSEMBLY__ */
> > >
> > > /*
> > > @@ -146,6 +153,14 @@
> > > .popsection
> > > .endm
> > >
> > > +.macro ANNOTATE type:req
> > > +.Lhere_\@:
> > > + .pushsection .discard.annotate,"M",@progbits,8
> > > + .long .Lhere_\@ - .
> > > + .long \type
> > > + .popsection
> > > +.endm
> > > +
> > > #endif /* __ASSEMBLY__ */
> > >
> > > #else /* !CONFIG_OBJTOOL */
> > > @@ -167,6 +182,8 @@
> > > .endm
> > > .macro REACHABLE
> > > .endm
> > > +.macro ANNOTATE
> > > +.endm
> > > #endif
> > >
> > > #endif /* CONFIG_OBJTOOL */
> > > --- a/tools/objtool/check.c
> > > +++ b/tools/objtool/check.c
> > > @@ -2308,6 +2308,41 @@ static int read_unwind_hints(struct objt
> > > return 0;
> > > }
> > >
> > > +static int read_annotate(struct objtool_file *file, void (*func)(int type, struct instruction *insn))
> > > +{
> > > + struct section *rsec, *sec;
> > > + struct instruction *insn;
> > > + struct reloc *reloc;
> > > + int type;
> > > +
> > > + rsec = find_section_by_name(file->elf, ".rela.discard.annotate");
> > > + if (!rsec)
> > > + return 0;
> > > +
> > > + sec = find_section_by_name(file->elf, ".discard.annotate");
> > > + if (!sec)
> > > + return 0;
> > > +
> > > + for_each_reloc(rsec, reloc) {
> > > + insn = find_insn(file, reloc->sym->sec,
> > > + reloc->sym->offset + reloc_addend(reloc));
> > > + if (!insn) {
> > > + WARN("bad .discard.annotate entry: %d", reloc_idx(reloc));
> > > + return -1;
> > > + }
> > > +
> > > + type = *(u32 *)(sec->data->d_buf + (reloc_idx(reloc) * sec->sh.sh_entsize) + 4);
> > > +
> > > + func(type, insn);
> > > + }
> > > +
> > > + return 0;
> > > +}
> >
> > So... ld.lld hates this :-(
> >
> > From an LLVM=-19 build we can see that:
> >
> > $ readelf -WS tmp-build/arch/x86/kvm/vmx/vmenter.o | grep annotate
> > [13] .discard.annotate PROGBITS 0000000000000000 00028c 000018 08 M 0 0 1
> >
> > $ readelf -WS tmp-build/arch/x86/kvm/kvm-intel.o | grep annotate
> > [ 3] .discard.annotate PROGBITS 0000000000000000 069fe0 0089d0 00 M 0 0 1
> >
> > Which tells us that the translation unit itself has a sh_entsize of 8,
> > while the linked object has sh_entsize of 0.
> >
> > This then completely messes up the indexing objtool does, which relies
> > on it being a sane number.
> >
> > GCC/binutils very much does not do this, it retains the 8.
> >
> > Dear clang folks, help?
>
> Perhaps Fangrui has immediate thoughts, since this appears to be an
> ld.lld thing? Otherwise, I will see if I can dig into this in the next
> couple of weeks (I have an LF webinar on Wednesday that I am still
> prepping for). Is this reproducible with just defconfig or something
> else?
I took the .config from the report you pointed me at yesterday.
https://lore.kernel.org/202411071743.HZsCuurm-lkp@intel.com/
And specifically the kvm build targets from:
$ make O=tmp-build/ LLVM=-19 arch/x86/kvm/
show this problem.
I just ran a defconfig, and that seems to behave properly. Notably,
vmlinux.o (definitely a link target) has entsize=8 for the relevant
section.
I'm not sure how the kvm targets might be 'special'.
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 01/11] objtool: Generic annotation infrastructure
2024-11-08 14:16 ` Peter Zijlstra
2024-11-08 14:57 ` Nathan Chancellor
@ 2024-11-08 19:03 ` Peter Zijlstra
1 sibling, 0 replies; 20+ messages in thread
From: Peter Zijlstra @ 2024-11-08 19:03 UTC (permalink / raw)
To: Sean Christopherson, Paolo Bonzini, Josh Poimboeuf,
Thomas Gleixner
Cc: linux-kernel, x86, kvm, nathan, ndesaulniers, morbo, justinstitt,
llvm
On Fri, Nov 08, 2024 at 03:16:00PM +0100, Peter Zijlstra wrote:
> From an LLVM=-19 build we can see that:
>
> $ readelf -WS tmp-build/arch/x86/kvm/vmx/vmenter.o | grep annotate
> [13] .discard.annotate PROGBITS 0000000000000000 00028c 000018 08 M 0 0 1
>
> $ readelf -WS tmp-build/arch/x86/kvm/kvm-intel.o | grep annotate
> [ 3] .discard.annotate PROGBITS 0000000000000000 069fe0 0089d0 00 M 0 0 1
>
> Which tells us that the translation unit itself has a sh_entsize of 8,
> while the linked object has sh_entsize of 0.
>
> This then completely messes up the indexing objtool does, which relies
> on it being a sane number.
>
> GCC/binutils very much does not do this, it retains the 8.
Anyway, for now I've added:
+ if (sec->sh.sh_entsize != 8) {
+ static bool warn = false;
+ if (!warn) {
+ WARN("%s: dodgy linker, sh_entsize != 8", sec->name);
+ warn = true;
+ }
+ sec->sh.sh_entsize = 8;
+ }
To objtool, this allows it function correctly and prints this reminder
to for us to figure out the linker story.
^ permalink raw reply [flat|nested] 20+ messages in thread
end of thread, other threads:[~2024-11-08 19:03 UTC | newest]
Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-12-04 9:37 [PATCH 00/11] x86/kvm/emulate: Avoid RET for FASTOPs Peter Zijlstra
2023-12-04 9:37 ` [PATCH 01/11] objtool: Generic annotation infrastructure Peter Zijlstra
2024-11-08 14:16 ` Peter Zijlstra
2024-11-08 14:57 ` Nathan Chancellor
2024-11-08 15:13 ` Peter Zijlstra
2024-11-08 19:03 ` Peter Zijlstra
2023-12-04 9:37 ` [PATCH 02/11] objtool: Convert ANNOTATE_NOENDBR to ANNOTATE Peter Zijlstra
2023-12-04 9:37 ` [PATCH 03/11] objtool: Convert ANNOTATE_RETPOLINE_SAFE " Peter Zijlstra
2023-12-06 23:31 ` Sean Christopherson
2024-09-13 20:47 ` James Houghton
2024-10-30 20:08 ` James Houghton
2024-11-06 17:42 ` Peter Zijlstra
2023-12-04 9:37 ` [PATCH 04/11] objtool: Convert instrumentation_{begin,end}() " Peter Zijlstra
2023-12-04 9:37 ` [PATCH 05/11] objtool: Convert VALIDATE_UNRET_BEGIN " Peter Zijlstra
2023-12-04 9:37 ` [PATCH 06/11] objtool: Convert ANNOTATE_IGNORE_ALTERNATIVE " Peter Zijlstra
2023-12-04 9:37 ` [PATCH 07/11] objtool: Convert ANNOTATE_INTRA_FUNCTION_CALLS " Peter Zijlstra
2023-12-04 9:37 ` [PATCH 08/11] objtool: Collapse annotate sequences Peter Zijlstra
2023-12-04 9:37 ` [PATCH 09/11] x86/kvm/emulate: Implement test_cc() in C Peter Zijlstra
2023-12-04 9:37 ` [PATCH 10/11] x86/nospec: JMP_NOSPEC Peter Zijlstra
2023-12-04 9:37 ` [PATCH 11/11] x86/kvm/emulate: Avoid RET for fastops Peter Zijlstra
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox