| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687 | /* * Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com) * * Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball. */#include <asm/errno.h>#include <sys/syscall.h>#include <sysdep.h>; Per man, libc clone( ) is as follows;; int clone(int (*fn)(void *), void *child_stack,;           int flags, void *arg, ...;           /* pid_t *ptid, struct user_desc *tls, pid_t *ctid */);;; NOTE: I'm assuming that the last 3 args are NOT var-args and in case all;	3 are not relevant, caller will nevertheless pass those as NULL.;       Current (Jul 2012) upstream powerpc/clone.S assumes similarly.;	Our LTP (from 2007) doesn't seem to have tests to prove otherwise; clone syscall in kernel (ABI: CONFIG_CLONE_BACKWARDS);; int sys_clone(unsigned long clone_flags,;		unsigned long newsp,;		int __user *parent_tidptr,;		void *tls,;		int __user *child_tidptr)#define CLONE_SETTLS		0x00080000ENTRY(clone)	cmp	r0, 0		; @fn can't be NULL	cmp.ne	r1, 0		; @child_stack can't be NULL	bz	.L__sys_err	; save some of the orig args	; r0 containg @fn will be clobbered AFTER syscall (with ret val)	; rest are clobbered BEFORE syscall due to different arg ordering	mov	r10, r0		; @fn	mov	r11, r3		; @args	mov	r12, r2		; @clone_flags	mov	r9,  r5		; @tls	; adjust libc args for syscall	mov 	r0, r2		; libc @flags is 1st syscall arg	mov	r2, r4		; libc @ptid	mov	r3, r5		; libc @tls	mov	r4, r6		; libc @ctid	mov	r8, __NR_clone	ARC_TRAP_INSN	cmp	r0, 0		; return code : 0 new process, !0 parent	blt	.L__sys_err2	; < 0 (signed) error	jnz	[blink]		; Parent returns	; ----- child starts here ---------#if defined(__UCLIBC_HAS_TLS__)	; Setup TP register (since kernel doesn't do that)	and.f	0, r12, CLONE_SETTLS	bz	.Lnext_clone_quirk	mov	r25, r9.Lnext_clone_quirk:#endif	; child jumps off to @fn with @arg as argument, and returns here	jl.d	[r10]	mov	r0, r11	; falls thru to _exit() with result from @fn (already in r0)	b	HIDDEN_JUMPTARGET(_exit).L__sys_err:	mov	r0, -EINVAL.L__sys_err2:	; (1) No need to make -ve kernel error code as positive errno	;   __syscall_error expects the -ve error code returned by kernel	; (2) r0 still had orig -ve kernel error code	; (3) Tail call to __syscall_error so we dont have to come back	;     here hence instead of jmp-n-link (reg push/pop) we do jmp	; (4) No need to route __syscall_error via PLT, B is inherently	;     position independent	b   __syscall_errorEND(clone)libc_hidden_def(clone)
 |