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 thread_start
  74. L(pseudo_end):
  75. ret
  76. ENTRY (thread_start)
  77. L(thread_start):
  78. cfi_startproc
  79. /* Clearing frame pointer is insufficient, use CFI. */
  80. cfi_undefined (rip)
  81. /* Clear the frame pointer. The ABI suggests this be done, to mark
  82. the outermost frame obviously. */
  83. xorl %ebp, %ebp
  84. /* Set up arguments for the function call. */
  85. popq %rax /* Function to call. */
  86. popq %rdi /* Argument. */
  87. call *%rax
  88. /* Call exit with return value from function call. */
  89. /* movq %rax, %rdi */
  90. /* movl $SYS_ify(exit), %eax */
  91. /* syscall */
  92. /* Instead of syscall exit, let's call _DkThreadExit */
  93. call _DkThreadExit(%rip)
  94. cfi_endproc
  95. cfi_startproc
  96. PSEUDO_END (clone)