153cee505SChristophe Leroy /* SPDX-License-Identifier: GPL-2.0 */
253cee505SChristophe Leroy /*
353cee505SChristophe Leroy * Copyright (C) 2024 Christophe Leroy <christophe.leroy@csgroup.eu>, CS GROUP France
453cee505SChristophe Leroy */
553cee505SChristophe Leroy #ifndef _ASM_POWERPC_VDSO_GETRANDOM_H
653cee505SChristophe Leroy #define _ASM_POWERPC_VDSO_GETRANDOM_H
753cee505SChristophe Leroy
853cee505SChristophe Leroy #ifndef __ASSEMBLY__
953cee505SChristophe Leroy
104e3fa1aeSChristophe Leroy #include <asm/vdso_datapage.h>
114e3fa1aeSChristophe Leroy
do_syscall_3(const unsigned long _r0,const unsigned long _r3,const unsigned long _r4,const unsigned long _r5)1253cee505SChristophe Leroy static __always_inline int do_syscall_3(const unsigned long _r0, const unsigned long _r3,
1353cee505SChristophe Leroy const unsigned long _r4, const unsigned long _r5)
1453cee505SChristophe Leroy {
1553cee505SChristophe Leroy register long r0 asm("r0") = _r0;
1653cee505SChristophe Leroy register unsigned long r3 asm("r3") = _r3;
1753cee505SChristophe Leroy register unsigned long r4 asm("r4") = _r4;
1853cee505SChristophe Leroy register unsigned long r5 asm("r5") = _r5;
1953cee505SChristophe Leroy register int ret asm ("r3");
2053cee505SChristophe Leroy
2153cee505SChristophe Leroy asm volatile(
2253cee505SChristophe Leroy " sc\n"
2353cee505SChristophe Leroy " bns+ 1f\n"
2453cee505SChristophe Leroy " neg %0, %0\n"
2553cee505SChristophe Leroy "1:\n"
2653cee505SChristophe Leroy : "=r" (ret), "+r" (r4), "+r" (r5), "+r" (r0)
2753cee505SChristophe Leroy : "r" (r3)
2853cee505SChristophe Leroy : "memory", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "cr0", "ctr");
2953cee505SChristophe Leroy
3053cee505SChristophe Leroy return ret;
3153cee505SChristophe Leroy }
3253cee505SChristophe Leroy
3353cee505SChristophe Leroy /**
3453cee505SChristophe Leroy * getrandom_syscall - Invoke the getrandom() syscall.
3553cee505SChristophe Leroy * @buffer: Destination buffer to fill with random bytes.
3653cee505SChristophe Leroy * @len: Size of @buffer in bytes.
3753cee505SChristophe Leroy * @flags: Zero or more GRND_* flags.
3853cee505SChristophe Leroy * Returns: The number of bytes written to @buffer, or a negative value indicating an error.
3953cee505SChristophe Leroy */
getrandom_syscall(void * buffer,size_t len,unsigned int flags)4053cee505SChristophe Leroy static __always_inline ssize_t getrandom_syscall(void *buffer, size_t len, unsigned int flags)
4153cee505SChristophe Leroy {
4253cee505SChristophe Leroy return do_syscall_3(__NR_getrandom, (unsigned long)buffer,
4353cee505SChristophe Leroy (unsigned long)len, (unsigned long)flags);
4453cee505SChristophe Leroy }
4553cee505SChristophe Leroy
__arch_get_vdso_u_rng_data(void)46*223970dfSThomas Weißschuh static __always_inline const struct vdso_rng_data *__arch_get_vdso_u_rng_data(void)
4753cee505SChristophe Leroy {
48*223970dfSThomas Weißschuh struct vdso_rng_data *data;
494e3fa1aeSChristophe Leroy
504e3fa1aeSChristophe Leroy asm (
514e3fa1aeSChristophe Leroy " bcl 20, 31, .+4 ;"
524e3fa1aeSChristophe Leroy "0: mflr %0 ;"
53*223970dfSThomas Weißschuh " addis %0, %0, (vdso_u_rng_data - 0b)@ha ;"
54*223970dfSThomas Weißschuh " addi %0, %0, (vdso_u_rng_data - 0b)@l ;"
554e3fa1aeSChristophe Leroy : "=r" (data) : : "lr"
564e3fa1aeSChristophe Leroy );
574e3fa1aeSChristophe Leroy
58*223970dfSThomas Weißschuh return data;
5953cee505SChristophe Leroy }
60*223970dfSThomas Weißschuh #define __arch_get_vdso_u_rng_data __arch_get_vdso_u_rng_data
6153cee505SChristophe Leroy
6253cee505SChristophe Leroy ssize_t __c_kernel_getrandom(void *buffer, size_t len, unsigned int flags, void *opaque_state,
634e3fa1aeSChristophe Leroy size_t opaque_len);
6453cee505SChristophe Leroy
6553cee505SChristophe Leroy #endif /* !__ASSEMBLY__ */
6653cee505SChristophe Leroy
6753cee505SChristophe Leroy #endif /* _ASM_POWERPC_VDSO_GETRANDOM_H */
68