mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00

As recently pointed out by Thomas, if a register is forced for two
different register variables, among them one is used as "+" (both input
and output) and another is only used as input, Clang would treat the
conflicting input parameters as undefined behaviour and optimize away
the argument assignment.
Instead use "=r" (only output) for the output parameter and "r" (only
input) for the input parameter.
While the example from the GCC documentation uses "0" for the input
parameter, this is not necessary as confirmed by the GCC developers and "r"
matches what the other architectures' vDSO implementations are using.
[ alex: Update log to match v2 (Thomas) ]
Link: https://lore.kernel.org/all/20250603-loongarch-vdso-syscall-v1-1-6d12d6dfbdd0@linutronix.de/
Link: https://gcc.gnu.org/onlinedocs/gcc-15.1.0/gcc/Local-Register-Variables.html
Link: https://gcc.gnu.org/pipermail/gcc-help/2025-June/144266.html
Cc: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
Cc: Nathan Chancellor <nathan@kernel.org>
Signed-off-by: Xi Ruoyao <xry111@xry111.site>
Reviewed-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
Fixes: ee0d03053e
("RISC-V: vDSO: Wire up getrandom() vDSO")
Link: https://lore.kernel.org/r/20250606092443.73650-2-xry111@xry111.site
Signed-off-by: Alexandre Ghiti <alexghiti@rivosinc.com>
Signed-off-by: Palmer Dabbelt <palmer@dabbelt.com>
30 lines
750 B
C
30 lines
750 B
C
/* SPDX-License-Identifier: GPL-2.0-only */
|
|
/*
|
|
* Copyright (C) 2025 Xi Ruoyao <xry111@xry111.site>. All Rights Reserved.
|
|
*/
|
|
#ifndef __ASM_VDSO_GETRANDOM_H
|
|
#define __ASM_VDSO_GETRANDOM_H
|
|
|
|
#ifndef __ASSEMBLY__
|
|
|
|
#include <asm/unistd.h>
|
|
|
|
static __always_inline ssize_t getrandom_syscall(void *_buffer, size_t _len, unsigned int _flags)
|
|
{
|
|
register long ret asm("a0");
|
|
register long nr asm("a7") = __NR_getrandom;
|
|
register void *buffer asm("a0") = _buffer;
|
|
register size_t len asm("a1") = _len;
|
|
register unsigned int flags asm("a2") = _flags;
|
|
|
|
asm volatile ("ecall\n"
|
|
: "=r" (ret)
|
|
: "r" (nr), "r" (buffer), "r" (len), "r" (flags)
|
|
: "memory");
|
|
|
|
return ret;
|
|
}
|
|
|
|
#endif /* !__ASSEMBLY__ */
|
|
|
|
#endif /* __ASM_VDSO_GETRANDOM_H */
|