or1k_clone.S 1.6 KB

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