From d4973c992203ed6fb761d3f3b871dd9849541b5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Fri, 16 Aug 2024 11:09:52 +0200 Subject: [PATCH] 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. --- lib/std/os/linux/mips.zig | 26 +++++++++++++++++--------- lib/std/os/linux/mips64.zig | 27 ++++++++++++++++++--------- 2 files changed, 35 insertions(+), 18 deletions(-) diff --git a/lib/std/os/linux/mips.zig b/lib/std/os/linux/mips.zig index aa02841926..5fe5337f22 100644 --- a/lib/std/os/linux/mips.zig +++ b/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), diff --git a/lib/std/os/linux/mips64.zig b/lib/std/os/linux/mips64.zig index 579d41ca75..068e15d8db 100644 --- a/lib/std/os/linux/mips64.zig +++ b/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),