Commit d4973c9922

Alex Rønne Petersen <alex@alexrp.com>
2024-08-16 11:09:52
std.os.linux: Fix syscall errno value handling for mips.
The kernel sets r7 to 0 (success) or -1 (error), and stores the result in r2. When r7 is -1 and the result is positive, it needs to be negated to get the errno value that higher-level code, such as errnoFromSyscall(), expects to see. The old code was missing the check that r2 is positive, but was also doing the r7 check incorrectly; since it can only be set to 0 or -1, the blez instruction would always branch. In practice, this fix is necessary for e.g. the ENOSYS error to be interpreted correctly. This manifested as hitting an unreachable branch when calling process_vm_readv() in std.debug.MemoryAccessor.
1 parent bcf41c8
Changed files (2)
lib
std
lib/std/os/linux/mips.zig
@@ -14,7 +14,8 @@ const timespec = linux.timespec;
 pub fn syscall0(number: SYS) usize {
     return asm volatile (
         \\ syscall
-        \\ blez $7, 1f
+        \\ beq $7, $zero, 1f
+        \\ blez $2, 1f
         \\ subu $2, $0, $2
         \\ 1:
         : [ret] "={$2}" (-> usize),
@@ -28,7 +29,7 @@ pub fn syscall_pipe(fd: *[2]i32) usize {
         \\ .set noat
         \\ .set noreorder
         \\ syscall
-        \\ blez $7, 1f
+        \\ beq $7, $zero, 1f
         \\ nop
         \\ b 2f
         \\ subu $2, $0, $2
@@ -46,7 +47,8 @@ pub fn syscall_pipe(fd: *[2]i32) usize {
 pub fn syscall1(number: SYS, arg1: usize) usize {
     return asm volatile (
         \\ syscall
-        \\ blez $7, 1f
+        \\ beq $7, $zero, 1f
+        \\ blez $2, 1f
         \\ subu $2, $0, $2
         \\ 1:
         : [ret] "={$2}" (-> usize),
@@ -59,7 +61,8 @@ pub fn syscall1(number: SYS, arg1: usize) usize {
 pub fn syscall2(number: SYS, arg1: usize, arg2: usize) usize {
     return asm volatile (
         \\ syscall
-        \\ blez $7, 1f
+        \\ beq $7, $zero, 1f
+        \\ blez $2, 1f
         \\ subu $2, $0, $2
         \\ 1:
         : [ret] "={$2}" (-> usize),
@@ -73,7 +76,8 @@ pub fn syscall2(number: SYS, arg1: usize, arg2: usize) usize {
 pub fn syscall3(number: SYS, arg1: usize, arg2: usize, arg3: usize) usize {
     return asm volatile (
         \\ syscall
-        \\ blez $7, 1f
+        \\ beq $7, $zero, 1f
+        \\ blez $2, 1f
         \\ subu $2, $0, $2
         \\ 1:
         : [ret] "={$2}" (-> usize),
@@ -88,7 +92,8 @@ pub fn syscall3(number: SYS, arg1: usize, arg2: usize, arg3: usize) usize {
 pub fn syscall4(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize) usize {
     return asm volatile (
         \\ syscall
-        \\ blez $7, 1f
+        \\ beq $7, $zero, 1f
+        \\ blez $2, 1f
         \\ subu $2, $0, $2
         \\ 1:
         : [ret] "={$2}" (-> usize),
@@ -108,7 +113,8 @@ pub fn syscall5(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize,
         \\ sw %[arg5], 16($sp)
         \\ syscall
         \\ addu $sp, $sp, 24
-        \\ blez $7, 1f
+        \\ beq $7, $zero, 1f
+        \\ blez $2, 1f
         \\ subu $2, $0, $2
         \\ 1:
         : [ret] "={$2}" (-> usize),
@@ -141,7 +147,8 @@ pub fn syscall6(
         \\ sw %[arg6], 20($sp)
         \\ syscall
         \\ addu $sp, $sp, 24
-        \\ blez $7, 1f
+        \\ beq $7, $zero, 1f
+        \\ blez $2, 1f
         \\ subu $2, $0, $2
         \\ 1:
         : [ret] "={$2}" (-> usize),
@@ -174,7 +181,8 @@ pub fn syscall7(
         \\ sw %[arg7], 24($sp)
         \\ syscall
         \\ addu $sp, $sp, 32
-        \\ blez $7, 1f
+        \\ beq $7, $zero, 1f
+        \\ blez $2, 1f
         \\ subu $2, $0, $2
         \\ 1:
         : [ret] "={$2}" (-> usize),
lib/std/os/linux/mips64.zig
@@ -14,7 +14,8 @@ const timespec = linux.timespec;
 pub fn syscall0(number: SYS) usize {
     return asm volatile (
         \\ syscall
-        \\ blez $7, 1f
+        \\ beq $7, $zero, 1f
+        \\ blez $2, 1f
         \\ dsubu $2, $0, $2
         \\ 1:
         : [ret] "={$2}" (-> usize),
@@ -28,7 +29,7 @@ pub fn syscall_pipe(fd: *[2]i32) usize {
         \\ .set noat
         \\ .set noreorder
         \\ syscall
-        \\ blez $7, 1f
+        \\ beq $7, $zero, 1f
         \\ nop
         \\ b 2f
         \\ subu $2, $0, $2
@@ -46,7 +47,9 @@ pub fn syscall_pipe(fd: *[2]i32) usize {
 pub fn syscall1(number: SYS, arg1: usize) usize {
     return asm volatile (
         \\ syscall
-        \\ blez $7, 1f
+        \\ beq $7, $zero, 1f
+        \\ blez $2, 1f
+        \\ nop
         \\ dsubu $2, $0, $2
         \\ 1:
         : [ret] "={$2}" (-> usize),
@@ -59,7 +62,8 @@ pub fn syscall1(number: SYS, arg1: usize) usize {
 pub fn syscall2(number: SYS, arg1: usize, arg2: usize) usize {
     return asm volatile (
         \\ syscall
-        \\ blez $7, 1f
+        \\ beq $7, $zero, 1f
+        \\ blez $2, 1f
         \\ dsubu $2, $0, $2
         \\ 1:
         : [ret] "={$2}" (-> usize),
@@ -73,7 +77,8 @@ pub fn syscall2(number: SYS, arg1: usize, arg2: usize) usize {
 pub fn syscall3(number: SYS, arg1: usize, arg2: usize, arg3: usize) usize {
     return asm volatile (
         \\ syscall
-        \\ blez $7, 1f
+        \\ beq $7, $zero, 1f
+        \\ blez $2, 1f
         \\ dsubu $2, $0, $2
         \\ 1:
         : [ret] "={$2}" (-> usize),
@@ -88,7 +93,8 @@ pub fn syscall3(number: SYS, arg1: usize, arg2: usize, arg3: usize) usize {
 pub fn syscall4(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize) usize {
     return asm volatile (
         \\ syscall
-        \\ blez $7, 1f
+        \\ beq $7, $zero, 1f
+        \\ blez $2, 1f
         \\ dsubu $2, $0, $2
         \\ 1:
         : [ret] "={$2}" (-> usize),
@@ -104,7 +110,8 @@ pub fn syscall4(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize)
 pub fn syscall5(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) usize {
     return asm volatile (
         \\ syscall
-        \\ blez $7, 1f
+        \\ beq $7, $zero, 1f
+        \\ blez $2, 1f
         \\ dsubu $2, $0, $2
         \\ 1:
         : [ret] "={$2}" (-> usize),
@@ -129,7 +136,8 @@ pub fn syscall6(
 ) usize {
     return asm volatile (
         \\ syscall
-        \\ blez $7, 1f
+        \\ beq $7, $zero, 1f
+        \\ blez $2, 1f
         \\ dsubu $2, $0, $2
         \\ 1:
         : [ret] "={$2}" (-> usize),
@@ -156,7 +164,8 @@ pub fn syscall7(
 ) usize {
     return asm volatile (
         \\ syscall
-        \\ blez $7, 1f
+        \\ beq $7, $zero, 1f
+        \\ blez $2, 1f
         \\ dsubu $2, $0, $2
         \\ 1:
         : [ret] "={$2}" (-> usize),