--- /dev/null
+From c8f9e946bc2a0a42e84b5f97f272932de6485b54 Mon Sep 17 00:00:00 2001
+From: Kevin Cernekee <cernekee@gmail.com>
+Date: Tue, 5 Jun 2012 15:05:20 -0700
+Subject: [PATCH] MIPS: Use $a0 instead of $v0 for __syscall_error() argument
+
+$a0 is saved across _dl_runtime_resolve(); $v0 is not. Unfortunately,
+__syscall_error() uses $v0 for its argument, not $a0 as is the MIPS ABI
+standard. This means that if lazy binding was used for __syscall_error(),
+the errno value in $v0 could get corrupted.
+
+The problem can be easily seen in testcases where syscalls in librt fail;
+when librt tries to call __syscall_error() in libc, the argument gets
+lost and errno gets set to a bogus value:
+
+ # ./tst-mqueue1 ; echo $?
+ mq_receive on O_WRONLY mqd_t did not fail with EBADF: Unknown error 2004684208
+ 1
+ # ./tst-mqueue2 ; echo $?
+ mq_timedreceive with too small msg_len did not fail with EMSGSIZE: Unknown error 1997360560
+ 1
+ # ./tst-mqueue4 ; echo $?
+ mq_timedsend did not fail with ETIMEDOUT: Unknown error 2008747440
+ 1
+
+When _dl_runtime_resolve() was taken out of the equation, the same test
+cases passed:
+
+ # LD_BIND_NOW=y ./tst-mqueue1 ; echo $?
+ 0
+ # LD_BIND_NOW=y ./tst-mqueue2 ; echo $?
+ 0
+ # LD_BIND_NOW=y ./tst-mqueue4 ; echo $?
+ 0
+
+Changing __syscall_error() to look at $a0 instead of $v0 fixed the
+problem.
+
+(Note that there is also a "__syscall_error.c" file which presumably
+uses the standard C calling conventions, but I do not think it is used
+on MIPS.)
+
+Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
+Signed-off-by: Bernhard Reutner-Fischer <rep.dot.nop@gmail.com>
+---
+ libc/sysdeps/linux/mips/syscall_error.S | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/libc/sysdeps/linux/mips/syscall_error.S b/libc/sysdeps/linux/mips/syscall_error.S
+index 51a8efa..0cc20da 100644
+--- a/libc/sysdeps/linux/mips/syscall_error.S
++++ b/libc/sysdeps/linux/mips/syscall_error.S
+@@ -43,7 +43,7 @@ ENTRY(__syscall_error)
+ #ifdef __PIC__
+ SAVE_GP(GPOFF)
+ #endif
+- REG_S v0, V0OFF(sp)
++ REG_S a0, V0OFF(sp)
+ REG_S ra, RAOFF(sp)
+
+ /* Find our per-thread errno address */
+--
+1.7.10.4
+