mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-19 22:11:22 +00:00

Provide the s390 specific vdso getrandom() architecture backend. _vdso_rng_data required data is placed within the _vdso_data vvar page, by using a hardcoded offset larger than vdso_data. As required the chacha20 implementation does not write to the stack. The implementation follows more or less the arm64 implementations and makes use of vector instructions. It has a fallback to the getrandom() system call for machines where the vector facility is not installed. The check if the vector facility is installed, as well as an optimization for machines with the vector-enhancements facility 2, is implemented with alternatives, avoiding runtime checks. Note that __kernel_getrandom() is implemented without the vdso user wrapper which would setup a stack frame for odd cases (aka very old glibc variants) where the caller has not done that. All callers of __kernel_getrandom() are required to setup a stack frame, like the C ABI requires it. The vdso testcases vdso_test_getrandom and vdso_test_chacha pass. Benchmark on a z16: $ ./vdso_test_getrandom bench-single vdso: 25000000 times in 0.493703559 seconds syscall: 25000000 times in 6.584025337 seconds Signed-off-by: Heiko Carstens <hca@linux.ibm.com> Reviewed-by: Harald Freudenberger <freude@linux.ibm.com> Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
40 lines
1.3 KiB
C
40 lines
1.3 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
|
|
#ifndef __ASM_VDSO_GETRANDOM_H
|
|
#define __ASM_VDSO_GETRANDOM_H
|
|
|
|
#ifndef __ASSEMBLY__
|
|
|
|
#include <vdso/datapage.h>
|
|
#include <asm/vdso/vsyscall.h>
|
|
#include <asm/syscall.h>
|
|
#include <asm/unistd.h>
|
|
#include <asm/page.h>
|
|
|
|
/**
|
|
* getrandom_syscall - Invoke the getrandom() syscall.
|
|
* @buffer: Destination buffer to fill with random bytes.
|
|
* @len: Size of @buffer in bytes.
|
|
* @flags: Zero or more GRND_* flags.
|
|
* Returns: The number of random bytes written to @buffer, or a negative value indicating an error.
|
|
*/
|
|
static __always_inline ssize_t getrandom_syscall(void *buffer, size_t len, unsigned int flags)
|
|
{
|
|
return syscall3(__NR_getrandom, (long)buffer, (long)len, (long)flags);
|
|
}
|
|
|
|
static __always_inline const struct vdso_rng_data *__arch_get_vdso_rng_data(void)
|
|
{
|
|
/*
|
|
* The RNG data is in the real VVAR data page, but if a task belongs to a time namespace
|
|
* then VVAR_DATA_PAGE_OFFSET points to the namespace-specific VVAR page and VVAR_TIMENS_
|
|
* PAGE_OFFSET points to the real VVAR page.
|
|
*/
|
|
if (IS_ENABLED(CONFIG_TIME_NS) && _vdso_data->clock_mode == VDSO_CLOCKMODE_TIMENS)
|
|
return (void *)&_vdso_rng_data + VVAR_TIMENS_PAGE_OFFSET * PAGE_SIZE;
|
|
return &_vdso_rng_data;
|
|
}
|
|
|
|
#endif /* !__ASSEMBLY__ */
|
|
|
|
#endif /* __ASM_VDSO_GETRANDOM_H */
|