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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
|
/* The clone3 syscall wrapper. Linux/powerpc64 version.
Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <sysdep.h>
#define _ERRNO_H 1
#include <bits/errno.h>
/* The userland implementation is:
int clone3 (struct clone_args *cl_args, size_t size,
int (*func)(void *arg), void *arg);
the kernel entry is:
int clone3 (struct clone_args *cl_args, size_t size);
The parameters are passed in registers from userland:
r3: cl_args
r4: size
r5: func
r6: arg */
#ifdef USE_PPC_SCV
/* This is equivalent to DO_CALL_SCV, but we cannot use the macro here
because it uses CFI directives and we just called cfi_endproc. */
# define DO_CLONE3_SVC_CALL(jumpfalse) \
CHECK_SCV_SUPPORT r28 jumpfalse; \
mflr r9; \
std r9, FRAME_LR_SAVE(r1); \
.machine "push"; \
.machine "power9"; \
scv 0; \
.machine "pop"; \
ld r9, FRAME_LR_SAVE(r1); \
mtlr r9; \
/* With scv an, an error is a value -4095 <= x < 0. */ \
cmpdi cr1, r3, 0; \
b 1f;
#else
# define DO_CLONE3_SVC_CALL(fail_branch)
#endif
.text
ENTRY(__clone3)
CALL_MCOUNT 4
/* Sanity checks args. */
cmpdi cr0, r3, 0
cmpdi cr1, r5, 0
cror cr0*4+eq, cr1*4+eq, cr0*4+eq
beq cr0,L(badargs)
/* Save some regs in the "red zone". */
#ifdef USE_PPC_SCV
std r28, -24(r1)
cfi_offset (r28, -24)
#endif
std r29, -16(r1)
std r30, -8(r1)
cfi_offset (r29, -16)
cfi_offset (r30, -8)
/* Save func and arg across syscall. */
mr r30, r5 /* Function in r30. */
mr r29, r6 /* Argument in r29. */
/* End FDE now, because in the child the unwind info will be
wrong. */
cfi_endproc
/* Setup a minimum stack frame for child. It needs to first calculate
the effective stack address, write the start empty backchain pointer,
and update the frame size in the input cl_args. */
ld r7, 40(r3) /* Load stack value. */
ld r8, 48(r3) /* Load stack_size value. */
li r10, 0
add r7, r7, r8 /* Calculate effective stack address. */
std r10, -FRAME_MIN_SIZE_PARM(r7)
addi r8, r8, -FRAME_MIN_SIZE_PARM
std r8, 48(r3)
/* Do the system call, the kernel expects:
r0: system call numer
r3: cl_args
r4: size */
li r0, SYS_ify(clone3)
DO_CLONE3_SVC_CALL (0f)
0: DO_CALL_SC
/* With sc, error is indicated by cr0.SO. */
cmpdi cr1, r3, 0
crandc cr1*4+eq, cr1*4+eq, cr0*4+so
1: bne- cr1,L(parent)
/* Child, load the function and arguments. */
std r2, FRAME_TOC_SAVE(r1)
PPC64_LOAD_FUNCPTR r30
mr r3, r29
bctrl
ld r2, FRAME_TOC_SAVE(r1)
li r0, SYS_ify(exit)
DO_CLONE3_SVC_CALL (2f)
2: DO_CALL_SC
/* We won't ever get here but provide a nop so that the linker
will insert a toc adjusting stub if necessary. */
nop
L(badargs):
cfi_startproc
li r3, EINVAL
TAIL_CALL_SYSCALL_ERROR
L(parent):
/* Check if scv is available. */
cmpdi cr1, r28, 0
/* Parent. Restore registers & return. */
#ifdef USE_PPC_SCV
cfi_offset (r28, -24)
ld r28, -24(r1)
cfi_restore (r28)
#endif
cfi_offset (r29,-16)
cfi_offset (r30,-8)
ld r29, -16(r1)
ld r30, -8(r1)
cfi_restore (r29)
cfi_restore (r30)
#ifdef USE_PPC_SCV
beq cr1, 0f
RET_SCV
b 1f
#endif
0: RET_SC
1: TAIL_CALL_SYSCALL_ERROR
PSEUDO_END (__clone3)
libc_hidden_def (__clone3)
weak_alias (__clone3, clone3)
|