diff options
| author | Mike Frysinger <vapier@gentoo.org> | 2005-02-15 01:38:50 +0000 | 
|---|---|---|
| committer | Mike Frysinger <vapier@gentoo.org> | 2005-02-15 01:38:50 +0000 | 
| commit | 119d5dfbe0adfb6f11c830fb2434dd01ac628cf1 (patch) | |
| tree | 9c3de0fb24dbe9a9c1295d12272d1e5af39ea062 /libc | |
| parent | fc59b6ec5140386c0072cae932d2812015016a5b (diff) | |
| download | uClibc-alpine-119d5dfbe0adfb6f11c830fb2434dd01ac628cf1.tar.bz2 uClibc-alpine-119d5dfbe0adfb6f11c830fb2434dd01ac628cf1.tar.xz  | |
some more x86_64 source
Diffstat (limited to 'libc')
| -rw-r--r-- | libc/sysdeps/linux/x86_64/clone.S | 116 | ||||
| -rw-r--r-- | libc/sysdeps/linux/x86_64/vfork.S | 53 | 
2 files changed, 169 insertions, 0 deletions
diff --git a/libc/sysdeps/linux/x86_64/clone.S b/libc/sysdeps/linux/x86_64/clone.S new file mode 100644 index 000000000..9d244d018 --- /dev/null +++ b/libc/sysdeps/linux/x86_64/clone.S @@ -0,0 +1,116 @@ +/* Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. + +   The GNU C Library 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 2.1 of the License, or (at your option) any later version. + +   The GNU C Library 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 the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +/* clone() is even more special than fork() as it mucks with stacks +   and invokes a function in the right context after its all over.  */ + +#define _ERRNO_H	1 +#include <bits/errno.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 +   r8d:	TID field in parent +   r9d: 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 +.globl __clone; +.type	__clone,@function +.align 4; +__clone: +	/* Sanity check arguments.  */ +	movq	$-EINVAL,%rax +	testq	%rdi,%rdi		/* no NULL function pointers */ +	jz	__syscall_error +	testq	%rsi,%rsi		/* no NULL stack pointers */ +	jz	__syscall_error + +	/* 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 +	movq	$__NR_clone,%rax + +	syscall + +	testq	%rax,%rax +	jl	__syscall_error +	jz	L(thread_start) + +L(pseudo_end): +	ret + +L(thread_start): +	/* Clear the frame pointer.  The ABI suggests this be done, to mark +	   the outermost frame obviously.  */ +	xorq	%rbp, %rbp + +#ifdef RESET_PID +	testq	$CLONE_THREAD, %rdi +	jne	1f +	testq	$CLONE_VM, %rdi +	movl	$-1, %eax +	jne	2f +	movq	__NR_getpid, %rax +	syscall +2:	movl	%eax, %fs:PID +	movl	%eax, %fs:TID +1: +#endif + +	/* 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 +	call	HIDDEN_JUMPTARGET (_exit) + +	cfi_startproc; +PSEUDO_END (BP_SYM (__clone)) + +weak_alias (BP_SYM (__clone), BP_SYM (clone)) diff --git a/libc/sysdeps/linux/x86_64/vfork.S b/libc/sysdeps/linux/x86_64/vfork.S new file mode 100644 index 000000000..072a3a0a8 --- /dev/null +++ b/libc/sysdeps/linux/x86_64/vfork.S @@ -0,0 +1,53 @@ +/* Copyright (C) 2001, 2002, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. + +   The GNU C Library 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 2.1 of the License, or (at your option) any later version. + +   The GNU C Library 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 the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#define _ERRNO_H	1 +#include <bits/errno.h> + +/* Clone the calling process, but without copying the whole address space. +   The calling process is suspended until the new process exits or is +   replaced by a call to `execve'.  Return -1 for errors, 0 to the new process, +   and the process ID of the new process to the old process.  */ + +.globl __vfork; +.type	__vfork,@function; +.align 16; +__vfork: + +	/* Pop the return PC value into RDI.  We need a register that +	   is preserved by the syscall and that we're allowed to destroy. */ +	popq	%rdi + +	/* Stuff the syscall number in RAX and enter into the kernel.  */ +	movl	$__NR_vfork, %eax +	syscall + +	/* Push back the return PC.  */ +	pushq	%rdi + +	cmpl	$-4095, %eax +	jae __syscall_error		/* Branch forward if it failed.  */ + +	/* Normal return.  */ +	ret + +__syscall_error: +	/* TODO: implement this ! :D */ + +.size	 __vfork,.Lsize-__vfork +.weak vfork ; vfork = __vfork  | 
