clone.S 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. /*
  2. * Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com)
  3. *
  4. * Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball.
  5. */
  6. #include <asm/errno.h>
  7. #include <sys/syscall.h>
  8. #include <sysdep.h>
  9. ; Per man, libc clone( ) is as follows
  10. ;
  11. ; int clone(int (*fn)(void *), void *child_stack,
  12. ; int flags, void *arg, ...
  13. ; /* pid_t *ptid, struct user_desc *tls, pid_t *ctid */);
  14. ;
  15. ; NOTE: I'm assuming that the last 3 args are NOT var-args and in case all
  16. ; 3 are not relevant, caller will nevertheless pass those as NULL.
  17. ; Current (Jul 2012) upstream powerpc/clone.S assumes similarly.
  18. ; Our LTP (from 2007) doesn't seem to have tests to prove otherwise
  19. ; clone syscall in kernel (ABI: CONFIG_CLONE_BACKWARDS)
  20. ;
  21. ; int sys_clone(unsigned long clone_flags,
  22. ; unsigned long newsp,
  23. ; int __user *parent_tidptr,
  24. ; void *tls,
  25. ; int __user *child_tidptr)
  26. #define CLONE_SETTLS 0x00080000
  27. ENTRY(clone)
  28. cmp r0, 0 ; @fn can't be NULL
  29. cmp.ne r1, 0 ; @child_stack can't be NULL
  30. bz .L__sys_err
  31. ; save some of the orig args
  32. ; r0 containg @fn will be clobbered AFTER syscall (with ret val)
  33. ; rest are clobbered BEFORE syscall due to different arg ordering
  34. mov r10, r0 ; @fn
  35. mov r11, r3 ; @args
  36. mov r12, r2 ; @clone_flags
  37. mov r9, r5 ; @tls
  38. ; adjust libc args for syscall
  39. mov r0, r2 ; libc @flags is 1st syscall arg
  40. mov r2, r4 ; libc @ptid
  41. mov r3, r5 ; libc @tls
  42. mov r4, r6 ; libc @ctid
  43. mov r8, __NR_clone
  44. ARC_TRAP_INSN
  45. cmp r0, 0 ; return code : 0 new process, !0 parent
  46. blt .L__sys_err2 ; < 0 (signed) error
  47. jnz [blink] ; Parent returns
  48. ; ----- child starts here ---------
  49. #if defined(__UCLIBC_HAS_TLS__)
  50. ; Setup TP register (since kernel doesn't do that)
  51. and.f 0, r12, CLONE_SETTLS
  52. bz .Lnext_clone_quirk
  53. mov r25, r9
  54. .Lnext_clone_quirk:
  55. #endif
  56. ; child jumps off to @fn with @arg as argument, and returns here
  57. jl.d [r10]
  58. mov r0, r11
  59. ; falls thru to _exit() with result from @fn (already in r0)
  60. b HIDDEN_JUMPTARGET(_exit)
  61. .L__sys_err:
  62. mov r0, -EINVAL
  63. .L__sys_err2:
  64. ; (1) No need to make -ve kernel error code as positive errno
  65. ; __syscall_error expects the -ve error code returned by kernel
  66. ; (2) r0 still had orig -ve kernel error code
  67. ; (3) Tail call to __syscall_error so we dont have to come back
  68. ; here hence instead of jmp-n-link (reg push/pop) we do jmp
  69. ; (4) No need to route __syscall_error via PLT, B is inherently
  70. ; position independent
  71. b __syscall_error
  72. END(clone)
  73. libc_hidden_def(clone)