* [PATCH RESEND v2 1/3] x86: Use MOVL when reading segment registers
@ 2026-01-05 9:02 Uros Bizjak
2026-01-05 9:02 ` [PATCH RESEND v2 2/3] x86/hyperv: Use savesegment() instead of inline asm() to save " Uros Bizjak
` (3 more replies)
0 siblings, 4 replies; 21+ messages in thread
From: Uros Bizjak @ 2026-01-05 9:02 UTC (permalink / raw)
To: linux-hyperv, x86, linux-kernel
Cc: Uros Bizjak, Michael Kelley, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, Dave Hansen, H. Peter Anvin
Use MOVL when reading segment registers to avoid 0x66 operand-size
override insn prefix. The segment value is always 16-bit and gets
zero-extended to the full 32-bit size.
Signed-off-by: Uros Bizjak <ubizjak@gmail.com>
Tested-by: Michael Kelley <mhklinux@outlook.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
---
arch/x86/include/asm/segment.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/x86/include/asm/segment.h b/arch/x86/include/asm/segment.h
index f59ae7186940..9f5be2bbd291 100644
--- a/arch/x86/include/asm/segment.h
+++ b/arch/x86/include/asm/segment.h
@@ -348,7 +348,7 @@ static inline void __loadsegment_fs(unsigned short value)
* Save a segment register away:
*/
#define savesegment(seg, value) \
- asm("mov %%" #seg ",%0":"=r" (value) : : "memory")
+ asm("movl %%" #seg ",%k0" : "=r" (value) : : "memory")
#endif /* !__ASSEMBLER__ */
#endif /* __KERNEL__ */
--
2.52.0
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH RESEND v2 2/3] x86/hyperv: Use savesegment() instead of inline asm() to save segment registers
2026-01-05 9:02 [PATCH RESEND v2 1/3] x86: Use MOVL when reading segment registers Uros Bizjak
@ 2026-01-05 9:02 ` Uros Bizjak
2026-01-19 16:22 ` H. Peter Anvin
2026-01-05 9:02 ` [PATCH RESEND v2 3/3] x86/hyperv: Remove ASM_CALL_CONSTRAINT with VMMCALL insn Uros Bizjak
` (2 subsequent siblings)
3 siblings, 1 reply; 21+ messages in thread
From: Uros Bizjak @ 2026-01-05 9:02 UTC (permalink / raw)
To: linux-hyperv, x86, linux-kernel
Cc: Uros Bizjak, Wei Liu, Michael Kelley, K. Y. Srinivasan,
Haiyang Zhang, Dexuan Cui, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, Dave Hansen, H. Peter Anvin
Use standard savesegment() utility macro to save segment registers.
Signed-off-by: Uros Bizjak <ubizjak@gmail.com>
Acked-by: Wei Liu <wei.liu@kernel.org>
Tested-by: Michael Kelley <mhklinux@outlook.com>
Cc: "K. Y. Srinivasan" <kys@microsoft.com>
Cc: Haiyang Zhang <haiyangz@microsoft.com>
Cc: Dexuan Cui <decui@microsoft.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
---
arch/x86/hyperv/ivm.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/arch/x86/hyperv/ivm.c b/arch/x86/hyperv/ivm.c
index 651771534cae..7365d8f43181 100644
--- a/arch/x86/hyperv/ivm.c
+++ b/arch/x86/hyperv/ivm.c
@@ -25,6 +25,7 @@
#include <asm/e820/api.h>
#include <asm/desc.h>
#include <asm/msr.h>
+#include <asm/segment.h>
#include <uapi/asm/vmx.h>
#ifdef CONFIG_AMD_MEM_ENCRYPT
@@ -315,16 +316,16 @@ int hv_snp_boot_ap(u32 apic_id, unsigned long start_ip, unsigned int cpu)
vmsa->gdtr.base = gdtr.address;
vmsa->gdtr.limit = gdtr.size;
- asm volatile("movl %%es, %%eax;" : "=a" (vmsa->es.selector));
+ savesegment(es, vmsa->es.selector);
hv_populate_vmcb_seg(vmsa->es, vmsa->gdtr.base);
- asm volatile("movl %%cs, %%eax;" : "=a" (vmsa->cs.selector));
+ savesegment(cs, vmsa->cs.selector);
hv_populate_vmcb_seg(vmsa->cs, vmsa->gdtr.base);
- asm volatile("movl %%ss, %%eax;" : "=a" (vmsa->ss.selector));
+ savesegment(ss, vmsa->ss.selector);
hv_populate_vmcb_seg(vmsa->ss, vmsa->gdtr.base);
- asm volatile("movl %%ds, %%eax;" : "=a" (vmsa->ds.selector));
+ savesegment(ds, vmsa->ds.selector);
hv_populate_vmcb_seg(vmsa->ds, vmsa->gdtr.base);
vmsa->efer = native_read_msr(MSR_EFER);
--
2.52.0
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH RESEND v2 3/3] x86/hyperv: Remove ASM_CALL_CONSTRAINT with VMMCALL insn
2026-01-05 9:02 [PATCH RESEND v2 1/3] x86: Use MOVL when reading segment registers Uros Bizjak
2026-01-05 9:02 ` [PATCH RESEND v2 2/3] x86/hyperv: Use savesegment() instead of inline asm() to save " Uros Bizjak
@ 2026-01-05 9:02 ` Uros Bizjak
2026-01-19 16:23 ` H. Peter Anvin
2026-01-19 16:22 ` [PATCH RESEND v2 1/3] x86: Use MOVL when reading segment registers H. Peter Anvin
2026-01-20 12:08 ` [tip: x86/cleanups] x86/segment: " tip-bot2 for Uros Bizjak
3 siblings, 1 reply; 21+ messages in thread
From: Uros Bizjak @ 2026-01-05 9:02 UTC (permalink / raw)
To: linux-hyperv, x86, linux-kernel
Cc: Uros Bizjak, Michael Kelley, K. Y. Srinivasan, Haiyang Zhang,
Wei Liu, Dexuan Cui, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, Dave Hansen, H. Peter Anvin
Unlike CALL instruction, VMMCALL does not push to the stack, so it's
OK to allow the compiler to insert it before the frame pointer gets
set up by the containing function. ASM_CALL_CONSTRAINT is for CALLs
that must be inserted after the frame pointer is set up, so it is
over-constraining here and can be removed.
Signed-off-by: Uros Bizjak <ubizjak@gmail.com>
Tested-by: Michael Kelley <mhklinux@outlook.com>
Cc: "K. Y. Srinivasan" <kys@microsoft.com>
Cc: Haiyang Zhang <haiyangz@microsoft.com>
Cc: Wei Liu <wei.liu@kernel.org>
Cc: Dexuan Cui <decui@microsoft.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
---
v2: Expand commit message and include ASM_CALL_CONSTRAINT explanation
---
arch/x86/hyperv/ivm.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/x86/hyperv/ivm.c b/arch/x86/hyperv/ivm.c
index 7365d8f43181..be7fad43a88d 100644
--- a/arch/x86/hyperv/ivm.c
+++ b/arch/x86/hyperv/ivm.c
@@ -392,7 +392,7 @@ u64 hv_snp_hypercall(u64 control, u64 param1, u64 param2)
register u64 __r8 asm("r8") = param2;
asm volatile("vmmcall"
- : "=a" (hv_status), ASM_CALL_CONSTRAINT,
+ : "=a" (hv_status),
"+c" (control), "+d" (param1), "+r" (__r8)
: : "cc", "memory", "r9", "r10", "r11");
--
2.52.0
^ permalink raw reply related [flat|nested] 21+ messages in thread
* Re: [PATCH RESEND v2 2/3] x86/hyperv: Use savesegment() instead of inline asm() to save segment registers
2026-01-05 9:02 ` [PATCH RESEND v2 2/3] x86/hyperv: Use savesegment() instead of inline asm() to save " Uros Bizjak
@ 2026-01-19 16:22 ` H. Peter Anvin
0 siblings, 0 replies; 21+ messages in thread
From: H. Peter Anvin @ 2026-01-19 16:22 UTC (permalink / raw)
To: Uros Bizjak, linux-hyperv, x86, linux-kernel
Cc: Wei Liu, Michael Kelley, K. Y. Srinivasan, Haiyang Zhang,
Dexuan Cui, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
Dave Hansen
On 2026-01-05 01:02, Uros Bizjak wrote:
> Use standard savesegment() utility macro to save segment registers.
>
> Signed-off-by: Uros Bizjak <ubizjak@gmail.com>
> Acked-by: Wei Liu <wei.liu@kernel.org>
> Tested-by: Michael Kelley <mhklinux@outlook.com>
> Cc: "K. Y. Srinivasan" <kys@microsoft.com>
> Cc: Haiyang Zhang <haiyangz@microsoft.com>
> Cc: Dexuan Cui <decui@microsoft.com>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Ingo Molnar <mingo@redhat.com>
> Cc: Borislav Petkov <bp@alien8.de>
> Cc: Dave Hansen <dave.hansen@linux.intel.com>
> Cc: "H. Peter Anvin" <hpa@zytor.com>
> ---
> arch/x86/hyperv/ivm.c | 9 +++++----
> 1 file changed, 5 insertions(+), 4 deletions(-)
>
Looks good to me.
Reviewed-by: H. Peter Anvin (Intel) <hpa@zytor.com>
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH RESEND v2 1/3] x86: Use MOVL when reading segment registers
2026-01-05 9:02 [PATCH RESEND v2 1/3] x86: Use MOVL when reading segment registers Uros Bizjak
2026-01-05 9:02 ` [PATCH RESEND v2 2/3] x86/hyperv: Use savesegment() instead of inline asm() to save " Uros Bizjak
2026-01-05 9:02 ` [PATCH RESEND v2 3/3] x86/hyperv: Remove ASM_CALL_CONSTRAINT with VMMCALL insn Uros Bizjak
@ 2026-01-19 16:22 ` H. Peter Anvin
2026-01-20 12:08 ` [tip: x86/cleanups] x86/segment: " tip-bot2 for Uros Bizjak
3 siblings, 0 replies; 21+ messages in thread
From: H. Peter Anvin @ 2026-01-19 16:22 UTC (permalink / raw)
To: Uros Bizjak, linux-hyperv, x86, linux-kernel
Cc: Michael Kelley, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
Dave Hansen
On 2026-01-05 01:02, Uros Bizjak wrote:
> Use MOVL when reading segment registers to avoid 0x66 operand-size
> override insn prefix. The segment value is always 16-bit and gets
> zero-extended to the full 32-bit size.
>
> Signed-off-by: Uros Bizjak <ubizjak@gmail.com>
> Tested-by: Michael Kelley <mhklinux@outlook.com>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Ingo Molnar <mingo@kernel.org>
> Cc: Borislav Petkov <bp@alien8.de>
> Cc: Dave Hansen <dave.hansen@linux.intel.com>
> Cc: "H. Peter Anvin" <hpa@zytor.com>
> ---
> arch/x86/include/asm/segment.h | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/arch/x86/include/asm/segment.h b/arch/x86/include/asm/segment.h
> index f59ae7186940..9f5be2bbd291 100644
> --- a/arch/x86/include/asm/segment.h
> +++ b/arch/x86/include/asm/segment.h
> @@ -348,7 +348,7 @@ static inline void __loadsegment_fs(unsigned short value)
> * Save a segment register away:
> */
> #define savesegment(seg, value) \
> - asm("mov %%" #seg ",%0":"=r" (value) : : "memory")
> + asm("movl %%" #seg ",%k0" : "=r" (value) : : "memory")
>
> #endif /* !__ASSEMBLER__ */
> #endif /* __KERNEL__ */
Looks good to me.
Reviewed-by: H. Peter Anvin (Intel) <hpa@zytor.com>
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH RESEND v2 3/3] x86/hyperv: Remove ASM_CALL_CONSTRAINT with VMMCALL insn
2026-01-05 9:02 ` [PATCH RESEND v2 3/3] x86/hyperv: Remove ASM_CALL_CONSTRAINT with VMMCALL insn Uros Bizjak
@ 2026-01-19 16:23 ` H. Peter Anvin
0 siblings, 0 replies; 21+ messages in thread
From: H. Peter Anvin @ 2026-01-19 16:23 UTC (permalink / raw)
To: Uros Bizjak, linux-hyperv, x86, linux-kernel
Cc: Michael Kelley, K. Y. Srinivasan, Haiyang Zhang, Wei Liu,
Dexuan Cui, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
Dave Hansen
On 2026-01-05 01:02, Uros Bizjak wrote:
> Unlike CALL instruction, VMMCALL does not push to the stack, so it's
> OK to allow the compiler to insert it before the frame pointer gets
> set up by the containing function. ASM_CALL_CONSTRAINT is for CALLs
> that must be inserted after the frame pointer is set up, so it is
> over-constraining here and can be removed.
>
> Signed-off-by: Uros Bizjak <ubizjak@gmail.com>
> Tested-by: Michael Kelley <mhklinux@outlook.com>
> Cc: "K. Y. Srinivasan" <kys@microsoft.com>
> Cc: Haiyang Zhang <haiyangz@microsoft.com>
> Cc: Wei Liu <wei.liu@kernel.org>
> Cc: Dexuan Cui <decui@microsoft.com>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Ingo Molnar <mingo@redhat.com>
> Cc: Borislav Petkov <bp@alien8.de>
> Cc: Dave Hansen <dave.hansen@linux.intel.com>
> Cc: "H. Peter Anvin" <hpa@zytor.com>
> ---
> v2: Expand commit message and include ASM_CALL_CONSTRAINT explanation
> ---
> arch/x86/hyperv/ivm.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/arch/x86/hyperv/ivm.c b/arch/x86/hyperv/ivm.c
> index 7365d8f43181..be7fad43a88d 100644
> --- a/arch/x86/hyperv/ivm.c
> +++ b/arch/x86/hyperv/ivm.c
> @@ -392,7 +392,7 @@ u64 hv_snp_hypercall(u64 control, u64 param1, u64 param2)
>
> register u64 __r8 asm("r8") = param2;
> asm volatile("vmmcall"
> - : "=a" (hv_status), ASM_CALL_CONSTRAINT,
> + : "=a" (hv_status),
> "+c" (control), "+d" (param1), "+r" (__r8)
> : : "cc", "memory", "r9", "r10", "r11");
>
Looks good to me; I'm not familiar directly with HyperV, but vmmcall is a
system call-type instruction which doesn't use the stack.
Acked-by: H. Peter Anvin (Intel) <hpa@zytor.com>
^ permalink raw reply [flat|nested] 21+ messages in thread
* [tip: x86/cleanups] x86/segment: Use MOVL when reading segment registers
2026-01-05 9:02 [PATCH RESEND v2 1/3] x86: Use MOVL when reading segment registers Uros Bizjak
` (2 preceding siblings ...)
2026-01-19 16:22 ` [PATCH RESEND v2 1/3] x86: Use MOVL when reading segment registers H. Peter Anvin
@ 2026-01-20 12:08 ` tip-bot2 for Uros Bizjak
2026-01-20 12:38 ` H. Peter Anvin
3 siblings, 1 reply; 21+ messages in thread
From: tip-bot2 for Uros Bizjak @ 2026-01-20 12:08 UTC (permalink / raw)
To: linux-tip-commits
Cc: Uros Bizjak, Borislav Petkov (AMD), H. Peter Anvin (Intel),
Michael Kelley, x86, linux-kernel
The following commit has been merged into the x86/cleanups branch of tip:
Commit-ID: 53ed3d91a141f5c8b3bce45b0004fbbfefe77956
Gitweb: https://git.kernel.org/tip/53ed3d91a141f5c8b3bce45b0004fbbfefe77956
Author: Uros Bizjak <ubizjak@gmail.com>
AuthorDate: Mon, 05 Jan 2026 10:02:32 +01:00
Committer: Borislav Petkov (AMD) <bp@alien8.de>
CommitterDate: Tue, 20 Jan 2026 12:34:58 +01:00
x86/segment: Use MOVL when reading segment registers
Use MOVL when reading segment registers to avoid 0x66 operand-size override
insn prefix. The segment value is always 16-bit and gets zero-extended to the
full 32-bit size.
Example:
4e4: 66 8c c0 mov %es,%ax
4e7: 66 89 83 80 0b 00 00 mov %ax,0xb80(%rbx)
4e4: 8c c0 mov %es,%eax
4e6: 66 89 83 80 0b 00 00 mov %ax,0xb80(%rbx)
Also, use the %k0 modifier which generates the SImode (signed integer)
register name for the target register.
[ bp: Extend and clarify commit message. ]
Signed-off-by: Uros Bizjak <ubizjak@gmail.com>
Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
Reviewed-by: H. Peter Anvin (Intel) <hpa@zytor.com>
Tested-by: Michael Kelley <mhklinux@outlook.com>
Link: https://patch.msgid.link/20260105090422.6243-1-ubizjak@gmail.com
---
arch/x86/include/asm/segment.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/x86/include/asm/segment.h b/arch/x86/include/asm/segment.h
index f59ae71..9f5be2b 100644
--- a/arch/x86/include/asm/segment.h
+++ b/arch/x86/include/asm/segment.h
@@ -348,7 +348,7 @@ static inline void __loadsegment_fs(unsigned short value)
* Save a segment register away:
*/
#define savesegment(seg, value) \
- asm("mov %%" #seg ",%0":"=r" (value) : : "memory")
+ asm("movl %%" #seg ",%k0" : "=r" (value) : : "memory")
#endif /* !__ASSEMBLER__ */
#endif /* __KERNEL__ */
^ permalink raw reply related [flat|nested] 21+ messages in thread
* Re: [tip: x86/cleanups] x86/segment: Use MOVL when reading segment registers
2026-01-20 12:08 ` [tip: x86/cleanups] x86/segment: " tip-bot2 for Uros Bizjak
@ 2026-01-20 12:38 ` H. Peter Anvin
2026-01-20 13:47 ` Uros Bizjak
` (2 more replies)
0 siblings, 3 replies; 21+ messages in thread
From: H. Peter Anvin @ 2026-01-20 12:38 UTC (permalink / raw)
To: linux-kernel, tip-bot2 for Uros Bizjak, linux-tip-commits
Cc: Uros Bizjak, Borislav Petkov (AMD), Michael Kelley, x86
On January 20, 2026 4:08:01 AM PST, tip-bot2 for Uros Bizjak <tip-bot2@linutronix.de> wrote:
>The following commit has been merged into the x86/cleanups branch of tip:
>
>Commit-ID: 53ed3d91a141f5c8b3bce45b0004fbbfefe77956
>Gitweb: https://git.kernel.org/tip/53ed3d91a141f5c8b3bce45b0004fbbfefe77956
>Author: Uros Bizjak <ubizjak@gmail.com>
>AuthorDate: Mon, 05 Jan 2026 10:02:32 +01:00
>Committer: Borislav Petkov (AMD) <bp@alien8.de>
>CommitterDate: Tue, 20 Jan 2026 12:34:58 +01:00
>
>x86/segment: Use MOVL when reading segment registers
>
>Use MOVL when reading segment registers to avoid 0x66 operand-size override
>insn prefix. The segment value is always 16-bit and gets zero-extended to the
>full 32-bit size.
>
>Example:
>
> 4e4: 66 8c c0 mov %es,%ax
> 4e7: 66 89 83 80 0b 00 00 mov %ax,0xb80(%rbx)
>
> 4e4: 8c c0 mov %es,%eax
> 4e6: 66 89 83 80 0b 00 00 mov %ax,0xb80(%rbx)
>
>Also, use the %k0 modifier which generates the SImode (signed integer)
>register name for the target register.
>
> [ bp: Extend and clarify commit message. ]
>
>Signed-off-by: Uros Bizjak <ubizjak@gmail.com>
>Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
>Reviewed-by: H. Peter Anvin (Intel) <hpa@zytor.com>
>Tested-by: Michael Kelley <mhklinux@outlook.com>
>Link: https://patch.msgid.link/20260105090422.6243-1-ubizjak@gmail.com
>---
> arch/x86/include/asm/segment.h | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
>diff --git a/arch/x86/include/asm/segment.h b/arch/x86/include/asm/segment.h
>index f59ae71..9f5be2b 100644
>--- a/arch/x86/include/asm/segment.h
>+++ b/arch/x86/include/asm/segment.h
>@@ -348,7 +348,7 @@ static inline void __loadsegment_fs(unsigned short value)
> * Save a segment register away:
> */
> #define savesegment(seg, value) \
>- asm("mov %%" #seg ",%0":"=r" (value) : : "memory")
>+ asm("movl %%" #seg ",%k0" : "=r" (value) : : "memory")
>
> #endif /* !__ASSEMBLER__ */
> #endif /* __KERNEL__ */
>
Incidentally, why aren't we using =rm here? Segment moves support memory operands.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [tip: x86/cleanups] x86/segment: Use MOVL when reading segment registers
2026-01-20 12:38 ` H. Peter Anvin
@ 2026-01-20 13:47 ` Uros Bizjak
2026-01-20 14:02 ` Uros Bizjak
2026-01-21 11:49 ` Brian Gerst
2026-03-12 9:30 ` Uros Bizjak
2 siblings, 1 reply; 21+ messages in thread
From: Uros Bizjak @ 2026-01-20 13:47 UTC (permalink / raw)
To: H. Peter Anvin
Cc: linux-kernel, tip-bot2 for Uros Bizjak, linux-tip-commits,
Borislav Petkov (AMD), Michael Kelley, x86
On Tue, Jan 20, 2026 at 1:38 PM H. Peter Anvin <hpa@zytor.com> wrote:
>
> On January 20, 2026 4:08:01 AM PST, tip-bot2 for Uros Bizjak <tip-bot2@linutronix.de> wrote:
> >The following commit has been merged into the x86/cleanups branch of tip:
> >
> >Commit-ID: 53ed3d91a141f5c8b3bce45b0004fbbfefe77956
> >Gitweb: https://git.kernel.org/tip/53ed3d91a141f5c8b3bce45b0004fbbfefe77956
> >Author: Uros Bizjak <ubizjak@gmail.com>
> >AuthorDate: Mon, 05 Jan 2026 10:02:32 +01:00
> >Committer: Borislav Petkov (AMD) <bp@alien8.de>
> >CommitterDate: Tue, 20 Jan 2026 12:34:58 +01:00
> >
> >x86/segment: Use MOVL when reading segment registers
> >
> >Use MOVL when reading segment registers to avoid 0x66 operand-size override
> >insn prefix. The segment value is always 16-bit and gets zero-extended to the
> >full 32-bit size.
> >
> >Example:
> >
> > 4e4: 66 8c c0 mov %es,%ax
> > 4e7: 66 89 83 80 0b 00 00 mov %ax,0xb80(%rbx)
> >
> > 4e4: 8c c0 mov %es,%eax
> > 4e6: 66 89 83 80 0b 00 00 mov %ax,0xb80(%rbx)
> >
> >Also, use the %k0 modifier which generates the SImode (signed integer)
> >register name for the target register.
> >
> > [ bp: Extend and clarify commit message. ]
> >
> >Signed-off-by: Uros Bizjak <ubizjak@gmail.com>
> >Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
> >Reviewed-by: H. Peter Anvin (Intel) <hpa@zytor.com>
> >Tested-by: Michael Kelley <mhklinux@outlook.com>
> >Link: https://patch.msgid.link/20260105090422.6243-1-ubizjak@gmail.com
> >---
> > arch/x86/include/asm/segment.h | 2 +-
> > 1 file changed, 1 insertion(+), 1 deletion(-)
> >
> >diff --git a/arch/x86/include/asm/segment.h b/arch/x86/include/asm/segment.h
> >index f59ae71..9f5be2b 100644
> >--- a/arch/x86/include/asm/segment.h
> >+++ b/arch/x86/include/asm/segment.h
> >@@ -348,7 +348,7 @@ static inline void __loadsegment_fs(unsigned short value)
> > * Save a segment register away:
> > */
> > #define savesegment(seg, value) \
> >- asm("mov %%" #seg ",%0":"=r" (value) : : "memory")
> >+ asm("movl %%" #seg ",%k0" : "=r" (value) : : "memory")
> >
> > #endif /* !__ASSEMBLER__ */
> > #endif /* __KERNEL__ */
> >
>
> Incidentally, why aren't we using =rm here? Segment moves support memory operands.
I have tried it with "=rm", and there were no cases when memory output
applies. Also, it would need to use ASM_OUTPUT_RM to handle clang
issues with memory output alternatives.
Uros.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [tip: x86/cleanups] x86/segment: Use MOVL when reading segment registers
2026-01-20 13:47 ` Uros Bizjak
@ 2026-01-20 14:02 ` Uros Bizjak
0 siblings, 0 replies; 21+ messages in thread
From: Uros Bizjak @ 2026-01-20 14:02 UTC (permalink / raw)
To: H. Peter Anvin
Cc: linux-kernel, tip-bot2 for Uros Bizjak, linux-tip-commits,
Borislav Petkov (AMD), Michael Kelley, x86
On Tue, Jan 20, 2026 at 2:47 PM Uros Bizjak <ubizjak@gmail.com> wrote:
>
> On Tue, Jan 20, 2026 at 1:38 PM H. Peter Anvin <hpa@zytor.com> wrote:
> >
> > On January 20, 2026 4:08:01 AM PST, tip-bot2 for Uros Bizjak <tip-bot2@linutronix.de> wrote:
> > >The following commit has been merged into the x86/cleanups branch of tip:
> > >
> > >Commit-ID: 53ed3d91a141f5c8b3bce45b0004fbbfefe77956
> > >Gitweb: https://git.kernel.org/tip/53ed3d91a141f5c8b3bce45b0004fbbfefe77956
> > >Author: Uros Bizjak <ubizjak@gmail.com>
> > >AuthorDate: Mon, 05 Jan 2026 10:02:32 +01:00
> > >Committer: Borislav Petkov (AMD) <bp@alien8.de>
> > >CommitterDate: Tue, 20 Jan 2026 12:34:58 +01:00
> > >
> > >x86/segment: Use MOVL when reading segment registers
> > >
> > >Use MOVL when reading segment registers to avoid 0x66 operand-size override
> > >insn prefix. The segment value is always 16-bit and gets zero-extended to the
> > >full 32-bit size.
> > >
> > >Example:
> > >
> > > 4e4: 66 8c c0 mov %es,%ax
> > > 4e7: 66 89 83 80 0b 00 00 mov %ax,0xb80(%rbx)
> > >
> > > 4e4: 8c c0 mov %es,%eax
> > > 4e6: 66 89 83 80 0b 00 00 mov %ax,0xb80(%rbx)
> > >
> > >Also, use the %k0 modifier which generates the SImode (signed integer)
> > >register name for the target register.
> > >
> > > [ bp: Extend and clarify commit message. ]
> > >
> > >Signed-off-by: Uros Bizjak <ubizjak@gmail.com>
> > >Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
> > >Reviewed-by: H. Peter Anvin (Intel) <hpa@zytor.com>
> > >Tested-by: Michael Kelley <mhklinux@outlook.com>
> > >Link: https://patch.msgid.link/20260105090422.6243-1-ubizjak@gmail.com
> > >---
> > > arch/x86/include/asm/segment.h | 2 +-
> > > 1 file changed, 1 insertion(+), 1 deletion(-)
> > >
> > >diff --git a/arch/x86/include/asm/segment.h b/arch/x86/include/asm/segment.h
> > >index f59ae71..9f5be2b 100644
> > >--- a/arch/x86/include/asm/segment.h
> > >+++ b/arch/x86/include/asm/segment.h
> > >@@ -348,7 +348,7 @@ static inline void __loadsegment_fs(unsigned short value)
> > > * Save a segment register away:
> > > */
> > > #define savesegment(seg, value) \
> > >- asm("mov %%" #seg ",%0":"=r" (value) : : "memory")
> > >+ asm("movl %%" #seg ",%k0" : "=r" (value) : : "memory")
> > >
> > > #endif /* !__ASSEMBLER__ */
> > > #endif /* __KERNEL__ */
> > >
> >
> > Incidentally, why aren't we using =rm here? Segment moves support memory operands.
>
> I have tried it with "=rm", and there were no cases when memory output
> applies. Also, it would need to use ASM_OUTPUT_RM to handle clang
> issues with memory output alternatives.
Also, savesegment() is defined as a macro, so e.g.:
--cut here--
#define savesegment(seg, value) \
asm("mov %%" #seg ",%0":"=rm" (value) : : "memory")
char c;
void foo (void)
{
savesegment (gs, c);
}
--cut here--
would result in a wrong code, where word sized 16-bit value is moved
to the location of "c".
Uros.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [tip: x86/cleanups] x86/segment: Use MOVL when reading segment registers
2026-01-20 12:38 ` H. Peter Anvin
2026-01-20 13:47 ` Uros Bizjak
@ 2026-01-21 11:49 ` Brian Gerst
2026-01-21 14:08 ` David Laight
2026-03-12 9:30 ` Uros Bizjak
2 siblings, 1 reply; 21+ messages in thread
From: Brian Gerst @ 2026-01-21 11:49 UTC (permalink / raw)
To: H. Peter Anvin
Cc: linux-kernel, tip-bot2 for Uros Bizjak, linux-tip-commits,
Uros Bizjak, Borislav Petkov (AMD), Michael Kelley, x86
On Wed, Jan 21, 2026 at 2:29 AM H. Peter Anvin <hpa@zytor.com> wrote:
>
> On January 20, 2026 4:08:01 AM PST, tip-bot2 for Uros Bizjak <tip-bot2@linutronix.de> wrote:
> >The following commit has been merged into the x86/cleanups branch of tip:
> >
> >Commit-ID: 53ed3d91a141f5c8b3bce45b0004fbbfefe77956
> >Gitweb: https://git.kernel.org/tip/53ed3d91a141f5c8b3bce45b0004fbbfefe77956
> >Author: Uros Bizjak <ubizjak@gmail.com>
> >AuthorDate: Mon, 05 Jan 2026 10:02:32 +01:00
> >Committer: Borislav Petkov (AMD) <bp@alien8.de>
> >CommitterDate: Tue, 20 Jan 2026 12:34:58 +01:00
> >
> >x86/segment: Use MOVL when reading segment registers
> >
> >Use MOVL when reading segment registers to avoid 0x66 operand-size override
> >insn prefix. The segment value is always 16-bit and gets zero-extended to the
> >full 32-bit size.
> >
> >Example:
> >
> > 4e4: 66 8c c0 mov %es,%ax
> > 4e7: 66 89 83 80 0b 00 00 mov %ax,0xb80(%rbx)
> >
> > 4e4: 8c c0 mov %es,%eax
> > 4e6: 66 89 83 80 0b 00 00 mov %ax,0xb80(%rbx)
> >
> >Also, use the %k0 modifier which generates the SImode (signed integer)
> >register name for the target register.
> >
> > [ bp: Extend and clarify commit message. ]
> >
> >Signed-off-by: Uros Bizjak <ubizjak@gmail.com>
> >Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
> >Reviewed-by: H. Peter Anvin (Intel) <hpa@zytor.com>
> >Tested-by: Michael Kelley <mhklinux@outlook.com>
> >Link: https://patch.msgid.link/20260105090422.6243-1-ubizjak@gmail.com
> >---
> > arch/x86/include/asm/segment.h | 2 +-
> > 1 file changed, 1 insertion(+), 1 deletion(-)
> >
> >diff --git a/arch/x86/include/asm/segment.h b/arch/x86/include/asm/segment.h
> >index f59ae71..9f5be2b 100644
> >--- a/arch/x86/include/asm/segment.h
> >+++ b/arch/x86/include/asm/segment.h
> >@@ -348,7 +348,7 @@ static inline void __loadsegment_fs(unsigned short value)
> > * Save a segment register away:
> > */
> > #define savesegment(seg, value) \
> >- asm("mov %%" #seg ",%0":"=r" (value) : : "memory")
> >+ asm("movl %%" #seg ",%k0" : "=r" (value) : : "memory")
> >
> > #endif /* !__ASSEMBLER__ */
> > #endif /* __KERNEL__ */
> >
>
> Incidentally, why aren't we using =rm here? Segment moves support memory operands.
You would have to be really careful to only use short (16-bit)
variables, because it will not zero-extend with a memory operand.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [tip: x86/cleanups] x86/segment: Use MOVL when reading segment registers
2026-01-21 11:49 ` Brian Gerst
@ 2026-01-21 14:08 ` David Laight
2026-01-21 16:16 ` Uros Bizjak
0 siblings, 1 reply; 21+ messages in thread
From: David Laight @ 2026-01-21 14:08 UTC (permalink / raw)
To: Brian Gerst
Cc: H. Peter Anvin, linux-kernel, tip-bot2 for Uros Bizjak,
linux-tip-commits, Uros Bizjak, Borislav Petkov (AMD),
Michael Kelley, x86
On Wed, 21 Jan 2026 06:49:16 -0500
Brian Gerst <brgerst@gmail.com> wrote:
> On Wed, Jan 21, 2026 at 2:29 AM H. Peter Anvin <hpa@zytor.com> wrote:
> >
> > On January 20, 2026 4:08:01 AM PST, tip-bot2 for Uros Bizjak <tip-bot2@linutronix.de> wrote:
> > >The following commit has been merged into the x86/cleanups branch of tip:
> > >
> > >Commit-ID: 53ed3d91a141f5c8b3bce45b0004fbbfefe77956
> > >Gitweb: https://git.kernel.org/tip/53ed3d91a141f5c8b3bce45b0004fbbfefe77956
> > >Author: Uros Bizjak <ubizjak@gmail.com>
> > >AuthorDate: Mon, 05 Jan 2026 10:02:32 +01:00
> > >Committer: Borislav Petkov (AMD) <bp@alien8.de>
> > >CommitterDate: Tue, 20 Jan 2026 12:34:58 +01:00
> > >
> > >x86/segment: Use MOVL when reading segment registers
> > >
> > >Use MOVL when reading segment registers to avoid 0x66 operand-size override
> > >insn prefix. The segment value is always 16-bit and gets zero-extended to the
> > >full 32-bit size.
> > >
> > >Example:
> > >
> > > 4e4: 66 8c c0 mov %es,%ax
> > > 4e7: 66 89 83 80 0b 00 00 mov %ax,0xb80(%rbx)
> > >
> > > 4e4: 8c c0 mov %es,%eax
> > > 4e6: 66 89 83 80 0b 00 00 mov %ax,0xb80(%rbx)
> > >
> > >Also, use the %k0 modifier which generates the SImode (signed integer)
> > >register name for the target register.
> > >
> > > [ bp: Extend and clarify commit message. ]
> > >
> > >Signed-off-by: Uros Bizjak <ubizjak@gmail.com>
> > >Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
> > >Reviewed-by: H. Peter Anvin (Intel) <hpa@zytor.com>
> > >Tested-by: Michael Kelley <mhklinux@outlook.com>
> > >Link: https://patch.msgid.link/20260105090422.6243-1-ubizjak@gmail.com
> > >---
> > > arch/x86/include/asm/segment.h | 2 +-
> > > 1 file changed, 1 insertion(+), 1 deletion(-)
> > >
> > >diff --git a/arch/x86/include/asm/segment.h b/arch/x86/include/asm/segment.h
> > >index f59ae71..9f5be2b 100644
> > >--- a/arch/x86/include/asm/segment.h
> > >+++ b/arch/x86/include/asm/segment.h
> > >@@ -348,7 +348,7 @@ static inline void __loadsegment_fs(unsigned short value)
> > > * Save a segment register away:
> > > */
> > > #define savesegment(seg, value) \
> > >- asm("mov %%" #seg ",%0":"=r" (value) : : "memory")
> > >+ asm("movl %%" #seg ",%k0" : "=r" (value) : : "memory")
> > >
> > > #endif /* !__ASSEMBLER__ */
> > > #endif /* __KERNEL__ */
> > >
> >
> > Incidentally, why aren't we using =rm here? Segment moves support memory operands.
>
> You would have to be really careful to only use short (16-bit)
> variables, because it will not zero-extend with a memory operand.
>
It would be much safer to have something that returned the value
of the segment register (zero extended to 32 bits).
David
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [tip: x86/cleanups] x86/segment: Use MOVL when reading segment registers
2026-01-21 14:08 ` David Laight
@ 2026-01-21 16:16 ` Uros Bizjak
2026-01-21 18:55 ` David Laight
0 siblings, 1 reply; 21+ messages in thread
From: Uros Bizjak @ 2026-01-21 16:16 UTC (permalink / raw)
To: David Laight
Cc: Brian Gerst, H. Peter Anvin, linux-kernel,
tip-bot2 for Uros Bizjak, linux-tip-commits,
Borislav Petkov (AMD), Michael Kelley, x86
On Wed, Jan 21, 2026 at 5:06 PM David Laight
<david.laight.linux@gmail.com> wrote:
>
> On Wed, 21 Jan 2026 06:49:16 -0500
> Brian Gerst <brgerst@gmail.com> wrote:
>
> > On Wed, Jan 21, 2026 at 2:29 AM H. Peter Anvin <hpa@zytor.com> wrote:
> > >
> > > On January 20, 2026 4:08:01 AM PST, tip-bot2 for Uros Bizjak <tip-bot2@linutronix.de> wrote:
> > > >The following commit has been merged into the x86/cleanups branch of tip:
> > > >
> > > >Commit-ID: 53ed3d91a141f5c8b3bce45b0004fbbfefe77956
> > > >Gitweb: https://git.kernel.org/tip/53ed3d91a141f5c8b3bce45b0004fbbfefe77956
> > > >Author: Uros Bizjak <ubizjak@gmail.com>
> > > >AuthorDate: Mon, 05 Jan 2026 10:02:32 +01:00
> > > >Committer: Borislav Petkov (AMD) <bp@alien8.de>
> > > >CommitterDate: Tue, 20 Jan 2026 12:34:58 +01:00
> > > >
> > > >x86/segment: Use MOVL when reading segment registers
> > > >
> > > >Use MOVL when reading segment registers to avoid 0x66 operand-size override
> > > >insn prefix. The segment value is always 16-bit and gets zero-extended to the
> > > >full 32-bit size.
> > > >
> > > >Example:
> > > >
> > > > 4e4: 66 8c c0 mov %es,%ax
> > > > 4e7: 66 89 83 80 0b 00 00 mov %ax,0xb80(%rbx)
> > > >
> > > > 4e4: 8c c0 mov %es,%eax
> > > > 4e6: 66 89 83 80 0b 00 00 mov %ax,0xb80(%rbx)
> > > >
> > > >Also, use the %k0 modifier which generates the SImode (signed integer)
> > > >register name for the target register.
> > > >
> > > > [ bp: Extend and clarify commit message. ]
> > > >
> > > >Signed-off-by: Uros Bizjak <ubizjak@gmail.com>
> > > >Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
> > > >Reviewed-by: H. Peter Anvin (Intel) <hpa@zytor.com>
> > > >Tested-by: Michael Kelley <mhklinux@outlook.com>
> > > >Link: https://patch.msgid.link/20260105090422.6243-1-ubizjak@gmail.com
> > > >---
> > > > arch/x86/include/asm/segment.h | 2 +-
> > > > 1 file changed, 1 insertion(+), 1 deletion(-)
> > > >
> > > >diff --git a/arch/x86/include/asm/segment.h b/arch/x86/include/asm/segment.h
> > > >index f59ae71..9f5be2b 100644
> > > >--- a/arch/x86/include/asm/segment.h
> > > >+++ b/arch/x86/include/asm/segment.h
> > > >@@ -348,7 +348,7 @@ static inline void __loadsegment_fs(unsigned short value)
> > > > * Save a segment register away:
> > > > */
> > > > #define savesegment(seg, value) \
> > > >- asm("mov %%" #seg ",%0":"=r" (value) : : "memory")
> > > >+ asm("movl %%" #seg ",%k0" : "=r" (value) : : "memory")
> > > >
> > > > #endif /* !__ASSEMBLER__ */
> > > > #endif /* __KERNEL__ */
> > > >
> > >
> > > Incidentally, why aren't we using =rm here? Segment moves support memory operands.
> >
> > You would have to be really careful to only use short (16-bit)
> > variables, because it will not zero-extend with a memory operand.
> >
>
> It would be much safer to have something that returned the value
> of the segment register (zero extended to 32 bits).
movl from %seg to 32-bit register (as proposed in the patch)
zero-extends the value all the way to word size (64-bits on x86_64).
The proposed solution also handles memory operands, so:
--cut here--
unsigned int m;
void foo(void)
{
asm("mov %%gs,%k0" : "=r"(m));
}
--cut here--
compiles to optimal code:
0000000000000000 <foo>:
0: 8c e8 mov %gs,%eax
2: 89 05 00 00 00 00 mov %eax,0x0(%rip) # 8 <foo+0x8>
4: R_X86_64_PC32 m-0x4
8: c3 ret
Uros.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [tip: x86/cleanups] x86/segment: Use MOVL when reading segment registers
2026-01-21 16:16 ` Uros Bizjak
@ 2026-01-21 18:55 ` David Laight
0 siblings, 0 replies; 21+ messages in thread
From: David Laight @ 2026-01-21 18:55 UTC (permalink / raw)
To: Uros Bizjak
Cc: Brian Gerst, H. Peter Anvin, linux-kernel,
tip-bot2 for Uros Bizjak, linux-tip-commits,
Borislav Petkov (AMD), Michael Kelley, x86
On Wed, 21 Jan 2026 17:16:53 +0100
Uros Bizjak <ubizjak@gmail.com> wrote:
> On Wed, Jan 21, 2026 at 5:06 PM David Laight
> <david.laight.linux@gmail.com> wrote:
> >
> > On Wed, 21 Jan 2026 06:49:16 -0500
> > Brian Gerst <brgerst@gmail.com> wrote:
> >
> > > On Wed, Jan 21, 2026 at 2:29 AM H. Peter Anvin <hpa@zytor.com> wrote:
> > > >
> > > > On January 20, 2026 4:08:01 AM PST, tip-bot2 for Uros Bizjak <tip-bot2@linutronix.de> wrote:
> > > > >The following commit has been merged into the x86/cleanups branch of tip:
> > > > >
> > > > >Commit-ID: 53ed3d91a141f5c8b3bce45b0004fbbfefe77956
> > > > >Gitweb: https://git.kernel.org/tip/53ed3d91a141f5c8b3bce45b0004fbbfefe77956
> > > > >Author: Uros Bizjak <ubizjak@gmail.com>
> > > > >AuthorDate: Mon, 05 Jan 2026 10:02:32 +01:00
> > > > >Committer: Borislav Petkov (AMD) <bp@alien8.de>
> > > > >CommitterDate: Tue, 20 Jan 2026 12:34:58 +01:00
> > > > >
> > > > >x86/segment: Use MOVL when reading segment registers
> > > > >
> > > > >Use MOVL when reading segment registers to avoid 0x66 operand-size override
> > > > >insn prefix. The segment value is always 16-bit and gets zero-extended to the
> > > > >full 32-bit size.
> > > > >
> > > > >Example:
> > > > >
> > > > > 4e4: 66 8c c0 mov %es,%ax
> > > > > 4e7: 66 89 83 80 0b 00 00 mov %ax,0xb80(%rbx)
> > > > >
> > > > > 4e4: 8c c0 mov %es,%eax
> > > > > 4e6: 66 89 83 80 0b 00 00 mov %ax,0xb80(%rbx)
> > > > >
> > > > >Also, use the %k0 modifier which generates the SImode (signed integer)
> > > > >register name for the target register.
> > > > >
> > > > > [ bp: Extend and clarify commit message. ]
> > > > >
> > > > >Signed-off-by: Uros Bizjak <ubizjak@gmail.com>
> > > > >Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
> > > > >Reviewed-by: H. Peter Anvin (Intel) <hpa@zytor.com>
> > > > >Tested-by: Michael Kelley <mhklinux@outlook.com>
> > > > >Link: https://patch.msgid.link/20260105090422.6243-1-ubizjak@gmail.com
> > > > >---
> > > > > arch/x86/include/asm/segment.h | 2 +-
> > > > > 1 file changed, 1 insertion(+), 1 deletion(-)
> > > > >
> > > > >diff --git a/arch/x86/include/asm/segment.h b/arch/x86/include/asm/segment.h
> > > > >index f59ae71..9f5be2b 100644
> > > > >--- a/arch/x86/include/asm/segment.h
> > > > >+++ b/arch/x86/include/asm/segment.h
> > > > >@@ -348,7 +348,7 @@ static inline void __loadsegment_fs(unsigned short value)
> > > > > * Save a segment register away:
> > > > > */
> > > > > #define savesegment(seg, value) \
> > > > >- asm("mov %%" #seg ",%0":"=r" (value) : : "memory")
> > > > >+ asm("movl %%" #seg ",%k0" : "=r" (value) : : "memory")
> > > > >
> > > > > #endif /* !__ASSEMBLER__ */
> > > > > #endif /* __KERNEL__ */
> > > > >
> > > >
> > > > Incidentally, why aren't we using =rm here? Segment moves support memory operands.
> > >
> > > You would have to be really careful to only use short (16-bit)
> > > variables, because it will not zero-extend with a memory operand.
> > >
> >
> > It would be much safer to have something that returned the value
> > of the segment register (zero extended to 32 bits).
>
> movl from %seg to 32-bit register (as proposed in the patch)
> zero-extends the value all the way to word size (64-bits on x86_64).
> The proposed solution also handles memory operands, so:
>
> --cut here--
> unsigned int m;
>
> void foo(void)
> {
> asm("mov %%gs,%k0" : "=r"(m));
> }
> --cut here--
>
> compiles to optimal code:
>
> 0000000000000000 <foo>:
> 0: 8c e8 mov %gs,%eax
> 2: 89 05 00 00 00 00 mov %eax,0x0(%rip) # 8 <foo+0x8>
> 4: R_X86_64_PC32 m-0x4
> 8: c3 ret
>
> Uros.
As does this version:
unsigned int m;
#define get_seg(seg) ({ \
unsigned int _seg_val; \
asm("mov %%" #seg ",%k0" : "=r"(_seg_val)); \
_seg_val; \
})
void bar(void)
{
m = get_seg(gs);
}
bar:
movl %gs, %eax
movl %eax, m(%rip)
retq
Without the hidden lvalue.
David
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [tip: x86/cleanups] x86/segment: Use MOVL when reading segment registers
2026-01-20 12:38 ` H. Peter Anvin
2026-01-20 13:47 ` Uros Bizjak
2026-01-21 11:49 ` Brian Gerst
@ 2026-03-12 9:30 ` Uros Bizjak
2026-03-12 18:55 ` H. Peter Anvin
` (2 more replies)
2 siblings, 3 replies; 21+ messages in thread
From: Uros Bizjak @ 2026-03-12 9:30 UTC (permalink / raw)
To: H. Peter Anvin
Cc: linux-kernel, Borislav Petkov (AMD), x86, Dave Hansen,
Ingo Molnar, Thomas Gleixner, Peter Zijlstra, David Laight
[-- Attachment #1: Type: text/plain, Size: 4137 bytes --]
On Tue, Jan 20, 2026 at 1:38 PM H. Peter Anvin <hpa@zytor.com> wrote:
>
> On January 20, 2026 4:08:01 AM PST, tip-bot2 for Uros Bizjak <tip-bot2@linutronix.de> wrote:
> >The following commit has been merged into the x86/cleanups branch of tip:
> >
> >Commit-ID: 53ed3d91a141f5c8b3bce45b0004fbbfefe77956
> >Gitweb: https://git.kernel.org/tip/53ed3d91a141f5c8b3bce45b0004fbbfefe77956
> >Author: Uros Bizjak <ubizjak@gmail.com>
> >AuthorDate: Mon, 05 Jan 2026 10:02:32 +01:00
> >Committer: Borislav Petkov (AMD) <bp@alien8.de>
> >CommitterDate: Tue, 20 Jan 2026 12:34:58 +01:00
> >
> >x86/segment: Use MOVL when reading segment registers
> >
> >Use MOVL when reading segment registers to avoid 0x66 operand-size override
> >insn prefix. The segment value is always 16-bit and gets zero-extended to the
> >full 32-bit size.
> >
> >Example:
> >
> > 4e4: 66 8c c0 mov %es,%ax
> > 4e7: 66 89 83 80 0b 00 00 mov %ax,0xb80(%rbx)
> >
> > 4e4: 8c c0 mov %es,%eax
> > 4e6: 66 89 83 80 0b 00 00 mov %ax,0xb80(%rbx)
> >
> >Also, use the %k0 modifier which generates the SImode (signed integer)
> >register name for the target register.
> >
> > [ bp: Extend and clarify commit message. ]
> >
> >Signed-off-by: Uros Bizjak <ubizjak@gmail.com>
> >Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
> >Reviewed-by: H. Peter Anvin (Intel) <hpa@zytor.com>
> >Tested-by: Michael Kelley <mhklinux@outlook.com>
> >Link: https://patch.msgid.link/20260105090422.6243-1-ubizjak@gmail.com
> >---
> > arch/x86/include/asm/segment.h | 2 +-
> > 1 file changed, 1 insertion(+), 1 deletion(-)
> >
> >diff --git a/arch/x86/include/asm/segment.h b/arch/x86/include/asm/segment.h
> >index f59ae71..9f5be2b 100644
> >--- a/arch/x86/include/asm/segment.h
> >+++ b/arch/x86/include/asm/segment.h
> >@@ -348,7 +348,7 @@ static inline void __loadsegment_fs(unsigned short value)
> > * Save a segment register away:
> > */
> > #define savesegment(seg, value) \
> >- asm("mov %%" #seg ",%0":"=r" (value) : : "memory")
> >+ asm("movl %%" #seg ",%k0" : "=r" (value) : : "memory")
> >
> > #endif /* !__ASSEMBLER__ */
> > #endif /* __KERNEL__ */
> >
>
> Incidentally, why aren't we using =rm here? Segment moves support memory operands.
Resurrecting an old thread.
We would like to always use MOVL to avoid 0x66 operand size override
prefix when reading to a register, but MOVL does not support memory
operands. MOVW is required in this case.
Also note that both GCC and clang have their own share of problems
with "=rm" output asm constraints. GCC mostly prefers register output
and clang prefers memory output.
So, due to the above reasons, the compilation results in unoptimal
code, e.g: current_save_fsgs() compiles to:
32333: 8c e0 mov %fs,%eax
32335: 66 89 82 0c 0c 00 00 mov %ax,0xc0c(%rdx)
3233c: 8c e8 mov %gs,%eax
3233e: 66 89 82 0e 0c 00 00 mov %ax,0xc0e(%rdx)
To solve the above issue, I'd like to propose a specialized
__savesegment() macro that would allow optimized save to a memory
location:
#define __savesegment(seg, loc) \
do { \
BUILD_BUG_ON(sizeof(loc) != 2); \
asm volatile("movw %%" #seg ",%0" : "=m" (loc)); \
} while (0)
so one can use this variant when the segment register is really saved
to a memory. The above code improves to:
32333: 8c a2 0c 0c 00 00 mov %fs,0xc0c(%rdx)
32339: 8c aa 0e 0c 00 00 mov %gs,0xc0e(%rdx)
Unfortunately, inline asm does not support alternative instructions
that would depend on output argument type (reg vs mem), so the
selection can not be automatic. But by having specialized macro, a
developer can use the variant that results in the most optimal code.
A prototype patch is attached to the message.
Uros.
[-- Attachment #2: p.diff.txt --]
[-- Type: text/plain, Size: 716 bytes --]
diff --git a/arch/x86/include/asm/segment.h b/arch/x86/include/asm/segment.h
index 0f4283dcd0c4..82cb692da116 100644
--- a/arch/x86/include/asm/segment.h
+++ b/arch/x86/include/asm/segment.h
@@ -347,8 +347,14 @@ static inline void __loadsegment_fs(unsigned short value)
/*
* Save a segment register away:
*/
-#define savesegment(seg, value) \
- asm volatile("movl %%" #seg ",%k0" : "=r" (value))
+#define savesegment(seg, var) \
+ asm volatile("movl %%" #seg ",%k0" : "=r" (var))
+
+#define __savesegment(seg, loc) \
+do { \
+ BUILD_BUG_ON(sizeof(loc) != 2); \
+ asm volatile("movw %%" #seg ",%0" : "=m" (loc)); \
+} while (0)
#endif /* !__ASSEMBLER__ */
#endif /* __KERNEL__ */
^ permalink raw reply related [flat|nested] 21+ messages in thread
* Re: [tip: x86/cleanups] x86/segment: Use MOVL when reading segment registers
2026-03-12 9:30 ` Uros Bizjak
@ 2026-03-12 18:55 ` H. Peter Anvin
2026-03-12 19:38 ` Uros Bizjak
2026-03-12 18:56 ` H. Peter Anvin
2026-03-12 19:11 ` H. Peter Anvin
2 siblings, 1 reply; 21+ messages in thread
From: H. Peter Anvin @ 2026-03-12 18:55 UTC (permalink / raw)
To: Uros Bizjak
Cc: linux-kernel, Borislav Petkov (AMD), x86, Dave Hansen,
Ingo Molnar, Thomas Gleixner, Peter Zijlstra, David Laight
On 2026-03-12 02:30, Uros Bizjak wrote:
>
> We would like to always use MOVL to avoid 0x66 operand size override
> prefix when reading to a register, but MOVL does not support memory
> operands. MOVW is required in this case.
>
Just use "mov" without any suffix.
GAS LISTING movseg.s page 1
1 .text
2
3 0000 8CD8 mov %ds,%eax
4 0002 668CD8 mov %ds,%ax
5 0005 8C1B mov %ds,(%rbx)
-hpa
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [tip: x86/cleanups] x86/segment: Use MOVL when reading segment registers
2026-03-12 9:30 ` Uros Bizjak
2026-03-12 18:55 ` H. Peter Anvin
@ 2026-03-12 18:56 ` H. Peter Anvin
2026-03-12 19:11 ` H. Peter Anvin
2 siblings, 0 replies; 21+ messages in thread
From: H. Peter Anvin @ 2026-03-12 18:56 UTC (permalink / raw)
To: Uros Bizjak
Cc: linux-kernel, Borislav Petkov (AMD), x86, Dave Hansen,
Ingo Molnar, Thomas Gleixner, Peter Zijlstra, David Laight
On 2026-03-12 02:30, Uros Bizjak wrote:
>
> so one can use this variant when the segment register is really saved
> to a memory. The above code improves to:
>
> 32333: 8c a2 0c 0c 00 00 mov %fs,0xc0c(%rdx)
> 32339: 8c aa 0e 0c 00 00 mov %gs,0xc0e(%rdx)
>
> Unfortunately, inline asm does not support alternative instructions
> that would depend on output argument type (reg vs mem), so the
> selection can not be automatic. But by having specialized macro, a
> developer can use the variant that results in the most optimal code.
>
> A prototype patch is attached to the message.
>
On a more general note, there is a *really* ugly way to distinguish operand
type on the gas side:
.section ".rodata","a"
.macro classify typevar:req argument:req
\typevar = 0
.irpc char,\argument
.ifeq .L_type
.ifc \char,%
\typevar = 1 /* Register */
.endif
.ifc \char,(
\typevar = 2 /* Memory */
.endif
.ifc \char,$
\typevar = 3 /* Immediate */
.endif
.endif
.endr
.ifne .L_type
\typevar = 2
.endif
.endm
classify .L_type,%rax
.ascii "Type = "
.byte .L_type + 0x30
.asciz "\n"
-hpa
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [tip: x86/cleanups] x86/segment: Use MOVL when reading segment registers
2026-03-12 9:30 ` Uros Bizjak
2026-03-12 18:55 ` H. Peter Anvin
2026-03-12 18:56 ` H. Peter Anvin
@ 2026-03-12 19:11 ` H. Peter Anvin
2026-03-12 19:50 ` Uros Bizjak
2 siblings, 1 reply; 21+ messages in thread
From: H. Peter Anvin @ 2026-03-12 19:11 UTC (permalink / raw)
To: Uros Bizjak
Cc: linux-kernel, Borislav Petkov (AMD), x86, Dave Hansen,
Ingo Molnar, Thomas Gleixner, Peter Zijlstra, David Laight
Note: I personally *hate* the savesegment() syntax. For one thing, I would
much rather see a more C-like syntax, even if that means making a bunch of
inline functions. Replacing the macro with something that is actually
type-safe would be a bloody good thing, too.
Something like:
/* Generates register operation */
static inline unsigned int ds(void)
{
unsigned int v;
asm volatile("mov %%ds,%0" : "=r" (v));
return v;
}
/* Generates memory operation */
static inline void save_ds(u16 *dst)
{
asm volatile("mov %%ds,%0" : "=m" (dst));
}
Generating those inlines can be macroized if we really feel the need to, of
course...
-hpa
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [tip: x86/cleanups] x86/segment: Use MOVL when reading segment registers
2026-03-12 18:55 ` H. Peter Anvin
@ 2026-03-12 19:38 ` Uros Bizjak
0 siblings, 0 replies; 21+ messages in thread
From: Uros Bizjak @ 2026-03-12 19:38 UTC (permalink / raw)
To: H. Peter Anvin
Cc: linux-kernel, Borislav Petkov (AMD), x86, Dave Hansen,
Ingo Molnar, Thomas Gleixner, Peter Zijlstra, David Laight
On Thu, Mar 12, 2026 at 7:55 PM H. Peter Anvin <hpa@zytor.com> wrote:
>
> On 2026-03-12 02:30, Uros Bizjak wrote:
> >
> > We would like to always use MOVL to avoid 0x66 operand size override
> > prefix when reading to a register, but MOVL does not support memory
> > operands. MOVW is required in this case.
> >
>
> Just use "mov" without any suffix.
>
> GAS LISTING movseg.s page 1
>
>
> 1 .text
> 2
> 3 0000 8CD8 mov %ds,%eax
> 4 0002 668CD8 mov %ds,%ax
> 5 0005 8C1B mov %ds,(%rbx)
True, but with a register operand we would prefer this (note %k modifier):
short foo (void)
{
short r;
asm ("mov %%ds, %k0" : "=r"(r));
return r;
}
to avoid 0x66 operand size prefix even for 16bit output registers.
Also, "mov %ds,%eax" will zero-extend to the output register all the
way to 64-bit width. When savesegment() is defined as:
+#define savesegment(seg, var) \
+ asm volatile("movl %%" #seg ",%k0" : "=r" (var))
it allows the following patch:
--cut here--
diff --git a/arch/x86/include/asm/elf.h b/arch/x86/include/asm/elf.h
index 2ba5f166e58f..c7f98977663c 100644
--- a/arch/x86/include/asm/elf.h
+++ b/arch/x86/include/asm/elf.h
@@ -187,7 +187,6 @@ void set_personality_ia32(bool);
#define ELF_CORE_COPY_REGS(pr_reg, regs) \
do { \
- unsigned v; \
(pr_reg)[0] = (regs)->r15; \
(pr_reg)[1] = (regs)->r14; \
(pr_reg)[2] = (regs)->r13; \
@@ -211,10 +210,10 @@ do { \
(pr_reg)[20] = (regs)->ss; \
(pr_reg)[21] = x86_fsbase_read_cpu(); \
(pr_reg)[22] = x86_gsbase_read_cpu_inactive(); \
- asm("movl %%ds,%0" : "=r" (v)); (pr_reg)[23] = v; \
- asm("movl %%es,%0" : "=r" (v)); (pr_reg)[24] = v; \
- asm("movl %%fs,%0" : "=r" (v)); (pr_reg)[25] = v; \
- asm("movl %%gs,%0" : "=r" (v)); (pr_reg)[26] = v; \
+ savesegment(ds, (pr_reg)[23]); \
+ savesegment(es, (pr_reg)[24]); \
+ savesegment(fs, (pr_reg)[25]); \
+ savesegment(gs, (pr_reg)[26]); \
} while (0);
--cut here--
that results in:
mov $ds, %eax
mov %rax, <mem>
without intermediate uint32 -> uint64 zext instruction.
Unfortunately, it is not possible to use %k on memory output operands
(so, "=rm" is not allowed with %k). Although the modifier is nop with
-masm=att, it will error out the compilation with -masm=intel. where:
mov %ds, DWORD PTR mb[rip]
Also, we want to store to exactly 2-byte memory location:
+#define __savesegment(seg, loc) \
+do { \
+ BUILD_BUG_ON(sizeof(loc) != 2); \
+ asm volatile("movw %%" #seg ",%0" : "=m" (loc)); \
+} while (0)
This macro will allow direct seg register store in e.g.:
--cut here--
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index 4c718f8adc59..84c8d7a047d6 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -197,8 +197,8 @@ int copy_thread(struct task_struct *p, const
struct kernel_clone_args *args)
p->thread.gsindex = current->thread.gsindex;
p->thread.gsbase = current->thread.gsbase;
- savesegment(es, p->thread.es);
- savesegment(ds, p->thread.ds);
+ __savesegment(es, p->thread.es);
+ __savesegment(ds, p->thread.ds);
if (p->mm && (clone_flags & (CLONE_VM | CLONE_VFORK)) == CLONE_VM)
set_bit(MM_CONTEXT_LOCK_LAM, &p->mm->context.flags);
--cut here--
Uros.
^ permalink raw reply related [flat|nested] 21+ messages in thread
* Re: [tip: x86/cleanups] x86/segment: Use MOVL when reading segment registers
2026-03-12 19:11 ` H. Peter Anvin
@ 2026-03-12 19:50 ` Uros Bizjak
2026-03-12 22:01 ` Uros Bizjak
0 siblings, 1 reply; 21+ messages in thread
From: Uros Bizjak @ 2026-03-12 19:50 UTC (permalink / raw)
To: H. Peter Anvin
Cc: linux-kernel, Borislav Petkov (AMD), x86, Dave Hansen,
Ingo Molnar, Thomas Gleixner, Peter Zijlstra, David Laight
On Thu, Mar 12, 2026 at 8:12 PM H. Peter Anvin <hpa@zytor.com> wrote:
>
> Note: I personally *hate* the savesegment() syntax. For one thing, I would
> much rather see a more C-like syntax, even if that means making a bunch of
> inline functions. Replacing the macro with something that is actually
> type-safe would be a bloody good thing, too.
>
> Something like:
>
> /* Generates register operation */
> static inline unsigned int ds(void)
> {
> unsigned int v;
> asm volatile("mov %%ds,%0" : "=r" (v));
> return v;
> }
Yes, this would be much better, but should be unsigned long, because
move from segment register zero-extends all the way to 64-bits:
static inline unsigned long read_ds(void)
{
unsigned long v;
asm volatile("mov %%ds,%k0" : "=r" (v));
return v;
}
Uros.
> /* Generates memory operation */
> static inline void save_ds(u16 *dst)
> {
> asm volatile("mov %%ds,%0" : "=m" (dst));
> }
>
> Generating those inlines can be macroized if we really feel the need to, of
> course...
>
> -hpa
>
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [tip: x86/cleanups] x86/segment: Use MOVL when reading segment registers
2026-03-12 19:50 ` Uros Bizjak
@ 2026-03-12 22:01 ` Uros Bizjak
0 siblings, 0 replies; 21+ messages in thread
From: Uros Bizjak @ 2026-03-12 22:01 UTC (permalink / raw)
To: H. Peter Anvin
Cc: linux-kernel, Borislav Petkov (AMD), x86, Dave Hansen,
Ingo Molnar, Thomas Gleixner, Peter Zijlstra, David Laight
On Thu, Mar 12, 2026 at 8:50 PM Uros Bizjak <ubizjak@gmail.com> wrote:
>
> On Thu, Mar 12, 2026 at 8:12 PM H. Peter Anvin <hpa@zytor.com> wrote:
> >
> > Note: I personally *hate* the savesegment() syntax. For one thing, I would
> > much rather see a more C-like syntax, even if that means making a bunch of
> > inline functions. Replacing the macro with something that is actually
> > type-safe would be a bloody good thing, too.
> >
> > Something like:
> >
> > /* Generates register operation */
> > static inline unsigned int ds(void)
> > {
> > unsigned int v;
> > asm volatile("mov %%ds,%0" : "=r" (v));
> > return v;
> > }
>
> Yes, this would be much better, but should be unsigned long, because
> move from segment register zero-extends all the way to 64-bits:
>
> static inline unsigned long read_ds(void)
> {
> unsigned long v;
> asm volatile("mov %%ds,%k0" : "=r" (v));
> return v;
> }
Now implemented at [1].
[1] https://lore.kernel.org/lkml/20260312215916.258176-4-ubizjak@gmail.com/T/#u
Uros.
^ permalink raw reply [flat|nested] 21+ messages in thread
end of thread, other threads:[~2026-03-12 22:01 UTC | newest]
Thread overview: 21+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-01-05 9:02 [PATCH RESEND v2 1/3] x86: Use MOVL when reading segment registers Uros Bizjak
2026-01-05 9:02 ` [PATCH RESEND v2 2/3] x86/hyperv: Use savesegment() instead of inline asm() to save " Uros Bizjak
2026-01-19 16:22 ` H. Peter Anvin
2026-01-05 9:02 ` [PATCH RESEND v2 3/3] x86/hyperv: Remove ASM_CALL_CONSTRAINT with VMMCALL insn Uros Bizjak
2026-01-19 16:23 ` H. Peter Anvin
2026-01-19 16:22 ` [PATCH RESEND v2 1/3] x86: Use MOVL when reading segment registers H. Peter Anvin
2026-01-20 12:08 ` [tip: x86/cleanups] x86/segment: " tip-bot2 for Uros Bizjak
2026-01-20 12:38 ` H. Peter Anvin
2026-01-20 13:47 ` Uros Bizjak
2026-01-20 14:02 ` Uros Bizjak
2026-01-21 11:49 ` Brian Gerst
2026-01-21 14:08 ` David Laight
2026-01-21 16:16 ` Uros Bizjak
2026-01-21 18:55 ` David Laight
2026-03-12 9:30 ` Uros Bizjak
2026-03-12 18:55 ` H. Peter Anvin
2026-03-12 19:38 ` Uros Bizjak
2026-03-12 18:56 ` H. Peter Anvin
2026-03-12 19:11 ` H. Peter Anvin
2026-03-12 19:50 ` Uros Bizjak
2026-03-12 22:01 ` Uros Bizjak
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox