1/* $NetBSD: __clone.S,v 1.9 2013/11/30 20:20:42 joerg 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#if !defined(__thumb__) || defined(_ARM_ARCH_T2) 69 _INVOKE_CERROR() 70#else 71 bcs .Lcerror 72#endif 73 74 /* 75 * r1 and r0 are the same as from fork: 76 * r1 == 0 in parent process, r1 == 1 in child process. 77 * r0 == pid of child in parent, r0 == pid of parent in child. 78 */ 79 /* if this is the parent then just return the pid */ 80#if defined(__thumb__) 81#if defined(_ARM_ARCH_T2) 82 cbz r1, 1f 83#else 84 cmp r1, #0x00 85 bne 1f 86#endif 87 RET 881: 89#else 90 cmp r1, #0x00 91 RETc(eq) 92#endif 93 94 /* 95 * This is the child 96 * load the function and arg off the stack 97 */ 98 pop {r1, r2} 99 100 /* place arg in r0 */ 101 mov r0, r2 102 103 /* call the function */ 104#ifdef _ARM_ARCH_5T 105 blx r1 106#else 107 /* setup return address */ 108 mov lr, pc 109 RETr(r1) 110#endif 111 /* call _exit with the returned value */ 112 bl PLT_SYM(_C_LABEL(_exit)) 113 114 /* NOTREACHED */ 115 116 /* error handler if func or stack is NULL */ 117 .align 0 118.Leinval: 119 movs r0, #EINVAL 120#if !defined(__thumb__) || defined(_ARM_ARCH_T2) 121 b CERROR 122#else 123.Lcerror: 124 push {lr} 125 bl CERROR 126 pop {pc} 127#endif 128END(__clone) 129