1/* The clone3 syscall wrapper. Linux/powerpc64 version.
2 Copyright (C) 2023-2024 Free Software Foundation, Inc.
3
4 This file is part of the GNU C Library.
5
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
10
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, see
18 <https://www.gnu.org/licenses/>. */
19
20#include <sysdep.h>
21#define _ERRNO_H 1
22#include <bits/errno.h>
23
24/* The userland implementation is:
25 int clone3 (struct clone_args *cl_args, size_t size,
26 int (*func)(void *arg), void *arg);
27
28 the kernel entry is:
29 int clone3 (struct clone_args *cl_args, size_t size);
30
31 The parameters are passed in registers from userland:
32 r3: cl_args
33 r4: size
34 r5: func
35 r6: arg */
36
37#ifdef USE_PPC_SCV
38/* This is equivalent to DO_CALL_SCV, but we cannot use the macro here
39 because it uses CFI directives and we just called cfi_endproc. */
40# define DO_CLONE3_SVC_CALL(jumpfalse) \
41 CHECK_SCV_SUPPORT r28 jumpfalse; \
42 mflr r9; \
43 std r9, FRAME_LR_SAVE(r1); \
44 .machine "push"; \
45 .machine "power9"; \
46 scv 0; \
47 .machine "pop"; \
48 ld r9, FRAME_LR_SAVE(r1); \
49 mtlr r9; \
50 /* With scv an, an error is a value -4095 <= x < 0. */ \
51 cmpdi cr1, r3, 0; \
52 b 1f;
53#else
54# define DO_CLONE3_SVC_CALL(fail_branch)
55#endif
56
57 .text
58ENTRY(__clone3)
59 CALL_MCOUNT 4
60
61 /* Sanity checks args. */
62 cmpdi cr0, r3, 0
63 cmpdi cr1, r5, 0
64 cror cr0*4+eq, cr1*4+eq, cr0*4+eq
65 beq cr0,L(badargs)
66
67 /* Save some regs in the "red zone". */
68#ifdef USE_PPC_SCV
69 std r28, -24(r1)
70 cfi_offset (r28, -24)
71#endif
72 std r29, -16(r1)
73 std r30, -8(r1)
74 cfi_offset (r29, -16)
75 cfi_offset (r30, -8)
76
77 /* Save func and arg across syscall. */
78 mr r30, r5 /* Function in r30. */
79 mr r29, r6 /* Argument in r29. */
80
81 /* End FDE now, because in the child the unwind info will be
82 wrong. */
83 cfi_endproc
84
85 /* Setup a minimum stack frame for child. It needs to first calculate
86 the effective stack address, write the start empty backchain pointer,
87 and update the frame size in the input cl_args. */
88 ld r7, 40(r3) /* Load stack value. */
89 ld r8, 48(r3) /* Load stack_size value. */
90 li r10, 0
91 add r7, r7, r8 /* Calculate effective stack address. */
92 std r10, -FRAME_MIN_SIZE_PARM(r7)
93 addi r8, r8, -FRAME_MIN_SIZE_PARM
94 std r8, 48(r3)
95
96 /* Do the system call, the kernel expects:
97 r0: system call numer
98 r3: cl_args
99 r4: size */
100 li r0, SYS_ify(clone3)
101 DO_CLONE3_SVC_CALL (0f)
1020: DO_CALL_SC
103
104 /* With sc, error is indicated by cr0.SO. */
105 cmpdi cr1, r3, 0
106 crandc cr1*4+eq, cr1*4+eq, cr0*4+so
107
1081: bne- cr1,L(parent)
109
110 /* Child, load the function and arguments. */
111 std r2, FRAME_TOC_SAVE(r1)
112 PPC64_LOAD_FUNCPTR r30
113 mr r3, r29
114 bctrl
115 ld r2, FRAME_TOC_SAVE(r1)
116
117 li r0, SYS_ify(exit)
118 DO_CLONE3_SVC_CALL (2f)
1192: DO_CALL_SC
120 /* We won't ever get here but provide a nop so that the linker
121 will insert a toc adjusting stub if necessary. */
122 nop
123
124L(badargs):
125 cfi_startproc
126 li r3, EINVAL
127 TAIL_CALL_SYSCALL_ERROR
128
129L(parent):
130 /* Check if scv is available. */
131 cmpdi cr1, r28, 0
132
133 /* Parent. Restore registers & return. */
134#ifdef USE_PPC_SCV
135 cfi_offset (r28, -24)
136 ld r28, -24(r1)
137 cfi_restore (r28)
138#endif
139 cfi_offset (r29,-16)
140 cfi_offset (r30,-8)
141 ld r29, -16(r1)
142 ld r30, -8(r1)
143 cfi_restore (r29)
144 cfi_restore (r30)
145
146#ifdef USE_PPC_SCV
147 beq cr1, 0f
148 RET_SCV
149 b 1f
150#endif
1510: RET_SC
1521: TAIL_CALL_SYSCALL_ERROR
153
154PSEUDO_END (__clone3)
155
156libc_hidden_def (__clone3)
157weak_alias (__clone3, clone3)
158

source code of glibc/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone3.S