From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 24316 invoked by alias); 29 Jan 2013 18:10:58 -0000 Received: (qmail 24294 invoked by uid 22791); 29 Jan 2013 18:10:55 -0000 X-SWARE-Spam-Status: No, hits=-4.5 required=5.0 tests=AWL,BAYES_00,KHOP_RCVD_UNTRUST,KHOP_THREADED,RCVD_IN_HOSTKARMA_W,RCVD_IN_HOSTKARMA_WL X-Spam-Check-By: sourceware.org Received: from relay1.mentorg.com (HELO relay1.mentorg.com) (192.94.38.131) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 29 Jan 2013 18:10:42 +0000 Received: from svr-orw-exc-10.mgc.mentorg.com ([147.34.98.58]) by relay1.mentorg.com with esmtp id 1U0Fdp-0007cd-DE from Maciej_Rozycki@mentor.com for libc-ports@sourceware.org; Tue, 29 Jan 2013 10:10:41 -0800 Received: from SVR-IES-FEM-01.mgc.mentorg.com ([137.202.0.104]) by SVR-ORW-EXC-10.mgc.mentorg.com with Microsoft SMTPSVC(6.0.3790.4675); Tue, 29 Jan 2013 10:10:41 -0800 Received: from [172.30.5.53] (137.202.0.76) by SVR-IES-FEM-01.mgc.mentorg.com (137.202.0.104) with Microsoft SMTP Server id 14.1.289.1; Tue, 29 Jan 2013 18:10:39 +0000 Date: Tue, 29 Jan 2013 18:10:00 -0000 From: "Maciej W. Rozycki" To: "Joseph S. Myers" CC: Subject: Re: [PATCH][BZ #15054] MIPS: Fix syscall wrappers for syscall restart support In-Reply-To: Message-ID: References: User-Agent: Alpine 1.10 (DEB 962 2008-03-14) MIME-Version: 1.0 Content-Type: text/plain; charset="US-ASCII" Mailing-List: contact libc-ports-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Post: List-Help: , Sender: libc-ports-owner@sourceware.org X-SW-Source: 2013-01/txt/msg00074.txt.bz2 On Thu, 24 Jan 2013, Joseph S. Myers wrote: > > > > + register long __s0 asm("$16") __attribute__((unused)) = number; \ > > > > > > Space between __attribute__ and ((unused)), everywhere this construct > > > appears in this patch. > > > > Oops, sorry about this oversight -- presumably there needs to be a space > > between asm and () as well, right? It looks like we don't respect this > > requirement at all right now throughout the files concerned. > > Yes, there should be such a space for asm as well. OK, thanks for confirming, I'll post a change to address this separately. Here's a new version of the syscall wrappers fix, posted because I decided to make a further adjustment throughout, that is to parenthesize "number", following commit f59cba71d8486e4749742f1a703424a08a2be8a7. I hope I got the formatting right with this change. I made no further changes beyond this and ones you previously requested. OK in this form? While at it I'll mention that the patch changes the constraint used for INTERNAL_SYSCALL from "i" to "IK" -- this is because "i" accepts any constant integer and if one produced by GCC happens to be outside the range supported by hardware instructions, then GAS will be happy to expand the LI macro into a multiple-instruction sequence. This is not going to work with the restart convention concerned. The use of "I" and "K" that accept integers that are within the range of the immediate value accepted by the ADDIU and the ORI hardware instructions used by GAS in LI macro expansion guarantees that only a single instruction will ever be generated to load the integer into $v0. The compiler will signal an error when an integer outside the range of these constraints is used. This is currently a safeguard only as we don't have syscalls at the moment that have their numbers outside of ths said range. The range currently allocated for Linux syscalls is [4000,6999]. And finally, unlike with the MOVE instruction there is no need to force the 32-bit encoding of the LI instruction in the microMIPS mode, because the 16-bit microMIPS LI hardware instruction only supports numbers in the [-1,126] range that lies entirely outside the Linux syscall range quoted above. Therefore in the microMIPS mode the LI macro will expand to ADDIU or ORI just as in the standard MIPS mode; the instructions likewise have the same ranges of their immediate argument respectively. For the record -- the numbers below 4000 are not ever expected to be used in Linux, because they were originally used by other MIPS OSes (presumably RISC/OS or IRIX) and were intended to be kept reserved in Linux for the purpose of foreign ABI emulation (similarly to the iBCS subsystem and x86/Linux). That as we know has never happened and it is unlikely to ever change though. 2013-01-29 Maciej W. Rozycki * sysdeps/unix/sysv/linux/mips/mips32/sysdep.h (MOVE32): New macro. (INTERNAL_SYSCALL_NCS): Use it. Rewrite to respect the syscall restart convention. (INTERNAL_SYSCALL): Rewrite to respect the syscall restart convention. (internal_syscall0, internal_syscall1): Likewise. (internal_syscall2, internal_syscall3): Likewise. (internal_syscall4, internal_syscall5): Likewise. (internal_syscall6, internal_syscall7): Likewise. * sysdeps/unix/sysv/linux/mips/mips64/n32/sysdep.h (MOVE32): New macro. (INTERNAL_SYSCALL_NCS): Use it. Rewrite to respect the syscall restart convention. (INTERNAL_SYSCALL): Rewrite to respect the syscall restart convention. (internal_syscall0, internal_syscall1): Likewise. (internal_syscall2, internal_syscall3): Likewise. (internal_syscall4, internal_syscall5): Likewise. (internal_syscall6): Likewise. * sysdeps/unix/sysv/linux/mips/mips64/n64/sysdep.h (MOVE32): New macro. (INTERNAL_SYSCALL_NCS): Use it. Rewrite to respect the syscall restart convention. (INTERNAL_SYSCALL): Rewrite to respect the syscall restart convention. (internal_syscall0, internal_syscall1): Likewise. (internal_syscall2, internal_syscall3): Likewise. (internal_syscall4, internal_syscall5): Likewise. (internal_syscall6): Likewise. Maciej glibc-mips-syscall-restart.diff Index: ports/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h =================================================================== --- glibc-fsf-trunk-quilt.orig/ports/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h 2013-01-29 11:21:13.000000000 +0000 +++ ports/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h 2013-01-29 16:36:53.127475050 +0000 @@ -67,25 +67,46 @@ #undef INTERNAL_SYSCALL_ERRNO #define INTERNAL_SYSCALL_ERRNO(val, err) ((void) (err), val) +/* Note that the Linux syscall restart convention requires the instruction + immediately preceding SYSCALL to initialize $v0 with the syscall number. + Then if a restart triggers, $v0 will have been clobbered by the syscall + interrupted, and needs to be reinititalized. The kernel will decrement + the PC by 4 before switching back to the user mode so that $v0 has been + reloaded before SYSCALL is executed again. This implies the place $v0 + is loaded from must be preserved across a syscall, e.g. an immediate, + static register, stack slot, etc. This also means we have to force a + 32-bit encoding of the microMIPS MOVE instruction if one is used. */ + +#ifdef __mips_micromips +# define MOVE32 "move32" +#else +# define MOVE32 "move" +#endif + #undef INTERNAL_SYSCALL -#define INTERNAL_SYSCALL(name, err, nr, args...) \ - internal_syscall##nr (, "li\t$2, %2\t\t\t# " #name "\n\t", \ - "i" (SYS_ify (name)), err, args) +#define INTERNAL_SYSCALL(name, err, nr, args...) \ + internal_syscall##nr ("li\t%0, %2\t\t\t# " #name "\n\t", \ + "IK" (SYS_ify (name)), \ + 0, err, args) #undef INTERNAL_SYSCALL_NCS -#define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \ - internal_syscall##nr (= number, , "r" (__v0), err, args) +#define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \ + internal_syscall##nr (MOVE32 "\t%0, %2\n\t", \ + "r" (__s0), \ + number, err, args) -#define internal_syscall0(ncs_init, cs_init, input, err, dummy...) \ +#define internal_syscall0(v0_init, input, number, err, dummy...) \ ({ \ long _sys_result; \ \ { \ - register long __v0 asm("$2") ncs_init; \ + register long __s0 asm("$16") __attribute__ ((unused)) \ + = (number); \ + register long __v0 asm("$2"); \ register long __a3 asm("$7"); \ __asm__ volatile ( \ ".set\tnoreorder\n\t" \ - cs_init \ + v0_init \ "syscall\n\t" \ ".set reorder" \ : "=r" (__v0), "=r" (__a3) \ @@ -97,17 +118,19 @@ _sys_result; \ }) -#define internal_syscall1(ncs_init, cs_init, input, err, arg1) \ +#define internal_syscall1(v0_init, input, number, err, arg1) \ ({ \ long _sys_result; \ \ { \ - register long __v0 asm("$2") ncs_init; \ + register long __s0 asm("$16") __attribute__ ((unused)) \ + = (number); \ + register long __v0 asm("$2"); \ register long __a0 asm("$4") = (long) (arg1); \ register long __a3 asm("$7"); \ __asm__ volatile ( \ ".set\tnoreorder\n\t" \ - cs_init \ + v0_init \ "syscall\n\t" \ ".set reorder" \ : "=r" (__v0), "=r" (__a3) \ @@ -119,20 +142,22 @@ _sys_result; \ }) -#define internal_syscall2(ncs_init, cs_init, input, err, arg1, arg2) \ +#define internal_syscall2(v0_init, input, number, err, arg1, arg2) \ ({ \ long _sys_result; \ \ { \ - register long __v0 asm("$2") ncs_init; \ + register long __s0 asm("$16") __attribute__ ((unused)) \ + = (number); \ + register long __v0 asm("$2"); \ register long __a0 asm("$4") = (long) (arg1); \ register long __a1 asm("$5") = (long) (arg2); \ register long __a3 asm("$7"); \ __asm__ volatile ( \ ".set\tnoreorder\n\t" \ - cs_init \ + v0_init \ "syscall\n\t" \ - ".set\treorder" \ + ".set\treorder" \ : "=r" (__v0), "=r" (__a3) \ : input, "r" (__a0), "r" (__a1) \ : __SYSCALL_CLOBBERS); \ @@ -142,21 +167,24 @@ _sys_result; \ }) -#define internal_syscall3(ncs_init, cs_init, input, err, arg1, arg2, arg3)\ +#define internal_syscall3(v0_init, input, number, err, \ + arg1, arg2, arg3) \ ({ \ long _sys_result; \ \ { \ - register long __v0 asm("$2") ncs_init; \ + register long __s0 asm("$16") __attribute__ ((unused)) \ + = (number); \ + register long __v0 asm("$2"); \ 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"); \ __asm__ volatile ( \ ".set\tnoreorder\n\t" \ - cs_init \ + v0_init \ "syscall\n\t" \ - ".set\treorder" \ + ".set\treorder" \ : "=r" (__v0), "=r" (__a3) \ : input, "r" (__a0), "r" (__a1), "r" (__a2) \ : __SYSCALL_CLOBBERS); \ @@ -166,21 +194,24 @@ _sys_result; \ }) -#define internal_syscall4(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4)\ +#define internal_syscall4(v0_init, input, number, err, \ + arg1, arg2, arg3, arg4) \ ({ \ long _sys_result; \ \ { \ - register long __v0 asm("$2") ncs_init; \ + register long __s0 asm("$16") __attribute__ ((unused)) \ + = (number); \ + register long __v0 asm("$2"); \ 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); \ __asm__ volatile ( \ ".set\tnoreorder\n\t" \ - cs_init \ + v0_init \ "syscall\n\t" \ - ".set\treorder" \ + ".set\treorder" \ : "=r" (__v0), "+r" (__a3) \ : input, "r" (__a0), "r" (__a1), "r" (__a2) \ : __SYSCALL_CLOBBERS); \ @@ -197,13 +228,16 @@ #define FORCE_FRAME_POINTER \ void *volatile __fp_force __attribute__ ((unused)) = alloca (4) -#define internal_syscall5(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5)\ +#define internal_syscall5(v0_init, input, number, err, \ + arg1, arg2, arg3, arg4, arg5) \ ({ \ long _sys_result; \ \ FORCE_FRAME_POINTER; \ { \ - register long __v0 asm("$2") ncs_init; \ + register long __s0 asm("$16") __attribute__ ((unused)) \ + = (number); \ + register long __v0 asm("$2"); \ register long __a0 asm("$4") = (long) (arg1); \ register long __a1 asm("$5") = (long) (arg2); \ register long __a2 asm("$6") = (long) (arg3); \ @@ -212,10 +246,10 @@ ".set\tnoreorder\n\t" \ "subu\t$29, 32\n\t" \ "sw\t%6, 16($29)\n\t" \ - cs_init \ + v0_init \ "syscall\n\t" \ "addiu\t$29, 32\n\t" \ - ".set\treorder" \ + ".set\treorder" \ : "=r" (__v0), "+r" (__a3) \ : input, "r" (__a0), "r" (__a1), "r" (__a2), \ "r" ((long) (arg5)) \ @@ -226,13 +260,16 @@ _sys_result; \ }) -#define internal_syscall6(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5, arg6)\ +#define internal_syscall6(v0_init, input, number, err, \ + arg1, arg2, arg3, arg4, arg5, arg6) \ ({ \ long _sys_result; \ \ FORCE_FRAME_POINTER; \ { \ - register long __v0 asm("$2") ncs_init; \ + register long __s0 asm("$16") __attribute__ ((unused)) \ + = (number); \ + register long __v0 asm("$2"); \ register long __a0 asm("$4") = (long) (arg1); \ register long __a1 asm("$5") = (long) (arg2); \ register long __a2 asm("$6") = (long) (arg3); \ @@ -242,10 +279,10 @@ "subu\t$29, 32\n\t" \ "sw\t%6, 16($29)\n\t" \ "sw\t%7, 20($29)\n\t" \ - cs_init \ + v0_init \ "syscall\n\t" \ "addiu\t$29, 32\n\t" \ - ".set\treorder" \ + ".set\treorder" \ : "=r" (__v0), "+r" (__a3) \ : input, "r" (__a0), "r" (__a1), "r" (__a2), \ "r" ((long) (arg5)), "r" ((long) (arg6)) \ @@ -256,13 +293,16 @@ _sys_result; \ }) -#define internal_syscall7(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5, arg6, arg7)\ +#define internal_syscall7(v0_init, input, number, err, \ + arg1, arg2, arg3, arg4, arg5, arg6, arg7) \ ({ \ long _sys_result; \ \ FORCE_FRAME_POINTER; \ { \ - register long __v0 asm("$2") ncs_init; \ + register long __s0 asm("$16") __attribute__ ((unused)) \ + = (number); \ + register long __v0 asm("$2"); \ register long __a0 asm("$4") = (long) (arg1); \ register long __a1 asm("$5") = (long) (arg2); \ register long __a2 asm("$6") = (long) (arg3); \ @@ -273,10 +313,10 @@ "sw\t%6, 16($29)\n\t" \ "sw\t%7, 20($29)\n\t" \ "sw\t%8, 24($29)\n\t" \ - cs_init \ + v0_init \ "syscall\n\t" \ "addiu\t$29, 32\n\t" \ - ".set\treorder" \ + ".set\treorder" \ : "=r" (__v0), "+r" (__a3) \ : input, "r" (__a0), "r" (__a1), "r" (__a2), \ "r" ((long) (arg5)), "r" ((long) (arg6)), "r" ((long) (arg7)) \ Index: ports/sysdeps/unix/sysv/linux/mips/mips64/n32/sysdep.h =================================================================== --- glibc-fsf-trunk-quilt.orig/ports/sysdeps/unix/sysv/linux/mips/mips64/n32/sysdep.h 2013-01-29 13:40:36.000000000 +0000 +++ ports/sysdeps/unix/sysv/linux/mips/mips64/n32/sysdep.h 2013-01-29 16:38:56.436531593 +0000 @@ -71,25 +71,46 @@ #undef INTERNAL_SYSCALL_ERRNO #define INTERNAL_SYSCALL_ERRNO(val, err) ((void) (err), val) +/* Note that the Linux syscall restart convention requires the instruction + immediately preceding SYSCALL to initialize $v0 with the syscall number. + Then if a restart triggers, $v0 will have been clobbered by the syscall + interrupted, and needs to be reinititalized. The kernel will decrement + the PC by 4 before switching back to the user mode so that $v0 has been + reloaded before SYSCALL is executed again. This implies the place $v0 + is loaded from must be preserved across a syscall, e.g. an immediate, + static register, stack slot, etc. This also means we have to force a + 32-bit encoding of the microMIPS MOVE instruction if one is used. */ + +#ifdef __mips_micromips +# define MOVE32 "move32" +#else +# define MOVE32 "move" +#endif + #undef INTERNAL_SYSCALL -#define INTERNAL_SYSCALL(name, err, nr, args...) \ - internal_syscall##nr (, "li\t$2, %2\t\t\t# " #name "\n\t", \ - "i" (SYS_ify (name)), err, args) +#define INTERNAL_SYSCALL(name, err, nr, args...) \ + internal_syscall##nr ("li\t%0, %2\t\t\t# " #name "\n\t", \ + "IK" (SYS_ify (name)), \ + 0, err, args) #undef INTERNAL_SYSCALL_NCS -#define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \ - internal_syscall##nr (= number, , "r" (__v0), err, args) +#define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \ + internal_syscall##nr (MOVE32 "\t%0, %2\n\t", \ + "r" (__s0), \ + number, err, args) -#define internal_syscall0(ncs_init, cs_init, input, err, dummy...) \ +#define internal_syscall0(v0_init, input, number, err, dummy...) \ ({ \ long _sys_result; \ \ { \ - register long long __v0 asm("$2") ncs_init; \ + register long long __s0 asm("$16") __attribute__((unused)) \ + = (number); \ + register long long __v0 asm("$2"); \ register long long __a3 asm("$7"); \ __asm__ volatile ( \ ".set\tnoreorder\n\t" \ - cs_init \ + v0_init \ "syscall\n\t" \ ".set reorder" \ : "=r" (__v0), "=r" (__a3) \ @@ -101,17 +122,19 @@ _sys_result; \ }) -#define internal_syscall1(ncs_init, cs_init, input, err, arg1) \ +#define internal_syscall1(v0_init, input, number, err, arg1) \ ({ \ long _sys_result; \ \ { \ - register long long __v0 asm("$2") ncs_init; \ + register long long __s0 asm("$16") __attribute__((unused)) \ + = (number); \ + register long long __v0 asm("$2"); \ register long long __a0 asm("$4") = ARGIFY (arg1); \ register long long __a3 asm("$7"); \ __asm__ volatile ( \ ".set\tnoreorder\n\t" \ - cs_init \ + v0_init \ "syscall\n\t" \ ".set reorder" \ : "=r" (__v0), "=r" (__a3) \ @@ -123,18 +146,20 @@ _sys_result; \ }) -#define internal_syscall2(ncs_init, cs_init, input, err, arg1, arg2) \ +#define internal_syscall2(v0_init, input, number, err, arg1, arg2) \ ({ \ long _sys_result; \ \ { \ - register long long __v0 asm("$2") ncs_init; \ + register long long __s0 asm("$16") __attribute__((unused)) \ + = (number); \ + register long long __v0 asm("$2"); \ register long long __a0 asm("$4") = ARGIFY (arg1); \ register long long __a1 asm("$5") = ARGIFY (arg2); \ register long long __a3 asm("$7"); \ __asm__ volatile ( \ ".set\tnoreorder\n\t" \ - cs_init \ + v0_init \ "syscall\n\t" \ ".set\treorder" \ : "=r" (__v0), "=r" (__a3) \ @@ -146,19 +171,22 @@ _sys_result; \ }) -#define internal_syscall3(ncs_init, cs_init, input, err, arg1, arg2, arg3) \ +#define internal_syscall3(v0_init, input, number, err, \ + arg1, arg2, arg3) \ ({ \ long _sys_result; \ \ { \ - register long long __v0 asm("$2") ncs_init; \ + register long long __s0 asm("$16") __attribute__((unused)) \ + = (number); \ + register long long __v0 asm("$2"); \ register long long __a0 asm("$4") = ARGIFY (arg1); \ register long long __a1 asm("$5") = ARGIFY (arg2); \ register long long __a2 asm("$6") = ARGIFY (arg3); \ register long long __a3 asm("$7"); \ __asm__ volatile ( \ ".set\tnoreorder\n\t" \ - cs_init \ + v0_init \ "syscall\n\t" \ ".set\treorder" \ : "=r" (__v0), "=r" (__a3) \ @@ -170,19 +198,22 @@ _sys_result; \ }) -#define internal_syscall4(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4) \ +#define internal_syscall4(v0_init, input, number, err, \ + arg1, arg2, arg3, arg4) \ ({ \ long _sys_result; \ \ { \ - register long long __v0 asm("$2") ncs_init; \ + register long long __s0 asm("$16") __attribute__((unused)) \ + = (number); \ + register long long __v0 asm("$2"); \ register long long __a0 asm("$4") = ARGIFY (arg1); \ register long long __a1 asm("$5") = ARGIFY (arg2); \ register long long __a2 asm("$6") = ARGIFY (arg3); \ register long long __a3 asm("$7") = ARGIFY (arg4); \ __asm__ volatile ( \ ".set\tnoreorder\n\t" \ - cs_init \ + v0_init \ "syscall\n\t" \ ".set\treorder" \ : "=r" (__v0), "+r" (__a3) \ @@ -194,12 +225,15 @@ _sys_result; \ }) -#define internal_syscall5(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5) \ +#define internal_syscall5(v0_init, input, number, err, \ + arg1, arg2, arg3, arg4, arg5) \ ({ \ long _sys_result; \ \ { \ - register long long __v0 asm("$2") ncs_init; \ + register long long __s0 asm("$16") __attribute__((unused)) \ + = (number); \ + register long long __v0 asm("$2"); \ register long long __a0 asm("$4") = ARGIFY (arg1); \ register long long __a1 asm("$5") = ARGIFY (arg2); \ register long long __a2 asm("$6") = ARGIFY (arg3); \ @@ -207,7 +241,7 @@ register long long __a4 asm("$8") = ARGIFY (arg5); \ __asm__ volatile ( \ ".set\tnoreorder\n\t" \ - cs_init \ + v0_init \ "syscall\n\t" \ ".set\treorder" \ : "=r" (__v0), "+r" (__a3) \ @@ -219,12 +253,15 @@ _sys_result; \ }) -#define internal_syscall6(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5, arg6) \ +#define internal_syscall6(v0_init, input, number, err, \ + arg1, arg2, arg3, arg4, arg5, arg6) \ ({ \ long _sys_result; \ \ { \ - register long long __v0 asm("$2") ncs_init; \ + register long long __s0 asm("$16") __attribute__((unused)) \ + = (number); \ + register long long __v0 asm("$2"); \ register long long __a0 asm("$4") = ARGIFY (arg1); \ register long long __a1 asm("$5") = ARGIFY (arg2); \ register long long __a2 asm("$6") = ARGIFY (arg3); \ @@ -233,7 +270,7 @@ register long long __a5 asm("$9") = ARGIFY (arg6); \ __asm__ volatile ( \ ".set\tnoreorder\n\t" \ - cs_init \ + v0_init \ "syscall\n\t" \ ".set\treorder" \ : "=r" (__v0), "+r" (__a3) \ Index: ports/sysdeps/unix/sysv/linux/mips/mips64/n64/sysdep.h =================================================================== --- glibc-fsf-trunk-quilt.orig/ports/sysdeps/unix/sysv/linux/mips/mips64/n64/sysdep.h 2013-01-29 13:40:36.000000000 +0000 +++ ports/sysdeps/unix/sysv/linux/mips/mips64/n64/sysdep.h 2013-01-29 16:39:20.336868564 +0000 @@ -67,25 +67,46 @@ #undef INTERNAL_SYSCALL_ERRNO #define INTERNAL_SYSCALL_ERRNO(val, err) ((void) (err), val) +/* Note that the Linux syscall restart convention requires the instruction + immediately preceding SYSCALL to initialize $v0 with the syscall number. + Then if a restart triggers, $v0 will have been clobbered by the syscall + interrupted, and needs to be reinititalized. The kernel will decrement + the PC by 4 before switching back to the user mode so that $v0 has been + reloaded before SYSCALL is executed again. This implies the place $v0 + is loaded from must be preserved across a syscall, e.g. an immediate, + static register, stack slot, etc. This also means we have to force a + 32-bit encoding of the microMIPS MOVE instruction if one is used. */ + +#ifdef __mips_micromips +# define MOVE32 "move32" +#else +# define MOVE32 "move" +#endif + #undef INTERNAL_SYSCALL -#define INTERNAL_SYSCALL(name, err, nr, args...) \ - internal_syscall##nr (, "li\t$2, %2\t\t\t# " #name "\n\t", \ - "i" (SYS_ify (name)), err, args) +#define INTERNAL_SYSCALL(name, err, nr, args...) \ + internal_syscall##nr ("li\t%0, %2\t\t\t# " #name "\n\t", \ + "IK" (SYS_ify (name)), \ + 0, err, args) #undef INTERNAL_SYSCALL_NCS -#define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \ - internal_syscall##nr (= number, , "r" (__v0), err, args) +#define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \ + internal_syscall##nr (MOVE32 "\t%0, %2\n\t", \ + "r" (__s0), \ + number, err, args) -#define internal_syscall0(ncs_init, cs_init, input, err, dummy...) \ +#define internal_syscall0(v0_init, input, number, err, dummy...) \ ({ \ long _sys_result; \ \ { \ - register long __v0 asm("$2") ncs_init; \ + register long __s0 asm("$16") __attribute__ ((unused)) \ + = (number); \ + register long __v0 asm("$2"); \ register long __a3 asm("$7"); \ __asm__ volatile ( \ ".set\tnoreorder\n\t" \ - cs_init \ + v0_init \ "syscall\n\t" \ ".set reorder" \ : "=r" (__v0), "=r" (__a3) \ @@ -97,17 +118,19 @@ _sys_result; \ }) -#define internal_syscall1(ncs_init, cs_init, input, err, arg1) \ +#define internal_syscall1(v0_init, input, number, err, arg1) \ ({ \ long _sys_result; \ \ { \ - register long __v0 asm("$2") ncs_init; \ + register long __s0 asm("$16") __attribute__ ((unused)) \ + = (number); \ + register long __v0 asm("$2"); \ register long __a0 asm("$4") = (long) (arg1); \ register long __a3 asm("$7"); \ __asm__ volatile ( \ ".set\tnoreorder\n\t" \ - cs_init \ + v0_init \ "syscall\n\t" \ ".set reorder" \ : "=r" (__v0), "=r" (__a3) \ @@ -119,18 +142,20 @@ _sys_result; \ }) -#define internal_syscall2(ncs_init, cs_init, input, err, arg1, arg2) \ +#define internal_syscall2(v0_init, input, number, err, arg1, arg2) \ ({ \ long _sys_result; \ \ { \ - register long __v0 asm("$2") ncs_init; \ + register long __s0 asm("$16") __attribute__ ((unused)) \ + = (number); \ + register long __v0 asm("$2"); \ register long __a0 asm("$4") = (long) (arg1); \ register long __a1 asm("$5") = (long) (arg2); \ register long __a3 asm("$7"); \ __asm__ volatile ( \ ".set\tnoreorder\n\t" \ - cs_init \ + v0_init \ "syscall\n\t" \ ".set\treorder" \ : "=r" (__v0), "=r" (__a3) \ @@ -142,19 +167,22 @@ _sys_result; \ }) -#define internal_syscall3(ncs_init, cs_init, input, err, arg1, arg2, arg3) \ +#define internal_syscall3(v0_init, input, number, err, \ + arg1, arg2, arg3) \ ({ \ long _sys_result; \ \ { \ - register long __v0 asm("$2") ncs_init; \ + register long __s0 asm("$16") __attribute__ ((unused)) \ + = (number); \ + register long __v0 asm("$2"); \ 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"); \ __asm__ volatile ( \ ".set\tnoreorder\n\t" \ - cs_init \ + v0_init \ "syscall\n\t" \ ".set\treorder" \ : "=r" (__v0), "=r" (__a3) \ @@ -166,19 +194,22 @@ _sys_result; \ }) -#define internal_syscall4(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4) \ +#define internal_syscall4(v0_init, input, number, err, \ + arg1, arg2, arg3, arg4) \ ({ \ long _sys_result; \ \ { \ - register long __v0 asm("$2") ncs_init; \ + register long __s0 asm("$16") __attribute__ ((unused)) \ + = (number); \ + register long __v0 asm("$2"); \ 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); \ __asm__ volatile ( \ ".set\tnoreorder\n\t" \ - cs_init \ + v0_init \ "syscall\n\t" \ ".set\treorder" \ : "=r" (__v0), "+r" (__a3) \ @@ -190,12 +221,15 @@ _sys_result; \ }) -#define internal_syscall5(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5) \ +#define internal_syscall5(v0_init, input, number, err, \ + arg1, arg2, arg3, arg4, arg5) \ ({ \ long _sys_result; \ \ { \ - register long __v0 asm("$2") ncs_init; \ + register long __s0 asm("$16") __attribute__ ((unused)) \ + = (number); \ + register long __v0 asm("$2"); \ register long __a0 asm("$4") = (long) (arg1); \ register long __a1 asm("$5") = (long) (arg2); \ register long __a2 asm("$6") = (long) (arg3); \ @@ -203,7 +237,7 @@ register long __a4 asm("$8") = (long) (arg5); \ __asm__ volatile ( \ ".set\tnoreorder\n\t" \ - cs_init \ + v0_init \ "syscall\n\t" \ ".set\treorder" \ : "=r" (__v0), "+r" (__a3) \ @@ -215,12 +249,15 @@ _sys_result; \ }) -#define internal_syscall6(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5, arg6) \ +#define internal_syscall6(v0_init, input, number, err, \ + arg1, arg2, arg3, arg4, arg5, arg6) \ ({ \ long _sys_result; \ \ { \ - register long __v0 asm("$2") ncs_init; \ + register long __s0 asm("$16") __attribute__ ((unused)) \ + = (number); \ + register long __v0 asm("$2"); \ register long __a0 asm("$4") = (long) (arg1); \ register long __a1 asm("$5") = (long) (arg2); \ register long __a2 asm("$6") = (long) (arg3); \ @@ -229,7 +266,7 @@ register long __a5 asm("$9") = (long) (arg6); \ __asm__ volatile ( \ ".set\tnoreorder\n\t" \ - cs_init \ + v0_init \ "syscall\n\t" \ ".set\treorder" \ : "=r" (__v0), "+r" (__a3) \