1/* Copyright (C) 1996-2022 Free Software Foundation, Inc. 2 This file is part of the GNU C Library. 3 4 The GNU C Library is free software; you can redistribute it and/or 5 modify it under the terms of the GNU Lesser General Public 6 License as published by the Free Software Foundation; either 7 version 2.1 of the License, or (at your option) any later version. 8 9 The GNU C Library is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 Lesser General Public License for more details. 13 14 You should have received a copy of the GNU Lesser General Public 15 License along with the GNU C Library. If not, see 16 <https://www.gnu.org/licenses/>. */ 17 18/* clone() is even more special than fork() as it mucks with stacks 19 and invokes a function in the right context after its all over. */ 20 21#include <sys/asm.h> 22#include <sysdep.h> 23#define _ERRNO_H 1 24#include <bits/errno.h> 25#include <tls.h> 26 27/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg, 28 void *parent_tidptr, void *tls, void *child_tidptr) */ 29 30 .text 31 .set nomips16 32#if _MIPS_SIM == _ABIO32 33# define EXTRA_LOCALS 1 34#else 35# define EXTRA_LOCALS 0 36#endif 37LOCALSZ= 4 38FRAMESZ= (((NARGSAVE+LOCALSZ)*SZREG)+ALSZ)&ALMASK 39GPOFF= FRAMESZ-(1*SZREG) 40NESTED(__clone,4*SZREG,sp) 41#ifdef __PIC__ 42 SETUP_GP 43#endif 44 PTR_SUBU sp, FRAMESZ 45 cfi_adjust_cfa_offset (FRAMESZ) 46 SETUP_GP64_STACK (GPOFF, __clone) 47#ifdef __PIC__ 48 SAVE_GP (GPOFF) 49#endif 50#ifdef PROF 51 .set noat 52 move $1,ra 53 jal _mcount 54 .set at 55#endif 56 57 /* Align stack to 8/16 bytes per the ABI. */ 58#if _MIPS_SIM == _ABIO32 59 li t0,-8 60#else 61 li t0,-16 62#endif 63 and a1,a1,t0 64 65 /* Sanity check arguments. */ 66 li v0,EINVAL 67 beqz a0,L(error) /* No NULL function pointers. */ 68 beqz a1,L(error) /* No NULL stack pointers. */ 69 70 PTR_SUBU a1,32 /* Reserve argument save space. */ 71 PTR_S a0,0(a1) /* Save function pointer. */ 72 PTR_S a3,PTRSIZE(a1) /* Save argument pointer. */ 73 LONG_S a2,(PTRSIZE*2)(a1) /* Save clone flags. */ 74 75 move a0,a2 76 77 /* Shuffle in the last three arguments - arguments 5, 6, and 7 to 78 this function, but arguments 3, 4, and 5 to the syscall. */ 79#if _MIPS_SIM == _ABIO32 80 PTR_L a2,(FRAMESZ+PTRSIZE+PTRSIZE+16)(sp) 81 PTR_S a2,16(sp) 82 PTR_L a2,(FRAMESZ+16)(sp) 83 PTR_L a3,(FRAMESZ+PTRSIZE+16)(sp) 84#else 85 move a2,a4 86 move a3,a5 87 move a4,a6 88#endif 89 90 /* Do the system call */ 91 li v0,__NR_clone 92 cfi_endproc 93 syscall 94 95 bnez a3,L(error) 96 beqz v0,L(thread_start) 97 98 /* Successful return from the parent */ 99 cfi_startproc 100 cfi_adjust_cfa_offset (FRAMESZ) 101 SETUP_GP64_STACK_CFI (GPOFF) 102 cfi_remember_state 103 RESTORE_GP64_STACK 104 PTR_ADDU sp, FRAMESZ 105 cfi_adjust_cfa_offset (-FRAMESZ) 106 ret 107 108 /* Something bad happened -- no child created */ 109L(error): 110 cfi_restore_state 111#ifdef __PIC__ 112 PTR_LA t9,__syscall_error 113 RESTORE_GP64_STACK 114 PTR_ADDU sp, FRAMESZ 115 cfi_adjust_cfa_offset (-FRAMESZ) 116 jr t9 117#else 118 RESTORE_GP64_STACK 119 PTR_ADDU sp, FRAMESZ 120 cfi_adjust_cfa_offset (-FRAMESZ) 121 j __syscall_error 122#endif 123 END(__clone) 124 125/* Load up the arguments to the function. Put this block of code in 126 its own function so that we can terminate the stack trace with our 127 debug info. */ 128 129ENTRY(__thread_start) 130L(thread_start): 131 cfi_undefined ($31) 132 /* cp is already loaded. */ 133 SAVE_GP (GPOFF) 134 /* The stackframe has been created on entry of clone(). */ 135 136 /* Restore the arg for user's function. */ 137 PTR_L t9,0(sp) /* Function pointer. */ 138 PTR_L a0,PTRSIZE(sp) /* Argument pointer. */ 139 140 /* Call the user's function. */ 141 jal t9 142 143 move a0,v0 144 li v0,__NR_exit 145 syscall 146 147 END(__thread_start) 148 149libc_hidden_def (__clone) 150weak_alias (__clone, clone) 151