Re: [PATCH RESEND] x86/kexec: store segment registers directly to memory in crash_setup_regs()

From: Uros Bizjak

Date: Mon Sep 07 2026 - 00:42:47 EST


On Mon, Sep 7, 2026 at 3:33 AM H. Peter Anvin <hpa@xxxxxxxxx> wrote:
>
> On 2026-09-06 11:39, Uros Bizjak wrote:
> > crash_setup_regs() currently moves segment registers (ss, cs, ds, es)
> > into pt_regs via a general purpose register (%eax). Update the code to
> > avoid the intermediate register and store segment registers directly
> > to their destination fields. This reduces the generated code from:
> >
>
> > diff --git a/arch/x86/include/asm/kexec.h b/arch/x86/include/asm/kexec.h
> > index 5cfb27f26583..ad7ef567452b 100644
> > --- a/arch/x86/include/asm/kexec.h
> > +++ b/arch/x86/include/asm/kexec.h
> > @@ -106,11 +106,11 @@ static inline void crash_setup_regs(struct pt_regs *newregs,
> > asm volatile("mov %%r14,%0" : "=m"(newregs->r14));
> > asm volatile("mov %%r15,%0" : "=m"(newregs->r15));
> > #endif
> > - asm volatile("mov %%ss,%k0" : "=a"(newregs->ss));
> > - asm volatile("mov %%cs,%k0" : "=a"(newregs->cs));
> > + asm volatile("mov %%ss,%0" : "=m"(newregs->ss));
> > + asm volatile("mov %%cs,%0" : "=m"(newregs->cs));
> > #ifdef CONFIG_X86_32
> > - asm volatile("mov %%ds,%k0" : "=a"(newregs->ds));
> > - asm volatile("mov %%es,%k0" : "=a"(newregs->es));
> > + asm volatile("mov %%ds,%0" : "=m"(newregs->ds));
> > + asm volatile("mov %%es,%0" : "=m"(newregs->es));
> > #endif
> > asm volatile("pushf\n\t"
> > "pop %0" : "=m"(newregs->flags));
>
> Why not use "=rm"? "=a" seems odd in the extreme.

"=rm" will produce assembly using an intermediate register due to GCC
PR124209 [1]. clang also has issues with "=rm", please see the
definition of ASM_OUTPUT_RM in compiler-clang.h. Using "=m" will
always create optimal code on both compilers.

[1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=124209

Uros.