* [PATCH] random: vDSO: Avoid call to memset() when zeroing reserved in __cvdso_getrandom_data()
@ 2026-09-16 21:58 Nathan Chancellor
2026-09-16 22:08 ` Nick Desaulniers
2026-09-17 9:26 ` Jason A. Donenfeld
0 siblings, 2 replies; 6+ messages in thread
From: Nathan Chancellor @ 2026-09-16 21:58 UTC (permalink / raw)
To: Andy Lutomirski, Thomas Gleixner, Theodore Ts'o, Jason A. Donenfeld
Cc: Vincenzo Frascino, Nick Desaulniers, Bill Wendling, Justin Stitt,
linux-kernel, llvm, Nathan Chancellor
After a recent change in LLVM [1], RISC-V builds fail when checking the
vDSO:
arch/riscv/kernel/vdso/vdso.so.dbg: dynamic relocations are not supported
make[4]: *** [arch/riscv/kernel/vdso/Makefile:78: arch/riscv/kernel/vdso/vdso.so.dbg] Error 1
memset() is now generated when zeroing params->reserved because LLVM has
an optimization (now run in more instances) that can recognize at
compile time when it is assigning a static value to a contiguous area of
memory and turn that into a call to memset(). Both clang and GCC assume
memset() is always available [2].
Hide the value of the iterator variable from the optimizer using
OPTIMIZER_HIDE_VAR to inhibit this optimization since it can no longer
assume that the zeroing is contiguous.
Link: https://github.com/llvm/llvm-project/commit/90cebef1411617fc3eedd359bdf00cb44b1c2439 [1]
Link: https://gcc.gnu.org/onlinedocs/gcc-16.2.0/gcc/Standards.html#index-ffreestanding [2]
Signed-off-by: Nathan Chancellor <nathan@kernel.org>
---
lib/vdso/getrandom.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/lib/vdso/getrandom.c b/lib/vdso/getrandom.c
index 2851afa9154f..d48d1fdb3351 100644
--- a/lib/vdso/getrandom.c
+++ b/lib/vdso/getrandom.c
@@ -4,6 +4,7 @@
*/
#include <linux/array_size.h>
+#include <linux/compiler.h>
#include <linux/minmax.h>
#include <vdso/datapage.h>
#include <vdso/getrandom.h>
@@ -83,8 +84,11 @@ __cvdso_getrandom_data(const struct vdso_rng_data *rng_info, void *buffer, size_
params->size_of_opaque_state = sizeof(*state);
params->mmap_prot = PROT_READ | PROT_WRITE;
params->mmap_flags = MAP_DROPPABLE | MAP_ANONYMOUS;
- for (size_t i = 0; i < ARRAY_SIZE(params->reserved); ++i)
+ for (size_t i = 0; i < ARRAY_SIZE(params->reserved); ++i) {
+ /* prevent compiler from turning loop into memset() */
+ OPTIMIZER_HIDE_VAR(i);
params->reserved[i] = 0;
+ }
return 0;
}
---
base-commit: cee9395acd8043be0644b25c34bfa86623f2b935
change-id: 20260916-vdso-getrandom-avoid-memset-llvm-24-74d45fa6031e
Best regards,
--
Cheers,
Nathan
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] random: vDSO: Avoid call to memset() when zeroing reserved in __cvdso_getrandom_data()
2026-09-16 21:58 [PATCH] random: vDSO: Avoid call to memset() when zeroing reserved in __cvdso_getrandom_data() Nathan Chancellor
@ 2026-09-16 22:08 ` Nick Desaulniers
2026-09-16 22:57 ` Nathan Chancellor
2026-09-17 9:26 ` Jason A. Donenfeld
1 sibling, 1 reply; 6+ messages in thread
From: Nick Desaulniers @ 2026-09-16 22:08 UTC (permalink / raw)
To: Nathan Chancellor
Cc: Andy Lutomirski, Thomas Gleixner, Theodore Ts'o,
Jason A. Donenfeld, Vincenzo Frascino, Bill Wendling,
Justin Stitt, linux-kernel, llvm
On Wed, Sep 16, 2026 at 2:59 PM Nathan Chancellor <nathan@kernel.org> wrote:
>
> After a recent change in LLVM [1], RISC-V builds fail when checking the
> vDSO:
>
> arch/riscv/kernel/vdso/vdso.so.dbg: dynamic relocations are not supported
> make[4]: *** [arch/riscv/kernel/vdso/Makefile:78: arch/riscv/kernel/vdso/vdso.so.dbg] Error 1
>
> memset() is now generated when zeroing params->reserved because LLVM has
> an optimization (now run in more instances) that can recognize at
> compile time when it is assigning a static value to a contiguous area of
> memory and turn that into a call to memset(). Both clang and GCC assume
> memset() is always available [2].
>
> Hide the value of the iterator variable from the optimizer using
> OPTIMIZER_HIDE_VAR to inhibit this optimization since it can no longer
> assume that the zeroing is contiguous.
>
> Link: https://github.com/llvm/llvm-project/commit/90cebef1411617fc3eedd359bdf00cb44b1c2439 [1]
> Link: https://gcc.gnu.org/onlinedocs/gcc-16.2.0/gcc/Standards.html#index-ffreestanding [2]
> Signed-off-by: Nathan Chancellor <nathan@kernel.org>
Link: https://github.com/ClangBuiltLinux/linux/issues/2183
Do we need to tag stable (I imagine this might be visible for older
kernels with newer llvm)?
Any idea why we only see this for riscv? Would think loop idiom
recognition would make this transform for any target.
Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
> ---
> lib/vdso/getrandom.c | 6 +++++-
> 1 file changed, 5 insertions(+), 1 deletion(-)
>
> diff --git a/lib/vdso/getrandom.c b/lib/vdso/getrandom.c
> index 2851afa9154f..d48d1fdb3351 100644
> --- a/lib/vdso/getrandom.c
> +++ b/lib/vdso/getrandom.c
> @@ -4,6 +4,7 @@
> */
>
> #include <linux/array_size.h>
> +#include <linux/compiler.h>
> #include <linux/minmax.h>
> #include <vdso/datapage.h>
> #include <vdso/getrandom.h>
> @@ -83,8 +84,11 @@ __cvdso_getrandom_data(const struct vdso_rng_data *rng_info, void *buffer, size_
> params->size_of_opaque_state = sizeof(*state);
> params->mmap_prot = PROT_READ | PROT_WRITE;
> params->mmap_flags = MAP_DROPPABLE | MAP_ANONYMOUS;
> - for (size_t i = 0; i < ARRAY_SIZE(params->reserved); ++i)
> + for (size_t i = 0; i < ARRAY_SIZE(params->reserved); ++i) {
> + /* prevent compiler from turning loop into memset() */
> + OPTIMIZER_HIDE_VAR(i);
> params->reserved[i] = 0;
> + }
> return 0;
> }
>
>
> ---
> base-commit: cee9395acd8043be0644b25c34bfa86623f2b935
> change-id: 20260916-vdso-getrandom-avoid-memset-llvm-24-74d45fa6031e
>
> Best regards,
> --
> Cheers,
> Nathan
>
--
Thanks,
~Nick Desaulniers
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] random: vDSO: Avoid call to memset() when zeroing reserved in __cvdso_getrandom_data()
2026-09-16 22:08 ` Nick Desaulniers
@ 2026-09-16 22:57 ` Nathan Chancellor
2026-09-16 23:40 ` Nick Desaulniers
0 siblings, 1 reply; 6+ messages in thread
From: Nathan Chancellor @ 2026-09-16 22:57 UTC (permalink / raw)
To: Nick Desaulniers
Cc: Andy Lutomirski, Thomas Gleixner, Theodore Ts'o,
Jason A. Donenfeld, Vincenzo Frascino, Bill Wendling,
Justin Stitt, linux-kernel, llvm
On Wed, Sep 16, 2026 at 03:08:38PM -0700, Nick Desaulniers wrote:
> Link: https://github.com/ClangBuiltLinux/linux/issues/2183
Whoops :/ thanks for including this
> Do we need to tag stable (I imagine this might be visible for older
> kernels with newer llvm)?
Yeah, we probably do, as I expect this error to happen with 6.16+ due to
commit ee0d03053e70 ("RISC-V: vDSO: Wire up getrandom() vDSO
implementation").
I will include those in v2 once the maintainers have had some time to
chime in to make sure this approach is okay.
> Any idea why we only see this for riscv? Would think loop idiom
> recognition would make this transform for any target.
I have not confirmed this but based on looking at the aarch64
disassembly when deciding how to tackle this, I suspect some backends
can expand certain calls to memset() to a set of instructions, as I saw
a set of stp calls with xzr as the source and offsets into params as the
dest.
> Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
Thanks for taking a look!
--
Cheers,
Nathan
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] random: vDSO: Avoid call to memset() when zeroing reserved in __cvdso_getrandom_data()
2026-09-16 22:57 ` Nathan Chancellor
@ 2026-09-16 23:40 ` Nick Desaulniers
0 siblings, 0 replies; 6+ messages in thread
From: Nick Desaulniers @ 2026-09-16 23:40 UTC (permalink / raw)
To: Nathan Chancellor
Cc: Andy Lutomirski, Thomas Gleixner, Theodore Ts'o,
Jason A. Donenfeld, Vincenzo Frascino, Bill Wendling,
Justin Stitt, linux-kernel, llvm
On Wed, Sep 16, 2026 at 3:57 PM Nathan Chancellor <nathan@kernel.org> wrote:
>
> > Any idea why we only see this for riscv? Would think loop idiom
> > recognition would make this transform for any target.
>
> I have not confirmed this but based on looking at the aarch64
> disassembly when deciding how to tackle this, I suspect some backends
> can expand certain calls to memset() to a set of instructions, as I saw
> a set of stp calls with xzr as the source and offsets into params as the
> dest.
https://godbolt.org/z/dbPrexfvo
Yeah, just seems like there's a heuristic/threshold for the trip
count. (GCC will also generate the libcall for trip counts >= 16).
--
Thanks,
~Nick Desaulniers
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] random: vDSO: Avoid call to memset() when zeroing reserved in __cvdso_getrandom_data()
2026-09-16 21:58 [PATCH] random: vDSO: Avoid call to memset() when zeroing reserved in __cvdso_getrandom_data() Nathan Chancellor
2026-09-16 22:08 ` Nick Desaulniers
@ 2026-09-17 9:26 ` Jason A. Donenfeld
2026-09-17 17:39 ` Nathan Chancellor
1 sibling, 1 reply; 6+ messages in thread
From: Jason A. Donenfeld @ 2026-09-17 9:26 UTC (permalink / raw)
To: Nathan Chancellor
Cc: Andy Lutomirski, Thomas Gleixner, Theodore Ts'o,
Vincenzo Frascino, Nick Desaulniers, Bill Wendling, Justin Stitt,
linux-kernel, llvm
On Wed, Sep 16, 2026 at 02:58:44PM -0700, Nathan Chancellor wrote:
> After a recent change in LLVM [1], RISC-V builds fail when checking the
> vDSO:
>
> arch/riscv/kernel/vdso/vdso.so.dbg: dynamic relocations are not supported
> make[4]: *** [arch/riscv/kernel/vdso/Makefile:78: arch/riscv/kernel/vdso/vdso.so.dbg] Error 1
>
> memset() is now generated when zeroing params->reserved because LLVM has
> an optimization (now run in more instances) that can recognize at
> compile time when it is assigning a static value to a contiguous area of
> memory and turn that into a call to memset(). Both clang and GCC assume
> memset() is always available [2].
>
> Hide the value of the iterator variable from the optimizer using
> OPTIMIZER_HIDE_VAR to inhibit this optimization since it can no longer
> assume that the zeroing is contiguous.
>
> Link: https://github.com/llvm/llvm-project/commit/90cebef1411617fc3eedd359bdf00cb44b1c2439 [1]
> Link: https://gcc.gnu.org/onlinedocs/gcc-16.2.0/gcc/Standards.html#index-ffreestanding [2]
> Signed-off-by: Nathan Chancellor <nathan@kernel.org>
> ---
> lib/vdso/getrandom.c | 6 +++++-
> 1 file changed, 5 insertions(+), 1 deletion(-)
>
> diff --git a/lib/vdso/getrandom.c b/lib/vdso/getrandom.c
> index 2851afa9154f..d48d1fdb3351 100644
> --- a/lib/vdso/getrandom.c
> +++ b/lib/vdso/getrandom.c
> @@ -4,6 +4,7 @@
> */
>
> #include <linux/array_size.h>
> +#include <linux/compiler.h>
> #include <linux/minmax.h>
> #include <vdso/datapage.h>
> #include <vdso/getrandom.h>
> @@ -83,8 +84,11 @@ __cvdso_getrandom_data(const struct vdso_rng_data *rng_info, void *buffer, size_
> params->size_of_opaque_state = sizeof(*state);
> params->mmap_prot = PROT_READ | PROT_WRITE;
> params->mmap_flags = MAP_DROPPABLE | MAP_ANONYMOUS;
> - for (size_t i = 0; i < ARRAY_SIZE(params->reserved); ++i)
> + for (size_t i = 0; i < ARRAY_SIZE(params->reserved); ++i) {
> + /* prevent compiler from turning loop into memset() */
> + OPTIMIZER_HIDE_VAR(i);
> params->reserved[i] = 0;
> + }
> return 0;
> }
I don't suspect this is the right change. On x86_64, this changes to
code from:
rep stosq
into:
loc_2D9:
mov dword ptr [rbx+rax*4+0Ch], 0
add rax, 1
cmp rax, 0Ch
jbe short loc_2D9
Which is a lot less compact. It seems like the actual solution is for
gcc&clang to emit this inline memset mnemonic when the platform has a
good one, and otherwise not. But disabling optimizations for all
platforms, because it's broken on one, seems bad.
In this case, the compiler is being smart: it identifies a loop and
rightly turns it into memset. But if this isn't a compilation
environment that has an outline function, it should do something else.
Jason
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] random: vDSO: Avoid call to memset() when zeroing reserved in __cvdso_getrandom_data()
2026-09-17 9:26 ` Jason A. Donenfeld
@ 2026-09-17 17:39 ` Nathan Chancellor
0 siblings, 0 replies; 6+ messages in thread
From: Nathan Chancellor @ 2026-09-17 17:39 UTC (permalink / raw)
To: Jason A. Donenfeld
Cc: Andy Lutomirski, Thomas Gleixner, Theodore Ts'o,
Vincenzo Frascino, Nick Desaulniers, Bill Wendling, Justin Stitt,
linux-kernel, llvm
On Thu, Sep 17, 2026 at 11:26:46AM +0200, Jason A. Donenfeld wrote:
> I don't suspect this is the right change. On x86_64, this changes to
> code from:
>
> rep stosq
>
> into:
>
> loc_2D9:
> mov dword ptr [rbx+rax*4+0Ch], 0
> add rax, 1
> cmp rax, 0Ch
> jbe short loc_2D9
>
> Which is a lot less compact. It seems like the actual solution is for
> gcc&clang to emit this inline memset mnemonic when the platform has a
> good one, and otherwise not. But disabling optimizations for all
> platforms, because it's broken on one, seems bad.
Yes, that is certainly fair criticism. That said, this optimization
happens in the middle end as far as I can tell, so I am not sure how
much target specific knowledge is available at that point.
Additionally...
> In this case, the compiler is being smart: it identifies a loop and
> rightly turns it into memset. But if this isn't a compilation
> environment that has an outline function, it should do something else.
As I mentioned in the commit message, compilers require all environments
(hosted or not) to provide memset(), so the "doing something else" is
nothing :)
GCC requires the freestanding environment provide memcpy, memmove,
memset and memcmp.
I guess another option is to just include a basic memset() like the one
in lib/string.c so that it is only used if the compiler makes this sort
of transformation, while leaving all other architectures alone.
--
Cheers,
Nathan
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-09-17 17:39 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-16 21:58 [PATCH] random: vDSO: Avoid call to memset() when zeroing reserved in __cvdso_getrandom_data() Nathan Chancellor
2026-09-16 22:08 ` Nick Desaulniers
2026-09-16 22:57 ` Nathan Chancellor
2026-09-16 23:40 ` Nick Desaulniers
2026-09-17 9:26 ` Jason A. Donenfeld
2026-09-17 17:39 ` Nathan Chancellor
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®