mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson
synced 2025-08-28 00:19:36 +00:00

VDSO time functions do not call any other function, so they don't need to save/restore LR. However, retrieving the address of VDSO data page requires using LR hence saving then restoring it, which can be heavy on some CPUs. On the other hand, VDSO functions on powerpc are not standard functions and require a wrapper function to call C VDSO functions. And that wrapper has to save and restore LR in order to call the C VDSO function, so retrieving VDSO data page address in that wrapper doesn't require additional save/restore of LR. For random VDSO functions it is a bit different. Because the function calls __arch_chacha20_blocks_nostack(), it saves and restores LR. Retrieving VDSO data page address can then be done there without additional save/restore of LR. So lets implement __arch_get_vdso_rng_data() and simplify the wrapper. It starts paving the way for the day powerpc will implement a more standard ABI for VDSO functions. Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Link: https://patch.msgid.link/a1a9bd0df508f1b5c04684b7366940577dfc6262.1727858295.git.christophe.leroy@csgroup.eu
57 lines
1.4 KiB
ArmAsm
57 lines
1.4 KiB
ArmAsm
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
/*
|
|
* Userland implementation of getrandom() for processes
|
|
* for use in the vDSO
|
|
*
|
|
* Copyright (C) 2024 Christophe Leroy <christophe.leroy@csgroup.eu>, CS GROUP France
|
|
*/
|
|
#include <asm/processor.h>
|
|
#include <asm/ppc_asm.h>
|
|
#include <asm/vdso.h>
|
|
#include <asm/vdso_datapage.h>
|
|
#include <asm/asm-offsets.h>
|
|
#include <asm/unistd.h>
|
|
|
|
/*
|
|
* The macro sets two stack frames, one for the caller and one for the callee
|
|
* because there are no requirement for the caller to set a stack frame when
|
|
* calling VDSO so it may have omitted to set one, especially on PPC64
|
|
*/
|
|
|
|
.macro cvdso_call funct
|
|
.cfi_startproc
|
|
PPC_STLU r1, -PPC_MIN_STKFRM(r1)
|
|
.cfi_adjust_cfa_offset PPC_MIN_STKFRM
|
|
mflr r0
|
|
PPC_STLU r1, -PPC_MIN_STKFRM(r1)
|
|
.cfi_adjust_cfa_offset PPC_MIN_STKFRM
|
|
PPC_STL r0, PPC_MIN_STKFRM + PPC_LR_STKOFF(r1)
|
|
.cfi_rel_offset lr, PPC_MIN_STKFRM + PPC_LR_STKOFF
|
|
#ifdef __powerpc64__
|
|
PPC_STL r2, PPC_MIN_STKFRM + STK_GOT(r1)
|
|
.cfi_rel_offset r2, PPC_MIN_STKFRM + STK_GOT
|
|
#endif
|
|
bl CFUNC(DOTSYM(\funct))
|
|
PPC_LL r0, PPC_MIN_STKFRM + PPC_LR_STKOFF(r1)
|
|
#ifdef __powerpc64__
|
|
PPC_LL r2, PPC_MIN_STKFRM + STK_GOT(r1)
|
|
.cfi_restore r2
|
|
#endif
|
|
cmpwi r3, 0
|
|
mtlr r0
|
|
addi r1, r1, 2 * PPC_MIN_STKFRM
|
|
.cfi_restore lr
|
|
.cfi_def_cfa_offset 0
|
|
crclr so
|
|
bgelr+
|
|
crset so
|
|
neg r3, r3
|
|
blr
|
|
.cfi_endproc
|
|
.endm
|
|
|
|
.text
|
|
V_FUNCTION_BEGIN(__kernel_getrandom)
|
|
cvdso_call __c_kernel_getrandom
|
|
V_FUNCTION_END(__kernel_getrandom)
|