[PATCH] MIPS64 N64 fork is broken

Waldemar Brodkorb wbx at openadk.org
Mon Jan 20 08:37:32 UTC 2014


Hi,

any news/comment about this?

thx
 Waldemar

Waldemar Brodkorb wrote,

> fork() is broken for MIPS64 N64 ABI. You can check it with a simple
> C program statically linked with qemu-mips64 user emulation.
> Internally fork() is using the clone system call (at least with NPTL)
> with 5 arguments. See ./libpthread/nptl/sysdeps/unix/sysv/linux/i386/fork.c.
> The calling conventions for MIPS N32 and N64 allow to use up to 8 registers
> for that. See http://en.wikipedia.org/wiki/Calling_convention#MIPS
> This is correctly implemented in libc/sysdeps/linux/mips/bits/syscalls.h,
> but not in libc/sysdeps/linux/mips/sysdep.h. fork.c uses the later one.
> It seems that fork() works fine for MIPS64 N32 with just using the stack like
> with the O32 case. There is a user of INLINE_SYSCALL with 7 arguments in
> libc/sysdeps/linux/common/sync_file_range.c for MIPS64 N32, so I decided to
> only use the macros for the MIPS64 N64 case. With this patch my uClibc based
> Linux system boots up fine in qemu-system-mips64.
> 
> Signed-off-by: Waldemar Brodkorb <wbx at openadk.org>
> ---
>  libc/sysdeps/linux/mips/sysdep.h |   63 ++++++++++++++++++++++++++++++++++++++
>  1 file changed, 63 insertions(+)
> 
> diff --git a/libc/sysdeps/linux/mips/sysdep.h b/libc/sysdeps/linux/mips/sysdep.h
> index 6dba1fb..46b6c53 100644
> --- a/libc/sysdeps/linux/mips/sysdep.h
> +++ b/libc/sysdeps/linux/mips/sysdep.h
> @@ -279,6 +279,8 @@ L(syse1):
>  	_sys_result;							\
>  })
>  
> +#if _MIPS_SIM == _ABIO32 || _MIPS_SIM == _ABIN32
> +
>  /* We need to use a frame pointer for the functions in which we
>     adjust $sp around the syscall, or debug information and unwind
>     information will be $sp relative and thus wrong during the syscall.  As
> @@ -382,6 +384,67 @@ L(syse1):
>  #define __SYSCALL_CLOBBERS "$1", "$3", "$8", "$9", "$10", "$11", "$12", "$13", \
>  	"$14", "$15", "$24", "$25", "memory"
>  
> +#else /* N64 */
> +
> +#undef internal_syscall5
> +#define internal_syscall5(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5) \
> +({ 									\
> +	long _sys_result;						\
> +									\
> +	{								\
> +	register long __v0 __asm__("$2") ncs_init;			\
> +	register long __a0 __asm__("$4") = (long) arg1; 	\
> +	register long __a1 __asm__("$5") = (long) arg2; 	\
> +	register long __a2 __asm__("$6") = (long) arg3; 	\
> +	register long __a3 __asm__("$7") = (long) arg4; 	\
> +	register long __a4 __asm__("$8") = (long) arg5; 	\
> +	__asm__ __volatile__ ( 						\
> +	".set\tnoreorder\n\t" 						\
> +	cs_init								\
> +	"syscall\n\t" 							\
> +	".set\treorder" 						\
> +	: "=r" (__v0), "+r" (__a3) 					\
> +	: input, "r" (__a0), "r" (__a1), "r" (__a2), "r" (__a4)		\
> +	: __SYSCALL_CLOBBERS); 						\
> +	err = __a3;							\
> +	_sys_result = __v0;						\
> +	}								\
> +	_sys_result;							\
> +})
> +
> +#undef internal_syscall6
> +#define internal_syscall6(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5, arg6) \
> +({ 									\
> +	long _sys_result;						\
> +									\
> +	{								\
> +	register long __v0 __asm__("$2") ncs_init;			\
> +	register long __a0 __asm__("$4") = (long) arg1; 	\
> +	register long __a1 __asm__("$5") = (long) arg2; 	\
> +	register long __a2 __asm__("$6") = (long) arg3; 	\
> +	register long __a3 __asm__("$7") = (long) arg4; 	\
> +	register long __a4 __asm__("$8") = (long) arg5; 	\
> +	register long __a5 __asm__("$9") = (long) arg6; 	\
> +	__asm__ __volatile__ ( 						\
> +	".set\tnoreorder\n\t" 						\
> +	cs_init								\
> +	"syscall\n\t" 							\
> +	".set\treorder" 						\
> +	: "=r" (__v0), "+r" (__a3) 					\
> +	: input, "r" (__a0), "r" (__a1), "r" (__a2), "r" (__a4),	\
> +	  "r" (__a5)							\
> +	: __SYSCALL_CLOBBERS); 						\
> +	err = __a3;							\
> +	_sys_result = __v0;						\
> +	}								\
> +	_sys_result;							\
> +})
> +
> +#define __SYSCALL_CLOBBERS "$1", "$3", "$10", "$11", "$12", "$13", \
> +	"$14", "$15", "$24", "$25", "hi", "lo", "memory"
> +
> +#endif
> +
>  /* Pointer mangling is not yet supported for MIPS.  */
>  #define PTR_MANGLE(var) (void) (var)
>  #define PTR_DEMANGLE(var) (void) (var)
> -- 
> 1.7.10.4
> 
> _______________________________________________
> uClibc mailing list
> uClibc at uclibc.org
> http://lists.busybox.net/mailman/listinfo/uclibc
> 


More information about the uClibc mailing list