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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
|
/*
* This file is subject to the terms and conditions of the LGPL V2.1
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 2018 Kalray Inc.
*/
#include <sysdep.h>
#define _ERRNO_H 1
#include <bits/errno.h>
/**
* Clone system call implementation for kvx
* int clone (int (*fn)(void *arg), void *child_stack, int flags, void *arg,
* pid_t *ptid, struct user_desc *tls, pid_t *ctid);
* $r0 = fn
* $r1 = child_stack
* $r2 = flags
* $r3 = args
* $r4 = ptid
* $r5 = tls
* $r6 = ctid
*
* The kernel expects to find its arguments in the following order:
* sys_clone(unsigned long clone_flags, unsigned long newsp,
* int __user * parent_tidptr,
* int __user * child_tidptr,
* unsigned long tls)
*
* So we have to make a few modifications before calling
*
*/
ENTRY (__clone)
/* Check fn and stack to be non-null */
cb.deqz $r1? L(clone_einval_error)
/* Align child stack first */
andd $r1 = $r1, -32
;;
cb.deqz $r0? L(clone_einval_error)
/* Prepare space for child arguments on stack and stay aligned */
addd $r1 = $r1, -32
;;
/* Save fn ($r0) on child stack */
sd 0[$r1] = $r0
/* Set clone_flags */
copyd $r0 = $r2
;;
/* Save args ($r3) on child stack */
sd 8[$r1] = $r3
/* Set parent_tidptr */
copyd $r2 = $r4
/* Set child_tidptr */
copyd $r3 = $r6
/* Set tls */
copyd $r4 = $r5
;;
scall SYS_ify(clone)
;;
/* If 0, then we are the child */
cb.deqz $r0? L(child_start)
;;
/* Else we are the parent, and we need to check for errors */
cb.dltz $r0? L(clone_error)
;;
/* No error ! Yeepa ! */
ret
;;
L(child_start):
/* get fn from stack */
ld $r1 = 0[$sp]
;;
/* Get args from stack */
ld $r0 = 8[$sp]
addd $sp = $sp, 32
;;
icall $r1
;;
scall SYS_ify(exit)
;;
/* We should never ever get here ! */
errop
;;
L(clone_einval_error):
make $r0 = -EINVAL
;;
L(clone_error):
/* goto __syscall_error but do not use call or $ra will be
* destroyed */
goto __syscall_error
;;
/* We will not return here but to clone caller
* (stored in $ra) */
errop
;;
END(__clone)
libc_hidden_def (__clone)
weak_alias (__clone,clone)
|