Skip to contentSkip to conversation

mips: convert to generic entry

PATCH Superseded FreeFlyingSheep 8 participants 15 messages Sep 7, 2021 – Sep 14, 2021

Subsystems (3)

v1 of 3 Superseded Latest is v3 →

lore
Share & tools
lore
#0 lore raw

cover mips: convert to generic entry

From: Feiyang Chen <[email protected]>

Convert mips to use the generic entry infrastructure from kernel/entry/*.

Feiyang Chen (2):
mips: convert syscall to generic entry
mips: convert irq to generic entry

 arch/mips/Kconfig                         |   1 +
 arch/mips/include/asm/entry-common.h      |  13 ++
 arch/mips/include/asm/irqflags.h          |  42 ----
 arch/mips/include/asm/ptrace.h            |   8 +-
 arch/mips/include/asm/sim.h               |  70 -------
 arch/mips/include/asm/stackframe.h        |   8 +
 arch/mips/include/asm/syscall.h           |   5 +
 arch/mips/include/asm/thread_info.h       |  17 +-
 arch/mips/include/uapi/asm/ptrace.h       |   7 +-
 arch/mips/kernel/Makefile                 |  14 +-
 arch/mips/kernel/entry.S                  | 143 +-------------
 arch/mips/kernel/genex.S                  | 148 +++-----------
 arch/mips/kernel/head.S                   |   1 -
 arch/mips/kernel/linux32.c                |   1 -
 arch/mips/kernel/ptrace.c                 |  78 --------
 arch/mips/kernel/r4k-bugs64.c             |  14 +-
 arch/mips/kernel/scall.S                  | 130 +++++++++++++
 arch/mips/kernel/scall32-o32.S            | 223 ----------------------
 arch/mips/kernel/scall64-n32.S            | 107 -----------
 arch/mips/kernel/scall64-n64.S            | 116 -----------
 arch/mips/kernel/scall64-o32.S            | 221 ---------------------
 arch/mips/kernel/signal.c                 |  59 +-----
 arch/mips/kernel/signal_n32.c             |  15 +-
 arch/mips/kernel/signal_o32.c             |  29 +--
 arch/mips/kernel/syscall.c                | 147 +++++++++++---
 arch/mips/kernel/syscalls/syscall_n32.tbl |   8 +-
 arch/mips/kernel/syscalls/syscall_n64.tbl |   8 +-
 arch/mips/kernel/syscalls/syscall_o32.tbl |   8 +-
 arch/mips/kernel/traps.c                  | 202 ++++++++++++++------
 arch/mips/kernel/unaligned.c              |  19 +-
 arch/mips/mm/c-octeon.c                   |  15 ++
 arch/mips/mm/cex-oct.S                    |   8 +-
 arch/mips/mm/fault.c                      |  12 +-
 arch/mips/mm/tlbex-fault.S                |   7 +-
 34 files changed, 562 insertions(+), 1342 deletions(-)
 create mode 100644 arch/mips/include/asm/entry-common.h
 delete mode 100644 arch/mips/include/asm/sim.h
 create mode 100644 arch/mips/kernel/scall.S
 delete mode 100644 arch/mips/kernel/scall32-o32.S
 delete mode 100644 arch/mips/kernel/scall64-n32.S
 delete mode 100644 arch/mips/kernel/scall64-n64.S
 delete mode 100644 arch/mips/kernel/scall64-o32.S
Signature · 1 line
2.27.0
#1 lore raw

PATCH 1/2 mips: convert syscall to generic entry

From: Feiyang Chen <[email protected]>

Convert mips syscall to use the generic entry infrastructure from kernel/entry/*.

There are a few special things on mips:

- There is one type of syscall on mips32 (scall32-o32) and three types of syscalls on mips64 (scall64-o32, scall64-n32 and scall64-n64). Now convert to C code to handle different types of syscalls.

- For some special syscalls (e.g. fork, clone, clone3 and sysmips), save_static_function() wrapper is used to save static registers. Now SAVE_STATIC is used in handle_sys before calling do_syscall(), so the save_static_function() wrapper can be removed.

- For sigreturn/rt_sigreturn and sysmips, inline assembly is used to jump to syscall_exit directly for skipping setting the error flag and restoring all registers. Now use regs->regs[27] to mark whether to handle the error flag and always restore all registers in handle_sys, so these functions can return normally as other architecture.

---
 arch/mips/Kconfig                         |   1 +
 arch/mips/include/asm/entry-common.h      |  13 ++
 arch/mips/include/asm/ptrace.h            |   8 +-
 arch/mips/include/asm/sim.h               |  70 -------
 arch/mips/include/asm/syscall.h           |   5 +
 arch/mips/include/asm/thread_info.h       |  17 +-
 arch/mips/include/uapi/asm/ptrace.h       |   7 +-
 arch/mips/kernel/Makefile                 |  14 +-
 arch/mips/kernel/entry.S                  |  75 ++------
 arch/mips/kernel/linux32.c                |   1 -
 arch/mips/kernel/ptrace.c                 |  78 --------
 arch/mips/kernel/scall.S                  | 135 +++++++++++++
 arch/mips/kernel/scall32-o32.S            | 223 ----------------------
 arch/mips/kernel/scall64-n32.S            | 107 -----------
 arch/mips/kernel/scall64-n64.S            | 116 -----------
 arch/mips/kernel/scall64-o32.S            | 221 ---------------------
 arch/mips/kernel/signal.c                 |  35 ++--
 arch/mips/kernel/signal_n32.c             |  15 +-
 arch/mips/kernel/signal_o32.c             |  29 +--
 arch/mips/kernel/syscall.c                | 147 +++++++++++---
 arch/mips/kernel/syscalls/syscall_n32.tbl |   8 +-
 arch/mips/kernel/syscalls/syscall_n64.tbl |   8 +-
 arch/mips/kernel/syscalls/syscall_o32.tbl |   8 +-
 23 files changed, 346 insertions(+), 995 deletions(-)
 create mode 100644 arch/mips/include/asm/entry-common.h
 delete mode 100644 arch/mips/include/asm/sim.h
 create mode 100644 arch/mips/kernel/scall.S
 delete mode 100644 arch/mips/kernel/scall32-o32.S
 delete mode 100644 arch/mips/kernel/scall64-n32.S
 delete mode 100644 arch/mips/kernel/scall64-n64.S
 delete mode 100644 arch/mips/kernel/scall64-o32.S
arch/mips/Kconfig +1 -0
index 0cf31a6cbee1..61aa125aa2da 100644
@@ -32,6 +32,7 @@ config MIPS
 	select GENERIC_ATOMIC64 if !64BIT
 	select GENERIC_CMOS_UPDATE
 	select GENERIC_CPU_AUTOPROBE
+	select GENERIC_ENTRY
 	select GENERIC_GETTIMEOFDAY
 	select GENERIC_IOMAP
 	select GENERIC_IRQ_PROBE
arch/mips/include/asm/entry-common.h new file +13 -0
new file mode 100644
index 000000000000..0fe2a098ded9
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef ARCH_LOONGARCH_ENTRY_COMMON_H
+#define ARCH_LOONGARCH_ENTRY_COMMON_H
+
+#include <linux/sched.h>
+#include <linux/processor.h>
+
+static inline bool on_thread_stack(void)
+{
+	return !(((unsigned long)(current->stack) ^ current_stack_pointer) & ~(THREAD_SIZE - 1));
+}
+
+#endif
arch/mips/include/asm/ptrace.h +5 -3
index daf3cf244ea9..1b8f9d2ddc44 100644
@@ -51,6 +51,11 @@ struct pt_regs {
 	unsigned long __last[0];
 } __aligned(8);
 
+static inline int regs_irqs_disabled(struct pt_regs *regs)
+{
+	return arch_irqs_disabled_flags(regs->cp0_status);
+}
+
 static inline unsigned long kernel_stack_pointer(struct pt_regs *regs)
 {
 	return regs->regs[29];
@@ -156,9 +161,6 @@ static inline long regs_return_value(struct pt_regs *regs)
 #define instruction_pointer(regs) ((regs)->cp0_epc)
 #define profile_pc(regs) instruction_pointer(regs)
 
-extern asmlinkage long syscall_trace_enter(struct pt_regs *regs, long syscall);
-extern asmlinkage void syscall_trace_leave(struct pt_regs *regs);
-
 extern void die(const char *, struct pt_regs *) __noreturn;
 
 static inline void die_if_kernel(const char *str, struct pt_regs *regs)
arch/mips/include/asm/sim.h deleted +0 -70

70 lines not on this page · raw message

arch/mips/include/asm/syscall.h +5 -0
index 25fa651c937d..02ca0d659428 100644
@@ -157,4 +157,9 @@ static inline int syscall_get_arch(struct task_struct *task)
 	return arch;
 }
 
+static inline bool arch_syscall_is_vdso_sigreturn(struct pt_regs *regs)
+{
+	return false;
+}
+
 #endif	/* __ASM_MIPS_SYSCALL_H */
arch/mips/include/asm/thread_info.h +4 -13
index 0b17aaa9e012..5a5237413065 100644
@@ -29,7 +29,8 @@ struct thread_info {
 	__u32			cpu;		/* current CPU */
 	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
 	struct pt_regs		*regs;
-	long			syscall;	/* syscall number */
+	unsigned long		syscall;	/* syscall number */
+	unsigned long		syscall_work;	/* SYSCALL_WORK_ flags */
 };
 
 /*
@@ -69,6 +70,8 @@ static inline struct thread_info *current_thread_info(void)
 	return __current_thread_info;
 }
 
+register unsigned long current_stack_pointer __asm__("$29");
+
 #endif /* !__ASSEMBLY__ */
 
 /* thread information allocation */
@@ -149,22 +152,10 @@ static inline struct thread_info *current_thread_info(void)
 #define _TIF_MSA_CTX_LIVE	(1<<TIF_MSA_CTX_LIVE)
 #define _TIF_SYSCALL_TRACEPOINT	(1<<TIF_SYSCALL_TRACEPOINT)
 
-#define _TIF_WORK_SYSCALL_ENTRY	(_TIF_NOHZ | _TIF_SYSCALL_TRACE |	\
-				 _TIF_SYSCALL_AUDIT | \
-				 _TIF_SYSCALL_TRACEPOINT | _TIF_SECCOMP)
-
-/* work to do in syscall_trace_leave() */
-#define _TIF_WORK_SYSCALL_EXIT	(_TIF_NOHZ | _TIF_SYSCALL_TRACE |	\
-				 _TIF_SYSCALL_AUDIT | _TIF_SYSCALL_TRACEPOINT)
-
 /* work to do on interrupt/exception return */
 #define _TIF_WORK_MASK		\
 	(_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_NOTIFY_RESUME |	\
 	 _TIF_UPROBE | _TIF_NOTIFY_SIGNAL)
-/* work to do on any return to u-space */
-#define _TIF_ALLWORK_MASK	(_TIF_NOHZ | _TIF_WORK_MASK |		\
-				 _TIF_WORK_SYSCALL_EXIT |		\
-				 _TIF_SYSCALL_TRACEPOINT)
 
 /*
  * We stash processor id into a COP0 register to retrieve it fast
arch/mips/include/uapi/asm/ptrace.h +4 -3
index f3c025445e45..27e2c85398bc 100644
@@ -102,8 +102,9 @@ struct pt_watch_regs {
 	};
 };
 
-#define PTRACE_GET_WATCH_REGS	0xd0
-#define PTRACE_SET_WATCH_REGS	0xd1
-
+#define PTRACE_SYSEMU			0x1f
+#define PTRACE_SYSEMU_SINGLESTEP	0x20
+#define PTRACE_GET_WATCH_REGS		0xd0
+#define PTRACE_SET_WATCH_REGS		0xd1
 
 #endif /* _UAPI_ASM_PTRACE_H */
arch/mips/kernel/Makefile +6 -8
index 814b3da30501..44875660f6ae 100644
@@ -5,10 +5,10 @@
 
 extra-y		:= head.o vmlinux.lds
 
-obj-y		+= branch.o cmpxchg.o elf.o entry.o genex.o idle.o irq.o \
-		   process.o prom.o ptrace.o reset.o setup.o signal.o \
-		   syscall.o time.o topology.o traps.o unaligned.o watch.o \
-		   vdso.o cacheinfo.o
+obj-y		+= branch.o cacheinfo.o cmpxchg.o elf.o entry.o genex.o \
+		   idle.o irq.o process.o prom.o ptrace.o reset.o scall.o \
+		   setup.o signal.o syscall.o time.o topology.o traps.o \
+		   unaligned.o watch.o vdso.o
 
 ifdef CONFIG_CPU_R3K_TLB
 obj-y		+= cpu-r3k-probe.o
@@ -76,11 +76,9 @@ obj-$(CONFIG_IRQ_TXX9)		+= irq_txx9.o
 obj-$(CONFIG_IRQ_GT641XX)	+= irq-gt641xx.o
 
 obj-$(CONFIG_KPROBES)		+= kprobes.o
-obj-$(CONFIG_32BIT)		+= scall32-o32.o
-obj-$(CONFIG_64BIT)		+= scall64-n64.o
 obj-$(CONFIG_MIPS32_COMPAT)	+= linux32.o ptrace32.o signal32.o
-obj-$(CONFIG_MIPS32_N32)	+= scall64-n32.o signal_n32.o
-obj-$(CONFIG_MIPS32_O32)	+= scall64-o32.o signal_o32.o
+obj-$(CONFIG_MIPS32_N32)	+= signal_n32.o
+obj-$(CONFIG_MIPS32_O32)	+= signal_o32.o
 
 obj-$(CONFIG_KGDB)		+= kgdb.o
 obj-$(CONFIG_PROC_FS)		+= proc.o
arch/mips/kernel/entry.S +16 -59

97 lines not on this page · raw message

arch/mips/kernel/linux32.c +0 -1
index 6b61be486303..2b4b1fc1ff1b 100644
@@ -38,7 +38,6 @@
 #include <net/scm.h>
 
 #include <asm/compat-signal.h>
-#include <asm/sim.h>
 #include <linux/uaccess.h>
 #include <asm/mmu_context.h>
 #include <asm/mman.h>
arch/mips/kernel/ptrace.c +0 -78

87 lines not on this page · raw message

arch/mips/kernel/scall.S new file +135 -0

135 lines not on this page · raw message

arch/mips/kernel/scall32-o32.S deleted +0 -223

223 lines not on this page · raw message

arch/mips/kernel/scall64-n32.S deleted +0 -107

107 lines not on this page · raw message

arch/mips/kernel/scall64-n64.S deleted +0 -116

116 lines not on this page · raw message

arch/mips/kernel/scall64-o32.S deleted +0 -221

221 lines not on this page · raw message

arch/mips/kernel/signal.c +11 -24
index f1e985109da0..1ec6a0cf1163 100644
@@ -32,7 +32,6 @@
 #include <linux/bitops.h>
 #include <asm/cacheflush.h>
 #include <asm/fpu.h>
-#include <asm/sim.h>
 #include <asm/ucontext.h>
 #include <asm/cpu-features.h>
 #include <asm/war.h>
@@ -627,7 +626,7 @@ SYSCALL_DEFINE3(sigaction, int, sig, const struct sigaction __user *, act,
 #endif
 
 #ifdef CONFIG_TRAD_SIGNALS
-asmlinkage void sys_sigreturn(void)
+asmlinkage long sys_sigreturn(void)
 {
 	struct sigframe __user *frame;
 	struct pt_regs *regs;
@@ -649,22 +648,16 @@ asmlinkage void sys_sigreturn(void)
 	else if (sig)
 		force_sig(sig);
 
-	/*
-	 * Don't let your children do this ...
-	 */
-	__asm__ __volatile__(
-		"move\t$29, %0\n\t"
-		"j\tsyscall_exit"
-		: /* no outputs */
-		: "r" (regs));
-	/* Unreached */
+	regs->regs[27] = 1;	/* return directly */
+	return regs->regs[2];
 
 badframe:
 	force_sig(SIGSEGV);
+	return 0;
 }
 #endif /* CONFIG_TRAD_SIGNALS */
 
-asmlinkage void sys_rt_sigreturn(void)
+asmlinkage long sys_rt_sigreturn(void)
 {
 	struct rt_sigframe __user *frame;
 	struct pt_regs *regs;
@@ -689,18 +682,12 @@ asmlinkage void sys_rt_sigreturn(void)
 	if (restore_altstack(&frame->rs_uc.uc_stack))
 		goto badframe;
 
-	/*
-	 * Don't let your children do this ...
-	 */
-	__asm__ __volatile__(
-		"move\t$29, %0\n\t"
-		"j\tsyscall_exit"
-		: /* no outputs */
-		: "r" (regs));
-	/* Unreached */
+	regs->regs[27] = 1;	/* return directly */
+	return regs->regs[2];
 
 badframe:
 	force_sig(SIGSEGV);
+	return 0;
 }
 
 #ifdef CONFIG_TRAD_SIGNALS
@@ -852,11 +839,11 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
 	signal_setup_done(ret, ksig, 0);
 }
 
