[PATCH] MIPS64 N64 fork is broken

Bernhard Reutner-Fischer rep.dot.nop at gmail.com
Wed Jan 22 20:06:00 UTC 2014


On 20 January 2014 09:37, Waldemar Brodkorb <wbx at openadk.org> wrote:
> 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.

The mips sysdeps looks highly repetitive, it would be nice to massage it to use
something like the i386 variant. Maybe you want to do that?

I am applying the below for now though, thanks!
cheers,
>>
>> 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
>>
> _______________________________________________
> uClibc mailing list
> uClibc at uclibc.org
> http://lists.busybox.net/mailman/listinfo/uclibc


More information about the uClibc mailing list