]> git.ipfire.org Git - thirdparty/glibc.git/blob - sysdeps/unix/sysv/linux/powerpc/powerpc32/clone.S
(CFLAGS-tst-align.c): Add -mpreferred-stack-boundary=4.
[thirdparty/glibc.git] / sysdeps / unix / sysv / linux / powerpc / powerpc32 / clone.S
1 /* Wrapper around clone system call.
2 Copyright (C) 1997,98,99,2000,02,2004 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, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 02111-1307 USA. */
19
20 #include <sysdep.h>
21 #define _ERRNO_H 1
22 #include <bits/errno.h>
23 #include <kernel-features.h>
24 #include <bp-sym.h>
25 #include <bp-asm.h>
26
27 #define CLONE_VM 0x00000100
28 #define CLONE_THREAD 0x00010000
29
30
31 /* This is the only really unusual system call in PPC linux, but not
32 because of any weirdness in the system call itself; because of
33 all the freaky stuff we have to do to make the call useful. */
34
35 /* int [r3] clone(int (*fn)(void *arg) [r3], void *child_stack [r4],
36 int flags [r5], void *arg [r6], void *parent_tid [r7],
37 void *tls [r8], void *child_tid [r9]); */
38
39 ENTRY (BP_SYM (__clone))
40 /* GKM FIXME: add bounds checks, where sensible. */
41 DISCARD_BOUNDS (r4)
42 DISCARD_BOUNDS (r6)
43
44 /* Check for child_stack == NULL || fn == NULL. */
45 cmpwi cr0,r4,0
46 cmpwi cr1,r3,0
47 cror cr0*4+eq,cr1*4+eq,cr0*4+eq
48 beq- cr0,L(badargs)
49
50 /* Set up stack frame for parent. */
51 stwu r1,-32(r1)
52 #ifdef RESET_PID
53 stmw r28,16(r1)
54 #else
55 # ifndef __ASSUME_FIXED_CLONE_SYSCALL
56 stmw r29,16(r1)
57 # else
58 stmw r30,16(r1)
59 # endif
60 #endif
61
62 /* Set up stack frame for child. */
63 clrrwi r4,r4,4
64 li r0,0
65 stwu r0,-16(r4)
66
67 /* Save fn, args, stack across syscall. */
68 mr r30,r3 /* Function in r30. */
69 #ifndef __ASSUME_FIXED_CLONE_SYSCALL
70 mr r29,r4 /* Stack pointer in r29. */
71 #endif
72 #ifdef RESET_PID
73 mr r28,r5
74 #endif
75 mr r31,r6 /* Argument in r31. */
76
77 /* 'flags' argument is first parameter to clone syscall. (The other
78 argument is the stack pointer, already in r4.) */
79 mr r3,r5
80
81 /* Move the parent_tid, child_tid and tls arguments. */
82 mr r5,r7
83 mr r6,r8
84 mr r7,r9
85
86 /* Do the call. */
87 DO_CALL(SYS_ify(clone))
88
89 /* Check for child process. */
90 cmpwi cr1,r3,0
91 crandc cr1*4+eq,cr1*4+eq,cr0*4+so
92 bne- cr1,L(parent) /* The '-' is to minimise the race. */
93
94 #ifndef __ASSUME_FIXED_CLONE_SYSCALL
95 /* On at least mklinux DR3a5, clone() doesn't actually change
96 the stack pointer. I'm pretty sure this is a bug, because
97 it adds a race condition if a signal is sent to a thread
98 just after it is created (in the previous three instructions). */
99 mr r1,r29
100 #endif
101
102 #ifdef RESET_PID
103 andis. r0,r28,CLONE_THREAD>>16
104 bne+ r0,L(oldpid)
105 andi. r0,r28,CLONE_VM
106 li r3,-1
107 bne- r0,L(nomoregetpid)
108 DO_CALL(SYS_ify(getpid))
109 L(nomoregetpid):
110 stw r3,TID(r2)
111 stw r3,PID(r2)
112 L(oldpid):
113 #endif
114
115 /* Call procedure. */
116 mtctr r30
117 mr r3,r31
118 bctrl
119 /* Call _exit with result from procedure. */
120 b HIDDEN_JUMPTARGET(_exit)
121
122 L(parent):
123 /* Parent. Restore registers & return. */
124 #ifdef RESET_PID
125 lmw r28,16(r1)
126 #else
127 # ifndef __ASSUME_FIXED_CLONE_SYSCALL
128 lmw r29,16(r1)
129 # else
130 lmw r30,16(r1)
131 # endif
132 #endif
133 addi r1,r1,32
134 bnslr+
135 b JUMPTARGET(__syscall_error)
136
137 L(badargs):
138 li r3,EINVAL
139 b JUMPTARGET(__syscall_error)
140 END (BP_SYM (__clone))
141
142 weak_alias (BP_SYM (__clone), BP_SYM (clone))