diff options
Diffstat (limited to 'libc/sysdeps/linux/kvx/clone.S')
-rw-r--r-- | libc/sysdeps/linux/kvx/clone.S | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/libc/sysdeps/linux/kvx/clone.S b/libc/sysdeps/linux/kvx/clone.S new file mode 100644 index 000000000..71ea80a01 --- /dev/null +++ b/libc/sysdeps/linux/kvx/clone.S @@ -0,0 +1,100 @@ +/* + * This file is subject to the terms and conditions of the LGPL V2.1 + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2018 Kalray Inc. + */ + +#include <sysdep.h> +#define _ERRNO_H 1 +#include <bits/errno.h> + +/** + * Clone system call implementation for kvx + * int clone (int (*fn)(void *arg), void *child_stack, int flags, void *arg, + * pid_t *ptid, struct user_desc *tls, pid_t *ctid); + * $r0 = fn + * $r1 = child_stack + * $r2 = flags + * $r3 = args + * $r4 = ptid + * $r5 = tls + * $r6 = ctid + * + * The kernel expects to find its arguments in the following order: + * sys_clone(unsigned long clone_flags, unsigned long newsp, + * int __user * parent_tidptr, + * int __user * child_tidptr, + * unsigned long tls) + * + * So we have to make a few modifications before calling + * + */ + +ENTRY (__clone) + /* Check fn and stack to be non-null */ + cb.deqz $r1? L(clone_einval_error) + /* Align child stack first */ + andd $r1 = $r1, -32 + ;; + cb.deqz $r0? L(clone_einval_error) + /* Prepare space for child arguments on stack and stay aligned */ + addd $r1 = $r1, -32 + ;; + /* Save fn ($r0) on child stack */ + sd 0[$r1] = $r0 + /* Set clone_flags */ + copyd $r0 = $r2 + ;; + /* Save args ($r3) on child stack */ + sd 8[$r1] = $r3 + /* Set parent_tidptr */ + copyd $r2 = $r4 + /* Set child_tidptr */ + copyd $r3 = $r6 + /* Set tls */ + copyd $r4 = $r5 + ;; + scall SYS_ify(clone) + ;; + /* If 0, then we are the child */ + cb.deqz $r0, L(child_start) + ;; + /* Else we are the parent, and we need to check for errors */ + cb.dltz $r0, L(clone_error) + ;; + /* No error ! Yeepa ! */ + ret + ;; +L(child_start): + /* get fn from stack */ + ld $r1 = 0[$sp] + ;; + /* Get args from stack */ + ld $r0 = 8[$sp] + addd $sp = $sp, 32 + ;; + icall $r1 + ;; + scall SYS_ify(exit) + ;; + /* We should never ever get here ! */ + errop + ;; +L(clone_einval_error): + make $r0 = -EINVAL + ;; +L(clone_error): + /* goto __syscall_error but do not use call or $ra will be + * destroyed */ + goto __syscall_error + ;; + /* We will not return here but to clone caller + * (stored in $ra) */ + errop + ;; +END(__clone) + +libc_hidden_def (__clone) +weak_alias (__clone,clone) |