1*45433ea2Sskrll/* $NetBSD: __clone.S,v 1.14 2021/06/30 21:20:30 skrll Exp $ */ 230b6c70fSchris 330b6c70fSchris/* 430b6c70fSchris * Copyright (c) 2001 Christopher Gilbert 530b6c70fSchris * All rights reserved. 630b6c70fSchris * 730b6c70fSchris * 1. Redistributions of source code must retain the above copyright 830b6c70fSchris * notice, this list of conditions and the following disclaimer. 930b6c70fSchris * 2. Redistributions in binary form must reproduce the above copyright 1030b6c70fSchris * notice, this list of conditions and the following disclaimer in the 1130b6c70fSchris * documentation and/or other materials provided with the distribution. 1230b6c70fSchris * 3. The name of the company nor the name of the author may be used to 1330b6c70fSchris * endorse or promote products derived from this software without specific 1430b6c70fSchris * prior written permission. 1530b6c70fSchris * 1630b6c70fSchris * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 1730b6c70fSchris * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 1830b6c70fSchris * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1930b6c70fSchris * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 2030b6c70fSchris * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 2130b6c70fSchris * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 2230b6c70fSchris * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2330b6c70fSchris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2430b6c70fSchris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2530b6c70fSchris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2630b6c70fSchris * SUCH DAMAGE. 2730b6c70fSchris */ 2830b6c70fSchris 2930b6c70fSchris#include "SYS.h" 302a674d4fSmatt#include <sys/errno.h> 3130b6c70fSchris 3230b6c70fSchris#ifdef WEAK_ALIAS 3330b6c70fSchrisWEAK_ALIAS(clone, __clone) 3430b6c70fSchris#endif 3530b6c70fSchris 3630b6c70fSchris/* 3730b6c70fSchris * int __clone(int (*fn)(void *), void *stack, int flags, void *arg); 3830b6c70fSchris */ 3930b6c70fSchrisENTRY(__clone) 4030b6c70fSchris 4130b6c70fSchris /* test stack and function are not null */ 422a674d4fSmatt#if defined(__thumb__) && defined(_ARM_ARCH_T2) 432a674d4fSmatt cbz r0, .Leinval 442a674d4fSmatt cbz r1, .Leinval 452a674d4fSmatt#elif !defined(__thumb__) 462a674d4fSmatt cmp r0, #0x00 472a674d4fSmatt cmpne r1, #0x00 481b907e18Sthorpej beq .Leinval 492a674d4fSmatt#else 502a674d4fSmatt cmp r0, #0x00 512a674d4fSmatt beq .Leinval 522a674d4fSmatt cmp r1, #0x00 532a674d4fSmatt beq .Leinval 542a674d4fSmatt#endif 5530b6c70fSchris 56a640fe8cSsnj /* place the func and its arg onto the child's stack */ 572a674d4fSmatt#if !defined(__thumb__) || defined(_ARM_ARCH_T2) 5830b6c70fSchris stmfd r1!, {r0, r3} 592a674d4fSmatt#else 602a674d4fSmatt subs r1, r1, #8 612a674d4fSmatt stmia r1!, {r0, r3} 622a674d4fSmatt#endif 6330b6c70fSchris 6430b6c70fSchris /* syscall expects (flags, stack) */ 6530b6c70fSchris mov r0, r2 6630b6c70fSchris 6730b6c70fSchris SYSTRAP(__clone) 682a674d4fSmatt _INVOKE_CERROR() 6930b6c70fSchris 7030b6c70fSchris /* 7130b6c70fSchris * r1 and r0 are the same as from fork: 7230b6c70fSchris * r1 == 0 in parent process, r1 == 1 in child process. 7330b6c70fSchris * r0 == pid of child in parent, r0 == pid of parent in child. 7430b6c70fSchris */ 7530b6c70fSchris /* if this is the parent then just return the pid */ 762a674d4fSmatt#if defined(__thumb__) 772a674d4fSmatt#if defined(_ARM_ARCH_T2) 782a674d4fSmatt cbz r1, 1f 792a674d4fSmatt#else 802a674d4fSmatt cmp r1, #0x00 812a674d4fSmatt bne 1f 822a674d4fSmatt#endif 832a674d4fSmatt RET 842a674d4fSmatt1: 852a674d4fSmatt#else 862a674d4fSmatt cmp r1, #0x00 87145b31afSrearnsha RETc(eq) 882a674d4fSmatt#endif 892a674d4fSmatt 9030b6c70fSchris /* 9130b6c70fSchris * This is the child 9230b6c70fSchris * load the function and arg off the stack 9330b6c70fSchris */ 942a674d4fSmatt pop {r1, r2} 9530b6c70fSchris 9630b6c70fSchris /* place arg in r0 */ 9730b6c70fSchris mov r0, r2 9830b6c70fSchris 9930b6c70fSchris /* call the function */ 1002a674d4fSmatt#ifdef _ARM_ARCH_5T 1012a674d4fSmatt blx r1 102145b31afSrearnsha#else 1032a674d4fSmatt /* setup return address */ 1042a674d4fSmatt mov lr, pc 1052a674d4fSmatt RETr(r1) 106145b31afSrearnsha#endif 10730b6c70fSchris /* call _exit with the returned value */ 108d0dcd65cSjoerg bl PLT_SYM(_C_LABEL(_exit)) 10930b6c70fSchris 11030b6c70fSchris /* NOTREACHED */ 11130b6c70fSchris 11230b6c70fSchris /* error handler if func or stack is NULL */ 1132a674d4fSmatt .align 0 1141b907e18Sthorpej.Leinval: 1152a674d4fSmatt movs r0, #EINVAL 1162a674d4fSmatt#if !defined(__thumb__) || defined(_ARM_ARCH_T2) 1173eafa987Smatt b CERROR 1182a674d4fSmatt#else 1192a674d4fSmatt.Lcerror: 120*45433ea2Sskrll push {r3, lr} 1212a674d4fSmatt bl CERROR 122*45433ea2Sskrll pop {r3, pc} 1232a674d4fSmatt#endif 1242a674d4fSmattEND(__clone) 125