* [PATCH] x86/speculation: Simplify and make CALL_NOSPEC consistent @ 2025-02-26 21:03 Pawan Gupta 2025-02-27 0:49 ` Andrew Cooper 0 siblings, 1 reply; 8+ messages in thread From: Pawan Gupta @ 2025-02-26 21:03 UTC (permalink / raw) To: x86, Josh Poimboeuf, Andrew Cooper; +Cc: linux-kernel 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. Also add the missing __CS_PREFIX to the CALL_NOSPEC macro. Signed-off-by: Pawan Gupta <pawan.kumar.gupta@linux.intel.com> --- arch/x86/include/asm/nospec-branch.h | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/arch/x86/include/asm/nospec-branch.h b/arch/x86/include/asm/nospec-branch.h index 7e8bf78c03d5..f12f83e7deb6 100644 --- a/arch/x86/include/asm/nospec-branch.h +++ b/arch/x86/include/asm/nospec-branch.h @@ -200,7 +200,7 @@ /* * 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(). + * a REX prefix byte to encode. Also see apply_retpolines(). */ .macro __CS_PREFIX reg:req .irp rs,r8,r9,r10,r11,r12,r13,r14,r15 @@ -420,20 +420,28 @@ static inline void call_depth_return_thunk(void) {} #ifdef CONFIG_X86_64 +/* + * 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 REX prefix byte to encode. Also see apply_retpolines(). + */ +#define __CS_PREFIX(reg) \ + .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 \ - 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_MITIGATION_RETPOLINE +#define CALL_NOSPEC __stringify(__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) --- base-commit: d082ecbc71e9e0bf49883ee4afd435a77a5101b6 change-id: 20250226-call-nospec-b94808f0dc75 Best regards, -- Thanks, Pawan ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] x86/speculation: Simplify and make CALL_NOSPEC consistent 2025-02-26 21:03 [PATCH] x86/speculation: Simplify and make CALL_NOSPEC consistent Pawan Gupta @ 2025-02-27 0:49 ` Andrew Cooper 2025-02-27 18:41 ` Pawan Gupta 0 siblings, 1 reply; 8+ messages in thread From: Andrew Cooper @ 2025-02-27 0:49 UTC (permalink / raw) To: Pawan Gupta, x86, Josh Poimboeuf; +Cc: linux-kernel On 26/02/2025 9:03 pm, Pawan Gupta wrote: > @@ -420,20 +420,28 @@ static inline void call_depth_return_thunk(void) {} > > #ifdef CONFIG_X86_64 > > +/* > + * 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 REX prefix byte to encode. Also see apply_retpolines(). > + */ Technically, both comments aren't quite accurate. __CS_PREFIX() emits a conditional CS prefix in a manner compatible with -mindirect-branch-cs-prefix, not the full 5/6 byte jmp/call. > +#define __CS_PREFIX(reg) \ > + .irp rs,r8,r9,r10,r11,r12,r13,r14,r15; \ > + .ifc \\rs, \reg; \ Why are these escaped differently? Given they're all \r of some form or another, I guess something is going wonky with __stringify(), but its still weird for them to be different. Do you have a fully pre-processed source to hand to see how CALL_NOSPEC ends up? ~Andrew ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] x86/speculation: Simplify and make CALL_NOSPEC consistent 2025-02-27 0:49 ` Andrew Cooper @ 2025-02-27 18:41 ` Pawan Gupta 2025-02-27 18:57 ` Andrew Cooper 0 siblings, 1 reply; 8+ messages in thread From: Pawan Gupta @ 2025-02-27 18:41 UTC (permalink / raw) To: Andrew Cooper; +Cc: x86, Josh Poimboeuf, linux-kernel On Thu, Feb 27, 2025 at 12:49:48AM +0000, Andrew Cooper wrote: > On 26/02/2025 9:03 pm, Pawan Gupta wrote: > > @@ -420,20 +420,28 @@ static inline void call_depth_return_thunk(void) {} > > > > #ifdef CONFIG_X86_64 > > > > +/* > > + * 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 REX prefix byte to encode. Also see apply_retpolines(). > > + */ > > Technically, both comments aren't quite accurate. __CS_PREFIX() emits a > conditional CS prefix in a manner compatible with > -mindirect-branch-cs-prefix, not the full 5/6 byte jmp/call. You are right, I will update the comment, and also the ASSEMBLY version where this comment came from: /* * 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 REX 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 > > +#define __CS_PREFIX(reg) \ > > + .irp rs,r8,r9,r10,r11,r12,r13,r14,r15; \ > > + .ifc \\rs, \reg; \ > > Why are these escaped differently? Given they're all \r of some form or > another, I guess something is going wonky with __stringify(), but its > still weird for them to be different. > > Do you have a fully pre-processed source to hand to see how CALL_NOSPEC > ends up? Below is the pre-processed source for test_cc() generated with "make arch/x86/kvm/emulate.i". - This is with double backslash in ".ifc \\rs, \reg": asm("push %[flags]; popf; " ".irp rs,r8,r9,r10,r11,r12,r13,r14,r15; .ifc \\rs, \%V[thunk_target]; .byte 0x2e; .endif; .endr;" "call __x86_indirect_thunk_%V[thunk_target]\n" ^ This ends up emitting the CS prefix byte correctly: 2e e8 51 c9 32 01 cs call ffffffff824289e0 - This is with single backslash in ".ifc \\rs, \reg": asm("push %[flags]; popf; " ".irp rs,r8,r9,r10,r11,r12,r13,r14,r15; .ifc \rs, \%V[thunk_target]; .byte 0x2e; .endif; .endr;" "c all __x86_indirect_thunk_%V[thunk_target]\n" ^ This version does not emit the CS prefix byte: e8 52 c9 32 01 call ffffffff824289e0 I tried looking in gcc inline assembly documentation but could not find anything that would explain this. :( ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] x86/speculation: Simplify and make CALL_NOSPEC consistent 2025-02-27 18:41 ` Pawan Gupta @ 2025-02-27 18:57 ` Andrew Cooper 2025-02-27 23:13 ` Pawan Gupta 0 siblings, 1 reply; 8+ messages in thread From: Andrew Cooper @ 2025-02-27 18:57 UTC (permalink / raw) To: Pawan Gupta; +Cc: x86, Josh Poimboeuf, linux-kernel On 27/02/2025 6:41 pm, Pawan Gupta wrote: > On Thu, Feb 27, 2025 at 12:49:48AM +0000, Andrew Cooper wrote: >> On 26/02/2025 9:03 pm, Pawan Gupta wrote: >>> @@ -420,20 +420,28 @@ static inline void call_depth_return_thunk(void) {} >>> >>> #ifdef CONFIG_X86_64 >>> >>> +/* >>> + * 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 REX prefix byte to encode. Also see apply_retpolines(). >>> + */ >> Technically, both comments aren't quite accurate. __CS_PREFIX() emits a >> conditional CS prefix in a manner compatible with >> -mindirect-branch-cs-prefix, not the full 5/6 byte jmp/call. > You are right, I will update the comment, and also the ASSEMBLY version > where this comment came from: > > /* > * 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 REX 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 > >>> +#define __CS_PREFIX(reg) \ >>> + .irp rs,r8,r9,r10,r11,r12,r13,r14,r15; \ >>> + .ifc \\rs, \reg; \ >> Why are these escaped differently? Given they're all \r of some form or >> another, I guess something is going wonky with __stringify(), but its >> still weird for them to be different. >> >> Do you have a fully pre-processed source to hand to see how CALL_NOSPEC >> ends up? > Below is the pre-processed source for test_cc() generated with "make arch/x86/kvm/emulate.i". > > - This is with double backslash in ".ifc \\rs, \reg": > > asm("push %[flags]; popf; " ".irp rs,r8,r9,r10,r11,r12,r13,r14,r15; .ifc \\rs, \%V[thunk_target]; .byte 0x2e; .endif; .endr;" "call __x86_indirect_thunk_%V[thunk_target]\n" > ^ > This ends up emitting the CS prefix byte correctly: > > 2e e8 51 c9 32 01 cs call ffffffff824289e0 > > - This is with single backslash in ".ifc \\rs, \reg": > > asm("push %[flags]; popf; " ".irp rs,r8,r9,r10,r11,r12,r13,r14,r15; .ifc \rs, \%V[thunk_target]; .byte 0x2e; .endif; .endr;" "c all __x86_indirect_thunk_%V[thunk_target]\n" > ^ > This version does not emit the CS prefix byte: > > e8 52 c9 32 01 call ffffffff824289e0 > > I tried looking in gcc inline assembly documentation but could not find > anything that would explain this. :( It's because it's about plain C strings. \r (from \rs) is Carriage Return (ASCII 0x0d). After AS's macro expansion, \reg becomes \% which is not a valid escape character, so the \ gets left intact. \reg should become \\reg or you'll probably get a compiler complaining eventually. ~Andrew ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] x86/speculation: Simplify and make CALL_NOSPEC consistent 2025-02-27 18:57 ` Andrew Cooper @ 2025-02-27 23:13 ` Pawan Gupta 2025-02-28 0:31 ` Pawan Gupta 0 siblings, 1 reply; 8+ messages in thread From: Pawan Gupta @ 2025-02-27 23:13 UTC (permalink / raw) To: Andrew Cooper; +Cc: x86, Josh Poimboeuf, linux-kernel On Thu, Feb 27, 2025 at 06:57:37PM +0000, Andrew Cooper wrote: > On 27/02/2025 6:41 pm, Pawan Gupta wrote: > > On Thu, Feb 27, 2025 at 12:49:48AM +0000, Andrew Cooper wrote: > >> On 26/02/2025 9:03 pm, Pawan Gupta wrote: > >>> @@ -420,20 +420,28 @@ static inline void call_depth_return_thunk(void) {} > >>> > >>> #ifdef CONFIG_X86_64 > >>> > >>> +/* > >>> + * 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 REX prefix byte to encode. Also see apply_retpolines(). > >>> + */ > >> Technically, both comments aren't quite accurate. __CS_PREFIX() emits a > >> conditional CS prefix in a manner compatible with > >> -mindirect-branch-cs-prefix, not the full 5/6 byte jmp/call. > > You are right, I will update the comment, and also the ASSEMBLY version > > where this comment came from: > > > > /* > > * 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 REX 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 > > > >>> +#define __CS_PREFIX(reg) \ > >>> + .irp rs,r8,r9,r10,r11,r12,r13,r14,r15; \ > >>> + .ifc \\rs, \reg; \ > >> Why are these escaped differently? Given they're all \r of some form or > >> another, I guess something is going wonky with __stringify(), but its > >> still weird for them to be different. > >> > >> Do you have a fully pre-processed source to hand to see how CALL_NOSPEC > >> ends up? > > Below is the pre-processed source for test_cc() generated with "make arch/x86/kvm/emulate.i". > > > > - This is with double backslash in ".ifc \\rs, \reg": > > > > asm("push %[flags]; popf; " ".irp rs,r8,r9,r10,r11,r12,r13,r14,r15; .ifc \\rs, \%V[thunk_target]; .byte 0x2e; .endif; .endr;" "call __x86_indirect_thunk_%V[thunk_target]\n" > > ^ > > This ends up emitting the CS prefix byte correctly: > > > > 2e e8 51 c9 32 01 cs call ffffffff824289e0 > > > > - This is with single backslash in ".ifc \\rs, \reg": > > > > asm("push %[flags]; popf; " ".irp rs,r8,r9,r10,r11,r12,r13,r14,r15; .ifc \rs, \%V[thunk_target]; .byte 0x2e; .endif; .endr;" "c all __x86_indirect_thunk_%V[thunk_target]\n" > > ^ > > This version does not emit the CS prefix byte: > > > > e8 52 c9 32 01 call ffffffff824289e0 > > > > I tried looking in gcc inline assembly documentation but could not find > > anything that would explain this. :( > > It's because it's about plain C strings. > > \r (from \rs) is Carriage Return (ASCII 0x0d). Ah, right. > After AS's macro expansion, \reg becomes \% which is not a valid escape > character, so the \ gets left intact. > > \reg should become \\reg or you'll probably get a compiler complaining > eventually. Using \\ for reg like this: .ifc \\rs, \\reg is not emitting the CS prefix. I am trying to wrap my head around the magic. Below is the pre-processor output: asm("push %[flags]; popf; " ".irp rs,r8,rax,r9,r10,r11,r12,r13,r14,r15; .ifc \\rs, \\%V[thunk_target]; .byte 0x2e; .endif; .end r;" "call __x86_indirect_thunk_%V[thunk_target]\n" : "=a"(rc), "+r" (current_stack_pointer) : [thunk_target]"r"(fop), [flags]"r"(flags)); ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] x86/speculation: Simplify and make CALL_NOSPEC consistent 2025-02-27 23:13 ` Pawan Gupta @ 2025-02-28 0:31 ` Pawan Gupta 2025-02-28 0:36 ` Andrew Cooper 0 siblings, 1 reply; 8+ messages in thread From: Pawan Gupta @ 2025-02-28 0:31 UTC (permalink / raw) To: Andrew Cooper; +Cc: x86, Josh Poimboeuf, linux-kernel On Thu, Feb 27, 2025 at 03:13:48PM -0800, Pawan Gupta wrote: > On Thu, Feb 27, 2025 at 06:57:37PM +0000, Andrew Cooper wrote: > > On 27/02/2025 6:41 pm, Pawan Gupta wrote: > > > On Thu, Feb 27, 2025 at 12:49:48AM +0000, Andrew Cooper wrote: > > >> On 26/02/2025 9:03 pm, Pawan Gupta wrote: > > >>> @@ -420,20 +420,28 @@ static inline void call_depth_return_thunk(void) {} > > >>> > > >>> #ifdef CONFIG_X86_64 > > >>> > > >>> +/* > > >>> + * 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 REX prefix byte to encode. Also see apply_retpolines(). > > >>> + */ > > >> Technically, both comments aren't quite accurate. __CS_PREFIX() emits a > > >> conditional CS prefix in a manner compatible with > > >> -mindirect-branch-cs-prefix, not the full 5/6 byte jmp/call. > > > You are right, I will update the comment, and also the ASSEMBLY version > > > where this comment came from: > > > > > > /* > > > * 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 REX 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 > > > > > >>> +#define __CS_PREFIX(reg) \ > > >>> + .irp rs,r8,r9,r10,r11,r12,r13,r14,r15; \ > > >>> + .ifc \\rs, \reg; \ > > >> Why are these escaped differently? Given they're all \r of some form or > > >> another, I guess something is going wonky with __stringify(), but its > > >> still weird for them to be different. > > >> > > >> Do you have a fully pre-processed source to hand to see how CALL_NOSPEC > > >> ends up? > > > Below is the pre-processed source for test_cc() generated with "make arch/x86/kvm/emulate.i". > > > > > > - This is with double backslash in ".ifc \\rs, \reg": > > > > > > asm("push %[flags]; popf; " ".irp rs,r8,r9,r10,r11,r12,r13,r14,r15; .ifc \\rs, \%V[thunk_target]; .byte 0x2e; .endif; .endr;" "call __x86_indirect_thunk_%V[thunk_target]\n" > > > ^ > > > This ends up emitting the CS prefix byte correctly: > > > > > > 2e e8 51 c9 32 01 cs call ffffffff824289e0 > > > > > > - This is with single backslash in ".ifc \\rs, \reg": > > > > > > asm("push %[flags]; popf; " ".irp rs,r8,r9,r10,r11,r12,r13,r14,r15; .ifc \rs, \%V[thunk_target]; .byte 0x2e; .endif; .endr;" "c all __x86_indirect_thunk_%V[thunk_target]\n" > > > ^ > > > This version does not emit the CS prefix byte: > > > > > > e8 52 c9 32 01 call ffffffff824289e0 > > > > > > I tried looking in gcc inline assembly documentation but could not find > > > anything that would explain this. :( > > > > It's because it's about plain C strings. > > > > \r (from \rs) is Carriage Return (ASCII 0x0d). > > Ah, right. > > > After AS's macro expansion, \reg becomes \% which is not a valid escape > > character, so the \ gets left intact. > > > > \reg should become \\reg or you'll probably get a compiler complaining > > eventually. > > Using \\ for reg like this: > > .ifc \\rs, \\reg > > is not emitting the CS prefix. I am trying to wrap my head around the > magic. Getting rid of one layer of macro makes it less magical: #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" #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 Preprocessor output is as expected, and this emits the CS prefix correctly: ".ifc \\rs, %V[thunk_target]" Full version: asm("push %[flags]; popf; " ".irp rs,r8,r9,r10,r11,r12,r13,r14,r15\n" ".ifc \\rs," "%V[thunk_target]" "\n" ".byte 0x2e\n" ".endif\n" ".endr\n" "call __x86_indirect_thunk_%V[thunk_target]\n" : "=a"(rc), "+r" (current_stack_pointer) : [thunk_target]"r"(fop), [flags]"r"(flags)); ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] x86/speculation: Simplify and make CALL_NOSPEC consistent 2025-02-28 0:31 ` Pawan Gupta @ 2025-02-28 0:36 ` Andrew Cooper 2025-02-28 1:06 ` Pawan Gupta 0 siblings, 1 reply; 8+ messages in thread From: Andrew Cooper @ 2025-02-28 0:36 UTC (permalink / raw) To: Pawan Gupta; +Cc: x86, Josh Poimboeuf, linux-kernel On 28/02/2025 12:31 am, Pawan Gupta wrote: > On Thu, Feb 27, 2025 at 03:13:48PM -0800, Pawan Gupta wrote: >> On Thu, Feb 27, 2025 at 06:57:37PM +0000, Andrew Cooper wrote: >>> On 27/02/2025 6:41 pm, Pawan Gupta wrote: >>>> On Thu, Feb 27, 2025 at 12:49:48AM +0000, Andrew Cooper wrote: >>>>> On 26/02/2025 9:03 pm, Pawan Gupta wrote: >>>>>> @@ -420,20 +420,28 @@ static inline void call_depth_return_thunk(void) {} >>>>>> >>>>>> #ifdef CONFIG_X86_64 >>>>>> >>>>>> +/* >>>>>> + * 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 REX prefix byte to encode. Also see apply_retpolines(). >>>>>> + */ >>>>> Technically, both comments aren't quite accurate. __CS_PREFIX() emits a >>>>> conditional CS prefix in a manner compatible with >>>>> -mindirect-branch-cs-prefix, not the full 5/6 byte jmp/call. >>>> You are right, I will update the comment, and also the ASSEMBLY version >>>> where this comment came from: >>>> >>>> /* >>>> * 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 REX 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 >>>> >>>>>> +#define __CS_PREFIX(reg) \ >>>>>> + .irp rs,r8,r9,r10,r11,r12,r13,r14,r15; \ >>>>>> + .ifc \\rs, \reg; \ >>>>> Why are these escaped differently? Given they're all \r of some form or >>>>> another, I guess something is going wonky with __stringify(), but its >>>>> still weird for them to be different. >>>>> >>>>> Do you have a fully pre-processed source to hand to see how CALL_NOSPEC >>>>> ends up? >>>> Below is the pre-processed source for test_cc() generated with "make arch/x86/kvm/emulate.i". >>>> >>>> - This is with double backslash in ".ifc \\rs, \reg": >>>> >>>> asm("push %[flags]; popf; " ".irp rs,r8,r9,r10,r11,r12,r13,r14,r15; .ifc \\rs, \%V[thunk_target]; .byte 0x2e; .endif; .endr;" "call __x86_indirect_thunk_%V[thunk_target]\n" >>>> ^ >>>> This ends up emitting the CS prefix byte correctly: >>>> >>>> 2e e8 51 c9 32 01 cs call ffffffff824289e0 >>>> >>>> - This is with single backslash in ".ifc \\rs, \reg": >>>> >>>> asm("push %[flags]; popf; " ".irp rs,r8,r9,r10,r11,r12,r13,r14,r15; .ifc \rs, \%V[thunk_target]; .byte 0x2e; .endif; .endr;" "c all __x86_indirect_thunk_%V[thunk_target]\n" >>>> ^ >>>> This version does not emit the CS prefix byte: >>>> >>>> e8 52 c9 32 01 call ffffffff824289e0 >>>> >>>> I tried looking in gcc inline assembly documentation but could not find >>>> anything that would explain this. :( >>> It's because it's about plain C strings. >>> >>> \r (from \rs) is Carriage Return (ASCII 0x0d). >> Ah, right. >> >>> After AS's macro expansion, \reg becomes \% which is not a valid escape >>> character, so the \ gets left intact. >>> >>> \reg should become \\reg or you'll probably get a compiler complaining >>> eventually. >> Using \\ for reg like this: >> >> .ifc \\rs, \\reg >> >> is not emitting the CS prefix. I am trying to wrap my head around the >> magic. > Getting rid of one layer of macro makes it less magical: > > #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" > > #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 > > Preprocessor output is as expected, and this emits the CS prefix correctly: > > ".ifc \\rs, %V[thunk_target]" > > Full version: > > asm("push %[flags]; popf; " ".irp rs,r8,r9,r10,r11,r12,r13,r14,r15\n" ".ifc \\rs," "%V[thunk_target]" "\n" ".byte 0x2e\n" ".endif\n" ".endr\n" "call __x86_indirect_thunk_%V[thunk_target]\n" > : "=a"(rc), "+r" (current_stack_pointer) : [thunk_target]"r"(fop), [flags]"r"(flags)); Yeah, I think that's a lot better. I still cant spot precisely what's wrong with the prior \\reg. ~Andrew ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] x86/speculation: Simplify and make CALL_NOSPEC consistent 2025-02-28 0:36 ` Andrew Cooper @ 2025-02-28 1:06 ` Pawan Gupta 0 siblings, 0 replies; 8+ messages in thread From: Pawan Gupta @ 2025-02-28 1:06 UTC (permalink / raw) To: Andrew Cooper; +Cc: x86, Josh Poimboeuf, linux-kernel On Fri, Feb 28, 2025 at 12:36:40AM +0000, Andrew Cooper wrote: > > Getting rid of one layer of macro makes it less magical: > > > > #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" > > > > #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 [...] > Yeah, I think that's a lot better. Ok, I will go with this approach for now. ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2025-02-28 1:06 UTC | newest] Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2025-02-26 21:03 [PATCH] x86/speculation: Simplify and make CALL_NOSPEC consistent Pawan Gupta 2025-02-27 0:49 ` Andrew Cooper 2025-02-27 18:41 ` Pawan Gupta 2025-02-27 18:57 ` Andrew Cooper 2025-02-27 23:13 ` Pawan Gupta 2025-02-28 0:31 ` Pawan Gupta 2025-02-28 0:36 ` Andrew Cooper 2025-02-28 1:06 ` Pawan Gupta
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®