hppa: Fix clone exit syscall argument passing (BZ#21512)
[glibc.git] / sysdeps / unix / sysv / linux / hppa / clone.S
blobe0daf174bb15c2b97c8c4a5e4392efea5140cadb
1 /* Copyright (C) 1996-2017 Free Software Foundation, Inc.
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.
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.
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.
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    <http://www.gnu.org/licenses/>.  */
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.  */
23 #include <asm/unistd.h>
24 #include <sysdep.h>
25 #define _ERRNO_H        1
26 #include <bits/errno.h>
27 #include <tcb-offsets.h>
29 /* Non-thread code calls __clone with the following parameters:
30    int clone(int (*fn)(void *arg),
31              void *child_stack,
32              int flags,
33              void *arg)
35    NPTL Code will call __clone with the following parameters:
36    int clone(int (*fn)(void *arg),
37              void *child_stack,
38              int flags,
39              void *arg,
40              int *parent_tidptr,
41              struct user_desc *newtls,
42              int *child_pidptr)
44    The code should not mangle the extra input registers.
45    Syscall expects:                             Input to __clone:
46         4(r25) - function pointer               (r26, arg0)
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)
55    Return:
57         On success the thread ID of the child process is returend in
58         the callers context.
59         On error return -1, and set errno to the value returned by
60         the syscall.
61  */
63         .text
64 ENTRY(__clone)
65         /* Prologue */
66         stwm    %r4, 64(%sp)
67         .cfi_def_cfa_offset -64
68         .cfi_offset 4, 0
69         stw     %sp, -4(%sp)
70 #ifdef PIC
71         stw     %r19, -32(%sp)
72         .cfi_offset 19, 32
73 #endif
75         /* Sanity check arguments.  */
76         comib,=,n  0, %arg0, .LerrorSanity        /* no NULL function pointers */
77         comib,=,n  0, %arg1, .LerrorSanity        /* no NULL stack pointers */
79         /* Save the function pointer, arg, and flags on the new stack.  */
80         stwm    %r26, 64(%r25)
81         stw     %r23, -60(%r25)
82         stw     %r24, -56(%r25)
83         /* Clone arguments are (int flags, void * child_stack) */
84         copy    %r24, %r26              /* flags are first */
85         /* User stack pointer is in the correct register already */
87         /* Load args from stack... */
88         ldw     -116(%sp), %r24         /* Load parent_tidptr */
89         ldw     -120(%sp), %r23         /* Load newtls */
90         ldw     -124(%sp), %r22         /* Load child_tidptr */
92         /* Save the PIC register. */
93 #ifdef PIC
94         copy    %r19, %r4               /* parent */
95 #endif
97         /* Do the system call */
98         ble     0x100(%sr2, %r0)
99         ldi     __NR_clone, %r20
101         ldi     -4096, %r1
102         comclr,>>= %r1, %ret0, %r0      /* Note: unsigned compare. */
103         b,n     .LerrorRest
105         /* Restore the PIC register.  */
106 #ifdef PIC
107         copy    %r4, %r19               /* parent */
108 #endif
110         comib,=,n 0, %ret0, .LthreadStart
112         /* Successful return from the parent
113            No need to restore the PIC register,
114            since we return immediately. */
116         ldw     -84(%sp), %rp
117         bv      %r0(%rp)
118         ldwm    -64(%sp), %r4
120 .LerrorRest:
121         /* Something bad happened -- no child created */
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)
127         ldwm    -64(%sp), %r4
129 .LerrorSanity:
130         /* Sanity checks failed, return -1, and set errno to EINVAL. */
131         bl      __syscall_error, %rp
132         ldi     EINVAL, %arg0
133         ldw     -84(%sp), %rp
134         bv      %r0(%rp)
135         ldwm    -64(%sp), %r4
137 .LthreadStart:
138         /* Load up the arguments.  */
139         ldw     -60(%sp), %arg0
140         ldw     -64(%sp), %r22
142         /* $$dyncall fixes child's PIC register */
144         /* Call the user's function */
145 #ifdef PIC
146         copy    %r19, %r4
147 #endif
148         bl      $$dyncall, %r31
149         copy    %r31, %rp
150 #ifdef PIC
151         copy    %r4, %r19
152 #endif
153         copy    %r28, %r26
154         ble     0x100(%sr2, %r0)
155         ldi     __NR_exit, %r20
157         /* We should not return from exit.
158            We do not restore r4, or the stack state.  */
159         iitlbp  %r0, (%sr0, %r0)
161 PSEUDO_END(__clone)
163 libc_hidden_def (__clone)
164 weak_alias (__clone, clone)