* [PATCH 0/8] objtool, x86/alternative: Convert objtool annotations and x86 alternatives to assembler macros
@ 2025-12-06 21:41 Josh Poimboeuf
2025-12-06 21:41 ` [PATCH 1/8] objtool: Rename ANNOTYPE_IGNORE_ALTS -> ANNOTYPE_IGNORE_ALTERNATIVE Josh Poimboeuf
` (8 more replies)
0 siblings, 9 replies; 20+ messages in thread
From: Josh Poimboeuf @ 2025-12-06 21:41 UTC (permalink / raw)
To: x86
Cc: linux-kernel, Linus Torvalds, Ingo Molnar, Peter Zijlstra,
Borislav Petkov, Thomas Gleixner
Convert objtool annotations and x86 alternatives to assembler macros.
This creates a shared C/asm alternative implementation and makes the
code generation significantly more readable.
Patches 1-5: convert objtool
Patches 6-8: convert alternatives
Based on tip/master.
Before:
-----
# ./arch/x86/include/asm/smap.h:47: alternative("", "stac", X86_FEATURE_SMAP);
# 47 "./arch/x86/include/asm/smap.h" 1
# ALT: oldinstr
771:
772:
# ALT: padding
.skip -(((775f-774f)-(772b-771b)) > 0) * ((775f-774f)-(772b-771b)),0x90
773:
.pushsection .altinstructions, "aM", @progbits, 14
.long 771b - .
.long 774f - .
.4byte ( 9*32+20)
.byte 773b-771b
.byte 775f-774f
.popsection
.pushsection .altinstr_replacement, "ax"
.pushsection .discard.annotate_data, "M", @progbits, 8; .long 1b - ., 1; .popsection
# ALT: replacement
774:
stac
775:
.popsection
-----
After:
-----
# ./arch/x86/include/asm/smap.h:47: alternative("", "stac", X86_FEATURE_SMAP);
# 47 "./arch/x86/include/asm/smap.h" 1
ALTERNATIVE "", "stac", "( 9*32+20)"
-----
Future work:
- BUG()/WARN()
- static_cpu_has()
- static calls/branches
- exceptions
- smp locks
- unwind hints
Josh Poimboeuf (8):
objtool: Rename ANNOTYPE_IGNORE_ALTS -> ANNOTYPE_IGNORE_ALTERNATIVE
objtool: Make ANNOTYPE_DATA_SPECIAL unique across all annotations
objtool: Rename C ANNOTATE_REACHABLE to ANNOTATE_REACHABLE_LABEL
objtool: Rename asm ANNOTATE_NOCFI_SYM to ANNOTATE_NOCFI
objtool: Convert annotations to assembler macros
x86/asm: Use unique code labels in __FILL_RETURN_BUFFER
x86/asm: Remove newlines in alternatives
x86/alternative: Convert alternatives to assembler macros
arch/x86/include/asm/alternative.h | 196 +++++++++++++-------------
arch/x86/include/asm/asm.h | 8 +-
arch/x86/include/asm/bug.h | 2 +-
arch/x86/include/asm/irq_stack.h | 2 +-
arch/x86/include/asm/jump_label.h | 1 +
arch/x86/include/asm/nospec-branch.h | 8 +-
arch/x86/include/asm/paravirt_types.h | 2 +-
arch/x86/include/asm/processor.h | 2 +-
arch/x86/include/asm/smap.h | 8 +-
arch/x86/include/asm/vmware.h | 2 +-
arch/x86/platform/efi/efi_stub_64.S | 2 +-
include/linux/annotate.h | 133 ++++++++---------
include/linux/objtool_types.h | 5 +-
tools/include/linux/objtool_types.h | 5 +-
tools/objtool/check.c | 4 +-
15 files changed, 196 insertions(+), 184 deletions(-)
--
2.52.0
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 1/8] objtool: Rename ANNOTYPE_IGNORE_ALTS -> ANNOTYPE_IGNORE_ALTERNATIVE
2025-12-06 21:41 [PATCH 0/8] objtool, x86/alternative: Convert objtool annotations and x86 alternatives to assembler macros Josh Poimboeuf
@ 2025-12-06 21:41 ` Josh Poimboeuf
2025-12-06 21:41 ` [PATCH 2/8] objtool: Make ANNOTYPE_DATA_SPECIAL unique across all annotations Josh Poimboeuf
` (7 subsequent siblings)
8 siblings, 0 replies; 20+ messages in thread
From: Josh Poimboeuf @ 2025-12-06 21:41 UTC (permalink / raw)
To: x86
Cc: linux-kernel, Linus Torvalds, Ingo Molnar, Peter Zijlstra,
Borislav Petkov, Thomas Gleixner
Rename ANNOTYPE_IGNORE_ALTS to ANNOTYPE_IGNORE_ALTERNATIVE for
consistency with its corresponding ANNOTATE_IGNORE_ALTERNATIVE macro.
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
include/linux/annotate.h | 4 ++--
include/linux/objtool_types.h | 2 +-
tools/include/linux/objtool_types.h | 2 +-
tools/objtool/check.c | 4 ++--
4 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/include/linux/annotate.h b/include/linux/annotate.h
index 2f1599c9e573..929f5c658a1d 100644
--- a/include/linux/annotate.h
+++ b/include/linux/annotate.h
@@ -75,7 +75,7 @@
* objtool annotation to ignore the alternatives and only consider the original
* instruction(s).
*/
-#define ANNOTATE_IGNORE_ALTERNATIVE ASM_ANNOTATE(ANNOTYPE_IGNORE_ALTS)
+#define ANNOTATE_IGNORE_ALTERNATIVE ASM_ANNOTATE(ANNOTYPE_IGNORE_ALTERNATIVE)
/*
* This macro indicates that the following intra-function call is valid.
* Any non-annotated intra-function call will cause objtool to issue a warning.
@@ -116,7 +116,7 @@
#define ANNOTATE_RETPOLINE_SAFE ANNOTATE type=ANNOTYPE_RETPOLINE_SAFE
/* ANNOTATE_INSTR_BEGIN ANNOTATE type=ANNOTYPE_INSTR_BEGIN */
/* ANNOTATE_INSTR_END ANNOTATE type=ANNOTYPE_INSTR_END */
-#define ANNOTATE_IGNORE_ALTERNATIVE ANNOTATE type=ANNOTYPE_IGNORE_ALTS
+#define ANNOTATE_IGNORE_ALTERNATIVE ANNOTATE type=ANNOTYPE_IGNORE_ALTERNATIVE
#define ANNOTATE_INTRA_FUNCTION_CALL ANNOTATE type=ANNOTYPE_INTRA_FUNCTION_CALL
#define ANNOTATE_UNRET_BEGIN ANNOTATE type=ANNOTYPE_UNRET_BEGIN
#define ANNOTATE_REACHABLE ANNOTATE type=ANNOTYPE_REACHABLE
diff --git a/include/linux/objtool_types.h b/include/linux/objtool_types.h
index c6def4049b1a..e740002018c0 100644
--- a/include/linux/objtool_types.h
+++ b/include/linux/objtool_types.h
@@ -62,7 +62,7 @@ struct unwind_hint {
#define ANNOTYPE_INSTR_BEGIN 3
#define ANNOTYPE_INSTR_END 4
#define ANNOTYPE_UNRET_BEGIN 5
-#define ANNOTYPE_IGNORE_ALTS 6
+#define ANNOTYPE_IGNORE_ALTERNATIVE 6
#define ANNOTYPE_INTRA_FUNCTION_CALL 7
#define ANNOTYPE_REACHABLE 8
#define ANNOTYPE_NOCFI 9
diff --git a/tools/include/linux/objtool_types.h b/tools/include/linux/objtool_types.h
index c6def4049b1a..e740002018c0 100644
--- a/tools/include/linux/objtool_types.h
+++ b/tools/include/linux/objtool_types.h
@@ -62,7 +62,7 @@ struct unwind_hint {
#define ANNOTYPE_INSTR_BEGIN 3
#define ANNOTYPE_INSTR_END 4
#define ANNOTYPE_UNRET_BEGIN 5
-#define ANNOTYPE_IGNORE_ALTS 6
+#define ANNOTYPE_IGNORE_ALTERNATIVE 6
#define ANNOTYPE_INTRA_FUNCTION_CALL 7
#define ANNOTYPE_REACHABLE 8
#define ANNOTYPE_NOCFI 9
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index 3f7999317f4d..53af6887852a 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -2358,7 +2358,7 @@ static int __annotate_early(struct objtool_file *file, int type, struct instruct
switch (type) {
/* Must be before add_special_section_alts() */
- case ANNOTYPE_IGNORE_ALTS:
+ case ANNOTYPE_IGNORE_ALTERNATIVE:
insn->ignore_alts = true;
break;
@@ -2439,7 +2439,7 @@ static int __annotate_late(struct objtool_file *file, int type, struct instructi
insn->unret = 1;
break;
- case ANNOTYPE_IGNORE_ALTS:
+ case ANNOTYPE_IGNORE_ALTERNATIVE:
/* early */
break;
--
2.52.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 2/8] objtool: Make ANNOTYPE_DATA_SPECIAL unique across all annotations
2025-12-06 21:41 [PATCH 0/8] objtool, x86/alternative: Convert objtool annotations and x86 alternatives to assembler macros Josh Poimboeuf
2025-12-06 21:41 ` [PATCH 1/8] objtool: Rename ANNOTYPE_IGNORE_ALTS -> ANNOTYPE_IGNORE_ALTERNATIVE Josh Poimboeuf
@ 2025-12-06 21:41 ` Josh Poimboeuf
2025-12-06 21:41 ` [PATCH 3/8] objtool: Rename C ANNOTATE_REACHABLE to ANNOTATE_REACHABLE_LABEL Josh Poimboeuf
` (6 subsequent siblings)
8 siblings, 0 replies; 20+ messages in thread
From: Josh Poimboeuf @ 2025-12-06 21:41 UTC (permalink / raw)
To: x86
Cc: linux-kernel, Linus Torvalds, Ingo Molnar, Peter Zijlstra,
Borislav Petkov, Thomas Gleixner
While text annotations and data annotations are placed in separate
sections, their underlying format (and creation macros) are the same.
Use the same ANNOTYPE value space for both to reduce the possibility of
clashes.
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
include/linux/objtool_types.h | 3 +--
tools/include/linux/objtool_types.h | 3 +--
2 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/include/linux/objtool_types.h b/include/linux/objtool_types.h
index e740002018c0..0b55dc386b69 100644
--- a/include/linux/objtool_types.h
+++ b/include/linux/objtool_types.h
@@ -66,7 +66,6 @@ struct unwind_hint {
#define ANNOTYPE_INTRA_FUNCTION_CALL 7
#define ANNOTYPE_REACHABLE 8
#define ANNOTYPE_NOCFI 9
-
-#define ANNOTYPE_DATA_SPECIAL 1
+#define ANNOTYPE_DATA_SPECIAL 10
#endif /* _LINUX_OBJTOOL_TYPES_H */
diff --git a/tools/include/linux/objtool_types.h b/tools/include/linux/objtool_types.h
index e740002018c0..0b55dc386b69 100644
--- a/tools/include/linux/objtool_types.h
+++ b/tools/include/linux/objtool_types.h
@@ -66,7 +66,6 @@ struct unwind_hint {
#define ANNOTYPE_INTRA_FUNCTION_CALL 7
#define ANNOTYPE_REACHABLE 8
#define ANNOTYPE_NOCFI 9
-
-#define ANNOTYPE_DATA_SPECIAL 1
+#define ANNOTYPE_DATA_SPECIAL 10
#endif /* _LINUX_OBJTOOL_TYPES_H */
--
2.52.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 3/8] objtool: Rename C ANNOTATE_REACHABLE to ANNOTATE_REACHABLE_LABEL
2025-12-06 21:41 [PATCH 0/8] objtool, x86/alternative: Convert objtool annotations and x86 alternatives to assembler macros Josh Poimboeuf
2025-12-06 21:41 ` [PATCH 1/8] objtool: Rename ANNOTYPE_IGNORE_ALTS -> ANNOTYPE_IGNORE_ALTERNATIVE Josh Poimboeuf
2025-12-06 21:41 ` [PATCH 2/8] objtool: Make ANNOTYPE_DATA_SPECIAL unique across all annotations Josh Poimboeuf
@ 2025-12-06 21:41 ` Josh Poimboeuf
2025-12-06 21:41 ` [PATCH 4/8] objtool: Rename asm ANNOTATE_NOCFI_SYM to ANNOTATE_NOCFI Josh Poimboeuf
` (5 subsequent siblings)
8 siblings, 0 replies; 20+ messages in thread
From: Josh Poimboeuf @ 2025-12-06 21:41 UTC (permalink / raw)
To: x86
Cc: linux-kernel, Linus Torvalds, Ingo Molnar, Peter Zijlstra,
Borislav Petkov, Thomas Gleixner
Unlike the asm version, the C version of ANNOTATE_REACHABLE takes an
argument. Rename it to ANNOTATE_REACHABLE_LABEL accordingly.
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
arch/x86/include/asm/bug.h | 2 +-
arch/x86/include/asm/irq_stack.h | 2 +-
include/linux/annotate.h | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/arch/x86/include/asm/bug.h b/arch/x86/include/asm/bug.h
index ee23b98353d7..df170c2f1e24 100644
--- a/arch/x86/include/asm/bug.h
+++ b/arch/x86/include/asm/bug.h
@@ -125,7 +125,7 @@ do { \
* message out than not know about it.
*/
-#define ARCH_WARN_REACHABLE ANNOTATE_REACHABLE(1b)
+#define ARCH_WARN_REACHABLE ANNOTATE_REACHABLE_LABEL(1b)
#define __WARN_FLAGS(cond_str, flags) \
do { \
diff --git a/arch/x86/include/asm/irq_stack.h b/arch/x86/include/asm/irq_stack.h
index 8325b79f2ac6..af4b10de3f9c 100644
--- a/arch/x86/include/asm/irq_stack.h
+++ b/arch/x86/include/asm/irq_stack.h
@@ -101,7 +101,7 @@
#define ASM_CALL_ARG0 \
"1: call %c[__func] \n" \
- ANNOTATE_REACHABLE(1b) " \n"
+ ANNOTATE_REACHABLE_LABEL(1b) " \n"
#define ASM_CALL_ARG1 \
"movq %[arg1], %%rdi \n" \
diff --git a/include/linux/annotate.h b/include/linux/annotate.h
index 929f5c658a1d..0ece31a9b585 100644
--- a/include/linux/annotate.h
+++ b/include/linux/annotate.h
@@ -94,7 +94,7 @@
* terminating, like a noreturn CALL or UD2 when we know they are not -- eg
* WARN using UD2.
*/
-#define ANNOTATE_REACHABLE(label) ASM_ANNOTATE_LABEL(label, ANNOTYPE_REACHABLE)
+#define ANNOTATE_REACHABLE_LABEL(label) ASM_ANNOTATE_LABEL(label, ANNOTYPE_REACHABLE)
/*
* This should not be used; it annotates away CFI violations. There are a few
* valid use cases like kexec handover to the next kernel image, and there is
--
2.52.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 4/8] objtool: Rename asm ANNOTATE_NOCFI_SYM to ANNOTATE_NOCFI
2025-12-06 21:41 [PATCH 0/8] objtool, x86/alternative: Convert objtool annotations and x86 alternatives to assembler macros Josh Poimboeuf
` (2 preceding siblings ...)
2025-12-06 21:41 ` [PATCH 3/8] objtool: Rename C ANNOTATE_REACHABLE to ANNOTATE_REACHABLE_LABEL Josh Poimboeuf
@ 2025-12-06 21:41 ` Josh Poimboeuf
2025-12-06 21:41 ` [PATCH 5/8] objtool: Convert annotations to assembler macros Josh Poimboeuf
` (4 subsequent siblings)
8 siblings, 0 replies; 20+ messages in thread
From: Josh Poimboeuf @ 2025-12-06 21:41 UTC (permalink / raw)
To: x86
Cc: linux-kernel, Linus Torvalds, Ingo Molnar, Peter Zijlstra,
Borislav Petkov, Thomas Gleixner
Unlike the C version, the asm version of ANNOTATE_NOCFI_SYM doesn't take
an argument. Rename it to ANNOTATE_NOCFI accordingly.
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
arch/x86/platform/efi/efi_stub_64.S | 2 +-
include/linux/annotate.h | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/x86/platform/efi/efi_stub_64.S b/arch/x86/platform/efi/efi_stub_64.S
index f0a5fba0717e..5aac37d379ab 100644
--- a/arch/x86/platform/efi/efi_stub_64.S
+++ b/arch/x86/platform/efi/efi_stub_64.S
@@ -14,7 +14,7 @@ SYM_FUNC_START(__efi_call)
/*
* The EFI code doesn't have any CFI, annotate away the CFI violation.
*/
- ANNOTATE_NOCFI_SYM
+ ANNOTATE_NOCFI
pushq %rbp
movq %rsp, %rbp
and $~0xf, %rsp
diff --git a/include/linux/annotate.h b/include/linux/annotate.h
index 0ece31a9b585..1678410efa1b 100644
--- a/include/linux/annotate.h
+++ b/include/linux/annotate.h
@@ -120,7 +120,7 @@
#define ANNOTATE_INTRA_FUNCTION_CALL ANNOTATE type=ANNOTYPE_INTRA_FUNCTION_CALL
#define ANNOTATE_UNRET_BEGIN ANNOTATE type=ANNOTYPE_UNRET_BEGIN
#define ANNOTATE_REACHABLE ANNOTATE type=ANNOTYPE_REACHABLE
-#define ANNOTATE_NOCFI_SYM ANNOTATE type=ANNOTYPE_NOCFI
+#define ANNOTATE_NOCFI ANNOTATE type=ANNOTYPE_NOCFI
#define ANNOTATE_DATA_SPECIAL ANNOTATE_DATA type=ANNOTYPE_DATA_SPECIAL
#endif /* __ASSEMBLY__ */
--
2.52.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 5/8] objtool: Convert annotations to assembler macros
2025-12-06 21:41 [PATCH 0/8] objtool, x86/alternative: Convert objtool annotations and x86 alternatives to assembler macros Josh Poimboeuf
` (3 preceding siblings ...)
2025-12-06 21:41 ` [PATCH 4/8] objtool: Rename asm ANNOTATE_NOCFI_SYM to ANNOTATE_NOCFI Josh Poimboeuf
@ 2025-12-06 21:41 ` Josh Poimboeuf
2025-12-07 14:51 ` Josh Poimboeuf
2025-12-08 9:37 ` Peter Zijlstra
2025-12-06 21:41 ` [PATCH 6/8] x86/asm: Use unique code labels in __FILL_RETURN_BUFFER Josh Poimboeuf
` (3 subsequent siblings)
8 siblings, 2 replies; 20+ messages in thread
From: Josh Poimboeuf @ 2025-12-06 21:41 UTC (permalink / raw)
To: x86
Cc: linux-kernel, Linus Torvalds, Ingo Molnar, Peter Zijlstra,
Borislav Petkov, Thomas Gleixner
Improve code generation readability by converting the objtool
annotations into assembler macros which are created when annotate.h is
included.
Before:
.pushsection .discard.annotate_insn, "M", @progbits, 8; .long 1b - ., 8; .popsection
After:
ANNOTATE_REACHABLE loc=1b
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
arch/x86/include/asm/asm.h | 8 +-
arch/x86/include/asm/jump_label.h | 1 +
include/linux/annotate.h | 132 +++++++++++++++---------------
3 files changed, 72 insertions(+), 69 deletions(-)
diff --git a/arch/x86/include/asm/asm.h b/arch/x86/include/asm/asm.h
index 0e8c611bc9e2..770321c908e5 100644
--- a/arch/x86/include/asm/asm.h
+++ b/arch/x86/include/asm/asm.h
@@ -2,15 +2,15 @@
#ifndef _ASM_X86_ASM_H
#define _ASM_X86_ASM_H
-#include <linux/annotate.h>
-
#ifdef __ASSEMBLER__
+# define __ASM_C(a,b) a
# define __ASM_FORM(x, ...) x,## __VA_ARGS__
# define __ASM_FORM_RAW(x, ...) x,## __VA_ARGS__
# define __ASM_FORM_COMMA(x, ...) x,## __VA_ARGS__,
# define __ASM_REGPFX %
#else
#include <linux/stringify.h>
+# define __ASM_C(a,b) b
# define __ASM_FORM(x, ...) " " __stringify(x,##__VA_ARGS__) " "
# define __ASM_FORM_RAW(x, ...) __stringify(x,##__VA_ARGS__)
# define __ASM_FORM_COMMA(x, ...) " " __stringify(x,##__VA_ARGS__) ","
@@ -115,6 +115,10 @@
#endif
+#define DEFINE_MACRO(name) \
+ __ASM_C(DEFINE_ ## name, \
+ asm(__stringify(DEFINE_ ## name)))
+
#ifndef __ASSEMBLER__
static __always_inline __pure void *rip_rel_ptr(void *p)
{
diff --git a/arch/x86/include/asm/jump_label.h b/arch/x86/include/asm/jump_label.h
index 05b16299588d..d34a16a4d305 100644
--- a/arch/x86/include/asm/jump_label.h
+++ b/arch/x86/include/asm/jump_label.h
@@ -11,6 +11,7 @@
#include <linux/stringify.h>
#include <linux/types.h>
+#include <linux/annotate.h>
#define JUMP_TABLE_ENTRY(key, label) \
".pushsection __jump_table, \"aw\" \n\t" \
diff --git a/include/linux/annotate.h b/include/linux/annotate.h
index 1678410efa1b..8b28f1a81ec4 100644
--- a/include/linux/annotate.h
+++ b/include/linux/annotate.h
@@ -3,53 +3,43 @@
#define _LINUX_ANNOTATE_H
#include <linux/objtool_types.h>
+#include <linux/stringify.h>
+#include <asm/asm.h>
+
+#define DEFINE___ANNOTATE \
+ .macro __ANNOTATE sec, type, loc; \
+ .pushsection __ASM_C(\sec, \\sec), "M", @progbits, 8; \
+ .long __ASM_C(\loc, \\loc) - .; \
+ .long __ASM_C(\type, \\type); \
+ .popsection; \
+ .endm
+
+#define __DEFINE_ANNOTATE(sec, name, type) \
+ .macro name loc=910b; \
+ 910: __ANNOTATE sec, type, __ASM_C(\loc, \\loc); \
+ .endm
+
+#define DEFINE_ANNOTATE(type) \
+ __DEFINE_ANNOTATE(.discard.annotate_insn, \
+ ANNOTATE_ ## type, ANNOTYPE_ ## type)
+
+#define DEFINE_ANNOTATE_DATA(type) \
+ __DEFINE_ANNOTATE(.discard.annotate_data, \
+ ANNOTATE_ ## type, ANNOTYPE_ ## type)
#ifdef CONFIG_OBJTOOL
-#define __ASM_ANNOTATE(section, label, type) \
- .pushsection section, "M", @progbits, 8; \
- .long label - ., type; \
- .popsection
-
-#ifndef __ASSEMBLY__
-
-#define ASM_ANNOTATE_LABEL(label, type) \
- __stringify(__ASM_ANNOTATE(.discard.annotate_insn, label, type))
-
-#define ASM_ANNOTATE(type) \
- "911: " \
- __stringify(__ASM_ANNOTATE(.discard.annotate_insn, 911b, type))
-
-#define ASM_ANNOTATE_DATA(type) \
- "912: " \
- __stringify(__ASM_ANNOTATE(.discard.annotate_data, 912b, type))
-
-#else /* __ASSEMBLY__ */
-
-.macro ANNOTATE type
-.Lhere_\@:
- __ASM_ANNOTATE(.discard.annotate_insn, .Lhere_\@, \type)
-.endm
-
-.macro ANNOTATE_DATA type
-.Lhere_\@:
- __ASM_ANNOTATE(.discard.annotate_data, .Lhere_\@, \type)
-.endm
-
-#endif /* __ASSEMBLY__ */
-
-#else /* !CONFIG_OBJTOOL */
-#ifndef __ASSEMBLY__
-#define ASM_ANNOTATE_LABEL(label, type) ""
-#define ASM_ANNOTATE(type)
-#define ASM_ANNOTATE_DATA(type)
-#else /* __ASSEMBLY__ */
-.macro ANNOTATE type
-.endm
-.macro ANNOTATE_DATA type
-.endm
-#endif /* __ASSEMBLY__ */
-#endif /* !CONFIG_OBJTOOL */
+DEFINE_MACRO(__ANNOTATE);
+DEFINE_MACRO(ANNOTATE(NOENDBR));
+DEFINE_MACRO(ANNOTATE(RETPOLINE_SAFE));
+DEFINE_MACRO(ANNOTATE(INSTR_BEGIN));
+DEFINE_MACRO(ANNOTATE(INSTR_END));
+DEFINE_MACRO(ANNOTATE(IGNORE_ALTERNATIVE));
+DEFINE_MACRO(ANNOTATE(INTRA_FUNCTION_CALL));
+DEFINE_MACRO(ANNOTATE(UNRET_BEGIN));
+DEFINE_MACRO(ANNOTATE(REACHABLE));
+DEFINE_MACRO(ANNOTATE(NOCFI));
+DEFINE_MACRO(ANNOTATE_DATA(DATA_SPECIAL));
#ifndef __ASSEMBLY__
@@ -57,30 +47,30 @@
* Annotate away the various 'relocation to !ENDBR` complaints; knowing that
* these relocations will never be used for indirect calls.
*/
-#define ANNOTATE_NOENDBR ASM_ANNOTATE(ANNOTYPE_NOENDBR)
-#define ANNOTATE_NOENDBR_SYM(sym) asm(ASM_ANNOTATE_LABEL(sym, ANNOTYPE_NOENDBR))
+#define ANNOTATE_NOENDBR "ANNOTATE_NOENDBR"
+#define ANNOTATE_NOENDBR_SYM(sym) asm("ANNOTATE_NOENDBR loc=" __stringify(sym))
/*
* This should be used immediately before an indirect jump/call. It tells
* objtool the subsequent indirect jump/call is vouched safe for retpoline
* builds.
*/
-#define ANNOTATE_RETPOLINE_SAFE ASM_ANNOTATE(ANNOTYPE_RETPOLINE_SAFE)
+#define ANNOTATE_RETPOLINE_SAFE "ANNOTATE_RETPOLINE_SAFE"
/*
* See linux/instrumentation.h
*/
-#define ANNOTATE_INSTR_BEGIN(label) ASM_ANNOTATE_LABEL(label, ANNOTYPE_INSTR_BEGIN)
-#define ANNOTATE_INSTR_END(label) ASM_ANNOTATE_LABEL(label, ANNOTYPE_INSTR_END)
+#define ANNOTATE_INSTR_BEGIN(label) "ANNOTATE_INSTR_BEGIN loc=" __stringify(label)
+#define ANNOTATE_INSTR_END(label) "ANNOTATE_INSTR_END loc=" __stringify(label)
/*
* objtool annotation to ignore the alternatives and only consider the original
* instruction(s).
*/
-#define ANNOTATE_IGNORE_ALTERNATIVE ASM_ANNOTATE(ANNOTYPE_IGNORE_ALTERNATIVE)
+#define ANNOTATE_IGNORE_ALTERNATIVE "ANNOTATE_IGNORE_ALTERNATIVE"
/*
* 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 ASM_ANNOTATE(ANNOTYPE_INTRA_FUNCTION_CALL)
+#define ANNOTATE_INTRA_FUNCTION_CALL "ANNOTATE_INTRA_FUNCTION_CALL"
/*
* Use objtool to validate the entry requirement that all code paths do
* VALIDATE_UNRET_END before RET.
@@ -88,13 +78,13 @@
* NOTE: The macro must be used at the beginning of a global symbol, otherwise
* it will be ignored.
*/
-#define ANNOTATE_UNRET_BEGIN ASM_ANNOTATE(ANNOTYPE_UNRET_BEGIN)
+#define ANNOTATE_UNRET_BEGIN "ANNOTATE_UNRET_BEGIN"
/*
* This should be used to refer to an instruction that is considered
* terminating, like a noreturn CALL or UD2 when we know they are not -- eg
* WARN using UD2.
*/
-#define ANNOTATE_REACHABLE_LABEL(label) ASM_ANNOTATE_LABEL(label, ANNOTYPE_REACHABLE)
+#define ANNOTATE_REACHABLE_LABEL(label) "ANNOTATE_REACHABLE loc=" __stringify(label)
/*
* This should not be used; it annotates away CFI violations. There are a few
* valid use cases like kexec handover to the next kernel image, and there is
@@ -103,25 +93,33 @@
* There are also a few real issues annotated away, like EFI because we can't
* control the EFI code.
*/
-#define ANNOTATE_NOCFI_SYM(sym) asm(ASM_ANNOTATE_LABEL(sym, ANNOTYPE_NOCFI))
+#define ANNOTATE_NOCFI_SYM(sym) asm("ANNOTATE_NOCFI loc=" __stringify(sym))
/*
* Annotate a special section entry. This emables livepatch module generation
* to find and extract individual special section entries as needed.
*/
-#define ANNOTATE_DATA_SPECIAL ASM_ANNOTATE_DATA(ANNOTYPE_DATA_SPECIAL)
+#define ANNOTATE_DATA_SPECIAL "ANNOTATE_DATA_SPECIAL"
-#else /* __ASSEMBLY__ */
-#define ANNOTATE_NOENDBR ANNOTATE type=ANNOTYPE_NOENDBR
-#define ANNOTATE_RETPOLINE_SAFE ANNOTATE type=ANNOTYPE_RETPOLINE_SAFE
-/* ANNOTATE_INSTR_BEGIN ANNOTATE type=ANNOTYPE_INSTR_BEGIN */
-/* ANNOTATE_INSTR_END ANNOTATE type=ANNOTYPE_INSTR_END */
-#define ANNOTATE_IGNORE_ALTERNATIVE ANNOTATE type=ANNOTYPE_IGNORE_ALTERNATIVE
-#define ANNOTATE_INTRA_FUNCTION_CALL ANNOTATE type=ANNOTYPE_INTRA_FUNCTION_CALL
-#define ANNOTATE_UNRET_BEGIN ANNOTATE type=ANNOTYPE_UNRET_BEGIN
-#define ANNOTATE_REACHABLE ANNOTATE type=ANNOTYPE_REACHABLE
-#define ANNOTATE_NOCFI ANNOTATE type=ANNOTYPE_NOCFI
-#define ANNOTATE_DATA_SPECIAL ANNOTATE_DATA type=ANNOTYPE_DATA_SPECIAL
-#endif /* __ASSEMBLY__ */
+#endif /* !__ASSEMBLY__ */
+
+#else /* !OBJTOOL */
+
+#define ANNOTATE_NOENDBR
+#define ANNOTATE_NOENDBR_SYM(sym)
+#define ANNOTATE_RETPOLINE_SAFE
+#define ANNOTATE_INSTR_BEGIN(label)
+#define ANNOTATE_INSTR_END(label)
+#define ANNOTATE_IGNORE_ALTERNATIVE
+#define ANNOTATE_INTRA_FUNCTION_CALL
+#define ANNOTATE_UNRET_BEGIN
+#define ANNOTATE_REACHABLE
+#define ANNOTATE_REACHABLE_LABEL(label)
+#define ANNOTATE_NOCFI
+#define ANNOTATE_NOCFI_SYM(sym)
+#define ANNOTATE_DATA_SPECIAL
+#define __ANNOTATE_DATA_SPECIAL(l)
+
+#endif /* !OBJTOOL */
#endif /* _LINUX_ANNOTATE_H */
--
2.52.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 6/8] x86/asm: Use unique code labels in __FILL_RETURN_BUFFER
2025-12-06 21:41 [PATCH 0/8] objtool, x86/alternative: Convert objtool annotations and x86 alternatives to assembler macros Josh Poimboeuf
` (4 preceding siblings ...)
2025-12-06 21:41 ` [PATCH 5/8] objtool: Convert annotations to assembler macros Josh Poimboeuf
@ 2025-12-06 21:41 ` Josh Poimboeuf
2025-12-06 21:41 ` [PATCH 7/8] x86/asm: Remove newlines in alternatives Josh Poimboeuf
` (2 subsequent siblings)
8 siblings, 0 replies; 20+ messages in thread
From: Josh Poimboeuf @ 2025-12-06 21:41 UTC (permalink / raw)
To: x86
Cc: linux-kernel, Linus Torvalds, Ingo Molnar, Peter Zijlstra,
Borislav Petkov, Thomas Gleixner
In preparation for unifying the C and asm alternative implementations,
change the code labels in __FILL_RETURN_BUFFER to be unique. The 771
and 772 labels are used by the C alternative implementation, which will
soon be extended for asm.
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
arch/x86/include/asm/nospec-branch.h | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/arch/x86/include/asm/nospec-branch.h b/arch/x86/include/asm/nospec-branch.h
index a5d41d8cd70a..334c6058a1ec 100644
--- a/arch/x86/include/asm/nospec-branch.h
+++ b/arch/x86/include/asm/nospec-branch.h
@@ -126,9 +126,9 @@
*/
#define __FILL_RETURN_SLOT \
ANNOTATE_INTRA_FUNCTION_CALL; \
- call 772f; \
+ call 872f; \
int3; \
-772:
+872:
/*
* Stuff the entire RSB.
@@ -140,12 +140,12 @@
#ifdef CONFIG_X86_64
#define __FILL_RETURN_BUFFER(reg, nr) \
mov $(nr/2), reg; \
-771: \
+871: \
__FILL_RETURN_SLOT \
__FILL_RETURN_SLOT \
add $(BITS_PER_LONG/8) * 2, %_ASM_SP; \
dec reg; \
- jnz 771b; \
+ jnz 871b; \
/* barrier for jnz misprediction */ \
lfence; \
CREDIT_CALL_DEPTH \
--
2.52.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 7/8] x86/asm: Remove newlines in alternatives
2025-12-06 21:41 [PATCH 0/8] objtool, x86/alternative: Convert objtool annotations and x86 alternatives to assembler macros Josh Poimboeuf
` (5 preceding siblings ...)
2025-12-06 21:41 ` [PATCH 6/8] x86/asm: Use unique code labels in __FILL_RETURN_BUFFER Josh Poimboeuf
@ 2025-12-06 21:41 ` Josh Poimboeuf
2025-12-07 14:52 ` Josh Poimboeuf
2025-12-06 21:41 ` [PATCH 8/8] x86/alternative: Convert alternatives to assembler macros Josh Poimboeuf
2025-12-11 1:06 ` [PATCH 0/8] objtool, x86/alternative: Convert objtool annotations and x86 " Borislav Petkov
8 siblings, 1 reply; 20+ messages in thread
From: Josh Poimboeuf @ 2025-12-06 21:41 UTC (permalink / raw)
To: x86
Cc: linux-kernel, Linus Torvalds, Ingo Molnar, Peter Zijlstra,
Borislav Petkov, Thomas Gleixner
In preparation for converting the alternative implementation to
assembler macros, remove all newlines from alternative instructions.
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
arch/x86/include/asm/paravirt_types.h | 2 +-
arch/x86/include/asm/processor.h | 2 +-
arch/x86/include/asm/smap.h | 8 ++++----
arch/x86/include/asm/vmware.h | 2 +-
4 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/arch/x86/include/asm/paravirt_types.h b/arch/x86/include/asm/paravirt_types.h
index 3502939415ad..a05fcc4f5172 100644
--- a/arch/x86/include/asm/paravirt_types.h
+++ b/arch/x86/include/asm/paravirt_types.h
@@ -249,7 +249,7 @@ extern struct paravirt_patch_template pv_ops;
* don't need to bother with CFI prefixes.
*/
#define PARAVIRT_CALL \
- ANNOTATE_RETPOLINE_SAFE "\n\t" \
+ ANNOTATE_RETPOLINE_SAFE "; " \
"call *%[paravirt_opptr];"
/*
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index a24c7805acdb..816dbddd7507 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -706,7 +706,7 @@ static inline u32 per_cpu_l2c_id(unsigned int cpu)
*/
static __always_inline void amd_clear_divider(void)
{
- asm volatile(ALTERNATIVE("", "div %2\n\t", X86_BUG_DIV0)
+ asm volatile(ALTERNATIVE("", "div %2", X86_BUG_DIV0)
:: "a" (0), "d" (0), "r" (1));
}
diff --git a/arch/x86/include/asm/smap.h b/arch/x86/include/asm/smap.h
index 977bef14a0ab..d9d565024e3b 100644
--- a/arch/x86/include/asm/smap.h
+++ b/arch/x86/include/asm/smap.h
@@ -77,7 +77,7 @@ static __always_inline unsigned long smap_save(void)
unsigned long flags;
asm volatile ("# smap_save\n\t"
- ALTERNATIVE(ANNOTATE_IGNORE_ALTERNATIVE "\n\t"
+ ALTERNATIVE(ANNOTATE_IGNORE_ALTERNATIVE
"", "pushf; pop %0; clac",
X86_FEATURE_SMAP)
: "=rm" (flags) : : "memory", "cc");
@@ -88,7 +88,7 @@ static __always_inline unsigned long smap_save(void)
static __always_inline void smap_restore(unsigned long flags)
{
asm volatile ("# smap_restore\n\t"
- ALTERNATIVE(ANNOTATE_IGNORE_ALTERNATIVE "\n\t"
+ ALTERNATIVE(ANNOTATE_IGNORE_ALTERNATIVE
"", "push %0; popf",
X86_FEATURE_SMAP)
: : "g" (flags) : "memory", "cc");
@@ -101,9 +101,9 @@ static __always_inline void smap_restore(unsigned long flags)
ALTERNATIVE("", "stac", X86_FEATURE_SMAP)
#define ASM_CLAC_UNSAFE \
- ALTERNATIVE("", ANNOTATE_IGNORE_ALTERNATIVE "\n\t" "clac", X86_FEATURE_SMAP)
+ ALTERNATIVE("", ANNOTATE_IGNORE_ALTERNATIVE "; clac", X86_FEATURE_SMAP)
#define ASM_STAC_UNSAFE \
- ALTERNATIVE("", ANNOTATE_IGNORE_ALTERNATIVE "\n\t" "stac", X86_FEATURE_SMAP)
+ ALTERNATIVE("", ANNOTATE_IGNORE_ALTERNATIVE "; stac", X86_FEATURE_SMAP)
#endif /* __ASSEMBLER__ */
diff --git a/arch/x86/include/asm/vmware.h b/arch/x86/include/asm/vmware.h
index c9cf43d5ef23..100fba7555bf 100644
--- a/arch/x86/include/asm/vmware.h
+++ b/arch/x86/include/asm/vmware.h
@@ -90,7 +90,7 @@ extern unsigned long vmware_tdx_hypercall(unsigned long cmd,
* set. The high word of %edx may contain input data from the caller.
*/
#define VMWARE_HYPERCALL \
- ALTERNATIVE_2("movw %[port], %%dx\n\t" \
+ ALTERNATIVE_2("movw %[port], %%dx; " \
"inl (%%dx), %%eax", \
"vmcall", X86_FEATURE_VMCALL, \
"vmmcall", X86_FEATURE_VMW_VMMCALL)
--
2.52.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 8/8] x86/alternative: Convert alternatives to assembler macros
2025-12-06 21:41 [PATCH 0/8] objtool, x86/alternative: Convert objtool annotations and x86 alternatives to assembler macros Josh Poimboeuf
` (6 preceding siblings ...)
2025-12-06 21:41 ` [PATCH 7/8] x86/asm: Remove newlines in alternatives Josh Poimboeuf
@ 2025-12-06 21:41 ` Josh Poimboeuf
2025-12-08 9:51 ` Peter Zijlstra
2025-12-11 1:06 ` [PATCH 0/8] objtool, x86/alternative: Convert objtool annotations and x86 " Borislav Petkov
8 siblings, 1 reply; 20+ messages in thread
From: Josh Poimboeuf @ 2025-12-06 21:41 UTC (permalink / raw)
To: x86
Cc: linux-kernel, Linus Torvalds, Ingo Molnar, Peter Zijlstra,
Borislav Petkov, Thomas Gleixner
Improve code generation readability by converting the alternatives into
assembler macros which are created when alternative.h is included.
Before:
# ./arch/x86/include/asm/smap.h:47: alternative("", "stac", X86_FEATURE_SMAP);
# 47 "./arch/x86/include/asm/smap.h" 1
# ALT: oldinstr
771:
772:
# ALT: padding
.skip -(((775f-774f)-(772b-771b)) > 0) * ((775f-774f)-(772b-771b)),0x90
773:
.pushsection .altinstructions, "aM", @progbits, 14
.long 771b - .
.long 774f - .
.4byte ( 9*32+20)
.byte 773b-771b
.byte 775f-774f
.popsection
.pushsection .altinstr_replacement, "ax"
ANNOTATE_DATA_SPECIAL
# ALT: replacement
774:
stac
775:
.popsection
After:
# ./arch/x86/include/asm/smap.h:47: alternative("", "stac", X86_FEATURE_SMAP);
# 47 "./arch/x86/include/asm/smap.h" 1
ALTERNATIVE "", "stac", "( 9*32+20)"
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
arch/x86/include/asm/alternative.h | 196 +++++++++++++++--------------
include/linux/annotate.h | 7 +-
2 files changed, 107 insertions(+), 96 deletions(-)
diff --git a/arch/x86/include/asm/alternative.h b/arch/x86/include/asm/alternative.h
index 03364510d5fe..89c69fe8f337 100644
--- a/arch/x86/include/asm/alternative.h
+++ b/arch/x86/include/asm/alternative.h
@@ -8,6 +8,90 @@
#include <asm/asm.h>
#include <asm/bug.h>
+/*
+ * CALC_MAX: assembler-compatible max based on the idea from:
+ * http://graphics.stanford.edu/~seander/bithacks.html#IntegerMinOrMax
+ *
+ * The additional "-" is needed because gas uses a "true" value of -1.
+ */
+#define CALC_MAX(a, b) (a ^ ((a ^ b) & -(-(a < b))))
+
+/* Add padding after the original instructions so the replacements can fit. */
+#define __ALT_SKIP(orig_len, len1, len2, len3) \
+ .skip -((CALC_MAX(CALC_MAX(len1, len2), len3) - orig_len) > 0) *\
+ (CALC_MAX(CALC_MAX(len1, len2), len3) - orig_len), 0x90
+
+#define ALT_SKIP __ALT_SKIP((772b-771b), (775f-774f), (776f-775f), (777f-776f))
+
+#define ALT_REPLACE(newinstr1, newinstr2, newinstr3) \
+ .pushsection .altinstr_replacement, "ax"; \
+ 774: newinstr1; \
+ 775: newinstr2; \
+ 776: newinstr3; \
+ 777: \
+ .popsection
+
+#define ALT_ENTRY(orig_begin, orig_end, new_begin, new_end, ft_flags) \
+ __ANNOTATE_DATA_SPECIAL(new_begin); \
+ .pushsection .altinstructions, "aM", @progbits, ALT_INSTR_SIZE; \
+ .long orig_begin - .; \
+ .long new_begin - .; \
+ .4byte ft_flags; \
+ .byte orig_end - orig_begin; \
+ .byte new_end - new_begin; \
+ .popsection
+
+/*
+ * These ALTERNATIVE .macros get created when this file gets included:
+ */
+
+#define DEFINE_ALTERNATIVE \
+.macro ALTERNATIVE oldinstr, newinstr, ft_flags; \
+ 771: __ASM_C(\oldinstr, \\oldinstr); \
+ 772: ALT_SKIP; \
+ 773: \
+ ALT_REPLACE(__ASM_C(\newinstr, \\newinstr),,); \
+ ALT_ENTRY(771b, 773b, 774b, 775b, \
+ __ASM_C(\ft_flags, \\ft_flags)); \
+.endm
+
+#define DEFINE_ALTERNATIVE_2 \
+.macro ALTERNATIVE_2 oldinstr, newinstr1, ft_flags1, \
+ newinstr2, ft_flags2; \
+ 771: __ASM_C(\oldinstr, \\oldinstr); \
+ 772: ALT_SKIP; \
+ 773: \
+ ALT_REPLACE(__ASM_C(\newinstr1, \\newinstr1), \
+ __ASM_C(\newinstr2, \\newinstr2),); \
+ ALT_ENTRY(771b, 773b, 774b, 775b, \
+ __ASM_C(\ft_flags1, \\ft_flags1)); \
+ ALT_ENTRY(771b, 773b, 775b, 776b, \
+ __ASM_C(\ft_flags2, \\ft_flags2)); \
+.endm
+
+#define DEFINE_ALTERNATIVE_3 \
+.macro ALTERNATIVE_3 oldinstr, newinstr1, ft_flags1, \
+ newinstr2, ft_flags2, \
+ newinstr3, ft_flags3; \
+ 771: __ASM_C(\oldinstr, \\oldinstr); \
+ 772: ALT_SKIP; \
+ 773: \
+ ALT_REPLACE(__ASM_C(\newinstr1, \\newinstr1), \
+ __ASM_C(\newinstr2, \\newinstr2), \
+ __ASM_C(\newinstr3, \\newinstr3)); \
+ ALT_ENTRY(771b, 773b, 774b, 775b, \
+ __ASM_C(\ft_flags1, \\ft_flags1)); \
+ ALT_ENTRY(771b, 773b, 775b, 776b, \
+ __ASM_C(\ft_flags2, \\ft_flags2)); \
+ ALT_ENTRY(771b, 773b, 776b, 777b, \
+ __ASM_C(\ft_flags3, \\ft_flags3)); \
+.endm
+
+DEFINE_MACRO(ALTERNATIVE);
+DEFINE_MACRO(ALTERNATIVE_2);
+DEFINE_MACRO(ALTERNATIVE_3);
+
+
#define ALT_FLAGS_SHIFT 16
#define ALT_FLAG_NOT (1 << 0)
@@ -184,53 +268,30 @@ static inline int alternatives_text_reserved(void *start, void *end)
#define ALT_CALL_INSTR "call BUG_func"
-#define alt_slen "772b-771b"
-#define alt_total_slen "773b-771b"
-#define alt_rlen "775f-774f"
+#define ALTERNATIVE(oldinstr, newinstr, ft_flags) \
+ "ALTERNATIVE \"" oldinstr "\", " \
+ "\"" newinstr "\", \"" __stringify(ft_flags) "\"\n"
-#define OLDINSTR(oldinstr) \
- "# ALT: oldinstr\n" \
- "771:\n\t" oldinstr "\n772:\n" \
- "# ALT: padding\n" \
- ".skip -(((" alt_rlen ")-(" alt_slen ")) > 0) * " \
- "((" alt_rlen ")-(" alt_slen ")),0x90\n" \
- "773:\n"
+#define ALTERNATIVE_2(oldinstr, \
+ newinstr1, ft_flags1, \
+ newinstr2, ft_flags2) \
+ "ALTERNATIVE_2 \"" oldinstr "\", " \
+ "\"" newinstr1 "\", \"" __stringify(ft_flags1) "\", " \
+ "\"" newinstr2 "\", \"" __stringify(ft_flags2) "\"\n"
-#define ALTINSTR_ENTRY(ft_flags) \
- ".pushsection .altinstructions, \"aM\", @progbits, " \
- __stringify(ALT_INSTR_SIZE) "\n" \
- " .long 771b - .\n" /* label */ \
- " .long 774f - .\n" /* new instruction */ \
- " .4byte " __stringify(ft_flags) "\n" /* feature + flags */ \
- " .byte " alt_total_slen "\n" /* source len */ \
- " .byte " alt_rlen "\n" /* replacement len */ \
- ".popsection\n"
-
-#define ALTINSTR_REPLACEMENT(newinstr) /* replacement */ \
- ".pushsection .altinstr_replacement, \"ax\"\n" \
- ANNOTATE_DATA_SPECIAL "\n" \
- "# ALT: replacement\n" \
- "774:\n\t" newinstr "\n775:\n" \
- ".popsection\n"
-
-/* alternative assembly primitive: */
-#define ALTERNATIVE(oldinstr, newinstr, ft_flags) \
- OLDINSTR(oldinstr) \
- ALTINSTR_ENTRY(ft_flags) \
- ALTINSTR_REPLACEMENT(newinstr)
-
-#define ALTERNATIVE_2(oldinstr, newinstr1, ft_flags1, newinstr2, ft_flags2) \
- ALTERNATIVE(ALTERNATIVE(oldinstr, newinstr1, ft_flags1), newinstr2, ft_flags2)
+#define ALTERNATIVE_3(oldinstr, \
+ newinstr1, ft_flags1, \
+ newinstr2, ft_flags2, \
+ newinstr3, ft_flags3) \
+ "ALTERNATIVE_3 \"" oldinstr "\", " \
+ "\"" newinstr1 "\", \"" __stringify(ft_flags1) "\", " \
+ "\"" newinstr2 "\", \"" __stringify(ft_flags2) "\", " \
+ "\"" newinstr3 "\", \"" __stringify(ft_flags3) "\"\n"
/* If @feature is set, patch in @newinstr_yes, otherwise @newinstr_no. */
#define ALTERNATIVE_TERNARY(oldinstr, ft_flags, newinstr_yes, newinstr_no) \
ALTERNATIVE_2(oldinstr, newinstr_no, X86_FEATURE_ALWAYS, newinstr_yes, ft_flags)
-#define ALTERNATIVE_3(oldinstr, newinstr1, ft_flags1, newinstr2, ft_flags2, \
- newinstr3, ft_flags3) \
- ALTERNATIVE(ALTERNATIVE_2(oldinstr, newinstr1, ft_flags1, newinstr2, ft_flags2), \
- newinstr3, ft_flags3)
-
/*
* Alternative instructions for different CPU types or capabilities.
*
@@ -332,65 +393,10 @@ void nop_func(void);
.endm
#endif
-/*
- * Issue one struct alt_instr descriptor entry (need to put it into
- * the section .altinstructions, see below). This entry contains
- * enough information for the alternatives patching code to patch an
- * instruction. See apply_alternatives().
- */
-.macro altinstr_entry orig alt ft_flags orig_len alt_len
- .long \orig - .
- .long \alt - .
- .4byte \ft_flags
- .byte \orig_len
- .byte \alt_len
-.endm
-
.macro ALT_CALL_INSTR
call BUG_func
.endm
-/*
- * Define an alternative between two instructions. If @feature is
- * present, early code in apply_alternatives() replaces @oldinstr with
- * @newinstr. ".skip" directive takes care of proper instruction padding
- * in case @newinstr is longer than @oldinstr.
- */
-#define __ALTERNATIVE(oldinst, newinst, flag) \
-740: \
- oldinst ; \
-741: \
- .skip -(((744f-743f)-(741b-740b)) > 0) * ((744f-743f)-(741b-740b)),0x90 ;\
-742: \
- .pushsection .altinstructions, "aM", @progbits, ALT_INSTR_SIZE ;\
- altinstr_entry 740b,743f,flag,742b-740b,744f-743f ; \
- .popsection ; \
- .pushsection .altinstr_replacement,"ax" ; \
-743: \
- ANNOTATE_DATA_SPECIAL ; \
- newinst ; \
-744: \
- .popsection ;
-
-.macro ALTERNATIVE oldinstr, newinstr, ft_flags
- __ALTERNATIVE(\oldinstr, \newinstr, \ft_flags)
-.endm
-
-/*
- * Same as ALTERNATIVE macro above but for two alternatives. If CPU
- * has @feature1, it replaces @oldinstr with @newinstr1. If CPU has
- * @feature2, it replaces @oldinstr with @feature2.
- */
-.macro ALTERNATIVE_2 oldinstr, newinstr1, ft_flags1, newinstr2, ft_flags2
- __ALTERNATIVE(__ALTERNATIVE(\oldinstr, \newinstr1, \ft_flags1),
- \newinstr2, \ft_flags2)
-.endm
-
-.macro ALTERNATIVE_3 oldinstr, newinstr1, ft_flags1, newinstr2, ft_flags2, newinstr3, ft_flags3
- __ALTERNATIVE(ALTERNATIVE_2(\oldinstr, \newinstr1, \ft_flags1, \newinstr2, \ft_flags2),
- \newinstr3, \ft_flags3)
-.endm
-
/* If @feature is set, patch in @newinstr_yes, otherwise @newinstr_no. */
#define ALTERNATIVE_TERNARY(oldinstr, ft_flags, newinstr_yes, newinstr_no) \
ALTERNATIVE_2 oldinstr, newinstr_no, X86_FEATURE_ALWAYS, \
diff --git a/include/linux/annotate.h b/include/linux/annotate.h
index 8b28f1a81ec4..a80fef36dc92 100644
--- a/include/linux/annotate.h
+++ b/include/linux/annotate.h
@@ -100,8 +100,13 @@ DEFINE_MACRO(ANNOTATE_DATA(DATA_SPECIAL));
* to find and extract individual special section entries as needed.
*/
#define ANNOTATE_DATA_SPECIAL "ANNOTATE_DATA_SPECIAL"
+#define __ANNOTATE_DATA_SPECIAL(label) __ANNOTATE .discard.annotate_data, ANNOTYPE_DATA_SPECIAL, label
-#endif /* !__ASSEMBLY__ */
+#else /* __ASSEMBLY__ */
+
+#define __ANNOTATE_DATA_SPECIAL(label) ANNOTATE_DATA_SPECIAL loc=label
+
+#endif /* __ASSEMBLY__ */
#else /* !OBJTOOL */
--
2.52.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH 5/8] objtool: Convert annotations to assembler macros
2025-12-06 21:41 ` [PATCH 5/8] objtool: Convert annotations to assembler macros Josh Poimboeuf
@ 2025-12-07 14:51 ` Josh Poimboeuf
2025-12-08 9:37 ` Peter Zijlstra
1 sibling, 0 replies; 20+ messages in thread
From: Josh Poimboeuf @ 2025-12-07 14:51 UTC (permalink / raw)
To: x86
Cc: linux-kernel, Linus Torvalds, Ingo Molnar, Peter Zijlstra,
Borislav Petkov, Thomas Gleixner
On Sat, Dec 06, 2025 at 01:41:12PM -0800, Josh Poimboeuf wrote:
> Improve code generation readability by converting the objtool
> annotations into assembler macros which are created when annotate.h is
> included.
>
> Before:
>
> .pushsection .discard.annotate_insn, "M", @progbits, 8; .long 1b - ., 8; .popsection
>
> After:
>
> ANNOTATE_REACHABLE loc=1b
>
> Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
This needs the following to build on non-x86:
diff --git a/arch/x86/include/asm/asm.h b/arch/x86/include/asm/asm.h
index 770321c908e5..e63810bfdc68 100644
--- a/arch/x86/include/asm/asm.h
+++ b/arch/x86/include/asm/asm.h
@@ -3,14 +3,12 @@
#define _ASM_X86_ASM_H
#ifdef __ASSEMBLER__
-# define __ASM_C(a,b) a
# define __ASM_FORM(x, ...) x,## __VA_ARGS__
# define __ASM_FORM_RAW(x, ...) x,## __VA_ARGS__
# define __ASM_FORM_COMMA(x, ...) x,## __VA_ARGS__,
# define __ASM_REGPFX %
#else
#include <linux/stringify.h>
-# define __ASM_C(a,b) b
# define __ASM_FORM(x, ...) " " __stringify(x,##__VA_ARGS__) " "
# define __ASM_FORM_RAW(x, ...) __stringify(x,##__VA_ARGS__)
# define __ASM_FORM_COMMA(x, ...) " " __stringify(x,##__VA_ARGS__) ","
@@ -115,10 +113,6 @@
#endif
-#define DEFINE_MACRO(name) \
- __ASM_C(DEFINE_ ## name, \
- asm(__stringify(DEFINE_ ## name)))
-
#ifndef __ASSEMBLER__
static __always_inline __pure void *rip_rel_ptr(void *p)
{
diff --git a/include/linux/annotate.h b/include/linux/annotate.h
index a80fef36dc92..a099a1d5e410 100644
--- a/include/linux/annotate.h
+++ b/include/linux/annotate.h
@@ -4,7 +4,7 @@
#include <linux/objtool_types.h>
#include <linux/stringify.h>
-#include <asm/asm.h>
+#include <linux/asm.h>
#define DEFINE___ANNOTATE \
.macro __ANNOTATE sec, type, loc; \
diff --git a/include/linux/asm.h b/include/linux/asm.h
new file mode 100644
index 000000000000..94836aa217b4
--- /dev/null
+++ b/include/linux/asm.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_ASM_H
+#define _LINUX_ASM_H
+
+#ifdef __ASSEMBLER__
+# define __ASM_C(a,b) a
+#else
+# define __ASM_C(a,b) b
+#endif
+
+#define DEFINE_MACRO(name) \
+ __ASM_C(DEFINE_ ## name, \
+ asm(__stringify(DEFINE_ ## name)))
+
+#endif /* _LINUX_ASM_H */
^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH 7/8] x86/asm: Remove newlines in alternatives
2025-12-06 21:41 ` [PATCH 7/8] x86/asm: Remove newlines in alternatives Josh Poimboeuf
@ 2025-12-07 14:52 ` Josh Poimboeuf
0 siblings, 0 replies; 20+ messages in thread
From: Josh Poimboeuf @ 2025-12-07 14:52 UTC (permalink / raw)
To: x86
Cc: linux-kernel, Linus Torvalds, Ingo Molnar, Peter Zijlstra,
Borislav Petkov, Thomas Gleixner
On Sat, Dec 06, 2025 at 01:41:14PM -0800, Josh Poimboeuf wrote:
> In preparation for converting the alternative implementation to
> assembler macros, remove all newlines from alternative instructions.
>
> Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
x86-32 fixes:
diff --git a/arch/x86/include/asm/nospec-branch.h b/arch/x86/include/asm/nospec-branch.h
index 334c6058a1ec..2313f3fe19d0 100644
--- a/arch/x86/include/asm/nospec-branch.h
+++ b/arch/x86/include/asm/nospec-branch.h
@@ -441,18 +441,18 @@ static inline void call_depth_return_thunk(void) {}
* -mindirect-branch-cs-prefix.
*/
#define __CS_PREFIX(reg) \
- ".irp rs,r8,r9,r10,r11,r12,r13,r14,r15\n" \
- ".ifc \\rs," reg "\n" \
- ".byte 0x2e\n" \
- ".endif\n" \
- ".endr\n"
+ ".irp rs,r8,r9,r10,r11,r12,r13,r14,r15; " \
+ ".ifc \\rs," reg "; " \
+ ".byte 0x2e; " \
+ ".endif; " \
+ ".endr; "
/*
* Inline asm uses the %V modifier which is only in newer GCC
* which is ensured when CONFIG_MITIGATION_RETPOLINE is defined.
*/
#define CALL_NOSPEC __CS_PREFIX("%V[thunk_target]") \
- "call __x86_indirect_thunk_%V[thunk_target]\n"
+ "call __x86_indirect_thunk_%V[thunk_target]"
# define THUNK_TARGET(addr) [thunk_target] "r" (addr)
@@ -464,30 +464,30 @@ static inline void call_depth_return_thunk(void) {}
*/
# define CALL_NOSPEC \
ALTERNATIVE_2( \
- ANNOTATE_RETPOLINE_SAFE "\n" \
- "call *%[thunk_target]\n", \
- " jmp 904f;\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" \
- " .align 16\n" \
- "904: call 901b;\n", \
+ ANNOTATE_RETPOLINE_SAFE "; " \
+ "call *%[thunk_target]; ", \
+ " jmp 904f; " \
+ " .align 16; " \
+ "901: call 903f; " \
+ "902: pause; " \
+ " lfence; " \
+ " jmp 902b; " \
+ " .align 16; " \
+ "903: lea 4(%%esp), %%esp; " \
+ " pushl %[thunk_target]; " \
+ " ret; " \
+ " .align 16; " \
+ "904: call 901b; ", \
X86_FEATURE_RETPOLINE, \
- "lfence;\n" \
- ANNOTATE_RETPOLINE_SAFE "\n" \
- "call *%[thunk_target]\n", \
+ "lfence; " \
+ ANNOTATE_RETPOLINE_SAFE "; " \
+ "call *%[thunk_target]; ", \
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 CALL_NOSPEC "call *%[thunk_target]; "
# define THUNK_TARGET(addr) [thunk_target] "rm" (addr)
#endif
diff --git a/arch/x86/kernel/irq_32.c b/arch/x86/kernel/irq_32.c
index c7a5d2960d57..9c5bb666bd55 100644
--- a/arch/x86/kernel/irq_32.c
+++ b/arch/x86/kernel/irq_32.c
@@ -53,7 +53,7 @@ DEFINE_PER_CPU_CACHE_HOT(struct irq_stack *, softirq_stack_ptr);
static void call_on_stack(void *func, void *stack)
{
- asm volatile("xchgl %[sp], %%esp\n"
+ asm volatile("xchgl %[sp], %%esp; "
CALL_NOSPEC
"movl %[sp], %%esp"
: [sp] "+b" (stack)
^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH 5/8] objtool: Convert annotations to assembler macros
2025-12-06 21:41 ` [PATCH 5/8] objtool: Convert annotations to assembler macros Josh Poimboeuf
2025-12-07 14:51 ` Josh Poimboeuf
@ 2025-12-08 9:37 ` Peter Zijlstra
1 sibling, 0 replies; 20+ messages in thread
From: Peter Zijlstra @ 2025-12-08 9:37 UTC (permalink / raw)
To: Josh Poimboeuf
Cc: x86, linux-kernel, Linus Torvalds, Ingo Molnar, Borislav Petkov,
Thomas Gleixner
On Sat, Dec 06, 2025 at 01:41:12PM -0800, Josh Poimboeuf wrote:
> Improve code generation readability by converting the objtool
> annotations into assembler macros which are created when annotate.h is
> included.
>
> Before:
>
> .pushsection .discard.annotate_insn, "M", @progbits, 8; .long 1b - ., 8; .popsection
>
> After:
>
> ANNOTATE_REACHABLE loc=1b
>
> Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
> diff --git a/arch/x86/include/asm/asm.h b/arch/x86/include/asm/asm.h
> index 0e8c611bc9e2..770321c908e5 100644
> --- a/arch/x86/include/asm/asm.h
> +++ b/arch/x86/include/asm/asm.h
> @@ -2,15 +2,15 @@
> #ifndef _ASM_X86_ASM_H
> #define _ASM_X86_ASM_H
>
> -#include <linux/annotate.h>
> -
> #ifdef __ASSEMBLER__
> +# define __ASM_C(a,b) a
> # define __ASM_FORM(x, ...) x,## __VA_ARGS__
> # define __ASM_FORM_RAW(x, ...) x,## __VA_ARGS__
> # define __ASM_FORM_COMMA(x, ...) x,## __VA_ARGS__,
> # define __ASM_REGPFX %
> #else
> #include <linux/stringify.h>
> +# define __ASM_C(a,b) b
> # define __ASM_FORM(x, ...) " " __stringify(x,##__VA_ARGS__) " "
> # define __ASM_FORM_RAW(x, ...) __stringify(x,##__VA_ARGS__)
> # define __ASM_FORM_COMMA(x, ...) " " __stringify(x,##__VA_ARGS__) ","
> @@ -115,6 +115,10 @@
>
> #endif
>
> +#define DEFINE_MACRO(name) \
> + __ASM_C(DEFINE_ ## name, \
> + asm(__stringify(DEFINE_ ## name)))
> +
> #ifndef __ASSEMBLER__
> static __always_inline __pure void *rip_rel_ptr(void *p)
> {
> diff --git a/include/linux/annotate.h b/include/linux/annotate.h
> index 1678410efa1b..8b28f1a81ec4 100644
> --- a/include/linux/annotate.h
> +++ b/include/linux/annotate.h
> @@ -3,53 +3,43 @@
> #define _LINUX_ANNOTATE_H
>
> #include <linux/objtool_types.h>
> +#include <linux/stringify.h>
> +#include <asm/asm.h>
> +
> +#define DEFINE___ANNOTATE \
> + .macro __ANNOTATE sec, type, loc; \
> + .pushsection __ASM_C(\sec, \\sec), "M", @progbits, 8; \
> + .long __ASM_C(\loc, \\loc) - .; \
> + .long __ASM_C(\type, \\type); \
> + .popsection; \
> + .endm
> +
> +#define __DEFINE_ANNOTATE(sec, name, type) \
> + .macro name loc=910b; \
> + 910: __ANNOTATE sec, type, __ASM_C(\loc, \\loc); \
> + .endm
> +
> +#define DEFINE_ANNOTATE(type) \
> + __DEFINE_ANNOTATE(.discard.annotate_insn, \
> + ANNOTATE_ ## type, ANNOTYPE_ ## type)
> +
> +#define DEFINE_ANNOTATE_DATA(type) \
> + __DEFINE_ANNOTATE(.discard.annotate_data, \
> + ANNOTATE_ ## type, ANNOTYPE_ ## type)
>
> #ifdef CONFIG_OBJTOOL
>
> +DEFINE_MACRO(__ANNOTATE);
> +DEFINE_MACRO(ANNOTATE(NOENDBR));
> +DEFINE_MACRO(ANNOTATE(RETPOLINE_SAFE));
> +DEFINE_MACRO(ANNOTATE(INSTR_BEGIN));
> +DEFINE_MACRO(ANNOTATE(INSTR_END));
> +DEFINE_MACRO(ANNOTATE(IGNORE_ALTERNATIVE));
> +DEFINE_MACRO(ANNOTATE(INTRA_FUNCTION_CALL));
> +DEFINE_MACRO(ANNOTATE(UNRET_BEGIN));
> +DEFINE_MACRO(ANNOTATE(REACHABLE));
> +DEFINE_MACRO(ANNOTATE(NOCFI));
> +DEFINE_MACRO(ANNOTATE_DATA(DATA_SPECIAL));
Well, that took a bit this Monday morning... :-)
Clever.
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 8/8] x86/alternative: Convert alternatives to assembler macros
2025-12-06 21:41 ` [PATCH 8/8] x86/alternative: Convert alternatives to assembler macros Josh Poimboeuf
@ 2025-12-08 9:51 ` Peter Zijlstra
2025-12-08 22:46 ` Josh Poimboeuf
0 siblings, 1 reply; 20+ messages in thread
From: Peter Zijlstra @ 2025-12-08 9:51 UTC (permalink / raw)
To: Josh Poimboeuf
Cc: x86, linux-kernel, Linus Torvalds, Ingo Molnar, Borislav Petkov,
Thomas Gleixner
On Sat, Dec 06, 2025 at 01:41:15PM -0800, Josh Poimboeuf wrote:
> Improve code generation readability by converting the alternatives into
> assembler macros which are created when alternative.h is included.
>
> Before:
>
> # ./arch/x86/include/asm/smap.h:47: alternative("", "stac", X86_FEATURE_SMAP);
> # 47 "./arch/x86/include/asm/smap.h" 1
> # ALT: oldinstr
> 771:
>
> 772:
> # ALT: padding
> .skip -(((775f-774f)-(772b-771b)) > 0) * ((775f-774f)-(772b-771b)),0x90
> 773:
> .pushsection .altinstructions, "aM", @progbits, 14
> .long 771b - .
> .long 774f - .
> .4byte ( 9*32+20)
> .byte 773b-771b
> .byte 775f-774f
> .popsection
> .pushsection .altinstr_replacement, "ax"
> ANNOTATE_DATA_SPECIAL
> # ALT: replacement
> 774:
> stac
> 775:
> .popsection
>
> After:
>
> # ./arch/x86/include/asm/smap.h:47: alternative("", "stac", X86_FEATURE_SMAP);
> # 47 "./arch/x86/include/asm/smap.h" 1
> ALTERNATIVE "", "stac", "( 9*32+20)"
>
So the problem with the gas macro thing is that it doesn't allow for
that nesting. I don't think we currently use it other than to define the
ALTERNATIVE_2 and ALTERNATIVE_3 macros, but IIRC the reason I started
all that was because it was fairly trivial to use things like
CALL_NOSPEC in an alternative (where CALL_NOSPEC is already an
alternative).
Anyway, yes, the macro variant is easier to read in the .s output.
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 8/8] x86/alternative: Convert alternatives to assembler macros
2025-12-08 9:51 ` Peter Zijlstra
@ 2025-12-08 22:46 ` Josh Poimboeuf
2025-12-09 9:24 ` Peter Zijlstra
0 siblings, 1 reply; 20+ messages in thread
From: Josh Poimboeuf @ 2025-12-08 22:46 UTC (permalink / raw)
To: Peter Zijlstra
Cc: x86, linux-kernel, Linus Torvalds, Ingo Molnar, Borislav Petkov,
Thomas Gleixner
On Mon, Dec 08, 2025 at 10:51:09AM +0100, Peter Zijlstra wrote:
> On Sat, Dec 06, 2025 at 01:41:15PM -0800, Josh Poimboeuf wrote:
> > Improve code generation readability by converting the alternatives into
> > assembler macros which are created when alternative.h is included.
> >
> > Before:
> >
> > # ./arch/x86/include/asm/smap.h:47: alternative("", "stac", X86_FEATURE_SMAP);
> > # 47 "./arch/x86/include/asm/smap.h" 1
> > # ALT: oldinstr
> > 771:
> >
> > 772:
> > # ALT: padding
> > .skip -(((775f-774f)-(772b-771b)) > 0) * ((775f-774f)-(772b-771b)),0x90
> > 773:
> > .pushsection .altinstructions, "aM", @progbits, 14
> > .long 771b - .
> > .long 774f - .
> > .4byte ( 9*32+20)
> > .byte 773b-771b
> > .byte 775f-774f
> > .popsection
> > .pushsection .altinstr_replacement, "ax"
> > ANNOTATE_DATA_SPECIAL
> > # ALT: replacement
> > 774:
> > stac
> > 775:
> > .popsection
> >
> > After:
> >
> > # ./arch/x86/include/asm/smap.h:47: alternative("", "stac", X86_FEATURE_SMAP);
> > # 47 "./arch/x86/include/asm/smap.h" 1
> > ALTERNATIVE "", "stac", "( 9*32+20)"
> >
>
> So the problem with the gas macro thing is that it doesn't allow for
> that nesting. I don't think we currently use it other than to define the
> ALTERNATIVE_2 and ALTERNATIVE_3 macros, but IIRC the reason I started
> all that was because it was fairly trivial to use things like
> CALL_NOSPEC in an alternative (where CALL_NOSPEC is already an
> alternative).
Trying to wrap my head around this nested alternative thing as I don't
see any current code doing that. Does that only work when the inner
alternative points to the same first original instruction as the outer
one? Or, can you patch anywhere inside the original or replacement?
--
Josh
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 8/8] x86/alternative: Convert alternatives to assembler macros
2025-12-08 22:46 ` Josh Poimboeuf
@ 2025-12-09 9:24 ` Peter Zijlstra
2025-12-10 1:15 ` Josh Poimboeuf
0 siblings, 1 reply; 20+ messages in thread
From: Peter Zijlstra @ 2025-12-09 9:24 UTC (permalink / raw)
To: Josh Poimboeuf
Cc: x86, linux-kernel, Linus Torvalds, Ingo Molnar, Borislav Petkov,
Thomas Gleixner
On Mon, Dec 08, 2025 at 02:46:23PM -0800, Josh Poimboeuf wrote:
> On Mon, Dec 08, 2025 at 10:51:09AM +0100, Peter Zijlstra wrote:
> > On Sat, Dec 06, 2025 at 01:41:15PM -0800, Josh Poimboeuf wrote:
> > > Improve code generation readability by converting the alternatives into
> > > assembler macros which are created when alternative.h is included.
> > >
> > > Before:
> > >
> > > # ./arch/x86/include/asm/smap.h:47: alternative("", "stac", X86_FEATURE_SMAP);
> > > # 47 "./arch/x86/include/asm/smap.h" 1
> > > # ALT: oldinstr
> > > 771:
> > >
> > > 772:
> > > # ALT: padding
> > > .skip -(((775f-774f)-(772b-771b)) > 0) * ((775f-774f)-(772b-771b)),0x90
> > > 773:
> > > .pushsection .altinstructions, "aM", @progbits, 14
> > > .long 771b - .
> > > .long 774f - .
> > > .4byte ( 9*32+20)
> > > .byte 773b-771b
> > > .byte 775f-774f
> > > .popsection
> > > .pushsection .altinstr_replacement, "ax"
> > > ANNOTATE_DATA_SPECIAL
> > > # ALT: replacement
> > > 774:
> > > stac
> > > 775:
> > > .popsection
> > >
> > > After:
> > >
> > > # ./arch/x86/include/asm/smap.h:47: alternative("", "stac", X86_FEATURE_SMAP);
> > > # 47 "./arch/x86/include/asm/smap.h" 1
> > > ALTERNATIVE "", "stac", "( 9*32+20)"
> > >
> >
> > So the problem with the gas macro thing is that it doesn't allow for
> > that nesting. I don't think we currently use it other than to define the
> > ALTERNATIVE_2 and ALTERNATIVE_3 macros, but IIRC the reason I started
> > all that was because it was fairly trivial to use things like
> > CALL_NOSPEC in an alternative (where CALL_NOSPEC is already an
> > alternative).
>
> Trying to wrap my head around this nested alternative thing as I don't
> see any current code doing that. Does that only work when the inner
> alternative points to the same first original instruction as the outer
> one? Or, can you patch anywhere inside the original or replacement?
They'd have to be at the exact same location.
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 8/8] x86/alternative: Convert alternatives to assembler macros
2025-12-09 9:24 ` Peter Zijlstra
@ 2025-12-10 1:15 ` Josh Poimboeuf
2025-12-10 9:16 ` Peter Zijlstra
0 siblings, 1 reply; 20+ messages in thread
From: Josh Poimboeuf @ 2025-12-10 1:15 UTC (permalink / raw)
To: Peter Zijlstra
Cc: x86, linux-kernel, Linus Torvalds, Ingo Molnar, Borislav Petkov,
Thomas Gleixner
On Tue, Dec 09, 2025 at 10:24:19AM +0100, Peter Zijlstra wrote:
> On Mon, Dec 08, 2025 at 02:46:23PM -0800, Josh Poimboeuf wrote:
> > On Mon, Dec 08, 2025 at 10:51:09AM +0100, Peter Zijlstra wrote:
> > > On Sat, Dec 06, 2025 at 01:41:15PM -0800, Josh Poimboeuf wrote:
> > > > # ./arch/x86/include/asm/smap.h:47: alternative("", "stac", X86_FEATURE_SMAP);
> > > > # 47 "./arch/x86/include/asm/smap.h" 1
> > > > ALTERNATIVE "", "stac", "( 9*32+20)"
> > > >
> > >
> > > So the problem with the gas macro thing is that it doesn't allow for
> > > that nesting. I don't think we currently use it other than to define the
> > > ALTERNATIVE_2 and ALTERNATIVE_3 macros, but IIRC the reason I started
> > > all that was because it was fairly trivial to use things like
> > > CALL_NOSPEC in an alternative (where CALL_NOSPEC is already an
> > > alternative).
> >
> > Trying to wrap my head around this nested alternative thing as I don't
> > see any current code doing that. Does that only work when the inner
> > alternative points to the same first original instruction as the outer
> > one? Or, can you patch anywhere inside the original or replacement?
>
> They'd have to be at the exact same location.
Ok, so while the syntax itself is nested, the underlying behavior is
just stacking alternatives together, like ALTERNATIVE_2 and _3 already
do, correct?
While it's clever that the current implementation allows that kind of
nested syntax, it seems dangerous. I don't see anything preventing the
inner ALTERNATIVE from being placed in the middle of the outer
ALTERNATIVE's original instructions, or anywhere in the outer's
replacement code.
It would be really easy to introduce CALL_NOSPEC in the middle of a
group of instructions in an ALTERNATIVE without realizing that you're
likely introducing some subtle or not-so-subtle bug on x86-32, which
just happens to hide an ALTERNATIVE_2 inside the CALL_NOSPEC...
The gas macro doesn't give you the leeway to make that mistake, so you'd
have to restructure the code slightly to make it fit into a proper
ALTERNATIVE_3. Which is less magical and more clear, so that seems like
a good thing.
--
Josh
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 8/8] x86/alternative: Convert alternatives to assembler macros
2025-12-10 1:15 ` Josh Poimboeuf
@ 2025-12-10 9:16 ` Peter Zijlstra
2025-12-11 5:20 ` Josh Poimboeuf
0 siblings, 1 reply; 20+ messages in thread
From: Peter Zijlstra @ 2025-12-10 9:16 UTC (permalink / raw)
To: Josh Poimboeuf
Cc: x86, linux-kernel, Linus Torvalds, Ingo Molnar, Borislav Petkov,
Thomas Gleixner
On Tue, Dec 09, 2025 at 05:15:06PM -0800, Josh Poimboeuf wrote:
> Ok, so while the syntax itself is nested, the underlying behavior is
> just stacking alternatives together, like ALTERNATIVE_2 and _3 already
> do, correct?
Yup.
> While it's clever that the current implementation allows that kind of
> nested syntax, it seems dangerous. I don't see anything preventing the
> inner ALTERNATIVE from being placed in the middle of the outer
> ALTERNATIVE's original instructions, or anywhere in the outer's
> replacement code.
>
> It would be really easy to introduce CALL_NOSPEC in the middle of a
> group of instructions in an ALTERNATIVE without realizing that you're
> likely introducing some subtle or not-so-subtle bug on x86-32, which
> just happens to hide an ALTERNATIVE_2 inside the CALL_NOSPEC...
I think I made objtool complain in that case, but I'm not sure.
> The gas macro doesn't give you the leeway to make that mistake, so you'd
> have to restructure the code slightly to make it fit into a proper
> ALTERNATIVE_3. Which is less magical and more clear, so that seems like
> a good thing.
Perhaps, I'm not really a fan of the ALTERNATIVE_n() macros much. I
think writing the nested ALTERNATIVE() form is actually more readable.
But perhaps I'm the crazy one -- wouldn't be the first time :-)
Anyway, seeing how its not actually used, and I've since solved the case
that gave rise to all this completely differently, perhaps I should just
shut up and let you do the conversion.
I mean, we will have to do ALTERNATIVE_4() at some point, and it will be
glorious... *sigh*
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 0/8] objtool, x86/alternative: Convert objtool annotations and x86 alternatives to assembler macros
2025-12-06 21:41 [PATCH 0/8] objtool, x86/alternative: Convert objtool annotations and x86 alternatives to assembler macros Josh Poimboeuf
` (7 preceding siblings ...)
2025-12-06 21:41 ` [PATCH 8/8] x86/alternative: Convert alternatives to assembler macros Josh Poimboeuf
@ 2025-12-11 1:06 ` Borislav Petkov
2025-12-11 5:27 ` Josh Poimboeuf
8 siblings, 1 reply; 20+ messages in thread
From: Borislav Petkov @ 2025-12-11 1:06 UTC (permalink / raw)
To: Josh Poimboeuf
Cc: x86, linux-kernel, Linus Torvalds, Ingo Molnar, Peter Zijlstra,
Thomas Gleixner
On Sat, Dec 06, 2025 at 01:41:07PM -0800, Josh Poimboeuf wrote:
> Convert objtool annotations and x86 alternatives to assembler macros.
> This creates a shared C/asm alternative implementation and makes the
> code generation significantly more readable.
I don't understand: all this churn for that?
So that .s output - which is looked at by 3 people on this planet - is "readable"?
Dunno, it was readable before too...
> Patches 1-5: convert objtool
> Patches 6-8: convert alternatives
>
> Based on tip/master.
>
> Before:
> -----
> # ./arch/x86/include/asm/smap.h:47: alternative("", "stac", X86_FEATURE_SMAP);
> # 47 "./arch/x86/include/asm/smap.h" 1
> # ALT: oldinstr
> 771:
>
> 772:
> # ALT: padding
... especially with those helpful comments...
> .skip -(((775f-774f)-(772b-771b)) > 0) * ((775f-774f)-(772b-771b)),0x90
> 773:
> .pushsection .altinstructions, "aM", @progbits, 14
> .long 771b - .
> .long 774f - .
> .4byte ( 9*32+20)
> .byte 773b-771b
> .byte 775f-774f
> .popsection
> .pushsection .altinstr_replacement, "ax"
> .pushsection .discard.annotate_data, "M", @progbits, 8; .long 1b - ., 1; .popsection
> # ALT: replacement
> 774:
> stac
> 775:
> .popsection
> -----
>
> After:
> -----
> # ./arch/x86/include/asm/smap.h:47: alternative("", "stac", X86_FEATURE_SMAP);
> # 47 "./arch/x86/include/asm/smap.h" 1
> ALTERNATIVE "", "stac", "( 9*32+20)"
Well, that's "readable" but one still needs to go see that ALTERNATIVE
macro definition now, right?
So you move the gory details somewhere else.
Sorry, I fail to see why we're doing this...
Thx.
--
Regards/Gruss,
Boris.
https://people.kernel.org/tglx/notes-about-netiquette
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 8/8] x86/alternative: Convert alternatives to assembler macros
2025-12-10 9:16 ` Peter Zijlstra
@ 2025-12-11 5:20 ` Josh Poimboeuf
0 siblings, 0 replies; 20+ messages in thread
From: Josh Poimboeuf @ 2025-12-11 5:20 UTC (permalink / raw)
To: Peter Zijlstra
Cc: x86, linux-kernel, Linus Torvalds, Ingo Molnar, Borislav Petkov,
Thomas Gleixner
On Wed, Dec 10, 2025 at 10:16:45AM +0100, Peter Zijlstra wrote:
> On Tue, Dec 09, 2025 at 05:15:06PM -0800, Josh Poimboeuf wrote:
>
> > Ok, so while the syntax itself is nested, the underlying behavior is
> > just stacking alternatives together, like ALTERNATIVE_2 and _3 already
> > do, correct?
>
> Yup.
>
> > While it's clever that the current implementation allows that kind of
> > nested syntax, it seems dangerous. I don't see anything preventing the
> > inner ALTERNATIVE from being placed in the middle of the outer
> > ALTERNATIVE's original instructions, or anywhere in the outer's
> > replacement code.
> >
> > It would be really easy to introduce CALL_NOSPEC in the middle of a
> > group of instructions in an ALTERNATIVE without realizing that you're
> > likely introducing some subtle or not-so-subtle bug on x86-32, which
> > just happens to hide an ALTERNATIVE_2 inside the CALL_NOSPEC...
>
> I think I made objtool complain in that case, but I'm not sure.
I do see some checks there. I'm not quite convinced all the edge cases
are covered.
> > The gas macro doesn't give you the leeway to make that mistake, so you'd
> > have to restructure the code slightly to make it fit into a proper
> > ALTERNATIVE_3. Which is less magical and more clear, so that seems like
> > a good thing.
>
> Perhaps, I'm not really a fan of the ALTERNATIVE_n() macros much. I
> think writing the nested ALTERNATIVE() form is actually more readable.
> But perhaps I'm the crazy one -- wouldn't be the first time :-)
The nesting might be more readable, but it feels like syntax sugar in a
way that's a conceptual mismatch compared to how the alternatives are
actually applied.
> Anyway, seeing how its not actually used, and I've since solved the case
> that gave rise to all this completely differently, perhaps I should just
> shut up and let you do the conversion.
>
> I mean, we will have to do ALTERNATIVE_4() at some point, and it will be
> glorious... *sigh*
Well, at least this makes it a unified implementation so the ugly is
only confined to a single place :-)
--
Josh
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 0/8] objtool, x86/alternative: Convert objtool annotations and x86 alternatives to assembler macros
2025-12-11 1:06 ` [PATCH 0/8] objtool, x86/alternative: Convert objtool annotations and x86 " Borislav Petkov
@ 2025-12-11 5:27 ` Josh Poimboeuf
0 siblings, 0 replies; 20+ messages in thread
From: Josh Poimboeuf @ 2025-12-11 5:27 UTC (permalink / raw)
To: Borislav Petkov
Cc: x86, linux-kernel, Linus Torvalds, Ingo Molnar, Peter Zijlstra,
Thomas Gleixner
On Thu, Dec 11, 2025 at 02:06:06AM +0100, Borislav Petkov wrote:
> On Sat, Dec 06, 2025 at 01:41:07PM -0800, Josh Poimboeuf wrote:
> > # ./arch/x86/include/asm/smap.h:47: alternative("", "stac", X86_FEATURE_SMAP);
> > # 47 "./arch/x86/include/asm/smap.h" 1
> > ALTERNATIVE "", "stac", "( 9*32+20)"
>
> Well, that's "readable" but one still needs to go see that ALTERNATIVE
> macro definition now, right?
>
> So you move the gory details somewhere else.
>
> Sorry, I fail to see why we're doing this...
Partially because Linus complains every time I mess up the code gen ;-)
But I like this change too.
Anybody reading the .s file should already know how alternatives work.
If not... go read alternatives.h!
--
Josh
^ permalink raw reply [flat|nested] 20+ messages in thread
end of thread, other threads:[~2025-12-11 5:27 UTC | newest]
Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-12-06 21:41 [PATCH 0/8] objtool, x86/alternative: Convert objtool annotations and x86 alternatives to assembler macros Josh Poimboeuf
2025-12-06 21:41 ` [PATCH 1/8] objtool: Rename ANNOTYPE_IGNORE_ALTS -> ANNOTYPE_IGNORE_ALTERNATIVE Josh Poimboeuf
2025-12-06 21:41 ` [PATCH 2/8] objtool: Make ANNOTYPE_DATA_SPECIAL unique across all annotations Josh Poimboeuf
2025-12-06 21:41 ` [PATCH 3/8] objtool: Rename C ANNOTATE_REACHABLE to ANNOTATE_REACHABLE_LABEL Josh Poimboeuf
2025-12-06 21:41 ` [PATCH 4/8] objtool: Rename asm ANNOTATE_NOCFI_SYM to ANNOTATE_NOCFI Josh Poimboeuf
2025-12-06 21:41 ` [PATCH 5/8] objtool: Convert annotations to assembler macros Josh Poimboeuf
2025-12-07 14:51 ` Josh Poimboeuf
2025-12-08 9:37 ` Peter Zijlstra
2025-12-06 21:41 ` [PATCH 6/8] x86/asm: Use unique code labels in __FILL_RETURN_BUFFER Josh Poimboeuf
2025-12-06 21:41 ` [PATCH 7/8] x86/asm: Remove newlines in alternatives Josh Poimboeuf
2025-12-07 14:52 ` Josh Poimboeuf
2025-12-06 21:41 ` [PATCH 8/8] x86/alternative: Convert alternatives to assembler macros Josh Poimboeuf
2025-12-08 9:51 ` Peter Zijlstra
2025-12-08 22:46 ` Josh Poimboeuf
2025-12-09 9:24 ` Peter Zijlstra
2025-12-10 1:15 ` Josh Poimboeuf
2025-12-10 9:16 ` Peter Zijlstra
2025-12-11 5:20 ` Josh Poimboeuf
2025-12-11 1:06 ` [PATCH 0/8] objtool, x86/alternative: Convert objtool annotations and x86 " Borislav Petkov
2025-12-11 5:27 ` Josh Poimboeuf
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox