1/* Wrapper around clone system call.  PowerPC64 version.
2   Copyright (C) 1997-2021 Free Software Foundation, Inc.
3   This file is part of the GNU C Library.
4
5   The GNU C Library is free software; you can redistribute it and/or
6   modify it under the terms of the GNU Lesser General Public
7   License as published by the Free Software Foundation; either
8   version 2.1 of the License, or (at your option) any later version.
9
10   The GNU C Library is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13   Lesser General Public License for more details.
14
15   You should have received a copy of the GNU Lesser General Public
16   License along with the GNU C Library; if not, see
17   <https://www.gnu.org/licenses/>.  */
18
19#include <sysdep.h>
20#define _ERRNO_H	1
21#include <bits/errno.h>
22
23/* This is the only really unusual system call in PPC linux, but not
24   because of any weirdness in the system call itself; because of
25   all the freaky stuff we have to do to make the call useful.  */
26
27/* int [r3] clone(int (*fn)(void *arg) [r3], void *child_stack [r4],
28                  int flags [r5], void *arg [r6], void *parent_tid [r7],
29                  void *tls [r8], void *child_tid [r9]); */
30
31ENTRY (__clone)
32	CALL_MCOUNT 7
33
34	/* Check for child_stack == NULL || fn == NULL.  */
35	cmpdi	cr0,r4,0
36	cmpdi	cr1,r3,0
37	cror	cr0*4+eq,cr1*4+eq,cr0*4+eq
38	beq-	cr0,L(badargs)
39
40	/* Save some regs in the "red zone".  */
41#ifdef USE_PPC_SCV
42	std	r28,-32(r1)
43	cfi_offset(r28,-32)
44#endif
45	std	r29,-24(r1)
46	std	r30,-16(r1)
47	std	r31,-8(r1)
48	cfi_offset(r29,-24)
49	cfi_offset(r30,-16)
50	cfi_offset(r31,-8)
51
52	/* Set up stack frame for child.  */
53	clrrdi	r4,r4,4
54	li	r0,0
55	stdu	r0,-FRAME_MIN_SIZE_PARM(r4)
56
57	/* Save fn, args, stack across syscall.  */
58	mr	r30,r3			/* Function in r30.  */
59	mr	r29,r5			/* Flags in r29.  */
60	mr	r31,r6			/* Argument in r31.  */
61
62	/* 'flags' argument is first parameter to clone syscall.
63	   Second is the stack pointer, already in r4.  */
64	mr	r3,r5
65	/* Move the parent_tid, child_tid and tls arguments. */
66	mr	r5,r7
67	mr	r6,r8
68	mr	r7,r9
69
70	/* End FDE now, because in the child the unwind info will be
71	   wrong.  */
72	cfi_endproc
73
74	/* Do the call.  */
75	li 	r0,SYS_ify(clone)
76#ifdef USE_PPC_SCV
77	CHECK_SCV_SUPPORT r28 0f
78	/* This is equivalent to DO_CALL_SCV, but we cannot use the macro here
79	because it uses CFI directives and we just called cfi_endproc.  */
80	mflr 	r9
81	std 	r9,FRAME_LR_SAVE(r1)
82	.machine "push"
83	.machine "power9"
84	scv 	0
85	.machine "pop"
86	ld 	r9,FRAME_LR_SAVE(r1)
87	mtlr 	r9
88
89	/* Check for child process.  */
90	/* When using scv, error is indicated by negative r3.  */
91	cmpdi	cr1,r3,0
92	b 1f
93#endif /* USE_PPC_SCV */
940:      DO_CALL_SC
95
96	/* Check for child process.  */
97	/* With sc, error is indicated by cr0.SO.  */
98	cmpdi	cr1,r3,0
99	crandc	cr1*4+eq,cr1*4+eq,cr0*4+so
1001:
101	bne-	cr1,L(parent)		/* The '-' is to minimise the race.  */
102
103	std	r2,FRAME_TOC_SAVE(r1)
104	/* Call procedure.  */
105	PPC64_LOAD_FUNCPTR r30
106	mr	r3,r31
107	bctrl
108	ld	r2,FRAME_TOC_SAVE(r1)
109
110	li	r0,(SYS_ify(exit))
111	DO_CALL_SC
112	/* We won't ever get here but provide a nop so that the linker
113	   will insert a toc adjusting stub if necessary.  */
114	nop
115
116L(badargs):
117	cfi_startproc
118	li	r3,EINVAL
119	TAIL_CALL_SYSCALL_ERROR
120
121L(parent):
122	/* Check if scv is available. */
123	cmpdi cr1,r28,0
124
125	/* Parent.  Restore registers & return.  */
126#ifdef USE_PPC_SCV
127	cfi_offset(r28,-32)
128	ld	r28,-32(r1)
129	cfi_restore(r28)
130#endif
131	cfi_offset(r29,-24)
132	cfi_offset(r30,-16)
133	cfi_offset(r31,-8)
134	ld	r29,-24(r1)
135	ld	r30,-16(r1)
136	ld	r31,-8(r1)
137	cfi_restore(r29)
138	cfi_restore(r30)
139	cfi_restore(r31)
140
141#ifdef USE_PPC_SCV
142	beq cr1,0f
143	RET_SCV
144	b 1f
145#endif
1460:	RET_SC
1471:	TAIL_CALL_SYSCALL_ERROR
148
149
150END (__clone)
151
152libc_hidden_def (__clone)
153weak_alias (__clone, clone)
154