Message ID | 20230203171237.1220878-4-adhemerval.zanella@linaro.org |
---|---|
State | New |
Headers | show |
Series | Add clone3 support for multiple architectures | expand |
Ping. On 03/02/23 14:12, Adhemerval Zanella wrote: > It follows the internal signature: > > extern int clone3 (struct clone_args *__cl_args, size_t __size, > int (*__func) (void *__arg), void *__arg); > > Checked on riscv64-linux-gnu-rv64imafdc-lp64d. > --- > sysdeps/unix/sysv/linux/riscv/clone3.S | 80 ++++++++++++++++++++++++++ > sysdeps/unix/sysv/linux/riscv/sysdep.h | 1 + > 2 files changed, 81 insertions(+) > create mode 100644 sysdeps/unix/sysv/linux/riscv/clone3.S > > diff --git a/sysdeps/unix/sysv/linux/riscv/clone3.S b/sysdeps/unix/sysv/linux/riscv/clone3.S > new file mode 100644 > index 0000000000..ee5780ee2f > --- /dev/null > +++ b/sysdeps/unix/sysv/linux/riscv/clone3.S > @@ -0,0 +1,80 @@ > +/* The clone3 syscall wrapper. Linux/RISC-V version. > + 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 <asm/errno.h> > +#include <sys/asm.h> > +#include <sysdep.h> > + > +/* The userland implementation is: > + int clone3 (struct clone_args *cl_args, size_t size, > + int (*func)(void *arg), void *arg); > + > + the kernel entry is: > + int clone3 (struct clone_args *cl_args, size_t size); > + > + The parameters are passed in registers from userland: > + a0: cl_args > + a1: size > + a2: func > + a3: arg */ > + > + .text > +ENTRY(__clone3) > + /* Sanity check args. */ > + beqz a0, L(invalid) /* No NULL cl_args pointer. */ > + beqz a2, L(invalid) /* No NULL function pointer. */ > + > + /* Do the system call, the kernel expects: > + a7: system call number > + a0: cl_args > + a1: size */ > + li a7, __NR_clone3 > + scall > + > + bltz a0, L(error) > + beqz a0, L(thread_start) > + > + ret > + > +L(invalid): > + li a0, -EINVAL > +L(error): > + tail __syscall_error > +END (__clone3) > + > +ENTRY(__thread_start_clone3) > +L(thread_start): > + /* Terminate call stack by noting ra is undefined. Use a dummy > + .cfi_label to force starting the FDE. */ > + .cfi_label .Ldummy > + cfi_undefined (ra) > + > + /* Restore the arg for user's function and call the user's > + function. */ > + mv a1, a2 /* Function pointer. */ > + mv a0, a3 /* Argument pointer. */ > + jalr a1 > + > + /* Call exit with the function's return value. */ > + li a7, __NR_exit > + scall > +END(__thread_start_clone3) > + > +libc_hidden_def (__clone3) > +weak_alias (__clone3, clone3) > diff --git a/sysdeps/unix/sysv/linux/riscv/sysdep.h b/sysdeps/unix/sysv/linux/riscv/sysdep.h > index 4af5fe5dbc..e96a930409 100644 > --- a/sysdeps/unix/sysv/linux/riscv/sysdep.h > +++ b/sysdeps/unix/sysv/linux/riscv/sysdep.h > @@ -151,6 +151,7 @@ > > /* RV32 does not support the gettime VDSO syscalls. */ > # endif > +# define HAVE_CLONE3_WRAPPER 1 > > /* List of system calls which are supported as vsyscalls (for RV32 and > RV64). */
On Fri, 03 Feb 2023 09:12:35 PST (-0800), adhemerval.zanella@linaro.org wrote: > It follows the internal signature: > > extern int clone3 (struct clone_args *__cl_args, size_t __size, > int (*__func) (void *__arg), void *__arg); > > Checked on riscv64-linux-gnu-rv64imafdc-lp64d. Due to a bug we only had clone3 on rv64 until 59a4e0d5511b ("RISC-V: Include clone3() on rv32"), which landed in 5.15 and was then backported all the way to 5.4. > --- > sysdeps/unix/sysv/linux/riscv/clone3.S | 80 ++++++++++++++++++++++++++ > sysdeps/unix/sysv/linux/riscv/sysdep.h | 1 + > 2 files changed, 81 insertions(+) > create mode 100644 sysdeps/unix/sysv/linux/riscv/clone3.S > > diff --git a/sysdeps/unix/sysv/linux/riscv/clone3.S b/sysdeps/unix/sysv/linux/riscv/clone3.S > new file mode 100644 > index 0000000000..ee5780ee2f > --- /dev/null > +++ b/sysdeps/unix/sysv/linux/riscv/clone3.S > @@ -0,0 +1,80 @@ > +/* The clone3 syscall wrapper. Linux/RISC-V version. > + 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 <asm/errno.h> > +#include <sys/asm.h> > +#include <sysdep.h> > + > +/* The userland implementation is: > + int clone3 (struct clone_args *cl_args, size_t size, > + int (*func)(void *arg), void *arg); > + > + the kernel entry is: > + int clone3 (struct clone_args *cl_args, size_t size); > + > + The parameters are passed in registers from userland: > + a0: cl_args > + a1: size > + a2: func > + a3: arg */ > + > + .text > +ENTRY(__clone3) > + /* Sanity check args. */ > + beqz a0, L(invalid) /* No NULL cl_args pointer. */ > + beqz a2, L(invalid) /* No NULL function pointer. */ > + > + /* Do the system call, the kernel expects: > + a7: system call number > + a0: cl_args > + a1: size */ > + li a7, __NR_clone3 IIUC this only builds with kernel headers 5.15 or newer on rv32. I'm not sure if that's a problem: unless I'm missing something we support building for those systems now, but rv32 is pretty esoteric so I'm not sure anyone cares -- maybe someone uses 5.15 on rv32 (some rv64 hardware is still being released with 5.10-based vendor kernels), but 5.4 is pretty old for us. > + scall > + > + bltz a0, L(error) > + beqz a0, L(thread_start) > + > + ret > + > +L(invalid): > + li a0, -EINVAL > +L(error): > + tail __syscall_error > +END (__clone3) > + > +ENTRY(__thread_start_clone3) > +L(thread_start): > + /* Terminate call stack by noting ra is undefined. Use a dummy > + .cfi_label to force starting the FDE. */ > + .cfi_label .Ldummy > + cfi_undefined (ra) > + > + /* Restore the arg for user's function and call the user's > + function. */ > + mv a1, a2 /* Function pointer. */ I think we don't need that mv, we can just call a2 directly? Unless I'm missing some reason the thread main needs to see a pointer to itself? > + mv a0, a3 /* Argument pointer. */ > + jalr a1 > + > + /* Call exit with the function's return value. */ > + li a7, __NR_exit > + scall > +END(__thread_start_clone3) > + > +libc_hidden_def (__clone3) > +weak_alias (__clone3, clone3) > diff --git a/sysdeps/unix/sysv/linux/riscv/sysdep.h b/sysdeps/unix/sysv/linux/riscv/sysdep.h > index 4af5fe5dbc..e96a930409 100644 > --- a/sysdeps/unix/sysv/linux/riscv/sysdep.h > +++ b/sysdeps/unix/sysv/linux/riscv/sysdep.h > @@ -151,6 +151,7 @@ > > /* RV32 does not support the gettime VDSO syscalls. */ > # endif > +# define HAVE_CLONE3_WRAPPER 1 > > /* List of system calls which are supported as vsyscalls (for RV32 and > RV64). */ That's just some minor comments though, so Reviewed-by: Palmer Dabbelt <palmer@rivosinc.com> Thanks! (and sorry I missed it for a bit)
On 29/05/23 11:04, Palmer Dabbelt wrote: > On Fri, 03 Feb 2023 09:12:35 PST (-0800), adhemerval.zanella@linaro.org wrote: >> It follows the internal signature: >> >> extern int clone3 (struct clone_args *__cl_args, size_t __size, >> int (*__func) (void *__arg), void *__arg); >> >> Checked on riscv64-linux-gnu-rv64imafdc-lp64d. > > Due to a bug we only had clone3 on rv64 until 59a4e0d5511b ("RISC-V: Include clone3() on rv32"), which landed in 5.15 and was then backported all the way to 5.4. > >> --- >> sysdeps/unix/sysv/linux/riscv/clone3.S | 80 ++++++++++++++++++++++++++ >> sysdeps/unix/sysv/linux/riscv/sysdep.h | 1 + >> 2 files changed, 81 insertions(+) >> create mode 100644 sysdeps/unix/sysv/linux/riscv/clone3.S >> >> diff --git a/sysdeps/unix/sysv/linux/riscv/clone3.S b/sysdeps/unix/sysv/linux/riscv/clone3.S >> new file mode 100644 >> index 0000000000..ee5780ee2f >> --- /dev/null >> +++ b/sysdeps/unix/sysv/linux/riscv/clone3.S >> @@ -0,0 +1,80 @@ >> +/* The clone3 syscall wrapper. Linux/RISC-V version. >> + 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 <asm/errno.h> >> +#include <sys/asm.h> >> +#include <sysdep.h> >> + >> +/* The userland implementation is: >> + int clone3 (struct clone_args *cl_args, size_t size, >> + int (*func)(void *arg), void *arg); >> + >> + the kernel entry is: >> + int clone3 (struct clone_args *cl_args, size_t size); >> + >> + The parameters are passed in registers from userland: >> + a0: cl_args >> + a1: size >> + a2: func >> + a3: arg */ >> + >> + .text >> +ENTRY(__clone3) >> + /* Sanity check args. */ >> + beqz a0, L(invalid) /* No NULL cl_args pointer. */ >> + beqz a2, L(invalid) /* No NULL function pointer. */ >> + >> + /* Do the system call, the kernel expects: >> + a7: system call number >> + a0: cl_args >> + a1: size */ >> + li a7, __NR_clone3 > > IIUC this only builds with kernel headers 5.15 or newer on rv32. I'm not sure if that's a problem: unless I'm missing something we support building for those systems now, but rv32 is pretty esoteric so I'm not sure anyone cares -- maybe someone uses 5.15 on rv32 (some rv64 hardware is still being released with 5.10-based vendor kernels), but 5.4 is pretty old for us. The __NR_XXX macros are now provided by arch-syscall.h, which in turn is generated by the kernel header. And we already have clone3 for rv32 since 3387c40a8bb. > >> + scall >> + >> + bltz a0, L(error) >> + beqz a0, L(thread_start) >> + >> + ret >> + >> +L(invalid): >> + li a0, -EINVAL >> +L(error): >> + tail __syscall_error >> +END (__clone3) >> + >> +ENTRY(__thread_start_clone3) >> +L(thread_start): >> + /* Terminate call stack by noting ra is undefined. Use a dummy >> + .cfi_label to force starting the FDE. */ >> + .cfi_label .Ldummy >> + cfi_undefined (ra) >> + >> + /* Restore the arg for user's function and call the user's >> + function. */ >> + mv a1, a2 /* Function pointer. */ > > I think we don't need that mv, we can just call a2 directly? Unless I'm missing some reason the thread main needs to see a pointer to itself? We can, I will change it. > >> + mv a0, a3 /* Argument pointer. */ >> + jalr a1 >> + >> + /* Call exit with the function's return value. */ >> + li a7, __NR_exit >> + scall >> +END(__thread_start_clone3) >> + >> +libc_hidden_def (__clone3) >> +weak_alias (__clone3, clone3) >> diff --git a/sysdeps/unix/sysv/linux/riscv/sysdep.h b/sysdeps/unix/sysv/linux/riscv/sysdep.h >> index 4af5fe5dbc..e96a930409 100644 >> --- a/sysdeps/unix/sysv/linux/riscv/sysdep.h >> +++ b/sysdeps/unix/sysv/linux/riscv/sysdep.h >> @@ -151,6 +151,7 @@ >> >> /* RV32 does not support the gettime VDSO syscalls. */ >> # endif >> +# define HAVE_CLONE3_WRAPPER 1 >> >> /* List of system calls which are supported as vsyscalls (for RV32 and >> RV64). */ > > That's just some minor comments though, so > > Reviewed-by: Palmer Dabbelt <palmer@rivosinc.com> Thanks. > > Thanks! (and sorry I missed it for a bit)
diff --git a/sysdeps/unix/sysv/linux/riscv/clone3.S b/sysdeps/unix/sysv/linux/riscv/clone3.S new file mode 100644 index 0000000000..ee5780ee2f --- /dev/null +++ b/sysdeps/unix/sysv/linux/riscv/clone3.S @@ -0,0 +1,80 @@ +/* The clone3 syscall wrapper. Linux/RISC-V version. + 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 <asm/errno.h> +#include <sys/asm.h> +#include <sysdep.h> + +/* The userland implementation is: + int clone3 (struct clone_args *cl_args, size_t size, + int (*func)(void *arg), void *arg); + + the kernel entry is: + int clone3 (struct clone_args *cl_args, size_t size); + + The parameters are passed in registers from userland: + a0: cl_args + a1: size + a2: func + a3: arg */ + + .text +ENTRY(__clone3) + /* Sanity check args. */ + beqz a0, L(invalid) /* No NULL cl_args pointer. */ + beqz a2, L(invalid) /* No NULL function pointer. */ + + /* Do the system call, the kernel expects: + a7: system call number + a0: cl_args + a1: size */ + li a7, __NR_clone3 + scall + + bltz a0, L(error) + beqz a0, L(thread_start) + + ret + +L(invalid): + li a0, -EINVAL +L(error): + tail __syscall_error +END (__clone3) + +ENTRY(__thread_start_clone3) +L(thread_start): + /* Terminate call stack by noting ra is undefined. Use a dummy + .cfi_label to force starting the FDE. */ + .cfi_label .Ldummy + cfi_undefined (ra) + + /* Restore the arg for user's function and call the user's + function. */ + mv a1, a2 /* Function pointer. */ + mv a0, a3 /* Argument pointer. */ + jalr a1 + + /* Call exit with the function's return value. */ + li a7, __NR_exit + scall +END(__thread_start_clone3) + +libc_hidden_def (__clone3) +weak_alias (__clone3, clone3) diff --git a/sysdeps/unix/sysv/linux/riscv/sysdep.h b/sysdeps/unix/sysv/linux/riscv/sysdep.h index 4af5fe5dbc..e96a930409 100644 --- a/sysdeps/unix/sysv/linux/riscv/sysdep.h +++ b/sysdeps/unix/sysv/linux/riscv/sysdep.h @@ -151,6 +151,7 @@ /* RV32 does not support the gettime VDSO syscalls. */ # endif +# define HAVE_CLONE3_WRAPPER 1 /* List of system calls which are supported as vsyscalls (for RV32 and RV64). */