1/* Wrapper around clone system call. RISC-V version. 2 Copyright (C) 1996-2021 Free Software Foundation, Inc. 3 This file is part of the GNU C Library. 4 5 The GNU C Library is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Lesser General Public 7 License as published by the Free Software Foundation; either 8 version 2.1 of the License, or (at your option) any later version. 9 10 The GNU C Library is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Lesser General Public License for more details. 14 15 You should have received a copy of the GNU Lesser General Public 16 License along with the GNU C Library. If not, see 17 <https://www.gnu.org/licenses/>. */ 18 19/* clone() is even more special than fork() as it mucks with stacks 20 and invokes a function in the right context after its all over. */ 21 22#include <sys/asm.h> 23#include <sysdep.h> 24#define _ERRNO_H 1 25#include <bits/errno.h> 26#include <tls.h> 27#include "tcb-offsets.h" 28 29/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg, 30 void *parent_tidptr, void *tls, void *child_tidptr) */ 31 32 .text 33LEAF (__clone) 34 35 /* Align stack to a 128-bit boundary as per RISC-V ABI. */ 36 andi a1,a1,ALMASK 37 38 /* Sanity check arguments. */ 39 beqz a0,L (invalid) /* No NULL function pointers. */ 40 beqz a1,L (invalid) /* No NULL stack pointers. */ 41 42 addi a1,a1,-16 /* Reserve argument save space. */ 43 REG_S a0,0(a1) /* Save function pointer. */ 44 REG_S a3,SZREG(a1) /* Save argument pointer. */ 45 46 /* The syscall expects the args to be in different slots. */ 47 mv a0,a2 48 mv a2,a4 49 mv a3,a5 50 mv a4,a6 51 52 /* Do the system call. */ 53 li a7,__NR_clone 54 scall 55 56 bltz a0,L (error) 57 beqz a0,L (thread_start) 58 59 /* Successful return from the parent. */ 60 ret 61 62L (invalid): 63 li a0, -EINVAL 64 /* Something bad happened -- no child created. */ 65L (error): 66 j __syscall_error 67 END (__clone) 68 69/* Load up the arguments to the function. Put this block of code in 70 its own function so that we can terminate the stack trace with our 71 debug info. */ 72 73ENTRY (__thread_start) 74L (thread_start): 75 /* Terminate call stack by noting ra is undefined. Use a dummy 76 .cfi_label to force starting the FDE. */ 77 .cfi_label .Ldummy 78 cfi_undefined (ra) 79 80 /* Restore the arg for user's function. */ 81 REG_L a1,0(sp) /* Function pointer. */ 82 REG_L a0,SZREG(sp) /* Argument pointer. */ 83 84 /* Call the user's function. */ 85 jalr a1 86 87 /* Call exit with the function's return value. */ 88 li a7, __NR_exit 89 scall 90 91 END (__thread_start) 92 93libc_hidden_def (__clone) 94weak_alias (__clone, clone) 95