Skip to contentSkip to conversation

x86/speculation: Make {JMP,CALL}_NOSPEC Consistent

PATCH In review Suraj Jitindar Singh 2 participants 11 messages Sep 3, 2025 – Sep 17, 2025 Stable branch

lore
Share & tools
lore
#0 lore raw

cover x86/speculation: Make {JMP,CALL}_NOSPEC Consistent

The 4 patches in this series make the JMP_NOSPEC and CALL_NOSPEC macros used in the kernel consistent with what is generated by the compiler.

("x86,nospec: Simplify {JMP,CALL}_NOSPEC") was merged in v6.0 and the remaining 3 patches in this series were merged in v6.15. All 4 were included in kernels v5.15+ as prerequisites for the backport of the ITS mitigations [1].

None of these patches were included in the backport of the ITS mitigations to the 5.10 kernel [2]. They all apply cleanly and are applicable to the 5.10 kernel. Thus I see no reason that they weren't applied here, unless someone can correct me?

I am sending them for inclusion in the 5.10 kernel as this kernel is still actively maintained for these kind of vulnerability mitigations and as such having these patches will unify the handling of these cases with subsequent kernel versions easing code understanding and the ease of backports in the future.

[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=1ac116ce6468670eeda39345a5585df308243dca
[2] https://lore.kernel.org/stable/[email protected]/

Pawan Gupta (3):
x86/speculation: Simplify and make CALL_NOSPEC consistent x86/speculation: Add a conditional CS prefix to CALL_NOSPEC x86/speculation: Remove the extra #ifdef around CALL_NOSPEC

Peter Zijlstra (1):
x86,nospec: Simplify {JMP,CALL}_NOSPEC

 arch/x86/include/asm/nospec-branch.h | 46 ++++++++++++++++++----------
 1 file changed, 30 insertions(+), 16 deletions(-)
Signature · 1 line
2.34.1
#1 lore raw

PATCH 1/4 x86,nospec: Simplify {JMP,CALL}_NOSPEC

From: Peter Zijlstra <[email protected]>

commit 09d09531a51a24635bc3331f56d92ee7092f5516 upstream.

Have {JMP,CALL}_NOSPEC generate the same code GCC does for indirect calls and rely on the objtool retpoline patching infrastructure.

There's no reason these should be alternatives while the vast bulk of compiler generated retpolines are not.

---
 arch/x86/include/asm/nospec-branch.h | 24 ++++++++++++++++++------
 1 file changed, 18 insertions(+), 6 deletions(-)
arch/x86/include/asm/nospec-branch.h +18 -6
index ce5e6e70d2a4..3434e5ebd3c7 100644
@@ -118,6 +118,19 @@
 #endif
 .endm
 
+/*
+ * Equivalent to -mindirect-branch-cs-prefix; emit the 5 byte jmp/call
+ * to the retpoline thunk with a CS prefix when the register requires
+ * a RAX prefix byte to encode. Also see apply_retpolines().
+ */
+.macro __CS_PREFIX reg:req
+	.irp rs,r8,r9,r10,r11,r12,r13,r14,r15
+	.ifc \reg,\rs
+	.byte 0x2e
+	.endif
+	.endr
+.endm
+
 /*
  * JMP_NOSPEC and CALL_NOSPEC macros can be used instead of a simple
  * indirect jmp/call which may be susceptible to the Spectre variant 2
@@ -125,19 +138,18 @@
  */
 .macro JMP_NOSPEC reg:req
 #ifdef CONFIG_RETPOLINE
-	ALTERNATIVE_2 __stringify(ANNOTATE_RETPOLINE_SAFE; jmp *%\reg), \
-		      __stringify(jmp __x86_indirect_thunk_\reg), X86_FEATURE_RETPOLINE, \
-		      __stringify(lfence; ANNOTATE_RETPOLINE_SAFE; jmp *%\reg), X86_FEATURE_RETPOLINE_LFENCE
+	__CS_PREFIX \reg
+	jmp	__x86_indirect_thunk_\reg
 #else
 	jmp	*%\reg
+	int3
 #endif
 .endm
 
 .macro CALL_NOSPEC reg:req
 #ifdef CONFIG_RETPOLINE
-	ALTERNATIVE_2 __stringify(ANNOTATE_RETPOLINE_SAFE; call *%\reg), \
-		      __stringify(call __x86_indirect_thunk_\reg), X86_FEATURE_RETPOLINE, \
-		      __stringify(lfence; ANNOTATE_RETPOLINE_SAFE; call *%\reg), X86_FEATURE_RETPOLINE_LFENCE
+	__CS_PREFIX \reg
+	call	__x86_indirect_thunk_\reg
 #else
 	call	*%\reg
 #endif
Signature · 1 line
2.34.1
#2 lore raw

PATCH 2/4 x86/speculation: Simplify and make CALL_NOSPEC consistent

In reply to Suraj Jitindar Singh

From: Pawan Gupta <[email protected]>

commit cfceff8526a426948b53445c02bcb98453c7330d upstream.

CALL_NOSPEC macro is used to generate Spectre-v2 mitigation friendly indirect branches. At compile time the macro defaults to indirect branch, and at runtime those can be patched to thunk based mitigations.

This approach is opposite of what is done for the rest of the kernel, where the compile time default is to replace indirect calls with retpoline thunk calls.

Make CALL_NOSPEC consistent with the rest of the kernel, default to retpoline thunk at compile time when CONFIG_MITIGATION_RETPOLINE is enabled.

---
 arch/x86/include/asm/nospec-branch.h | 15 +++++----------
 1 file changed, 5 insertions(+), 10 deletions(-)
arch/x86/include/asm/nospec-branch.h +5 -10
index 3434e5ebd3c7..bb7dd09dc295 100644
@@ -285,16 +285,11 @@ extern retpoline_thunk_t __x86_indirect_thunk_array[];
  * Inline asm uses the %V modifier which is only in newer GCC
  * which is ensured when CONFIG_RETPOLINE is defined.
  */
-# define CALL_NOSPEC						\
-	ALTERNATIVE_2(						\
-	ANNOTATE_RETPOLINE_SAFE					\
-	"call *%[thunk_target]\n",				\
-	"call __x86_indirect_thunk_%V[thunk_target]\n",		\
-	X86_FEATURE_RETPOLINE,					\
-	"lfence;\n"						\
-	ANNOTATE_RETPOLINE_SAFE					\
-	"call *%[thunk_target]\n",				\
-	X86_FEATURE_RETPOLINE_LFENCE)
+#ifdef CONFIG_RETPOLINE
+#define CALL_NOSPEC	"call __x86_indirect_thunk_%V[thunk_target]\n"
+#else
+#define CALL_NOSPEC	"call *%[thunk_target]\n"
+#endif
 
 # define THUNK_TARGET(addr) [thunk_target] "r" (addr)
 
Signature · 1 line
2.34.1
#3 lore raw

PATCH 3/4 x86/speculation: Add a conditional CS prefix to CALL_NOSPEC

In reply to Suraj Jitindar Singh

From: Pawan Gupta <[email protected]>

commit 052040e34c08428a5a388b85787e8531970c0c67 upstream.

Retpoline mitigation for spectre-v2 uses thunks for indirect branches. To support this mitigation compilers add a CS prefix with -mindirect-branch-cs-prefix. For an indirect branch in asm, this needs to be added manually.

CS prefix is already being added to indirect branches in asm files, but not in inline asm. Add CS prefix to CALL_NOSPEC for inline asm as well. There is no JMP_NOSPEC for inline asm.

---
 arch/x86/include/asm/nospec-branch.h | 19 +++++++++++++++----
 1 file changed, 15 insertions(+), 4 deletions(-)
arch/x86/include/asm/nospec-branch.h +15 -4
index bb7dd09dc295..2cade6749322 100644
@@ -119,9 +119,8 @@
 .endm
 
 /*
- * Equivalent to -mindirect-branch-cs-prefix; emit the 5 byte jmp/call
- * to the retpoline thunk with a CS prefix when the register requires
- * a RAX prefix byte to encode. Also see apply_retpolines().
+ * Emits a conditional CS prefix that is compatible with
+ * -mindirect-branch-cs-prefix.
  */
 .macro __CS_PREFIX reg:req
 	.irp rs,r8,r9,r10,r11,r12,r13,r14,r15
@@ -281,12 +280,24 @@ extern retpoline_thunk_t __x86_indirect_thunk_array[];
 
 #ifdef CONFIG_X86_64
 
+/*
+ * Emits a conditional CS prefix that is compatible with
+ * -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"
+
 /*
  * Inline asm uses the %V modifier which is only in newer GCC
  * which is ensured when CONFIG_RETPOLINE is defined.
  */
 #ifdef CONFIG_RETPOLINE
-#define CALL_NOSPEC	"call __x86_indirect_thunk_%V[thunk_target]\n"
+#define CALL_NOSPEC	__CS_PREFIX("%V[thunk_target]")	\
+			"call __x86_indirect_thunk_%V[thunk_target]\n"
 #else
 #define CALL_NOSPEC	"call *%[thunk_target]\n"
 #endif
Signature · 1 line
2.34.1
#4 lore raw

PATCH 4/4 x86/speculation: Remove the extra #ifdef around CALL_NOSPEC

In reply to Suraj Jitindar Singh

From: Pawan Gupta <[email protected]>

commit c8c81458863ab686cda4fe1e603fccaae0f12460 upstream.

Commit:

010c4a461c1d ("x86/speculation: Simplify and make CALL_NOSPEC consistent")

added an #ifdef CONFIG_MITIGATION_RETPOLINE around the CALL_NOSPEC definition. This is not required as this code is already under a larger #ifdef.

Remove the extra #ifdef, no functional change.

vmlinux size remains same before and after this change:

CONFIG_MITIGATION_RETPOLINE=y:

      text       data        bss         dec        hex    filename
  25434752    7342290    2301212    35078254    217406e    vmlinux.before
  25434752    7342290    2301212    35078254    217406e    vmlinux.after

# CONFIG_MITIGATION_RETPOLINE is not set:

      text       data        bss         dec        hex    filename
  22943094    6214994    1550152    30708240    1d49210    vmlinux.before
  22943094    6214994    1550152    30708240    1d49210    vmlinux.after
---
 arch/x86/include/asm/nospec-branch.h | 4 ----
 1 file changed, 4 deletions(-)
arch/x86/include/asm/nospec-branch.h +0 -4
index 2cade6749322..9f84a00776e2 100644
@@ -295,12 +295,8 @@ extern retpoline_thunk_t __x86_indirect_thunk_array[];
  * Inline asm uses the %V modifier which is only in newer GCC
  * which is ensured when CONFIG_RETPOLINE is defined.
  */
-#ifdef CONFIG_RETPOLINE
 #define CALL_NOSPEC	__CS_PREFIX("%V[thunk_target]")	\
 			"call __x86_indirect_thunk_%V[thunk_target]\n"
-#else
-#define CALL_NOSPEC	"call *%[thunk_target]\n"
-#endif
 
 # define THUNK_TARGET(addr) [thunk_target] "r" (addr)
 
Signature · 1 line
2.34.1
maintainer
#5 lore raw
In reply to Suraj Jitindar Singh
Quoted 11 lines · Suraj Jitindar Singh

The 4 patches in this series make the JMP_NOSPEC and CALL_NOSPEC macros used in the kernel consistent with what is generated by the compiler.

("x86,nospec: Simplify {JMP,CALL}_NOSPEC") was merged in v6.0 and the remaining 3 patches in this series were merged in v6.15. All 4 were included in kernels v5.15+ as prerequisites for the backport of the ITS mitigations [1].

None of these patches were included in the backport of the ITS mitigations to the 5.10 kernel [2]. They all apply cleanly and are applicable to the 5.10 kernel. Thus I see no reason that they weren't applied here, unless someone can correct me?

Do they actually fix anything?

Quoted 5 lines

I am sending them for inclusion in the 5.10 kernel as this kernel is still actively maintained for these kind of vulnerability mitigations and as such having these patches will unify the handling of these cases with subsequent kernel versions easing code understanding and the ease of backports in the future.

Does this actually allow this to happen? I think there are a few speculation fixes that have not been backported to this kernel tree, so why not just make this as a part of that work instead? Just adding infastructure that doesn't do anything isn't usually a good idea.

thanks,

greg k-h

#6 lore raw

Re: [PATCH 5.10 0/4] x86/speculation: Make {JMP, CALL}_NOSPEC Consistent

Quoted 26 lines · Greg KH

CAUTION: This email originated from outside of the organization. Do not click links or open attachments unless you can confirm the sender and know the content is safe.

Quoted 11 lines · Suraj Jitindar Singh

The 4 patches in this series make the JMP_NOSPEC and CALL_NOSPEC macros used
in the kernel consistent with what is generated by the compiler.

("x86,nospec: Simplify {JMP,CALL}_NOSPEC") was merged in v6.0 and the remaining
3 patches in this series were merged in v6.15. All 4 were included in kernels
v5.15+ as prerequisites for the backport of the ITS mitigations [1].

Quoted 7 lines

None of these patches were included in the backport of the ITS mitigations to
the 5.10 kernel [2]. They all apply cleanly and are applicable to the 5.10
kernel. Thus I see no reason that they weren't applied here, unless someone can
correct me?

Quoted 1 line

Do they actually fix anything?

They do not, no.

Quoted 11 lines
Quoted 10 lines

I am sending them for inclusion in the 5.10 kernel as this kernel is still
actively maintained for these kind of vulnerability mitigations and as such
having these patches will unify the handling of these cases with subsequent
kernel versions easing code understanding and the ease of backports in the
future.

Quoted 6 lines

Does this actually allow this to happen?  I think there are a few speculation fixes that have not been backported to this kernel tree, so
why not just make this as a part of that work instead?  Just adding infastructure that doesn't do anything isn't usually a good idea.

In my case at least, it does. I had to spend time working out why this code was different compared to newer stable and upstream, and determining if this required special handling - which would not have been necessary if this code was the same. Other speculation fixes don't touch this path which is why it was included in the ITS mitigation patch series for other stable versions. It does do something, any where the macros are used this does something and is then rewritten by the alternatives code.

Trying to save my own (and anyone elses) sanity for having to work out why this is different in the future in an area which does still get regularly touched for these old kernels. Understand it doesn't fit the regular stable patch mold but wanted to help in case these were just unintentionally missed in this stable stream. But I acknowledge as you point out that they are not fixing anything.

Suraj

Quoted 3 lines

thanks,

greg k-h

#7 lore raw

Re: [PATCH 5.10 0/4] x86/speculation: Make {JMP, CALL}_NOSPEC Consistent

Quoted 52 lines · Suraj
Quoted 20 lines · Greg KH
Quoted 11 lines · Suraj Jitindar Singh

The 4 patches in this series make the JMP_NOSPEC and CALL_NOSPEC macros used
in the kernel consistent with what is generated by the compiler.

("x86,nospec: Simplify {JMP,CALL}_NOSPEC") was merged in v6.0 and the remaining
3 patches in this series were merged in v6.15. All 4 were included in kernels
v5.15+ as prerequisites for the backport of the ITS mitigations [1].

Quoted 7 lines

None of these patches were included in the backport of the ITS mitigations to
the 5.10 kernel [2]. They all apply cleanly and are applicable to the 5.10
kernel. Thus I see no reason that they weren't applied here, unless someone can
correct me?

Quoted 1 line

Do they actually fix anything?

They do not, no.

Quoted 11 lines
Quoted 10 lines

I am sending them for inclusion in the 5.10 kernel as this kernel is still
actively maintained for these kind of vulnerability mitigations and as such
having these patches will unify the handling of these cases with subsequent
kernel versions easing code understanding and the ease of backports in the
future.

Quoted 6 lines

Does this actually allow this to happen?  I think there are a few speculation fixes that have not been backported to this kernel tree, so
why not just make this as a part of that work instead?  Just adding infastructure that doesn't do anything isn't usually a good idea.

In my case at least, it does. I had to spend time working out why this code was different compared to newer stable and upstream, and determining if this required special handling - which would not have been necessary if this code was the same. Other speculation fixes don't touch this path which is why it was included in the ITS mitigation patch series for other stable versions. It does do something, any where the macros are used this does something and is then rewritten by the alternatives code.

Quoted 6 lines

Trying to save my own (and anyone elses) sanity for having to work out why this is different in the future in an area which does still get regularly touched for these old kernels. Understand it doesn't fit the regular stable patch mold but wanted to help in case these were just unintentionally missed in this stable stream. But I acknowledge as you point out that they are not fixing anything.

If you want to include this as part of a patch series that does add additional speculation bugfixes, as it would make that series work easier, that's great, but on its own, it wouldn't make much sense to do this for no reason.

good luck with keeping this alive, that's not an easy task.

greg k-h

maintainer
#8 lore raw
In reply to Suraj Jitindar Singh
Quoted 12 lines · Suraj Jitindar Singh

The 4 patches in this series make the JMP_NOSPEC and CALL_NOSPEC macros used in the kernel consistent with what is generated by the compiler.

("x86,nospec: Simplify {JMP,CALL}_NOSPEC") was merged in v6.0 and the remaining 3 patches in this series were merged in v6.15. All 4 were included in kernels v5.15+ as prerequisites for the backport of the ITS mitigations [1].

None of these patches were included in the backport of the ITS mitigations to the 5.10 kernel [2]. They all apply cleanly and are applicable to the 5.10 kernel. Thus I see no reason that they weren't applied here, unless someone can correct me?

Quoted 5 lines

I am sending them for inclusion in the 5.10 kernel as this kernel is still actively maintained for these kind of vulnerability mitigations and as such having these patches will unify the handling of these cases with subsequent kernel versions easing code understanding and the ease of backports in the future.

Also, you only really have about 1 more year left for this kernel version, why not take the time to move any systems that are somehow still using this to a more modern kernel instead? What's preventing that from happening?

Running any x86 systems on this old kernel right now is probably not a good idea given the huge number of unfixed bugs in it...

thanks,

greg k-h

#9 lore raw

Re: [PATCH 5.10 0/4] x86/speculation: Make {JMP, CALL}_NOSPEC Consistent

Quoted 36 lines · Greg KH

CAUTION: This email originated from outside of the organization. Do not click links or open attachments unless you can confirm the sender and know the content is safe.

Quoted 19 lines · Suraj Jitindar Singh

The 4 patches in this series make the JMP_NOSPEC and CALL_NOSPEC macros used
in the kernel consistent with what is generated by the compiler.

("x86,nospec: Simplify {JMP,CALL}_NOSPEC") was merged in v6.0 and the remaining
3 patches in this series were merged in v6.15. All 4 were included in kernels
v5.15+ as prerequisites for the backport of the ITS mitigations [1].

None of these patches were included in the backport of the ITS mitigations to
the 5.10 kernel [2]. They all apply cleanly and are applicable to the 5.10
kernel. Thus I see no reason that they weren't applied here, unless someone can
correct me?

Quoted 9 lines

I am sending them for inclusion in the 5.10 kernel as this kernel is still
actively maintained for these kind of vulnerability mitigations and as such
having these patches will unify the handling of these cases with subsequent
kernel versions easing code understanding and the ease of backports in the
future.

Quoted 4 lines

Also, you only really have about 1 more year left for this kernel version, why not take the time to move any systems that are somehow still using this to a more modern kernel instead?  What's preventing that from happening?

You can lead a horse to water but you can't make it drink.

Quoted 5 lines

Running any x86 systems on this old kernel right now is probably not a
good idea given the huge number of unfixed bugs in it...

Aware of that and agree.

Suraj

Quoted 3 lines

thanks,

greg k-h

#10 lore raw

Re: [PATCH 5.10 0/4] x86/speculation: Make {JMP, CALL}_NOSPEC Consistent

Quoted 45 lines · Suraj
Quoted 36 lines · Greg KH

CAUTION: This email originated from outside of the organization. Do not click links or open attachments unless you can confirm the sender and know the content is safe.

Quoted 19 lines · Suraj Jitindar Singh

The 4 patches in this series make the JMP_NOSPEC and CALL_NOSPEC macros used
in the kernel consistent with what is generated by the compiler.

("x86,nospec: Simplify {JMP,CALL}_NOSPEC") was merged in v6.0 and the remaining
3 patches in this series were merged in v6.15. All 4 were included in kernels
v5.15+ as prerequisites for the backport of the ITS mitigations [1].

None of these patches were included in the backport of the ITS mitigations to
the 5.10 kernel [2]. They all apply cleanly and are applicable to the 5.10
kernel. Thus I see no reason that they weren't applied here, unless someone can
correct me?

Quoted 9 lines

I am sending them for inclusion in the 5.10 kernel as this kernel is still
actively maintained for these kind of vulnerability mitigations and as such
having these patches will unify the handling of these cases with subsequent
kernel versions easing code understanding and the ease of backports in the
future.

Quoted 4 lines

Also, you only really have about 1 more year left for this kernel version, why not take the time to move any systems that are somehow still using this to a more modern kernel instead?  What's preventing that from happening?

You can lead a horse to water but you can't make it drink.

Quoted 1 line
Quoted 6 lines
Quoted 4 lines

Running any x86 systems on this old kernel right now is probably not a
good idea given the huge number of unfixed bugs in it...

Aware of that and agree.

We have the tools that show just how many unfixed CVEs are in the current 5.10.y tree, doesn't that make anyone a bit nervous:

$ ./scripts/strak v5.10.244 | wc -l
1096

good luck!

greg k-h