]>
Commit | Line | Data |
---|---|---|
04277e02 | 1 | /* Copyright (C) 1996-2019 Free Software Foundation, Inc. |
b35e2407 UD |
2 | This file is part of the GNU C Library. |
3 | Contributed by David Huggins-Daines <dhd@debian.org>, 2000. | |
4 | Based on the Alpha version by Richard Henderson <rth@tamu.edu>, 1996. | |
5 | ||
6 | The GNU C Library is free software; you can redistribute it and/or | |
3214b89b AJ |
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. | |
b35e2407 UD |
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 | |
3214b89b | 14 | Lesser General Public License for more details. |
b35e2407 | 15 | |
3214b89b | 16 | You should have received a copy of the GNU Lesser General Public |
ab84e3ff PE |
17 | License along with the GNU C Library. If not, see |
18 | <http://www.gnu.org/licenses/>. */ | |
b35e2407 UD |
19 | |
20 | /* clone() is even more special than fork() as it mucks with stacks | |
21 | and invokes a function in the right context after its all over. */ | |
22 | ||
23 | #include <asm/unistd.h> | |
24 | #include <sysdep.h> | |
25 | #define _ERRNO_H 1 | |
26 | #include <bits/errno.h> | |
d83f0734 | 27 | #include <tcb-offsets.h> |
b35e2407 | 28 | |
a29e6e84 | 29 | /* Non-thread code calls __clone with the following parameters: |
5556231d JM |
30 | int clone(int (*fn)(void *arg), |
31 | void *child_stack, | |
32 | int flags, | |
0daa0500 | 33 | void *arg) |
5556231d | 34 | |
a29e6e84 | 35 | NPTL Code will call __clone with the following parameters: |
5556231d JM |
36 | int clone(int (*fn)(void *arg), |
37 | void *child_stack, | |
38 | int flags, | |
0daa0500 | 39 | void *arg, |
5556231d JM |
40 | int *parent_tidptr, |
41 | struct user_desc *newtls, | |
0daa0500 | 42 | int *child_pidptr) |
5556231d | 43 | |
a29e6e84 CD |
44 | The code should not mangle the extra input registers. |
45 | Syscall expects: Input to __clone: | |
5556231d | 46 | 4(r25) - function pointer (r26, arg0) |
a29e6e84 CD |
47 | 0(r25) - argument (r23, arg3) |
48 | r26 - clone flags. (r24, arg2) | |
49 | r25+64 - user stack pointer. (r25, arg1) | |
50 | r24 - parent tid pointer. (stack - 52) | |
51 | r23 - struct user_desc newtls pointer. (stack - 56) | |
52 | r22 - child tid pointer. (stack - 60) | |
53 | r20 - clone syscall number (constant) | |
0daa0500 CD |
54 | |
55 | Return: | |
56 | ||
5556231d | 57 | On success the thread ID of the child process is returend in |
0daa0500 | 58 | the callers context. |
5556231d | 59 | On error return -1, and set errno to the value returned by |
0daa0500 | 60 | the syscall. |
a29e6e84 | 61 | */ |
b35e2407 UD |
62 | |
63 | .text | |
64 | ENTRY(__clone) | |
0daa0500 | 65 | /* Prologue */ |
7cad09f9 | 66 | stwm %r4, 64(%sp) |
ce1917d0 JDA |
67 | .cfi_def_cfa_offset -64 |
68 | .cfi_offset 4, 0 | |
0daa0500 | 69 | stw %sp, -4(%sp) |
7cad09f9 | 70 | #ifdef PIC |
0daa0500 | 71 | stw %r19, -32(%sp) |
ce1917d0 | 72 | .cfi_offset 19, 32 |
7cad09f9 | 73 | #endif |
b35e2407 UD |
74 | |
75 | /* Sanity check arguments. */ | |
0daa0500 CD |
76 | comib,=,n 0, %arg0, .LerrorSanity /* no NULL function pointers */ |
77 | comib,=,n 0, %arg1, .LerrorSanity /* no NULL stack pointers */ | |
b35e2407 | 78 | |
7cad09f9 | 79 | /* Save the function pointer, arg, and flags on the new stack. */ |
0daa0500 CD |
80 | stwm %r26, 64(%r25) |
81 | stw %r23, -60(%r25) | |
7cad09f9 | 82 | stw %r24, -56(%r25) |
a29e6e84 | 83 | /* Clone arguments are (int flags, void * child_stack) */ |
0daa0500 | 84 | copy %r24, %r26 /* flags are first */ |
a29e6e84 CD |
85 | /* User stack pointer is in the correct register already */ |
86 | ||
87 | /* Load args from stack... */ | |
0daa0500 CD |
88 | ldw -116(%sp), %r24 /* Load parent_tidptr */ |
89 | ldw -120(%sp), %r23 /* Load newtls */ | |
90 | ldw -124(%sp), %r22 /* Load child_tidptr */ | |
b35e2407 | 91 | |
46bf1d81 UD |
92 | /* Save the PIC register. */ |
93 | #ifdef PIC | |
7cad09f9 | 94 | copy %r19, %r4 /* parent */ |
46bf1d81 UD |
95 | #endif |
96 | ||
b35e2407 | 97 | /* Do the system call */ |
0daa0500 CD |
98 | ble 0x100(%sr2, %r0) |
99 | ldi __NR_clone, %r20 | |
b35e2407 | 100 | |
0daa0500 CD |
101 | ldi -4096, %r1 |
102 | comclr,>>= %r1, %ret0, %r0 /* Note: unsigned compare. */ | |
a29e6e84 | 103 | b,n .LerrorRest |
b35e2407 | 104 | |
7cad09f9 CD |
105 | /* Restore the PIC register. */ |
106 | #ifdef PIC | |
5556231d | 107 | copy %r4, %r19 /* parent */ |
7cad09f9 CD |
108 | #endif |
109 | ||
0daa0500 | 110 | comib,=,n 0, %ret0, .LthreadStart |
b35e2407 | 111 | |
46bf1d81 | 112 | /* Successful return from the parent |
5556231d | 113 | No need to restore the PIC register, |
46bf1d81 UD |
114 | since we return immediately. */ |
115 | ||
0daa0500 | 116 | ldw -84(%sp), %rp |
b35e2407 | 117 | bv %r0(%rp) |
7cad09f9 | 118 | ldwm -64(%sp), %r4 |
46bf1d81 | 119 | |
31e69e34 | 120 | .LerrorRest: |
a29e6e84 | 121 | /* Something bad happened -- no child created */ |
0daa0500 CD |
122 | bl __syscall_error, %rp |
123 | sub %r0, %ret0, %arg0 | |
124 | ldw -84(%sp), %rp | |
125 | /* Return after setting errno, ret0 is set to -1 by __syscall_error. */ | |
126 | bv %r0(%rp) | |
7cad09f9 | 127 | ldwm -64(%sp), %r4 |
0daa0500 CD |
128 | |
129 | .LerrorSanity: | |
130 | /* Sanity checks failed, return -1, and set errno to EINVAL. */ | |
131 | bl __syscall_error, %rp | |
132 | ldi EINVAL, %arg0 | |
0daa0500 | 133 | ldw -84(%sp), %rp |
a29e6e84 | 134 | bv %r0(%rp) |
7cad09f9 | 135 | ldwm -64(%sp), %r4 |
b35e2407 | 136 | |
0daa0500 | 137 | .LthreadStart: |
b35e2407 | 138 | /* Load up the arguments. */ |
0daa0500 CD |
139 | ldw -60(%sp), %arg0 |
140 | ldw -64(%sp), %r22 | |
46bf1d81 | 141 | |
382466e0 | 142 | /* $$dyncall fixes child's PIC register */ |
b35e2407 UD |
143 | |
144 | /* Call the user's function */ | |
7cad09f9 CD |
145 | #ifdef PIC |
146 | copy %r19, %r4 | |
147 | #endif | |
0daa0500 CD |
148 | bl $$dyncall, %r31 |
149 | copy %r31, %rp | |
7cad09f9 CD |
150 | #ifdef PIC |
151 | copy %r4, %r19 | |
152 | #endif | |
48145e1c | 153 | copy %r28, %r26 |
3f823e87 AZ |
154 | ble 0x100(%sr2, %r0) |
155 | ldi __NR_exit, %r20 | |
b35e2407 | 156 | |
3f823e87 | 157 | /* We should not return from exit. |
7cad09f9 | 158 | We do not restore r4, or the stack state. */ |
0daa0500 | 159 | iitlbp %r0, (%sr0, %r0) |
b35e2407 UD |
160 | |
161 | PSEUDO_END(__clone) | |
162 | ||
9ff72da4 | 163 | libc_hidden_def (__clone) |
8796ce21 | 164 | weak_alias (__clone, clone) |