clone-x86_64.S 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. /* Copyright (C) 2014 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 Lesser 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 Lesser General Public License for more details.
  11. You should have received a copy of the GNU Lesser 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 <asm/errno.h>
  24. #include "sysdep-x86_64.h"
  25. #define CLONE_VM 0x00000100
  26. #define CLONE_THREAD 0x00010000
  27. /* The userland implementation is:
  28. int clone (int (*fn)(void *arg), void *child_stack, int flags, void *arg),
  29. the kernel entry is:
  30. int clone (long flags, void *child_stack).
  31. The parameters are passed in register and on the stack from userland:
  32. rdi: fn
  33. rsi: child_stack
  34. rdx: flags
  35. rcx: arg
  36. r8: TID field in parent
  37. r9: thread pointer
  38. esp+8: TID field in child
  39. The kernel expects:
  40. rax: system call number
  41. rdi: flags
  42. rsi: child_stack
  43. rdx: TID field in parent
  44. r10: TID field in child
  45. r8: thread pointer */
  46. .text
  47. ENTRY (clone)
  48. /* Sanity check arguments. */
  49. movq $-EINVAL, %rax
  50. testq %rdi, %rdi /* no NULL function pointers */
  51. /* jz SYSCALL_ERROR_LABEL */
  52. testq %rsi, %rsi /* no NULL stack pointers */
  53. /* jz SYSCALL_ERROR_LABEL */
  54. /* Insert the argument onto the new stack. */
  55. subq $16, %rsi
  56. movq %rcx, 8(%rsi)
  57. /* Save the function pointer. It will be popped off in the
  58. child in the ebx frobbing below. */
  59. movq %rdi, 0(%rsi)
  60. /* Do the system call. */
  61. movq %rdx, %rdi
  62. movq %r8, %rdx
  63. movq %r9, %r8
  64. movq 8(%rsp), %r10
  65. movl $SYS_ify(clone), %eax
  66. /* End FDE now, because in the child the unwind info will be
  67. wrong. */
  68. cfi_endproc
  69. syscall
  70. testq %rax, %rax
  71. /* jl SYSCALL_ERROR_LABEL */
  72. jz thread_start
  73. ret
  74. ENTRY (thread_start)
  75. thread_start:
  76. cfi_startproc
  77. /* Clearing frame pointer is insufficient, use CFI. */
  78. cfi_undefined (rip)
  79. /* Clear the frame pointer. The ABI suggests this be done, to mark
  80. the outermost frame obviously. */
  81. xorl %ebp, %ebp
  82. /* Set up arguments for the function call. */
  83. popq %rax /* Function to call. */
  84. popq %rdi /* Argument. */
  85. call *%rax
  86. /* Call exit with return value from function call. */
  87. /* movq %rax, %rdi */
  88. /* movl $SYS_ify(exit), %eax */
  89. /* syscall */
  90. /* Instead of syscall exit, let's call _DkThreadExit */
  91. call *_DkThreadExit(%rip)
  92. cfi_endproc
  93. cfi_startproc
  94. END (clone)