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 33WEAK_ALIAS(clone, __clone) 34#endif 35 36/* 37 * int __clone(int (*fn)(void *), void *stack, int flags, void *arg); 38 */ 39ENTRY(__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 841: 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 124END(__clone) 125