1 | /* The clone3 syscall wrapper. Linux/RISC-V version. |
2 | Copyright (C) 2023-2024 Free Software Foundation, Inc. |
3 | |
4 | This file is part of the GNU C Library. |
5 | |
6 | The GNU C Library is free software; you can redistribute it and/or |
7 | modify it under the terms of the GNU Lesser General Public |
8 | License as published by the Free Software Foundation; either |
9 | version 2.1 of the License, or (at your option) any later version. |
10 | |
11 | The GNU C Library is distributed in the hope that it will be useful, |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
14 | Lesser General Public License for more details. |
15 | |
16 | You should have received a copy of the GNU Lesser General Public |
17 | License along with the GNU C Library; if not, see |
18 | <https://www.gnu.org/licenses/>. */ |
19 | |
20 | #include <asm/errno.h> |
21 | #include <sys/asm.h> |
22 | #include <sysdep.h> |
23 | |
24 | /* The userland implementation is: |
25 | int clone3 (struct clone_args *cl_args, size_t size, |
26 | int (*func)(void *arg), void *arg); |
27 | |
28 | the kernel entry is: |
29 | int clone3 (struct clone_args *cl_args, size_t size); |
30 | |
31 | The parameters are passed in registers from userland: |
32 | a0: cl_args |
33 | a1: size |
34 | a2: func |
35 | a3: arg */ |
36 | |
37 | .text |
38 | ENTRY(__clone3) |
39 | /* Sanity check args. */ |
40 | beqz a0, L(invalid) /* No NULL cl_args pointer. */ |
41 | beqz a2, L(invalid) /* No NULL function pointer. */ |
42 | |
43 | /* Do the system call, the kernel expects: |
44 | a7: system call number |
45 | a0: cl_args |
46 | a1: size */ |
47 | li a7, __NR_clone3 |
48 | scall |
49 | |
50 | bltz a0, L(error) |
51 | beqz a0, L(thread_start) |
52 | |
53 | ret |
54 | |
55 | L(invalid): |
56 | li a0, -EINVAL |
57 | L(error): |
58 | tail __syscall_error |
59 | END (__clone3) |
60 | |
61 | ENTRY(__thread_start_clone3) |
62 | L(thread_start): |
63 | /* Terminate call stack by noting ra is undefined. Use a dummy |
64 | .cfi_label to force starting the FDE. */ |
65 | .cfi_label .Ldummy |
66 | cfi_undefined (ra) |
67 | |
68 | /* Restore the arg for user's function and call the user's |
69 | function. */ |
70 | mv a0, a3 /* Argument pointer. */ |
71 | jalr a2 |
72 | |
73 | /* Call exit with the function's return value. */ |
74 | li a7, __NR_exit |
75 | scall |
76 | END(__thread_start_clone3) |
77 | |
78 | libc_hidden_def (__clone3) |
79 | weak_alias (__clone3, clone3) |
80 | |