mailing list of musl libc
 help / color / Atom feed
* [musl] [PATCH] fix mips syscall asm regressions and kernel bug
@ 2020-03-11 23:09 Rich Felker
  2020-03-14  0:12 ` Rich Felker
  0 siblings, 1 reply; 2+ messages in thread
From: Rich Felker @ 2020-03-11 23:09 UTC (permalink / raw)
  To: musl; +Cc: Andreas Dröscher

[-- Attachment #1: Type: text/plain, Size: 0 bytes --]



[-- Attachment #2: 0001-revert-previous-changes-to-mips64-n32-syscall-asm-co.patch --]
[-- Type: text/plain, Size: 8166 bytes --]

From a6ab25ff9885a810c8ceba42b9b1ea3badaae879 Mon Sep 17 00:00:00 2001
From: Rich Felker <dalias@aerifal.cx>
Date: Wed, 11 Mar 2020 18:43:11 -0400
Subject: [PATCH 1/4] revert previous changes to mips64/n32 syscall asm
 constraints

effectivly revert commit ddc7c4f936c7a90781072f10dbaa122007e939d0
which was wrong; it caused a major regression on Linux versions prior
to 2.6.36. old kernels did not properly preserve r2 across syscall
restart, and instead restarted with the instruction right before
syscall, imposing a contract that the previous instruction must load
r2 from an immediate or a register (or memory) not clobbered by the
syscall.

since other changes were made since, this is not a direct revert, only
a functional one. the improved style and removal of redundant
constraints are kept.
---
 arch/mips64/syscall_arch.h  | 56 +++++++++++++++++-----------------
 arch/mipsn32/syscall_arch.h | 61 ++++++++++++++++++++-----------------
 2 files changed, 61 insertions(+), 56 deletions(-)

diff --git a/arch/mips64/syscall_arch.h b/arch/mips64/syscall_arch.h
index 69c429b8..8f6758d3 100644
--- a/arch/mips64/syscall_arch.h
+++ b/arch/mips64/syscall_arch.h
@@ -16,11 +16,11 @@
 static inline long __syscall0(long n)
 {
 	register long r7 __asm__("$7");
-	register long r2 __asm__("$2") = n;
+	register long r2 __asm__("$2");
 	__asm__ __volatile__ (
-		"syscall"
-		: "+&r"(r2), "=r"(r7)
-		:
+		"daddu $2,$0,%2 ; syscall"
+		: "=&r"(r2), "=r"(r7)
+		: "ir"(n)
 		: SYSCALL_CLOBBERLIST);
 	return r7 ? -r2 : r2;
 }
@@ -29,11 +29,11 @@ static inline long __syscall1(long n, long a)
 {
 	register long r4 __asm__("$4") = a;
 	register long r7 __asm__("$7");
-	register long r2 __asm__("$2") = n;
+	register long r2 __asm__("$2");
 	__asm__ __volatile__ (
-		"syscall"
-		: "+&r"(r2), "=r"(r7)
-		: "r"(r4)
+		"daddu $2,$0,%2 ; syscall"
+		: "=&r"(r2), "=r"(r7)
+		: "ir"(n), "r"(r4)
 		: SYSCALL_CLOBBERLIST);
 	return r7 ? -r2 : r2;
 }
@@ -43,12 +43,12 @@ static inline long __syscall2(long n, long a, long b)
 	register long r4 __asm__("$4") = a;
 	register long r5 __asm__("$5") = b;
 	register long r7 __asm__("$7");
-	register long r2 __asm__("$2") = n;
+	register long r2 __asm__("$2");
 
 	__asm__ __volatile__ (
-		"syscall"
-		: "+&r"(r2), "=r"(r7)
-		: "r"(r4), "r"(r5)
+		"daddu $2,$0,%2 ; syscall"
+		: "=&r"(r2), "=r"(r7)
+		: "ir"(n), "r"(r4), "r"(r5)
 		: SYSCALL_CLOBBERLIST);
 	return r7 ? -r2 : r2;
 }
@@ -59,12 +59,12 @@ static inline long __syscall3(long n, long a, long b, long c)
 	register long r5 __asm__("$5") = b;
 	register long r6 __asm__("$6") = c;
 	register long r7 __asm__("$7");
-	register long r2 __asm__("$2") = n;
+	register long r2 __asm__("$2");
 
 	__asm__ __volatile__ (
-		"syscall"
-		: "+&r"(r2), "=r"(r7)
-		: "r"(r4), "r"(r5), "r"(r6)
+		"daddu $2,$0,%2 ; syscall"
+		: "=&r"(r2), "=r"(r7)
+		: "ir"(n), "r"(r4), "r"(r5), "r"(r6)
 		: SYSCALL_CLOBBERLIST);
 	return r7 ? -r2 : r2;
 }
@@ -75,12 +75,12 @@ static inline long __syscall4(long n, long a, long b, long c, long d)
 	register long r5 __asm__("$5") = b;
 	register long r6 __asm__("$6") = c;
 	register long r7 __asm__("$7") = d;
-	register long r2 __asm__("$2") = n;
+	register long r2 __asm__("$2");
 
 	__asm__ __volatile__ (
-		"syscall"
-		: "+&r"(r2), "+r"(r7)
-		: "r"(r4), "r"(r5), "r"(r6)
+		"daddu $2,$0,%2 ; syscall"
+		: "=&r"(r2), "+r"(r7)
+		: "ir"(n), "r"(r4), "r"(r5), "r"(r6)
 		: SYSCALL_CLOBBERLIST);
 	return r7 ? -r2 : r2;
 }
@@ -92,12 +92,12 @@ static inline long __syscall5(long n, long a, long b, long c, long d, long e)
 	register long r6 __asm__("$6") = c;
 	register long r7 __asm__("$7") = d;
 	register long r8 __asm__("$8") = e;
-	register long r2 __asm__("$2") = n;
+	register long r2 __asm__("$2");
 
 	__asm__ __volatile__ (
-		"syscall"
-		: "+&r"(r2), "+r"(r7)
-		: "r"(r4), "r"(r5), "r"(r6), "r"(r8)
+		"daddu $2,$0,%2 ; syscall"
+		: "=&r"(r2), "+r"(r7)
+		: "ir"(n), "r"(r4), "r"(r5), "r"(r6), "r"(r8)
 		: SYSCALL_CLOBBERLIST);
 	return r7 ? -r2 : r2;
 }
@@ -110,12 +110,12 @@ static inline long __syscall6(long n, long a, long b, long c, long d, long e, lo
 	register long r7 __asm__("$7") = d;
 	register long r8 __asm__("$8") = e;
 	register long r9 __asm__("$9") = f;
-	register long r2 __asm__("$2") = n;
+	register long r2 __asm__("$2");
 
 	__asm__ __volatile__ (
-		"syscall"
-		: "+&r"(r2), "+r"(r7)
-		: "r"(r4), "r"(r5), "r"(r6), "r"(r8), "r"(r9)
+		"daddu $2,$0,%2 ; syscall"
+		: "=&r"(r2), "+r"(r7)
+		: "ir"(n), "r"(r4), "r"(r5), "r"(r6), "r"(r8), "r"(r9)
 		: SYSCALL_CLOBBERLIST);
 	return r7 ? -r2 : r2;
 }
diff --git a/arch/mipsn32/syscall_arch.h b/arch/mipsn32/syscall_arch.h
index c1a4b7da..bc29e318 100644
--- a/arch/mipsn32/syscall_arch.h
+++ b/arch/mipsn32/syscall_arch.h
@@ -16,11 +16,11 @@
 static inline long __syscall0(long n)
 {
 	register long r7 __asm__("$7");
-	register long r2 __asm__("$2") = n;
+	register long r2 __asm__("$2");
 	__asm__ __volatile__ (
-		"syscall"
-		: "+&r"(r2), "=r"(r7)
-		:
+		"daddu $2,$0,%2 ; syscall"
+		: "=&r"(r2), "=r"(r7)
+		: "ir"(n)
 		: SYSCALL_CLOBBERLIST);
 	return r7 ? -r2 : r2;
 }
@@ -29,11 +29,11 @@ static inline long __syscall1(long n, long a)
 {
 	register long r4 __asm__("$4") = a;
 	register long r7 __asm__("$7");
-	register long r2 __asm__("$2") = n;
+	register long r2 __asm__("$2");
 	__asm__ __volatile__ (
-		"syscall"
-		: "+&r"(r2), "=r"(r7)
-		: "r"(r4)
+		"daddu $2,$0,%2 ; syscall"
+		: "=&r"(r2), "=r"(r7)
+		: "ir"(n), "r"(r4)
 		: SYSCALL_CLOBBERLIST);
 	return r7 ? -r2 : r2;
 }
@@ -43,11 +43,12 @@ static inline long __syscall2(long n, long a, long b)
 	register long r4 __asm__("$4") = a;
 	register long r5 __asm__("$5") = b;
 	register long r7 __asm__("$7");
-	register long r2 __asm__("$2") = n;
+	register long r2 __asm__("$2");
+
 	__asm__ __volatile__ (
-		"syscall"
-		: "+&r"(r2), "=r"(r7)
-		: "r"(r4), "r"(r5)
+		"daddu $2,$0,%2 ; syscall"
+		: "=&r"(r2), "=r"(r7)
+		: "ir"(n), "r"(r4), "r"(r5)
 		: SYSCALL_CLOBBERLIST);
 	return r7 ? -r2 : r2;
 }
@@ -58,11 +59,12 @@ static inline long __syscall3(long n, long a, long b, long c)
 	register long r5 __asm__("$5") = b;
 	register long r6 __asm__("$6") = c;
 	register long r7 __asm__("$7");
-	register long r2 __asm__("$2") = n;
+	register long r2 __asm__("$2");
+
 	__asm__ __volatile__ (
-		"syscall"
-		: "+&r"(r2), "=r"(r7)
-		: "r"(r4), "r"(r5), "r"(r6)
+		"daddu $2,$0,%2 ; syscall"
+		: "=&r"(r2), "=r"(r7)
+		: "ir"(n), "r"(r4), "r"(r5), "r"(r6)
 		: SYSCALL_CLOBBERLIST);
 	return r7 ? -r2 : r2;
 }
@@ -73,11 +75,12 @@ static inline long __syscall4(long n, long a, long b, long c, long d)
 	register long r5 __asm__("$5") = b;
 	register long r6 __asm__("$6") = c;
 	register long r7 __asm__("$7") = d;
-	register long r2 __asm__("$2") = n;
+	register long r2 __asm__("$2");
+
 	__asm__ __volatile__ (
-		"syscall"
-		: "+&r"(r2), "+r"(r7)
-		: "r"(r4), "r"(r5), "r"(r6)
+		"daddu $2,$0,%2 ; syscall"
+		: "=&r"(r2), "+r"(r7)
+		: "ir"(n), "r"(r4), "r"(r5), "r"(r6)
 		: SYSCALL_CLOBBERLIST);
 	return r7 ? -r2 : r2;
 }
@@ -89,11 +92,12 @@ static inline long __syscall5(long n, long a, long b, long c, long d, long e)
 	register long r6 __asm__("$6") = c;
 	register long r7 __asm__("$7") = d;
 	register long r8 __asm__("$8") = e;
-	register long r2 __asm__("$2") = n;
+	register long r2 __asm__("$2");
+
 	__asm__ __volatile__ (
-		"syscall"
-		: "+&r"(r2), "+r"(r7)
-		: "r"(r4), "r"(r5), "r"(r6), "r"(r8)
+		"daddu $2,$0,%2 ; syscall"
+		: "=&r"(r2), "+r"(r7)
+		: "ir"(n), "r"(r4), "r"(r5), "r"(r6), "r"(r8)
 		: SYSCALL_CLOBBERLIST);
 	return r7 ? -r2 : r2;
 }
@@ -106,11 +110,12 @@ static inline long __syscall6(long n, long a, long b, long c, long d, long e, lo
 	register long r7 __asm__("$7") = d;
 	register long r8 __asm__("$8") = e;
 	register long r9 __asm__("$9") = f;
-	register long r2 __asm__("$2") = n;
+	register long r2 __asm__("$2");
+
 	__asm__ __volatile__ (
-		"syscall"
-		: "+&r"(r2), "+r"(r7)
-		: "r"(r4), "r"(r5), "r"(r6), "r"(r8), "r"(r9)
+		"daddu $2,$0,%2 ; syscall"
+		: "=&r"(r2), "+r"(r7)
+		: "ir"(n), "r"(r4), "r"(r5), "r"(r6), "r"(r8), "r"(r9)
 		: SYSCALL_CLOBBERLIST);
 	return r7 ? -r2 : r2;
 }
-- 
2.21.0


[-- Attachment #3: 0002-revert-previous-changes-to-mips-32-bit-o32-syscall-a.patch --]
[-- Type: text/plain, Size: 5286 bytes --]

From 6182ff1f35675c60c201be73e60654c15af77c2f Mon Sep 17 00:00:00 2001
From: Rich Felker <dalias@aerifal.cx>
Date: Wed, 11 Mar 2020 18:50:21 -0400
Subject: [PATCH 2/4] revert previous changes to mips (32-bit, o32) syscall asm

exactly revert commit 604f8d3d8b08ee4f548de193050ef93a7753c2e0. it's
wrong for the same reason as a6ab25ff9885a810c8ceba42b9b1ea3badaae879
but does not have to deal with conflicting changes since.

improvements that were valid will be added back as a separate commit.
---
 arch/mips/syscall_arch.h | 63 ++++++++++++++++++++--------------------
 1 file changed, 31 insertions(+), 32 deletions(-)

diff --git a/arch/mips/syscall_arch.h b/arch/mips/syscall_arch.h
index f821e73f..a3812188 100644
--- a/arch/mips/syscall_arch.h
+++ b/arch/mips/syscall_arch.h
@@ -18,11 +18,10 @@
 static inline long __syscall0(long n)
 {
 	register long r7 __asm__("$7");
-	register long r2 __asm__("$2") = n;
+	register long r2 __asm__("$2");
 	__asm__ __volatile__ (
-		"syscall"
-		: "+r"(r2), "=r"(r7)
-		:
+		"addu $2,$0,%2 ; syscall"
+		: "=&r"(r2), "=r"(r7) : "ir"(n), "0"(r2), "1"(r7)
 		: SYSCALL_CLOBBERLIST, "$8", "$9", "$10");
 	return r7 ? -r2 : r2;
 }
@@ -31,11 +30,11 @@ static inline long __syscall1(long n, long a)
 {
 	register long r4 __asm__("$4") = a;
 	register long r7 __asm__("$7");
-	register long r2 __asm__("$2") = n;
+	register long r2 __asm__("$2");
 	__asm__ __volatile__ (
-		"syscall"
-		: "+r"(r2), "=r"(r7)
-		: "r"(r4)
+		"addu $2,$0,%2 ; syscall"
+		: "=&r"(r2), "=r"(r7) : "ir"(n), "0"(r2), "1"(r7),
+		  "r"(r4)
 		: SYSCALL_CLOBBERLIST, "$8", "$9", "$10");
 	return r7 ? -r2 : r2;
 }
@@ -45,11 +44,11 @@ static inline long __syscall2(long n, long a, long b)
 	register long r4 __asm__("$4") = a;
 	register long r5 __asm__("$5") = b;
 	register long r7 __asm__("$7");
-	register long r2 __asm__("$2") = n;
+	register long r2 __asm__("$2");
 	__asm__ __volatile__ (
-		"syscall"
-		: "+r"(r2), "=r"(r7)
-		: "r"(r4), "r"(r5)
+		"addu $2,$0,%2 ; syscall"
+		: "=&r"(r2), "=r"(r7) : "ir"(n), "0"(r2), "1"(r7),
+		  "r"(r4), "r"(r5)
 		: SYSCALL_CLOBBERLIST, "$8", "$9", "$10");
 	return r7 ? -r2 : r2;
 }
@@ -60,11 +59,11 @@ static inline long __syscall3(long n, long a, long b, long c)
 	register long r5 __asm__("$5") = b;
 	register long r6 __asm__("$6") = c;
 	register long r7 __asm__("$7");
-	register long r2 __asm__("$2") = n;
+	register long r2 __asm__("$2");
 	__asm__ __volatile__ (
-		"syscall"
-		: "+r"(r2), "=r"(r7)
-		: "r"(r4), "r"(r5), "r"(r6)
+		"addu $2,$0,%2 ; syscall"
+		: "=&r"(r2), "=r"(r7) : "ir"(n), "0"(r2), "1"(r7),
+		  "r"(r4), "r"(r5), "r"(r6)
 		: SYSCALL_CLOBBERLIST, "$8", "$9", "$10");
 	return r7 ? -r2 : r2;
 }
@@ -75,11 +74,11 @@ static inline long __syscall4(long n, long a, long b, long c, long d)
 	register long r5 __asm__("$5") = b;
 	register long r6 __asm__("$6") = c;
 	register long r7 __asm__("$7") = d;
-	register long r2 __asm__("$2") = n;
+	register long r2 __asm__("$2");
 	__asm__ __volatile__ (
-		"syscall"
-		: "+r"(r2), "+r"(r7)
-		: "r"(r4), "r"(r5), "r"(r6)
+		"addu $2,$0,%2 ; syscall"
+		: "=&r"(r2), "=r"(r7) : "ir"(n), "0"(r2), "1"(r7),
+		  "r"(r4), "r"(r5), "r"(r6)
 		: SYSCALL_CLOBBERLIST, "$8", "$9", "$10");
 	return r7 ? -r2 : r2;
 }
@@ -91,13 +90,13 @@ static inline long __syscall5(long n, long a, long b, long c, long d, long e)
 	register long r6 __asm__("$6") = c;
 	register long r7 __asm__("$7") = d;
 	register long r8 __asm__("$8") = e;
-	register long r2 __asm__("$2") = n;
+	register long r2 __asm__("$2");
 	__asm__ __volatile__ (
 		"subu $sp,$sp,32 ; sw $8,16($sp) ; "
-		"syscall ;"
+		"addu $2,$0,%3 ; syscall ;"
 		"addu $sp,$sp,32"
-		: "+r"(r2), "+r"(r7), "+r"(r8)
-		: "r"(r4), "r"(r5), "r"(r6)
+		: "=&r"(r2), "=r"(r7), "+r"(r8)
+		: "ir"(n), "0"(r2), "1"(r7), "r"(r4), "r"(r5), "r"(r6)
 		: SYSCALL_CLOBBERLIST, "$9", "$10");
 	return r7 ? -r2 : r2;
 }
@@ -110,13 +109,13 @@ static inline long __syscall6(long n, long a, long b, long c, long d, long e, lo
 	register long r7 __asm__("$7") = d;
 	register long r8 __asm__("$8") = e;
 	register long r9 __asm__("$9") = f;
-	register long r2 __asm__("$2") = n;
+	register long r2 __asm__("$2");
 	__asm__ __volatile__ (
 		"subu $sp,$sp,32 ; sw $8,16($sp) ; sw $9,20($sp) ; "
-		"syscall ;"
+		"addu $2,$0,%4 ; syscall ;"
 		"addu $sp,$sp,32"
-		: "+r"(r2), "+r"(r7), "+r"(r8), "+r"(r9)
-		: "r"(r4), "r"(r5), "r"(r6)
+		: "=&r"(r2), "=r"(r7), "+r"(r8), "+r"(r9)
+		: "ir"(n), "0"(r2), "1"(r7), "r"(r4), "r"(r5), "r"(r6)
 		: SYSCALL_CLOBBERLIST, "$10");
 	return r7 ? -r2 : r2;
 }
@@ -130,13 +129,13 @@ static inline long __syscall7(long n, long a, long b, long c, long d, long e, lo
 	register long r8 __asm__("$8") = e;
 	register long r9 __asm__("$9") = f;
 	register long r10 __asm__("$10") = g;
-	register long r2 __asm__("$2") = n;
+	register long r2 __asm__("$2");
 	__asm__ __volatile__ (
 		"subu $sp,$sp,32 ; sw $8,16($sp) ; sw $9,20($sp) ; sw $10,24($sp) ; "
-		"syscall ;"
+		"addu $2,$0,%5 ; syscall ;"
 		"addu $sp,$sp,32"
-		: "+r"(r2), "+r"(r7), "+r"(r8), "+r"(r9), "+r"(r10)
-		: "r"(r4), "r"(r5), "r"(r6)
+		: "=&r"(r2), "=r"(r7), "+r"(r8), "+r"(r9), "+r"(r10)
+		: "ir"(n), "0"(r2), "1"(r7), "r"(r4), "r"(r5), "r"(r6)
 		: SYSCALL_CLOBBERLIST);
 	return r7 ? -r2 : r2;
 }
-- 
2.21.0


[-- Attachment #4: 0003-restore-mips-syscall-asm-improvements-from-reverted-.patch --]
[-- Type: text/plain, Size: 3886 bytes --]

From dd656a205b5f1d0513f7c71c70c786af1e248304 Mon Sep 17 00:00:00 2001
From: Rich Felker <dalias@aerifal.cx>
Date: Wed, 11 Mar 2020 18:58:38 -0400
Subject: [PATCH 3/4] restore mips syscall asm improvements from reverted
 change

in addition to the wrong change to loading of r2, commit
604f8d3d8b08ee4f548de193050ef93a7753c2e0 removed some useless,
redundant, and possibly undefined constraints. bring back the good
parts.
---
 arch/mips/syscall_arch.h | 31 ++++++++++++++++---------------
 1 file changed, 16 insertions(+), 15 deletions(-)

diff --git a/arch/mips/syscall_arch.h b/arch/mips/syscall_arch.h
index a3812188..0a5d6d8f 100644
--- a/arch/mips/syscall_arch.h
+++ b/arch/mips/syscall_arch.h
@@ -21,7 +21,8 @@ static inline long __syscall0(long n)
 	register long r2 __asm__("$2");
 	__asm__ __volatile__ (
 		"addu $2,$0,%2 ; syscall"
-		: "=&r"(r2), "=r"(r7) : "ir"(n), "0"(r2), "1"(r7)
+		: "=&r"(r2), "=r"(r7)
+		: "ir"(n)
 		: SYSCALL_CLOBBERLIST, "$8", "$9", "$10");
 	return r7 ? -r2 : r2;
 }
@@ -33,8 +34,8 @@ static inline long __syscall1(long n, long a)
 	register long r2 __asm__("$2");
 	__asm__ __volatile__ (
 		"addu $2,$0,%2 ; syscall"
-		: "=&r"(r2), "=r"(r7) : "ir"(n), "0"(r2), "1"(r7),
-		  "r"(r4)
+		: "=&r"(r2), "=r"(r7)
+		: "ir"(n), "r"(r4)
 		: SYSCALL_CLOBBERLIST, "$8", "$9", "$10");
 	return r7 ? -r2 : r2;
 }
@@ -47,8 +48,8 @@ static inline long __syscall2(long n, long a, long b)
 	register long r2 __asm__("$2");
 	__asm__ __volatile__ (
 		"addu $2,$0,%2 ; syscall"
-		: "=&r"(r2), "=r"(r7) : "ir"(n), "0"(r2), "1"(r7),
-		  "r"(r4), "r"(r5)
+		: "=&r"(r2), "=r"(r7)
+		: "ir"(n), "r"(r4), "r"(r5)
 		: SYSCALL_CLOBBERLIST, "$8", "$9", "$10");
 	return r7 ? -r2 : r2;
 }
@@ -62,8 +63,8 @@ static inline long __syscall3(long n, long a, long b, long c)
 	register long r2 __asm__("$2");
 	__asm__ __volatile__ (
 		"addu $2,$0,%2 ; syscall"
-		: "=&r"(r2), "=r"(r7) : "ir"(n), "0"(r2), "1"(r7),
-		  "r"(r4), "r"(r5), "r"(r6)
+		: "=&r"(r2), "=r"(r7)
+		: "ir"(n), "r"(r4), "r"(r5), "r"(r6)
 		: SYSCALL_CLOBBERLIST, "$8", "$9", "$10");
 	return r7 ? -r2 : r2;
 }
@@ -77,8 +78,8 @@ static inline long __syscall4(long n, long a, long b, long c, long d)
 	register long r2 __asm__("$2");
 	__asm__ __volatile__ (
 		"addu $2,$0,%2 ; syscall"
-		: "=&r"(r2), "=r"(r7) : "ir"(n), "0"(r2), "1"(r7),
-		  "r"(r4), "r"(r5), "r"(r6)
+		: "=&r"(r2), "+r"(r7)
+		: "ir"(n), "r"(r4), "r"(r5), "r"(r6)
 		: SYSCALL_CLOBBERLIST, "$8", "$9", "$10");
 	return r7 ? -r2 : r2;
 }
@@ -95,8 +96,8 @@ static inline long __syscall5(long n, long a, long b, long c, long d, long e)
 		"subu $sp,$sp,32 ; sw $8,16($sp) ; "
 		"addu $2,$0,%3 ; syscall ;"
 		"addu $sp,$sp,32"
-		: "=&r"(r2), "=r"(r7), "+r"(r8)
-		: "ir"(n), "0"(r2), "1"(r7), "r"(r4), "r"(r5), "r"(r6)
+		: "=&r"(r2), "+r"(r7), "+r"(r8)
+		: "ir"(n), "r"(r4), "r"(r5), "r"(r6)
 		: SYSCALL_CLOBBERLIST, "$9", "$10");
 	return r7 ? -r2 : r2;
 }
@@ -114,8 +115,8 @@ static inline long __syscall6(long n, long a, long b, long c, long d, long e, lo
 		"subu $sp,$sp,32 ; sw $8,16($sp) ; sw $9,20($sp) ; "
 		"addu $2,$0,%4 ; syscall ;"
 		"addu $sp,$sp,32"
-		: "=&r"(r2), "=r"(r7), "+r"(r8), "+r"(r9)
-		: "ir"(n), "0"(r2), "1"(r7), "r"(r4), "r"(r5), "r"(r6)
+		: "=&r"(r2), "+r"(r7), "+r"(r8), "+r"(r9)
+		: "ir"(n), "r"(r4), "r"(r5), "r"(r6)
 		: SYSCALL_CLOBBERLIST, "$10");
 	return r7 ? -r2 : r2;
 }
@@ -134,8 +135,8 @@ static inline long __syscall7(long n, long a, long b, long c, long d, long e, lo
 		"subu $sp,$sp,32 ; sw $8,16($sp) ; sw $9,20($sp) ; sw $10,24($sp) ; "
 		"addu $2,$0,%5 ; syscall ;"
 		"addu $sp,$sp,32"
-		: "=&r"(r2), "=r"(r7), "+r"(r8), "+r"(r9), "+r"(r10)
-		: "ir"(n), "0"(r2), "1"(r7), "r"(r4), "r"(r5), "r"(r6)
+		: "=&r"(r2), "+r"(r7), "+r"(r8), "+r"(r9), "+r"(r10)
+		: "ir"(n), "r"(r4), "r"(r5), "r"(r6)
 		: SYSCALL_CLOBBERLIST);
 	return r7 ? -r2 : r2;
 }
-- 
2.21.0


[-- Attachment #5: 0004-work-around-negated-error-code-bug-on-some-mips-kern.patch --]
[-- Type: text/plain, Size: 7966 bytes --]

From a102a531615ac2eed153c37eb6ae44386573a04a Mon Sep 17 00:00:00 2001
From: Rich Felker <dalias@aerifal.cx>
Date: Wed, 11 Mar 2020 19:02:52 -0400
Subject: [PATCH 4/4] work around negated error code bug on some mips kernels
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

on all mips variants, Linux did (and maybe still does) have some
syscall return paths that wrongly return both the error flag in r7 and
a negated error code in r2. in particular this happened for at least
some causes of ENOSYS.

add an extra check to only negate the error code if it's positive to
begin with.

bug report and concept for patch by Andreas Dröscher.
---
 arch/mips/syscall_arch.h    | 16 ++++++++--------
 arch/mips64/syscall_arch.h  | 14 +++++++-------
 arch/mipsn32/syscall_arch.h | 14 +++++++-------
 3 files changed, 22 insertions(+), 22 deletions(-)

diff --git a/arch/mips/syscall_arch.h b/arch/mips/syscall_arch.h
index 0a5d6d8f..fc301db8 100644
--- a/arch/mips/syscall_arch.h
+++ b/arch/mips/syscall_arch.h
@@ -24,7 +24,7 @@ static inline long __syscall0(long n)
 		: "=&r"(r2), "=r"(r7)
 		: "ir"(n)
 		: SYSCALL_CLOBBERLIST, "$8", "$9", "$10");
-	return r7 ? -r2 : r2;
+	return r7 && r2>0 ? -r2 : r2;
 }
 
 static inline long __syscall1(long n, long a)
@@ -37,7 +37,7 @@ static inline long __syscall1(long n, long a)
 		: "=&r"(r2), "=r"(r7)
 		: "ir"(n), "r"(r4)
 		: SYSCALL_CLOBBERLIST, "$8", "$9", "$10");
-	return r7 ? -r2 : r2;
+	return r7 && r2>0 ? -r2 : r2;
 }
 
 static inline long __syscall2(long n, long a, long b)
@@ -51,7 +51,7 @@ static inline long __syscall2(long n, long a, long b)
 		: "=&r"(r2), "=r"(r7)
 		: "ir"(n), "r"(r4), "r"(r5)
 		: SYSCALL_CLOBBERLIST, "$8", "$9", "$10");
-	return r7 ? -r2 : r2;
+	return r7 && r2>0 ? -r2 : r2;
 }
 
 static inline long __syscall3(long n, long a, long b, long c)
@@ -66,7 +66,7 @@ static inline long __syscall3(long n, long a, long b, long c)
 		: "=&r"(r2), "=r"(r7)
 		: "ir"(n), "r"(r4), "r"(r5), "r"(r6)
 		: SYSCALL_CLOBBERLIST, "$8", "$9", "$10");
-	return r7 ? -r2 : r2;
+	return r7 && r2>0 ? -r2 : r2;
 }
 
 static inline long __syscall4(long n, long a, long b, long c, long d)
@@ -81,7 +81,7 @@ static inline long __syscall4(long n, long a, long b, long c, long d)
 		: "=&r"(r2), "+r"(r7)
 		: "ir"(n), "r"(r4), "r"(r5), "r"(r6)
 		: SYSCALL_CLOBBERLIST, "$8", "$9", "$10");
-	return r7 ? -r2 : r2;
+	return r7 && r2>0 ? -r2 : r2;
 }
 
 static inline long __syscall5(long n, long a, long b, long c, long d, long e)
@@ -99,7 +99,7 @@ static inline long __syscall5(long n, long a, long b, long c, long d, long e)
 		: "=&r"(r2), "+r"(r7), "+r"(r8)
 		: "ir"(n), "r"(r4), "r"(r5), "r"(r6)
 		: SYSCALL_CLOBBERLIST, "$9", "$10");
-	return r7 ? -r2 : r2;
+	return r7 && r2>0 ? -r2 : r2;
 }
 
 static inline long __syscall6(long n, long a, long b, long c, long d, long e, long f)
@@ -118,7 +118,7 @@ static inline long __syscall6(long n, long a, long b, long c, long d, long e, lo
 		: "=&r"(r2), "+r"(r7), "+r"(r8), "+r"(r9)
 		: "ir"(n), "r"(r4), "r"(r5), "r"(r6)
 		: SYSCALL_CLOBBERLIST, "$10");
-	return r7 ? -r2 : r2;
+	return r7 && r2>0 ? -r2 : r2;
 }
 
 static inline long __syscall7(long n, long a, long b, long c, long d, long e, long f, long g)
@@ -138,7 +138,7 @@ static inline long __syscall7(long n, long a, long b, long c, long d, long e, lo
 		: "=&r"(r2), "+r"(r7), "+r"(r8), "+r"(r9), "+r"(r10)
 		: "ir"(n), "r"(r4), "r"(r5), "r"(r6)
 		: SYSCALL_CLOBBERLIST);
-	return r7 ? -r2 : r2;
+	return r7 && r2>0 ? -r2 : r2;
 }
 
 #define VDSO_USEFUL
diff --git a/arch/mips64/syscall_arch.h b/arch/mips64/syscall_arch.h
index 8f6758d3..62492640 100644
--- a/arch/mips64/syscall_arch.h
+++ b/arch/mips64/syscall_arch.h
@@ -22,7 +22,7 @@ static inline long __syscall0(long n)
 		: "=&r"(r2), "=r"(r7)
 		: "ir"(n)
 		: SYSCALL_CLOBBERLIST);
-	return r7 ? -r2 : r2;
+	return r7 && r2>0 ? -r2 : r2;
 }
 
 static inline long __syscall1(long n, long a)
@@ -35,7 +35,7 @@ static inline long __syscall1(long n, long a)
 		: "=&r"(r2), "=r"(r7)
 		: "ir"(n), "r"(r4)
 		: SYSCALL_CLOBBERLIST);
-	return r7 ? -r2 : r2;
+	return r7 && r2>0 ? -r2 : r2;
 }
 
 static inline long __syscall2(long n, long a, long b)
@@ -50,7 +50,7 @@ static inline long __syscall2(long n, long a, long b)
 		: "=&r"(r2), "=r"(r7)
 		: "ir"(n), "r"(r4), "r"(r5)
 		: SYSCALL_CLOBBERLIST);
-	return r7 ? -r2 : r2;
+	return r7 && r2>0 ? -r2 : r2;
 }
 
 static inline long __syscall3(long n, long a, long b, long c)
@@ -66,7 +66,7 @@ static inline long __syscall3(long n, long a, long b, long c)
 		: "=&r"(r2), "=r"(r7)
 		: "ir"(n), "r"(r4), "r"(r5), "r"(r6)
 		: SYSCALL_CLOBBERLIST);
-	return r7 ? -r2 : r2;
+	return r7 && r2>0 ? -r2 : r2;
 }
 
 static inline long __syscall4(long n, long a, long b, long c, long d)
@@ -82,7 +82,7 @@ static inline long __syscall4(long n, long a, long b, long c, long d)
 		: "=&r"(r2), "+r"(r7)
 		: "ir"(n), "r"(r4), "r"(r5), "r"(r6)
 		: SYSCALL_CLOBBERLIST);
-	return r7 ? -r2 : r2;
+	return r7 && r2>0 ? -r2 : r2;
 }
 
 static inline long __syscall5(long n, long a, long b, long c, long d, long e)
@@ -99,7 +99,7 @@ static inline long __syscall5(long n, long a, long b, long c, long d, long e)
 		: "=&r"(r2), "+r"(r7)
 		: "ir"(n), "r"(r4), "r"(r5), "r"(r6), "r"(r8)
 		: SYSCALL_CLOBBERLIST);
-	return r7 ? -r2 : r2;
+	return r7 && r2>0 ? -r2 : r2;
 }
 
 static inline long __syscall6(long n, long a, long b, long c, long d, long e, long f)
@@ -117,7 +117,7 @@ static inline long __syscall6(long n, long a, long b, long c, long d, long e, lo
 		: "=&r"(r2), "+r"(r7)
 		: "ir"(n), "r"(r4), "r"(r5), "r"(r6), "r"(r8), "r"(r9)
 		: SYSCALL_CLOBBERLIST);
-	return r7 ? -r2 : r2;
+	return r7 && r2>0 ? -r2 : r2;
 }
 
 #define VDSO_USEFUL
diff --git a/arch/mipsn32/syscall_arch.h b/arch/mipsn32/syscall_arch.h
index bc29e318..8b9e9ddd 100644
--- a/arch/mipsn32/syscall_arch.h
+++ b/arch/mipsn32/syscall_arch.h
@@ -22,7 +22,7 @@ static inline long __syscall0(long n)
 		: "=&r"(r2), "=r"(r7)
 		: "ir"(n)
 		: SYSCALL_CLOBBERLIST);
-	return r7 ? -r2 : r2;
+	return r7 && r2>0 ? -r2 : r2;
 }
 
 static inline long __syscall1(long n, long a)
@@ -35,7 +35,7 @@ static inline long __syscall1(long n, long a)
 		: "=&r"(r2), "=r"(r7)
 		: "ir"(n), "r"(r4)
 		: SYSCALL_CLOBBERLIST);
-	return r7 ? -r2 : r2;
+	return r7 && r2>0 ? -r2 : r2;
 }
 
 static inline long __syscall2(long n, long a, long b)
@@ -50,7 +50,7 @@ static inline long __syscall2(long n, long a, long b)
 		: "=&r"(r2), "=r"(r7)
 		: "ir"(n), "r"(r4), "r"(r5)
 		: SYSCALL_CLOBBERLIST);
-	return r7 ? -r2 : r2;
+	return r7 && r2>0 ? -r2 : r2;
 }
 
 static inline long __syscall3(long n, long a, long b, long c)
@@ -66,7 +66,7 @@ static inline long __syscall3(long n, long a, long b, long c)
 		: "=&r"(r2), "=r"(r7)
 		: "ir"(n), "r"(r4), "r"(r5), "r"(r6)
 		: SYSCALL_CLOBBERLIST);
-	return r7 ? -r2 : r2;
+	return r7 && r2>0 ? -r2 : r2;
 }
 
 static inline long __syscall4(long n, long a, long b, long c, long d)
@@ -82,7 +82,7 @@ static inline long __syscall4(long n, long a, long b, long c, long d)
 		: "=&r"(r2), "+r"(r7)
 		: "ir"(n), "r"(r4), "r"(r5), "r"(r6)
 		: SYSCALL_CLOBBERLIST);
-	return r7 ? -r2 : r2;
+	return r7 && r2>0 ? -r2 : r2;
 }
 
 static inline long __syscall5(long n, long a, long b, long c, long d, long e)
@@ -99,7 +99,7 @@ static inline long __syscall5(long n, long a, long b, long c, long d, long e)
 		: "=&r"(r2), "+r"(r7)
 		: "ir"(n), "r"(r4), "r"(r5), "r"(r6), "r"(r8)
 		: SYSCALL_CLOBBERLIST);
-	return r7 ? -r2 : r2;
+	return r7 && r2>0 ? -r2 : r2;
 }
 
 static inline long __syscall6(long n, long a, long b, long c, long d, long e, long f)
@@ -117,7 +117,7 @@ static inline long __syscall6(long n, long a, long b, long c, long d, long e, lo
 		: "=&r"(r2), "+r"(r7)
 		: "ir"(n), "r"(r4), "r"(r5), "r"(r6), "r"(r8), "r"(r9)
 		: SYSCALL_CLOBBERLIST);
-	return r7 ? -r2 : r2;
+	return r7 && r2>0 ? -r2 : r2;
 }
 
 #define VDSO_USEFUL
-- 
2.21.0


^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [musl] [PATCH] fix mips syscall asm regressions and kernel bug
  2020-03-11 23:09 [musl] [PATCH] fix mips syscall asm regressions and kernel bug Rich Felker
@ 2020-03-14  0:12 ` Rich Felker
  0 siblings, 0 replies; 2+ messages in thread
