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