Message ID | 20230407230711.2621614-2-evan@rivosinc.com |
---|---|
State | New |
Headers | show |
Series | RISC-V: ifunced memcpy using new kernel hwprobe interface | expand |
On Fri, 07 Apr 2023 16:07:08 PDT (-0700), Evan Green wrote: > Add awareness and a thin wrapper function around a new Linux system call > that allows callers to get architecture and microarchitecture > information about the CPUs from the kernel. This can be used to > do things like dynamically choose a memcpy implementation. Linux 6.4, which has the syscall, was released earlier this week. IIRC that was the last procedural blocker for these, but not sure if anyone else had comments on the implementation -- no big rush on my end, but it'd be nice to aim for these in the next release so folks can start building stuff on it (as opposed to calling the syscall directly). > Signed-off-by: Evan Green <evan@rivosinc.com> > Reviewed-by: Palmer Dabbelt <palmer@rivosinc.com> > --- > > Changes in v3: > - Update argument types to match v4 kernel interface > > Changes in v2: > - hwprobe.h: Use __has_include and duplicate Linux content to make > compilation work when Linux headers are absent (Adhemerval) > - hwprobe.h: Put declaration under __USE_GNU (Adhemerval) > - Use INLINE_SYSCALL_CALL (Adhemerval) > - Update versions > - Update UNALIGNED_MASK to match kernel v3 series. > > sysdeps/unix/sysv/linux/riscv/Makefile | 4 +- > sysdeps/unix/sysv/linux/riscv/Versions | 3 + > sysdeps/unix/sysv/linux/riscv/hwprobe.c | 30 ++++++++ > .../unix/sysv/linux/riscv/rv32/arch-syscall.h | 1 + > .../unix/sysv/linux/riscv/rv32/libc.abilist | 1 + > .../unix/sysv/linux/riscv/rv64/arch-syscall.h | 1 + > .../unix/sysv/linux/riscv/rv64/libc.abilist | 1 + > sysdeps/unix/sysv/linux/riscv/sys/hwprobe.h | 68 +++++++++++++++++++ > sysdeps/unix/sysv/linux/syscall-names.list | 1 + > 9 files changed, 108 insertions(+), 2 deletions(-) > create mode 100644 sysdeps/unix/sysv/linux/riscv/hwprobe.c > create mode 100644 sysdeps/unix/sysv/linux/riscv/sys/hwprobe.h > > diff --git a/sysdeps/unix/sysv/linux/riscv/Makefile b/sysdeps/unix/sysv/linux/riscv/Makefile > index 4b6eacb32f..45cc29e40d 100644 > --- a/sysdeps/unix/sysv/linux/riscv/Makefile > +++ b/sysdeps/unix/sysv/linux/riscv/Makefile > @@ -1,6 +1,6 @@ > ifeq ($(subdir),misc) > -sysdep_headers += sys/cachectl.h > -sysdep_routines += flush-icache > +sysdep_headers += sys/cachectl.h sys/hwprobe.h > +sysdep_routines += flush-icache hwprobe > endif > > ifeq ($(subdir),stdlib) > diff --git a/sysdeps/unix/sysv/linux/riscv/Versions b/sysdeps/unix/sysv/linux/riscv/Versions > index 5625d2a0b8..8717b62a4a 100644 > --- a/sysdeps/unix/sysv/linux/riscv/Versions > +++ b/sysdeps/unix/sysv/linux/riscv/Versions > @@ -8,4 +8,7 @@ libc { > GLIBC_2.27 { > __riscv_flush_icache; > } > + GLIBC_2.39 { > + __riscv_hwprobe; > + } > } > diff --git a/sysdeps/unix/sysv/linux/riscv/hwprobe.c b/sysdeps/unix/sysv/linux/riscv/hwprobe.c > new file mode 100644 > index 0000000000..e9023e2fba > --- /dev/null > +++ b/sysdeps/unix/sysv/linux/riscv/hwprobe.c > @@ -0,0 +1,30 @@ > +/* RISC-V hardware feature probing support on Linux > + Copyright (C) 2023 Free Software Foundation, Inc. > + > + This file is part of the GNU C Library. > + > + The GNU C Library is free software; you can redistribute it and/or > + modify it under the terms of the GNU Lesser General Public License as > + published by the Free Software Foundation; either version 2.1 of the > + License, or (at your option) any later version. > + > + The GNU C Library is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + Lesser General Public License for more details. > + > + You should have received a copy of the GNU Lesser General Public > + License along with the GNU C Library; if not, see > + <https://www.gnu.org/licenses/>. */ > + > +#include <sys/syscall.h> > +#include <sys/hwprobe.h> > +#include <sysdep.h> > + > +int > +__riscv_hwprobe (struct riscv_hwprobe *pairs, size_t pair_count, > + size_t cpu_count, unsigned long *cpus, unsigned int flags) > +{ > + return INLINE_SYSCALL_CALL (riscv_hwprobe, pairs, pair_count, > + cpu_count, cpus, flags); > +} > diff --git a/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h b/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h > index 202520ee25..2416e041c8 100644 > --- a/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h > +++ b/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h > @@ -198,6 +198,7 @@ > #define __NR_request_key 218 > #define __NR_restart_syscall 128 > #define __NR_riscv_flush_icache 259 > +#define __NR_riscv_hwprobe 258 > #define __NR_rseq 293 > #define __NR_rt_sigaction 134 > #define __NR_rt_sigpending 136 > diff --git a/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist b/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist > index b716f5c763..1548587eb1 100644 > --- a/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist > +++ b/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist > @@ -2428,3 +2428,4 @@ GLIBC_2.38 __isoc23_wcstoull F > GLIBC_2.38 __isoc23_wcstoull_l F > GLIBC_2.38 __isoc23_wcstoumax F > GLIBC_2.38 __isoc23_wscanf F > +GLIBC_2.39 __riscv_hwprobe F > diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h b/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h > index 4e65f337d4..a32bc82f60 100644 > --- a/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h > +++ b/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h > @@ -205,6 +205,7 @@ > #define __NR_request_key 218 > #define __NR_restart_syscall 128 > #define __NR_riscv_flush_icache 259 > +#define __NR_riscv_hwprobe 258 > #define __NR_rseq 293 > #define __NR_rt_sigaction 134 > #define __NR_rt_sigpending 136 > diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist > index 774e777b65..49c0577b61 100644 > --- a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist > +++ b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist > @@ -2628,3 +2628,4 @@ GLIBC_2.38 __isoc23_wcstoull F > GLIBC_2.38 __isoc23_wcstoull_l F > GLIBC_2.38 __isoc23_wcstoumax F > GLIBC_2.38 __isoc23_wscanf F > +GLIBC_2.39 __riscv_hwprobe F > diff --git a/sysdeps/unix/sysv/linux/riscv/sys/hwprobe.h b/sysdeps/unix/sysv/linux/riscv/sys/hwprobe.h > new file mode 100644 > index 0000000000..49e27ee855 > --- /dev/null > +++ b/sysdeps/unix/sysv/linux/riscv/sys/hwprobe.h > @@ -0,0 +1,68 @@ > +/* RISC-V architecture probe interface > + Copyright (C) 2023 Free Software Foundation, Inc. > + > + This file is part of the GNU C Library. > + > + The GNU C Library is free software; you can redistribute it and/or > + modify it under the terms of the GNU Lesser General Public > + License as published by the Free Software Foundation; either > + version 2.1 of the License, or (at your option) any later version. > + > + The GNU C Library is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + Lesser General Public License for more details. > + > + You should have received a copy of the GNU Lesser General Public > + License along with the GNU C Library. If not, see > + <https://www.gnu.org/licenses/>. */ > + > +#ifndef _SYS_HWPROBE_H > +#define _SYS_HWPROBE_H 1 > + > +#include <features.h> > +#include <stddef.h> > +#ifdef __has_include > +# if __has_include (<asm/hwprobe.h>) > +# include <asm/hwprobe.h> > +# endif > +#endif > + > +/* > + * Define a (probably stale) version of the interface if the Linux headers > + * aren't present. > + */ > +#ifndef RISCV_HWPROBE_KEY_MVENDORID > +struct riscv_hwprobe { > + signed long long key; > + unsigned long long value; > +}; > + > +#define RISCV_HWPROBE_KEY_MVENDORID 0 > +#define RISCV_HWPROBE_KEY_MARCHID 1 > +#define RISCV_HWPROBE_KEY_MIMPID 2 > +#define RISCV_HWPROBE_KEY_BASE_BEHAVIOR 3 > +#define RISCV_HWPROBE_BASE_BEHAVIOR_IMA (1 << 0) > +#define RISCV_HWPROBE_KEY_IMA_EXT_0 4 > +#define RISCV_HWPROBE_IMA_FD (1 << 0) > +#define RISCV_HWPROBE_IMA_C (1 << 1) > +#define RISCV_HWPROBE_KEY_CPUPERF_0 5 > +#define RISCV_HWPROBE_MISALIGNED_UNKNOWN (0 << 0) > +#define RISCV_HWPROBE_MISALIGNED_EMULATED (1 << 0) > +#define RISCV_HWPROBE_MISALIGNED_SLOW (2 << 0) > +#define RISCV_HWPROBE_MISALIGNED_FAST (3 << 0) > +#define RISCV_HWPROBE_MISALIGNED_MASK (7 << 0) > + > +#endif // RISCV_HWPROBE_KEY_MVENDORID > + > +__BEGIN_DECLS > + > +#ifdef __USE_GNU > +int > +__riscv_hwprobe (struct riscv_hwprobe *pairs, size_t pair_count, > + size_t cpu_count, unsigned long *cpus, unsigned int flags); > +#endif > + > +__END_DECLS > + > +#endif /* sys/hwprobe.h */ > diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list > index 5d27b5279c..bbc0e01d3a 100644 > --- a/sysdeps/unix/sysv/linux/syscall-names.list > +++ b/sysdeps/unix/sysv/linux/syscall-names.list > @@ -477,6 +477,7 @@ renameat2 > request_key > restart_syscall > riscv_flush_icache > +riscv_hwprobe > rmdir > rseq > rt_sigaction
* Evan Green: > diff --git a/sysdeps/unix/sysv/linux/riscv/sys/hwprobe.h b/sysdeps/unix/sysv/linux/riscv/sys/hwprobe.h > new file mode 100644 > index 0000000000..49e27ee855 > +__BEGIN_DECLS > + > +#ifdef __USE_GNU > +int > +__riscv_hwprobe (struct riscv_hwprobe *pairs, size_t pair_count, > + size_t cpu_count, unsigned long *cpus, unsigned int flags); > +#endif > + > +__END_DECLS This isn't a standard header, so you don't need to use __USE_GNU, you can declare the function unconditionally. I suspect some of the arguments can't be null pointers, so maybe use __nonnull, and probably the access attributes as well. I also expect that the function can be _THROW (it's not a cancellation point or planned to be in the future). There are some style issues (“long” instead of “long int”, the indentation in the quoted declaration, unusual (for glibc) comment formatting, but the committer can clean those up before committing. Thanks, Florian
diff --git a/sysdeps/unix/sysv/linux/riscv/Makefile b/sysdeps/unix/sysv/linux/riscv/Makefile index 4b6eacb32f..45cc29e40d 100644 --- a/sysdeps/unix/sysv/linux/riscv/Makefile +++ b/sysdeps/unix/sysv/linux/riscv/Makefile @@ -1,6 +1,6 @@ ifeq ($(subdir),misc) -sysdep_headers += sys/cachectl.h -sysdep_routines += flush-icache +sysdep_headers += sys/cachectl.h sys/hwprobe.h +sysdep_routines += flush-icache hwprobe endif ifeq ($(subdir),stdlib) diff --git a/sysdeps/unix/sysv/linux/riscv/Versions b/sysdeps/unix/sysv/linux/riscv/Versions index 5625d2a0b8..8717b62a4a 100644 --- a/sysdeps/unix/sysv/linux/riscv/Versions +++ b/sysdeps/unix/sysv/linux/riscv/Versions @@ -8,4 +8,7 @@ libc { GLIBC_2.27 { __riscv_flush_icache; } + GLIBC_2.39 { + __riscv_hwprobe; + } } diff --git a/sysdeps/unix/sysv/linux/riscv/hwprobe.c b/sysdeps/unix/sysv/linux/riscv/hwprobe.c new file mode 100644 index 0000000000..e9023e2fba --- /dev/null +++ b/sysdeps/unix/sysv/linux/riscv/hwprobe.c @@ -0,0 +1,30 @@ +/* RISC-V hardware feature probing support on Linux + Copyright (C) 2023 Free Software Foundation, Inc. + + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <sys/syscall.h> +#include <sys/hwprobe.h> +#include <sysdep.h> + +int +__riscv_hwprobe (struct riscv_hwprobe *pairs, size_t pair_count, + size_t cpu_count, unsigned long *cpus, unsigned int flags) +{ + return INLINE_SYSCALL_CALL (riscv_hwprobe, pairs, pair_count, + cpu_count, cpus, flags); +} diff --git a/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h b/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h index 202520ee25..2416e041c8 100644 --- a/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h +++ b/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h @@ -198,6 +198,7 @@ #define __NR_request_key 218 #define __NR_restart_syscall 128 #define __NR_riscv_flush_icache 259 +#define __NR_riscv_hwprobe 258 #define __NR_rseq 293 #define __NR_rt_sigaction 134 #define __NR_rt_sigpending 136 diff --git a/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist b/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist index b716f5c763..1548587eb1 100644 --- a/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist +++ b/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist @@ -2428,3 +2428,4 @@ GLIBC_2.38 __isoc23_wcstoull F GLIBC_2.38 __isoc23_wcstoull_l F GLIBC_2.38 __isoc23_wcstoumax F GLIBC_2.38 __isoc23_wscanf F +GLIBC_2.39 __riscv_hwprobe F diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h b/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h index 4e65f337d4..a32bc82f60 100644 --- a/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h +++ b/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h @@ -205,6 +205,7 @@ #define __NR_request_key 218 #define __NR_restart_syscall 128 #define __NR_riscv_flush_icache 259 +#define __NR_riscv_hwprobe 258 #define __NR_rseq 293 #define __NR_rt_sigaction 134 #define __NR_rt_sigpending 136 diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist index 774e777b65..49c0577b61 100644 --- a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist +++ b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist @@ -2628,3 +2628,4 @@ GLIBC_2.38 __isoc23_wcstoull F GLIBC_2.38 __isoc23_wcstoull_l F GLIBC_2.38 __isoc23_wcstoumax F GLIBC_2.38 __isoc23_wscanf F +GLIBC_2.39 __riscv_hwprobe F diff --git a/sysdeps/unix/sysv/linux/riscv/sys/hwprobe.h b/sysdeps/unix/sysv/linux/riscv/sys/hwprobe.h new file mode 100644 index 0000000000..49e27ee855 --- /dev/null +++ b/sysdeps/unix/sysv/linux/riscv/sys/hwprobe.h @@ -0,0 +1,68 @@ +/* RISC-V architecture probe interface + Copyright (C) 2023 Free Software Foundation, Inc. + + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + <https://www.gnu.org/licenses/>. */ + +#ifndef _SYS_HWPROBE_H +#define _SYS_HWPROBE_H 1 + +#include <features.h> +#include <stddef.h> +#ifdef __has_include +# if __has_include (<asm/hwprobe.h>) +# include <asm/hwprobe.h> +# endif +#endif + +/* + * Define a (probably stale) version of the interface if the Linux headers + * aren't present. + */ +#ifndef RISCV_HWPROBE_KEY_MVENDORID +struct riscv_hwprobe { + signed long long key; + unsigned long long value; +}; + +#define RISCV_HWPROBE_KEY_MVENDORID 0 +#define RISCV_HWPROBE_KEY_MARCHID 1 +#define RISCV_HWPROBE_KEY_MIMPID 2 +#define RISCV_HWPROBE_KEY_BASE_BEHAVIOR 3 +#define RISCV_HWPROBE_BASE_BEHAVIOR_IMA (1 << 0) +#define RISCV_HWPROBE_KEY_IMA_EXT_0 4 +#define RISCV_HWPROBE_IMA_FD (1 << 0) +#define RISCV_HWPROBE_IMA_C (1 << 1) +#define RISCV_HWPROBE_KEY_CPUPERF_0 5 +#define RISCV_HWPROBE_MISALIGNED_UNKNOWN (0 << 0) +#define RISCV_HWPROBE_MISALIGNED_EMULATED (1 << 0) +#define RISCV_HWPROBE_MISALIGNED_SLOW (2 << 0) +#define RISCV_HWPROBE_MISALIGNED_FAST (3 << 0) +#define RISCV_HWPROBE_MISALIGNED_MASK (7 << 0) + +#endif // RISCV_HWPROBE_KEY_MVENDORID + +__BEGIN_DECLS + +#ifdef __USE_GNU +int +__riscv_hwprobe (struct riscv_hwprobe *pairs, size_t pair_count, + size_t cpu_count, unsigned long *cpus, unsigned int flags); +#endif + +__END_DECLS + +#endif /* sys/hwprobe.h */ diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list index 5d27b5279c..bbc0e01d3a 100644 --- a/sysdeps/unix/sysv/linux/syscall-names.list +++ b/sysdeps/unix/sysv/linux/syscall-names.list @@ -477,6 +477,7 @@ renameat2 request_key restart_syscall riscv_flush_icache +riscv_hwprobe rmdir rseq rt_sigaction