2 * Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com)
4 * Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball.
8 #include <sys/syscall.h>
11 ; Per man, libc clone( ) is as follows
13 ; int clone(int (*fn)(void *), void *child_stack,
14 ; int flags, void *arg, ...
15 ; /* pid_t *ptid, struct user_desc *tls, pid_t *ctid */);
17 ; NOTE: I'm assuming that the last 3 args are NOT var-args and in case all
18 ; 3 are not relevant, caller will nevertheless pass those as NULL.
19 ; Current (Jul 2012) upstream powerpc/clone.S assumes similarly.
20 ; Our LTP (from 2007) doesn't seem to have tests to prove otherwise
22 ; clone syscall in kernel
24 ; int sys_clone(unsigned long clone_flags, unsigned long newsp,
25 ; int __user *parent_tidptr, void *tls,
26 ; int __user *child_tidptr)
30 cmp r0, 0 ; @fn can't be NULL
31 cmp.ne r1, 0 ; @child_stack can't be NULL
34 ; @fn and @args needed after the syscall for child
35 ; However r3 containing @arg will be clobbered BEFORE syscall
36 ; r0 containg @fn will be clobbered AFTER syscall (with ret val)
40 ; adjust libc args for syscall
41 mov r0, r2 ; libc @flags is 1st syscall arg
42 mov r2, r4 ; libc @ptid
43 mov r3, r5 ; libc @tls
44 mov r4, r6 ; libc @ctid
48 cmp r0, 0 ; return code : 0 new process, !0 parent
49 blt .L__sys_err2 ; < 0 (signed) error
50 jnz [blink] ; Parent returns
52 ; child jumps off to @fn with @arg as argument
56 ; falls thru to _exit() with result from @fn (already in r0)
57 b HIDDEN_JUMPTARGET(_exit)
62 ; (1) No need to make -ve kernel error code as positive errno
63 ; __syscall_error expects the -ve error code returned by kernel
64 ; (2) r0 still had orig -ve kernel error code
65 ; (3) Tail call to __syscall_error so we dont have to come back
66 ; here hence instead of jmp-n-link (reg push/pop) we do jmp
67 ; (4) No need to route __syscall_error via PLT, B is inherently
68 ; position independent
71 libc_hidden_def(clone)