This is the mail archive of the libc-ports@sources.redhat.com mailing list for the libc-ports project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH][BZ #15054] MIPS: Fix syscall wrappers for syscall restart support


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  <macro@codesourcery.com>

	* 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)					\


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]