-static void do_signal(struct pt_regs *regs)
+void arch_do_signal_or_restart(struct pt_regs *regs, bool has_signal)
 {
 	struct ksignal ksig;
 
-	if (get_signal(&ksig)) {
+	if (has_signal && get_signal(&ksig)) {
 		/* Whee!  Actually deliver the signal.	*/
 		handle_signal(&ksig, regs);
 		return;
@@ -904,7 +891,7 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, void *unused,
 
 	/* deal with pending signal delivery */
 	if (thread_info_flags & (_TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL))
-		do_signal(regs);
+		arch_do_signal_or_restart(regs, thread_info_flags & _TIF_SIGPENDING);
 
 	if (thread_info_flags & _TIF_NOTIFY_RESUME) {
 		tracehook_notify_resume(regs);
arch/mips/kernel/signal_n32.c +4 -11
index 7bd00fad61af..b52b995a8a9b 100644
@@ -19,7 +19,6 @@
 #include <asm/asm.h>
 #include <asm/cacheflush.h>
 #include <asm/compat-signal.h>
-#include <asm/sim.h>
 #include <linux/uaccess.h>
 #include <asm/ucontext.h>
 #include <asm/fpu.h>
@@ -51,7 +50,7 @@ struct rt_sigframe_n32 {
 	struct ucontextn32 rs_uc;
 };
 
-asmlinkage void sysn32_rt_sigreturn(void)
+asmlinkage long sysn32_rt_sigreturn(void)
 {
 	struct rt_sigframe_n32 __user *frame;
 	struct pt_regs *regs;
@@ -76,18 +75,12 @@ asmlinkage void sysn32_rt_sigreturn(void)
 	if (compat_restore_altstack(&frame->rs_uc.uc_stack))
 		goto badframe;
 
-	/*
-	 * Don't let your children do this ...
-	 */
-	__asm__ __volatile__(
-		"move\t$29, %0\n\t"
-		"j\tsyscall_exit"
-		: /* no outputs */
-		: "r" (regs));
-	/* Unreached */
+	regs->regs[27] = 1;	/* return directly */
+	return regs->regs[2];
 
 badframe:
 	force_sig(SIGSEGV);
+	return 0;
 }
 
 static int setup_rt_frame_n32(void *sig_return, struct ksignal *ksig,
arch/mips/kernel/signal_o32.c +8 -21
index 299a7a28ca33..9245806e06f1 100644
@@ -17,7 +17,6 @@
 #include <asm/abi.h>
 #include <asm/compat-signal.h>
 #include <asm/dsp.h>
-#include <asm/sim.h>
 #include <asm/unistd.h>
 
 #include "signal-common.h"
@@ -151,7 +150,7 @@ static int setup_frame_32(void *sig_return, struct ksignal *ksig,
 	return 0;
 }
 
-asmlinkage void sys32_rt_sigreturn(void)
+asmlinkage long sys32_rt_sigreturn(void)
 {
 	struct rt_sigframe32 __user *frame;
 	struct pt_regs *regs;
@@ -176,18 +175,12 @@ asmlinkage void sys32_rt_sigreturn(void)
 	if (compat_restore_altstack(&frame->rs_uc.uc_stack))
 		goto badframe;
 
-	/*
-	 * Don't let your children do this ...
-	 */
-	__asm__ __volatile__(
-		"move\t$29, %0\n\t"
-		"j\tsyscall_exit"
-		: /* no outputs */
-		: "r" (regs));
-	/* Unreached */
+	regs->regs[27] = 1;	/* return directly */
+	return regs->regs[2];
 
 badframe:
 	force_sig(SIGSEGV);
+	return 0;
 }
 
 static int setup_rt_frame_32(void *sig_return, struct ksignal *ksig,
@@ -253,7 +246,7 @@ struct mips_abi mips_abi_32 = {
 };
 
 
-asmlinkage void sys32_sigreturn(void)
+asmlinkage long sys32_sigreturn(void)
 {
 	struct sigframe32 __user *frame;
 	struct pt_regs *regs;
@@ -275,16 +268,10 @@ asmlinkage void sys32_sigreturn(void)
 	else if (sig)
 		force_sig(sig);
 
-	/*
-	 * Don't let your children do this ...
-	 */
-	__asm__ __volatile__(
-		"move\t$29, %0\n\t"
-		"j\tsyscall_exit"
-		: /* no outputs */
-		: "r" (regs));
-	/* Unreached */
+	regs->regs[27] = 1;	/* return directly */
+	return regs->regs[2];
 
 badframe:
 	force_sig(SIGSEGV);
+	return 0;
 }
arch/mips/kernel/syscall.c +122 -25

178 lines not on this page · raw message

arch/mips/kernel/syscalls/syscall_n32.tbl +4 -4
index 70e32de2bcaa..d9ae765e51f1 100644
@@ -62,8 +62,8 @@
 52	n32	socketpair			sys_socketpair
 53	n32	setsockopt			sys_setsockopt
 54	n32	getsockopt			sys_getsockopt
-55	n32	clone				__sys_clone
-56	n32	fork				__sys_fork
+55	n32	clone				sys_clone
+56	n32	fork				sys_fork
 57	n32	execve				compat_sys_execve
 58	n32	exit				sys_exit
 59	n32	wait4				compat_sys_wait4
@@ -207,7 +207,7 @@
 196	n32	sched_getaffinity		compat_sys_sched_getaffinity
 197	n32	cacheflush			sys_cacheflush
 198	n32	cachectl			sys_cachectl
-199	n32	sysmips				__sys_sysmips
+199	n32	sysmips				sys_sysmips
 200	n32	io_setup			compat_sys_io_setup
 201	n32	io_destroy			sys_io_destroy
 202	n32	io_getevents			sys_io_getevents_time32
@@ -373,7 +373,7 @@
 432	n32	fsmount				sys_fsmount
 433	n32	fspick				sys_fspick
 434	n32	pidfd_open			sys_pidfd_open
-435	n32	clone3				__sys_clone3
+435	n32	clone3				sys_clone3
 436	n32	close_range			sys_close_range
 437	n32	openat2				sys_openat2
 438	n32	pidfd_getfd			sys_pidfd_getfd
arch/mips/kernel/syscalls/syscall_n64.tbl +4 -4
index 1ca7bc337932..edec3e82d67a 100644
@@ -62,8 +62,8 @@
 52	n64	socketpair			sys_socketpair
 53	n64	setsockopt			sys_setsockopt
 54	n64	getsockopt			sys_getsockopt
-55	n64	clone				__sys_clone
-56	n64	fork				__sys_fork
+55	n64	clone				sys_clone
+56	n64	fork				sys_fork
 57	n64	execve				sys_execve
 58	n64	exit				sys_exit
 59	n64	wait4				sys_wait4
@@ -207,7 +207,7 @@
 196	n64	sched_getaffinity		sys_sched_getaffinity
 197	n64	cacheflush			sys_cacheflush
 198	n64	cachectl			sys_cachectl
-199	n64	sysmips				__sys_sysmips
+199	n64	sysmips				sys_sysmips
 200	n64	io_setup			sys_io_setup
 201	n64	io_destroy			sys_io_destroy
 202	n64	io_getevents			sys_io_getevents
@@ -349,7 +349,7 @@
 432	n64	fsmount				sys_fsmount
 433	n64	fspick				sys_fspick
 434	n64	pidfd_open			sys_pidfd_open
-435	n64	clone3				__sys_clone3
+435	n64	clone3				sys_clone3
 436	n64	close_range			sys_close_range
 437	n64	openat2				sys_openat2
 438	n64	pidfd_getfd			sys_pidfd_getfd
arch/mips/kernel/syscalls/syscall_o32.tbl +4 -4
index a61c35edaa74..89a1f267da6a 100644
@@ -9,7 +9,7 @@
 #
 0	o32	syscall				sys_syscall			sys32_syscall
 1	o32	exit				sys_exit
-2	o32	fork				__sys_fork
+2	o32	fork				sys_fork
 3	o32	read				sys_read
 4	o32	write				sys_write
 5	o32	open				sys_open			compat_sys_open
@@ -131,7 +131,7 @@
 117	o32	ipc				sys_ipc				compat_sys_ipc
 118	o32	fsync				sys_fsync
 119	o32	sigreturn			sys_sigreturn			sys32_sigreturn
-120	o32	clone				__sys_clone
+120	o32	clone				sys_clone
 121	o32	setdomainname			sys_setdomainname
 122	o32	uname				sys_newuname
 123	o32	modify_ldt			sys_ni_syscall
@@ -160,7 +160,7 @@
 146	o32	writev				sys_writev
 147	o32	cacheflush			sys_cacheflush
 148	o32	cachectl			sys_cachectl
-149	o32	sysmips				__sys_sysmips
+149	o32	sysmips				sys_sysmips
 150	o32	unused150			sys_ni_syscall
 151	o32	getsid				sys_getsid
 152	o32	fdatasync			sys_fdatasync
@@ -422,7 +422,7 @@
 432	o32	fsmount				sys_fsmount
 433	o32	fspick				sys_fspick
 434	o32	pidfd_open			sys_pidfd_open
-435	o32	clone3				__sys_clone3
+435	o32	clone3				sys_clone3
 436	o32	close_range			sys_close_range
 437	o32	openat2				sys_openat2
 438	o32	pidfd_getfd			sys_pidfd_getfd
Signature · 1 line
2.27.0
Reviewed-by on v1 1/2
#2 lore raw

Re: [PATCH 1/2] mips: convert syscall to generic entry

Quoted 16 lines · FreeFlyingSheep

From: Feiyang Chen <[email protected]>

Convert mips syscall to use the generic entry infrastructure from kernel/entry/*.

There are a few special things on mips:

- There is one type of syscall on mips32 (scall32-o32) and three types of syscalls on mips64 (scall64-o32, scall64-n32 and scall64-n64). Now convert to C code to handle different types of syscalls.

- For some special syscalls (e.g. fork, clone, clone3 and sysmips), save_static_function() wrapper is used to save static registers. Now SAVE_STATIC is used in handle_sys before calling do_syscall(), so the save_static_function() wrapper can be removed.

Quoted 5 lines

- For sigreturn/rt_sigreturn and sysmips, inline assembly is used to jump to syscall_exit directly for skipping setting the error flag and restoring all registers. Now use regs->regs[27] to mark whether to handle the error flag and always restore all registers in handle_sys, so these functions can return normally as other architecture.

Hmm, that would give us overhead of register context on these syscalls.

I guess it's worthy?

Quoted 3 lines

For the code,

After spending 3hrs diving into syscall handling hell, I must say you've done a good job. I'll start a LTP run to see if we miss any corner cases. And left IRQ part for another trial.

Thanks.

Jiaxun

Quoted 1,817 lines
---
  arch/mips/Kconfig                         |   1 +
  arch/mips/include/asm/entry-common.h      |  13 ++
  arch/mips/include/asm/ptrace.h            |   8 +-
  arch/mips/include/asm/sim.h               |  70 -------
  arch/mips/include/asm/syscall.h           |   5 +
  arch/mips/include/asm/thread_info.h       |  17 +-
  arch/mips/include/uapi/asm/ptrace.h       |   7 +-
  arch/mips/kernel/Makefile                 |  14 +-
  arch/mips/kernel/entry.S                  |  75 ++------
  arch/mips/kernel/linux32.c                |   1 -
  arch/mips/kernel/ptrace.c                 |  78 --------
  arch/mips/kernel/scall.S                  | 135 +++++++++++++
  arch/mips/kernel/scall32-o32.S            | 223 ----------------------
  arch/mips/kernel/scall64-n32.S            | 107 -----------
  arch/mips/kernel/scall64-n64.S            | 116 -----------
  arch/mips/kernel/scall64-o32.S            | 221 ---------------------
  arch/mips/kernel/signal.c                 |  35 ++--
  arch/mips/kernel/signal_n32.c             |  15 +-
  arch/mips/kernel/signal_o32.c             |  29 +--
  arch/mips/kernel/syscall.c                | 147 +++++++++++---
  arch/mips/kernel/syscalls/syscall_n32.tbl |   8 +-
  arch/mips/kernel/syscalls/syscall_n64.tbl |   8 +-
  arch/mips/kernel/syscalls/syscall_o32.tbl |   8 +-
  23 files changed, 346 insertions(+), 995 deletions(-)

create mode 100644 arch/mips/include/asm/entry-common.h delete mode 100644 arch/mips/include/asm/sim.h create mode 100644 arch/mips/kernel/scall.S delete mode 100644 arch/mips/kernel/scall32-o32.S delete mode 100644 arch/mips/kernel/scall64-n32.S delete mode 100644 arch/mips/kernel/scall64-n64.S delete mode 100644 arch/mips/kernel/scall64-o32.S

arch/mips/Kconfig +1 -0
index 0cf31a6cbee1..61aa125aa2da 100644
@@ -32,6 +32,7 @@ config MIPS
  	select GENERIC_ATOMIC64 if !64BIT
  	select GENERIC_CMOS_UPDATE
  	select GENERIC_CPU_AUTOPROBE
+	select GENERIC_ENTRY
  	select GENERIC_GETTIMEOFDAY
  	select GENERIC_IOMAP
  	select GENERIC_IRQ_PROBE
arch/mips/include/asm/entry-common.h new file +13 -0
new file mode 100644
index 000000000000..0fe2a098ded9
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef ARCH_LOONGARCH_ENTRY_COMMON_H
+#define ARCH_LOONGARCH_ENTRY_COMMON_H
+
+#include <linux/sched.h>
+#include <linux/processor.h>
+
+static inline bool on_thread_stack(void)
+{
+	return !(((unsigned long)(current->stack) ^ current_stack_pointer) & ~(THREAD_SIZE - 1));
+}
+
+#endif
arch/mips/include/asm/ptrace.h +5 -3
index daf3cf244ea9..1b8f9d2ddc44 100644
@@ -51,6 +51,11 @@ struct pt_regs {
  	unsigned long __last[0];
  } __aligned(8);
 
+static inline int regs_irqs_disabled(struct pt_regs *regs)
+{
+	return arch_irqs_disabled_flags(regs->cp0_status);
+}
+
  static inline unsigned long kernel_stack_pointer(struct pt_regs *regs)
  {
  	return regs->regs[29];
@@ -156,9 +161,6 @@ static inline long regs_return_value(struct pt_regs *regs)
  #define instruction_pointer(regs) ((regs)->cp0_epc)
  #define profile_pc(regs) instruction_pointer(regs)
 
-extern asmlinkage long syscall_trace_enter(struct pt_regs *regs, long syscall);
-extern asmlinkage void syscall_trace_leave(struct pt_regs *regs);
-
  extern void die(const char *, struct pt_regs *) __noreturn;
 
  static inline void die_if_kernel(const char *str, struct pt_regs *regs)
arch/mips/include/asm/sim.h deleted +0 -70
deleted file mode 100644
index 59f31a95facd..000000000000
@@ -1,70 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1999, 2000, 2003 Ralf Baechle
- * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
- */
-#ifndef _ASM_SIM_H
-#define _ASM_SIM_H
-
-
-#include <asm/asm-offsets.h>
-
-#define __str2(x) #x
-#define __str(x) __str2(x)
-
-#ifdef CONFIG_32BIT
-
-#define save_static_function(symbol)					\
-__asm__(								\
-	".text\n\t"							\
-	".globl\t__" #symbol "\n\t"					\
-	".align\t2\n\t"							\
-	".type\t__" #symbol ", @function\n\t"				\
-	".ent\t__" #symbol ", 0\n__"					\
-	#symbol":\n\t"							\
-	".frame\t$29, 0, $31\n\t"					\
-	"sw\t$16,"__str(PT_R16)"($29)\t\t\t# save_static_function\n\t"	\
-	"sw\t$17,"__str(PT_R17)"($29)\n\t"				\
-	"sw\t$18,"__str(PT_R18)"($29)\n\t"				\
-	"sw\t$19,"__str(PT_R19)"($29)\n\t"				\
-	"sw\t$20,"__str(PT_R20)"($29)\n\t"				\
-	"sw\t$21,"__str(PT_R21)"($29)\n\t"				\
-	"sw\t$22,"__str(PT_R22)"($29)\n\t"				\
-	"sw\t$23,"__str(PT_R23)"($29)\n\t"				\
-	"sw\t$30,"__str(PT_R30)"($29)\n\t"				\
-	"j\t" #symbol "\n\t"						\
-	".end\t__" #symbol "\n\t"					\
-	".size\t__" #symbol",. - __" #symbol)
-
-#endif /* CONFIG_32BIT */
-
-#ifdef CONFIG_64BIT
-
-#define save_static_function(symbol)					\
-__asm__(								\
-	".text\n\t"							\
-	".globl\t__" #symbol "\n\t"					\
-	".align\t2\n\t"							\
-	".type\t__" #symbol ", @function\n\t"				\
-	".ent\t__" #symbol ", 0\n__"					\
-	#symbol":\n\t"							\
-	".frame\t$29, 0, $31\n\t"					\
-	"sd\t$16,"__str(PT_R16)"($29)\t\t\t# save_static_function\n\t"	\
-	"sd\t$17,"__str(PT_R17)"($29)\n\t"				\
-	"sd\t$18,"__str(PT_R18)"($29)\n\t"				\
-	"sd\t$19,"__str(PT_R19)"($29)\n\t"				\
-	"sd\t$20,"__str(PT_R20)"($29)\n\t"				\
-	"sd\t$21,"__str(PT_R21)"($29)\n\t"				\
-	"sd\t$22,"__str(PT_R22)"($29)\n\t"				\
-	"sd\t$23,"__str(PT_R23)"($29)\n\t"				\
-	"sd\t$30,"__str(PT_R30)"($29)\n\t"				\
-	"j\t" #symbol "\n\t"						\
-	".end\t__" #symbol "\n\t"					\
-	".size\t__" #symbol",. - __" #symbol)
-
-#endif /* CONFIG_64BIT */
-
-#endif /* _ASM_SIM_H */
arch/mips/include/asm/syscall.h +5 -0
index 25fa651c937d..02ca0d659428 100644
@@ -157,4 +157,9 @@ static inline int syscall_get_arch(struct task_struct *task)
  	return arch;
  }
 
+static inline bool arch_syscall_is_vdso_sigreturn(struct pt_regs *regs)
+{
+	return false;
+}
+
  #endif	/* __ASM_MIPS_SYSCALL_H */
arch/mips/include/asm/thread_info.h +4 -13
index 0b17aaa9e012..5a5237413065 100644
@@ -29,7 +29,8 @@ struct thread_info {
  	__u32			cpu;		/* current CPU */
  	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
  	struct pt_regs		*regs;
-	long			syscall;	/* syscall number */
+	unsigned long		syscall;	/* syscall number */
+	unsigned long		syscall_work;	/* SYSCALL_WORK_ flags */
  };
 
  /*
@@ -69,6 +70,8 @@ static inline struct thread_info *current_thread_info(void)
  	return __current_thread_info;
  }
 
+register unsigned long current_stack_pointer __asm__("$29");
+
  #endif /* !__ASSEMBLY__ */
 
  /* thread information allocation */
@@ -149,22 +152,10 @@ static inline struct thread_info *current_thread_info(void)
  #define _TIF_MSA_CTX_LIVE	(1<<TIF_MSA_CTX_LIVE)
  #define _TIF_SYSCALL_TRACEPOINT	(1<<TIF_SYSCALL_TRACEPOINT)
 
-#define _TIF_WORK_SYSCALL_ENTRY	(_TIF_NOHZ | _TIF_SYSCALL_TRACE |	\
-				 _TIF_SYSCALL_AUDIT | \
-				 _TIF_SYSCALL_TRACEPOINT | _TIF_SECCOMP)
-
-/* work to do in syscall_trace_leave() */
-#define _TIF_WORK_SYSCALL_EXIT	(_TIF_NOHZ | _TIF_SYSCALL_TRACE |	\
-				 _TIF_SYSCALL_AUDIT | _TIF_SYSCALL_TRACEPOINT)
-
  /* work to do on interrupt/exception return */
  #define _TIF_WORK_MASK		\
  	(_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_NOTIFY_RESUME |	\
  	 _TIF_UPROBE | _TIF_NOTIFY_SIGNAL)
-/* work to do on any return to u-space */
-#define _TIF_ALLWORK_MASK	(_TIF_NOHZ | _TIF_WORK_MASK |		\
-				 _TIF_WORK_SYSCALL_EXIT |		\
-				 _TIF_SYSCALL_TRACEPOINT)
 
  /*
   * We stash processor id into a COP0 register to retrieve it fast
arch/mips/include/uapi/asm/ptrace.h +4 -3
index f3c025445e45..27e2c85398bc 100644
@@ -102,8 +102,9 @@ struct pt_watch_regs {
  	};
  };
 
-#define PTRACE_GET_WATCH_REGS	0xd0
-#define PTRACE_SET_WATCH_REGS	0xd1
-
+#define PTRACE_SYSEMU			0x1f
+#define PTRACE_SYSEMU_SINGLESTEP	0x20
+#define PTRACE_GET_WATCH_REGS		0xd0
+#define PTRACE_SET_WATCH_REGS		0xd1
 
  #endif /* _UAPI_ASM_PTRACE_H */
arch/mips/kernel/Makefile +6 -8
index 814b3da30501..44875660f6ae 100644
@@ -5,10 +5,10 @@
 
  extra-y		:= head.o vmlinux.lds
 
-obj-y		+= branch.o cmpxchg.o elf.o entry.o genex.o idle.o irq.o \
-		   process.o prom.o ptrace.o reset.o setup.o signal.o \
-		   syscall.o time.o topology.o traps.o unaligned.o watch.o \
-		   vdso.o cacheinfo.o
+obj-y		+= branch.o cacheinfo.o cmpxchg.o elf.o entry.o genex.o \
+		   idle.o irq.o process.o prom.o ptrace.o reset.o scall.o \
+		   setup.o signal.o syscall.o time.o topology.o traps.o \
+		   unaligned.o watch.o vdso.o
 
  ifdef CONFIG_CPU_R3K_TLB
  obj-y		+= cpu-r3k-probe.o
@@ -76,11 +76,9 @@ obj-$(CONFIG_IRQ_TXX9)		+= irq_txx9.o
  obj-$(CONFIG_IRQ_GT641XX)	+= irq-gt641xx.o
 
  obj-$(CONFIG_KPROBES)		+= kprobes.o
-obj-$(CONFIG_32BIT)		+= scall32-o32.o
-obj-$(CONFIG_64BIT)		+= scall64-n64.o
  obj-$(CONFIG_MIPS32_COMPAT)	+= linux32.o ptrace32.o signal32.o
-obj-$(CONFIG_MIPS32_N32)	+= scall64-n32.o signal_n32.o
-obj-$(CONFIG_MIPS32_O32)	+= scall64-o32.o signal_o32.o
+obj-$(CONFIG_MIPS32_N32)	+= signal_n32.o
+obj-$(CONFIG_MIPS32_O32)	+= signal_o32.o
 
  obj-$(CONFIG_KGDB)		+= kgdb.o
  obj-$(CONFIG_PROC_FS)		+= proc.o
arch/mips/kernel/entry.S +16 -59
index 4b896f5023ff..1a2aec9dab1b 100644
@@ -72,49 +72,32 @@ FEXPORT(ret_from_kernel_thread)
  	jal	schedule_tail		# a0 = struct task_struct *prev
  	move	a0, s1
  	jal	s0
-	j	syscall_exit
+	move	a0, sp
+	jal	syscall_exit_to_user_mode
+
+	.set	noat
+	RESTORE_STATIC
+	RESTORE_SOME
+	RESTORE_SP_AND_RET
+	.set	at
 
  FEXPORT(ret_from_fork)
  	jal	schedule_tail		# a0 = struct task_struct *prev
-
-FEXPORT(syscall_exit)
-#ifdef CONFIG_DEBUG_RSEQ
  	move	a0, sp
-	jal	rseq_syscall
-#endif
-	local_irq_disable		# make sure need_resched and
-					# signals dont change between
-					# sampling and return
-	LONG_L	a2, TI_FLAGS($28)	# current->work
-	li	t0, _TIF_ALLWORK_MASK
-	and	t0, a2, t0
-	bnez	t0, syscall_exit_work
+	jal	syscall_exit_to_user_mode
 
-restore_all:				# restore full frame
  	.set	noat
-	RESTORE_TEMP
-	RESTORE_AT
  	RESTORE_STATIC
-restore_partial:		# restore partial frame
-#ifdef CONFIG_TRACE_IRQFLAGS
-	SAVE_STATIC
-	SAVE_AT
-	SAVE_TEMP
-	LONG_L	v0, PT_STATUS(sp)
-#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
-	and	v0, ST0_IEP
-#else
-	and	v0, ST0_IE
-#endif
-	beqz	v0, 1f
-	jal	trace_hardirqs_on
-	b	2f
-1:	jal	trace_hardirqs_off
-2:
+	RESTORE_SOME
+	RESTORE_SP_AND_RET
+	.set	at
+
+restore_all:				# restore full frame
+	.set	noat
  	RESTORE_TEMP
  	RESTORE_AT
  	RESTORE_STATIC
-#endif
+restore_partial:			# restore partial frame
  	RESTORE_SOME
  	RESTORE_SP_AND_RET
  	.set	at
@@ -143,32 +126,6 @@ work_notifysig:				# deal with pending signals and
  	jal	do_notify_resume	# a2 already loaded
  	j	resume_userspace_check
 
-FEXPORT(syscall_exit_partial)
-#ifdef CONFIG_DEBUG_RSEQ
-	move	a0, sp
-	jal	rseq_syscall
-#endif
-	local_irq_disable		# make sure need_resched doesn't
-					# change between and return
-	LONG_L	a2, TI_FLAGS($28)	# current->work
-	li	t0, _TIF_ALLWORK_MASK
-	and	t0, a2
-	beqz	t0, restore_partial
-	SAVE_STATIC
-syscall_exit_work:
-	LONG_L	t0, PT_STATUS(sp)		# returning to kernel mode?
-	andi	t0, t0, KU_USER
-	beqz	t0, resume_kernel
-	li	t0, _TIF_WORK_SYSCALL_EXIT
-	and	t0, a2			# a2 is preloaded with TI_FLAGS
-	beqz	t0, work_pending	# trace bit set?
-	local_irq_enable		# could let syscall_trace_leave()
-					# call schedule() instead
-	TRACE_IRQS_ON
-	move	a0, sp
-	jal	syscall_trace_leave
-	b	resume_userspace
-
  #if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR5) || \
      defined(CONFIG_CPU_MIPSR6) || defined(CONFIG_MIPS_MT)
 
arch/mips/kernel/linux32.c +0 -1
index 6b61be486303..2b4b1fc1ff1b 100644
@@ -38,7 +38,6 @@
  #include <net/scm.h>
 
  #include <asm/compat-signal.h>
-#include <asm/sim.h>
  #include <linux/uaccess.h>
  #include <asm/mmu_context.h>
  #include <asm/mman.h>
arch/mips/kernel/ptrace.c +0 -78
index db7c5be1d4a3..04c08e41cfd3 100644
@@ -46,9 +46,6 @@
  #include <asm/bootinfo.h>
  #include <asm/reg.h>
 
-#define CREATE_TRACE_POINTS
-#include <trace/events/syscalls.h>
-
  /*
   * Called by kernel/ptrace.c when detaching..
   *
@@ -1305,78 +1302,3 @@ long arch_ptrace(struct task_struct *child, long request,
   out:
  	return ret;
  }
-
-/*
- * Notification of system call entry/exit
- * - triggered by current->work.syscall_trace
- */
-asmlinkage long syscall_trace_enter(struct pt_regs *regs, long syscall)
-{
-	user_exit();
-
-	current_thread_info()->syscall = syscall;
-
-	if (test_thread_flag(TIF_SYSCALL_TRACE)) {
-		if (tracehook_report_syscall_entry(regs))
-			return -1;
-		syscall = current_thread_info()->syscall;
-	}
-
-#ifdef CONFIG_SECCOMP
-	if (unlikely(test_thread_flag(TIF_SECCOMP))) {
-		int ret, i;
-		struct seccomp_data sd;
-		unsigned long args[6];
-
-		sd.nr = syscall;
-		sd.arch = syscall_get_arch(current);
-		syscall_get_arguments(current, regs, args);
-		for (i = 0; i < 6; i++)
-			sd.args[i] = args[i];
-		sd.instruction_pointer = KSTK_EIP(current);
-
-		ret = __secure_computing(&sd);
-		if (ret == -1)
-			return ret;
-		syscall = current_thread_info()->syscall;
-	}
-#endif
-
-	if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
-		trace_sys_enter(regs, regs->regs[2]);
-
-	audit_syscall_entry(syscall, regs->regs[4], regs->regs[5],
-			    regs->regs[6], regs->regs[7]);
-
-	/*
-	 * Negative syscall numbers are mistaken for rejected syscalls, but
-	 * won't have had the return value set appropriately, so we do so now.
-	 */
-	if (syscall < 0)
-		syscall_set_return_value(current, regs, -ENOSYS, 0);
-	return syscall;
-}
-
-/*
- * Notification of system call entry/exit
- * - triggered by current->work.syscall_trace
- */
-asmlinkage void syscall_trace_leave(struct pt_regs *regs)
-{
-        /*
-	 * We may come here right after calling schedule_user()
-	 * or do_notify_resume(), in which case we can be in RCU
-	 * user mode.
-	 */
-	user_exit();
-
-	audit_syscall_exit(regs);
-
-	if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
-		trace_sys_exit(regs, regs_return_value(regs));
-
-	if (test_thread_flag(TIF_SYSCALL_TRACE))
-		tracehook_report_syscall_exit(regs, 0);
-
-	user_enter();
-}
arch/mips/kernel/scall.S new file +135 -0
new file mode 100644
index 000000000000..7b35969151de
@@ -0,0 +1,135 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 1995, 96, 97, 98, 99, 2000, 01, 02 by Ralf Baechle
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
+ * Copyright (C) 2001 MIPS Technologies, Inc.
+ * Copyright (C) 2004 Thiemo Seufer
+ * Copyright (C) 2014 Imagination Technologies Ltd.
+ */
+#include <linux/errno.h>
+#include <asm/asm.h>
+#include <asm/asmmacro.h>
+#include <asm/irqflags.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+#include <asm/asm-offsets.h>
+#include <asm/sysmips.h>
+#include <asm/thread_info.h>
+#include <asm/unistd.h>
+#include <asm/war.h>
+
+	.align	5
+NESTED(handle_sys, PT_SIZE, sp)
+	.set	noat
+	SAVE_SOME
+	SAVE_STATIC
+	CLI
+	.set	at
+
+	move	a0, sp
+	jal	do_syscall
+
+	.set	noat
+	RESTORE_TEMP
+	RESTORE_AT
+	RESTORE_STATIC
+	RESTORE_SOME
+	RESTORE_SP_AND_RET
+	.set	at
+	END(handle_sys)
+
+#ifdef CONFIG_32BIT
+LEAF(sys_syscall)
+	subu	t0, a0, __NR_O32_Linux		# check syscall number
+	sltiu	v0, t0, __NR_O32_Linux_syscalls
+	beqz	t0, einval			# do not recurse
+	sll	t1, t0, 2
+	beqz	v0, einval
+	lw	t2, sys_call_table(t1)		# syscall routine
+
+	move	a0, a1				# shift argument registers
+	move	a1, a2
+	move	a2, a3
+	lw	a3, 16(sp)
+	lw	t4, 20(sp)
+	lw	t5, 24(sp)
+	lw	t6, 28(sp)
+	sw	t4, 16(sp)
+	sw	t5, 20(sp)
+	sw	t6, 24(sp)
+	jr	t2
+	/* Unreached */
+
+einval: li	v0, -ENOSYS
+	jr	ra
+	END(sys_syscall)
+
+#ifdef CONFIG_MIPS_MT_FPAFF
+	/*
+	 * For FPU affinity scheduling on MIPS MT processors, we need to
+	 * intercept sys_sched_xxxaffinity() calls until we get a proper hook
+	 * in kernel/sched/core.c.  Considered only temporary we only support
+	 * these hooks for the 32-bit kernel - there is no MIPS64 MT processor
+	 * atm.
+	 */
+#define sys_sched_setaffinity	mipsmt_sys_sched_setaffinity
+#define sys_sched_getaffinity	mipsmt_sys_sched_getaffinity
+#endif /* CONFIG_MIPS_MT_FPAFF */
+
+#define __SYSCALL_WITH_COMPAT(nr, native, compat)	__SYSCALL(nr, native)
+#define __SYSCALL(nr, entry) 	PTR entry
+	.align	2
+	.type	sys_call_table, @object
+EXPORT(sys_call_table)
+#include <asm/syscall_table_o32.h>
+#endif /* CONFIG_32BIT */
+
+#ifdef CONFIG_64BIT
+#ifdef CONFIG_MIPS32_O32
+LEAF(sys32_syscall)
+	subu	t0, a0, __NR_O32_Linux		# check syscall number
+	sltiu	v0, t0, __NR_O32_Linux_syscalls
+	beqz	t0, einval			# do not recurse
+	dsll	t1, t0, 3
+	beqz	v0, einval
+	ld	t2, sys32_call_table(t1)	# syscall routine
+
+	move	a0, a1				# shift argument registers
+	move	a1, a2
+	move	a2, a3
+	move	a3, a4
+	move	a4, a5
+	move	a5, a6
+	move	a6, a7
+	jr	t2
+	/* Unreached */
+
+einval: li	v0, -ENOSYS
+	jr	ra
+	END(sys32_syscall)
+
+#define __SYSCALL_WITH_COMPAT(nr, native, compat)	__SYSCALL(nr, compat)
+#define __SYSCALL(nr, entry)	PTR entry
+	.align	3
+	.type	sys32_call_table,@object
+EXPORT(sys32_call_table)
+#include <asm/syscall_table_o32.h>
+#endif /* CONFIG_MIPS32_O32 */
+
+#ifdef CONFIG_MIPS32_N32
+#undef __SYSCALL
+#define __SYSCALL(nr, entry)	PTR entry
+	.align	3
+	.type	sysn32_call_table, @object
+EXPORT(sysn32_call_table)
+#include <asm/syscall_table_n32.h>
+#endif /* CONFIG_MIPS32_N32 */
+
+#undef __SYSCALL
+#define __SYSCALL(nr, entry)	PTR entry
+	.align	3
+	.type	sys_call_table, @object
+EXPORT(sys_call_table)
+#include <asm/syscall_table_n64.h>
+#endif /* CONFIG_64BIT */
arch/mips/kernel/scall32-o32.S deleted +0 -223
deleted file mode 100644
index b1b2e106f711..000000000000
@@ -1,223 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1995-99, 2000- 02, 06 Ralf Baechle <[email protected]>
- * Copyright (C) 2001 MIPS Technologies, Inc.
- * Copyright (C) 2004 Thiemo Seufer
- * Copyright (C) 2014 Imagination Technologies Ltd.
- */
-#include <linux/errno.h>
-#include <asm/asm.h>
-#include <asm/asmmacro.h>
-#include <asm/irqflags.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-#include <asm/isadep.h>
-#include <asm/sysmips.h>
-#include <asm/thread_info.h>
-#include <asm/unistd.h>
-#include <asm/war.h>
-#include <asm/asm-offsets.h>
-
-	.align	5
-NESTED(handle_sys, PT_SIZE, sp)
-	.set	noat
-	SAVE_SOME
-	TRACE_IRQS_ON_RELOAD
-	STI
-	.set	at
-
-	lw	t1, PT_EPC(sp)		# skip syscall on return
-
-	addiu	t1, 4			# skip to next instruction
-	sw	t1, PT_EPC(sp)
-
-	sw	a3, PT_R26(sp)		# save a3 for syscall restarting
-
-	/*
-	 * More than four arguments.  Try to deal with it by copying the
-	 * stack arguments from the user stack to the kernel stack.
-	 * This Sucks (TM).
-	 */
-	lw	t0, PT_R29(sp)		# get old user stack pointer
-
-	/*
-	 * We intentionally keep the kernel stack a little below the top of
-	 * userspace so we don't have to do a slower byte accurate check here.
-	 */
-	addu	t4, t0, 32
-	bltz	t4, bad_stack		# -> sp is bad
-
-	/*
-	 * Ok, copy the args from the luser stack to the kernel stack.
-	 */
-
-	.set    push
-	.set    noreorder
-	.set	nomacro
-
-load_a4: user_lw(t5, 16(t0))		# argument #5 from usp
-load_a5: user_lw(t6, 20(t0))		# argument #6 from usp
-load_a6: user_lw(t7, 24(t0))		# argument #7 from usp
-load_a7: user_lw(t8, 28(t0))		# argument #8 from usp
-loads_done:
-
-	sw	t5, 16(sp)		# argument #5 to ksp
-	sw	t6, 20(sp)		# argument #6 to ksp
-	sw	t7, 24(sp)		# argument #7 to ksp
-	sw	t8, 28(sp)		# argument #8 to ksp
-	.set	pop
-
-	.section __ex_table,"a"
-	PTR	load_a4, bad_stack_a4
-	PTR	load_a5, bad_stack_a5
-	PTR	load_a6, bad_stack_a6
-	PTR	load_a7, bad_stack_a7
-	.previous
-
-	lw	t0, TI_FLAGS($28)	# syscall tracing enabled?
-	li	t1, _TIF_WORK_SYSCALL_ENTRY
-	and	t0, t1
-	bnez	t0, syscall_trace_entry # -> yes
-syscall_common:
-	subu	v0, v0, __NR_O32_Linux	# check syscall number
-	sltiu	t0, v0, __NR_O32_Linux_syscalls
-	beqz	t0, illegal_syscall
-
-	sll	t0, v0, 2
-	la	t1, sys_call_table
-	addu	t1, t0
-	lw	t2, (t1)		# syscall routine
-
-	beqz	t2, illegal_syscall
-
-	jalr	t2			# Do The Real Thing (TM)
-
-	li	t0, -EMAXERRNO - 1	# error?
-	sltu	t0, t0, v0
-	sw	t0, PT_R7(sp)		# set error flag
-	beqz	t0, 1f
-
-	lw	t1, PT_R2(sp)		# syscall number
-	negu	v0			# error
-	sw	t1, PT_R0(sp)		# save it for syscall restarting
-1:	sw	v0, PT_R2(sp)		# result
-
-o32_syscall_exit:
-	j	syscall_exit_partial
-
-/* ------------------------------------------------------------------------ */
-
-syscall_trace_entry:
-	SAVE_STATIC
-	move	a0, sp
-
-	/*
-	 * syscall number is in v0 unless we called syscall(__NR_###)
-	 * where the real syscall number is in a0
-	 */
-	move	a1, v0
-	subu	t2, v0,  __NR_O32_Linux
-	bnez	t2, 1f /* __NR_syscall at offset 0 */
-	lw	a1, PT_R4(sp)
-
-1:	jal	syscall_trace_enter
-
-	bltz	v0, 1f			# seccomp failed? Skip syscall
-
-	RESTORE_STATIC
-	lw	v0, PT_R2(sp)		# Restore syscall (maybe modified)
-	lw	a0, PT_R4(sp)		# Restore argument registers
-	lw	a1, PT_R5(sp)
-	lw	a2, PT_R6(sp)
-	lw	a3, PT_R7(sp)
-	j	syscall_common
-
-1:	j	syscall_exit
-
-/* ------------------------------------------------------------------------ */
-
-	/*
-	 * Our open-coded access area sanity test for the stack pointer
-	 * failed. We probably should handle this case a bit more drastic.
-	 */
-bad_stack:
-	li	v0, EFAULT
-	sw	v0, PT_R2(sp)
-	li	t0, 1				# set error flag
-	sw	t0, PT_R7(sp)
-	j	o32_syscall_exit
-
-bad_stack_a4:
-	li	t5, 0
-	b	load_a5
-
-bad_stack_a5:
-	li	t6, 0
-	b	load_a6
-
-bad_stack_a6:
-	li	t7, 0
-	b	load_a7
-
-bad_stack_a7:
-	li	t8, 0
-	b	loads_done
-
-	/*
-	 * The system call does not exist in this kernel
-	 */
-illegal_syscall:
-	li	v0, ENOSYS			# error
-	sw	v0, PT_R2(sp)
-	li	t0, 1				# set error flag
-	sw	t0, PT_R7(sp)
-	j	o32_syscall_exit
-	END(handle_sys)
-
-	LEAF(sys_syscall)
-	subu	t0, a0, __NR_O32_Linux	# check syscall number
-	sltiu	v0, t0, __NR_O32_Linux_syscalls
-	beqz	t0, einval		# do not recurse
-	sll	t1, t0, 2
-	beqz	v0, einval
-	lw	t2, sys_call_table(t1)		# syscall routine
-
-	move	a0, a1				# shift argument registers
-	move	a1, a2
-	move	a2, a3
-	lw	a3, 16(sp)
-	lw	t4, 20(sp)
-	lw	t5, 24(sp)
-	lw	t6, 28(sp)
-	sw	t4, 16(sp)
-	sw	t5, 20(sp)
-	sw	t6, 24(sp)
-	jr	t2
-	/* Unreached */
-
-einval: li	v0, -ENOSYS
-	jr	ra
-	END(sys_syscall)
-
-#ifdef CONFIG_MIPS_MT_FPAFF
-	/*
-	 * For FPU affinity scheduling on MIPS MT processors, we need to
-	 * intercept sys_sched_xxxaffinity() calls until we get a proper hook
-	 * in kernel/sched/core.c.  Considered only temporary we only support
-	 * these hooks for the 32-bit kernel - there is no MIPS64 MT processor
-	 * atm.
-	 */
-#define sys_sched_setaffinity	mipsmt_sys_sched_setaffinity
-#define sys_sched_getaffinity	mipsmt_sys_sched_getaffinity
-#endif /* CONFIG_MIPS_MT_FPAFF */
-
-#define __SYSCALL_WITH_COMPAT(nr, native, compat)	__SYSCALL(nr, native)
-#define __SYSCALL(nr, entry) 	PTR entry
-	.align	2
-	.type	sys_call_table, @object
-EXPORT(sys_call_table)
-#include <asm/syscall_table_o32.h>
arch/mips/kernel/scall64-n32.S deleted +0 -107
deleted file mode 100644
index f650c55a17dc..000000000000
@@ -1,107 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1995, 96, 97, 98, 99, 2000, 01 by Ralf Baechle
- * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
- * Copyright (C) 2001 MIPS Technologies, Inc.
- */
-#include <linux/errno.h>
-#include <asm/asm.h>
-#include <asm/asmmacro.h>
-#include <asm/irqflags.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-#include <asm/thread_info.h>
-#include <asm/unistd.h>
-
-#ifndef CONFIG_MIPS32_O32
-/* No O32, so define handle_sys here */
-#define handle_sysn32 handle_sys
-#endif
-
-	.align	5
-NESTED(handle_sysn32, PT_SIZE, sp)
-#ifndef CONFIG_MIPS32_O32
-	.set	noat
-	SAVE_SOME
-	TRACE_IRQS_ON_RELOAD
-	STI
-	.set	at
-#endif
-
-	dsubu	t0, v0, __NR_N32_Linux	# check syscall number
-	sltiu	t0, t0, __NR_N32_Linux_syscalls
-
-#ifndef CONFIG_MIPS32_O32
-	ld	t1, PT_EPC(sp)		# skip syscall on return
-	daddiu	t1, 4			# skip to next instruction
-	sd	t1, PT_EPC(sp)
-#endif
-	beqz	t0, not_n32_scall
-
-	sd	a3, PT_R26(sp)		# save a3 for syscall restarting
-
-	li	t1, _TIF_WORK_SYSCALL_ENTRY
-	LONG_L	t0, TI_FLAGS($28)	# syscall tracing enabled?
-	and	t0, t1, t0
-	bnez	t0, n32_syscall_trace_entry
-
-syscall_common:
-	dsll	t0, v0, 3		# offset into table
-	ld	t2, (sysn32_call_table - (__NR_N32_Linux * 8))(t0)
-
-	jalr	t2			# Do The Real Thing (TM)
-
-	li	t0, -EMAXERRNO - 1	# error?
-	sltu	t0, t0, v0
-	sd	t0, PT_R7(sp)		# set error flag
-	beqz	t0, 1f
-
-	ld	t1, PT_R2(sp)		# syscall number
-	dnegu	v0			# error
-	sd	t1, PT_R0(sp)		# save it for syscall restarting
-1:	sd	v0, PT_R2(sp)		# result
-
-	j	syscall_exit_partial
-
-/* ------------------------------------------------------------------------ */
-
-n32_syscall_trace_entry:
-	SAVE_STATIC
-	move	a0, sp
-	move	a1, v0
-	jal	syscall_trace_enter
-
-	bltz	v0, 1f			# seccomp failed? Skip syscall
-
-	RESTORE_STATIC
-	ld	v0, PT_R2(sp)		# Restore syscall (maybe modified)
-	ld	a0, PT_R4(sp)		# Restore argument registers
-	ld	a1, PT_R5(sp)
-	ld	a2, PT_R6(sp)
-	ld	a3, PT_R7(sp)
-	ld	a4, PT_R8(sp)
-	ld	a5, PT_R9(sp)
-
-	dsubu	t2, v0, __NR_N32_Linux	# check (new) syscall number
-	sltiu   t0, t2, __NR_N32_Linux_syscalls
-	beqz	t0, not_n32_scall
-
-	j	syscall_common
-
-1:	j	syscall_exit
-
-not_n32_scall:
-	/* This is not an n32 compatibility syscall, pass it on to
-	   the n64 syscall handlers.  */
-	j	handle_sys64
-
-	END(handle_sysn32)
-
-#define __SYSCALL(nr, entry)	PTR entry
-	.type	sysn32_call_table, @object
-EXPORT(sysn32_call_table)
-#include <asm/syscall_table_n32.h>
arch/mips/kernel/scall64-n64.S deleted +0 -116
deleted file mode 100644
index 5d7bfc65e4d0..000000000000
@@ -1,116 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1995, 96, 97, 98, 99, 2000, 01, 02 by Ralf Baechle
- * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
- * Copyright (C) 2001 MIPS Technologies, Inc.
- */
-#include <linux/errno.h>
-#include <asm/asm.h>
-#include <asm/asmmacro.h>
-#include <asm/irqflags.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-#include <asm/asm-offsets.h>
-#include <asm/sysmips.h>
-#include <asm/thread_info.h>
-#include <asm/unistd.h>
-#include <asm/war.h>
-
-#ifndef CONFIG_MIPS32_COMPAT
-/* Neither O32 nor N32, so define handle_sys here */
-#define handle_sys64 handle_sys
-#endif
-
-	.align	5
-NESTED(handle_sys64, PT_SIZE, sp)
-#if !defined(CONFIG_MIPS32_O32) && !defined(CONFIG_MIPS32_N32)
-	/*
-	 * When 32-bit compatibility is configured scall_o32.S
-	 * already did this.
-	 */
-	.set	noat
-	SAVE_SOME
-	TRACE_IRQS_ON_RELOAD
-	STI
-	.set	at
-#endif
-
-#if !defined(CONFIG_MIPS32_O32) && !defined(CONFIG_MIPS32_N32)
-	ld	t1, PT_EPC(sp)		# skip syscall on return
-	daddiu	t1, 4			# skip to next instruction
-	sd	t1, PT_EPC(sp)
-#endif
-
-	sd	a3, PT_R26(sp)		# save a3 for syscall restarting
-
-	li	t1, _TIF_WORK_SYSCALL_ENTRY
-	LONG_L	t0, TI_FLAGS($28)	# syscall tracing enabled?
-	and	t0, t1, t0
-	bnez	t0, syscall_trace_entry
-
-syscall_common:
-	dsubu	t2, v0, __NR_64_Linux
-	sltiu   t0, t2, __NR_64_Linux_syscalls
-	beqz	t0, illegal_syscall
-
-	dsll	t0, t2, 3		# offset into table
-	dla	t2, sys_call_table
-	daddu	t0, t2, t0
-	ld	t2, (t0)		# syscall routine
-	beqz	t2, illegal_syscall
-
-	jalr	t2			# Do The Real Thing (TM)
-
-	li	t0, -EMAXERRNO - 1	# error?
-	sltu	t0, t0, v0
-	sd	t0, PT_R7(sp)		# set error flag
-	beqz	t0, 1f
-
-	ld	t1, PT_R2(sp)		# syscall number
-	dnegu	v0			# error
-	sd	t1, PT_R0(sp)		# save it for syscall restarting
-1:	sd	v0, PT_R2(sp)		# result
-
-n64_syscall_exit:
-	j	syscall_exit_partial
-
-/* ------------------------------------------------------------------------ */
-
-syscall_trace_entry:
-	SAVE_STATIC
-	move	a0, sp
-	move	a1, v0
-	jal	syscall_trace_enter
-
-	bltz	v0, 1f			# seccomp failed? Skip syscall
-
-	RESTORE_STATIC
-	ld	v0, PT_R2(sp)		# Restore syscall (maybe modified)
-	ld	a0, PT_R4(sp)		# Restore argument registers
-	ld	a1, PT_R5(sp)
-	ld	a2, PT_R6(sp)
-	ld	a3, PT_R7(sp)
-	ld	a4, PT_R8(sp)
-	ld	a5, PT_R9(sp)
-	j	syscall_common
-
-1:	j	syscall_exit
-
-illegal_syscall:
-	/* This also isn't a 64-bit syscall, throw an error.  */
-	li	v0, ENOSYS			# error
-	sd	v0, PT_R2(sp)
-	li	t0, 1				# set error flag
-	sd	t0, PT_R7(sp)
-	j	n64_syscall_exit
-	END(handle_sys64)
-
-#define __SYSCALL(nr, entry)	PTR entry
-	.align	3
-	.type	sys_call_table, @object
-EXPORT(sys_call_table)
-#include <asm/syscall_table_n64.h>
arch/mips/kernel/scall64-o32.S deleted +0 -221
deleted file mode 100644
index cedc8bd88804..000000000000
@@ -1,221 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1995 - 2000, 2001 by Ralf Baechle
- * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
- * Copyright (C) 2001 MIPS Technologies, Inc.
- * Copyright (C) 2004 Thiemo Seufer
- *
- * Hairy, the userspace application uses a different argument passing
- * convention than the kernel, so we have to translate things from o32
- * to ABI64 calling convention.	 64-bit syscalls are also processed
- * here for now.
- */
-#include <linux/errno.h>
-#include <asm/asm.h>
-#include <asm/asmmacro.h>
-#include <asm/irqflags.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-#include <asm/thread_info.h>
-#include <asm/unistd.h>
-#include <asm/sysmips.h>
-
-	.align	5
-NESTED(handle_sys, PT_SIZE, sp)
-	.set	noat
-	SAVE_SOME
-	TRACE_IRQS_ON_RELOAD
-	STI
-	.set	at
-	ld	t1, PT_EPC(sp)		# skip syscall on return
-
-	dsubu	t0, v0, __NR_O32_Linux	# check syscall number
-	sltiu	t0, t0, __NR_O32_Linux_syscalls
-	daddiu	t1, 4			# skip to next instruction
-	sd	t1, PT_EPC(sp)
-	beqz	t0, not_o32_scall
-#if 0
- SAVE_ALL
- move a1, v0
- ASM_PRINT("Scall %ld\n")
- RESTORE_ALL
-#endif
-
-	/* We don't want to stumble over broken sign extensions from
-	   userland. O32 does never use the upper half. */
-	sll	a0, a0, 0
-	sll	a1, a1, 0
-	sll	a2, a2, 0
-	sll	a3, a3, 0
-
-	sd	a3, PT_R26(sp)		# save a3 for syscall restarting
-
-	/*
-	 * More than four arguments.  Try to deal with it by copying the
-	 * stack arguments from the user stack to the kernel stack.
-	 * This Sucks (TM).
-	 *
-	 * We intentionally keep the kernel stack a little below the top of
-	 * userspace so we don't have to do a slower byte accurate check here.
-	 */
-	ld	t0, PT_R29(sp)		# get old user stack pointer
-	daddu	t1, t0, 32
-	bltz	t1, bad_stack
-
-load_a4: lw	a4, 16(t0)		# argument #5 from usp
-load_a5: lw	a5, 20(t0)		# argument #6 from usp
-load_a6: lw	a6, 24(t0)		# argument #7 from usp
-load_a7: lw	a7, 28(t0)		# argument #8 from usp
-loads_done:
-
-	.section __ex_table,"a"
-	PTR	load_a4, bad_stack_a4
-	PTR	load_a5, bad_stack_a5
-	PTR	load_a6, bad_stack_a6
-	PTR	load_a7, bad_stack_a7
-	.previous
-
-	li	t1, _TIF_WORK_SYSCALL_ENTRY
-	LONG_L	t0, TI_FLAGS($28)	# syscall tracing enabled?
-	and	t0, t1, t0
-	bnez	t0, trace_a_syscall
-
-syscall_common:
-	dsll	t0, v0, 3		# offset into table
-	ld	t2, (sys32_call_table - (__NR_O32_Linux * 8))(t0)
-
-	jalr	t2			# Do The Real Thing (TM)
-
-	li	t0, -EMAXERRNO - 1	# error?
-	sltu	t0, t0, v0
-	sd	t0, PT_R7(sp)		# set error flag
-	beqz	t0, 1f
-
-	ld	t1, PT_R2(sp)		# syscall number
-	dnegu	v0			# error
-	sd	t1, PT_R0(sp)		# save it for syscall restarting
-1:	sd	v0, PT_R2(sp)		# result
-
-o32_syscall_exit:
-	j	syscall_exit_partial
-
-/* ------------------------------------------------------------------------ */
-
-trace_a_syscall:
-	SAVE_STATIC
-	sd	a4, PT_R8(sp)		# Save argument registers
-	sd	a5, PT_R9(sp)
-	sd	a6, PT_R10(sp)
-	sd	a7, PT_R11(sp)		# For indirect syscalls
-
-	move	a0, sp
-	/*
-	 * absolute syscall number is in v0 unless we called syscall(__NR_###)
-	 * where the real syscall number is in a0
-	 * note: NR_syscall is the first O32 syscall but the macro is
-	 * only defined when compiling with -mabi=32 (CONFIG_32BIT)
-	 * therefore __NR_O32_Linux is used (4000)
-	 */
-	.set	push
-	.set	reorder
-	subu	t1, v0,  __NR_O32_Linux
-	move	a1, v0
-	bnez	t1, 1f /* __NR_syscall at offset 0 */
-	ld	a1, PT_R4(sp) /* Arg1 for __NR_syscall case */
-	.set	pop
-
-1:	jal	syscall_trace_enter
-
-	bltz	v0, 1f			# seccomp failed? Skip syscall
-
-	RESTORE_STATIC
-	ld	v0, PT_R2(sp)		# Restore syscall (maybe modified)
-	ld	a0, PT_R4(sp)		# Restore argument registers
-	ld	a1, PT_R5(sp)
-	ld	a2, PT_R6(sp)
-	ld	a3, PT_R7(sp)
-	ld	a4, PT_R8(sp)
-	ld	a5, PT_R9(sp)
-	ld	a6, PT_R10(sp)
-	ld	a7, PT_R11(sp)		# For indirect syscalls
-
-	dsubu	t0, v0, __NR_O32_Linux	# check (new) syscall number
-	sltiu	t0, t0, __NR_O32_Linux_syscalls
-	beqz	t0, not_o32_scall
-
-	j	syscall_common
-
-1:	j	syscall_exit
-
-/* ------------------------------------------------------------------------ */
-
-	/*
-	 * The stackpointer for a call with more than 4 arguments is bad.
-	 */
-bad_stack:
-	li	v0, EFAULT
-	sd	v0, PT_R2(sp)
-	li	t0, 1			# set error flag
-	sd	t0, PT_R7(sp)
-	j	o32_syscall_exit
-
-bad_stack_a4:
-	li	a4, 0
-	b	load_a5
-
-bad_stack_a5:
-	li	a5, 0
-	b	load_a6
-
-bad_stack_a6:
-	li	a6, 0
-	b	load_a7
-
-bad_stack_a7:
-	li	a7, 0
-	b	loads_done
-
-not_o32_scall:
-	/*
-	 * This is not an o32 compatibility syscall, pass it on
-	 * to the 64-bit syscall handlers.
-	 */
-#ifdef CONFIG_MIPS32_N32
-	j	handle_sysn32
-#else
-	j	handle_sys64
-#endif
-	END(handle_sys)
-
-LEAF(sys32_syscall)
-	subu	t0, a0, __NR_O32_Linux	# check syscall number
-	sltiu	v0, t0, __NR_O32_Linux_syscalls
-	beqz	t0, einval		# do not recurse
-	dsll	t1, t0, 3
-	beqz	v0, einval
-	ld	t2, sys32_call_table(t1)		# syscall routine
-
-	move	a0, a1			# shift argument registers
-	move	a1, a2
-	move	a2, a3
-	move	a3, a4
-	move	a4, a5
-	move	a5, a6
-	move	a6, a7
-	jr	t2
-	/* Unreached */
-
-einval: li	v0, -ENOSYS
-	jr	ra
-	END(sys32_syscall)
-
-#define __SYSCALL_WITH_COMPAT(nr, native, compat)	__SYSCALL(nr, compat)
-#define __SYSCALL(nr, entry)	PTR entry
-	.align	3
-	.type	sys32_call_table,@object
-EXPORT(sys32_call_table)
-#include <asm/syscall_table_o32.h>
arch/mips/kernel/signal.c +11 -24
index f1e985109da0..1ec6a0cf1163 100644
@@ -32,7 +32,6 @@
  #include <linux/bitops.h>
  #include <asm/cacheflush.h>
  #include <asm/fpu.h>
-#include <asm/sim.h>
  #include <asm/ucontext.h>
  #include <asm/cpu-features.h>
  #include <asm/war.h>
@@ -627,7 +626,7 @@ SYSCALL_DEFINE3(sigaction, int, sig, const struct sigaction __user *, act,
  #endif
 
  #ifdef CONFIG_TRAD_SIGNALS
-asmlinkage void sys_sigreturn(void)
+asmlinkage long sys_sigreturn(void)
  {
  	struct sigframe __user *frame;
  	struct pt_regs *regs;
@@ -649,22 +648,16 @@ asmlinkage void sys_sigreturn(void)
  	else if (sig)
  		force_sig(sig);
 
-	/*
-	 * Don't let your children do this ...
-	 */
-	__asm__ __volatile__(
-		"move\t$29, %0\n\t"
-		"j\tsyscall_exit"
-		: /* no outputs */
-		: "r" (regs));
-	/* Unreached */
+	regs->regs[27] = 1;	/* return directly */
+	return regs->regs[2];
 
  badframe:
  	force_sig(SIGSEGV);
+	return 0;
  }
  #endif /* CONFIG_TRAD_SIGNALS */
 
-asmlinkage void sys_rt_sigreturn(void)
+asmlinkage long sys_rt_sigreturn(void)
  {
  	struct rt_sigframe __user *frame;
  	struct pt_regs *regs;
@@ -689,18 +682,12 @@ asmlinkage void sys_rt_sigreturn(void)
  	if (restore_altstack(&frame->rs_uc.uc_stack))
  		goto badframe;
 
-	/*
-	 * Don't let your children do this ...
-	 */
-	__asm__ __volatile__(
-		"move\t$29, %0\n\t"
-		"j\tsyscall_exit"
-		: /* no outputs */
-		: "r" (regs));
-	/* Unreached */
+	regs->regs[27] = 1;	/* return directly */
+	return regs->regs[2];
 
  badframe:
  	force_sig(SIGSEGV);
+	return 0;
  }
 
  #ifdef CONFIG_TRAD_SIGNALS
@@ -852,11 +839,11 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
  	signal_setup_done(ret, ksig, 0);
  }
 
-static void do_signal(struct pt_regs *regs)
+void arch_do_signal_or_restart(struct pt_regs *regs, bool has_signal)
  {
  	struct ksignal ksig;
 
-	if (get_signal(&ksig)) {
+	if (has_signal && get_signal(&ksig)) {
  		/* Whee!  Actually deliver the signal.	*/
  		handle_signal(&ksig, regs);
  		return;
@@ -904,7 +891,7 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, void *unused,
 
  	/* deal with pending signal delivery */
  	if (thread_info_flags & (_TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL))
-		do_signal(regs);
+		arch_do_signal_or_restart(regs, thread_info_flags & _TIF_SIGPENDING);
 
  	if (thread_info_flags & _TIF_NOTIFY_RESUME) {
  		tracehook_notify_resume(regs);
arch/mips/kernel/signal_n32.c +4 -11
index 7bd00fad61af..b52b995a8a9b 100644
@@ -19,7 +19,6 @@
  #include <asm/asm.h>
  #include <asm/cacheflush.h>
  #include <asm/compat-signal.h>
-#include <asm/sim.h>
  #include <linux/uaccess.h>
  #include <asm/ucontext.h>
  #include <asm/fpu.h>
@@ -51,7 +50,7 @@ struct rt_sigframe_n32 {
  	struct ucontextn32 rs_uc;
  };
 
-asmlinkage void sysn32_rt_sigreturn(void)
+asmlinkage long sysn32_rt_sigreturn(void)
  {
  	struct rt_sigframe_n32 __user *frame;
  	struct pt_regs *regs;
@@ -76,18 +75,12 @@ asmlinkage void sysn32_rt_sigreturn(void)
  	if (compat_restore_altstack(&frame->rs_uc.uc_stack))
  		goto badframe;
 
-	/*
-	 * Don't let your children do this ...
-	 */
-	__asm__ __volatile__(
-		"move\t$29, %0\n\t"
-		"j\tsyscall_exit"
-		: /* no outputs */
-		: "r" (regs));
-	/* Unreached */
+	regs->regs[27] = 1;	/* return directly */
+	return regs->regs[2];
 
  badframe:
  	force_sig(SIGSEGV);
+	return 0;
  }
 
  static int setup_rt_frame_n32(void *sig_return, struct ksignal *ksig,
arch/mips/kernel/signal_o32.c +8 -21
index 299a7a28ca33..9245806e06f1 100644
@@ -17,7 +17,6 @@
  #include <asm/abi.h>
  #include <asm/compat-signal.h>
  #include <asm/dsp.h>
-#include <asm/sim.h>
  #include <asm/unistd.h>
 
  #include "signal-common.h"
@@ -151,7 +150,7 @@ static int setup_frame_32(void *sig_return, struct ksignal *ksig,
  	return 0;
  }
 
-asmlinkage void sys32_rt_sigreturn(void)
+asmlinkage long sys32_rt_sigreturn(void)
  {
  	struct rt_sigframe32 __user *frame;
  	struct pt_regs *regs;
@@ -176,18 +175,12 @@ asmlinkage void sys32_rt_sigreturn(void)
  	if (compat_restore_altstack(&frame->rs_uc.uc_stack))
  		goto badframe;
 
-	/*
-	 * Don't let your children do this ...
-	 */
-	__asm__ __volatile__(
-		"move\t$29, %0\n\t"
-		"j\tsyscall_exit"
-		: /* no outputs */
-		: "r" (regs));
-	/* Unreached */
+	regs->regs[27] = 1;	/* return directly */
+	return regs->regs[2];
 
  badframe:
  	force_sig(SIGSEGV);
+	return 0;
  }
 
  static int setup_rt_frame_32(void *sig_return, struct ksignal *ksig,
@@ -253,7 +246,7 @@ struct mips_abi mips_abi_32 = {
  };
 
 
-asmlinkage void sys32_sigreturn(void)
+asmlinkage long sys32_sigreturn(void)
  {
  	struct sigframe32 __user *frame;
  	struct pt_regs *regs;
@@ -275,16 +268,10 @@ asmlinkage void sys32_sigreturn(void)
  	else if (sig)
  		force_sig(sig);
 
-	/*
-	 * Don't let your children do this ...
-	 */
-	__asm__ __volatile__(
-		"move\t$29, %0\n\t"
-		"j\tsyscall_exit"
-		: /* no outputs */
-		: "r" (regs));
-	/* Unreached */
+	regs->regs[27] = 1;	/* return directly */
+	return regs->regs[2];
 
  badframe:
  	force_sig(SIGSEGV);
+	return 0;
  }
arch/mips/kernel/syscall.c +122 -25
index 2afa3eef486a..6dc78648b274 100644
@@ -8,6 +8,7 @@
   * Copyright (C) 2001 MIPS Technologies, Inc.
   */
  #include <linux/capability.h>
+#include <linux/entry-common.h>
  #include <linux/errno.h>
  #include <linux/linkage.h>
  #include <linux/fs.h>
@@ -35,9 +36,9 @@
  #include <asm/cacheflush.h>
  #include <asm/asm-offsets.h>
  #include <asm/signal.h>
-#include <asm/sim.h>
  #include <asm/shmparam.h>
  #include <asm/sync.h>
+#include <asm/syscall.h>
  #include <asm/sysmips.h>
  #include <asm/switch_to.h>
 
@@ -79,10 +80,6 @@ SYSCALL_DEFINE6(mips_mmap2, unsigned long, addr, unsigned long, len,
  			       pgoff >> (PAGE_SHIFT - 12));
  }
 
-save_static_function(sys_fork);
-save_static_function(sys_clone);
-save_static_function(sys_clone3);
-
  SYSCALL_DEFINE1(set_thread_area, unsigned long, addr)
  {
  	struct thread_info *ti = task_thread_info(current);
@@ -182,28 +179,11 @@ static inline int mips_atomic_set(unsigned long addr, unsigned long new)
  		return err;
 
  	regs = current_pt_regs();
-	regs->regs[2] = old;
-	regs->regs[7] = 0;	/* No error */
-
-	/*
-	 * Don't let your children do this ...
-	 */
-	__asm__ __volatile__(
-	"	move	$29, %0						\n"
-	"	j	syscall_exit					\n"
-	: /* no outputs */
-	: "r" (regs));
-
-	/* unreached.  Honestly.  */
-	unreachable();
+	regs->regs[7] = 0;	/* no error */
+	regs->regs[27] = 1;	/* return directly */
+	return old;
  }
 
-/*
- * mips_atomic_set() normally returns directly via syscall_exit potentially
- * clobbering static registers, so be sure to preserve them.
- */
-save_static_function(sys_sysmips);
-
  SYSCALL_DEFINE3(sysmips, long, cmd, long, arg1, long, arg2)
  {
  	switch (cmd) {
@@ -249,3 +229,120 @@ asmlinkage void bad_stack(void)
  {
  	do_exit(SIGSEGV);
  }
+
+#if defined(CONFIG_32BIT) || defined(CONFIG_MIPS32_O32)
+static inline int get_args(struct pt_regs *regs)
+{
+	int *usp = (int *)regs->regs[29];
+
+#ifdef CONFIG_MIPS32_O32
+	/*
+	 * Hairy, the userspace application uses a different argument passing
+	 * convention than the kernel, so we have to translate things from o32
+	 * to ABI64 calling convention.
+	 *
+	 * We don't want to stumble over broken sign extensions from userland.
+	 * O32 does never use the upper half.
+	 */
+	regs->regs[4] = (int)regs->regs[4];
+	regs->regs[5] = (int)regs->regs[5];
+	regs->regs[6] = (int)regs->regs[6];
+	regs->regs[7] = (int)regs->regs[7];
+#endif
+
+	/*
+	 * More than four arguments.  Try to deal with it by copying the
+	 * stack arguments from the user stack to the kernel stack.
+	 * This Sucks (TM).
+	 *
+	 * We intentionally keep the kernel stack a little below the top of
+	 * userspace so we don't have to do a slower byte accurate check here.
+	 */
+	if (!access_ok(usp, 32))
+		return -1;
+
+	get_user(regs->regs[8], usp + 4);
+	get_user(regs->regs[9], usp + 5);
+	get_user(regs->regs[10], usp + 6);
+	get_user(regs->regs[11], usp + 7);
+
+	return 0;
+}
+#endif
+
+typedef long (*sys_call_fn)(unsigned long, unsigned long,
+	unsigned long, unsigned long, unsigned long, unsigned long);
+
+void noinstr do_syscall(struct pt_regs *regs)
+{
+	unsigned long nr;
+	unsigned long ret;
+	sys_call_fn syscall_fn = NULL;
+
+	nr = regs->regs[2];
+	current_thread_info()->syscall = nr;
+	nr = syscall_enter_from_user_mode(regs, nr);
+
+	regs->cp0_epc += 4;		/* skip syscall on return */
+					/* skip to next instruction */
+	regs->regs[26] = regs->regs[7];	/* save a3 for syscall restarting */
+	regs->regs[27] = 0;		/* do not return directly */
+
+#ifdef CONFIG_32BIT
+	if (nr >= __NR_O32_Linux && nr < __NR_O32_Linux + __NR_O32_Linux_syscalls) {
+		if (get_args(regs) < 0) {
+			ret = EFAULT;
+			goto error;
+		}
+		syscall_fn = (sys_call_fn)sys_call_table[nr - __NR_O32_Linux];
+	}
+#endif
+
+#ifdef CONFIG_MIPS32_O32
+	if (nr >= __NR_O32_Linux && nr < __NR_O32_Linux + __NR_O32_Linux_syscalls) {
+		if (get_args(regs) < 0) {
+			ret = EFAULT;
+			goto error;
+		}
+		syscall_fn = (sys_call_fn)sys32_call_table[nr - __NR_O32_Linux];
+	}
+#endif
+
+#ifdef CONFIG_MIPS32_N32
+	if (nr >= __NR_N32_Linux && nr < __NR_N32_Linux + __NR_N32_Linux_syscalls)
+		syscall_fn = (sys_call_fn)sysn32_call_table[nr - __NR_N32_Linux];
+#endif
+
+#ifdef CONFIG_64BIT
+	if (nr >= __NR_64_Linux && nr < __NR_64_Linux + __NR_64_Linux_syscalls)
+		syscall_fn = (sys_call_fn)sys_call_table[nr - __NR_64_Linux];
+#endif
+
+	if (!syscall_fn) {
+		ret = ENOSYS;
+		goto error;
+	}
+
+	ret = syscall_fn(regs->regs[4], regs->regs[5], regs->regs[6],
+			 regs->regs[7], regs->regs[8], regs->regs[9]);
+
+	if (regs->regs[27])		/* return directly? */
+		goto out;
+
+	regs->regs[7] = 0;		/* clear error flag */
+	if (ret >= -EMAXERRNO - 1) {	/* error? */
+		regs->regs[0] = nr;	/* save syscall number */
+					/* for syscall restarting */
+		ret = -ret;
+		goto error;
+	}
+
+	goto out;
+
+error:
+	regs->regs[7] = 1;		/* set error flag */
+
+out:
+	regs->regs[2] = ret;
+	syscall_exit_to_user_mode(regs);
+}
arch/mips/kernel/syscalls/syscall_n32.tbl +4 -4
index 70e32de2bcaa..d9ae765e51f1 100644
@@ -62,8 +62,8 @@
  52	n32	socketpair			sys_socketpair
  53	n32	setsockopt			sys_setsockopt
  54	n32	getsockopt			sys_getsockopt
-55	n32	clone				__sys_clone
-56	n32	fork				__sys_fork
+55	n32	clone				sys_clone
+56	n32	fork				sys_fork
  57	n32	execve				compat_sys_execve
  58	n32	exit				sys_exit
  59	n32	wait4				compat_sys_wait4
@@ -207,7 +207,7 @@
  196	n32	sched_getaffinity		compat_sys_sched_getaffinity
  197	n32	cacheflush			sys_cacheflush
  198	n32	cachectl			sys_cachectl
-199	n32	sysmips				__sys_sysmips
+199	n32	sysmips				sys_sysmips
  200	n32	io_setup			compat_sys_io_setup
  201	n32	io_destroy			sys_io_destroy
  202	n32	io_getevents			sys_io_getevents_time32
@@ -373,7 +373,7 @@
  432	n32	fsmount				sys_fsmount
  433	n32	fspick				sys_fspick
  434	n32	pidfd_open			sys_pidfd_open
-435	n32	clone3				__sys_clone3
+435	n32	clone3				sys_clone3
  436	n32	close_range			sys_close_range
  437	n32	openat2				sys_openat2
  438	n32	pidfd_getfd			sys_pidfd_getfd
arch/mips/kernel/syscalls/syscall_n64.tbl +4 -4
index 1ca7bc337932..edec3e82d67a 100644
@@ -62,8 +62,8 @@
  52	n64	socketpair			sys_socketpair
  53	n64	setsockopt			sys_setsockopt
  54	n64	getsockopt			sys_getsockopt
-55	n64	clone				__sys_clone
-56	n64	fork				__sys_fork
+55	n64	clone				sys_clone
+56	n64	fork				sys_fork
  57	n64	execve				sys_execve
  58	n64	exit				sys_exit
  59	n64	wait4				sys_wait4
@@ -207,7 +207,7 @@
  196	n64	sched_getaffinity		sys_sched_getaffinity
  197	n64	cacheflush			sys_cacheflush
  198	n64	cachectl			sys_cachectl
-199	n64	sysmips				__sys_sysmips
+199	n64	sysmips				sys_sysmips
  200	n64	io_setup			sys_io_setup
  201	n64	io_destroy			sys_io_destroy
  202	n64	io_getevents			sys_io_getevents
@@ -349,7 +349,7 @@
  432	n64	fsmount				sys_fsmount
  433	n64	fspick				sys_fspick
  434	n64	pidfd_open			sys_pidfd_open
-435	n64	clone3				__sys_clone3
+435	n64	clone3				sys_clone3
  436	n64	close_range			sys_close_range
  437	n64	openat2				sys_openat2
  438	n64	pidfd_getfd			sys_pidfd_getfd
arch/mips/kernel/syscalls/syscall_o32.tbl +4 -4
index a61c35edaa74..89a1f267da6a 100644
@@ -9,7 +9,7 @@
  #
  0	o32	syscall				sys_syscall			sys32_syscall
  1	o32	exit				sys_exit
-2	o32	fork				__sys_fork
+2	o32	fork				sys_fork
  3	o32	read				sys_read
  4	o32	write				sys_write
  5	o32	open				sys_open			compat_sys_open
@@ -131,7 +131,7 @@
  117	o32	ipc				sys_ipc				compat_sys_ipc
  118	o32	fsync				sys_fsync
  119	o32	sigreturn			sys_sigreturn			sys32_sigreturn
-120	o32	clone				__sys_clone
+120	o32	clone				sys_clone
  121	o32	setdomainname			sys_setdomainname
  122	o32	uname				sys_newuname
  123	o32	modify_ldt			sys_ni_syscall
@@ -160,7 +160,7 @@
  146	o32	writev				sys_writev
  147	o32	cacheflush			sys_cacheflush
  148	o32	cachectl			sys_cachectl
-149	o32	sysmips				__sys_sysmips
+149	o32	sysmips				sys_sysmips
  150	o32	unused150			sys_ni_syscall
  151	o32	getsid				sys_getsid
  152	o32	fdatasync			sys_fdatasync
@@ -422,7 +422,7 @@
  432	o32	fsmount				sys_fsmount
  433	o32	fspick				sys_fspick
  434	o32	pidfd_open			sys_pidfd_open
-435	o32	clone3				__sys_clone3
+435	o32	clone3				sys_clone3
  436	o32	close_range			sys_close_range
  437	o32	openat2				sys_openat2
  438	o32	pidfd_getfd			sys_pidfd_getfd
author
#3 lore raw

Re: [PATCH 1/2] mips: convert syscall to generic entry

Quoted 25 lines · Jiaxun Yang
Quoted 16 lines · FreeFlyingSheep

From: Feiyang Chen <[email protected]>

Convert mips syscall to use the generic entry infrastructure from kernel/entry/*.

There are a few special things on mips:

- There is one type of syscall on mips32 (scall32-o32) and three types of syscalls on mips64 (scall64-o32, scall64-n32 and scall64-n64). Now convert to C code to handle different types of syscalls.

- For some special syscalls (e.g. fork, clone, clone3 and sysmips), save_static_function() wrapper is used to save static registers. Now SAVE_STATIC is used in handle_sys before calling do_syscall(), so the save_static_function() wrapper can be removed.

Quoted 5 lines

- For sigreturn/rt_sigreturn and sysmips, inline assembly is used to jump to syscall_exit directly for skipping setting the error flag and restoring all registers. Now use regs->regs[27] to mark whether to handle the error flag and always restore all registers in handle_sys, so these functions can return normally as other architecture.

Quoted 4 lines

Hmm, that would give us overhead of register context on these syscalls.

I guess it's worthy?

Hi, Jiaxun,

Saving and restoring registers against different system calls can be difficult due to the use of generic entry.
To avoid a lot of duplicate code, I think the overhead is worth it.

Quoted 4 lines
Quoted 3 lines
Quoted 8 lines

For the code,

After spending 3hrs diving into syscall handling hell, I must say you've done a good job. I'll start a LTP run to see if we miss any corner cases. And left IRQ part for another trial.

Thank you for your review. I've already run tests in Unixbench. It's more reassuring to run tests in LTP, so I'll do that too.

Thanks,
Feiyang

Quoted 1,821 lines

Thanks.

Jiaxun

Quoted 1,817 lines
---
  arch/mips/Kconfig                         |   1 +
  arch/mips/include/asm/entry-common.h      |  13 ++
  arch/mips/include/asm/ptrace.h            |   8 +-
  arch/mips/include/asm/sim.h               |  70 -------
  arch/mips/include/asm/syscall.h           |   5 +
  arch/mips/include/asm/thread_info.h       |  17 +-
  arch/mips/include/uapi/asm/ptrace.h       |   7 +-
  arch/mips/kernel/Makefile                 |  14 +-
  arch/mips/kernel/entry.S                  |  75 ++------
  arch/mips/kernel/linux32.c                |   1 -
  arch/mips/kernel/ptrace.c                 |  78 --------
  arch/mips/kernel/scall.S                  | 135 +++++++++++++
  arch/mips/kernel/scall32-o32.S            | 223 ----------------------
  arch/mips/kernel/scall64-n32.S            | 107 -----------
  arch/mips/kernel/scall64-n64.S            | 116 -----------
  arch/mips/kernel/scall64-o32.S            | 221 ---------------------
  arch/mips/kernel/signal.c                 |  35 ++--
  arch/mips/kernel/signal_n32.c             |  15 +-
  arch/mips/kernel/signal_o32.c             |  29 +--
  arch/mips/kernel/syscall.c                | 147 +++++++++++---
  arch/mips/kernel/syscalls/syscall_n32.tbl |   8 +-
  arch/mips/kernel/syscalls/syscall_n64.tbl |   8 +-
  arch/mips/kernel/syscalls/syscall_o32.tbl |   8 +-
  23 files changed, 346 insertions(+), 995 deletions(-)

create mode 100644 arch/mips/include/asm/entry-common.h delete mode 100644 arch/mips/include/asm/sim.h create mode 100644 arch/mips/kernel/scall.S delete mode 100644 arch/mips/kernel/scall32-o32.S delete mode 100644 arch/mips/kernel/scall64-n32.S delete mode 100644 arch/mips/kernel/scall64-n64.S delete mode 100644 arch/mips/kernel/scall64-o32.S

arch/mips/Kconfig +1 -0
index 0cf31a6cbee1..61aa125aa2da 100644
@@ -32,6 +32,7 @@ config MIPS
      select GENERIC_ATOMIC64 if !64BIT
      select GENERIC_CMOS_UPDATE
      select GENERIC_CPU_AUTOPROBE
+     select GENERIC_ENTRY
      select GENERIC_GETTIMEOFDAY
      select GENERIC_IOMAP
      select GENERIC_IRQ_PROBE
arch/mips/include/asm/entry-common.h new file +13 -0
new file mode 100644
index 000000000000..0fe2a098ded9
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef ARCH_LOONGARCH_ENTRY_COMMON_H
+#define ARCH_LOONGARCH_ENTRY_COMMON_H
+
+#include <linux/sched.h>
+#include <linux/processor.h>
+
+static inline bool on_thread_stack(void)
+{
+     return !(((unsigned long)(current->stack) ^ current_stack_pointer) & ~(THREAD_SIZE - 1));
+}
+
+#endif
arch/mips/include/asm/ptrace.h +5 -3
index daf3cf244ea9..1b8f9d2ddc44 100644
@@ -51,6 +51,11 @@ struct pt_regs {
      unsigned long __last[0];
  } __aligned(8);
 
+static inline int regs_irqs_disabled(struct pt_regs *regs)
+{
+     return arch_irqs_disabled_flags(regs->cp0_status);
+}
+
  static inline unsigned long kernel_stack_pointer(struct pt_regs *regs)
  {
      return regs->regs[29];
@@ -156,9 +161,6 @@ static inline long regs_return_value(struct pt_regs *regs)
  #define instruction_pointer(regs) ((regs)->cp0_epc)
  #define profile_pc(regs) instruction_pointer(regs)
 
-extern asmlinkage long syscall_trace_enter(struct pt_regs *regs, long syscall);
-extern asmlinkage void syscall_trace_leave(struct pt_regs *regs);
-
  extern void die(const char *, struct pt_regs *) __noreturn;
 
  static inline void die_if_kernel(const char *str, struct pt_regs *regs)
arch/mips/include/asm/sim.h deleted +0 -70
deleted file mode 100644
index 59f31a95facd..000000000000
@@ -1,70 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1999, 2000, 2003 Ralf Baechle
- * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
- */
-#ifndef _ASM_SIM_H
-#define _ASM_SIM_H
-
-
-#include <asm/asm-offsets.h>
-
-#define __str2(x) #x
-#define __str(x) __str2(x)
-
-#ifdef CONFIG_32BIT
-
-#define save_static_function(symbol)                                 \
-__asm__(                                                             \
-     ".text\n\t"                                                     \
-     ".globl\t__" #symbol "\n\t"                                     \
-     ".align\t2\n\t"                                                 \
-     ".type\t__" #symbol ", @function\n\t"                           \
-     ".ent\t__" #symbol ", 0\n__"                                    \
-     #symbol":\n\t"                                                  \
-     ".frame\t$29, 0, $31\n\t"                                       \
-     "sw\t$16,"__str(PT_R16)"($29)\t\t\t# save_static_function\n\t"  \
-     "sw\t$17,"__str(PT_R17)"($29)\n\t"                              \
-     "sw\t$18,"__str(PT_R18)"($29)\n\t"                              \
-     "sw\t$19,"__str(PT_R19)"($29)\n\t"                              \
-     "sw\t$20,"__str(PT_R20)"($29)\n\t"                              \
-     "sw\t$21,"__str(PT_R21)"($29)\n\t"                              \
-     "sw\t$22,"__str(PT_R22)"($29)\n\t"                              \
-     "sw\t$23,"__str(PT_R23)"($29)\n\t"                              \
-     "sw\t$30,"__str(PT_R30)"($29)\n\t"                              \
-     "j\t" #symbol "\n\t"                                            \
-     ".end\t__" #symbol "\n\t"                                       \
-     ".size\t__" #symbol",. - __" #symbol)
-
-#endif /* CONFIG_32BIT */
-
-#ifdef CONFIG_64BIT
-
-#define save_static_function(symbol)                                 \
-__asm__(                                                             \
-     ".text\n\t"                                                     \
-     ".globl\t__" #symbol "\n\t"                                     \
-     ".align\t2\n\t"                                                 \
-     ".type\t__" #symbol ", @function\n\t"                           \
-     ".ent\t__" #symbol ", 0\n__"                                    \
-     #symbol":\n\t"                                                  \
-     ".frame\t$29, 0, $31\n\t"                                       \
-     "sd\t$16,"__str(PT_R16)"($29)\t\t\t# save_static_function\n\t"  \
-     "sd\t$17,"__str(PT_R17)"($29)\n\t"                              \
-     "sd\t$18,"__str(PT_R18)"($29)\n\t"                              \
-     "sd\t$19,"__str(PT_R19)"($29)\n\t"                              \
-     "sd\t$20,"__str(PT_R20)"($29)\n\t"                              \
-     "sd\t$21,"__str(PT_R21)"($29)\n\t"                              \
-     "sd\t$22,"__str(PT_R22)"($29)\n\t"                              \
-     "sd\t$23,"__str(PT_R23)"($29)\n\t"                              \
-     "sd\t$30,"__str(PT_R30)"($29)\n\t"                              \
-     "j\t" #symbol "\n\t"                                            \
-     ".end\t__" #symbol "\n\t"                                       \
-     ".size\t__" #symbol",. - __" #symbol)
-
-#endif /* CONFIG_64BIT */
-
-#endif /* _ASM_SIM_H */
arch/mips/include/asm/syscall.h +5 -0
index 25fa651c937d..02ca0d659428 100644
@@ -157,4 +157,9 @@ static inline int syscall_get_arch(struct task_struct *task)
      return arch;
  }
 
+static inline bool arch_syscall_is_vdso_sigreturn(struct pt_regs *regs)
+{
+     return false;
+}
+
  #endif      /* __ASM_MIPS_SYSCALL_H */
arch/mips/include/asm/thread_info.h +4 -13
index 0b17aaa9e012..5a5237413065 100644
@@ -29,7 +29,8 @@ struct thread_info {
      __u32                   cpu;            /* current CPU */
      int                     preempt_count;  /* 0 => preemptable, <0 => BUG */
      struct pt_regs          *regs;
-     long                    syscall;        /* syscall number */
+     unsigned long           syscall;        /* syscall number */
+     unsigned long           syscall_work;   /* SYSCALL_WORK_ flags */
  };
 
  /*
@@ -69,6 +70,8 @@ static inline struct thread_info *current_thread_info(void)
      return __current_thread_info;
  }
 
+register unsigned long current_stack_pointer __asm__("$29");
+
  #endif /* !__ASSEMBLY__ */
 
  /* thread information allocation */
@@ -149,22 +152,10 @@ static inline struct thread_info *current_thread_info(void)
  #define _TIF_MSA_CTX_LIVE   (1<<TIF_MSA_CTX_LIVE)
  #define _TIF_SYSCALL_TRACEPOINT     (1<<TIF_SYSCALL_TRACEPOINT)
 
-#define _TIF_WORK_SYSCALL_ENTRY      (_TIF_NOHZ | _TIF_SYSCALL_TRACE |       \
-                              _TIF_SYSCALL_AUDIT | \
-                              _TIF_SYSCALL_TRACEPOINT | _TIF_SECCOMP)
-
-/* work to do in syscall_trace_leave() */
-#define _TIF_WORK_SYSCALL_EXIT       (_TIF_NOHZ | _TIF_SYSCALL_TRACE |       \
-                              _TIF_SYSCALL_AUDIT | _TIF_SYSCALL_TRACEPOINT)
-
  /* work to do on interrupt/exception return */
  #define _TIF_WORK_MASK              \
      (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_NOTIFY_RESUME |     \
       _TIF_UPROBE | _TIF_NOTIFY_SIGNAL)
-/* work to do on any return to u-space */
-#define _TIF_ALLWORK_MASK    (_TIF_NOHZ | _TIF_WORK_MASK |           \
-                              _TIF_WORK_SYSCALL_EXIT |               \
-                              _TIF_SYSCALL_TRACEPOINT)
 
  /*
   * We stash processor id into a COP0 register to retrieve it fast
arch/mips/include/uapi/asm/ptrace.h +4 -3
index f3c025445e45..27e2c85398bc 100644
@@ -102,8 +102,9 @@ struct pt_watch_regs {
      };
  };
 
-#define PTRACE_GET_WATCH_REGS        0xd0
-#define PTRACE_SET_WATCH_REGS        0xd1
-
+#define PTRACE_SYSEMU                        0x1f
+#define PTRACE_SYSEMU_SINGLESTEP     0x20
+#define PTRACE_GET_WATCH_REGS                0xd0
+#define PTRACE_SET_WATCH_REGS                0xd1
 
  #endif /* _UAPI_ASM_PTRACE_H */
arch/mips/kernel/Makefile +6 -8
index 814b3da30501..44875660f6ae 100644
@@ -5,10 +5,10 @@
 
  extra-y             := head.o vmlinux.lds
 
-obj-y                += branch.o cmpxchg.o elf.o entry.o genex.o idle.o irq.o \
-                process.o prom.o ptrace.o reset.o setup.o signal.o \
-                syscall.o time.o topology.o traps.o unaligned.o watch.o \
-                vdso.o cacheinfo.o
+obj-y                += branch.o cacheinfo.o cmpxchg.o elf.o entry.o genex.o \
+                idle.o irq.o process.o prom.o ptrace.o reset.o scall.o \
+                setup.o signal.o syscall.o time.o topology.o traps.o \
+                unaligned.o watch.o vdso.o
 
  ifdef CONFIG_CPU_R3K_TLB
  obj-y               += cpu-r3k-probe.o
@@ -76,11 +76,9 @@ obj-$(CONFIG_IRQ_TXX9)             += irq_txx9.o
  obj-$(CONFIG_IRQ_GT641XX)   += irq-gt641xx.o
 
  obj-$(CONFIG_KPROBES)               += kprobes.o
-obj-$(CONFIG_32BIT)          += scall32-o32.o
-obj-$(CONFIG_64BIT)          += scall64-n64.o
  obj-$(CONFIG_MIPS32_COMPAT) += linux32.o ptrace32.o signal32.o
-obj-$(CONFIG_MIPS32_N32)     += scall64-n32.o signal_n32.o
-obj-$(CONFIG_MIPS32_O32)     += scall64-o32.o signal_o32.o
+obj-$(CONFIG_MIPS32_N32)     += signal_n32.o
+obj-$(CONFIG_MIPS32_O32)     += signal_o32.o
 
  obj-$(CONFIG_KGDB)          += kgdb.o
  obj-$(CONFIG_PROC_FS)               += proc.o
arch/mips/kernel/entry.S +16 -59
index 4b896f5023ff..1a2aec9dab1b 100644
@@ -72,49 +72,32 @@ FEXPORT(ret_from_kernel_thread)
      jal     schedule_tail           # a0 = struct task_struct *prev
      move    a0, s1
      jal     s0
-     j       syscall_exit
+     move    a0, sp
+     jal     syscall_exit_to_user_mode
+
+     .set    noat
+     RESTORE_STATIC
+     RESTORE_SOME
+     RESTORE_SP_AND_RET
+     .set    at
 
  FEXPORT(ret_from_fork)
      jal     schedule_tail           # a0 = struct task_struct *prev
-
-FEXPORT(syscall_exit)
-#ifdef CONFIG_DEBUG_RSEQ
      move    a0, sp
-     jal     rseq_syscall
-#endif
-     local_irq_disable               # make sure need_resched and
-                                     # signals dont change between
-                                     # sampling and return
-     LONG_L  a2, TI_FLAGS($28)       # current->work
-     li      t0, _TIF_ALLWORK_MASK
-     and     t0, a2, t0
-     bnez    t0, syscall_exit_work
+     jal     syscall_exit_to_user_mode
 
-restore_all:                         # restore full frame
      .set    noat
-     RESTORE_TEMP
-     RESTORE_AT
      RESTORE_STATIC
-restore_partial:             # restore partial frame
-#ifdef CONFIG_TRACE_IRQFLAGS
-     SAVE_STATIC
-     SAVE_AT
-     SAVE_TEMP
-     LONG_L  v0, PT_STATUS(sp)
-#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
-     and     v0, ST0_IEP
-#else
-     and     v0, ST0_IE
-#endif
-     beqz    v0, 1f
-     jal     trace_hardirqs_on
-     b       2f
-1:   jal     trace_hardirqs_off
-2:
+     RESTORE_SOME
+     RESTORE_SP_AND_RET
+     .set    at
+
+restore_all:                         # restore full frame
+     .set    noat
      RESTORE_TEMP
      RESTORE_AT
      RESTORE_STATIC
-#endif
+restore_partial:                     # restore partial frame
      RESTORE_SOME
      RESTORE_SP_AND_RET
      .set    at
@@ -143,32 +126,6 @@ work_notifysig:                          # deal with pending signals and
      jal     do_notify_resume        # a2 already loaded
      j       resume_userspace_check
 
-FEXPORT(syscall_exit_partial)
-#ifdef CONFIG_DEBUG_RSEQ
-     move    a0, sp
-     jal     rseq_syscall
-#endif
-     local_irq_disable               # make sure need_resched doesn't
-                                     # change between and return
-     LONG_L  a2, TI_FLAGS($28)       # current->work
-     li      t0, _TIF_ALLWORK_MASK
-     and     t0, a2
-     beqz    t0, restore_partial
-     SAVE_STATIC
-syscall_exit_work:
-     LONG_L  t0, PT_STATUS(sp)               # returning to kernel mode?
-     andi    t0, t0, KU_USER
-     beqz    t0, resume_kernel
-     li      t0, _TIF_WORK_SYSCALL_EXIT
-     and     t0, a2                  # a2 is preloaded with TI_FLAGS
-     beqz    t0, work_pending        # trace bit set?
-     local_irq_enable                # could let syscall_trace_leave()
-                                     # call schedule() instead
-     TRACE_IRQS_ON
-     move    a0, sp
-     jal     syscall_trace_leave
-     b       resume_userspace
-
  #if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR5) || \
      defined(CONFIG_CPU_MIPSR6) || defined(CONFIG_MIPS_MT)
 
arch/mips/kernel/linux32.c +0 -1
index 6b61be486303..2b4b1fc1ff1b 100644
@@ -38,7 +38,6 @@
  #include <net/scm.h>
 
  #include <asm/compat-signal.h>
-#include <asm/sim.h>
  #include <linux/uaccess.h>
  #include <asm/mmu_context.h>
  #include <asm/mman.h>
arch/mips/kernel/ptrace.c +0 -78
index db7c5be1d4a3..04c08e41cfd3 100644
@@ -46,9 +46,6 @@
  #include <asm/bootinfo.h>
  #include <asm/reg.h>
 
-#define CREATE_TRACE_POINTS
-#include <trace/events/syscalls.h>
-
  /*
   * Called by kernel/ptrace.c when detaching..
   *
@@ -1305,78 +1302,3 @@ long arch_ptrace(struct task_struct *child, long request,
   out:
      return ret;
  }
-
-/*
- * Notification of system call entry/exit
- * - triggered by current->work.syscall_trace
- */
-asmlinkage long syscall_trace_enter(struct pt_regs *regs, long syscall)
-{
-     user_exit();
-
-     current_thread_info()->syscall = syscall;
-
-     if (test_thread_flag(TIF_SYSCALL_TRACE)) {
-             if (tracehook_report_syscall_entry(regs))
-                     return -1;
-             syscall = current_thread_info()->syscall;
-     }
-
-#ifdef CONFIG_SECCOMP
-     if (unlikely(test_thread_flag(TIF_SECCOMP))) {
-             int ret, i;
-             struct seccomp_data sd;
-             unsigned long args[6];
-
-             sd.nr = syscall;
-             sd.arch = syscall_get_arch(current);
-             syscall_get_arguments(current, regs, args);
-             for (i = 0; i < 6; i++)
-                     sd.args[i] = args[i];
-             sd.instruction_pointer = KSTK_EIP(current);
-
-             ret = __secure_computing(&sd);
-             if (ret == -1)
-                     return ret;
-             syscall = current_thread_info()->syscall;
-     }
-#endif
-
-     if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
-             trace_sys_enter(regs, regs->regs[2]);
-
-     audit_syscall_entry(syscall, regs->regs[4], regs->regs[5],
-                         regs->regs[6], regs->regs[7]);
-
-     /*
-      * Negative syscall numbers are mistaken for rejected syscalls, but
-      * won't have had the return value set appropriately, so we do so now.
-      */
-     if (syscall < 0)
-             syscall_set_return_value(current, regs, -ENOSYS, 0);
-     return syscall;
-}
-
-/*
- * Notification of system call entry/exit
- * - triggered by current->work.syscall_trace
- */
-asmlinkage void syscall_trace_leave(struct pt_regs *regs)
-{
-        /*
-      * We may come here right after calling schedule_user()
-      * or do_notify_resume(), in which case we can be in RCU
-      * user mode.
-      */
-     user_exit();
-
-     audit_syscall_exit(regs);
-
-     if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
-             trace_sys_exit(regs, regs_return_value(regs));
-
-     if (test_thread_flag(TIF_SYSCALL_TRACE))
-             tracehook_report_syscall_exit(regs, 0);
-
-     user_enter();
-}
arch/mips/kernel/scall.S new file +135 -0
new file mode 100644
index 000000000000..7b35969151de
@@ -0,0 +1,135 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 1995, 96, 97, 98, 99, 2000, 01, 02 by Ralf Baechle
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
+ * Copyright (C) 2001 MIPS Technologies, Inc.
+ * Copyright (C) 2004 Thiemo Seufer
+ * Copyright (C) 2014 Imagination Technologies Ltd.
+ */
+#include <linux/errno.h>
+#include <asm/asm.h>
+#include <asm/asmmacro.h>
+#include <asm/irqflags.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+#include <asm/asm-offsets.h>
+#include <asm/sysmips.h>
+#include <asm/thread_info.h>
+#include <asm/unistd.h>
+#include <asm/war.h>
+
+     .align  5
+NESTED(handle_sys, PT_SIZE, sp)
+     .set    noat
+     SAVE_SOME
+     SAVE_STATIC
+     CLI
+     .set    at
+
+     move    a0, sp
+     jal     do_syscall
+
+     .set    noat
+     RESTORE_TEMP
+     RESTORE_AT
+     RESTORE_STATIC
+     RESTORE_SOME
+     RESTORE_SP_AND_RET
+     .set    at
+     END(handle_sys)
+
+#ifdef CONFIG_32BIT
+LEAF(sys_syscall)
+     subu    t0, a0, __NR_O32_Linux          # check syscall number
+     sltiu   v0, t0, __NR_O32_Linux_syscalls
+     beqz    t0, einval                      # do not recurse
+     sll     t1, t0, 2
+     beqz    v0, einval
+     lw      t2, sys_call_table(t1)          # syscall routine
+
+     move    a0, a1                          # shift argument registers
+     move    a1, a2
+     move    a2, a3
+     lw      a3, 16(sp)
+     lw      t4, 20(sp)
+     lw      t5, 24(sp)
+     lw      t6, 28(sp)
+     sw      t4, 16(sp)
+     sw      t5, 20(sp)
+     sw      t6, 24(sp)
+     jr      t2
+     /* Unreached */
+
+einval: li   v0, -ENOSYS
+     jr      ra
+     END(sys_syscall)
+
+#ifdef CONFIG_MIPS_MT_FPAFF
+     /*
+      * For FPU affinity scheduling on MIPS MT processors, we need to
+      * intercept sys_sched_xxxaffinity() calls until we get a proper hook
+      * in kernel/sched/core.c.  Considered only temporary we only support
+      * these hooks for the 32-bit kernel - there is no MIPS64 MT processor
+      * atm.
+      */
+#define sys_sched_setaffinity        mipsmt_sys_sched_setaffinity
+#define sys_sched_getaffinity        mipsmt_sys_sched_getaffinity
+#endif /* CONFIG_MIPS_MT_FPAFF */
+
+#define __SYSCALL_WITH_COMPAT(nr, native, compat)    __SYSCALL(nr, native)
+#define __SYSCALL(nr, entry)         PTR entry
+     .align  2
+     .type   sys_call_table, @object
+EXPORT(sys_call_table)
+#include <asm/syscall_table_o32.h>
+#endif /* CONFIG_32BIT */
+
+#ifdef CONFIG_64BIT
+#ifdef CONFIG_MIPS32_O32
+LEAF(sys32_syscall)
+     subu    t0, a0, __NR_O32_Linux          # check syscall number
+     sltiu   v0, t0, __NR_O32_Linux_syscalls
+     beqz    t0, einval                      # do not recurse
+     dsll    t1, t0, 3
+     beqz    v0, einval
+     ld      t2, sys32_call_table(t1)        # syscall routine
+
+     move    a0, a1                          # shift argument registers
+     move    a1, a2
+     move    a2, a3
+     move    a3, a4
+     move    a4, a5
+     move    a5, a6
+     move    a6, a7
+     jr      t2
+     /* Unreached */
+
+einval: li   v0, -ENOSYS
+     jr      ra
+     END(sys32_syscall)
+
+#define __SYSCALL_WITH_COMPAT(nr, native, compat)    __SYSCALL(nr, compat)
+#define __SYSCALL(nr, entry) PTR entry
+     .align  3
+     .type   sys32_call_table,@object
+EXPORT(sys32_call_table)
+#include <asm/syscall_table_o32.h>
+#endif /* CONFIG_MIPS32_O32 */
+
+#ifdef CONFIG_MIPS32_N32
+#undef __SYSCALL
+#define __SYSCALL(nr, entry) PTR entry
+     .align  3
+     .type   sysn32_call_table, @object
+EXPORT(sysn32_call_table)
+#include <asm/syscall_table_n32.h>
+#endif /* CONFIG_MIPS32_N32 */
+
+#undef __SYSCALL
+#define __SYSCALL(nr, entry) PTR entry
+     .align  3
+     .type   sys_call_table, @object
+EXPORT(sys_call_table)
+#include <asm/syscall_table_n64.h>
+#endif /* CONFIG_64BIT */
arch/mips/kernel/scall32-o32.S deleted +0 -223
deleted file mode 100644
index b1b2e106f711..000000000000
@@ -1,223 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1995-99, 2000- 02, 06 Ralf Baechle <[email protected]>
- * Copyright (C) 2001 MIPS Technologies, Inc.
- * Copyright (C) 2004 Thiemo Seufer
- * Copyright (C) 2014 Imagination Technologies Ltd.
- */
-#include <linux/errno.h>
-#include <asm/asm.h>
-#include <asm/asmmacro.h>
-#include <asm/irqflags.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-#include <asm/isadep.h>
-#include <asm/sysmips.h>
-#include <asm/thread_info.h>
-#include <asm/unistd.h>
-#include <asm/war.h>
-#include <asm/asm-offsets.h>
-
-     .align  5
-NESTED(handle_sys, PT_SIZE, sp)
-     .set    noat
-     SAVE_SOME
-     TRACE_IRQS_ON_RELOAD
-     STI
-     .set    at
-
-     lw      t1, PT_EPC(sp)          # skip syscall on return
-
-     addiu   t1, 4                   # skip to next instruction
-     sw      t1, PT_EPC(sp)
-
-     sw      a3, PT_R26(sp)          # save a3 for syscall restarting
-
-     /*
-      * More than four arguments.  Try to deal with it by copying the
-      * stack arguments from the user stack to the kernel stack.
-      * This Sucks (TM).
-      */
-     lw      t0, PT_R29(sp)          # get old user stack pointer
-
-     /*
-      * We intentionally keep the kernel stack a little below the top of
-      * userspace so we don't have to do a slower byte accurate check here.
-      */
-     addu    t4, t0, 32
-     bltz    t4, bad_stack           # -> sp is bad
-
-     /*
-      * Ok, copy the args from the luser stack to the kernel stack.
-      */
-
-     .set    push
-     .set    noreorder
-     .set    nomacro
-
-load_a4: user_lw(t5, 16(t0))         # argument #5 from usp
-load_a5: user_lw(t6, 20(t0))         # argument #6 from usp
-load_a6: user_lw(t7, 24(t0))         # argument #7 from usp
-load_a7: user_lw(t8, 28(t0))         # argument #8 from usp
-loads_done:
-
-     sw      t5, 16(sp)              # argument #5 to ksp
-     sw      t6, 20(sp)              # argument #6 to ksp
-     sw      t7, 24(sp)              # argument #7 to ksp
-     sw      t8, 28(sp)              # argument #8 to ksp
-     .set    pop
-
-     .section __ex_table,"a"
-     PTR     load_a4, bad_stack_a4
-     PTR     load_a5, bad_stack_a5
-     PTR     load_a6, bad_stack_a6
-     PTR     load_a7, bad_stack_a7
-     .previous
-
-     lw      t0, TI_FLAGS($28)       # syscall tracing enabled?
-     li      t1, _TIF_WORK_SYSCALL_ENTRY
-     and     t0, t1
-     bnez    t0, syscall_trace_entry # -> yes
-syscall_common:
-     subu    v0, v0, __NR_O32_Linux  # check syscall number
-     sltiu   t0, v0, __NR_O32_Linux_syscalls
-     beqz    t0, illegal_syscall
-
-     sll     t0, v0, 2
-     la      t1, sys_call_table
-     addu    t1, t0
-     lw      t2, (t1)                # syscall routine
-
-     beqz    t2, illegal_syscall
-
-     jalr    t2                      # Do The Real Thing (TM)
-
-     li      t0, -EMAXERRNO - 1      # error?
-     sltu    t0, t0, v0
-     sw      t0, PT_R7(sp)           # set error flag
-     beqz    t0, 1f
-
-     lw      t1, PT_R2(sp)           # syscall number
-     negu    v0                      # error
-     sw      t1, PT_R0(sp)           # save it for syscall restarting
-1:   sw      v0, PT_R2(sp)           # result
-
-o32_syscall_exit:
-     j       syscall_exit_partial
-
-/* ------------------------------------------------------------------------ */
-
-syscall_trace_entry:
-     SAVE_STATIC
-     move    a0, sp
-
-     /*
-      * syscall number is in v0 unless we called syscall(__NR_###)
-      * where the real syscall number is in a0
-      */
-     move    a1, v0
-     subu    t2, v0,  __NR_O32_Linux
-     bnez    t2, 1f /* __NR_syscall at offset 0 */
-     lw      a1, PT_R4(sp)
-
-1:   jal     syscall_trace_enter
-
-     bltz    v0, 1f                  # seccomp failed? Skip syscall
-
-     RESTORE_STATIC
-     lw      v0, PT_R2(sp)           # Restore syscall (maybe modified)
-     lw      a0, PT_R4(sp)           # Restore argument registers
-     lw      a1, PT_R5(sp)
-     lw      a2, PT_R6(sp)
-     lw      a3, PT_R7(sp)
-     j       syscall_common
-
-1:   j       syscall_exit
-
-/* ------------------------------------------------------------------------ */
-
-     /*
-      * Our open-coded access area sanity test for the stack pointer
-      * failed. We probably should handle this case a bit more drastic.
-      */
-bad_stack:
-     li      v0, EFAULT
-     sw      v0, PT_R2(sp)
-     li      t0, 1                           # set error flag
-     sw      t0, PT_R7(sp)
-     j       o32_syscall_exit
-
-bad_stack_a4:
-     li      t5, 0
-     b       load_a5
-
-bad_stack_a5:
-     li      t6, 0
-     b       load_a6
-
-bad_stack_a6:
-     li      t7, 0
-     b       load_a7
-
-bad_stack_a7:
-     li      t8, 0
-     b       loads_done
-
-     /*
-      * The system call does not exist in this kernel
-      */
-illegal_syscall:
-     li      v0, ENOSYS                      # error
-     sw      v0, PT_R2(sp)
-     li      t0, 1                           # set error flag
-     sw      t0, PT_R7(sp)
-     j       o32_syscall_exit
-     END(handle_sys)
-
-     LEAF(sys_syscall)
-     subu    t0, a0, __NR_O32_Linux  # check syscall number
-     sltiu   v0, t0, __NR_O32_Linux_syscalls
-     beqz    t0, einval              # do not recurse
-     sll     t1, t0, 2
-     beqz    v0, einval
-     lw      t2, sys_call_table(t1)          # syscall routine
-
-     move    a0, a1                          # shift argument registers
-     move    a1, a2
-     move    a2, a3
-     lw      a3, 16(sp)
-     lw      t4, 20(sp)
-     lw      t5, 24(sp)
-     lw      t6, 28(sp)
-     sw      t4, 16(sp)
-     sw      t5, 20(sp)
-     sw      t6, 24(sp)
-     jr      t2
-     /* Unreached */
-
-einval: li   v0, -ENOSYS
-     jr      ra
-     END(sys_syscall)
-
-#ifdef CONFIG_MIPS_MT_FPAFF
-     /*
-      * For FPU affinity scheduling on MIPS MT processors, we need to
-      * intercept sys_sched_xxxaffinity() calls until we get a proper hook
-      * in kernel/sched/core.c.  Considered only temporary we only support
-      * these hooks for the 32-bit kernel - there is no MIPS64 MT processor
-      * atm.
-      */
-#define sys_sched_setaffinity        mipsmt_sys_sched_setaffinity
-#define sys_sched_getaffinity        mipsmt_sys_sched_getaffinity
-#endif /* CONFIG_MIPS_MT_FPAFF */
-
-#define __SYSCALL_WITH_COMPAT(nr, native, compat)    __SYSCALL(nr, native)
-#define __SYSCALL(nr, entry)         PTR entry
-     .align  2
-     .type   sys_call_table, @object
-EXPORT(sys_call_table)
-#include <asm/syscall_table_o32.h>
arch/mips/kernel/scall64-n32.S deleted +0 -107
deleted file mode 100644
index f650c55a17dc..000000000000
@@ -1,107 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1995, 96, 97, 98, 99, 2000, 01 by Ralf Baechle
- * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
- * Copyright (C) 2001 MIPS Technologies, Inc.
- */
-#include <linux/errno.h>
-#include <asm/asm.h>
-#include <asm/asmmacro.h>
-#include <asm/irqflags.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-#include <asm/thread_info.h>
-#include <asm/unistd.h>
-
-#ifndef CONFIG_MIPS32_O32
-/* No O32, so define handle_sys here */
-#define handle_sysn32 handle_sys
-#endif
-
-     .align  5
-NESTED(handle_sysn32, PT_SIZE, sp)
-#ifndef CONFIG_MIPS32_O32
-     .set    noat
-     SAVE_SOME
-     TRACE_IRQS_ON_RELOAD
-     STI
-     .set    at
-#endif
-
-     dsubu   t0, v0, __NR_N32_Linux  # check syscall number
-     sltiu   t0, t0, __NR_N32_Linux_syscalls
-
-#ifndef CONFIG_MIPS32_O32
-     ld      t1, PT_EPC(sp)          # skip syscall on return
-     daddiu  t1, 4                   # skip to next instruction
-     sd      t1, PT_EPC(sp)
-#endif
-     beqz    t0, not_n32_scall
-
-     sd      a3, PT_R26(sp)          # save a3 for syscall restarting
-
-     li      t1, _TIF_WORK_SYSCALL_ENTRY
-     LONG_L  t0, TI_FLAGS($28)       # syscall tracing enabled?
-     and     t0, t1, t0
-     bnez    t0, n32_syscall_trace_entry
-
-syscall_common:
-     dsll    t0, v0, 3               # offset into table
-     ld      t2, (sysn32_call_table - (__NR_N32_Linux * 8))(t0)
-
-     jalr    t2                      # Do The Real Thing (TM)
-
-     li      t0, -EMAXERRNO - 1      # error?
-     sltu    t0, t0, v0
-     sd      t0, PT_R7(sp)           # set error flag
-     beqz    t0, 1f
-
-     ld      t1, PT_R2(sp)           # syscall number
-     dnegu   v0                      # error
-     sd      t1, PT_R0(sp)           # save it for syscall restarting
-1:   sd      v0, PT_R2(sp)           # result
-
-     j       syscall_exit_partial
-
-/* ------------------------------------------------------------------------ */
-
-n32_syscall_trace_entry:
-     SAVE_STATIC
-     move    a0, sp
-     move    a1, v0
-     jal     syscall_trace_enter
-
-     bltz    v0, 1f                  # seccomp failed? Skip syscall
-
-     RESTORE_STATIC
-     ld      v0, PT_R2(sp)           # Restore syscall (maybe modified)
-     ld      a0, PT_R4(sp)           # Restore argument registers
-     ld      a1, PT_R5(sp)
-     ld      a2, PT_R6(sp)
-     ld      a3, PT_R7(sp)
-     ld      a4, PT_R8(sp)
-     ld      a5, PT_R9(sp)
-
-     dsubu   t2, v0, __NR_N32_Linux  # check (new) syscall number
-     sltiu   t0, t2, __NR_N32_Linux_syscalls
-     beqz    t0, not_n32_scall
-
-     j       syscall_common
-
-1:   j       syscall_exit
-
-not_n32_scall:
-     /* This is not an n32 compatibility syscall, pass it on to
-        the n64 syscall handlers.  */
-     j       handle_sys64
-
-     END(handle_sysn32)
-
-#define __SYSCALL(nr, entry) PTR entry
-     .type   sysn32_call_table, @object
-EXPORT(sysn32_call_table)
-#include <asm/syscall_table_n32.h>
arch/mips/kernel/scall64-n64.S deleted +0 -116
deleted file mode 100644
index 5d7bfc65e4d0..000000000000
@@ -1,116 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1995, 96, 97, 98, 99, 2000, 01, 02 by Ralf Baechle
- * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
- * Copyright (C) 2001 MIPS Technologies, Inc.
- */
-#include <linux/errno.h>
-#include <asm/asm.h>
-#include <asm/asmmacro.h>
-#include <asm/irqflags.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-#include <asm/asm-offsets.h>
-#include <asm/sysmips.h>
-#include <asm/thread_info.h>
-#include <asm/unistd.h>
-#include <asm/war.h>
-
-#ifndef CONFIG_MIPS32_COMPAT
-/* Neither O32 nor N32, so define handle_sys here */
-#define handle_sys64 handle_sys
-#endif
-
-     .align  5
-NESTED(handle_sys64, PT_SIZE, sp)
-#if !defined(CONFIG_MIPS32_O32) && !defined(CONFIG_MIPS32_N32)
-     /*
-      * When 32-bit compatibility is configured scall_o32.S
-      * already did this.
-      */
-     .set    noat
-     SAVE_SOME
-     TRACE_IRQS_ON_RELOAD
-     STI
-     .set    at
-#endif
-
-#if !defined(CONFIG_MIPS32_O32) && !defined(CONFIG_MIPS32_N32)
-     ld      t1, PT_EPC(sp)          # skip syscall on return
-     daddiu  t1, 4                   # skip to next instruction
-     sd      t1, PT_EPC(sp)
-#endif
-
-     sd      a3, PT_R26(sp)          # save a3 for syscall restarting
-
-     li      t1, _TIF_WORK_SYSCALL_ENTRY
-     LONG_L  t0, TI_FLAGS($28)       # syscall tracing enabled?
-     and     t0, t1, t0
-     bnez    t0, syscall_trace_entry
-
-syscall_common:
-     dsubu   t2, v0, __NR_64_Linux
-     sltiu   t0, t2, __NR_64_Linux_syscalls
-     beqz    t0, illegal_syscall
-
-     dsll    t0, t2, 3               # offset into table
-     dla     t2, sys_call_table
-     daddu   t0, t2, t0
-     ld      t2, (t0)                # syscall routine
-     beqz    t2, illegal_syscall
-
-     jalr    t2                      # Do The Real Thing (TM)
-
-     li      t0, -EMAXERRNO - 1      # error?
-     sltu    t0, t0, v0
-     sd      t0, PT_R7(sp)           # set error flag
-     beqz    t0, 1f
-
-     ld      t1, PT_R2(sp)           # syscall number
-     dnegu   v0                      # error
-     sd      t1, PT_R0(sp)           # save it for syscall restarting
-1:   sd      v0, PT_R2(sp)           # result
-
-n64_syscall_exit:
-     j       syscall_exit_partial
-
-/* ------------------------------------------------------------------------ */
-
-syscall_trace_entry:
-     SAVE_STATIC
-     move    a0, sp
-     move    a1, v0
-     jal     syscall_trace_enter
-
-     bltz    v0, 1f                  # seccomp failed? Skip syscall
-
-     RESTORE_STATIC
-     ld      v0, PT_R2(sp)           # Restore syscall (maybe modified)
-     ld      a0, PT_R4(sp)           # Restore argument registers
-     ld      a1, PT_R5(sp)
-     ld      a2, PT_R6(sp)
-     ld      a3, PT_R7(sp)
-     ld      a4, PT_R8(sp)
-     ld      a5, PT_R9(sp)
-     j       syscall_common
-
-1:   j       syscall_exit
-
-illegal_syscall:
-     /* This also isn't a 64-bit syscall, throw an error.  */
-     li      v0, ENOSYS                      # error
-     sd      v0, PT_R2(sp)
-     li      t0, 1                           # set error flag
-     sd      t0, PT_R7(sp)
-     j       n64_syscall_exit
-     END(handle_sys64)
-
-#define __SYSCALL(nr, entry) PTR entry
-     .align  3
-     .type   sys_call_table, @object
-EXPORT(sys_call_table)
-#include <asm/syscall_table_n64.h>
arch/mips/kernel/scall64-o32.S deleted +0 -221
deleted file mode 100644
index cedc8bd88804..000000000000
@@ -1,221 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1995 - 2000, 2001 by Ralf Baechle
- * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
- * Copyright (C) 2001 MIPS Technologies, Inc.
- * Copyright (C) 2004 Thiemo Seufer
- *
- * Hairy, the userspace application uses a different argument passing
- * convention than the kernel, so we have to translate things from o32
- * to ABI64 calling convention.       64-bit syscalls are also processed
- * here for now.
- */
-#include <linux/errno.h>
-#include <asm/asm.h>
-#include <asm/asmmacro.h>
-#include <asm/irqflags.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-#include <asm/thread_info.h>
-#include <asm/unistd.h>
-#include <asm/sysmips.h>
-
-     .align  5
-NESTED(handle_sys, PT_SIZE, sp)
-     .set    noat
-     SAVE_SOME
-     TRACE_IRQS_ON_RELOAD
-     STI
-     .set    at
-     ld      t1, PT_EPC(sp)          # skip syscall on return
-
-     dsubu   t0, v0, __NR_O32_Linux  # check syscall number
-     sltiu   t0, t0, __NR_O32_Linux_syscalls
-     daddiu  t1, 4                   # skip to next instruction
-     sd      t1, PT_EPC(sp)
-     beqz    t0, not_o32_scall
-#if 0
- SAVE_ALL
- move a1, v0
- ASM_PRINT("Scall %ld\n")
- RESTORE_ALL
-#endif
-
-     /* We don't want to stumble over broken sign extensions from
-        userland. O32 does never use the upper half. */
-     sll     a0, a0, 0
-     sll     a1, a1, 0
-     sll     a2, a2, 0
-     sll     a3, a3, 0
-
-     sd      a3, PT_R26(sp)          # save a3 for syscall restarting
-
-     /*
-      * More than four arguments.  Try to deal with it by copying the
-      * stack arguments from the user stack to the kernel stack.
-      * This Sucks (TM).
-      *
-      * We intentionally keep the kernel stack a little below the top of
-      * userspace so we don't have to do a slower byte accurate check here.
-      */
-     ld      t0, PT_R29(sp)          # get old user stack pointer
-     daddu   t1, t0, 32
-     bltz    t1, bad_stack
-
-load_a4: lw  a4, 16(t0)              # argument #5 from usp
-load_a5: lw  a5, 20(t0)              # argument #6 from usp
-load_a6: lw  a6, 24(t0)              # argument #7 from usp
-load_a7: lw  a7, 28(t0)              # argument #8 from usp
-loads_done:
-
-     .section __ex_table,"a"
-     PTR     load_a4, bad_stack_a4
-     PTR     load_a5, bad_stack_a5
-     PTR     load_a6, bad_stack_a6
-     PTR     load_a7, bad_stack_a7
-     .previous
-
-     li      t1, _TIF_WORK_SYSCALL_ENTRY
-     LONG_L  t0, TI_FLAGS($28)       # syscall tracing enabled?
-     and     t0, t1, t0
-     bnez    t0, trace_a_syscall
-
-syscall_common:
-     dsll    t0, v0, 3               # offset into table
-     ld      t2, (sys32_call_table - (__NR_O32_Linux * 8))(t0)
-
-     jalr    t2                      # Do The Real Thing (TM)
-
-     li      t0, -EMAXERRNO - 1      # error?
-     sltu    t0, t0, v0
-     sd      t0, PT_R7(sp)           # set error flag
-     beqz    t0, 1f
-
-     ld      t1, PT_R2(sp)           # syscall number
-     dnegu   v0                      # error
-     sd      t1, PT_R0(sp)           # save it for syscall restarting
-1:   sd      v0, PT_R2(sp)           # result
-
-o32_syscall_exit:
-     j       syscall_exit_partial
-
-/* ------------------------------------------------------------------------ */
-
-trace_a_syscall:
-     SAVE_STATIC
-     sd      a4, PT_R8(sp)           # Save argument registers
-     sd      a5, PT_R9(sp)
-     sd      a6, PT_R10(sp)
-     sd      a7, PT_R11(sp)          # For indirect syscalls
-
-     move    a0, sp
-     /*
-      * absolute syscall number is in v0 unless we called syscall(__NR_###)
-      * where the real syscall number is in a0
-      * note: NR_syscall is the first O32 syscall but the macro is
-      * only defined when compiling with -mabi=32 (CONFIG_32BIT)
-      * therefore __NR_O32_Linux is used (4000)
-      */
-     .set    push
-     .set    reorder
-     subu    t1, v0,  __NR_O32_Linux
-     move    a1, v0
-     bnez    t1, 1f /* __NR_syscall at offset 0 */
-     ld      a1, PT_R4(sp) /* Arg1 for __NR_syscall case */
-     .set    pop
-
-1:   jal     syscall_trace_enter
-
-     bltz    v0, 1f                  # seccomp failed? Skip syscall
-
-     RESTORE_STATIC
-     ld      v0, PT_R2(sp)           # Restore syscall (maybe modified)
-     ld      a0, PT_R4(sp)           # Restore argument registers
-     ld      a1, PT_R5(sp)
-     ld      a2, PT_R6(sp)
-     ld      a3, PT_R7(sp)
-     ld      a4, PT_R8(sp)
-     ld      a5, PT_R9(sp)
-     ld      a6, PT_R10(sp)
-     ld      a7, PT_R11(sp)          # For indirect syscalls
-
-     dsubu   t0, v0, __NR_O32_Linux  # check (new) syscall number
-     sltiu   t0, t0, __NR_O32_Linux_syscalls
-     beqz    t0, not_o32_scall
-
-     j       syscall_common
-
-1:   j       syscall_exit
-
-/* ------------------------------------------------------------------------ */
-
-     /*
-      * The stackpointer for a call with more than 4 arguments is bad.
-      */
-bad_stack:
-     li      v0, EFAULT
-     sd      v0, PT_R2(sp)
-     li      t0, 1                   # set error flag
-     sd      t0, PT_R7(sp)
-     j       o32_syscall_exit
-
-bad_stack_a4:
-     li      a4, 0
-     b       load_a5
-
-bad_stack_a5:
-     li      a5, 0
-     b       load_a6
-
-bad_stack_a6:
-     li      a6, 0
-     b       load_a7
-
-bad_stack_a7:
-     li      a7, 0
-     b       loads_done
-
-not_o32_scall:
-     /*
-      * This is not an o32 compatibility syscall, pass it on
-      * to the 64-bit syscall handlers.
-      */
-#ifdef CONFIG_MIPS32_N32
-     j       handle_sysn32
-#else
-     j       handle_sys64
-#endif
-     END(handle_sys)
-
-LEAF(sys32_syscall)
-     subu    t0, a0, __NR_O32_Linux  # check syscall number
-     sltiu   v0, t0, __NR_O32_Linux_syscalls
-     beqz    t0, einval              # do not recurse
-     dsll    t1, t0, 3
-     beqz    v0, einval
-     ld      t2, sys32_call_table(t1)                # syscall routine
-
-     move    a0, a1                  # shift argument registers
-     move    a1, a2
-     move    a2, a3
-     move    a3, a4
-     move    a4, a5
-     move    a5, a6
-     move    a6, a7
-     jr      t2
-     /* Unreached */
-
-einval: li   v0, -ENOSYS
-     jr      ra
-     END(sys32_syscall)
-
-#define __SYSCALL_WITH_COMPAT(nr, native, compat)    __SYSCALL(nr, compat)
-#define __SYSCALL(nr, entry) PTR entry
-     .align  3
-     .type   sys32_call_table,@object
-EXPORT(sys32_call_table)
-#include <asm/syscall_table_o32.h>
arch/mips/kernel/signal.c +11 -24
index f1e985109da0..1ec6a0cf1163 100644
@@ -32,7 +32,6 @@
  #include <linux/bitops.h>
  #include <asm/cacheflush.h>
  #include <asm/fpu.h>
-#include <asm/sim.h>
  #include <asm/ucontext.h>
  #include <asm/cpu-features.h>
  #include <asm/war.h>
@@ -627,7 +626,7 @@ SYSCALL_DEFINE3(sigaction, int, sig, const struct sigaction __user *, act,
  #endif
 
  #ifdef CONFIG_TRAD_SIGNALS
-asmlinkage void sys_sigreturn(void)
+asmlinkage long sys_sigreturn(void)
  {
      struct sigframe __user *frame;
      struct pt_regs *regs;
@@ -649,22 +648,16 @@ asmlinkage void sys_sigreturn(void)
      else if (sig)
              force_sig(sig);
 
-     /*
-      * Don't let your children do this ...
-      */
-     __asm__ __volatile__(
-             "move\t$29, %0\n\t"
-             "j\tsyscall_exit"
-             : /* no outputs */
-             : "r" (regs));
-     /* Unreached */
+     regs->regs[27] = 1;     /* return directly */
+     return regs->regs[2];
 
  badframe:
      force_sig(SIGSEGV);
+     return 0;
  }
  #endif /* CONFIG_TRAD_SIGNALS */
 
-asmlinkage void sys_rt_sigreturn(void)
+asmlinkage long sys_rt_sigreturn(void)
  {
      struct rt_sigframe __user *frame;
      struct pt_regs *regs;
@@ -689,18 +682,12 @@ asmlinkage void sys_rt_sigreturn(void)
      if (restore_altstack(&frame->rs_uc.uc_stack))
              goto badframe;
 
-     /*
-      * Don't let your children do this ...
-      */
-     __asm__ __volatile__(
-             "move\t$29, %0\n\t"
-             "j\tsyscall_exit"
-             : /* no outputs */
-             : "r" (regs));
-     /* Unreached */
+     regs->regs[27] = 1;     /* return directly */
+     return regs->regs[2];
 
  badframe:
      force_sig(SIGSEGV);
+     return 0;
  }
 
  #ifdef CONFIG_TRAD_SIGNALS
@@ -852,11 +839,11 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
      signal_setup_done(ret, ksig, 0);
  }
 
-static void do_signal(struct pt_regs *regs)
+void arch_do_signal_or_restart(struct pt_regs *regs, bool has_signal)
  {
      struct ksignal ksig;
 
-     if (get_signal(&ksig)) {
+     if (has_signal && get_signal(&ksig)) {
              /* Whee!  Actually deliver the signal.  */
              handle_signal(&ksig, regs);
              return;
@@ -904,7 +891,7 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, void *unused,
 
      /* deal with pending signal delivery */
      if (thread_info_flags & (_TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL))
-             do_signal(regs);
+             arch_do_signal_or_restart(regs, thread_info_flags & _TIF_SIGPENDING);
 
      if (thread_info_flags & _TIF_NOTIFY_RESUME) {
              tracehook_notify_resume(regs);
arch/mips/kernel/signal_n32.c +4 -11
index 7bd00fad61af..b52b995a8a9b 100644
@@ -19,7 +19,6 @@
  #include <asm/asm.h>
  #include <asm/cacheflush.h>
  #include <asm/compat-signal.h>
-#include <asm/sim.h>
  #include <linux/uaccess.h>
  #include <asm/ucontext.h>
  #include <asm/fpu.h>
@@ -51,7 +50,7 @@ struct rt_sigframe_n32 {
      struct ucontextn32 rs_uc;
  };
 
-asmlinkage void sysn32_rt_sigreturn(void)
+asmlinkage long sysn32_rt_sigreturn(void)
  {
      struct rt_sigframe_n32 __user *frame;
      struct pt_regs *regs;
@@ -76,18 +75,12 @@ asmlinkage void sysn32_rt_sigreturn(void)
      if (compat_restore_altstack(&frame->rs_uc.uc_stack))
              goto badframe;
 
-     /*
-      * Don't let your children do this ...
-      */
-     __asm__ __volatile__(
-             "move\t$29, %0\n\t"
-             "j\tsyscall_exit"
-             : /* no outputs */
-             : "r" (regs));
-     /* Unreached */
+     regs->regs[27] = 1;     /* return directly */
+     return regs->regs[2];
 
  badframe:
      force_sig(SIGSEGV);
+     return 0;
  }
 
  static int setup_rt_frame_n32(void *sig_return, struct ksignal *ksig,
arch/mips/kernel/signal_o32.c +8 -21
index 299a7a28ca33..9245806e06f1 100644
@@ -17,7 +17,6 @@
  #include <asm/abi.h>
  #include <asm/compat-signal.h>
  #include <asm/dsp.h>
-#include <asm/sim.h>
  #include <asm/unistd.h>
 
  #include "signal-common.h"
@@ -151,7 +150,7 @@ static int setup_frame_32(void *sig_return, struct ksignal *ksig,
      return 0;
  }
 
-asmlinkage void sys32_rt_sigreturn(void)
+asmlinkage long sys32_rt_sigreturn(void)
  {
      struct rt_sigframe32 __user *frame;
      struct pt_regs *regs;
@@ -176,18 +175,12 @@ asmlinkage void sys32_rt_sigreturn(void)
      if (compat_restore_altstack(&frame->rs_uc.uc_stack))
              goto badframe;
 
-     /*
-      * Don't let your children do this ...
-      */
-     __asm__ __volatile__(
-             "move\t$29, %0\n\t"
-             "j\tsyscall_exit"
-             : /* no outputs */
-             : "r" (regs));
-     /* Unreached */
+     regs->regs[27] = 1;     /* return directly */
+     return regs->regs[2];
 
  badframe:
      force_sig(SIGSEGV);
+     return 0;
  }
 
  static int setup_rt_frame_32(void *sig_return, struct ksignal *ksig,
@@ -253,7 +246,7 @@ struct mips_abi mips_abi_32 = {
  };
 
 
-asmlinkage void sys32_sigreturn(void)
+asmlinkage long sys32_sigreturn(void)
  {
      struct sigframe32 __user *frame;
      struct pt_regs *regs;
@@ -275,16 +268,10 @@ asmlinkage void sys32_sigreturn(void)
      else if (sig)
              force_sig(sig);
 
-     /*
-      * Don't let your children do this ...
-      */
-     __asm__ __volatile__(
-             "move\t$29, %0\n\t"
-             "j\tsyscall_exit"
-             : /* no outputs */
-             : "r" (regs));
-     /* Unreached */
+     regs->regs[27] = 1;     /* return directly */
+     return regs->regs[2];
 
  badframe:
      force_sig(SIGSEGV);
+     return 0;
  }
arch/mips/kernel/syscall.c +122 -25
index 2afa3eef486a..6dc78648b274 100644
@@ -8,6 +8,7 @@
   * Copyright (C) 2001 MIPS Technologies, Inc.
   */
  #include <linux/capability.h>
+#include <linux/entry-common.h>
  #include <linux/errno.h>
  #include <linux/linkage.h>
  #include <linux/fs.h>
@@ -35,9 +36,9 @@
  #include <asm/cacheflush.h>
  #include <asm/asm-offsets.h>
  #include <asm/signal.h>
-#include <asm/sim.h>
  #include <asm/shmparam.h>
  #include <asm/sync.h>
+#include <asm/syscall.h>
  #include <asm/sysmips.h>
  #include <asm/switch_to.h>
 
@@ -79,10 +80,6 @@ SYSCALL_DEFINE6(mips_mmap2, unsigned long, addr, unsigned long, len,
                             pgoff >> (PAGE_SHIFT - 12));
  }
 
-save_static_function(sys_fork);
-save_static_function(sys_clone);
-save_static_function(sys_clone3);
-
  SYSCALL_DEFINE1(set_thread_area, unsigned long, addr)
  {
      struct thread_info *ti = task_thread_info(current);
@@ -182,28 +179,11 @@ static inline int mips_atomic_set(unsigned long addr, unsigned long new)
              return err;
 
      regs = current_pt_regs();
-     regs->regs[2] = old;
-     regs->regs[7] = 0;      /* No error */
-
-     /*
-      * Don't let your children do this ...
-      */
-     __asm__ __volatile__(
-     "       move    $29, %0                                         \n"
-     "       j       syscall_exit                                    \n"
-     : /* no outputs */
-     : "r" (regs));
-
-     /* unreached.  Honestly.  */
-     unreachable();
+     regs->regs[7] = 0;      /* no error */
+     regs->regs[27] = 1;     /* return directly */
+     return old;
  }
 
-/*
- * mips_atomic_set() normally returns directly via syscall_exit potentially
- * clobbering static registers, so be sure to preserve them.
- */
-save_static_function(sys_sysmips);
-
  SYSCALL_DEFINE3(sysmips, long, cmd, long, arg1, long, arg2)
  {
      switch (cmd) {
@@ -249,3 +229,120 @@ asmlinkage void bad_stack(void)
  {
      do_exit(SIGSEGV);
  }
+
+#if defined(CONFIG_32BIT) || defined(CONFIG_MIPS32_O32)
+static inline int get_args(struct pt_regs *regs)
+{
+     int *usp = (int *)regs->regs[29];
+
+#ifdef CONFIG_MIPS32_O32
+     /*
+      * Hairy, the userspace application uses a different argument passing
+      * convention than the kernel, so we have to translate things from o32
+      * to ABI64 calling convention.
+      *
+      * We don't want to stumble over broken sign extensions from userland.
+      * O32 does never use the upper half.
+      */
+     regs->regs[4] = (int)regs->regs[4];
+     regs->regs[5] = (int)regs->regs[5];
+     regs->regs[6] = (int)regs->regs[6];
+     regs->regs[7] = (int)regs->regs[7];
+#endif
+
+     /*
+      * More than four arguments.  Try to deal with it by copying the
+      * stack arguments from the user stack to the kernel stack.
+      * This Sucks (TM).
+      *
+      * We intentionally keep the kernel stack a little below the top of
+      * userspace so we don't have to do a slower byte accurate check here.
+      */
+     if (!access_ok(usp, 32))
+             return -1;
+
+     get_user(regs->regs[8], usp + 4);
+     get_user(regs->regs[9], usp + 5);
+     get_user(regs->regs[10], usp + 6);
+     get_user(regs->regs[11], usp + 7);
+
+     return 0;
+}
+#endif
+
+typedef long (*sys_call_fn)(unsigned long, unsigned long,
+     unsigned long, unsigned long, unsigned long, unsigned long);
+
+void noinstr do_syscall(struct pt_regs *regs)
+{
+     unsigned long nr;
+     unsigned long ret;
+     sys_call_fn syscall_fn = NULL;
+
+     nr = regs->regs[2];
+     current_thread_info()->syscall = nr;
+     nr = syscall_enter_from_user_mode(regs, nr);
+
+     regs->cp0_epc += 4;             /* skip syscall on return */
+                                     /* skip to next instruction */
+     regs->regs[26] = regs->regs[7]; /* save a3 for syscall restarting */
+     regs->regs[27] = 0;             /* do not return directly */
+
+#ifdef CONFIG_32BIT
+     if (nr >= __NR_O32_Linux && nr < __NR_O32_Linux + __NR_O32_Linux_syscalls) {
+             if (get_args(regs) < 0) {
+                     ret = EFAULT;
+                     goto error;
+             }
+             syscall_fn = (sys_call_fn)sys_call_table[nr - __NR_O32_Linux];
+     }
+#endif
+
+#ifdef CONFIG_MIPS32_O32
+     if (nr >= __NR_O32_Linux && nr < __NR_O32_Linux + __NR_O32_Linux_syscalls) {
+             if (get_args(regs) < 0) {
+                     ret = EFAULT;
+                     goto error;
+             }
+             syscall_fn = (sys_call_fn)sys32_call_table[nr - __NR_O32_Linux];
+     }
+#endif
+
+#ifdef CONFIG_MIPS32_N32
+     if (nr >= __NR_N32_Linux && nr < __NR_N32_Linux + __NR_N32_Linux_syscalls)
+             syscall_fn = (sys_call_fn)sysn32_call_table[nr - __NR_N32_Linux];
+#endif
+
+#ifdef CONFIG_64BIT
+     if (nr >= __NR_64_Linux && nr < __NR_64_Linux + __NR_64_Linux_syscalls)
+             syscall_fn = (sys_call_fn)sys_call_table[nr - __NR_64_Linux];
+#endif
+
+     if (!syscall_fn) {
+             ret = ENOSYS;
+             goto error;
+     }
+
+     ret = syscall_fn(regs->regs[4], regs->regs[5], regs->regs[6],
+                      regs->regs[7], regs->regs[8], regs->regs[9]);
+
+     if (regs->regs[27])             /* return directly? */
+             goto out;
+
+     regs->regs[7] = 0;              /* clear error flag */
+     if (ret >= -EMAXERRNO - 1) {    /* error? */
+             regs->regs[0] = nr;     /* save syscall number */
+                                     /* for syscall restarting */
+             ret = -ret;
+             goto error;
+     }
+
+     goto out;
+
+error:
+     regs->regs[7] = 1;              /* set error flag */
+
+out:
+     regs->regs[2] = ret;
+     syscall_exit_to_user_mode(regs);
+}
arch/mips/kernel/syscalls/syscall_n32.tbl +4 -4
index 70e32de2bcaa..d9ae765e51f1 100644
@@ -62,8 +62,8 @@
  52  n32     socketpair                      sys_socketpair
  53  n32     setsockopt                      sys_setsockopt
  54  n32     getsockopt                      sys_getsockopt
-55   n32     clone                           __sys_clone
-56   n32     fork                            __sys_fork
+55   n32     clone                           sys_clone
+56   n32     fork                            sys_fork
  57  n32     execve                          compat_sys_execve
  58  n32     exit                            sys_exit
  59  n32     wait4                           compat_sys_wait4
@@ -207,7 +207,7 @@
  196 n32     sched_getaffinity               compat_sys_sched_getaffinity
  197 n32     cacheflush                      sys_cacheflush
  198 n32     cachectl                        sys_cachectl
-199  n32     sysmips                         __sys_sysmips
+199  n32     sysmips                         sys_sysmips
  200 n32     io_setup                        compat_sys_io_setup
  201 n32     io_destroy                      sys_io_destroy
  202 n32     io_getevents                    sys_io_getevents_time32
@@ -373,7 +373,7 @@
  432 n32     fsmount                         sys_fsmount
  433 n32     fspick                          sys_fspick
  434 n32     pidfd_open                      sys_pidfd_open
-435  n32     clone3                          __sys_clone3
+435  n32     clone3                          sys_clone3
  436 n32     close_range                     sys_close_range
  437 n32     openat2                         sys_openat2
  438 n32     pidfd_getfd                     sys_pidfd_getfd
arch/mips/kernel/syscalls/syscall_n64.tbl +4 -4
index 1ca7bc337932..edec3e82d67a 100644
@@ -62,8 +62,8 @@
  52  n64     socketpair                      sys_socketpair
  53  n64     setsockopt                      sys_setsockopt
  54  n64     getsockopt                      sys_getsockopt
-55   n64     clone                           __sys_clone
-56   n64     fork                            __sys_fork
+55   n64     clone                           sys_clone
+56   n64     fork                            sys_fork
  57  n64     execve                          sys_execve
  58  n64     exit                            sys_exit
  59  n64     wait4                           sys_wait4
@@ -207,7 +207,7 @@
  196 n64     sched_getaffinity               sys_sched_getaffinity
  197 n64     cacheflush                      sys_cacheflush
  198 n64     cachectl                        sys_cachectl
-199  n64     sysmips                         __sys_sysmips
+199  n64     sysmips                         sys_sysmips
  200 n64     io_setup                        sys_io_setup
  201 n64     io_destroy                      sys_io_destroy
  202 n64     io_getevents                    sys_io_getevents
@@ -349,7 +349,7 @@
  432 n64     fsmount                         sys_fsmount
  433 n64     fspick                          sys_fspick
  434 n64     pidfd_open                      sys_pidfd_open
-435  n64     clone3                          __sys_clone3
+435  n64     clone3                          sys_clone3
  436 n64     close_range                     sys_close_range
  437 n64     openat2                         sys_openat2
  438 n64     pidfd_getfd                     sys_pidfd_getfd
arch/mips/kernel/syscalls/syscall_o32.tbl +4 -4
index a61c35edaa74..89a1f267da6a 100644
@@ -9,7 +9,7 @@
  #
  0   o32     syscall                         sys_syscall                     sys32_syscall
  1   o32     exit                            sys_exit
-2    o32     fork                            __sys_fork
+2    o32     fork                            sys_fork
  3   o32     read                            sys_read
  4   o32     write                           sys_write
  5   o32     open                            sys_open                        compat_sys_open
@@ -131,7 +131,7 @@
  117 o32     ipc                             sys_ipc                         compat_sys_ipc
  118 o32     fsync                           sys_fsync
  119 o32     sigreturn                       sys_sigreturn                   sys32_sigreturn
-120  o32     clone                           __sys_clone
+120  o32     clone                           sys_clone
  121 o32     setdomainname                   sys_setdomainname
  122 o32     uname                           sys_newuname
  123 o32     modify_ldt                      sys_ni_syscall
@@ -160,7 +160,7 @@
  146 o32     writev                          sys_writev
  147 o32     cacheflush                      sys_cacheflush
  148 o32     cachectl                        sys_cachectl
-149  o32     sysmips                         __sys_sysmips
+149  o32     sysmips                         sys_sysmips
  150 o32     unused150                       sys_ni_syscall
  151 o32     getsid                          sys_getsid
  152 o32     fdatasync                       sys_fdatasync
@@ -422,7 +422,7 @@
  432 o32     fsmount                         sys_fsmount
  433 o32     fspick                          sys_fspick
  434 o32     pidfd_open                      sys_pidfd_open
-435  o32     clone3                          __sys_clone3
+435  o32     clone3                          sys_clone3
  436 o32     close_range                     sys_close_range
  437 o32     openat2                         sys_openat2
  438 o32     pidfd_getfd                     sys_pidfd_getfd
Reviewed-by
#4 lore raw

Re: [PATCH 1/2] mips: convert syscall to generic entry

Quoted 1,878 lines · 陈飞扬
Quoted 25 lines · Jiaxun Yang
Quoted 16 lines · FreeFlyingSheep

From: Feiyang Chen <[email protected]>

Convert mips syscall to use the generic entry infrastructure from kernel/entry/*.

There are a few special things on mips:

- There is one type of syscall on mips32 (scall32-o32) and three types of syscalls on mips64 (scall64-o32, scall64-n32 and scall64-n64). Now convert to C code to handle different types of syscalls.

- For some special syscalls (e.g. fork, clone, clone3 and sysmips), save_static_function() wrapper is used to save static registers. Now SAVE_STATIC is used in handle_sys before calling do_syscall(), so the save_static_function() wrapper can be removed.

Quoted 5 lines

- For sigreturn/rt_sigreturn and sysmips, inline assembly is used to jump to syscall_exit directly for skipping setting the error flag and restoring all registers. Now use regs->regs[27] to mark whether to handle the error flag and always restore all registers in handle_sys, so these functions can return normally as other architecture.

Quoted 4 lines

Hmm, that would give us overhead of register context on these syscalls.

I guess it's worthy?

Hi, Jiaxun,

Saving and restoring registers against different system calls can be difficult due to the use of generic entry.
To avoid a lot of duplicate code, I think the overhead is worth it.

Quoted 4 lines
Quoted 3 lines
Quoted 8 lines

For the code,

After spending 3hrs diving into syscall handling hell, I must say you've done a good job. I'll start a LTP run to see if we miss any corner cases. And left IRQ part for another trial.

Thank you for your review. I've already run tests in Unixbench. It's more reassuring to run tests in LTP, so I'll do that too.

Thanks,
Feiyang

Quoted 1,821 lines

Thanks.

Jiaxun

Quoted 1,817 lines
---
  arch/mips/Kconfig                         |   1 +
  arch/mips/include/asm/entry-common.h      |  13 ++
  arch/mips/include/asm/ptrace.h            |   8 +-
  arch/mips/include/asm/sim.h               |  70 -------
  arch/mips/include/asm/syscall.h           |   5 +
  arch/mips/include/asm/thread_info.h       |  17 +-
  arch/mips/include/uapi/asm/ptrace.h       |   7 +-
  arch/mips/kernel/Makefile                 |  14 +-
  arch/mips/kernel/entry.S                  |  75 ++------
  arch/mips/kernel/linux32.c                |   1 -
  arch/mips/kernel/ptrace.c                 |  78 --------
  arch/mips/kernel/scall.S                  | 135 +++++++++++++
  arch/mips/kernel/scall32-o32.S            | 223 ----------------------
  arch/mips/kernel/scall64-n32.S            | 107 -----------
  arch/mips/kernel/scall64-n64.S            | 116 -----------
  arch/mips/kernel/scall64-o32.S            | 221 ---------------------
  arch/mips/kernel/signal.c                 |  35 ++--
  arch/mips/kernel/signal_n32.c             |  15 +-
  arch/mips/kernel/signal_o32.c             |  29 +--
  arch/mips/kernel/syscall.c                | 147 +++++++++++---
  arch/mips/kernel/syscalls/syscall_n32.tbl |   8 +-
  arch/mips/kernel/syscalls/syscall_n64.tbl |   8 +-
  arch/mips/kernel/syscalls/syscall_o32.tbl |   8 +-
  23 files changed, 346 insertions(+), 995 deletions(-)

create mode 100644 arch/mips/include/asm/entry-common.h delete mode 100644 arch/mips/include/asm/sim.h create mode 100644 arch/mips/kernel/scall.S delete mode 100644 arch/mips/kernel/scall32-o32.S delete mode 100644 arch/mips/kernel/scall64-n32.S delete mode 100644 arch/mips/kernel/scall64-n64.S delete mode 100644 arch/mips/kernel/scall64-o32.S

arch/mips/Kconfig +1 -0
index 0cf31a6cbee1..61aa125aa2da 100644
@@ -32,6 +32,7 @@ config MIPS
      select GENERIC_ATOMIC64 if !64BIT
      select GENERIC_CMOS_UPDATE
      select GENERIC_CPU_AUTOPROBE
+     select GENERIC_ENTRY
      select GENERIC_GETTIMEOFDAY
      select GENERIC_IOMAP
      select GENERIC_IRQ_PROBE
arch/mips/include/asm/entry-common.h new file +13 -0
new file mode 100644
index 000000000000..0fe2a098ded9
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef ARCH_LOONGARCH_ENTRY_COMMON_H
+#define ARCH_LOONGARCH_ENTRY_COMMON_H
+
+#include <linux/sched.h>
+#include <linux/processor.h>
+
+static inline bool on_thread_stack(void)
+{
+     return !(((unsigned long)(current->stack) ^ current_stack_pointer) & ~(THREAD_SIZE - 1));
+}
+
+#endif
arch/mips/include/asm/ptrace.h +5 -3
index daf3cf244ea9..1b8f9d2ddc44 100644
@@ -51,6 +51,11 @@ struct pt_regs {
      unsigned long __last[0];
  } __aligned(8);
 
+static inline int regs_irqs_disabled(struct pt_regs *regs)
+{
+     return arch_irqs_disabled_flags(regs->cp0_status);
+}
+
  static inline unsigned long kernel_stack_pointer(struct pt_regs *regs)
  {
      return regs->regs[29];
@@ -156,9 +161,6 @@ static inline long regs_return_value(struct pt_regs *regs)
  #define instruction_pointer(regs) ((regs)->cp0_epc)
  #define profile_pc(regs) instruction_pointer(regs)
 
-extern asmlinkage long syscall_trace_enter(struct pt_regs *regs, long syscall);
-extern asmlinkage void syscall_trace_leave(struct pt_regs *regs);
-
  extern void die(const char *, struct pt_regs *) __noreturn;
 
  static inline void die_if_kernel(const char *str, struct pt_regs *regs)
arch/mips/include/asm/sim.h deleted +0 -70
deleted file mode 100644
index 59f31a95facd..000000000000
@@ -1,70 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1999, 2000, 2003 Ralf Baechle
- * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
- */
-#ifndef _ASM_SIM_H
-#define _ASM_SIM_H
-
-
-#include <asm/asm-offsets.h>
-
-#define __str2(x) #x
-#define __str(x) __str2(x)
-
-#ifdef CONFIG_32BIT
-
-#define save_static_function(symbol)                                 \
-__asm__(                                                             \
-     ".text\n\t"                                                     \
-     ".globl\t__" #symbol "\n\t"                                     \
-     ".align\t2\n\t"                                                 \
-     ".type\t__" #symbol ", @function\n\t"                           \
-     ".ent\t__" #symbol ", 0\n__"                                    \
-     #symbol":\n\t"                                                  \
-     ".frame\t$29, 0, $31\n\t"                                       \
-     "sw\t$16,"__str(PT_R16)"($29)\t\t\t# save_static_function\n\t"  \
-     "sw\t$17,"__str(PT_R17)"($29)\n\t"                              \
-     "sw\t$18,"__str(PT_R18)"($29)\n\t"                              \
-     "sw\t$19,"__str(PT_R19)"($29)\n\t"                              \
-     "sw\t$20,"__str(PT_R20)"($29)\n\t"                              \
-     "sw\t$21,"__str(PT_R21)"($29)\n\t"                              \
-     "sw\t$22,"__str(PT_R22)"($29)\n\t"                              \
-     "sw\t$23,"__str(PT_R23)"($29)\n\t"                              \
-     "sw\t$30,"__str(PT_R30)"($29)\n\t"                              \
-     "j\t" #symbol "\n\t"                                            \
-     ".end\t__" #symbol "\n\t"                                       \
-     ".size\t__" #symbol",. - __" #symbol)
-
-#endif /* CONFIG_32BIT */
-
-#ifdef CONFIG_64BIT
-
-#define save_static_function(symbol)                                 \
-__asm__(                                                             \
-     ".text\n\t"                                                     \
-     ".globl\t__" #symbol "\n\t"                                     \
-     ".align\t2\n\t"                                                 \
-     ".type\t__" #symbol ", @function\n\t"                           \
-     ".ent\t__" #symbol ", 0\n__"                                    \
-     #symbol":\n\t"                                                  \
-     ".frame\t$29, 0, $31\n\t"                                       \
-     "sd\t$16,"__str(PT_R16)"($29)\t\t\t# save_static_function\n\t"  \
-     "sd\t$17,"__str(PT_R17)"($29)\n\t"                              \
-     "sd\t$18,"__str(PT_R18)"($29)\n\t"                              \
-     "sd\t$19,"__str(PT_R19)"($29)\n\t"                              \
-     "sd\t$20,"__str(PT_R20)"($29)\n\t"                              \
-     "sd\t$21,"__str(PT_R21)"($29)\n\t"                              \
-     "sd\t$22,"__str(PT_R22)"($29)\n\t"                              \
-     "sd\t$23,"__str(PT_R23)"($29)\n\t"                              \
-     "sd\t$30,"__str(PT_R30)"($29)\n\t"                              \
-     "j\t" #symbol "\n\t"                                            \
-     ".end\t__" #symbol "\n\t"                                       \
-     ".size\t__" #symbol",. - __" #symbol)
-
-#endif /* CONFIG_64BIT */
-
-#endif /* _ASM_SIM_H */
arch/mips/include/asm/syscall.h +5 -0
index 25fa651c937d..02ca0d659428 100644
@@ -157,4 +157,9 @@ static inline int syscall_get_arch(struct task_struct *task)
      return arch;
  }
 
+static inline bool arch_syscall_is_vdso_sigreturn(struct pt_regs *regs)
+{
+     return false;
+}
+
  #endif      /* __ASM_MIPS_SYSCALL_H */
arch/mips/include/asm/thread_info.h +4 -13
index 0b17aaa9e012..5a5237413065 100644
@@ -29,7 +29,8 @@ struct thread_info {
      __u32                   cpu;            /* current CPU */
      int                     preempt_count;  /* 0 => preemptable, <0 => BUG */
      struct pt_regs          *regs;
-     long                    syscall;        /* syscall number */
+     unsigned long           syscall;        /* syscall number */
+     unsigned long           syscall_work;   /* SYSCALL_WORK_ flags */
  };
 
  /*
@@ -69,6 +70,8 @@ static inline struct thread_info *current_thread_info(void)
      return __current_thread_info;
  }
 
+register unsigned long current_stack_pointer __asm__("$29");
+
  #endif /* !__ASSEMBLY__ */
 
  /* thread information allocation */
@@ -149,22 +152,10 @@ static inline struct thread_info *current_thread_info(void)
  #define _TIF_MSA_CTX_LIVE   (1<<TIF_MSA_CTX_LIVE)
  #define _TIF_SYSCALL_TRACEPOINT     (1<<TIF_SYSCALL_TRACEPOINT)
 
-#define _TIF_WORK_SYSCALL_ENTRY      (_TIF_NOHZ | _TIF_SYSCALL_TRACE |       \
-                              _TIF_SYSCALL_AUDIT | \
-                              _TIF_SYSCALL_TRACEPOINT | _TIF_SECCOMP)
-
-/* work to do in syscall_trace_leave() */
-#define _TIF_WORK_SYSCALL_EXIT       (_TIF_NOHZ | _TIF_SYSCALL_TRACE |       \
-                              _TIF_SYSCALL_AUDIT | _TIF_SYSCALL_TRACEPOINT)
-
  /* work to do on interrupt/exception return */
  #define _TIF_WORK_MASK              \
      (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_NOTIFY_RESUME |     \
       _TIF_UPROBE | _TIF_NOTIFY_SIGNAL)
-/* work to do on any return to u-space */
-#define _TIF_ALLWORK_MASK    (_TIF_NOHZ | _TIF_WORK_MASK |           \
-                              _TIF_WORK_SYSCALL_EXIT |               \
-                              _TIF_SYSCALL_TRACEPOINT)
 
  /*
   * We stash processor id into a COP0 register to retrieve it fast
arch/mips/include/uapi/asm/ptrace.h +4 -3
index f3c025445e45..27e2c85398bc 100644
@@ -102,8 +102,9 @@ struct pt_watch_regs {
      };
  };
 
-#define PTRACE_GET_WATCH_REGS        0xd0
-#define PTRACE_SET_WATCH_REGS        0xd1
-
+#define PTRACE_SYSEMU                        0x1f
+#define PTRACE_SYSEMU_SINGLESTEP     0x20
+#define PTRACE_GET_WATCH_REGS                0xd0
+#define PTRACE_SET_WATCH_REGS                0xd1
 
  #endif /* _UAPI_ASM_PTRACE_H */
arch/mips/kernel/Makefile +6 -8
index 814b3da30501..44875660f6ae 100644
@@ -5,10 +5,10 @@
 
  extra-y             := head.o vmlinux.lds
 
-obj-y                += branch.o cmpxchg.o elf.o entry.o genex.o idle.o irq.o \
-                process.o prom.o ptrace.o reset.o setup.o signal.o \
-                syscall.o time.o topology.o traps.o unaligned.o watch.o \
-                vdso.o cacheinfo.o
+obj-y                += branch.o cacheinfo.o cmpxchg.o elf.o entry.o genex.o \
+                idle.o irq.o process.o prom.o ptrace.o reset.o scall.o \
+                setup.o signal.o syscall.o time.o topology.o traps.o \
+                unaligned.o watch.o vdso.o
 
  ifdef CONFIG_CPU_R3K_TLB
  obj-y               += cpu-r3k-probe.o
@@ -76,11 +76,9 @@ obj-$(CONFIG_IRQ_TXX9)             += irq_txx9.o
  obj-$(CONFIG_IRQ_GT641XX)   += irq-gt641xx.o
 
  obj-$(CONFIG_KPROBES)               += kprobes.o
-obj-$(CONFIG_32BIT)          += scall32-o32.o
-obj-$(CONFIG_64BIT)          += scall64-n64.o
  obj-$(CONFIG_MIPS32_COMPAT) += linux32.o ptrace32.o signal32.o
-obj-$(CONFIG_MIPS32_N32)     += scall64-n32.o signal_n32.o
-obj-$(CONFIG_MIPS32_O32)     += scall64-o32.o signal_o32.o
+obj-$(CONFIG_MIPS32_N32)     += signal_n32.o
+obj-$(CONFIG_MIPS32_O32)     += signal_o32.o
 
  obj-$(CONFIG_KGDB)          += kgdb.o
  obj-$(CONFIG_PROC_FS)               += proc.o
arch/mips/kernel/entry.S +16 -59
index 4b896f5023ff..1a2aec9dab1b 100644
@@ -72,49 +72,32 @@ FEXPORT(ret_from_kernel_thread)
      jal     schedule_tail           # a0 = struct task_struct *prev
      move    a0, s1
      jal     s0
-     j       syscall_exit
+     move    a0, sp
+     jal     syscall_exit_to_user_mode
+
+     .set    noat
+     RESTORE_STATIC
+     RESTORE_SOME
+     RESTORE_SP_AND_RET
+     .set    at
 
  FEXPORT(ret_from_fork)
      jal     schedule_tail           # a0 = struct task_struct *prev
-
-FEXPORT(syscall_exit)
-#ifdef CONFIG_DEBUG_RSEQ
      move    a0, sp
-     jal     rseq_syscall
-#endif
-     local_irq_disable               # make sure need_resched and
-                                     # signals dont change between
-                                     # sampling and return
-     LONG_L  a2, TI_FLAGS($28)       # current->work
-     li      t0, _TIF_ALLWORK_MASK
-     and     t0, a2, t0
-     bnez    t0, syscall_exit_work
+     jal     syscall_exit_to_user_mode
 
-restore_all:                         # restore full frame
      .set    noat
-     RESTORE_TEMP
-     RESTORE_AT
      RESTORE_STATIC
-restore_partial:             # restore partial frame
-#ifdef CONFIG_TRACE_IRQFLAGS
-     SAVE_STATIC
-     SAVE_AT
-     SAVE_TEMP
-     LONG_L  v0, PT_STATUS(sp)
-#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
-     and     v0, ST0_IEP
-#else
-     and     v0, ST0_IE
-#endif
-     beqz    v0, 1f
-     jal     trace_hardirqs_on
-     b       2f
-1:   jal     trace_hardirqs_off
-2:
+     RESTORE_SOME
+     RESTORE_SP_AND_RET
+     .set    at
+
+restore_all:                         # restore full frame
+     .set    noat
      RESTORE_TEMP
      RESTORE_AT
      RESTORE_STATIC
-#endif
+restore_partial:                     # restore partial frame
      RESTORE_SOME
      RESTORE_SP_AND_RET
      .set    at
@@ -143,32 +126,6 @@ work_notifysig:                          # deal with pending signals and
      jal     do_notify_resume        # a2 already loaded
      j       resume_userspace_check
 
-FEXPORT(syscall_exit_partial)
-#ifdef CONFIG_DEBUG_RSEQ
-     move    a0, sp
-     jal     rseq_syscall
-#endif
-     local_irq_disable               # make sure need_resched doesn't
-                                     # change between and return
-     LONG_L  a2, TI_FLAGS($28)       # current->work
-     li      t0, _TIF_ALLWORK_MASK
-     and     t0, a2
-     beqz    t0, restore_partial
-     SAVE_STATIC
-syscall_exit_work:
-     LONG_L  t0, PT_STATUS(sp)               # returning to kernel mode?
-     andi    t0, t0, KU_USER
-     beqz    t0, resume_kernel
-     li      t0, _TIF_WORK_SYSCALL_EXIT
-     and     t0, a2                  # a2 is preloaded with TI_FLAGS
-     beqz    t0, work_pending        # trace bit set?
-     local_irq_enable                # could let syscall_trace_leave()
-                                     # call schedule() instead
-     TRACE_IRQS_ON
-     move    a0, sp
-     jal     syscall_trace_leave
-     b       resume_userspace
-
  #if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR5) || \
      defined(CONFIG_CPU_MIPSR6) || defined(CONFIG_MIPS_MT)
 
arch/mips/kernel/linux32.c +0 -1
index 6b61be486303..2b4b1fc1ff1b 100644
@@ -38,7 +38,6 @@
  #include <net/scm.h>
 
  #include <asm/compat-signal.h>
-#include <asm/sim.h>
  #include <linux/uaccess.h>
  #include <asm/mmu_context.h>
  #include <asm/mman.h>
arch/mips/kernel/ptrace.c +0 -78
index db7c5be1d4a3..04c08e41cfd3 100644
@@ -46,9 +46,6 @@
  #include <asm/bootinfo.h>
  #include <asm/reg.h>
 
-#define CREATE_TRACE_POINTS
-#include <trace/events/syscalls.h>
-
  /*
   * Called by kernel/ptrace.c when detaching..
   *
@@ -1305,78 +1302,3 @@ long arch_ptrace(struct task_struct *child, long request,
   out:
      return ret;
  }
-
-/*
- * Notification of system call entry/exit
- * - triggered by current->work.syscall_trace
- */
-asmlinkage long syscall_trace_enter(struct pt_regs *regs, long syscall)
-{
-     user_exit();
-
-     current_thread_info()->syscall = syscall;
-
-     if (test_thread_flag(TIF_SYSCALL_TRACE)) {
-             if (tracehook_report_syscall_entry(regs))
-                     return -1;
-             syscall = current_thread_info()->syscall;
-     }
-
-#ifdef CONFIG_SECCOMP
-     if (unlikely(test_thread_flag(TIF_SECCOMP))) {
-             int ret, i;
-             struct seccomp_data sd;
-             unsigned long args[6];
-
-             sd.nr = syscall;
-             sd.arch = syscall_get_arch(current);
-             syscall_get_arguments(current, regs, args);
-             for (i = 0; i < 6; i++)
-                     sd.args[i] = args[i];
-             sd.instruction_pointer = KSTK_EIP(current);
-
-             ret = __secure_computing(&sd);
-             if (ret == -1)
-                     return ret;
-             syscall = current_thread_info()->syscall;
-     }
-#endif
-
-     if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
-             trace_sys_enter(regs, regs->regs[2]);
-
-     audit_syscall_entry(syscall, regs->regs[4], regs->regs[5],
-                         regs->regs[6], regs->regs[7]);
-
-     /*
-      * Negative syscall numbers are mistaken for rejected syscalls, but
-      * won't have had the return value set appropriately, so we do so now.
-      */
-     if (syscall < 0)
-             syscall_set_return_value(current, regs, -ENOSYS, 0);
-     return syscall;
-}
-
-/*
- * Notification of system call entry/exit
- * - triggered by current->work.syscall_trace
- */
-asmlinkage void syscall_trace_leave(struct pt_regs *regs)
-{
-        /*
-      * We may come here right after calling schedule_user()
-      * or do_notify_resume(), in which case we can be in RCU
-      * user mode.
-      */
-     user_exit();
-
-     audit_syscall_exit(regs);
-
-     if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
-             trace_sys_exit(regs, regs_return_value(regs));
-
-     if (test_thread_flag(TIF_SYSCALL_TRACE))
-             tracehook_report_syscall_exit(regs, 0);
-
-     user_enter();
-}
arch/mips/kernel/scall.S new file +135 -0
new file mode 100644
index 000000000000..7b35969151de
@@ -0,0 +1,135 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 1995, 96, 97, 98, 99, 2000, 01, 02 by Ralf Baechle
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
+ * Copyright (C) 2001 MIPS Technologies, Inc.
+ * Copyright (C) 2004 Thiemo Seufer
+ * Copyright (C) 2014 Imagination Technologies Ltd.
+ */
+#include <linux/errno.h>
+#include <asm/asm.h>
+#include <asm/asmmacro.h>
+#include <asm/irqflags.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+#include <asm/asm-offsets.h>
+#include <asm/sysmips.h>
+#include <asm/thread_info.h>
+#include <asm/unistd.h>
+#include <asm/war.h>
+
+     .align  5
+NESTED(handle_sys, PT_SIZE, sp)
+     .set    noat
+     SAVE_SOME
+     SAVE_STATIC
+     CLI
+     .set    at
+
+     move    a0, sp
+     jal     do_syscall
+
+     .set    noat
+     RESTORE_TEMP
+     RESTORE_AT
+     RESTORE_STATIC
+     RESTORE_SOME
+     RESTORE_SP_AND_RET
+     .set    at
+     END(handle_sys)
+
+#ifdef CONFIG_32BIT
+LEAF(sys_syscall)
+     subu    t0, a0, __NR_O32_Linux          # check syscall number
+     sltiu   v0, t0, __NR_O32_Linux_syscalls
+     beqz    t0, einval                      # do not recurse
+     sll     t1, t0, 2
+     beqz    v0, einval
+     lw      t2, sys_call_table(t1)          # syscall routine
+
+     move    a0, a1                          # shift argument registers
+     move    a1, a2
+     move    a2, a3
+     lw      a3, 16(sp)
+     lw      t4, 20(sp)
+     lw      t5, 24(sp)
+     lw      t6, 28(sp)
+     sw      t4, 16(sp)
+     sw      t5, 20(sp)
+     sw      t6, 24(sp)
+     jr      t2
+     /* Unreached */
+
+einval: li   v0, -ENOSYS
+     jr      ra
+     END(sys_syscall)
+
+#ifdef CONFIG_MIPS_MT_FPAFF
+     /*
+      * For FPU affinity scheduling on MIPS MT processors, we need to
+      * intercept sys_sched_xxxaffinity() calls until we get a proper hook
+      * in kernel/sched/core.c.  Considered only temporary we only support
+      * these hooks for the 32-bit kernel - there is no MIPS64 MT processor
+      * atm.
+      */
+#define sys_sched_setaffinity        mipsmt_sys_sched_setaffinity
+#define sys_sched_getaffinity        mipsmt_sys_sched_getaffinity
+#endif /* CONFIG_MIPS_MT_FPAFF */
+
+#define __SYSCALL_WITH_COMPAT(nr, native, compat)    __SYSCALL(nr, native)
+#define __SYSCALL(nr, entry)         PTR entry
+     .align  2
+     .type   sys_call_table, @object
+EXPORT(sys_call_table)
+#include <asm/syscall_table_o32.h>
+#endif /* CONFIG_32BIT */
+
+#ifdef CONFIG_64BIT
+#ifdef CONFIG_MIPS32_O32
+LEAF(sys32_syscall)
+     subu    t0, a0, __NR_O32_Linux          # check syscall number
+     sltiu   v0, t0, __NR_O32_Linux_syscalls
+     beqz    t0, einval                      # do not recurse
+     dsll    t1, t0, 3
+     beqz    v0, einval
+     ld      t2, sys32_call_table(t1)        # syscall routine
+
+     move    a0, a1                          # shift argument registers
+     move    a1, a2
+     move    a2, a3
+     move    a3, a4
+     move    a4, a5
+     move    a5, a6
+     move    a6, a7
+     jr      t2
+     /* Unreached */
+
+einval: li   v0, -ENOSYS
+     jr      ra
+     END(sys32_syscall)
+
+#define __SYSCALL_WITH_COMPAT(nr, native, compat)    __SYSCALL(nr, compat)
+#define __SYSCALL(nr, entry) PTR entry
+     .align  3
+     .type   sys32_call_table,@object
+EXPORT(sys32_call_table)
+#include <asm/syscall_table_o32.h>
+#endif /* CONFIG_MIPS32_O32 */
+
+#ifdef CONFIG_MIPS32_N32
+#undef __SYSCALL
+#define __SYSCALL(nr, entry) PTR entry
+     .align  3
+     .type   sysn32_call_table, @object
+EXPORT(sysn32_call_table)
+#include <asm/syscall_table_n32.h>
+#endif /* CONFIG_MIPS32_N32 */
+
+#undef __SYSCALL
+#define __SYSCALL(nr, entry) PTR entry
+     .align  3
+     .type   sys_call_table, @object
+EXPORT(sys_call_table)
+#include <asm/syscall_table_n64.h>
+#endif /* CONFIG_64BIT */
arch/mips/kernel/scall32-o32.S deleted +0 -223
deleted file mode 100644
index b1b2e106f711..000000000000
@@ -1,223 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1995-99, 2000- 02, 06 Ralf Baechle <[email protected]>
- * Copyright (C) 2001 MIPS Technologies, Inc.
- * Copyright (C) 2004 Thiemo Seufer
- * Copyright (C) 2014 Imagination Technologies Ltd.
- */
-#include <linux/errno.h>
-#include <asm/asm.h>
-#include <asm/asmmacro.h>
-#include <asm/irqflags.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-#include <asm/isadep.h>
-#include <asm/sysmips.h>
-#include <asm/thread_info.h>
-#include <asm/unistd.h>
-#include <asm/war.h>
-#include <asm/asm-offsets.h>
-
-     .align  5
-NESTED(handle_sys, PT_SIZE, sp)
-     .set    noat
-     SAVE_SOME
-     TRACE_IRQS_ON_RELOAD
-     STI
-     .set    at
-
-     lw      t1, PT_EPC(sp)          # skip syscall on return
-
-     addiu   t1, 4                   # skip to next instruction
-     sw      t1, PT_EPC(sp)
-
-     sw      a3, PT_R26(sp)          # save a3 for syscall restarting
-
-     /*
-      * More than four arguments.  Try to deal with it by copying the
-      * stack arguments from the user stack to the kernel stack.
-      * This Sucks (TM).
-      */
-     lw      t0, PT_R29(sp)          # get old user stack pointer
-
-     /*
-      * We intentionally keep the kernel stack a little below the top of
-      * userspace so we don't have to do a slower byte accurate check here.
-      */
-     addu    t4, t0, 32
-     bltz    t4, bad_stack           # -> sp is bad
-
-     /*
-      * Ok, copy the args from the luser stack to the kernel stack.
-      */
-
-     .set    push
-     .set    noreorder
-     .set    nomacro
-
-load_a4: user_lw(t5, 16(t0))         # argument #5 from usp
-load_a5: user_lw(t6, 20(t0))         # argument #6 from usp
-load_a6: user_lw(t7, 24(t0))         # argument #7 from usp
-load_a7: user_lw(t8, 28(t0))         # argument #8 from usp
-loads_done:
-
-     sw      t5, 16(sp)              # argument #5 to ksp
-     sw      t6, 20(sp)              # argument #6 to ksp
-     sw      t7, 24(sp)              # argument #7 to ksp
-     sw      t8, 28(sp)              # argument #8 to ksp
-     .set    pop
-
-     .section __ex_table,"a"
-     PTR     load_a4, bad_stack_a4
-     PTR     load_a5, bad_stack_a5
-     PTR     load_a6, bad_stack_a6
-     PTR     load_a7, bad_stack_a7
-     .previous
-
-     lw      t0, TI_FLAGS($28)       # syscall tracing enabled?
-     li      t1, _TIF_WORK_SYSCALL_ENTRY
-     and     t0, t1
-     bnez    t0, syscall_trace_entry # -> yes
-syscall_common:
-     subu    v0, v0, __NR_O32_Linux  # check syscall number
-     sltiu   t0, v0, __NR_O32_Linux_syscalls
-     beqz    t0, illegal_syscall
-
-     sll     t0, v0, 2
-     la      t1, sys_call_table
-     addu    t1, t0
-     lw      t2, (t1)                # syscall routine
-
-     beqz    t2, illegal_syscall
-
-     jalr    t2                      # Do The Real Thing (TM)
-
-     li      t0, -EMAXERRNO - 1      # error?
-     sltu    t0, t0, v0
-     sw      t0, PT_R7(sp)           # set error flag
-     beqz    t0, 1f
-
-     lw      t1, PT_R2(sp)           # syscall number
-     negu    v0                      # error
-     sw      t1, PT_R0(sp)           # save it for syscall restarting
-1:   sw      v0, PT_R2(sp)           # result
-
-o32_syscall_exit:
-     j       syscall_exit_partial
-
-/* ------------------------------------------------------------------------ */
-
-syscall_trace_entry:
-     SAVE_STATIC
-     move    a0, sp
-
-     /*
-      * syscall number is in v0 unless we called syscall(__NR_###)
-      * where the real syscall number is in a0
-      */
-     move    a1, v0
-     subu    t2, v0,  __NR_O32_Linux
-     bnez    t2, 1f /* __NR_syscall at offset 0 */
-     lw      a1, PT_R4(sp)
-
-1:   jal     syscall_trace_enter
-
-     bltz    v0, 1f                  # seccomp failed? Skip syscall
-
-     RESTORE_STATIC
-     lw      v0, PT_R2(sp)           # Restore syscall (maybe modified)
-     lw      a0, PT_R4(sp)           # Restore argument registers
-     lw      a1, PT_R5(sp)
-     lw      a2, PT_R6(sp)
-     lw      a3, PT_R7(sp)
-     j       syscall_common
-
-1:   j       syscall_exit
-
-/* ------------------------------------------------------------------------ */
-
-     /*
-      * Our open-coded access area sanity test for the stack pointer
-      * failed. We probably should handle this case a bit more drastic.
-      */
-bad_stack:
-     li      v0, EFAULT
-     sw      v0, PT_R2(sp)
-     li      t0, 1                           # set error flag
-     sw      t0, PT_R7(sp)
-     j       o32_syscall_exit
-
-bad_stack_a4:
-     li      t5, 0
-     b       load_a5
-
-bad_stack_a5:
-     li      t6, 0
-     b       load_a6
-
-bad_stack_a6:
-     li      t7, 0
-     b       load_a7
-
-bad_stack_a7:
-     li      t8, 0
-     b       loads_done
-
-     /*
-      * The system call does not exist in this kernel
-      */
-illegal_syscall:
-     li      v0, ENOSYS                      # error
-     sw      v0, PT_R2(sp)
-     li      t0, 1                           # set error flag
-     sw      t0, PT_R7(sp)
-     j       o32_syscall_exit
-     END(handle_sys)
-
-     LEAF(sys_syscall)
-     subu    t0, a0, __NR_O32_Linux  # check syscall number
-     sltiu   v0, t0, __NR_O32_Linux_syscalls
-     beqz    t0, einval              # do not recurse
-     sll     t1, t0, 2
-     beqz    v0, einval
-     lw      t2, sys_call_table(t1)          # syscall routine
-
-     move    a0, a1                          # shift argument registers
-     move    a1, a2
-     move    a2, a3
-     lw      a3, 16(sp)
-     lw      t4, 20(sp)
-     lw      t5, 24(sp)
-     lw      t6, 28(sp)
-     sw      t4, 16(sp)
-     sw      t5, 20(sp)
-     sw      t6, 24(sp)
-     jr      t2
-     /* Unreached */
-
-einval: li   v0, -ENOSYS
-     jr      ra
-     END(sys_syscall)
-
-#ifdef CONFIG_MIPS_MT_FPAFF
-     /*
-      * For FPU affinity scheduling on MIPS MT processors, we need to
-      * intercept sys_sched_xxxaffinity() calls until we get a proper hook
-      * in kernel/sched/core.c.  Considered only temporary we only support
-      * these hooks for the 32-bit kernel - there is no MIPS64 MT processor
-      * atm.
-      */
-#define sys_sched_setaffinity        mipsmt_sys_sched_setaffinity
-#define sys_sched_getaffinity        mipsmt_sys_sched_getaffinity
-#endif /* CONFIG_MIPS_MT_FPAFF */
-
-#define __SYSCALL_WITH_COMPAT(nr, native, compat)    __SYSCALL(nr, native)
-#define __SYSCALL(nr, entry)         PTR entry
-     .align  2
-     .type   sys_call_table, @object
-EXPORT(sys_call_table)
-#include <asm/syscall_table_o32.h>
arch/mips/kernel/scall64-n32.S deleted +0 -107
deleted file mode 100644
index f650c55a17dc..000000000000
@@ -1,107 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1995, 96, 97, 98, 99, 2000, 01 by Ralf Baechle
- * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
- * Copyright (C) 2001 MIPS Technologies, Inc.
- */
-#include <linux/errno.h>
-#include <asm/asm.h>
-#include <asm/asmmacro.h>
-#include <asm/irqflags.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-#include <asm/thread_info.h>
-#include <asm/unistd.h>
-
-#ifndef CONFIG_MIPS32_O32
-/* No O32, so define handle_sys here */
-#define handle_sysn32 handle_sys
-#endif
-
-     .align  5
-NESTED(handle_sysn32, PT_SIZE, sp)
-#ifndef CONFIG_MIPS32_O32
-     .set    noat
-     SAVE_SOME
-     TRACE_IRQS_ON_RELOAD
-     STI
-     .set    at
-#endif
-
-     dsubu   t0, v0, __NR_N32_Linux  # check syscall number
-     sltiu   t0, t0, __NR_N32_Linux_syscalls
-
-#ifndef CONFIG_MIPS32_O32
-     ld      t1, PT_EPC(sp)          # skip syscall on return
-     daddiu  t1, 4                   # skip to next instruction
-     sd      t1, PT_EPC(sp)
-#endif
-     beqz    t0, not_n32_scall
-
-     sd      a3, PT_R26(sp)          # save a3 for syscall restarting
-
-     li      t1, _TIF_WORK_SYSCALL_ENTRY
-     LONG_L  t0, TI_FLAGS($28)       # syscall tracing enabled?
-     and     t0, t1, t0
-     bnez    t0, n32_syscall_trace_entry
-
-syscall_common:
-     dsll    t0, v0, 3               # offset into table
-     ld      t2, (sysn32_call_table - (__NR_N32_Linux * 8))(t0)
-
-     jalr    t2                      # Do The Real Thing (TM)
-
-     li      t0, -EMAXERRNO - 1      # error?
-     sltu    t0, t0, v0
-     sd      t0, PT_R7(sp)           # set error flag
-     beqz    t0, 1f
-
-     ld      t1, PT_R2(sp)           # syscall number
-     dnegu   v0                      # error
-     sd      t1, PT_R0(sp)           # save it for syscall restarting
-1:   sd      v0, PT_R2(sp)           # result
-
-     j       syscall_exit_partial
-
-/* ------------------------------------------------------------------------ */
-
-n32_syscall_trace_entry:
-     SAVE_STATIC
-     move    a0, sp
-     move    a1, v0
-     jal     syscall_trace_enter
-
-     bltz    v0, 1f                  # seccomp failed? Skip syscall
-
-     RESTORE_STATIC
-     ld      v0, PT_R2(sp)           # Restore syscall (maybe modified)
-     ld      a0, PT_R4(sp)           # Restore argument registers
-     ld      a1, PT_R5(sp)
-     ld      a2, PT_R6(sp)
-     ld      a3, PT_R7(sp)
-     ld      a4, PT_R8(sp)
-     ld      a5, PT_R9(sp)
-
-     dsubu   t2, v0, __NR_N32_Linux  # check (new) syscall number
-     sltiu   t0, t2, __NR_N32_Linux_syscalls
-     beqz    t0, not_n32_scall
-
-     j       syscall_common
-
-1:   j       syscall_exit
-
-not_n32_scall:
-     /* This is not an n32 compatibility syscall, pass it on to
-        the n64 syscall handlers.  */
-     j       handle_sys64
-
-     END(handle_sysn32)
-
-#define __SYSCALL(nr, entry) PTR entry
-     .type   sysn32_call_table, @object
-EXPORT(sysn32_call_table)
-#include <asm/syscall_table_n32.h>
arch/mips/kernel/scall64-n64.S deleted +0 -116
deleted file mode 100644
index 5d7bfc65e4d0..000000000000
@@ -1,116 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1995, 96, 97, 98, 99, 2000, 01, 02 by Ralf Baechle
- * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
- * Copyright (C) 2001 MIPS Technologies, Inc.
- */
-#include <linux/errno.h>
-#include <asm/asm.h>
-#include <asm/asmmacro.h>
-#include <asm/irqflags.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-#include <asm/asm-offsets.h>
-#include <asm/sysmips.h>
-#include <asm/thread_info.h>
-#include <asm/unistd.h>
-#include <asm/war.h>
-
-#ifndef CONFIG_MIPS32_COMPAT
-/* Neither O32 nor N32, so define handle_sys here */
-#define handle_sys64 handle_sys
-#endif
-
-     .align  5
-NESTED(handle_sys64, PT_SIZE, sp)
-#if !defined(CONFIG_MIPS32_O32) && !defined(CONFIG_MIPS32_N32)
-     /*
-      * When 32-bit compatibility is configured scall_o32.S
-      * already did this.
-      */
-     .set    noat
-     SAVE_SOME
-     TRACE_IRQS_ON_RELOAD
-     STI
-     .set    at
-#endif
-
-#if !defined(CONFIG_MIPS32_O32) && !defined(CONFIG_MIPS32_N32)
-     ld      t1, PT_EPC(sp)          # skip syscall on return
-     daddiu  t1, 4                   # skip to next instruction
-     sd      t1, PT_EPC(sp)
-#endif
-
-     sd      a3, PT_R26(sp)          # save a3 for syscall restarting
-
-     li      t1, _TIF_WORK_SYSCALL_ENTRY
-     LONG_L  t0, TI_FLAGS($28)       # syscall tracing enabled?
-     and     t0, t1, t0
-     bnez    t0, syscall_trace_entry
-
-syscall_common:
-     dsubu   t2, v0, __NR_64_Linux
-     sltiu   t0, t2, __NR_64_Linux_syscalls
-     beqz    t0, illegal_syscall
-
-     dsll    t0, t2, 3               # offset into table
-     dla     t2, sys_call_table
-     daddu   t0, t2, t0
-     ld      t2, (t0)                # syscall routine
-     beqz    t2, illegal_syscall
-
-     jalr    t2                      # Do The Real Thing (TM)
-
-     li      t0, -EMAXERRNO - 1      # error?
-     sltu    t0, t0, v0
-     sd      t0, PT_R7(sp)           # set error flag
-     beqz    t0, 1f
-
-     ld      t1, PT_R2(sp)           # syscall number
-     dnegu   v0                      # error
-     sd      t1, PT_R0(sp)           # save it for syscall restarting
-1:   sd      v0, PT_R2(sp)           # result
-
-n64_syscall_exit:
-     j       syscall_exit_partial
-
-/* ------------------------------------------------------------------------ */
-
-syscall_trace_entry:
-     SAVE_STATIC
-     move    a0, sp
-     move    a1, v0
-     jal     syscall_trace_enter
-
-     bltz    v0, 1f                  # seccomp failed? Skip syscall
-
-     RESTORE_STATIC
-     ld      v0, PT_R2(sp)           # Restore syscall (maybe modified)
-     ld      a0, PT_R4(sp)           # Restore argument registers
-     ld      a1, PT_R5(sp)
-     ld      a2, PT_R6(sp)
-     ld      a3, PT_R7(sp)
-     ld      a4, PT_R8(sp)
-     ld      a5, PT_R9(sp)
-     j       syscall_common
-
-1:   j       syscall_exit
-
-illegal_syscall:
-     /* This also isn't a 64-bit syscall, throw an error.  */
-     li      v0, ENOSYS                      # error
-     sd      v0, PT_R2(sp)
-     li      t0, 1                           # set error flag
-     sd      t0, PT_R7(sp)
-     j       n64_syscall_exit
-     END(handle_sys64)
-
-#define __SYSCALL(nr, entry) PTR entry
-     .align  3
-     .type   sys_call_table, @object
-EXPORT(sys_call_table)
-#include <asm/syscall_table_n64.h>
arch/mips/kernel/scall64-o32.S deleted +0 -221
deleted file mode 100644
index cedc8bd88804..000000000000
@@ -1,221 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1995 - 2000, 2001 by Ralf Baechle
- * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
- * Copyright (C) 2001 MIPS Technologies, Inc.
- * Copyright (C) 2004 Thiemo Seufer
- *
- * Hairy, the userspace application uses a different argument passing
- * convention than the kernel, so we have to translate things from o32
- * to ABI64 calling convention.       64-bit syscalls are also processed
- * here for now.
- */
-#include <linux/errno.h>
-#include <asm/asm.h>
-#include <asm/asmmacro.h>
-#include <asm/irqflags.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-#include <asm/thread_info.h>
-#include <asm/unistd.h>
-#include <asm/sysmips.h>
-
-     .align  5
-NESTED(handle_sys, PT_SIZE, sp)
-     .set    noat
-     SAVE_SOME
-     TRACE_IRQS_ON_RELOAD
-     STI
-     .set    at
-     ld      t1, PT_EPC(sp)          # skip syscall on return
-
-     dsubu   t0, v0, __NR_O32_Linux  # check syscall number
-     sltiu   t0, t0, __NR_O32_Linux_syscalls
-     daddiu  t1, 4                   # skip to next instruction
-     sd      t1, PT_EPC(sp)
-     beqz    t0, not_o32_scall
-#if 0
- SAVE_ALL
- move a1, v0
- ASM_PRINT("Scall %ld\n")
- RESTORE_ALL
-#endif
-
-     /* We don't want to stumble over broken sign extensions from
-        userland. O32 does never use the upper half. */
-     sll     a0, a0, 0
-     sll     a1, a1, 0
-     sll     a2, a2, 0
-     sll     a3, a3, 0
-
-     sd      a3, PT_R26(sp)          # save a3 for syscall restarting
-
-     /*
-      * More than four arguments.  Try to deal with it by copying the
-      * stack arguments from the user stack to the kernel stack.
-      * This Sucks (TM).
-      *
-      * We intentionally keep the kernel stack a little below the top of
-      * userspace so we don't have to do a slower byte accurate check here.
-      */
-     ld      t0, PT_R29(sp)          # get old user stack pointer
-     daddu   t1, t0, 32
-     bltz    t1, bad_stack
-
-load_a4: lw  a4, 16(t0)              # argument #5 from usp
-load_a5: lw  a5, 20(t0)              # argument #6 from usp
-load_a6: lw  a6, 24(t0)              # argument #7 from usp
-load_a7: lw  a7, 28(t0)              # argument #8 from usp
-loads_done:
-
-     .section __ex_table,"a"
-     PTR     load_a4, bad_stack_a4
-     PTR     load_a5, bad_stack_a5
-     PTR     load_a6, bad_stack_a6
-     PTR     load_a7, bad_stack_a7
-     .previous
-
-     li      t1, _TIF_WORK_SYSCALL_ENTRY
-     LONG_L  t0, TI_FLAGS($28)       # syscall tracing enabled?
-     and     t0, t1, t0
-     bnez    t0, trace_a_syscall
-
-syscall_common:
-     dsll    t0, v0, 3               # offset into table
-     ld      t2, (sys32_call_table - (__NR_O32_Linux * 8))(t0)
-
-     jalr    t2                      # Do The Real Thing (TM)
-
-     li      t0, -EMAXERRNO - 1      # error?
-     sltu    t0, t0, v0
-     sd      t0, PT_R7(sp)           # set error flag
-     beqz    t0, 1f
-
-     ld      t1, PT_R2(sp)           # syscall number
-     dnegu   v0                      # error
-     sd      t1, PT_R0(sp)           # save it for syscall restarting
-1:   sd      v0, PT_R2(sp)           # result
-
-o32_syscall_exit:
-     j       syscall_exit_partial
-
-/* ------------------------------------------------------------------------ */
-
-trace_a_syscall:
-     SAVE_STATIC
-     sd      a4, PT_R8(sp)           # Save argument registers
-     sd      a5, PT_R9(sp)
-     sd      a6, PT_R10(sp)
-     sd      a7, PT_R11(sp)          # For indirect syscalls
-
-     move    a0, sp
-     /*
-      * absolute syscall number is in v0 unless we called syscall(__NR_###)
-      * where the real syscall number is in a0
-      * note: NR_syscall is the first O32 syscall but the macro is
-      * only defined when compiling with -mabi=32 (CONFIG_32BIT)
-      * therefore __NR_O32_Linux is used (4000)
-      */
-     .set    push
-     .set    reorder
-     subu    t1, v0,  __NR_O32_Linux
-     move    a1, v0
-     bnez    t1, 1f /* __NR_syscall at offset 0 */
-     ld      a1, PT_R4(sp) /* Arg1 for __NR_syscall case */
-     .set    pop
-
-1:   jal     syscall_trace_enter
-
-     bltz    v0, 1f                  # seccomp failed? Skip syscall
-
-     RESTORE_STATIC
-     ld      v0, PT_R2(sp)           # Restore syscall (maybe modified)
-     ld      a0, PT_R4(sp)           # Restore argument registers
-     ld      a1, PT_R5(sp)
-     ld      a2, PT_R6(sp)
-     ld      a3, PT_R7(sp)
-     ld      a4, PT_R8(sp)
-     ld      a5, PT_R9(sp)
-     ld      a6, PT_R10(sp)
-     ld      a7, PT_R11(sp)          # For indirect syscalls
-
-     dsubu   t0, v0, __NR_O32_Linux  # check (new) syscall number
-     sltiu   t0, t0, __NR_O32_Linux_syscalls
-     beqz    t0, not_o32_scall
-
-     j       syscall_common
-
-1:   j       syscall_exit
-
-/* ------------------------------------------------------------------------ */
-
-     /*
-      * The stackpointer for a call with more than 4 arguments is bad.
-      */
-bad_stack:
-     li      v0, EFAULT
-     sd      v0, PT_R2(sp)
-     li      t0, 1                   # set error flag
-     sd      t0, PT_R7(sp)
-     j       o32_syscall_exit
-
-bad_stack_a4:
-     li      a4, 0
-     b       load_a5
-
-bad_stack_a5:
-     li      a5, 0
-     b       load_a6
-
-bad_stack_a6:
-     li      a6, 0
-     b       load_a7
-
-bad_stack_a7:
-     li      a7, 0
-     b       loads_done
-
-not_o32_scall:
-     /*
-      * This is not an o32 compatibility syscall, pass it on
-      * to the 64-bit syscall handlers.
-      */
-#ifdef CONFIG_MIPS32_N32
-     j       handle_sysn32
-#else
-     j       handle_sys64
-#endif
-     END(handle_sys)
-
-LEAF(sys32_syscall)
-     subu    t0, a0, __NR_O32_Linux  # check syscall number
-     sltiu   v0, t0, __NR_O32_Linux_syscalls
-     beqz    t0, einval              # do not recurse
-     dsll    t1, t0, 3
-     beqz    v0, einval
-     ld      t2, sys32_call_table(t1)                # syscall routine
-
-     move    a0, a1                  # shift argument registers
-     move    a1, a2
-     move    a2, a3
-     move    a3, a4
-     move    a4, a5
-     move    a5, a6
-     move    a6, a7
-     jr      t2
-     /* Unreached */
-
-einval: li   v0, -ENOSYS
-     jr      ra
-     END(sys32_syscall)
-
-#define __SYSCALL_WITH_COMPAT(nr, native, compat)    __SYSCALL(nr, compat)
-#define __SYSCALL(nr, entry) PTR entry
-     .align  3
-     .type   sys32_call_table,@object
-EXPORT(sys32_call_table)
-#include <asm/syscall_table_o32.h>
arch/mips/kernel/signal.c +11 -24
index f1e985109da0..1ec6a0cf1163 100644
@@ -32,7 +32,6 @@
  #include <linux/bitops.h>
  #include <asm/cacheflush.h>
  #include <asm/fpu.h>
-#include <asm/sim.h>
  #include <asm/ucontext.h>
  #include <asm/cpu-features.h>
  #include <asm/war.h>
@@ -627,7 +626,7 @@ SYSCALL_DEFINE3(sigaction, int, sig, const struct sigaction __user *, act,
  #endif
 
  #ifdef CONFIG_TRAD_SIGNALS
-asmlinkage void sys_sigreturn(void)
+asmlinkage long sys_sigreturn(void)
  {
      struct sigframe __user *frame;
      struct pt_regs *regs;
@@ -649,22 +648,16 @@ asmlinkage void sys_sigreturn(void)
      else if (sig)
              force_sig(sig);
 
-     /*
-      * Don't let your children do this ...
-      */
-     __asm__ __volatile__(
-             "move\t$29, %0\n\t"
-             "j\tsyscall_exit"
-             : /* no outputs */
-             : "r" (regs));
-     /* Unreached */
+     regs->regs[27] = 1;     /* return directly */
+     return regs->regs[2];
 
  badframe:
      force_sig(SIGSEGV);
+     return 0;
  }
  #endif /* CONFIG_TRAD_SIGNALS */
 
-asmlinkage void sys_rt_sigreturn(void)
+asmlinkage long sys_rt_sigreturn(void)
  {
      struct rt_sigframe __user *frame;
      struct pt_regs *regs;
@@ -689,18 +682,12 @@ asmlinkage void sys_rt_sigreturn(void)
      if (restore_altstack(&frame->rs_uc.uc_stack))
              goto badframe;
 
-     /*
-      * Don't let your children do this ...
-      */
-     __asm__ __volatile__(
-             "move\t$29, %0\n\t"
-             "j\tsyscall_exit"
-             : /* no outputs */
-             : "r" (regs));
-     /* Unreached */
+     regs->regs[27] = 1;     /* return directly */
+     return regs->regs[2];
 
  badframe:
      force_sig(SIGSEGV);
+     return 0;
  }
 
  #ifdef CONFIG_TRAD_SIGNALS
@@ -852,11 +839,11 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
      signal_setup_done(ret, ksig, 0);
  }
 
-static void do_signal(struct pt_regs *regs)
+void arch_do_signal_or_restart(struct pt_regs *regs, bool has_signal)
  {
      struct ksignal ksig;
 
-     if (get_signal(&ksig)) {
+     if (has_signal && get_signal(&ksig)) {
              /* Whee!  Actually deliver the signal.  */
              handle_signal(&ksig, regs);
              return;
@@ -904,7 +891,7 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, void *unused,
 
      /* deal with pending signal delivery */
      if (thread_info_flags & (_TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL))
-             do_signal(regs);
+             arch_do_signal_or_restart(regs, thread_info_flags & _TIF_SIGPENDING);
 
      if (thread_info_flags & _TIF_NOTIFY_RESUME) {
              tracehook_notify_resume(regs);
arch/mips/kernel/signal_n32.c +4 -11
index 7bd00fad61af..b52b995a8a9b 100644
@@ -19,7 +19,6 @@
  #include <asm/asm.h>
  #include <asm/cacheflush.h>
  #include <asm/compat-signal.h>
-#include <asm/sim.h>
  #include <linux/uaccess.h>
  #include <asm/ucontext.h>
  #include <asm/fpu.h>
@@ -51,7 +50,7 @@ struct rt_sigframe_n32 {
      struct ucontextn32 rs_uc;
  };
 
-asmlinkage void sysn32_rt_sigreturn(void)
+asmlinkage long sysn32_rt_sigreturn(void)
  {
      struct rt_sigframe_n32 __user *frame;
      struct pt_regs *regs;
@@ -76,18 +75,12 @@ asmlinkage void sysn32_rt_sigreturn(void)
      if (compat_restore_altstack(&frame->rs_uc.uc_stack))
              goto badframe;
 
-     /*
-      * Don't let your children do this ...
-      */
-     __asm__ __volatile__(
-             "move\t$29, %0\n\t"
-             "j\tsyscall_exit"
-             : /* no outputs */
-             : "r" (regs));
-     /* Unreached */
+     regs->regs[27] = 1;     /* return directly */
+     return regs->regs[2];
 
  badframe:
      force_sig(SIGSEGV);
+     return 0;
  }
 
  static int setup_rt_frame_n32(void *sig_return, struct ksignal *ksig,
arch/mips/kernel/signal_o32.c +8 -21
index 299a7a28ca33..9245806e06f1 100644
@@ -17,7 +17,6 @@
  #include <asm/abi.h>
  #include <asm/compat-signal.h>
  #include <asm/dsp.h>
-#include <asm/sim.h>
  #include <asm/unistd.h>
 
  #include "signal-common.h"
@@ -151,7 +150,7 @@ static int setup_frame_32(void *sig_return, struct ksignal *ksig,
      return 0;
  }
 
-asmlinkage void sys32_rt_sigreturn(void)
+asmlinkage long sys32_rt_sigreturn(void)
  {
      struct rt_sigframe32 __user *frame;
      struct pt_regs *regs;
@@ -176,18 +175,12 @@ asmlinkage void sys32_rt_sigreturn(void)
      if (compat_restore_altstack(&frame->rs_uc.uc_stack))
              goto badframe;
 
-     /*
-      * Don't let your children do this ...
-      */
-     __asm__ __volatile__(
-             "move\t$29, %0\n\t"
-             "j\tsyscall_exit"
-             : /* no outputs */
-             : "r" (regs));
-     /* Unreached */
+     regs->regs[27] = 1;     /* return directly */
+     return regs->regs[2];
 
  badframe:
      force_sig(SIGSEGV);
+     return 0;
  }
 
  static int setup_rt_frame_32(void *sig_return, struct ksignal *ksig,
@@ -253,7 +246,7 @@ struct mips_abi mips_abi_32 = {
  };
 
 
-asmlinkage void sys32_sigreturn(void)
+asmlinkage long sys32_sigreturn(void)
  {
      struct sigframe32 __user *frame;
      struct pt_regs *regs;
@@ -275,16 +268,10 @@ asmlinkage void sys32_sigreturn(void)
      else if (sig)
              force_sig(sig);
 
-     /*
-      * Don't let your children do this ...
-      */
-     __asm__ __volatile__(
-             "move\t$29, %0\n\t"
-             "j\tsyscall_exit"
-             : /* no outputs */
-             : "r" (regs));
-     /* Unreached */
+     regs->regs[27] = 1;     /* return directly */
+     return regs->regs[2];
 
  badframe:
      force_sig(SIGSEGV);
+     return 0;
  }
arch/mips/kernel/syscall.c +122 -25
index 2afa3eef486a..6dc78648b274 100644
@@ -8,6 +8,7 @@
   * Copyright (C) 2001 MIPS Technologies, Inc.
   */
  #include <linux/capability.h>
+#include <linux/entry-common.h>
  #include <linux/errno.h>
  #include <linux/linkage.h>
  #include <linux/fs.h>
@@ -35,9 +36,9 @@
  #include <asm/cacheflush.h>
  #include <asm/asm-offsets.h>
  #include <asm/signal.h>
-#include <asm/sim.h>
  #include <asm/shmparam.h>
  #include <asm/sync.h>
+#include <asm/syscall.h>
  #include <asm/sysmips.h>
  #include <asm/switch_to.h>
 
@@ -79,10 +80,6 @@ SYSCALL_DEFINE6(mips_mmap2, unsigned long, addr, unsigned long, len,
                             pgoff >> (PAGE_SHIFT - 12));
  }
 
-save_static_function(sys_fork);
-save_static_function(sys_clone);
-save_static_function(sys_clone3);
-
  SYSCALL_DEFINE1(set_thread_area, unsigned long, addr)
  {
      struct thread_info *ti = task_thread_info(current);
@@ -182,28 +179,11 @@ static inline int mips_atomic_set(unsigned long addr, unsigned long new)
              return err;
 
      regs = current_pt_regs();
-     regs->regs[2] = old;
-     regs->regs[7] = 0;      /* No error */
-
-     /*
-      * Don't let your children do this ...
-      */
-     __asm__ __volatile__(
-     "       move    $29, %0                                         \n"
-     "       j       syscall_exit                                    \n"
-     : /* no outputs */
-     : "r" (regs));
-
-     /* unreached.  Honestly.  */
-     unreachable();
+     regs->regs[7] = 0;      /* no error */
+     regs->regs[27] = 1;     /* return directly */
+     return old;
  }
 
-/*
- * mips_atomic_set() normally returns directly via syscall_exit potentially
- * clobbering static registers, so be sure to preserve them.
- */
-save_static_function(sys_sysmips);
-
  SYSCALL_DEFINE3(sysmips, long, cmd, long, arg1, long, arg2)
  {
      switch (cmd) {
@@ -249,3 +229,120 @@ asmlinkage void bad_stack(void)
  {
      do_exit(SIGSEGV);
  }
+
+#if defined(CONFIG_32BIT) || defined(CONFIG_MIPS32_O32)
+static inline int get_args(struct pt_regs *regs)
+{
+     int *usp = (int *)regs->regs[29];
+
+#ifdef CONFIG_MIPS32_O32
+     /*
+      * Hairy, the userspace application uses a different argument passing
+      * convention than the kernel, so we have to translate things from o32
+      * to ABI64 calling convention.
+      *
+      * We don't want to stumble over broken sign extensions from userland.
+      * O32 does never use the upper half.
+      */
+     regs->regs[4] = (int)regs->regs[4];
+     regs->regs[5] = (int)regs->regs[5];
+     regs->regs[6] = (int)regs->regs[6];
+     regs->regs[7] = (int)regs->regs[7];
+#endif
+
+     /*
+      * More than four arguments.  Try to deal with it by copying the
+      * stack arguments from the user stack to the kernel stack.
+      * This Sucks (TM).
+      *
+      * We intentionally keep the kernel stack a little below the top of
+      * userspace so we don't have to do a slower byte accurate check here.
+      */
+     if (!access_ok(usp, 32))
+             return -1;
+
+     get_user(regs->regs[8], usp + 4);
+     get_user(regs->regs[9], usp + 5);
+     get_user(regs->regs[10], usp + 6);
+     get_user(regs->regs[11], usp + 7);
+
+     return 0;
+}
+#endif
+
+typedef long (*sys_call_fn)(unsigned long, unsigned long,
+     unsigned long, unsigned long, unsigned long, unsigned long);
+
+void noinstr do_syscall(struct pt_regs *regs)
+{
+     unsigned long nr;
+     unsigned long ret;
+     sys_call_fn syscall_fn = NULL;
+
+     nr = regs->regs[2];
+     current_thread_info()->syscall = nr;
+     nr = syscall_enter_from_user_mode(regs, nr);
+
+     regs->cp0_epc += 4;             /* skip syscall on return */
+                                     /* skip to next instruction */
+     regs->regs[26] = regs->regs[7]; /* save a3 for syscall restarting */
+     regs->regs[27] = 0;             /* do not return directly */
+
+#ifdef CONFIG_32BIT
+     if (nr >= __NR_O32_Linux && nr < __NR_O32_Linux + __NR_O32_Linux_syscalls) {
+             if (get_args(regs) < 0) {
+                     ret = EFAULT;
+                     goto error;
+             }
+             syscall_fn = (sys_call_fn)sys_call_table[nr - __NR_O32_Linux];
+     }
+#endif
+
+#ifdef CONFIG_MIPS32_O32
+     if (nr >= __NR_O32_Linux && nr < __NR_O32_Linux + __NR_O32_Linux_syscalls) {
+             if (get_args(regs) < 0) {
+                     ret = EFAULT;
+                     goto error;
+             }
+             syscall_fn = (sys_call_fn)sys32_call_table[nr - __NR_O32_Linux];
+     }
+#endif
+
+#ifdef CONFIG_MIPS32_N32
+     if (nr >= __NR_N32_Linux && nr < __NR_N32_Linux + __NR_N32_Linux_syscalls)
+             syscall_fn = (sys_call_fn)sysn32_call_table[nr - __NR_N32_Linux];
+#endif
+
+#ifdef CONFIG_64BIT
+     if (nr >= __NR_64_Linux && nr < __NR_64_Linux + __NR_64_Linux_syscalls)
+             syscall_fn = (sys_call_fn)sys_call_table[nr - __NR_64_Linux];
+#endif
+
+     if (!syscall_fn) {
+             ret = ENOSYS;
+             goto error;
+     }
+
+     ret = syscall_fn(regs->regs[4], regs->regs[5], regs->regs[6],
+                      regs->regs[7], regs->regs[8], regs->regs[9]);
+
+     if (regs->regs[27])             /* return directly? */
+             goto out;
+
+     regs->regs[7] = 0;              /* clear error flag */
+     if (ret >= -EMAXERRNO - 1) {    /* error? */
+             regs->regs[0] = nr;     /* save syscall number */
+                                     /* for syscall restarting */
+             ret = -ret;
+             goto error;
+     }
+
+     goto out;
+
+error:
+     regs->regs[7] = 1;              /* set error flag */
+
+out:
+     regs->regs[2] = ret;
+     syscall_exit_to_user_mode(regs);
+}
arch/mips/kernel/syscalls/syscall_n32.tbl +4 -4
index 70e32de2bcaa..d9ae765e51f1 100644
@@ -62,8 +62,8 @@
  52  n32     socketpair                      sys_socketpair
  53  n32     setsockopt                      sys_setsockopt
  54  n32     getsockopt                      sys_getsockopt
-55   n32     clone                           __sys_clone
-56   n32     fork                            __sys_fork
+55   n32     clone                           sys_clone
+56   n32     fork                            sys_fork
  57  n32     execve                          compat_sys_execve
  58  n32     exit                            sys_exit
  59  n32     wait4                           compat_sys_wait4
@@ -207,7 +207,7 @@
  196 n32     sched_getaffinity               compat_sys_sched_getaffinity
  197 n32     cacheflush                      sys_cacheflush
  198 n32     cachectl                        sys_cachectl
-199  n32     sysmips                         __sys_sysmips
+199  n32     sysmips                         sys_sysmips
  200 n32     io_setup                        compat_sys_io_setup
  201 n32     io_destroy                      sys_io_destroy
  202 n32     io_getevents                    sys_io_getevents_time32
@@ -373,7 +373,7 @@
  432 n32     fsmount                         sys_fsmount
  433 n32     fspick                          sys_fspick
  434 n32     pidfd_open                      sys_pidfd_open
-435  n32     clone3                          __sys_clone3
+435  n32     clone3                          sys_clone3
  436 n32     close_range                     sys_close_range
  437 n32     openat2                         sys_openat2
  438 n32     pidfd_getfd                     sys_pidfd_getfd
arch/mips/kernel/syscalls/syscall_n64.tbl +4 -4
index 1ca7bc337932..edec3e82d67a 100644
@@ -62,8 +62,8 @@
  52  n64     socketpair                      sys_socketpair
  53  n64     setsockopt                      sys_setsockopt
  54  n64     getsockopt                      sys_getsockopt
-55   n64     clone                           __sys_clone
-56   n64     fork                            __sys_fork
+55   n64     clone                           sys_clone
+56   n64     fork                            sys_fork
  57  n64     execve                          sys_execve
  58  n64     exit                            sys_exit
  59  n64     wait4                           sys_wait4
@@ -207,7 +207,7 @@
  196 n64     sched_getaffinity               sys_sched_getaffinity
  197 n64     cacheflush                      sys_cacheflush
  198 n64     cachectl                        sys_cachectl
-199  n64     sysmips                         __sys_sysmips
+199  n64     sysmips                         sys_sysmips
  200 n64     io_setup                        sys_io_setup
  201 n64     io_destroy                      sys_io_destroy
  202 n64     io_getevents                    sys_io_getevents
@@ -349,7 +349,7 @@
  432 n64     fsmount                         sys_fsmount
  433 n64     fspick                          sys_fspick
  434 n64     pidfd_open                      sys_pidfd_open
-435  n64     clone3                          __sys_clone3
+435  n64     clone3                          sys_clone3
  436 n64     close_range                     sys_close_range
  437 n64     openat2                         sys_openat2
  438 n64     pidfd_getfd                     sys_pidfd_getfd
arch/mips/kernel/syscalls/syscall_o32.tbl +4 -4
index a61c35edaa74..89a1f267da6a 100644
@@ -9,7 +9,7 @@
  #
  0   o32     syscall                         sys_syscall                     sys32_syscall
  1   o32     exit                            sys_exit
-2    o32     fork                            __sys_fork
+2    o32     fork                            sys_fork
  3   o32     read                            sys_read
  4   o32     write                           sys_write
  5   o32     open                            sys_open                        compat_sys_open
@@ -131,7 +131,7 @@
  117 o32     ipc                             sys_ipc                         compat_sys_ipc
  118 o32     fsync                           sys_fsync
  119 o32     sigreturn                       sys_sigreturn                   sys32_sigreturn
-120  o32     clone                           __sys_clone
+120  o32     clone                           sys_clone
  121 o32     setdomainname                   sys_setdomainname
  122 o32     uname                           sys_newuname
  123 o32     modify_ldt                      sys_ni_syscall
@@ -160,7 +160,7 @@
  146 o32     writev                          sys_writev
  147 o32     cacheflush                      sys_cacheflush
  148 o32     cachectl                        sys_cachectl
-149  o32     sysmips                         __sys_sysmips
+149  o32     sysmips                         sys_sysmips
  150 o32     unused150                       sys_ni_syscall
  151 o32     getsid                          sys_getsid
  152 o32     fdatasync                       sys_fdatasync
@@ -422,7 +422,7 @@
  432 o32     fsmount                         sys_fsmount
  433 o32     fspick                          sys_fspick
  434 o32     pidfd_open                      sys_pidfd_open
-435  o32     clone3                          __sys_clone3
+435  o32     clone3                          sys_clone3
  436 o32     close_range                     sys_close_range
  437 o32     openat2                         sys_openat2
  438 o32     pidfd_getfd                     sys_pidfd_getfd
#5 lore raw

Re: [PATCH 1/2] mips: convert syscall to generic entry

In reply to 陈飞扬
Quoted 28 lines · 陈飞扬
Quoted 27 lines · Jiaxun Yang
Quoted 16 lines · FreeFlyingSheep

From: Feiyang Chen <[email protected]>

Convert mips syscall to use the generic entry infrastructure from kernel/entry/*.

There are a few special things on mips:

- There is one type of syscall on mips32 (scall32-o32) and three types of syscalls on mips64 (scall64-o32, scall64-n32 and scall64-n64). Now convert to C code to handle different types of syscalls.

- For some special syscalls (e.g. fork, clone, clone3 and sysmips), save_static_function() wrapper is used to save static registers. Now SAVE_STATIC is used in handle_sys before calling do_syscall(), so the save_static_function() wrapper can be removed.

Quoted 5 lines

- For sigreturn/rt_sigreturn and sysmips, inline assembly is used to jump to syscall_exit directly for skipping setting the error flag and restoring all registers. Now use regs->regs[27] to mark whether to handle the error flag and always restore all registers in handle_sys, so these functions can return normally as other architecture.

Hmm, that would give us overhead of register context on these syscalls.

Quoted 8 lines
Quoted 2 lines

I guess it's worthy?

Hi, Jiaxun,

Saving and restoring registers against different system calls can be difficult due to the use of generic entry.
To avoid a lot of duplicate code, I think the overhead is worth it.

could you please provide numbers for that ? This code still runs on low end MIPS CPUs for which overhead might mean a different ballpark than some highend Loongson CPUs.

Thomas.

Signature · 2 lines
Crap can work. Given enough thrust pigs will fly, but it's not necessarily a
good idea.                                                [ RFC1925, 2.3 ]
#6 lore raw

Re: [PATCH 1/2] mips: convert syscall to generic entry

Quoted 29 lines · Thomas Bogendoerfer
Quoted 28 lines · 陈飞扬
Quoted 27 lines · Jiaxun Yang
Quoted 16 lines · FreeFlyingSheep

From: Feiyang Chen <[email protected]>

Convert mips syscall to use the generic entry infrastructure from kernel/entry/*.

There are a few special things on mips:

- There is one type of syscall on mips32 (scall32-o32) and three types of syscalls on mips64 (scall64-o32, scall64-n32 and scall64-n64). Now convert to C code to handle different types of syscalls.

- For some special syscalls (e.g. fork, clone, clone3 and sysmips), save_static_function() wrapper is used to save static registers. Now SAVE_STATIC is used in handle_sys before calling do_syscall(), so the save_static_function() wrapper can be removed.

Quoted 5 lines

- For sigreturn/rt_sigreturn and sysmips, inline assembly is used to jump to syscall_exit directly for skipping setting the error flag and restoring all registers. Now use regs->regs[27] to mark whether to handle the error flag and always restore all registers in handle_sys, so these functions can return normally as other architecture.

Hmm, that would give us overhead of register context on these syscalls.

I guess it's worthy?

Quoted 8 lines
Quoted 5 lines

Hi, Jiaxun,

Saving and restoring registers against different system calls can be difficult due to the use of generic entry.
To avoid a lot of duplicate code, I think the overhead is worth it.

could you please provide numbers for that ? This code still runs on low end MIPS CPUs for which overhead might mean a different ballpark than some highend Loongson CPUs.

It shows ~3% regression for UnixBench on MT7621A (1004Kec).

+ Yanjie could you help with a run on ingenic platform?

Thanks.

- Jiaxun

Quoted 3 lines

Thomas.

#7 lore raw

Re: [PATCH 1/2] mips: convert syscall to generic entry

Hi,

Quoted 37 lines · Jiaxun Yang
Quoted 35 lines · Thomas Bogendoerfer
Quoted 34 lines · 陈飞扬
Quoted 19 lines · Jiaxun Yang
Quoted 17 lines · FreeFlyingSheep

From: Feiyang Chen <[email protected]>

Convert mips syscall to use the generic entry infrastructure from kernel/entry/*.

There are a few special things on mips:

- There is one type of syscall on mips32 (scall32-o32) and three types
of syscalls on mips64 (scall64-o32, scall64-n32 and scall64-n64). Now convert to C code to handle different types of syscalls.

- For some special syscalls (e.g. fork, clone, clone3 and sysmips), save_static_function() wrapper is used to save static registers. Now SAVE_STATIC is used in handle_sys before calling do_syscall(), so the save_static_function() wrapper can be removed.

Quoted 9 lines
Quoted 5 lines

- For sigreturn/rt_sigreturn and sysmips, inline assembly is used to jump to syscall_exit directly for skipping setting the error flag and restoring all registers. Now use regs->regs[27] to mark whether to handle the error flag and always restore all registers in handle_sys, so these functions can return normally as other architecture.

Hmm, that would give us overhead of register context on these syscalls.

I guess it's worthy?

Hi, Jiaxun,

Saving and restoring registers against different system calls can be difficult due to the use of generic entry.
To avoid a lot of duplicate code, I think the overhead is worth it.

Quoted 7 lines
Quoted 3 lines

could you please provide numbers for that ? This code still runs on low end MIPS CPUs for which overhead might mean a different ballpark than some highend Loongson CPUs.

It shows ~3% regression for UnixBench on MT7621A (1004Kec).

+ Yanjie could you help with a run on ingenic platform?

Sure, I can help with JZ4775, JZ4780, X1000, X1830, X2000 from Ingenic, and SF16A18, SF19A2890 from SiFlower.

+ Paul could you help with a run on JZ4760 and JZ4770?

+ Nikolaus could you help with a run on JZ4730?

Thanks and best regards!

Quoted 8 lines

Thanks.

- Jiaxun

Quoted 3 lines

Thomas.

#8 lore raw

Re: [PATCH 1/2] mips: convert syscall to generic entry

Hi,

Quoted 44 lines · Zhou Yanjie

Hi,

Quoted 41 lines · Jiaxun Yang
Quoted 38 lines · Thomas Bogendoerfer
Quoted 27 lines · 陈飞扬
Quoted 26 lines · Jiaxun Yang
Quoted 17 lines · FreeFlyingSheep

From: Feiyang Chen <[email protected]>

Convert mips syscall to use the generic entry infrastructure from kernel/entry/*.

There are a few special things on mips:

- There is one type of syscall on mips32 (scall32-o32) and three types
of syscalls on mips64 (scall64-o32, scall64-n32 and scall64-n64). Now convert to C code to handle different types of syscalls.

- For some special syscalls (e.g. fork, clone, clone3 and sysmips), save_static_function() wrapper is used to save static registers. Now SAVE_STATIC is used in handle_sys before calling do_syscall(), so the save_static_function() wrapper can be removed.

Quoted 5 lines

- For sigreturn/rt_sigreturn and sysmips, inline assembly is used to jump to syscall_exit directly for skipping setting the error flag and restoring all registers. Now use regs->regs[27] to mark whether to handle the error flag and always restore all registers in handle_sys, so these functions can return normally as other architecture.

Hmm, that would give us overhead of register context on these syscalls.

Quoted 7 lines
Quoted 2 lines

I guess it's worthy?

Hi, Jiaxun,

Saving and restoring registers against different system calls can be difficult due to the use of generic entry.
To avoid a lot of duplicate code, I think the overhead is worth it.

could you please provide numbers for that ? This code still runs on low end MIPS CPUs for which overhead might mean a different ballpark than some highend Loongson CPUs.

Quoted 6 lines
Quoted 3 lines

It shows ~3% regression for UnixBench on MT7621A (1004Kec).

+ Yanjie could you help with a run on ingenic platform?

Sure, I can help with JZ4775, JZ4780, X1000, X1830, X2000 from Ingenic, and SF16A18, SF19A2890 from SiFlower.

Sorry for the delay.

I encountered some troubles when testing UNIX Bench on the Ingenic X2000(SMT on) and two SiFlower processors, so I ended up with only the following test results:

Score Without Patches    Score With Patches    Performance Change    SoC Model
            105.9                                    101.2                      -4.4%                         JZ4775 132.4                                    122.0                      -7.9%                         JZ4780(SMP off) 170.2                                    149.5                    -12.2%                         JZ4780(SMP on) 101.3                                      89.0                    -12.1%                         X1000E 187.1                                    177.7                      -5.0%                         X1830 324.9                                    312.2                      -3.9%                         X2000(SMT off)

On the whole, the impact on performance is quite huge.

Thanks and best regards!

Quoted 17 lines

+ Paul could you help with a run on JZ4760 and JZ4770?

+ Nikolaus could you help with a run on JZ4730?

Thanks and best regards!

Quoted 8 lines

Thanks.

- Jiaxun

Quoted 3 lines

Thomas.

#9 lore raw

Re: [PATCH 1/2] mips: convert syscall to generic entry

Quoted 62 lines · Zhou Yanjie

Hi,

Quoted 45 lines · Zhou Yanjie

Hi,

Quoted 42 lines · Jiaxun Yang
Quoted 39 lines · Thomas Bogendoerfer
Quoted 28 lines · 陈飞扬
Quoted 27 lines · Jiaxun Yang
Quoted 17 lines · FreeFlyingSheep

From: Feiyang Chen <[email protected]>

Convert mips syscall to use the generic entry infrastructure from kernel/entry/*.

There are a few special things on mips:

- There is one type of syscall on mips32 (scall32-o32) and three types
of syscalls on mips64 (scall64-o32, scall64-n32 and scall64-n64). Now convert to C code to handle different types of syscalls.

- For some special syscalls (e.g. fork, clone, clone3 and sysmips), save_static_function() wrapper is used to save static registers. Now SAVE_STATIC is used in handle_sys before calling do_syscall(), so the save_static_function() wrapper can be removed.

Quoted 6 lines

- For sigreturn/rt_sigreturn and sysmips, inline assembly is used to
jump to syscall_exit directly for skipping setting the error flag and restoring all registers. Now use regs->regs[27] to mark whether to handle the error flag and always restore all registers in handle_sys, so these functions can return normally as other architecture.

Hmm, that would give us overhead of register context on these syscalls.

Quoted 7 lines
Quoted 2 lines

I guess it's worthy?

Hi, Jiaxun,

Saving and restoring registers against different system calls can be difficult due to the use of generic entry.
To avoid a lot of duplicate code, I think the overhead is worth it.

could you please provide numbers for that ? This code still runs on low end MIPS CPUs for which overhead might mean a different ballpark than some highend Loongson CPUs.

Quoted 6 lines
Quoted 3 lines

It shows ~3% regression for UnixBench on MT7621A (1004Kec).

+ Yanjie could you help with a run on ingenic platform?

Sure, I can help with JZ4775, JZ4780, X1000, X1830, X2000 from Ingenic, and SF16A18, SF19A2890 from SiFlower.

Sorry for the delay.

I encountered some troubles when testing UNIX Bench on the Ingenic X2000(SMT on) and two SiFlower processors, so I ended up with only the following test results:

Quoted 8 lines

Score Without Patches    Score With Patches    Performance Change    SoC Model
            105.9                                    101.2              -4.4%                         JZ4775 132.4                                    122.0              -7.9%                         JZ4780(SMP off) 170.2                                    149.5
-12.2%                         JZ4780(SMP on)
            101.3                                      89.0                -12.1%                         X1000E 187.1                                    177.7              -5.0%                         X1830 324.9                                    312.2              -3.9%                         X2000(SMT off)

Apologies for the bad format :(

Score Without Patches  Score With Patches  Performance Change SoC Model 105.9                101.2              -4.4% JZ4775 132.4                122.0              -7.9% JZ4780(SMP off) 170.2                149.5             -12.2% JZ4780(SMP on) 101.3                 89.0             -12.1% X1000E 187.1                177.7              -5.0% X1830 324.9                312.2              -3.9% X2000(SMT off)

Quoted 25 lines

On the whole, the impact on performance is quite huge.

Thanks and best regards!

Quoted 17 lines

+ Paul could you help with a run on JZ4760 and JZ4770?

+ Nikolaus could you help with a run on JZ4730?

Thanks and best regards!

Quoted 8 lines

Thanks.

- Jiaxun

Quoted 3 lines

Thomas.

#10 lore raw

Re: [PATCH 1/2] mips: convert syscall to generic entry

In reply to Zhou Yanjie

Hi,

Quoted 47 lines

Am 09.09.2021 um 14:45 schrieb Zhou Yanjie <[email protected]>:

Hi,

Quoted 42 lines · Jiaxun Yang
Quoted 29 lines · Thomas Bogendoerfer
Quoted 28 lines · 陈飞扬
Quoted 27 lines · Jiaxun Yang
Quoted 16 lines · FreeFlyingSheep

From: Feiyang Chen <[email protected]>

Convert mips syscall to use the generic entry infrastructure from kernel/entry/*.

There are a few special things on mips:

- There is one type of syscall on mips32 (scall32-o32) and three types of syscalls on mips64 (scall64-o32, scall64-n32 and scall64-n64). Now convert to C code to handle different types of syscalls.

- For some special syscalls (e.g. fork, clone, clone3 and sysmips), save_static_function() wrapper is used to save static registers. Now SAVE_STATIC is used in handle_sys before calling do_syscall(), so the save_static_function() wrapper can be removed.

Quoted 5 lines

- For sigreturn/rt_sigreturn and sysmips, inline assembly is used to jump to syscall_exit directly for skipping setting the error flag and restoring all registers. Now use regs->regs[27] to mark whether to handle the error flag and always restore all registers in handle_sys, so these functions can return normally as other architecture.

Hmm, that would give us overhead of register context on these syscalls.

I guess it's worthy?

Quoted 8 lines
Quoted 5 lines

Hi, Jiaxun,

Saving and restoring registers against different system calls can be difficult due to the use of generic entry.
To avoid a lot of duplicate code, I think the overhead is worth it.

could you please provide numbers for that ? This code still runs on low end MIPS CPUs for which overhead might mean a different ballpark than some highend Loongson CPUs.

It shows ~3% regression for UnixBench on MT7621A (1004Kec).

Quoted 8 lines
Quoted 1 line

+ Yanjie could you help with a run on ingenic platform?

Sure, I can help with JZ4775, JZ4780, X1000, X1830, X2000 from Ingenic, and SF16A18, SF19A2890 from SiFlower.

+ Paul could you help with a run on JZ4760 and JZ4770?

+ Nikolaus could you help with a run on JZ4730?

Have not observed a negative effect on jz4730. Same for jz4780. But I have not done performance tests.

BR,
Nikolaus

#11 lore raw

Re: [PATCH 1/2] mips: convert syscall to generic entry

In reply to Thomas Bogendoerfer
Quoted 35 lines · Thomas Bogendoerfer <[email protected]> 于2021年9月8日周三 下午5:36写道:
Quoted 33 lines · 陈飞扬
Quoted 25 lines · Jiaxun Yang
Quoted 16 lines · FreeFlyingSheep

From: Feiyang Chen <[email protected]>

Convert mips syscall to use the generic entry infrastructure from kernel/entry/*.

There are a few special things on mips:

- There is one type of syscall on mips32 (scall32-o32) and three types of syscalls on mips64 (scall64-o32, scall64-n32 and scall64-n64). Now convert to C code to handle different types of syscalls.

- For some special syscalls (e.g. fork, clone, clone3 and sysmips), save_static_function() wrapper is used to save static registers. Now SAVE_STATIC is used in handle_sys before calling do_syscall(), so the save_static_function() wrapper can be removed.

Quoted 5 lines

- For sigreturn/rt_sigreturn and sysmips, inline assembly is used to jump to syscall_exit directly for skipping setting the error flag and restoring all registers. Now use regs->regs[27] to mark whether to handle the error flag and always restore all registers in handle_sys, so these functions can return normally as other architecture.

Quoted 4 lines

Hmm, that would give us overhead of register context on these syscalls.

I guess it's worthy?

Hi, Jiaxun,

Quoted 7 lines
Quoted 3 lines

Saving and restoring registers against different system calls can be difficult due to the use of generic entry.
To avoid a lot of duplicate code, I think the overhead is worth it.

could you please provide numbers for that ? This code still runs on low end MIPS CPUs for which overhead might mean a different ballpark than some highend Loongson CPUs.

It shows ~2% regression for UnixBench on LOONGSON 3a4000 (a1901).

Thanks,

Yanteng

#12 lore raw

Re: [PATCH 1/2] mips: convert syscall to generic entry

In reply to Thomas Bogendoerfer
Quoted 35 lines · Thomas Bogendoerfer
Quoted 33 lines · 陈飞扬
Quoted 25 lines · Jiaxun Yang
Quoted 16 lines · FreeFlyingSheep

From: Feiyang Chen <[email protected]>

Convert mips syscall to use the generic entry infrastructure from kernel/entry/*.

There are a few special things on mips:

- There is one type of syscall on mips32 (scall32-o32) and three types of syscalls on mips64 (scall64-o32, scall64-n32 and scall64-n64). Now convert to C code to handle different types of syscalls.

- For some special syscalls (e.g. fork, clone, clone3 and sysmips), save_static_function() wrapper is used to save static registers. Now SAVE_STATIC is used in handle_sys before calling do_syscall(), so the save_static_function() wrapper can be removed.

Quoted 5 lines

- For sigreturn/rt_sigreturn and sysmips, inline assembly is used to jump to syscall_exit directly for skipping setting the error flag and restoring all registers. Now use regs->regs[27] to mark whether to handle the error flag and always restore all registers in handle_sys, so these functions can return normally as other architecture.

Quoted 4 lines

Hmm, that would give us overhead of register context on these syscalls.

I guess it's worthy?

Hi, Jiaxun,

Quoted 7 lines
Quoted 3 lines

Saving and restoring registers against different system calls can be difficult due to the use of generic entry.
To avoid a lot of duplicate code, I think the overhead is worth it.

could you please provide numbers for that ? This code still runs on low end MIPS CPUs for which overhead might mean a different ballpark than some highend Loongson CPUs.

Hi, Thomas, Jiaxun, Yanjie, Nikolaus,

Thank you for your help. The impact on performance seems somewhat significant, I will make improvements in the v2 of the patchset.

Thanks,
Feiyang

Quoted 6 lines

Thomas.

--
Crap can work. Given enough thrust pigs will fly, but it's not necessarily a
good idea. [ RFC1925, 2.3 ]

#13 lore raw

PATCH 2/2 mips: convert irq to generic entry

In reply to FreeFlyingSheep

From: Feiyang Chen <[email protected]>

Convert mips irq to use the generic entry infrastructure from kernel/entry/*.

When entering the handler functions written in C, there are three
status: STI, CLI and KMODE. Now use CLI for all handler functions, since interrupts must be disabled before calling irqentry_enter().

- For handler functions who originally used STI, enable interrupts after calling irqentry_enter().

- For handler functions who originally used KMODE, enable interrupts after calling irqentry_enter() only if they are enabled in the parent context.

- If CONFIG_HARDWARE_WATCHPOINTS is defined, interrupts will be enabled after the watch registers are read. Only enable interrupts manually in do_watch() if it is not defined.

The IRQ stack is disabled temporarily because it is too complex to collaborate with the generic code (this will be improved by later patches).

---
 arch/mips/include/asm/irqflags.h   |  42 ------
 arch/mips/include/asm/stackframe.h |   8 ++
 arch/mips/kernel/entry.S           |  82 ------------
 arch/mips/kernel/genex.S           | 148 ++++-----------------
 arch/mips/kernel/head.S            |   1 -
 arch/mips/kernel/r4k-bugs64.c      |  14 +-
 arch/mips/kernel/scall.S           |   7 +-
 arch/mips/kernel/signal.c          |  26 ----
 arch/mips/kernel/traps.c           | 202 ++++++++++++++++++++---------
 arch/mips/kernel/unaligned.c       |  19 +--
 arch/mips/mm/c-octeon.c            |  15 +++
 arch/mips/mm/cex-oct.S             |   8 +-
 arch/mips/mm/fault.c               |  12 +-
 arch/mips/mm/tlbex-fault.S         |   7 +-
 14 files changed, 230 insertions(+), 361 deletions(-)
arch/mips/include/asm/irqflags.h +0 -42
index f5b8300f4573..ee7519b0d23f 100644
@@ -11,8 +11,6 @@
 #ifndef _ASM_IRQFLAGS_H
 #define _ASM_IRQFLAGS_H
 
-#ifndef __ASSEMBLY__
-
 #include <linux/compiler.h>
 #include <linux/stringify.h>
 #include <asm/compiler.h>
@@ -142,44 +140,4 @@ static inline int arch_irqs_disabled(void)
 	return arch_irqs_disabled_flags(arch_local_save_flags());
 }
 
-#endif /* #ifndef __ASSEMBLY__ */
-
-/*
- * Do the CPU's IRQ-state tracing from assembly code.
- */
-#ifdef CONFIG_TRACE_IRQFLAGS
-/* Reload some registers clobbered by trace_hardirqs_on */
-#ifdef CONFIG_64BIT
-# define TRACE_IRQS_RELOAD_REGS						\
-	LONG_L	$11, PT_R11(sp);					\
-	LONG_L	$10, PT_R10(sp);					\
-	LONG_L	$9, PT_R9(sp);						\
-	LONG_L	$8, PT_R8(sp);						\
-	LONG_L	$7, PT_R7(sp);						\
-	LONG_L	$6, PT_R6(sp);						\
-	LONG_L	$5, PT_R5(sp);						\
-	LONG_L	$4, PT_R4(sp);						\
-	LONG_L	$2, PT_R2(sp)
-#else
-# define TRACE_IRQS_RELOAD_REGS						\
-	LONG_L	$7, PT_R7(sp);						\
-	LONG_L	$6, PT_R6(sp);						\
-	LONG_L	$5, PT_R5(sp);						\
-	LONG_L	$4, PT_R4(sp);						\
-	LONG_L	$2, PT_R2(sp)
-#endif
-# define TRACE_IRQS_ON							\
-	CLI;	/* make sure trace_hardirqs_on() is called in kernel level */ \
-	jal	trace_hardirqs_on
-# define TRACE_IRQS_ON_RELOAD						\
-	TRACE_IRQS_ON;							\
-	TRACE_IRQS_RELOAD_REGS
-# define TRACE_IRQS_OFF							\
-	jal	trace_hardirqs_off
-#else
-# define TRACE_IRQS_ON
-# define TRACE_IRQS_ON_RELOAD
-# define TRACE_IRQS_OFF
-#endif
-
 #endif /* _ASM_IRQFLAGS_H */
arch/mips/include/asm/stackframe.h +8 -0
index aa430a6c68b2..8bc74d7950fb 100644
@@ -444,6 +444,14 @@
 		RESTORE_SP \docfi
 		.endm
 
+		.macro	RESTORE_ALL_AND_RET docfi=0
+		RESTORE_TEMP \docfi
+		RESTORE_STATIC \docfi
+		RESTORE_AT \docfi
+		RESTORE_SOME \docfi
+		RESTORE_SP_AND_RET \docfi
+		.endm
+
 /*
  * Move to kernel mode and disable interrupts.
  * Set cp0 enable bit as sign that we're running on the kernel stack
arch/mips/kernel/entry.S +0 -82

102 lines not on this page · raw message

arch/mips/kernel/genex.S +26 -122

228 lines not on this page · raw message

arch/mips/kernel/head.S +0 -1
index b825ed4476c7..5f028dbd5961 100644
@@ -19,7 +19,6 @@
 #include <asm/addrspace.h>
 #include <asm/asm.h>
 #include <asm/asmmacro.h>
-#include <asm/irqflags.h>
 #include <asm/regdef.h>
 #include <asm/mipsregs.h>
 #include <asm/stackframe.h>
arch/mips/kernel/r4k-bugs64.c +10 -4
index 35729c9e6cfa..0384b649877c 100644
@@ -3,6 +3,7 @@
  * Copyright (C) 2003, 2004, 2007  Maciej W. Rozycki
  */
 #include <linux/context_tracking.h>
+#include <linux/entry-common.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/ptrace.h>
@@ -168,14 +169,19 @@ static __always_inline __init void check_mult_sh(void)
 
 static volatile int daddi_ov;
 
-asmlinkage void __init do_daddi_ov(struct pt_regs *regs)
+asmlinkage void noinstr __init do_daddi_ov(struct pt_regs *regs)
 {
-	enum ctx_state prev_state;
+	irqentry_state_t state = irqentry_enter(regs);
+
+	/* Enable interrupt if enabled in parent context */
+	if (likely(!regs_irqs_disabled(regs)))
+		local_irq_enable();
 
-	prev_state = exception_enter();
 	daddi_ov = 1;
 	regs->cp0_epc += 4;
-	exception_exit(prev_state);
+
+	local_irq_disable();
+	irqentry_exit(regs, state);
 }
 
 static __init void check_daddi(void)
arch/mips/kernel/scall.S +1 -6
index 7b35969151de..3bd955ce5462 100644
@@ -9,7 +9,6 @@
 #include <linux/errno.h>
 #include <asm/asm.h>
 #include <asm/asmmacro.h>
-#include <asm/irqflags.h>
 #include <asm/mipsregs.h>
 #include <asm/regdef.h>
 #include <asm/stackframe.h>
@@ -31,11 +30,7 @@ NESTED(handle_sys, PT_SIZE, sp)
 	jal	do_syscall
 
 	.set	noat
-	RESTORE_TEMP
-	RESTORE_AT
-	RESTORE_STATIC
-	RESTORE_SOME
-	RESTORE_SP_AND_RET
+	RESTORE_ALL_AND_RET
 	.set	at
 	END(handle_sys)
 
arch/mips/kernel/signal.c +0 -26
index 1ec6a0cf1163..dbcfbaf03558 100644
@@ -875,32 +875,6 @@ void arch_do_signal_or_restart(struct pt_regs *regs, bool has_signal)
 	restore_saved_sigmask();
 }
 
-/*
- * notification of userspace execution resumption
- * - triggered by the TIF_WORK_MASK flags
- */
-asmlinkage void do_notify_resume(struct pt_regs *regs, void *unused,
-	__u32 thread_info_flags)
-{
-	local_irq_enable();
-
-	user_exit();
-
-	if (thread_info_flags & _TIF_UPROBE)
-		uprobe_notify_resume(regs);
-
-	/* deal with pending signal delivery */
-	if (thread_info_flags & (_TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL))
-		arch_do_signal_or_restart(regs, thread_info_flags & _TIF_SIGPENDING);
-
-	if (thread_info_flags & _TIF_NOTIFY_RESUME) {
-		tracehook_notify_resume(regs);
-		rseq_handle_notify_resume(NULL, regs);
-	}
-
-	user_enter();
-}
-
 #if defined(CONFIG_SMP) && defined(CONFIG_MIPS_FP_SUPPORT)
 static int smp_save_fp_context(void __user *sc)
 {
arch/mips/kernel/traps.c +141 -61

435 lines not on this page · raw message

arch/mips/kernel/unaligned.c +11 -8
index df4b708c04a9..fe46016a6afc 100644
@@ -74,6 +74,7 @@
  *	 Undo the partial store in this case.
  */
 #include <linux/context_tracking.h>
+#include <linux/entry-common.h>
 #include <linux/mm.h>
 #include <linux/signal.h>
 #include <linux/smp.h>
@@ -1472,12 +1473,15 @@ static void emulate_load_store_MIPS16e(struct pt_regs *regs, void __user * addr)
 	force_sig(SIGILL);
 }
 
-asmlinkage void do_ade(struct pt_regs *regs)
+asmlinkage void noinstr do_ade(struct pt_regs *regs)
 {
-	enum ctx_state prev_state;
+	irqentry_state_t state = irqentry_enter(regs);
 	unsigned int *pc;
 
-	prev_state = exception_enter();
+	/* Enable interrupt if enabled in parent context */
+	if (likely(!regs_irqs_disabled(regs)))
+		local_irq_enable();
+
 	perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS,
 			1, regs, regs->cp0_badvaddr);
 	/*
@@ -1530,16 +1534,15 @@ asmlinkage void do_ade(struct pt_regs *regs)
 
 	emulate_load_store_insn(regs, (void __user *)regs->cp0_badvaddr, pc);
 
-	return;
+	goto out;
 
 sigbus:
 	die_if_kernel("Kernel unaligned instruction access", regs);
 	force_sig(SIGBUS);
 
-	/*
-	 * XXX On return from the signal handler we should advance the epc
-	 */
-	exception_exit(prev_state);
+out:
+	local_irq_disable();
+	irqentry_exit(regs, state);
 }
 
 #ifdef CONFIG_DEBUG_FS
arch/mips/mm/c-octeon.c +15 -0
index ec2ae501539a..e68c9e6c6480 100644
@@ -5,6 +5,7 @@
  *
  * Copyright (C) 2005-2007 Cavium Networks
  */
+#include <linux/entry-common.h>
 #include <linux/export.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
@@ -349,3 +350,17 @@ asmlinkage void cache_parity_error_octeon_non_recoverable(void)
 	co_cache_error_call_notifiers(1);
 	panic("Can't handle cache error: nested exception");
 }
+
+asmlinkage void noinstr do_cache_err(struct pt_regs *regs)
+{
+	irqentry_state_t state = irqentry_enter(regs);
+
+	/* Enable interrupt if enabled in parent context */
+	if (likely(!regs_irqs_disabled(regs)))
+		local_irq_enable();
+
+	cache_parity_error_octeon_recoverable();
+
+	local_irq_disable();
+	irqentry_exit(regs, state);
+}
arch/mips/mm/cex-oct.S +4 -4
index 9029092aa740..7d39087d208b 100644
@@ -60,11 +60,11 @@
 	.set	noat
 
 	SAVE_ALL
-	KMODE
-	jal	cache_parity_error_octeon_recoverable
-	nop
-	j	ret_from_exception
+	CLI
+	move	a0, sp
+	jal	do_cache_err
 	nop
 
+	RESTORE_ALL_AND_RET
 	.set pop
 	END(handle_cache_err)
arch/mips/mm/fault.c +9 -3
index e7abda9c013f..e55bd45a596b 100644
@@ -8,6 +8,7 @@
 #include <linux/context_tracking.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
+#include <linux/entry-common.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -327,9 +328,14 @@ static void __kprobes __do_page_fault(struct pt_regs *regs, unsigned long write,
 asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
 	unsigned long write, unsigned long address)
 {
-	enum ctx_state prev_state;
+	irqentry_state_t state = irqentry_enter(regs);
+
+	/* Enable interrupt if enabled in parent context */
+	if (likely(!regs_irqs_disabled(regs)))
+		local_irq_enable();
 
-	prev_state = exception_enter();
 	__do_page_fault(regs, write, address);
-	exception_exit(prev_state);
+
+	local_irq_disable();
+	irqentry_exit(regs, state);
 }
arch/mips/mm/tlbex-fault.S +5 -2
index 77db401fc620..e16b4aa1fcc4 100644
@@ -15,12 +15,15 @@
 	.cfi_signal_frame
 	SAVE_ALL docfi=1
 	MFC0	a2, CP0_BADVADDR
-	KMODE
+	CLI
 	move	a0, sp
 	REG_S	a2, PT_BVADDR(sp)
 	li	a1, \write
 	jal	do_page_fault
-	j	ret_from_exception
+
+	.set	noat
+	RESTORE_ALL_AND_RET
+	.set	at
 	END(tlb_do_page_fault_\write)
 	.endm
 
Signature · 1 line
2.27.0
Reviewed-by on v1 2/2
#14 lore raw

Re: [PATCH 2/2] mips: convert irq to generic entry

Quoted 1,201 lines · FreeFlyingSheep

From: Feiyang Chen <[email protected]>

Convert mips irq to use the generic entry infrastructure from kernel/entry/*.

When entering the handler functions written in C, there are three
status: STI, CLI and KMODE. Now use CLI for all handler functions, since interrupts must be disabled before calling irqentry_enter().

- For handler functions who originally used STI, enable interrupts after calling irqentry_enter().

- For handler functions who originally used KMODE, enable interrupts after calling irqentry_enter() only if they are enabled in the parent context.

- If CONFIG_HARDWARE_WATCHPOINTS is defined, interrupts will be enabled after the watch registers are read. Only enable interrupts manually in do_watch() if it is not defined.

The IRQ stack is disabled temporarily because it is too complex to collaborate with the generic code (this will be improved by later patches).

---
 arch/mips/include/asm/irqflags.h   |  42 ------
 arch/mips/include/asm/stackframe.h |   8 ++
 arch/mips/kernel/entry.S           |  82 ------------
 arch/mips/kernel/genex.S           | 148 ++++-----------------
 arch/mips/kernel/head.S            |   1 -
 arch/mips/kernel/r4k-bugs64.c      |  14 +-
 arch/mips/kernel/scall.S           |   7 +-
 arch/mips/kernel/signal.c          |  26 ----
 arch/mips/kernel/traps.c           | 202 ++++++++++++++++++++---------
 arch/mips/kernel/unaligned.c       |  19 +--
 arch/mips/mm/c-octeon.c            |  15 +++
 arch/mips/mm/cex-oct.S             |   8 +-
 arch/mips/mm/fault.c               |  12 +-
 arch/mips/mm/tlbex-fault.S         |   7 +-
 14 files changed, 230 insertions(+), 361 deletions(-)
arch/mips/include/asm/irqflags.h +0 -42
index f5b8300f4573..ee7519b0d23f 100644
@@ -11,8 +11,6 @@
 #ifndef _ASM_IRQFLAGS_H
 #define _ASM_IRQFLAGS_H
 
-#ifndef __ASSEMBLY__
-
 #include <linux/compiler.h>
 #include <linux/stringify.h>
 #include <asm/compiler.h>
@@ -142,44 +140,4 @@ static inline int arch_irqs_disabled(void)
        return arch_irqs_disabled_flags(arch_local_save_flags());
 }
 
-#endif /* #ifndef __ASSEMBLY__ */
-
-/*
- * Do the CPU's IRQ-state tracing from assembly code.
- */
-#ifdef CONFIG_TRACE_IRQFLAGS
-/* Reload some registers clobbered by trace_hardirqs_on */
-#ifdef CONFIG_64BIT
-# define TRACE_IRQS_RELOAD_REGS                                                \
-       LONG_L  $11, PT_R11(sp);                                        \
-       LONG_L  $10, PT_R10(sp);                                        \
-       LONG_L  $9, PT_R9(sp);                                          \
-       LONG_L  $8, PT_R8(sp);                                          \
-       LONG_L  $7, PT_R7(sp);                                          \
-       LONG_L  $6, PT_R6(sp);                                          \
-       LONG_L  $5, PT_R5(sp);                                          \
-       LONG_L  $4, PT_R4(sp);                                          \
-       LONG_L  $2, PT_R2(sp)
-#else
-# define TRACE_IRQS_RELOAD_REGS                                                \
-       LONG_L  $7, PT_R7(sp);                                          \
-       LONG_L  $6, PT_R6(sp);                                          \
-       LONG_L  $5, PT_R5(sp);                                          \
-       LONG_L  $4, PT_R4(sp);                                          \
-       LONG_L  $2, PT_R2(sp)
-#endif
-# define TRACE_IRQS_ON                                                 \
-       CLI;    /* make sure trace_hardirqs_on() is called in kernel level */ \
-       jal     trace_hardirqs_on
-# define TRACE_IRQS_ON_RELOAD                                          \
-       TRACE_IRQS_ON;                                                  \
-       TRACE_IRQS_RELOAD_REGS
-# define TRACE_IRQS_OFF                                                        \
-       jal     trace_hardirqs_off
-#else
-# define TRACE_IRQS_ON
-# define TRACE_IRQS_ON_RELOAD
-# define TRACE_IRQS_OFF
-#endif
-
 #endif /* _ASM_IRQFLAGS_H */
arch/mips/include/asm/stackframe.h +8 -0
index aa430a6c68b2..8bc74d7950fb 100644
@@ -444,6 +444,14 @@
                RESTORE_SP \docfi
                .endm
 
+               .macro  RESTORE_ALL_AND_RET docfi=0
+               RESTORE_TEMP \docfi
+               RESTORE_STATIC \docfi
+               RESTORE_AT \docfi
+               RESTORE_SOME \docfi
+               RESTORE_SP_AND_RET \docfi
+               .endm
+
 /*
  * Move to kernel mode and disable interrupts.
  * Set cp0 enable bit as sign that we're running on the kernel stack
arch/mips/kernel/entry.S +0 -82
index 1a2aec9dab1b..c9148831d820 100644
@@ -11,7 +11,6 @@
 #include <asm/asm.h>
 #include <asm/asmmacro.h>
 #include <asm/compiler.h>
-#include <asm/irqflags.h>
 #include <asm/regdef.h>
 #include <asm/mipsregs.h>
 #include <asm/stackframe.h>
@@ -19,55 +18,8 @@
 #include <asm/thread_info.h>
 #include <asm/war.h>
 
-#ifndef CONFIG_PREEMPTION
-#define resume_kernel  restore_all
-#else
-#define __ret_from_irq ret_from_exception
-#endif
-
        .text
        .align  5
-#ifndef CONFIG_PREEMPTION
-FEXPORT(ret_from_exception)
-       local_irq_disable                       # preempt stop
-       b       __ret_from_irq
-#endif
-FEXPORT(ret_from_irq)
-       LONG_S  s0, TI_REGS($28)
-FEXPORT(__ret_from_irq)
-/*
- * We can be coming here from a syscall done in the kernel space,
- * e.g. a failed kernel_execve().
- */
-resume_userspace_check:
-       LONG_L  t0, PT_STATUS(sp)               # returning to kernel mode?
-       andi    t0, t0, KU_USER
-       beqz    t0, resume_kernel
-
-resume_userspace:
-       local_irq_disable               # make sure we dont miss an
-                                       # interrupt setting need_resched
-                                       # between sampling and return
-       LONG_L  a2, TI_FLAGS($28)       # current->work
-       andi    t0, a2, _TIF_WORK_MASK  # (ignoring syscall_trace)
-       bnez    t0, work_pending
-       j       restore_all
-
-#ifdef CONFIG_PREEMPTION
-resume_kernel:
-       local_irq_disable
-       lw      t0, TI_PRE_COUNT($28)
-       bnez    t0, restore_all
-       LONG_L  t0, TI_FLAGS($28)
-       andi    t1, t0, _TIF_NEED_RESCHED
-       beqz    t1, restore_all
-       LONG_L  t0, PT_STATUS(sp)               # Interrupts off?
-       andi    t0, 1
-       beqz    t0, restore_all
-       PTR_LA  ra, restore_all
-       j       preempt_schedule_irq
-#endif
-
 FEXPORT(ret_from_kernel_thread)
        jal     schedule_tail           # a0 = struct task_struct *prev
        move    a0, s1
@@ -92,40 +44,6 @@ FEXPORT(ret_from_fork)
        RESTORE_SP_AND_RET
        .set    at
 
-restore_all:                           # restore full frame
-       .set    noat
-       RESTORE_TEMP
-       RESTORE_AT
-       RESTORE_STATIC
-restore_partial:                       # restore partial frame
-       RESTORE_SOME
-       RESTORE_SP_AND_RET
-       .set    at
-
-work_pending:
-       andi    t0, a2, _TIF_NEED_RESCHED # a2 is preloaded with TI_FLAGS
-       beqz    t0, work_notifysig
-work_resched:
-       TRACE_IRQS_OFF
-       jal     schedule
-
-       local_irq_disable               # make sure need_resched and
-                                       # signals dont change between
-                                       # sampling and return
-       LONG_L  a2, TI_FLAGS($28)
-       andi    t0, a2, _TIF_WORK_MASK  # is there any work to be done
-                                       # other than syscall tracing?
-       beqz    t0, restore_all
-       andi    t0, a2, _TIF_NEED_RESCHED
-       bnez    t0, work_resched
-
-work_notifysig:                                # deal with pending signals and
-                                       # notify-resume requests
-       move    a0, sp
-       li      a1, 0
-       jal     do_notify_resume        # a2 already loaded
-       j       resume_userspace_check
-
 #if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR5) || \
     defined(CONFIG_CPU_MIPSR6) || defined(CONFIG_MIPS_MT)
 
arch/mips/kernel/genex.S +26 -122
index 743d75927b71..60e288d307ff 100644
@@ -13,7 +13,6 @@
 #include <asm/asm.h>
 #include <asm/asmmacro.h>
 #include <asm/cacheops.h>
-#include <asm/irqflags.h>
 #include <asm/regdef.h>
 #include <asm/fpregdef.h>
 #include <asm/mipsregs.h>
@@ -182,53 +181,16 @@ NESTED(handle_int, PT_SIZE, sp)
 #endif
        SAVE_ALL docfi=1
        CLI
-       TRACE_IRQS_OFF
 
-       LONG_L  s0, TI_REGS($28)
-       LONG_S  sp, TI_REGS($28)
-
-       /*
-        * SAVE_ALL ensures we are using a valid kernel stack for the thread.
-        * Check if we are already using the IRQ stack.
-        */
-       move    s1, sp # Preserve the sp
-
-       /* Get IRQ stack for this CPU */
-       ASM_CPUID_MFC0  k0, ASM_SMP_CPUID_REG
-#if defined(CONFIG_32BIT) || defined(KBUILD_64BIT_SYM32)
-       lui     k1, %hi(irq_stack)
-#else
-       lui     k1, %highest(irq_stack)
-       daddiu  k1, %higher(irq_stack)
-       dsll    k1, 16
-       daddiu  k1, %hi(irq_stack)
-       dsll    k1, 16
-#endif
-       LONG_SRL        k0, SMP_CPUID_PTRSHIFT
-       LONG_ADDU       k1, k0
-       LONG_L  t0, %lo(irq_stack)(k1)
-
-       # Check if already on IRQ stack
-       PTR_LI  t1, ~(_THREAD_SIZE-1)
-       and     t1, t1, sp
-       beq     t0, t1, 2f
-
-       /* Switch to IRQ stack */
-       li      t1, _IRQ_STACK_START
-       PTR_ADD sp, t0, t1
-
-       /* Save task's sp on IRQ stack so that unwinding can follow it */
-       LONG_S  s1, 0(sp)
-2:
-       jal     plat_irq_dispatch
-
-       /* Restore sp */
-       move    sp, s1
-
-       j       ret_from_irq
+       move    a0, sp
+       jal     do_int
 #ifdef CONFIG_CPU_MICROMIPS
        nop
 #endif
+
+       .set    noat
+       RESTORE_ALL_AND_RET
+       .set    at
        END(handle_int)
 
        __INIT
@@ -290,54 +252,12 @@ NESTED(except_vec_vi_handler, 0, sp)
        SAVE_TEMP
        SAVE_STATIC
        CLI
-#ifdef CONFIG_TRACE_IRQFLAGS
-       move    s0, v0
-       TRACE_IRQS_OFF
-       move    v0, s0
-#endif
-
-       LONG_L  s0, TI_REGS($28)
-       LONG_S  sp, TI_REGS($28)
 
-       /*
-        * SAVE_ALL ensures we are using a valid kernel stack for the thread.
-        * Check if we are already using the IRQ stack.
-        */
-       move    s1, sp # Preserve the sp
-
-       /* Get IRQ stack for this CPU */
-       ASM_CPUID_MFC0  k0, ASM_SMP_CPUID_REG
-#if defined(CONFIG_32BIT) || defined(KBUILD_64BIT_SYM32)
-       lui     k1, %hi(irq_stack)
-#else
-       lui     k1, %highest(irq_stack)
-       daddiu  k1, %higher(irq_stack)
-       dsll    k1, 16
-       daddiu  k1, %hi(irq_stack)
-       dsll    k1, 16
-#endif
-       LONG_SRL        k0, SMP_CPUID_PTRSHIFT
-       LONG_ADDU       k1, k0
-       LONG_L  t0, %lo(irq_stack)(k1)
-
-       # Check if already on IRQ stack
-       PTR_LI  t1, ~(_THREAD_SIZE-1)
-       and     t1, t1, sp
-       beq     t0, t1, 2f
-
-       /* Switch to IRQ stack */
-       li      t1, _IRQ_STACK_START
-       PTR_ADD sp, t0, t1
-
-       /* Save task's sp on IRQ stack so that unwinding can follow it */
-       LONG_S  s1, 0(sp)
-2:
-       jalr    v0
-
-       /* Restore sp */
-       move    sp, s1
+       move    a0, sp
+       move    a1, v0
+       jal     do_vi
 
-       j       ret_from_irq
+       RESTORE_ALL_AND_RET
        END(except_vec_vi_handler)
 
 /*
@@ -462,22 +382,12 @@ NESTED(nmi_handler, PT_SIZE, sp)
        .set    pop
        END(nmi_handler)
 
-       .macro  __build_clear_none
-       .endm
-
-       .macro  __build_clear_sti
-       TRACE_IRQS_ON
-       STI
-       .endm
-
        .macro  __build_clear_cli
        CLI
-       TRACE_IRQS_OFF
        .endm
 
        .macro  __build_clear_fpe
        CLI
-       TRACE_IRQS_OFF
        .set    push
        /* gas fails to assemble cfc1 for some archs (octeon).*/ \
        .set    mips1
@@ -488,14 +398,13 @@ NESTED(nmi_handler, PT_SIZE, sp)
 
        .macro  __build_clear_msa_fpe
        CLI
-       TRACE_IRQS_OFF
        _cfcmsa a1, MSA_CSR
        .endm
 
        .macro  __build_clear_ade
        MFC0    t0, CP0_BADVADDR
        PTR_S   t0, PT_BVADDR(sp)
-       KMODE
+       CLI
        .endm
 
        .macro __build_clear_gsexc
@@ -507,8 +416,7 @@ NESTED(nmi_handler, PT_SIZE, sp)
        .set    mips32
        mfc0    a1, CP0_DIAGNOSTIC1
        .set    pop
-       TRACE_IRQS_ON
-       STI
+       CLI
        .endm
 
        .macro  __BUILD_silent exception
@@ -547,7 +455,7 @@ NESTED(nmi_handler, PT_SIZE, sp)
        __BUILD_\verbose \exception
        move    a0, sp
        jal     do_\handler
-       j       ret_from_exception
+       RESTORE_ALL_AND_RET
        END(handle_\exception)
        .endm
 
@@ -559,32 +467,28 @@ NESTED(nmi_handler, PT_SIZE, sp)
        BUILD_HANDLER ades ade ade silent               /* #5  */
        BUILD_HANDLER ibe be cli silent                 /* #6  */
        BUILD_HANDLER dbe be cli silent                 /* #7  */
-       BUILD_HANDLER bp bp sti silent                  /* #9  */
-       BUILD_HANDLER ri ri sti silent                  /* #10 */
-       BUILD_HANDLER cpu cpu sti silent                /* #11 */
-       BUILD_HANDLER ov ov sti silent                  /* #12 */
-       BUILD_HANDLER tr tr sti silent                  /* #13 */
+       BUILD_HANDLER bp bp cli silent                  /* #9  */
+       BUILD_HANDLER ri ri cli silent                  /* #10 */
+       BUILD_HANDLER cpu cpu cli silent                /* #11 */
+       BUILD_HANDLER ov ov cli silent                  /* #12 */
+       BUILD_HANDLER tr tr cli silent                  /* #13 */
        BUILD_HANDLER msa_fpe msa_fpe msa_fpe silent    /* #14 */
 #ifdef CONFIG_MIPS_FP_SUPPORT
        BUILD_HANDLER fpe fpe fpe silent                /* #15 */
 #endif
-       BUILD_HANDLER ftlb ftlb none silent             /* #16 */
+       BUILD_HANDLER ftlb ftlb cli silent              /* #16 */
        BUILD_HANDLER gsexc gsexc gsexc silent          /* #16 */
-       BUILD_HANDLER msa msa sti silent                /* #21 */
-       BUILD_HANDLER mdmx mdmx sti silent              /* #22 */
+       BUILD_HANDLER msa msa cli silent                /* #21 */
+       BUILD_HANDLER mdmx mdmx cli silent              /* #22 */
 #ifdef CONFIG_HARDWARE_WATCHPOINTS
-       /*
-        * For watch, interrupts will be enabled after the watch
-        * registers are read.
-        */
        BUILD_HANDLER watch watch cli silent            /* #23 */
 #else
-       BUILD_HANDLER watch watch sti verbose           /* #23 */
+       BUILD_HANDLER watch watch cli verbose           /* #23 */
 #endif
        BUILD_HANDLER mcheck mcheck cli verbose         /* #24 */
-       BUILD_HANDLER mt mt sti silent                  /* #25 */
-       BUILD_HANDLER dsp dsp sti silent                /* #26 */
-       BUILD_HANDLER reserved reserved sti verbose     /* others */
+       BUILD_HANDLER mt mt cli silent                  /* #25 */
+       BUILD_HANDLER dsp dsp cli silent                /* #26 */
+       BUILD_HANDLER reserved reserved cli verbose     /* others */
 
        .align  5
        LEAF(handle_ri_rdhwr_tlbp)
@@ -678,5 +582,5 @@ isrdhwr:
 
        __INIT
 
-       BUILD_HANDLER  daddi_ov daddi_ov none silent    /* #12 */
+       BUILD_HANDLER  daddi_ov daddi_ov cli silent     /* #12 */
 #endif
arch/mips/kernel/head.S +0 -1
index b825ed4476c7..5f028dbd5961 100644
@@ -19,7 +19,6 @@
 #include <asm/addrspace.h>
 #include <asm/asm.h>
 #include <asm/asmmacro.h>
-#include <asm/irqflags.h>
 #include <asm/regdef.h>
 #include <asm/mipsregs.h>
 #include <asm/stackframe.h>
arch/mips/kernel/r4k-bugs64.c +10 -4
index 35729c9e6cfa..0384b649877c 100644
@@ -3,6 +3,7 @@
  * Copyright (C) 2003, 2004, 2007  Maciej W. Rozycki
  */
 #include <linux/context_tracking.h>
+#include <linux/entry-common.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/ptrace.h>
@@ -168,14 +169,19 @@ static __always_inline __init void check_mult_sh(void)
 
 static volatile int daddi_ov;
 
-asmlinkage void __init do_daddi_ov(struct pt_regs *regs)
+asmlinkage void noinstr __init do_daddi_ov(struct pt_regs *regs)
 {
-       enum ctx_state prev_state;
+       irqentry_state_t state = irqentry_enter(regs);
+
+       /* Enable interrupt if enabled in parent context */
+       if (likely(!regs_irqs_disabled(regs)))
+               local_irq_enable();
 
-       prev_state = exception_enter();
        daddi_ov = 1;
        regs->cp0_epc += 4;
-       exception_exit(prev_state);
+
+       local_irq_disable();
+       irqentry_exit(regs, state);
 }
 
 static __init void check_daddi(void)
arch/mips/kernel/scall.S +1 -6
index 7b35969151de..3bd955ce5462 100644
@@ -9,7 +9,6 @@
 #include <linux/errno.h>
 #include <asm/asm.h>
 #include <asm/asmmacro.h>
-#include <asm/irqflags.h>
 #include <asm/mipsregs.h>
 #include <asm/regdef.h>
 #include <asm/stackframe.h>
@@ -31,11 +30,7 @@ NESTED(handle_sys, PT_SIZE, sp)
        jal     do_syscall
 
        .set    noat
-       RESTORE_TEMP
-       RESTORE_AT
-       RESTORE_STATIC
-       RESTORE_SOME
-       RESTORE_SP_AND_RET
+       RESTORE_ALL_AND_RET
        .set    at
        END(handle_sys)
 
arch/mips/kernel/signal.c +0 -26
index 1ec6a0cf1163..dbcfbaf03558 100644
@@ -875,32 +875,6 @@ void arch_do_signal_or_restart(struct pt_regs *regs, bool has_signal)
        restore_saved_sigmask();
 }
 
-/*
- * notification of userspace execution resumption
- * - triggered by the TIF_WORK_MASK flags
- */
-asmlinkage void do_notify_resume(struct pt_regs *regs, void *unused,
-       __u32 thread_info_flags)
-{
-       local_irq_enable();
-
-       user_exit();
-
-       if (thread_info_flags & _TIF_UPROBE)
-               uprobe_notify_resume(regs);
-
-       /* deal with pending signal delivery */
-       if (thread_info_flags & (_TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL))
-               arch_do_signal_or_restart(regs, thread_info_flags & _TIF_SIGPENDING);
-
-       if (thread_info_flags & _TIF_NOTIFY_RESUME) {
-               tracehook_notify_resume(regs);
-               rseq_handle_notify_resume(NULL, regs);
-       }
-
-       user_enter();
-}
-
 #if defined(CONFIG_SMP) && defined(CONFIG_MIPS_FP_SUPPORT)
 static int smp_save_fp_context(void __user *sc)
 {
arch/mips/kernel/traps.c +141 -61
index 6f07362de5ce..69290e67dd68 100644
@@ -17,6 +17,7 @@
 #include <linux/compiler.h>
 #include <linux/context_tracking.h>
 #include <linux/cpu_pm.h>
+#include <linux/entry-common.h>
 #include <linux/kexec.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -438,15 +439,14 @@ static const struct exception_table_entry *search_dbe_tables(unsigned long addr)
        return e;
 }
 
-asmlinkage void do_be(struct pt_regs *regs)
+asmlinkage void noinstr do_be(struct pt_regs *regs)
 {
+       irqentry_state_t state = irqentry_enter(regs);
        const int field = 2 * sizeof(unsigned long);
        const struct exception_table_entry *fixup = NULL;
        int data = regs->cp0_cause & 4;
        int action = MIPS_BE_FATAL;
-       enum ctx_state prev_state;
 
-       prev_state = exception_enter();
        /* XXX For now.  Fixme, this searches the wrong table ...  */
        if (data && !user_mode(regs))
                fixup = search_dbe_tables(exception_epc(regs));
@@ -486,7 +486,7 @@ asmlinkage void do_be(struct pt_regs *regs)
        force_sig(SIGBUS);
 
 out:
-       exception_exit(prev_state);
+       irqentry_exit(regs, state);
 }
 
 /*
@@ -743,15 +743,18 @@ static int simulate_loongson3_cpucfg(struct pt_regs *regs,
 }
 #endif /* CONFIG_CPU_LOONGSON3_CPUCFG_EMULATION */
 
-asmlinkage void do_ov(struct pt_regs *regs)
+asmlinkage void noinstr do_ov(struct pt_regs *regs)
 {
-       enum ctx_state prev_state;
+       irqentry_state_t state = irqentry_enter(regs);
+
+       local_irq_enable();
 
-       prev_state = exception_enter();
        die_if_kernel("Integer overflow", regs);
 
        force_sig_fault(SIGFPE, FPE_INTOVF, (void __user *)regs->cp0_epc);
-       exception_exit(prev_state);
+
+       local_irq_disable();
+       irqentry_exit(regs, state);
 }
 
 #ifdef CONFIG_MIPS_FP_SUPPORT
@@ -865,13 +868,12 @@ static int simulate_fp(struct pt_regs *regs, unsigned int opcode,
 /*
  * XXX Delayed fp exceptions when doing a lazy ctx switch XXX
  */
-asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)
+asmlinkage void noinstr do_fpe(struct pt_regs *regs, unsigned long fcr31)
 {
-       enum ctx_state prev_state;
+       irqentry_state_t state = irqentry_enter(regs);
        void __user *fault_addr;
        int sig;
 
-       prev_state = exception_enter();
        if (notify_die(DIE_FP, "FP exception", regs, 0, current->thread.trap_nr,
                       SIGFPE) == NOTIFY_STOP)
                goto out;
@@ -916,7 +918,8 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)
        process_fpemu_return(sig, fault_addr, fcr31);
 
 out:
-       exception_exit(prev_state);
+       local_irq_disable();
+       irqentry_exit(regs, state);
 }
 
 /*
@@ -1018,14 +1021,16 @@ void do_trap_or_bp(struct pt_regs *regs, unsigned int code, int si_code,
        }
 }
 
-asmlinkage void do_bp(struct pt_regs *regs)
+asmlinkage void noinstr do_bp(struct pt_regs *regs)
 {
-       unsigned long epc = msk_isa16_mode(exception_epc(regs));
-       unsigned int opcode, bcode;
-       enum ctx_state prev_state;
+       irqentry_state_t state = irqentry_enter(regs);
        bool user = user_mode(regs);
+       unsigned int opcode, bcode;
+       unsigned long epc;
+
+       local_irq_enable();
 
-       prev_state = exception_enter();
+       epc = msk_isa16_mode(exception_epc(regs));
        current->thread.trap_nr = (regs->cp0_cause >> 2) & 0x1f;
        if (get_isa16_mode(regs->cp0_epc)) {
                u16 instr[2];
@@ -1097,7 +1102,8 @@ asmlinkage void do_bp(struct pt_regs *regs)
        do_trap_or_bp(regs, bcode, TRAP_BRKPT, "Break");
 
 out:
-       exception_exit(prev_state);
+       local_irq_disable();
+       irqentry_exit(regs, state);
        return;
 
 out_sigsegv:
@@ -1105,15 +1111,17 @@ asmlinkage void do_bp(struct pt_regs *regs)
        goto out;
 }
 
-asmlinkage void do_tr(struct pt_regs *regs)
+asmlinkage void noinstr do_tr(struct pt_regs *regs)
 {
+       irqentry_state_t state = irqentry_enter(regs);
+       bool user = user_mode(regs);
        u32 opcode, tcode = 0;
-       enum ctx_state prev_state;
+       unsigned long epc;
        u16 instr[2];
-       bool user = user_mode(regs);
-       unsigned long epc = msk_isa16_mode(exception_epc(regs));
 
-       prev_state = exception_enter();
+       local_irq_enable();
+
+       epc = msk_isa16_mode(exception_epc(regs));
        current->thread.trap_nr = (regs->cp0_cause >> 2) & 0x1f;
        if (get_isa16_mode(regs->cp0_epc)) {
                if (__get_inst16(&instr[0], (u16 *)(epc + 0), user) ||
@@ -1134,7 +1142,8 @@ asmlinkage void do_tr(struct pt_regs *regs)
        do_trap_or_bp(regs, tcode, 0, "Trap");
 
 out:
-       exception_exit(prev_state);
+       local_irq_disable();
+       irqentry_exit(regs, state);
        return;
 
 out_sigsegv:
@@ -1142,15 +1151,19 @@ asmlinkage void do_tr(struct pt_regs *regs)
        goto out;
 }
 
-asmlinkage void do_ri(struct pt_regs *regs)
+asmlinkage void noinstr do_ri(struct pt_regs *regs)
 {
-       unsigned int __user *epc = (unsigned int __user *)exception_epc(regs);
+       irqentry_state_t state = irqentry_enter(regs);
        unsigned long old_epc = regs->cp0_epc;
        unsigned long old31 = regs->regs[31];
-       enum ctx_state prev_state;
+       unsigned int __user *epc;
        unsigned int opcode = 0;
        int status = -1;
 
+       local_irq_enable();
+
+       epc = (unsigned int __user *)exception_epc(regs);
+
        /*
         * Avoid any kernel code. Just emulate the R2 instruction
         * as quickly as possible.
@@ -1177,7 +1190,6 @@ asmlinkage void do_ri(struct pt_regs *regs)
 
 no_r2_instr:
 
-       prev_state = exception_enter();
        current->thread.trap_nr = (regs->cp0_cause >> 2) & 0x1f;
 
        if (notify_die(DIE_RI, "RI Fault", regs, 0, current->thread.trap_nr,
@@ -1233,7 +1245,8 @@ asmlinkage void do_ri(struct pt_regs *regs)
        }
 
 out:
-       exception_exit(prev_state);
+       local_irq_disable();
+       irqentry_exit(regs, state);
 }
 
 /*
@@ -1393,16 +1406,17 @@ static int enable_restore_fp_context(int msa)
 
 #endif /* CONFIG_MIPS_FP_SUPPORT */
 
-asmlinkage void do_cpu(struct pt_regs *regs)
+asmlinkage void noinstr do_cpu(struct pt_regs *regs)
 {
-       enum ctx_state prev_state;
+       irqentry_state_t state = irqentry_enter(regs);
        unsigned int __user *epc;
        unsigned long old_epc, old31;
        unsigned int opcode;
        unsigned int cpid;
        int status;
 
-       prev_state = exception_enter();
+       local_irq_enable();
+
        cpid = (regs->cp0_cause >> CAUSEB_CE) & 3;
 
        if (cpid != 2)
@@ -1495,14 +1509,14 @@ asmlinkage void do_cpu(struct pt_regs *regs)
                break;
        }
 
-       exception_exit(prev_state);
+       local_irq_disable();
+       irqentry_exit(regs, state);
 }
 
-asmlinkage void do_msa_fpe(struct pt_regs *regs, unsigned int msacsr)
+asmlinkage void noinstr do_msa_fpe(struct pt_regs *regs, unsigned int msacsr)
 {
-       enum ctx_state prev_state;
+       irqentry_state_t state = irqentry_enter(regs);
 
-       prev_state = exception_enter();
        current->thread.trap_nr = (regs->cp0_cause >> 2) & 0x1f;
        if (notify_die(DIE_MSAFP, "MSA FP exception", regs, 0,
                       current->thread.trap_nr, SIGFPE) == NOTIFY_STOP)
@@ -1514,16 +1528,18 @@ asmlinkage void do_msa_fpe(struct pt_regs *regs, unsigned int msacsr)
 
        die_if_kernel("do_msa_fpe invoked from kernel context!", regs);
        force_sig(SIGFPE);
+
 out:
-       exception_exit(prev_state);
+       local_irq_disable();
+       irqentry_exit(regs, state);
 }
 
-asmlinkage void do_msa(struct pt_regs *regs)
+asmlinkage void noinstr do_msa(struct pt_regs *regs)
 {
-       enum ctx_state prev_state;
+       irqentry_state_t state = irqentry_enter(regs);
        int err;
 
-       prev_state = exception_enter();
+       local_irq_enable();
 
        if (!cpu_has_msa || test_thread_flag(TIF_32BIT_FPREGS)) {
                force_sig(SIGILL);
@@ -1535,27 +1551,39 @@ asmlinkage void do_msa(struct pt_regs *regs)
        err = enable_restore_fp_context(1);
        if (err)
                force_sig(SIGILL);
+
 out:
-       exception_exit(prev_state);
+       local_irq_disable();
+       irqentry_exit(regs, state);
 }
 
-asmlinkage void do_mdmx(struct pt_regs *regs)
+asmlinkage void noinstr do_mdmx(struct pt_regs *regs)
 {
-       enum ctx_state prev_state;
+       irqentry_state_t state = irqentry_enter(regs);
+
+       local_irq_enable();
 
-       prev_state = exception_enter();
        force_sig(SIGILL);
-       exception_exit(prev_state);
+
+       local_irq_disable();
+       irqentry_exit(regs, state);
 }
 
 /*
  * Called with interrupts disabled.
  */
-asmlinkage void do_watch(struct pt_regs *regs)
+asmlinkage void noinstr do_watch(struct pt_regs *regs)
 {
-       enum ctx_state prev_state;
+       irqentry_state_t state = irqentry_enter(regs);
+
+#ifndef CONFIG_HARDWARE_WATCHPOINTS
+       /*
+        * For watch, interrupts will be enabled after the watch
+        * registers are read.
+        */
+       local_irq_enable();
+#endif
 
-       prev_state = exception_enter();
        /*
         * Clear WP (bit 22) bit of cause register so we don't loop
         * forever.
@@ -1575,15 +1603,16 @@ asmlinkage void do_watch(struct pt_regs *regs)
                mips_clear_watch_registers();
                local_irq_enable();
        }
-       exception_exit(prev_state);
+
+       local_irq_disable();
+       irqentry_exit(regs, state);
 }
 
-asmlinkage void do_mcheck(struct pt_regs *regs)
+asmlinkage void noinstr do_mcheck(struct pt_regs *regs)
 {
+       irqentry_state_t state = irqentry_enter(regs);
        int multi_match = regs->cp0_status & ST0_TS;
-       enum ctx_state prev_state;
 
-       prev_state = exception_enter();
        show_regs(regs);
 
        if (multi_match) {
@@ -1601,12 +1630,17 @@ asmlinkage void do_mcheck(struct pt_regs *regs)
        panic("Caught Machine Check exception - %scaused by multiple "
              "matching entries in the TLB.",
              (multi_match) ? "" : "not ");
+
+       irqentry_exit(regs, state);
 }
 
-asmlinkage void do_mt(struct pt_regs *regs)
+asmlinkage void noinstr do_mt(struct pt_regs *regs)
 {
+       irqentry_state_t state = irqentry_enter(regs);
        int subcode;
 
+       local_irq_enable();
+
        subcode = (read_vpe_c0_vpecontrol() & VPECONTROL_EXCPT)
                        >> VPECONTROL_EXCPT_SHIFT;
        switch (subcode) {
@@ -1636,19 +1670,33 @@ asmlinkage void do_mt(struct pt_regs *regs)
        die_if_kernel("MIPS MT Thread exception in kernel", regs);
 
        force_sig(SIGILL);
+
+       local_irq_disable();
+       irqentry_exit(regs, state);
 }
 
 
-asmlinkage void do_dsp(struct pt_regs *regs)
+asmlinkage void noinstr do_dsp(struct pt_regs *regs)
 {
+       irqentry_state_t state = irqentry_enter(regs);
+
+       local_irq_enable();
+
        if (cpu_has_dsp)
                panic("Unexpected DSP exception");
 
        force_sig(SIGILL);
+
+       local_irq_disable();
+       irqentry_exit(regs, state);
 }
 
-asmlinkage void do_reserved(struct pt_regs *regs)
+asmlinkage void noinstr do_reserved(struct pt_regs *regs)
 {
+       irqentry_state_t state = irqentry_enter(regs);
+
+       local_irq_enable();
+
        /*
         * Game over - no way to handle this if it ever occurs.  Most probably
         * caused by a new unknown cpu type or after another deadly
@@ -1657,6 +1705,9 @@ asmlinkage void do_reserved(struct pt_regs *regs)
        show_regs(regs);
        panic("Caught reserved exception %ld - should not happen.",
              (regs->cp0_cause & 0x7f) >> 2);
+
+       local_irq_disable();
+       irqentry_exit(regs, state);
 }
 
 static int __initdata l1parity = 1;
@@ -1871,11 +1922,16 @@ asmlinkage void cache_parity_error(void)
        panic("Can't handle the cache error!");
 }
 
-asmlinkage void do_ftlb(void)
+asmlinkage void noinstr do_ftlb(struct pt_regs *regs)
 {
+       irqentry_state_t state = irqentry_enter(regs);
        const int field = 2 * sizeof(unsigned long);
        unsigned int reg_val;
 
+       /* Enable interrupt if enabled in parent context */
+       if (likely(!regs_irqs_disabled(regs)))
+               local_irq_enable();
+
        /* For the moment, report the problem and hang. */
        if ((cpu_has_mips_r2_r6) &&
            (((current_cpu_data.processor_id & 0xff0000) == PRID_COMP_MIPS) ||
@@ -1898,16 +1954,17 @@ asmlinkage void do_ftlb(void)
        }
        /* Just print the cacheerr bits for now */
        cache_parity_error();
+       local_irq_disable();
+       irqentry_exit(regs, state);
 }
 
-asmlinkage void do_gsexc(struct pt_regs *regs, u32 diag1)
+asmlinkage void noinstr do_gsexc(struct pt_regs *regs, u32 diag1)
 {
+       irqentry_state_t state = irqentry_enter(regs);
        u32 exccode = (diag1 & LOONGSON_DIAG1_EXCCODE) >>
                        LOONGSON_DIAG1_EXCCODE_SHIFT;
-       enum ctx_state prev_state;
-
-       prev_state = exception_enter();
 
+       local_irq_enable();
        switch (exccode) {
        case 0x08:
                /* Undocumented exception, will trigger on certain
@@ -1928,7 +1985,30 @@ asmlinkage void do_gsexc(struct pt_regs *regs, u32 diag1)
                panic("Unhandled Loongson exception - GSCause = %08x", diag1);
        }
 
-       exception_exit(prev_state);
+       local_irq_disable();
+       irqentry_exit(regs, state);
+}
+
+asmlinkage void noinstr do_int(struct pt_regs *regs)
+{
+       irqentry_state_t state = irqentry_enter(regs);
+       struct pt_regs *old_regs = set_irq_regs(regs);
+
+       plat_irq_dispatch();
+
+       set_irq_regs(old_regs);
+       irqentry_exit(regs, state);
+}
+
+asmlinkage void noinstr do_vi(struct pt_regs *regs, vi_handler_t handler)
+{
+       irqentry_state_t state = irqentry_enter(regs);
+       struct pt_regs *old_regs = set_irq_regs(regs);
+
+       handler();
+
+       set_irq_regs(old_regs);
+       irqentry_exit(regs, state);
 }
 
 /*
arch/mips/kernel/unaligned.c +11 -8
index df4b708c04a9..fe46016a6afc 100644
@@ -74,6 +74,7 @@
  *      Undo the partial store in this case.
  */
 #include <linux/context_tracking.h>
+#include <linux/entry-common.h>
 #include <linux/mm.h>
 #include <linux/signal.h>
 #include <linux/smp.h>
@@ -1472,12 +1473,15 @@ static void emulate_load_store_MIPS16e(struct pt_regs *regs, void __user * addr)
        force_sig(SIGILL);
 }
 
-asmlinkage void do_ade(struct pt_regs *regs)
+asmlinkage void noinstr do_ade(struct pt_regs *regs)
 {
-       enum ctx_state prev_state;
+       irqentry_state_t state = irqentry_enter(regs);
        unsigned int *pc;
 
-       prev_state = exception_enter();
+       /* Enable interrupt if enabled in parent context */
+       if (likely(!regs_irqs_disabled(regs)))
+               local_irq_enable();
+
        perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS,
                        1, regs, regs->cp0_badvaddr);
        /*
@@ -1530,16 +1534,15 @@ asmlinkage void do_ade(struct pt_regs *regs)
 
        emulate_load_store_insn(regs, (void __user *)regs->cp0_badvaddr, pc);
 
-       return;
+       goto out;
 
 sigbus:
        die_if_kernel("Kernel unaligned instruction access", regs);
        force_sig(SIGBUS);
 
-       /*
-        * XXX On return from the signal handler we should advance the epc
-        */
-       exception_exit(prev_state);
+out:
+       local_irq_disable();
+       irqentry_exit(regs, state);
 }
 
 #ifdef CONFIG_DEBUG_FS
arch/mips/mm/c-octeon.c +15 -0
index ec2ae501539a..e68c9e6c6480 100644
@@ -5,6 +5,7 @@
  *
  * Copyright (C) 2005-2007 Cavium Networks
  */
+#include <linux/entry-common.h>
 #include <linux/export.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
@@ -349,3 +350,17 @@ asmlinkage void cache_parity_error_octeon_non_recoverable(void)
        co_cache_error_call_notifiers(1);
        panic("Can't handle cache error: nested exception");
 }
+
+asmlinkage void noinstr do_cache_err(struct pt_regs *regs)
+{
+       irqentry_state_t state = irqentry_enter(regs);
+
+       /* Enable interrupt if enabled in parent context */
+       if (likely(!regs_irqs_disabled(regs)))
+               local_irq_enable();
+
+       cache_parity_error_octeon_recoverable();
+
+       local_irq_disable();
+       irqentry_exit(regs, state);
+}
arch/mips/mm/cex-oct.S +4 -4
index 9029092aa740..7d39087d208b 100644
@@ -60,11 +60,11 @@
        .set    noat
 
        SAVE_ALL
-       KMODE
-       jal     cache_parity_error_octeon_recoverable
-       nop
-       j       ret_from_exception
+       CLI
+       move    a0, sp
+       jal     do_cache_err
        nop
 
+       RESTORE_ALL_AND_RET
        .set pop
        END(handle_cache_err)
arch/mips/mm/fault.c +9 -3
index e7abda9c013f..e55bd45a596b 100644
@@ -8,6 +8,7 @@
 #include <linux/context_tracking.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
+#include <linux/entry-common.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -327,9 +328,14 @@ static void __kprobes __do_page_fault(struct pt_regs *regs, unsigned long write,
 asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
        unsigned long write, unsigned long address)
 {
-       enum ctx_state prev_state;
+       irqentry_state_t state = irqentry_enter(regs);
+
+       /* Enable interrupt if enabled in parent context */
+       if (likely(!regs_irqs_disabled(regs)))
+               local_irq_enable();
 
-       prev_state = exception_enter();
        __do_page_fault(regs, write, address);
-       exception_exit(prev_state);
+
+       local_irq_disable();
+       irqentry_exit(regs, state);
 }
arch/mips/mm/tlbex-fault.S +5 -3
index 77db401fc620..e16b4aa1fcc4 100644
@@ -15,12 +15,15 @@
        .cfi_signal_frame
        SAVE_ALL docfi=1
        MFC0    a2, CP0_BADVADDR
-       KMODE
+       CLI
        move    a0, sp
        REG_S   a2, PT_BVADDR(sp)
        li      a1, \write
        jal     do_page_fault
-       j       ret_from_exception
+
+       .set    noat
+       RESTORE_ALL_AND_RET
+       .set    at
        END(tlb_do_page_fault_\write)
        .endm
 
--

2.27.0