From patchwork Sat Dec 21 12:18:29 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Waldemar Brodkorb X-Patchwork-Id: 304409 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from whitealder.osuosl.org (whitealder.osuosl.org [140.211.166.138]) by ozlabs.org (Postfix) with ESMTP id A5DF92C00A7 for ; Sat, 21 Dec 2013 23:22:04 +1100 (EST) Received: from localhost (localhost [127.0.0.1]) by whitealder.osuosl.org (Postfix) with ESMTP id 366428BC24; Sat, 21 Dec 2013 12:22:02 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from whitealder.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id e+1es5u7Xsi9; Sat, 21 Dec 2013 12:22:00 +0000 (UTC) Received: from ash.osuosl.org (ash.osuosl.org [140.211.166.34]) by whitealder.osuosl.org (Postfix) with ESMTP id 5F7328A361; Sat, 21 Dec 2013 12:22:00 +0000 (UTC) X-Original-To: uclibc@lists.busybox.net Delivered-To: uclibc@osuosl.org Received: from whitealder.osuosl.org (whitealder.osuosl.org [140.211.166.138]) by ash.osuosl.org (Postfix) with ESMTP id 593241BFAA8 for ; Sat, 21 Dec 2013 12:21:59 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by whitealder.osuosl.org (Postfix) with ESMTP id 56C798A361 for ; Sat, 21 Dec 2013 12:21:59 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from whitealder.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id ccdf6Hl0om1z for ; Sat, 21 Dec 2013 12:21:57 +0000 (UTC) X-Greylist: from auto-whitelisted by SQLgrey-1.7.6 Received: from helium.waldemar-brodkorb.de (helium.waldemar-brodkorb.de [89.238.66.15]) by whitealder.osuosl.org (Postfix) with ESMTPS id 889BC8171D for ; Sat, 21 Dec 2013 12:21:57 +0000 (UTC) Received: by helium.waldemar-brodkorb.de (Postfix, from userid 1000) id 10AC210152; Sat, 21 Dec 2013 13:18:29 +0100 (CET) Date: Sat, 21 Dec 2013 13:18:29 +0100 From: Waldemar Brodkorb To: uclibc@uclibc.org Subject: [PATCH] MIPS64 N64 fork is broken Message-ID: <20131221121829.GA14600@waldemar-brodkorb.de> MIME-Version: 1.0 Content-Disposition: inline X-Operating-System: Linux 3.2.0-4-amd64 x86_64 User-Agent: Mutt/1.5.21 (2010-09-15) X-BeenThere: uclibc@uclibc.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Discussion and development of uClibc \(the embedded C library\)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: uclibc-bounces@uclibc.org Sender: uclibc-bounces@uclibc.org 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 --- 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)