clone-x86_64.S 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. /* Copyright (C) 2014 OSCAR lab, Stony Brook University
  2. This file is part of Graphene Library OS.
  3. Graphene Library OS is free software: you can redistribute it and/or
  4. modify it under the terms of the GNU General Public License
  5. as published by the Free Software Foundation, either version 3 of the
  6. License, or (at your option) any later version.
  7. Graphene Library OS is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>. */
  13. /*
  14. * clone-x86_64.S
  15. *
  16. * This file contains architecture-specific implementation of clone
  17. * method.
  18. * The source code is imported and modified from the GNU C Library.
  19. */
  20. /* clone() is even more special than fork() as it mucks with stacks
  21. and invokes a function in the right context after its all over. */
  22. #include <asm/unistd.h>
  23. #include <sysdep.h>
  24. #include <asm-errno.h>
  25. #include "sysdep-x86_64.h"
  26. #define CLONE_VM 0x00000100
  27. #define CLONE_THREAD 0x00010000
  28. /* The userland implementation is:
  29. int clone (int (*fn)(void *arg), void *child_stack, int flags, void *arg),
  30. the kernel entry is:
  31. int clone (long flags, void *child_stack).
  32. The parameters are passed in register and on the stack from userland:
  33. rdi: fn
  34. rsi: child_stack
  35. rdx: flags
  36. rcx: arg
  37. r8: TID field in parent
  38. r9: thread pointer
  39. esp+8: TID field in child
  40. The kernel expects:
  41. rax: system call number
  42. rdi: flags
  43. rsi: child_stack
  44. rdx: TID field in parent
  45. r10: TID field in child
  46. r8: thread pointer */
  47. .text
  48. ENTRY (clone)
  49. /* Sanity check arguments. */
  50. movq $-EINVAL,%rax
  51. testq %rdi,%rdi /* no NULL function pointers */
  52. /* jz SYSCALL_ERROR_LABEL */
  53. testq %rsi,%rsi /* no NULL stack pointers */
  54. /* jz SYSCALL_ERROR_LABEL */
  55. /* Insert the argument onto the new stack. */
  56. subq $16,%rsi
  57. movq %rcx,8(%rsi)
  58. /* Save the function pointer. It will be popped off in the
  59. child in the ebx frobbing below. */
  60. movq %rdi,0(%rsi)
  61. /* Do the system call. */
  62. movq %rdx, %rdi
  63. movq %r8, %rdx
  64. movq %r9, %r8
  65. movq 8(%rsp), %r10
  66. movl $SYS_ify(clone),%eax
  67. /* End FDE now, because in the child the unwind info will be
  68. wrong. */
  69. cfi_endproc;
  70. syscall
  71. testq %rax,%rax
  72. /* jl SYSCALL_ERROR_LABEL */
  73. jz L(thread_start)
  74. L(pseudo_end):
  75. ret
  76. L(thread_start):
  77. cfi_startproc;
  78. /* Clearing frame pointer is insufficient, use CFI. */
  79. cfi_undefined (rip);
  80. /* Clear the frame pointer. The ABI suggests this be done, to mark
  81. the outermost frame obviously. */
  82. xorl %ebp, %ebp
  83. /* Set up arguments for the function call. */
  84. popq %rax /* Function to call. */
  85. popq %rdi /* Argument. */
  86. call *%rax
  87. /* Call exit with return value from function call. */
  88. /* movq %rax, %rdi */
  89. /* movl $SYS_ify(exit), %eax */
  90. /* syscall */
  91. /* Instead of syscall exit, let's call _DkThreadExit */
  92. movq _DkThreadExit@GOTPCREL(%rip), %rax
  93. call *%rax
  94. cfi_endproc;
  95. cfi_startproc;
  96. PSEUDO_END (clone)