[PATCH] MIPS: fix forced successful syscalls

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On mips any syscalls who return a value between -MAXERRNO (1133) and
-1, is considered as an error (the error flag is set and return value
is the positive value of the error number).

But some syscalls can return values between -MAXERRNO and -1 like
sys_time and sys_times. In this case the userspace return value is
-return value of the syscall and the error flag set.

This patch add a TIF_NOERROR thread flag which indicates that the
return value of a syscall is always correct.

All ABIs are updated (kernel 32 o32, kernel64 o32, kernel64 n32
and kernel64 n64).
---
 arch/mips/include/asm/ptrace.h      |  5 +++++
 arch/mips/include/asm/thread_info.h |  2 ++
 arch/mips/kernel/scall32-o32.S      | 14 ++++++++++++++
 arch/mips/kernel/scall64-64.S       | 14 ++++++++++++++
 arch/mips/kernel/scall64-n32.S      | 14 ++++++++++++++
 arch/mips/kernel/scall64-o32.S      | 14 ++++++++++++++
 6 files changed, 63 insertions(+)

diff --git a/arch/mips/include/asm/ptrace.h b/arch/mips/include/asm/ptrace.h
index 5e6cd09..51552f2 100644
--- a/arch/mips/include/asm/ptrace.h
+++ b/arch/mips/include/asm/ptrace.h
@@ -94,6 +94,11 @@ static inline void die_if_kernel(const char *str, struct pt_regs *regs)
 		die(str, regs);
 }
 
+#define force_successful_syscall_return()   \
+	do { \
+		set_thread_flag(TIF_NOERROR); \
+	} while(0)
+
 #define current_pt_regs()						\
 ({									\
 	unsigned long sp = (unsigned long)__builtin_frame_address(0);	\
diff --git a/arch/mips/include/asm/thread_info.h b/arch/mips/include/asm/thread_info.h
index 61215a3..6764fc1 100644
--- a/arch/mips/include/asm/thread_info.h
+++ b/arch/mips/include/asm/thread_info.h
@@ -116,6 +116,7 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_32BIT_ADDR		23	/* 32-bit address space (o32/n32) */
 #define TIF_FPUBOUND		24	/* thread bound to FPU-full CPU set */
 #define TIF_LOAD_WATCH		25	/* If set, load watch registers */
+#define TIF_NOERROR		30	/* Force successful syscall return */
 #define TIF_SYSCALL_TRACE	31	/* syscall trace active */
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
@@ -131,6 +132,7 @@ static inline struct thread_info *current_thread_info(void)
 #define _TIF_32BIT_REGS		(1<<TIF_32BIT_REGS)
 #define _TIF_32BIT_ADDR		(1<<TIF_32BIT_ADDR)
 #define _TIF_FPUBOUND		(1<<TIF_FPUBOUND)
+#define _TIF_NOERROR		(1<<TIF_NOERROR)
 #define _TIF_LOAD_WATCH		(1<<TIF_LOAD_WATCH)
 
 #define _TIF_WORK_SYSCALL_ENTRY	(_TIF_NOHZ | _TIF_SYSCALL_TRACE |	\
diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S
index e774bb1..4ac30ac 100644
--- a/arch/mips/kernel/scall32-o32.S
+++ b/arch/mips/kernel/scall32-o32.S
@@ -58,8 +58,22 @@ stack_done:
 
 	jalr	t2			# Do The Real Thing (TM)
 
+	li	t0, 0			# no error for negative return ?
+	lw	t2, TI_FLAGS($28)
+	li	t1, _TIF_NOERROR
+	and	t2, t1
+	bnez	t2, syscall_ret_noerror
+
 	li	t0, -EMAXERRNO - 1	# error?
 	sltu	t0, t0, v0
+	b	syscall_ret_error
+
+syscall_ret_noerror:
+	li	t1, ~_TIF_NOERROR	# clear TIF_NOERROR
+	and	t2, t1
+	sw	t2, TI_FLAGS($28)
+
+syscall_ret_error:
 	sw	t0, PT_R7(sp)		# set error flag
 	beqz	t0, 1f
 
diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S
index be6627e..793ba7e 100644
--- a/arch/mips/kernel/scall64-64.S
+++ b/arch/mips/kernel/scall64-64.S
@@ -61,8 +61,22 @@ NESTED(handle_sys64, PT_SIZE, sp)
 
 	jalr	t2			# Do The Real Thing (TM)
 
+	li	t0, 0			# no error for negative return ?
+	LONG_L	t2, TI_FLAGS($28)
+	li	t1, _TIF_NOERROR
+	and	t2, t1
+	bnez	t2, syscall_ret_noerror
+
 	li	t0, -EMAXERRNO - 1	# error?
 	sltu	t0, t0, v0
+	b	syscall_ret_error
+
+syscall_ret_noerror:
+	li	t1, ~_TIF_NOERROR	# clear TIF_NOERROR
+	and	t2, t1
+	LONG_S	t2, TI_FLAGS($28)
+
+syscall_ret_error:
 	sd	t0, PT_R7(sp)		# set error flag
 	beqz	t0, 1f
 
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
index cab1507..ccac0c6 100644
--- a/arch/mips/kernel/scall64-n32.S
+++ b/arch/mips/kernel/scall64-n32.S
@@ -54,8 +54,22 @@ NESTED(handle_sysn32, PT_SIZE, sp)
 
 	jalr	t2			# Do The Real Thing (TM)
 
+	li	t0, 0			# no error for negative return ?
+	LONG_L	t2, TI_FLAGS($28)
+	li	t1, _TIF_NOERROR
+	and	t2, t1
+	bnez	t2, syscall_ret_noerror
+
 	li	t0, -EMAXERRNO - 1	# error?
 	sltu	t0, t0, v0
+	b	syscall_ret_error
+
+syscall_ret_noerror:
+	li	t1, ~_TIF_NOERROR	# clear TIF_NOERROR
+	and	t2, t1
+	LONG_S	t2, TI_FLAGS($28)
+
+syscall_ret_error:
 	sd	t0, PT_R7(sp)		# set error flag
 	beqz	t0, 1f
 
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
index 37605dc..b1d3d51 100644
--- a/arch/mips/kernel/scall64-o32.S
+++ b/arch/mips/kernel/scall64-o32.S
@@ -88,8 +88,22 @@ NESTED(handle_sys, PT_SIZE, sp)
 
 	jalr	t2			# Do The Real Thing (TM)
 
+	li	t0, 0			# no error for negative return ?
+	LONG_L	t2, TI_FLAGS($28)
+	li	t1, _TIF_NOERROR
+	and	t2, t1
+	bnez	t2, syscall_ret_noerror
+
 	li	t0, -EMAXERRNO - 1	# error?
 	sltu	t0, t0, v0
+	b	syscall_ret_error
+
+syscall_ret_noerror:
+	li	t1, ~_TIF_NOERROR	# clear TIF_NOERROR
+	and	t2, t1
+	LONG_S	t2, TI_FLAGS($28)
+
+syscall_ret_error:
 	sd	t0, PT_R7(sp)		# set error flag
 	beqz	t0, 1f
 
-- 
1.8.3.1


[Index of Archives]     [Linux MIPS Home]     [LKML Archive]     [Linux ARM Kernel]     [Linux ARM]     [Linux]     [Git]     [Yosemite News]     [Linux SCSI]     [Linux Hams]

  Powered by Linux