1 /* $NetBSD: __clone.S,v 1.14 2021/06/30 21:20:30 skrll Exp $ */ 2 3 /* 4 * Copyright (c) 2001 Christopher Gilbert 5 * All rights reserved. 6 * 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 3. The name of the company nor the name of the author may be used to 13 * endorse or promote products derived from this software without specific 14 * prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include "SYS.h" 30 #include <sys/errno.h> 31 32 #ifdef WEAK_ALIAS 33 WEAK_ALIAS(clone, __clone) 34 #endif 35 36 /* 37 * int __clone(int (*fn)(void *), void *stack, int flags, void *arg); 38 */ 39 ENTRY(__clone) 40 41 /* test stack and function are not null */ 42 #if defined(__thumb__) && defined(_ARM_ARCH_T2) 43 cbz r0, .Leinval 44 cbz r1, .Leinval 45 #elif !defined(__thumb__) 46 cmp r0, #0x00 47 cmpne r1, #0x00 48 beq .Leinval 49 #else 50 cmp r0, #0x00 51 beq .Leinval 52 cmp r1, #0x00 53 beq .Leinval 54 #endif 55 56 /* place the func and its arg onto the child's stack */ 57 #if !defined(__thumb__) || defined(_ARM_ARCH_T2) 58 stmfd r1!, {r0, r3} 59 #else 60 subs r1, r1, #8 61 stmia r1!, {r0, r3} 62 #endif 63 64 /* syscall expects (flags, stack) */ 65 mov r0, r2 66 67 SYSTRAP(__clone) 68 _INVOKE_CERROR() 69 70 /* 71 * r1 and r0 are the same as from fork: 72 * r1 == 0 in parent process, r1 == 1 in child process. 73 * r0 == pid of child in parent, r0 == pid of parent in child. 74 */ 75 /* if this is the parent then just return the pid */ 76 #if defined(__thumb__) 77 #if defined(_ARM_ARCH_T2) 78 cbz r1, 1f 79 #else 80 cmp r1, #0x00 81 bne 1f 82 #endif 83 RET 84 1: 85 #else 86 cmp r1, #0x00 87 RETc(eq) 88 #endif 89 90 /* 91 * This is the child 92 * load the function and arg off the stack 93 */ 94 pop {r1, r2} 95 96 /* place arg in r0 */ 97 mov r0, r2 98 99 /* call the function */ 100 #ifdef _ARM_ARCH_5T 101 blx r1 102 #else 103 /* setup return address */ 104 mov lr, pc 105 RETr(r1) 106 #endif 107 /* call _exit with the returned value */ 108 bl PLT_SYM(_C_LABEL(_exit)) 109 110 /* NOTREACHED */ 111 112 /* error handler if func or stack is NULL */ 113 .align 0 114 .Leinval: 115 movs r0, #EINVAL 116 #if !defined(__thumb__) || defined(_ARM_ARCH_T2) 117 b CERROR 118 #else 119 .Lcerror: 120 push {r3, lr} 121 bl CERROR 122 pop {r3, pc} 123 #endif 124 END(__clone) 125