From: Rich Felker @ 2020-03-14  0:12 UTC (permalink / raw)
  To: musl

On Wed, Mar 11, 2020 at 07:09:25PM -0400, Rich Felker wrote:
> >From dd656a205b5f1d0513f7c71c70c786af1e248304 Mon Sep 17 00:00:00 2001
> From: Rich Felker <dalias@aerifal.cx>
> Date: Wed, 11 Mar 2020 18:58:38 -0400
> Subject: [PATCH 3/4] restore mips syscall asm improvements from reverted
>  change
> 
> in addition to the wrong change to loading of r2, commit
> 604f8d3d8b08ee4f548de193050ef93a7753c2e0 removed some useless,
> redundant, and possibly undefined constraints. bring back the good
> parts.
> ---
>  arch/mips/syscall_arch.h | 31 ++++++++++++++++---------------
>  1 file changed, 16 insertions(+), 15 deletions(-)
> 
> diff --git a/arch/mips/syscall_arch.h b/arch/mips/syscall_arch.h
> index a3812188..0a5d6d8f 100644
> --- a/arch/mips/syscall_arch.h
> +++ b/arch/mips/syscall_arch.h
> @@ -21,7 +21,8 @@ static inline long __syscall0(long n)
>  	register long r2 __asm__("$2");
>  	__asm__ __volatile__ (
>  		"addu $2,$0,%2 ; syscall"
> -		: "=&r"(r2), "=r"(r7) : "ir"(n), "0"(r2), "1"(r7)
> +		: "=&r"(r2), "=r"(r7)
> +		: "ir"(n)
>  		: SYSCALL_CLOBBERLIST, "$8", "$9", "$10");
>  	return r7 ? -r2 : r2;
>  }

This part of the change (also present in the 64-bit versions) was
horribly wrong because of an ancient GCC bug: specific-register
bindings for outputs are not honored at all with earlyclobber. This is
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87733

I think for now I can work around it by adding back the dummy input
constraint the old asm was using. This looks wrong but at least it
worked.

Rich

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, back to index

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-03-11 23:09 [musl] [PATCH] fix mips syscall asm regressions and kernel bug Rich Felker
2020-03-14  0:12 ` Rich Felker

mailing list of musl libc

Archives are clonable: git clone --mirror http://inbox.vuxu.org/musl

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://inbox.vuxu.org/vuxu.archive.musl


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git