1#include <sysdep.h>
2
3#define CLONE_VM      0x00000100
4#define CLONE_THREAD  0x00010000
5
6.text
7ENTRY(__or1k_clone)
8
9	/* To handle GCC varargs we need to use our __clone wrapper to pop
10	   everything from the stack for us.
11	   Now everything is placed in the registers which saves us a lot
12	   of trouble.
13
14	   The userland implementation is:
15		  int clone (int (*fn)(void *), void *child_stack,
16			    int flags, void *arg, pid_t *ptid,
17			    struct user_desc *tls, pid_t *ctid);
18
19	     The kernel entry is:
20		  int clone (long flags, void *child_stack, int *parent_tid,
21			  int *child_tid, struct void *tls)
22	     NB: tls isn't really an argument, it is read from r7 directly.
23	*/
24
25	/* Put 'fn', 'arg' and 'flags' on child stack */
26	l.addi r4, r4, -12
27	l.sw  8(r4), r3
28	l.sw  4(r4), r6
29	l.sw  0(r4), r5
30
31	l.ori r3, r5, 0
32	/* child_stack is already in r4 */
33	l.ori r5, r7, 0
34	l.lwz r6, 0(r1)
35	l.ori r7, r8, 0
36
37	DO_CALL (clone)
38
39	l.sfgeui r11, 0xf001
40	l.bf L(error)
41	 l.nop
42
43	/* If we are not the child, return the pid */
44	l.sfeqi r11, 0
45	l.bf L(child)
46	 l.nop
47
48	l.jr r9
49	 l.nop
50
51L(child):
52	/* Load flags */
53	l.lwz r3, 0(r1)
54
55	/* Update PID, but only if we do not share the same PID
56	   as our parent */
57	l.srli  r4, r3, 16
58	l.andi r4, r4, hi(CLONE_THREAD)
59	l.sfnei r4, 0
60	l.bf L(oldpid)
61	 l.nop
62
63L(oldpid):
64	/* Load function from stack */
65	l.lwz r11, 8(r1)
66	l.jalr r11
67	 l.lwz r3, 4(r1)
68
69	/* Exit the child thread */
70	l.jal HIDDEN_JUMPTARGET(_exit)
71	 l.ori r3, r11, 0
72
73L(error):
74#ifdef __PIC__
75	l.j plt(__syscall_error)
76#else
77	l.j __syscall_error
78#endif
79	 l.ori r3,r11,0
80
81END (__or1k_clone)
82