123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115 |
- /* Copyright (C) 2014 Stony Brook University
- This file is part of Graphene Library OS.
- Graphene Library OS is free software: you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public License
- as published by the Free Software Foundation, either version 3 of the
- License, or (at your option) any later version.
- Graphene Library OS is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
- You should have received a copy of the GNU Lesser General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>. */
- /*
- * clone-x86_64.S
- *
- * This file contains architecture-specific implementation of clone
- * method.
- * The source code is imported and modified from the GNU C Library.
- */
- /* clone() is even more special than fork() as it mucks with stacks
- and invokes a function in the right context after its all over. */
- #include <asm/unistd.h>
- #include <asm/errno.h>
- #include "sysdep-x86_64.h"
- #define CLONE_VM 0x00000100
- #define CLONE_THREAD 0x00010000
- /* The userland implementation is:
- int clone (int (*fn)(void *arg), void *child_stack, int flags, void *arg),
- the kernel entry is:
- int clone (long flags, void *child_stack).
- The parameters are passed in register and on the stack from userland:
- rdi: fn
- rsi: child_stack
- rdx: flags
- rcx: arg
- r8: TID field in parent
- r9: thread pointer
- esp+8: TID field in child
- The kernel expects:
- rax: system call number
- rdi: flags
- rsi: child_stack
- rdx: TID field in parent
- r10: TID field in child
- r8: thread pointer */
- .text
- ENTRY (clone)
- /* Sanity check arguments. */
- movq $-EINVAL, %rax
- testq %rdi, %rdi /* no NULL function pointers */
- /* jz SYSCALL_ERROR_LABEL */
- testq %rsi, %rsi /* no NULL stack pointers */
- /* jz SYSCALL_ERROR_LABEL */
- /* Insert the argument onto the new stack. */
- subq $16, %rsi
- movq %rcx, 8(%rsi)
- /* Save the function pointer. It will be popped off in the
- child in the ebx frobbing below. */
- movq %rdi, 0(%rsi)
- /* Do the system call. */
- movq %rdx, %rdi
- movq %r8, %rdx
- movq %r9, %r8
- movq 8(%rsp), %r10
- movl $SYS_ify(clone), %eax
- /* End FDE now, because in the child the unwind info will be
- wrong. */
- cfi_endproc
- syscall
- testq %rax, %rax
- /* jl SYSCALL_ERROR_LABEL */
- jz thread_start
- ret
- ENTRY (thread_start)
- thread_start:
- cfi_startproc
- /* Clearing frame pointer is insufficient, use CFI. */
- cfi_undefined (rip)
- /* Clear the frame pointer. The ABI suggests this be done, to mark
- the outermost frame obviously. */
- xorl %ebp, %ebp
- /* Set up arguments for the function call. */
- popq %rax /* Function to call. */
- popq %rdi /* Argument. */
- call *%rax
- /* Call exit with return value from function call. */
- /* movq %rax, %rdi */
- /* movl $SYS_ify(exit), %eax */
- /* syscall */
- /* Instead of syscall exit, let's call _DkThreadExit */
- call *_DkThreadExit(%rip)
- cfi_endproc
- cfi_startproc
- END (clone)
|