linux-yocto/tools/testing/selftests/vDSO/vdso_call.h
Christophe Leroy 6eda706a53 selftests: vDSO: fix the way vDSO functions are called for powerpc
vdso_test_correctness test fails on powerpc:

~ # ./vdso_test_correctness
...
[RUN]	Testing clock_gettime for clock CLOCK_REALTIME_ALARM (8)...
[FAIL]	No such clock, but __vdso_clock_gettime returned 22
[RUN]	Testing clock_gettime for clock CLOCK_BOOTTIME_ALARM (9)...
[FAIL]	No such clock, but __vdso_clock_gettime returned 22
[RUN]	Testing clock_gettime for clock CLOCK_SGI_CYCLE (10)...
[FAIL]	No such clock, but __vdso_clock_gettime returned 22
...
[RUN]	Testing clock_gettime for clock invalid (-1)...
[FAIL]	No such clock, but __vdso_clock_gettime returned 22
[RUN]	Testing clock_gettime for clock invalid (-2147483648)...
[FAIL]	No such clock, but __vdso_clock_gettime returned 22
[RUN]	Testing clock_gettime for clock invalid (2147483647)...
[FAIL]	No such clock, but __vdso_clock_gettime returned 22

On powerpc, a call to a VDSO function is not an ordinary C function
call. Unlike several architectures which returns a negative error code
in case of an error, powerpc sets CR[SO] and returns the error code
as a positive value.

Define and use a macro called VDSO_CALL() which takes a pointer
to the function to call, the number of arguments and the arguments.

Also update ABI vdso documentation to reflect this subtlety.

Provide a specific version of VDSO_CALL() for powerpc that negates
the error code on return when CR[SO] is set.

Fixes: c7e5789b24 ("kselftest: Move test_vdso to the vDSO test suite")
Fixes: 2e9a972566 ("selftests: vdso: Add a selftest for vDSO getcpu()")
Fixes: 693f5ca08c ("kselftest: Extend vDSO selftest")
Fixes: b2f1c3db28 ("kselftest: Extend vdso correctness test to clock_gettime64")
Fixes: 4920a2590e ("selftests/vDSO: add tests for vgetrandom")
Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
Acked-by: Shuah Khan <skhan@linuxfoundation.org>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2024-08-30 15:48:45 +02:00

71 lines
1.7 KiB
C

/* SPDX-License-Identifier: GPL-2.0 */
/*
* Macro to call vDSO functions
*
* Copyright (C) 2024 Christophe Leroy <christophe.leroy@csgroup.eu>, CS GROUP France
*/
#ifndef __VDSO_CALL_H__
#define __VDSO_CALL_H__
#ifdef __powerpc__
#define LOADARGS_1(fn, __arg1) do { \
_r0 = fn; \
_r3 = (long)__arg1; \
} while (0)
#define LOADARGS_2(fn, __arg1, __arg2) do { \
_r0 = fn; \
_r3 = (long)__arg1; \
_r4 = (long)__arg2; \
} while (0)
#define LOADARGS_3(fn, __arg1, __arg2, __arg3) do { \
_r0 = fn; \
_r3 = (long)__arg1; \
_r4 = (long)__arg2; \
_r5 = (long)__arg3; \
} while (0)
#define LOADARGS_5(fn, __arg1, __arg2, __arg3, __arg4, __arg5) do { \
_r0 = fn; \
_r3 = (long)__arg1; \
_r4 = (long)__arg2; \
_r5 = (long)__arg3; \
_r6 = (long)__arg4; \
_r7 = (long)__arg5; \
} while (0)
#define VDSO_CALL(fn, nr, args...) ({ \
register void *_r0 asm ("r0"); \
register long _r3 asm ("r3"); \
register long _r4 asm ("r4"); \
register long _r5 asm ("r5"); \
register long _r6 asm ("r6"); \
register long _r7 asm ("r7"); \
register long _r8 asm ("r8"); \
register long _rval asm ("r3"); \
\
LOADARGS_##nr(fn, args); \
\
asm volatile( \
" mtctr %0\n" \
" bctrl\n" \
" bns+ 1f\n" \
" neg 3, 3\n" \
"1:" \
: "+r" (_r0), "=r" (_r3), "+r" (_r4), "+r" (_r5), \
"+r" (_r6), "+r" (_r7), "+r" (_r8) \
: "r" (_rval) \
: "r9", "r10", "r11", "r12", "cr0", "cr1", "cr5", \
"cr6", "cr7", "xer", "lr", "ctr", "memory" \
); \
_rval; \
})
#else
#define VDSO_CALL(fn, nr, args...) fn(args)
#endif
#endif