diff options
author | Waldemar Brodkorb <wbx@openadk.org> | 2017-04-17 14:48:50 +0200 |
---|---|---|
committer | Waldemar Brodkorb <wbx@openadk.org> | 2017-05-14 10:29:09 +0200 |
commit | 69ea4c1f65bff99575cd7f0210312dc355929240 (patch) | |
tree | 43fe11a4e27c85b742e2434f6e8ec0b25576d8af /libc/sysdeps/linux/or1k/or1k_clone.S | |
parent | be6a02b9a0317a7441de9aa2e3e07fe838787d57 (diff) |
or1k: add clone() from old GNU libc implementation
Diffstat (limited to 'libc/sysdeps/linux/or1k/or1k_clone.S')
-rw-r--r-- | libc/sysdeps/linux/or1k/or1k_clone.S | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/libc/sysdeps/linux/or1k/or1k_clone.S b/libc/sysdeps/linux/or1k/or1k_clone.S new file mode 100644 index 000000000..a2c16ac9e --- /dev/null +++ b/libc/sysdeps/linux/or1k/or1k_clone.S @@ -0,0 +1,77 @@ +#include <sysdep.h> + +#define CLONE_VM 0x00000100 +#define CLONE_THREAD 0x00010000 + +.text +ENTRY(__or1k_clone) + + /* To handle GCC varargs we need to use our __clone wrapper to pop + everything from the stack for us. + Now everything is placed in the registers which saves us a lot + of trouble. + + The userland implementation is: + int clone (int (*fn)(void *), void *child_stack, + int flags, void *arg, pid_t *ptid, + struct user_desc *tls, pid_t *ctid); + + The kernel entry is: + int clone (long flags, void *child_stack, int *parent_tid, + int *child_tid, struct void *tls) + NB: tls isn't really an argument, it is read from r7 directly. + */ + + /* Put 'fn', 'arg' and 'flags' on child stack */ + l.addi r4, r4, -12 + l.sw 8(r4), r3 + l.sw 4(r4), r6 + l.sw 0(r4), r5 + + l.ori r3, r5, 0 + /* child_stack is already in r4 */ + l.ori r5, r7, 0 + l.lwz r6, 0(r1) + l.ori r7, r8, 0 + + DO_CALL (clone) + + l.sfgeui r11, 0xf001 + l.bf L(error) + l.nop + + /* If we are not the child, return the pid */ + l.sfeqi r11, 0 + l.bf L(child) + l.nop + + l.jr r9 + l.nop + +L(child): + /* Load flags */ + l.lwz r3, 0(r1) + + /* Update PID, but only if we do not share the same PID + as our parent */ + l.srli r4, r3, 16 + l.andi r4, r4, hi(CLONE_THREAD) + l.sfnei r4, 0 + l.bf L(oldpid) + l.nop + +L(oldpid): + /* Load function from stack */ + l.lwz r11, 8(r1) + l.jalr r11 + l.lwz r3, 4(r1) + + /* Exit the child thread */ + l.jal HIDDEN_JUMPTARGET(_exit) + l.ori r3, r11, 0 + +L(error): + l.j SYSCALL_ERROR_NAME + l.ori r3,r11,0 + +PSEUDO_END (__or1k_clone) |