/* * 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 #define _ERRNO_H 1 #include /** * 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)