xref: /linux/arch/powerpc/include/asm/vdso/getrandom.h (revision 4f9786035f9e519db41375818e1d0b5f20da2f10)
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