When the bpf syscall returns -ENOTSUPP, the kernel does not set psr/csr. glibc's syscall() then thinks everything is fine and skips updating errno, causing all kinds of confusion in bpf selftests. sparc decides whether to set psr/csr by comparing syscall return value with ERESTART_RESTARTBLOCK, which is smaller than ENOTSUPP. Fix by introducing EMAXERRNO (like mips) and comparing with that insead. Cc: David S. Miller <davem@xxxxxxxxxxxxx> Signed-off-by: Ilya Leoshkevich <iii@xxxxxxxxxxxxx> --- arch/sparc/include/asm/errno.h | 10 ++++++++++ arch/sparc/kernel/entry.S | 2 +- arch/sparc/kernel/process.c | 6 +++--- arch/sparc/kernel/syscalls.S | 2 +- 4 files changed, 15 insertions(+), 5 deletions(-) create mode 100644 arch/sparc/include/asm/errno.h diff --git a/arch/sparc/include/asm/errno.h b/arch/sparc/include/asm/errno.h new file mode 100644 index 000000000000..0e0a790b8ea8 --- /dev/null +++ b/arch/sparc/include/asm/errno.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_SPARC_ERRNO_H +#define _ASM_SPARC_ERRNO_H + +#include <uapi/asm/errno.h> + +/* The biggest error number defined here or in <linux/errno.h>. */ +#define EMAXERRNO 1133 + +#endif /* _ASM_SPARC_ERRNO_H */ diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S index a269ad2fe6df..a24b46ad7b20 100644 --- a/arch/sparc/kernel/entry.S +++ b/arch/sparc/kernel/entry.S @@ -1004,7 +1004,7 @@ do_syscall: ret_sys_call: ld [%curptr + TI_FLAGS], %l5 - cmp %o0, -ERESTART_RESTARTBLOCK + cmp %o0, -EMAXERRNO ld [%sp + STACKFRAME_SZ + PT_PSR], %g3 set PSR_C, %g2 bgeu 1f diff --git a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c index 0442ab00518d..582933d16f9f 100644 --- a/arch/sparc/kernel/process.c +++ b/arch/sparc/kernel/process.c @@ -32,7 +32,7 @@ asmlinkage long sparc_fork(struct pt_regs *regs) * the parent's %o1. So detect that case and restore it * here. */ - if ((unsigned long)ret >= -ERESTART_RESTARTBLOCK) + if ((unsigned long)ret >= -EMAXERRNO) regs->u_regs[UREG_I1] = orig_i1; return ret; @@ -57,7 +57,7 @@ asmlinkage long sparc_vfork(struct pt_regs *regs) * the parent's %o1. So detect that case and restore it * here. */ - if ((unsigned long)ret >= -ERESTART_RESTARTBLOCK) + if ((unsigned long)ret >= -EMAXERRNO) regs->u_regs[UREG_I1] = orig_i1; return ret; @@ -103,7 +103,7 @@ asmlinkage long sparc_clone(struct pt_regs *regs) * the parent's %o1. So detect that case and restore it * here. */ - if ((unsigned long)ret >= -ERESTART_RESTARTBLOCK) + if ((unsigned long)ret >= -EMAXERRNO) regs->u_regs[UREG_I1] = orig_i1; return ret; diff --git a/arch/sparc/kernel/syscalls.S b/arch/sparc/kernel/syscalls.S index 0e8ab0602c36..9064304f6a3a 100644 --- a/arch/sparc/kernel/syscalls.S +++ b/arch/sparc/kernel/syscalls.S @@ -262,7 +262,7 @@ ret_sys_call: mov %ulo(TSTATE_XCARRY | TSTATE_ICARRY), %g2 sllx %g2, 32, %g2 - cmp %o0, -ERESTART_RESTARTBLOCK + cmp %o0, -EMAXERRNO bgeu,pn %xcc, 1f andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT|_TIF_SYSCALL_TRACEPOINT|_TIF_NOHZ), %g0 ldx [%sp + PTREGS_OFF + PT_V9_TNPC], %l1 ! pc = npc -- 2.39.1