diff options
| author | Markos Chandras <markos.chandras@imgtec.com> | 2010-11-18 14:58:01 +0000 | 
|---|---|---|
| committer | Bernhard Reutner-Fischer <rep.dot.nop@gmail.com> | 2013-03-14 22:47:08 +0100 | 
| commit | daecc9a410a6f23d80daf8ce3afd280fea329e63 (patch) | |
| tree | 8d603dd538809431cc01b9e656c827d1f0709052 /libc/sysdeps | |
| parent | 20221281b3d67880439cd1d16c151f4528d034fb (diff) | |
metag: Add NPTL support
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
Signed-off-by: Bernhard Reutner-Fischer <rep.dot.nop@gmail.com>
Diffstat (limited to 'libc/sysdeps')
| -rw-r--r-- | libc/sysdeps/linux/common/Makefile.in | 1 | ||||
| -rw-r--r-- | libc/sysdeps/linux/metag/Makefile.arch | 4 | ||||
| -rw-r--r-- | libc/sysdeps/linux/metag/bits/atomic.h | 66 | ||||
| -rw-r--r-- | libc/sysdeps/linux/metag/bits/syscalls.h | 73 | ||||
| -rw-r--r-- | libc/sysdeps/linux/metag/clone.S | 50 | ||||
| -rw-r--r-- | libc/sysdeps/linux/metag/crt1.S | 3 | ||||
| -rw-r--r-- | libc/sysdeps/linux/metag/libc-metag_load_tp.S | 7 | ||||
| -rw-r--r-- | libc/sysdeps/linux/metag/sysdep.h | 59 | ||||
| -rw-r--r-- | libc/sysdeps/linux/metag/vfork.S | 67 | 
9 files changed, 294 insertions, 36 deletions
diff --git a/libc/sysdeps/linux/common/Makefile.in b/libc/sysdeps/linux/common/Makefile.in index f7083a48b..dbf0b0fd4 100644 --- a/libc/sysdeps/linux/common/Makefile.in +++ b/libc/sysdeps/linux/common/Makefile.in @@ -69,6 +69,7 @@ CSRC- += fork.c getpid.c raise.c #open.c close.c read.c write.c  CSRC- += $(if $(findstring =arm=,=$(TARGET_ARCH)=),vfork.c)  CSRC- += $(if $(findstring =x86_64=,=$(TARGET_ARCH)=),vfork.c)  #CSRC- += $(if $(findstring =mips=y=,=$(TARGET_ARCH)=$(CONFIG_MIPS_O32_ABI)=),waitpid.c) +CSRC- += $(if $(findstring =metag=,=$(TARGET_ARCH)=),vfork.c)  endif  ifneq ($(ARCH_HAS_DEPRECATED_SYSCALLS),y)  # No conversion is needed for new architectures diff --git a/libc/sysdeps/linux/metag/Makefile.arch b/libc/sysdeps/linux/metag/Makefile.arch index 0e6fbfe12..3f11d6da8 100644 --- a/libc/sysdeps/linux/metag/Makefile.arch +++ b/libc/sysdeps/linux/metag/Makefile.arch @@ -7,4 +7,6 @@  CSRC-y := brk.c syscall.c metag.c __syscall_error.c -SSRC-y := _longjmp.S clone.S setjmp.S +SSRC-y := _longjmp.S clone.S setjmp.S vfork.S + +SSRC-$(UCLIBC_HAS_THREADS_NATIVE) += libc-metag_load_tp.S diff --git a/libc/sysdeps/linux/metag/bits/atomic.h b/libc/sysdeps/linux/metag/bits/atomic.h new file mode 100644 index 000000000..64aa50bc4 --- /dev/null +++ b/libc/sysdeps/linux/metag/bits/atomic.h @@ -0,0 +1,66 @@ +/* + * Copyrith (C) 2013 Imagination Technologies Ltd. + * + * Licensed under LGPL v2.1 or later, see the file COPYING.LIB in this tarball. + * + */ + +#include <stdint.h> +#include <sysdep.h> + +typedef int8_t atomic8_t; +typedef uint8_t uatomic8_t; +typedef int_fast8_t atomic_fast8_t; +typedef uint_fast8_t uatomic_fast8_t; + +typedef int32_t atomic32_t; +typedef uint32_t uatomic32_t; +typedef int_fast32_t atomic_fast32_t; +typedef uint_fast32_t uatomic_fast32_t; + +typedef intptr_t atomicptr_t; +typedef uintptr_t uatomicptr_t; +typedef intmax_t atomic_max_t; +typedef uintmax_t uatomic_max_t; + +void __metag_link_error (void); + +#define atomic_full_barrier() \ +     __asm__ __volatile__("": : :"memory") + +/* Atomic compare and exchange.  This sequence relies on the kernel to +   provide a compare and exchange operation which is atomic. */ + +#define __arch_compare_and_exchange_val_8_acq(mem, newval, oldval) \ +  ({ __metag_link_error (); oldval; }) + +#define __arch_compare_and_exchange_val_16_acq(mem, newval, oldval) \ +  ({ __metag_link_error (); oldval; }) + +/* This code uses the kernel helper to do cmpxchg. It relies on the fact +   the helper code only clobbers D0Re0. */ +#define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval)     \ +  ({ register __typeof (oldval) a_current __asm__ ("D1Ar1");		\ +    register __typeof (oldval) a_newval __asm__ ("D0Ar2") = (newval);   \ +    register __typeof (mem) a_ptr __asm__ ("D1Ar3") = (mem);            \ +    register __typeof (oldval) a_oldval __asm__ ("D0Ar4") = (oldval);	\ +    __asm__ __volatile__						\ +      ("0:\n\t"								\ +       "GETD	%[cur], [%[ptr]]\n\t"					\ +       "CMP	%[cur], %[old]\n\t"					\ +       "BNE	1f\n\t"							\ +       "MOVT	D1RtP, #0x6fff\n\t"					\ +       "ADD	D1RtP, D1RtP, #0xf040\n\t"				\ +       "SWAP	D1RtP, PC\n\t"						\ +       "MOV	%[cur], %[old]\n\t"					\ +       "CMP	D0Re0, #0\n\t"						\ +       "BNE	0b\n\t"							\ +       "1:"								\ +       : [cur] "=&r" (a_current)					\ +       : [new] "r" (a_newval), [ptr] "r" (a_ptr),			\ +	 [old] "r" (a_oldval)						\ +       : "D0Re0", "D1RtP", "cc", "memory");				\ +    a_current; }) + +#define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \ +  ({ __metag_link_error (); oldval; }) diff --git a/libc/sysdeps/linux/metag/bits/syscalls.h b/libc/sysdeps/linux/metag/bits/syscalls.h index b5c8fc58c..7ea09c2c3 100644 --- a/libc/sysdeps/linux/metag/bits/syscalls.h +++ b/libc/sysdeps/linux/metag/bits/syscalls.h @@ -49,8 +49,9 @@  (__extension__                                                          \    ({unsigned int __sys_result;						\      {									\ +      PREP_ARGS_##nr (args);						\        register int _result __asm__ ("D0Re0"), _nr __asm__ ("D1Re0");	\ -      LOAD_ARGS_##nr (args);						\ +      LOAD_ARGS_##nr;							\        _nr = (name);							\        __asm__ volatile ("SWITCH  #0x440001 ! syscall " #name		\  			: "=r" (_result)				\ @@ -68,32 +69,52 @@  #undef INTERNAL_SYSCALL_ERRNO  #define INTERNAL_SYSCALL_ERRNO(val, err)	(-(val)) -#define LOAD_ARGS_0() +#define PREP_ARGS_0() +#define PREP_ARGS_1(a1)                                 \ +  int _t1 = (int) (a1);                                 \ +  PREP_ARGS_0 () +#define PREP_ARGS_2(a1, a2)                             \ +  int _t2 = (int) (a2);                                 \ +  PREP_ARGS_1 (a1) +#define PREP_ARGS_3(a1, a2, a3)                         \ +  int _t3 = (int) (a3);                                 \ +  PREP_ARGS_2 (a1, a2) +#define PREP_ARGS_4(a1, a2, a3, a4)                     \ +  int _t4 = (int) (a4);                                 \ +  PREP_ARGS_3 (a1, a2, a3) +#define PREP_ARGS_5(a1, a2, a3, a4, a5)                 \ +  int _t5 = (int) (a5);                                 \ +  PREP_ARGS_4 (a1, a2, a3, a4) +#define PREP_ARGS_6(a1, a2, a3, a4, a5, a6)             \ +  int _t6 = (int) (a6);                                 \ +  PREP_ARGS_5 (a1, a2, a3, a4, a5) + +#define LOAD_ARGS_0  #define ASM_ARGS_0 -#define LOAD_ARGS_1(a1)					\ -  register int _a1 __asm__ ("D1Ar1") = (int) (a1);	\ -  LOAD_ARGS_0 () -#define ASM_ARGS_1	ASM_ARGS_0, "d" (_a1) -#define LOAD_ARGS_2(a1, a2)				\ -  register int _a2 __asm__ ("D0Ar2") = (int) (a2);	\ -  LOAD_ARGS_1 (a1) -#define ASM_ARGS_2	ASM_ARGS_1, "d" (_a2) -#define LOAD_ARGS_3(a1, a2, a3)				\ -  register int _a3 __asm__ ("D1Ar3") = (int) (a3);	\ -  LOAD_ARGS_2 (a1, a2) -#define ASM_ARGS_3	ASM_ARGS_2, "d" (_a3) -#define LOAD_ARGS_4(a1, a2, a3, a4)			\ -  register int _a4 __asm__ ("D0Ar4") = (int) (a4);	\ -  LOAD_ARGS_3 (a1, a2, a3) -#define ASM_ARGS_4	ASM_ARGS_3, "d" (_a4) -#define LOAD_ARGS_5(a1, a2, a3, a4, a5)			\ -  register int _a5 __asm__ ("D1Ar5") = (int) (a5);	\ -  LOAD_ARGS_4 (a1, a2, a3, a4) -#define ASM_ARGS_5	ASM_ARGS_4, "d" (_a5) -#define LOAD_ARGS_6(a1, a2, a3, a4, a5, a6)		\ -  register int _a6 __asm__ ("D0Ar6") = (int) (a6);	\ -  LOAD_ARGS_5 (a1, a2, a3, a4, a5) -#define ASM_ARGS_6	ASM_ARGS_5, "d" (_a6) +#define LOAD_ARGS_1                                     \ +  register int _a1 __asm__ ("D1Ar1") = (int) (_t1);     \ +  LOAD_ARGS_0 +#define ASM_ARGS_1 ASM_ARGS_0, "d" (_a1) +#define LOAD_ARGS_2                                     \ +  register int _a2 __asm__ ("D0Ar2") = (int) (_t2);     \ +  LOAD_ARGS_1 +#define ASM_ARGS_2 ASM_ARGS_1, "d" (_a2) +#define LOAD_ARGS_3                                     \ +  register int _a3 __asm__ ("D1Ar3") = (int) (_t3);     \ +  LOAD_ARGS_2 +#define ASM_ARGS_3 ASM_ARGS_2, "d" (_a3) +#define LOAD_ARGS_4                                     \ +  register int _a4 __asm__ ("D0Ar4") = (int) (_t4);     \ +  LOAD_ARGS_3 +#define ASM_ARGS_4 ASM_ARGS_3, "d" (_a4) +#define LOAD_ARGS_5                                     \ +  register int _a5 __asm__ ("D1Ar5") = (int) (_t5);     \ +  LOAD_ARGS_4 +#define ASM_ARGS_5 ASM_ARGS_4, "d" (_a5) +#define LOAD_ARGS_6                                     \ +  register int _a6 __asm__ ("D0Ar6") = (int) (_t6);     \ +  LOAD_ARGS_5 +#define ASM_ARGS_6 ASM_ARGS_5, "d" (_a6)  #endif /* __ASSEMBLER__ */  #endif /* _BITS_SYSCALLS_H */ diff --git a/libc/sysdeps/linux/metag/clone.S b/libc/sysdeps/linux/metag/clone.S index 8fff56710..d9d836338 100644 --- a/libc/sysdeps/linux/metag/clone.S +++ b/libc/sysdeps/linux/metag/clone.S @@ -8,7 +8,17 @@  #include <asm/errno.h>  #include <asm/unistd.h> -/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg); */ +#define CLONE_VM      0x00000100 +#define CLONE_THREAD  0x00010000 + +#ifdef __PIC__ +#define __CLONE_METAG_LOAD_TP ___metag_load_tp@PLT +#else +#define __CLONE_METAG_LOAD_TP ___metag_load_tp +#endif + +/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg, +			pid_t *ptid, struct user_desc *tls, pid_t *ctid); */  	.text  	.global	__clone @@ -25,8 +35,12 @@ __clone:  	MOV D0FrT, D1Ar1  	! do the system call -	! get flags  	MOV	D1Ar1, D1Ar3 +	MOV	D1Ar3, D1Ar5 +	MOV	D1Ar5, D0Ar6 +	MOV	D0Ar6, D0Ar4 +	GETD	D0Ar4, [A0StP+#-4] +  	! new sp is already in D0Ar2  	MOV	D1Re0, #__NR_clone  	SWITCH	#0x440001 @@ -38,14 +52,36 @@ __clone:  	! BRKPNT  	! We are the child -	! pick the function arg and call address off the stack and execute -	MOV     D0Ar2, D0FrT -	MOV     D1Ar1, D0Ar4 -	MOV     D1RtP, PC +#ifdef RESET_PID +	SETL	[A0StP++], D0FrT, D1RtP +	MOVT	D0FrT, #HI(CLONE_THREAD) +	ADD	D0FrT, D0FrT, #LO(CLONE_THREAD) +	ANDS	D0FrT, D0FrT, D1Ar1 +	BNZ	3f +	MOVT	D0FrT, #HI(CLONE_VM) +	ADD	D0FrT, D0FrT, #LO(CLONE_VM) +	ANDS	D0FrT, D0FrT, D1Ar1 +	BZ	1f +	MOV	D1Ar1, #-1 +	BA	2f +1:	MOV	D1Re0, #__NR_getpid +	SWITCH	#0x440001 +	MOV	D1Ar1, D0Re0 +2:	CALLR	D1RtP, __CLONE_METAG_LOAD_TP +	SUB	D0Re0, D0Re0, #TLS_PRE_TCB_SIZE +	SETD	[D0Re0 + #PID], D1Ar1 +	SETD	[D0Re0 + #TID], D1Ar1 +3:	GETL	D0FrT, D1RtP, [--A0StP] +#endif +	! Rearrange the function arg and call address from registers +	MOV	D0Ar2, D0FrT +	MOV	D1Ar1, D0Ar6 +	MOV	D1RtP, PC  	ADD	D1RtP, D1RtP, #8  	MOV	PC, D0Ar2 -	! and we are done, passing the return value through D0Re0 +	! and we are done, passing the return value D0Re0 through D1Ar1 +	MOV	D1Ar1, D0Re0  #ifdef __PIC__  	B	_exit@PLT  #else diff --git a/libc/sysdeps/linux/metag/crt1.S b/libc/sysdeps/linux/metag/crt1.S index 74adc1fdb..e8561a46b 100644 --- a/libc/sysdeps/linux/metag/crt1.S +++ b/libc/sysdeps/linux/metag/crt1.S @@ -29,6 +29,7 @@ __start:  	MOV	D1Ar3,D0Ar2			! argv  	MOV	D0Ar2,D1Ar1			! argc +	MOV	D0Ar6,D0Ar4			! rtld_fini  #ifdef __PIC__  	ADDT	A1LbP,CPC1,#HI(__GLOBAL_OFFSET_TABLE__) @@ -54,8 +55,6 @@ __start:  	ADD	D1Ar5,D1Ar5,#LO(__fini)  #endif -	MOV	D0Ar6,#0			! rtld_fini -  	MOVT	D1Re0,#0x80  	SETL	[A0StP++],D0Re0,D1Re0		! stack_end (8Mb) diff --git a/libc/sysdeps/linux/metag/libc-metag_load_tp.S b/libc/sysdeps/linux/metag/libc-metag_load_tp.S new file mode 100644 index 000000000..a91f162ec --- /dev/null +++ b/libc/sysdeps/linux/metag/libc-metag_load_tp.S @@ -0,0 +1,7 @@ +/* + * Copyright (C) 2013 Imagination Technologies Ltd. + * + * Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball. + */ + +#include <ldso/ldso/metag/metag_load_tp.S> diff --git a/libc/sysdeps/linux/metag/sysdep.h b/libc/sysdeps/linux/metag/sysdep.h new file mode 100644 index 000000000..a12f393ce --- /dev/null +++ b/libc/sysdeps/linux/metag/sysdep.h @@ -0,0 +1,59 @@ +/* + * Assembler macros for Meta. + * + * Licensed under LGPL v2.1 or later, see the file COPYING.LIB in this tarball. + */ + +#include <common/sysdep.h> + +#include <features.h> +#include <libc-internal.h> + +#ifdef	__ASSEMBLER__ + +#ifdef SHARED +#define PLTJMP(_x)	_x##@PLT +#else +#define PLTJMP(_x)	_x +#endif + +#undef	PSEUDO_END +#define	PSEUDO_END(name)						\ +  SYSCALL_ERROR_HANDLER							\ +  END (name) + +#if defined NOT_IN_libc +# define SYSCALL_ERROR __local_syscall_error +# ifdef RTLD_PRIVATE_ERRNO +#  define SYSCALL_ERROR_HANDLER					\ +__local_syscall_error:						\ +       NEG	D0Re0, D0Re0;					\ +       ADDT	D1Re0, CPC1, #HI(_rtld_errno);			\ +       ADD	D1Re0, D1Re0, #LO(_rtld_errno) + 4;		\ +       SETD	[D1Re0], D0Re0;					\ +       NEG	D0Re0, #0x1;					\ +       MOV	PC, D1RtP; +# else +#  define SYSCALL_ERROR_HANDLER					\ +__local_syscall_error:						\ +	MOV	D1Re0, D1RtP;					\ +	SETL	[A0StP++], D0Re0, D1Re0;			\ +	CALLR	D1RtP, PLTJMP(___errno_location);		\ +	GETD	D1Re0, [A0StP+#-8];				\ +	NEG	D1Re0, D1Re0;					\ +	SETD	[D0Re0], D1Re0;					\ +	NEG	D0Re0, #0x1;					\ +	GETD	D1RtP, [A0StP+#-4];				\ +	SUB	A0StP, A0StP, #0x8;				\ +	MOV	PC, D1RtP; +# endif +#else +# define SYSCALL_ERROR_HANDLER	/* Nothing here; code in sysdep.S is used.  */ +# define SYSCALL_ERROR ___syscall_error +#endif + +#endif /* __ASSEMBLER __*/ + +/* Pointer mangling is not yet supported for META.  */ +#define PTR_MANGLE(var) (void) (var) +#define PTR_DEMANGLE(var) (void) (var) diff --git a/libc/sysdeps/linux/metag/vfork.S b/libc/sysdeps/linux/metag/vfork.S new file mode 100644 index 000000000..8573dedd3 --- /dev/null +++ b/libc/sysdeps/linux/metag/vfork.S @@ -0,0 +1,67 @@ +!    Copyright (C) 2013 Imagination Technologies Ltd. + +!    Licensed under LGPL v2.1 or later, see the file COPYING.LIB in this tarball. + +#include <asm/unistd.h> + +#define _ERRNO_H +#include <bits/errno.h> +#include <sys/syscall.h> + +#ifndef SAVE_PID +#define SAVE_PID +#endif + +#ifndef RESTORE_PID +#define RESTORE_PID +#endif + +#ifdef __NR_vfork +#define __VFORK_NR __NR_vfork +#else +#define __VFORK_NR __NR_fork +#endif + +/* 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.  */ + +	.balign 4 +	.global	___vfork +	.hidden	___vfork +	.type	___vfork, @function +___vfork: + +	SAVE_PID + +	MOV	D1Ar1, #0x4111	/* CLONE_VM | CLONE_VFORK | SIGCHLD */ +	MOV	D0Ar2, #0 +	MOV	D1Ar3, #0 +	MOV	D0Ar4, #0 +	MOV	D1Ar5, #0 +	MOV	D0Ar6, #0 +	MOV	D1Re0, #__NR_clone +	SWITCH  #0x440001 + +	RESTORE_PID + +	MOVT	D1Re0, #HI(-4096) +	ADD	D1Re0, D1Re0, #LO(-4096) +	CMP	D1Re0, D0Re0 +	BCS	error + +	/* Syscall worked. Return to child/parent */ +	MOV	PC, D1RtP + +error: +	MOV	D1Ar1, D0Re0 +#ifdef __PIC__ +	B	___syscall_error@PLT +#else +	B	___syscall_error +#endif +	.size ___vfork,.-___vfork + +weak_alias(__vfork,vfork) +libc_hidden_weak(vfork)  | 
