diff options
author | Vineet Gupta <vgupta@synopsys.com> | 2018-10-23 14:44:30 -0700 |
---|---|---|
committer | Vineet Gupta <vgupta@synopsys.com> | 2020-07-10 16:08:44 -0700 |
commit | add5071a5c95083b628a3bd03654437fcc6d8f81 (patch) | |
tree | f2d25a253006bfce9cae4b0b1d7c6cc6a13c70f4 /sysdeps/unix/sysv/linux/arc/clone.S | |
parent | 3ab8611a229fc2bd9a165d067390f7b6165ef6d4 (diff) | |
download | glibc-add5071a5c95083b628a3bd03654437fcc6d8f81.zip glibc-add5071a5c95083b628a3bd03654437fcc6d8f81.tar.gz glibc-add5071a5c95083b628a3bd03654437fcc6d8f81.tar.bz2 |
ARC: Linux Syscall Interface
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Diffstat (limited to 'sysdeps/unix/sysv/linux/arc/clone.S')
-rw-r--r-- | sysdeps/unix/sysv/linux/arc/clone.S | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/sysdeps/unix/sysv/linux/arc/clone.S b/sysdeps/unix/sysv/linux/arc/clone.S new file mode 100644 index 0000000..f14a5d3 --- /dev/null +++ b/sysdeps/unix/sysv/linux/arc/clone.S @@ -0,0 +1,93 @@ +/* clone() implementation for ARC. + Copyright (C) 2020 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andrew Jenner <andrew@codesourcery.com>, 2008. + + 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 <sysdep.h> +#define _ERRNO_H 1 +#include <bits/errno.h> +#include <tcb-offsets.h> + +#define CLONE_SETTLS 0x00080000 + +/* int clone(int (*fn)(void *), void *child_stack, + int flags, void *arg, ... + < pid_t *ptid, struct user_desc *tls, pid_t *ctid > ); + + NOTE: I'm assuming that the last 3 args are NOT var-args and in case all + 3 are not relevant, caller will nevertheless pass those as NULL. + + clone syscall in kernel (ABI: CONFIG_CLONE_BACKWARDS) + + int sys_clone(unsigned long int clone_flags, + unsigned long int newsp, + int __user *parent_tidptr, + void *tls, + int __user *child_tidptr). */ + +ENTRY (__clone) + cmp r0, 0 /* @fn can't be NULL. */ + cmp.ne r1, 0 /* @child_stack can't be NULL. */ + bz L (__sys_err) + + /* save some of the orig args + r0 containg @fn will be clobbered AFTER syscall (with ret val) + rest are clobbered BEFORE syscall due to different arg ordering. */ + mov r10, r0 /* @fn. */ + mov r11, r3 /* @args. */ + mov r12, r2 /* @clone_flags. */ + mov r9, r5 /* @tls. */ + + /* adjust libc args for syscall. */ + + mov r0, r2 /* libc @flags is 1st syscall arg. */ + mov r2, r4 /* libc @ptid. */ + mov r3, r5 /* libc @tls. */ + mov r4, r6 /* libc @ctid. */ + mov r8, __NR_clone + ARC_TRAP_INSN + + cmp r0, 0 /* return code : 0 new process, !0 parent. */ + blt L (__sys_err2) /* < 0 (signed) error. */ + jnz [blink] /* Parent returns. */ + + /* child jumps off to @fn with @arg as argument + TP register already set by kernel. */ + jl.d [r10] + mov r0, r11 + + /* exit() with result from @fn (already in r0). */ + mov r8, __NR_exit + ARC_TRAP_INSN + /* In case it ever came back. */ + flag 1 + +L (__sys_err): + mov r0, -EINVAL +L (__sys_err2): + /* (1) No need to make -ve kernel error code as positive errno + __syscall_error expects the -ve error code returned by kernel + (2) r0 still had orig -ve kernel error code + (3) Tail call to __syscall_error so we dont have to come back + here hence instead of jmp-n-link (reg push/pop) we do jmp + (4) No need to route __syscall_error via PLT, B is inherently + position independent. */ + b __syscall_error +PSEUDO_END (__clone) +libc_hidden_def (__clone) +weak_alias (__clone, clone) |