diff options
author | Matheus Castanho <msc@linux.ibm.com> | 2020-12-03 14:15:27 -0300 |
---|---|---|
committer | Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com> | 2020-12-30 18:26:25 -0300 |
commit | 68ab82f56690ada86ac1e0c46bad06ba189a10ef (patch) | |
tree | e76e999e3b9ccda3133e2dc09b53161a6dec8460 /sysdeps/powerpc/powerpc32 | |
parent | 9835632cf43fd6d1f8b8f40a88892a45b6bfad6e (diff) | |
download | glibc-68ab82f56690ada86ac1e0c46bad06ba189a10ef.tar.gz glibc-68ab82f56690ada86ac1e0c46bad06ba189a10ef.tar.xz glibc-68ab82f56690ada86ac1e0c46bad06ba189a10ef.zip |
powerpc: Runtime selection between sc and scv for syscalls
Linux kernel v5.9 added support for system calls using the scv instruction for POWER9 and later. The new codepath provides better performance (see below) if compared to using sc. For the foreseeable future, both sc and scv mechanisms will co-exist, so this patch enables glibc to do a runtime check and use scv when it is available. Before issuing the system call to the kernel, we check hwcap2 in the TCB for PPC_FEATURE2_SCV to see if scv is supported by the kernel. If not, we fallback to sc and keep the old behavior. The kernel implements a different error return convention for scv, so when returning from a system call we need to handle the return value differently depending on the instruction we used to enter the kernel. For syscalls implemented in ASM, entry and exit are implemented by different macros (PSEUDO and PSEUDO_RET, resp.), which may be used in sequence (e.g. for templated syscalls) or with other instructions in between (e.g. clone). To avoid accessing the TCB a second time on PSEUDO_RET to check which instruction we used, the value read from hwcap2 is cached on a non-volatile register. This is not needed when using INTERNAL_SYSCALL macro, since entry and exit are bundled into the same inline asm directive. The dynamic loader may issue syscalls before the TCB has been setup so it always uses sc with no extra checks. For the static case, there is no compile-time way to determine if we are inside startup code, so we also check the value of the thread pointer before effectively accessing the TCB. For such situations in which the availability of scv cannot be determined, sc is always used. Support for scv in syscalls implemented in their own ASM file (clone and vfork) will be added later. For now simply use sc as before. Average performance over 1M calls for each syscall "type": - stat: C wrapper calling INTERNAL_SYSCALL - getpid: templated ASM syscall - syscall: call to gettid using syscall function Standard: stat : 1.573445 us / ~3619 cycles getpid : 0.164986 us / ~379 cycles syscall : 0.162743 us / ~374 cycles With scv: stat : 1.537049 us / ~3535 cycles <~ -84 cycles / -2.32% getpid : 0.109923 us / ~253 cycles <~ -126 cycles / -33.25% syscall : 0.116410 us / ~268 cycles <~ -106 cycles / -28.34% Tested on powerpc, powerpc64, powerpc64le (with and without scv) Tested-by: Lucas A. M. Magalhães <lamm@linux.ibm.com> Reviewed-by: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com>
Diffstat (limited to 'sysdeps/powerpc/powerpc32')
-rw-r--r-- | sysdeps/powerpc/powerpc32/sysdep.h | 15 |
1 files changed, 12 insertions, 3 deletions
diff --git a/sysdeps/powerpc/powerpc32/sysdep.h b/sysdeps/powerpc/powerpc32/sysdep.h index 829eec266a..a3fc1f0ca7 100644 --- a/sysdeps/powerpc/powerpc32/sysdep.h +++ b/sysdeps/powerpc/powerpc32/sysdep.h @@ -92,7 +92,10 @@ GOT_LABEL: ; \ #define DO_CALL(syscall) \ li 0,syscall; \ - sc + DO_CALL_SC + +#define DO_CALL_SC \ + sc #undef JUMPTARGET #ifdef PIC @@ -106,14 +109,20 @@ GOT_LABEL: ; \ # define HIDDEN_JUMPTARGET(name) __GI_##name##@local #endif +#define TAIL_CALL_SYSCALL_ERROR \ + b __syscall_error@local + #define PSEUDO(name, syscall_name, args) \ .section ".text"; \ ENTRY (name) \ DO_CALL (SYS_ify (syscall_name)); +#define RET_SC \ + bnslr+; + #define PSEUDO_RET \ - bnslr+; \ - b __syscall_error@local + RET_SC; \ + TAIL_CALL_SYSCALL_ERROR #define ret PSEUDO_RET #undef PSEUDO_END |