From: David Laight <david.laight.linux@gmail.com>
To: Borislav Petkov <bp@alien8.de>
Cc: Usama Arif <usama.arif@linux.dev>,
dave.hansen@linux.intel.com, dsterba@suse.com, hpa@zytor.com,
linux-kernel@vger.kernel.org, mingo@redhat.com, terrelln@fb.com,
tglx@kernel.org, x86@kernel.org, torvalds@linux-foundation.org,
kas@kernel.org, hannes@cmpxchg.org, riel@surriel.com,
shakeel.butt@linux.dev, kernel-team@meta.com
Subject: Re: [PATCH v3 2/2] x86/lib: Use REP MOVSB for large memcpy() on ERMS CPUs without FSRM
Date: Thu, 12 Nov 2026 09:37:29 +0000 [thread overview]
Message-ID: <20261112093729.065afd6c@pumpkin> (raw)
In-Reply-To: <20261111234608.GAavT-QFRo6EtvoL0y@fat_crate.local>
On Wed, 11 Nov 2026 15:46:08 -0800
Borislav Petkov <bp@alien8.de> wrote:
> On Wed, Nov 11, 2026 at 05:20:53AM -0800, Usama Arif wrote:
> > diff --git a/arch/x86/lib/memcpy_64.S b/arch/x86/lib/memcpy_64.S
> > index 7bb146c811029..5320862e0274e 100644
> > --- a/arch/x86/lib/memcpy_64.S
> > +++ b/arch/x86/lib/memcpy_64.S
> > @@ -27,15 +27,13 @@
> > *
> > * The 'rep movsb' itself is small enough to replace the call, but the
> > * two register moves blow up the code. And one of them is "needed"
> > - * only for the return value that is the same as the source input,
> > + * only for the return value that is the same as the destination input,
> > * which the compiler could/should do much better anyway.
> > */
> > SYM_TYPED_FUNC_START(__memcpy)
> > - ALTERNATIVE "jmp memcpy_orig", "", X86_FEATURE_FSRM
> > -
> > movq %rdi, %rax
> > movq %rdx, %rcx
> > - rep movsb
> > + ALTERNATIVE "jmp memcpy_orig", "rep movsb", X86_FEATURE_FSRM
> > RET
> > SYM_FUNC_END(__memcpy)
> > EXPORT_SYMBOL(__memcpy)
> > @@ -45,12 +43,16 @@ SYM_PIC_ALIAS(memcpy)
> > EXPORT_SYMBOL(memcpy)
> >
> > SYM_FUNC_START_LOCAL(memcpy_orig)
> > - movq %rdi, %rax
> > - movq %rdx, %rcx
> > -
> > cmpq $0x20, %rcx
> > jb .Lhandle_tail
> >
> > + /*
> > + * RCX holds the count for REP MOVSB and scalar copying; RDX is scratch.
> > + * Shift RDX to check length >= 2048 without destroying the REP count.
> > + * The 10-byte alternative fits a NOP without ERMS.
> > + */
> > + ALTERNATIVE "", __stringify(shrq $11, %rdx; jnz .Lerms), X86_FEATURE_ERMS
>
> Sorry, this is adding more JMPs in "conditional" alternatives code and thus
> turns this into a bigger and unmaintainable mess than it already is.
>
> The 2K limit looks like something conjured out of a thin air as it seems it
> work for your particular case. I'm sure we will have to whack it in the future
> because someone else will complain of the opposite.
>
> This needs to be done with alternative_call*, even at the price of some
> duplicated code but without turning what already is a mess, into a bigger one.
Multiple functions seems like a good idea.
In some cases you can patch the constant in the instruction.
That is safe here even if a multi-byte constant crosses a cache line
because it is only an optimisation.
Patching the call sites would certainly be cleaner.
More interesting would be having a function with a non-standard calling
convention (%rdi, %rsi, %rcx, everything else preserved, void result)
so that the 5 byte call can be patched with "rep movsb; nop3".
I can't see anywhere that uses the result.
Maybe start with "rep movsb; nop3" and patch with the call?
You'd still need a normal memcpy() for the calls gcc makes and if the
address is taken.
A special function to do the patching would also make sense.
All Intel non-atom cpu since sandy bridge run 'rep movsb' as fast
as 'rep movsq' - so you only need to worry about short copies.
Whereas some of the older Zen cpu run misaligned copies slowly.
So you could pick/patch the most appropriate code using more complex
logic than just whether one of the X86_FEATURE_xxx bits is set.
The same calling convention might make sense for memmove().
Although it probably wants a scratch register for the (dst - src < len)
check (it might want dst in the scratch register!).
David
>
> Or a static key or even with stop_machine_nmi() (currently in review) which
> patches the kernel even later, when it is convenient to do so.
>
> Whatever it takes to keep this code readable and sane.
>
> But not this.
>
> Sorry.
>
next prev parent reply other threads:[~2026-11-12 9:37 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-11 13:20 [PATCH v3 0/2] x86/lib: Use REP MOVSB for large memcpy() on ERMS CPUs without FSRM Usama Arif
2026-11-11 13:20 ` [PATCH v3 1/2] x86/lib: Keep the scalar memcpy() count in RCX Usama Arif
2026-11-11 13:20 ` [PATCH v3 2/2] x86/lib: Use REP MOVSB for large memcpy() on ERMS CPUs without FSRM Usama Arif
2026-11-11 13:56 ` Peter Zijlstra
2026-11-11 23:46 ` Borislav Petkov
2026-11-12 9:37 ` David Laight [this message]
2026-11-11 18:19 ` [PATCH v3 0/2] " Kiryl Shutsemau
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261112093729.065afd6c@pumpkin \
--to=david.laight.linux@gmail.com \
--cc=bp@alien8.de \
--cc=dave.hansen@linux.intel.com \
--cc=dsterba@suse.com \
--cc=hannes@cmpxchg.org \
--cc=hpa@zytor.com \
--cc=kas@kernel.org \
--cc=kernel-team@meta.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@redhat.com \
--cc=riel@surriel.com \
--cc=shakeel.butt@linux.dev \
--cc=terrelln@fb.com \
--cc=tglx@kernel.org \
--cc=torvalds@linux-foundation.org \
--cc=usama.arif@linux.dev \
--cc=x86@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox