clone.S 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. ! Copyright (C) 2013 Imagination Technologies Ltd.
  2. ! Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball.
  3. ! clone() is even more special than fork() as it mucks with stacks
  4. ! and invokes a function in the right context after its all over.
  5. #include <asm/errno.h>
  6. #include <asm/unistd.h>
  7. #define CLONE_VM 0x00000100
  8. #define CLONE_THREAD 0x00010000
  9. #ifdef __PIC__
  10. #define __CLONE_METAG_LOAD_TP ___metag_load_tp@PLT
  11. #else
  12. #define __CLONE_METAG_LOAD_TP ___metag_load_tp
  13. #endif
  14. /* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg,
  15. pid_t *ptid, struct user_desc *tls, pid_t *ctid); */
  16. .text
  17. .global __clone
  18. .type __clone,function
  19. __clone:
  20. ! sanity check args
  21. MOV D0Re0, #-EINVAL
  22. CMP D1Ar1, #0
  23. BEQ ___error
  24. CMP D0Ar2, #0
  25. BEQ ___error
  26. ! save function pointer
  27. MOV D0FrT, D1Ar1
  28. ! do the system call
  29. MOV D1Ar1, D1Ar3
  30. MOV D1Ar3, D1Ar5
  31. MOV D1Ar5, D0Ar6
  32. MOV D0Ar6, D0Ar4
  33. GETD D0Ar4, [A0StP+#-4]
  34. ! new sp is already in D0Ar2
  35. MOV D1Re0, #__NR_clone
  36. SWITCH #0x440001
  37. CMP D0Re0,#0
  38. ! Error on -1
  39. BLT ___error
  40. ! If non-zero we are the parent
  41. MOVNE PC, D1RtP
  42. ! BRKPNT
  43. ! We are the child
  44. #ifdef RESET_PID
  45. SETL [A0StP++], D0FrT, D1RtP
  46. MOVT D0FrT, #HI(CLONE_THREAD)
  47. ADD D0FrT, D0FrT, #LO(CLONE_THREAD)
  48. ANDS D0FrT, D0FrT, D1Ar1
  49. BNZ 3f
  50. MOVT D0FrT, #HI(CLONE_VM)
  51. ADD D0FrT, D0FrT, #LO(CLONE_VM)
  52. ANDS D0FrT, D0FrT, D1Ar1
  53. BZ 1f
  54. MOV D1Ar1, #-1
  55. BA 2f
  56. 1: MOV D1Re0, #__NR_getpid
  57. SWITCH #0x440001
  58. MOV D1Ar1, D0Re0
  59. 2: CALLR D1RtP, __CLONE_METAG_LOAD_TP
  60. SUB D0Re0, D0Re0, #TLS_PRE_TCB_SIZE
  61. SETD [D0Re0 + #PID], D1Ar1
  62. SETD [D0Re0 + #TID], D1Ar1
  63. 3: GETL D0FrT, D1RtP, [--A0StP]
  64. #endif
  65. ! Rearrange the function arg and call address from registers
  66. MOV D0Ar2, D0FrT
  67. MOV D1Ar1, D0Ar6
  68. MOV D1RtP, PC
  69. ADD D1RtP, D1RtP, #8
  70. MOV PC, D0Ar2
  71. ! and we are done, passing the return value D0Re0 through D1Ar1
  72. MOV D1Ar1, D0Re0
  73. #ifdef __PIC__
  74. B _exit@PLT
  75. #else
  76. B _exit
  77. #endif
  78. ___error:
  79. MOV D1Ar1, D0Re0
  80. #ifdef __PIC__
  81. B ___syscall_error@PLT
  82. #else
  83. B ___syscall_error
  84. #endif
  85. .size __clone, .-__clone
  86. .weak _clone
  87. _clone = __clone