1 /* clone() implementation for ARC.
2 Copyright (C) 2020 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4 Contributed by Andrew Jenner <andrew@codesourcery.com>, 2008.
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.
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.
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/>. */
23 #include <bits/errno.h>
24 #include <tcb-offsets.h>
26 #define CLONE_SETTLS 0x00080000
28 /* int clone(int (*fn)(void *), void *child_stack,
29 int flags, void *arg, ...
30 < pid_t *ptid, struct user_desc *tls, pid_t *ctid > );
32 NOTE: I'm assuming that the last 3 args are NOT var-args and in case all
33 3 are not relevant, caller will nevertheless pass those as NULL.
35 clone syscall in kernel (ABI: CONFIG_CLONE_BACKWARDS)
37 int sys_clone(unsigned long int clone_flags,
38 unsigned long int newsp,
39 int __user *parent_tidptr,
41 int __user *child_tidptr). */
44 cmp r0, 0 /* @fn can't be NULL. */
45 cmp.ne r1, 0 /* @child_stack can't be NULL. */
48 /* save some of the orig args
49 r0 containg @fn will be clobbered AFTER syscall (with ret val)
50 rest are clobbered BEFORE syscall due to different arg ordering. */
51 mov r10, r0 /* @fn. */
52 mov r11, r3 /* @args. */
53 mov r12, r2 /* @clone_flags. */
54 mov r9, r5 /* @tls. */
56 /* adjust libc args for syscall. */
58 mov r0, r2 /* libc @flags is 1st syscall arg. */
59 mov r2, r4 /* libc @ptid. */
60 mov r3, r5 /* libc @tls. */
61 mov r4, r6 /* libc @ctid. */
65 cmp r0, 0 /* return code : 0 new process, !0 parent. */
66 blt L (__sys_err2) /* < 0 (signed) error. */
67 jnz [blink] /* Parent returns. */
69 /* child jumps off to @fn with @arg as argument
70 TP register already set by kernel. */
74 /* exit() with result from @fn (already in r0). */
77 /* In case it ever came back. */
83 /* (1) No need to make -ve kernel error code as positive errno
84 __syscall_error expects the -ve error code returned by kernel
85 (2) r0 still had orig -ve kernel error code
86 (3) Tail call to __syscall_error so we dont have to come back
87 here hence instead of jmp-n-link (reg push/pop) we do jmp
88 (4) No need to route __syscall_error via PLT, B is inherently
89 position independent. */
92 libc_hidden_def (__clone)
93 weak_alias (__clone, clone)