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