* [PATCH 0/2] mips: convert to generic entry
@ 2021-09-07 6:16 FreeFlyingSheep
2021-09-07 6:16 ` [PATCH 1/2] mips: convert syscall " FreeFlyingSheep
2021-09-07 6:16 ` [PATCH 2/2] mips: convert irq " FreeFlyingSheep
0 siblings, 2 replies; 15+ messages in thread
From: FreeFlyingSheep @ 2021-09-07 6:16 UTC (permalink / raw)
To: tsbogend, tglx, peterz, luto, arnd
Cc: Feiyang Chen, linux-mips, linux-arch, chenhuacai, jiaxun.yang,
chris.chenfeiyang
From: Feiyang Chen <chenfeiyang@loongson.cn>
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
--
2.27.0
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 1/2] mips: convert syscall to generic entry
2021-09-07 6:16 [PATCH 0/2] mips: convert to generic entry FreeFlyingSheep
@ 2021-09-07 6:16 ` FreeFlyingSheep
2021-09-07 13:48 ` Jiaxun Yang
2021-09-07 6:16 ` [PATCH 2/2] mips: convert irq " FreeFlyingSheep
1 sibling, 1 reply; 15+ messages in thread
From: FreeFlyingSheep @ 2021-09-07 6:16 UTC (permalink / raw)
To: tsbogend, tglx, peterz, luto, arnd
Cc: Feiyang Chen, linux-mips, linux-arch, chenhuacai, jiaxun.yang,
chris.chenfeiyang, Yanteng Si
From: Feiyang Chen <chenfeiyang@loongson.cn>
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.
Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
---
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
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 0cf31a6cbee1..61aa125aa2da 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -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
diff --git a/arch/mips/include/asm/entry-common.h b/arch/mips/include/asm/entry-common.h
new file mode 100644
index 000000000000..0fe2a098ded9
--- /dev/null
+++ b/arch/mips/include/asm/entry-common.h
@@ -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
diff --git a/arch/mips/include/asm/ptrace.h b/arch/mips/include/asm/ptrace.h
index daf3cf244ea9..1b8f9d2ddc44 100644
--- a/arch/mips/include/asm/ptrace.h
+++ b/arch/mips/include/asm/ptrace.h
@@ -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)
diff --git a/arch/mips/include/asm/sim.h b/arch/mips/include/asm/sim.h
deleted file mode 100644
index 59f31a95facd..000000000000
--- a/arch/mips/include/asm/sim.h
+++ /dev/null
@@ -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 */
diff --git a/arch/mips/include/asm/syscall.h b/arch/mips/include/asm/syscall.h
index 25fa651c937d..02ca0d659428 100644
--- a/arch/mips/include/asm/syscall.h
+++ b/arch/mips/include/asm/syscall.h
@@ -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 */
diff --git a/arch/mips/include/asm/thread_info.h b/arch/mips/include/asm/thread_info.h
index 0b17aaa9e012..5a5237413065 100644
--- a/arch/mips/include/asm/thread_info.h
+++ b/arch/mips/include/asm/thread_info.h
@@ -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
diff --git a/arch/mips/include/uapi/asm/ptrace.h b/arch/mips/include/uapi/asm/ptrace.h
index f3c025445e45..27e2c85398bc 100644
--- a/arch/mips/include/uapi/asm/ptrace.h
+++ b/arch/mips/include/uapi/asm/ptrace.h
@@ -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 */
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index 814b3da30501..44875660f6ae 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -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
diff --git a/arch/mips/kernel/entry.S b/arch/mips/kernel/entry.S
index 4b896f5023ff..1a2aec9dab1b 100644
--- a/arch/mips/kernel/entry.S
+++ b/arch/mips/kernel/entry.S
@@ -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)
diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c
index 6b61be486303..2b4b1fc1ff1b 100644
--- a/arch/mips/kernel/linux32.c
+++ b/arch/mips/kernel/linux32.c
@@ -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>
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index db7c5be1d4a3..04c08e41cfd3 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -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();
-}
diff --git a/arch/mips/kernel/scall.S b/arch/mips/kernel/scall.S
new file mode 100644
index 000000000000..7b35969151de
--- /dev/null
+++ b/arch/mips/kernel/scall.S
@@ -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 */
diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S
deleted file mode 100644
index b1b2e106f711..000000000000
--- a/arch/mips/kernel/scall32-o32.S
+++ /dev/null
@@ -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 <ralf@linux-mips.org>
- * 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>
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
deleted file mode 100644
index f650c55a17dc..000000000000
--- a/arch/mips/kernel/scall64-n32.S
+++ /dev/null
@@ -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>
diff --git a/arch/mips/kernel/scall64-n64.S b/arch/mips/kernel/scall64-n64.S
deleted file mode 100644
index 5d7bfc65e4d0..000000000000
--- a/arch/mips/kernel/scall64-n64.S
+++ /dev/null
@@ -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>
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
deleted file mode 100644
index cedc8bd88804..000000000000
--- a/arch/mips/kernel/scall64-o32.S
+++ /dev/null
@@ -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>
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c
index f1e985109da0..1ec6a0cf1163 100644
--- a/arch/mips/kernel/signal.c
+++ b/arch/mips/kernel/signal.c
@@ -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);
diff --git a/arch/mips/kernel/signal_n32.c b/arch/mips/kernel/signal_n32.c
index 7bd00fad61af..b52b995a8a9b 100644
--- a/arch/mips/kernel/signal_n32.c
+++ b/arch/mips/kernel/signal_n32.c
@@ -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,
diff --git a/arch/mips/kernel/signal_o32.c b/arch/mips/kernel/signal_o32.c
index 299a7a28ca33..9245806e06f1 100644
--- a/arch/mips/kernel/signal_o32.c
+++ b/arch/mips/kernel/signal_o32.c
@@ -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;
}
diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c
index 2afa3eef486a..6dc78648b274 100644
--- a/arch/mips/kernel/syscall.c
+++ b/arch/mips/kernel/syscall.c
@@ -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);
+}
diff --git a/arch/mips/kernel/syscalls/syscall_n32.tbl b/arch/mips/kernel/syscalls/syscall_n32.tbl
index 70e32de2bcaa..d9ae765e51f1 100644
--- a/arch/mips/kernel/syscalls/syscall_n32.tbl
+++ b/arch/mips/kernel/syscalls/syscall_n32.tbl
@@ -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
diff --git a/arch/mips/kernel/syscalls/syscall_n64.tbl b/arch/mips/kernel/syscalls/syscall_n64.tbl
index 1ca7bc337932..edec3e82d67a 100644
--- a/arch/mips/kernel/syscalls/syscall_n64.tbl
+++ b/arch/mips/kernel/syscalls/syscall_n64.tbl
@@ -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
diff --git a/arch/mips/kernel/syscalls/syscall_o32.tbl b/arch/mips/kernel/syscalls/syscall_o32.tbl
index a61c35edaa74..89a1f267da6a 100644
--- a/arch/mips/kernel/syscalls/syscall_o32.tbl
+++ b/arch/mips/kernel/syscalls/syscall_o32.tbl
@@ -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
--
2.27.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 2/2] mips: convert irq to generic entry
2021-09-07 6:16 [PATCH 0/2] mips: convert to generic entry FreeFlyingSheep
2021-09-07 6:16 ` [PATCH 1/2] mips: convert syscall " FreeFlyingSheep
@ 2021-09-07 6:16 ` FreeFlyingSheep
2021-09-08 7:17 ` Huacai Chen
1 sibling, 1 reply; 15+ messages in thread
From: FreeFlyingSheep @ 2021-09-07 6:16 UTC (permalink / raw)
To: tsbogend, tglx, peterz, luto, arnd
Cc: Feiyang Chen, linux-mips, linux-arch, chenhuacai, jiaxun.yang,
chris.chenfeiyang, Yanteng Si
From: Feiyang Chen <chenfeiyang@loongson.cn>
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).
Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
---
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(-)
diff --git a/arch/mips/include/asm/irqflags.h b/arch/mips/include/asm/irqflags.h
index f5b8300f4573..ee7519b0d23f 100644
--- a/arch/mips/include/asm/irqflags.h
+++ b/arch/mips/include/asm/irqflags.h
@@ -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 */
diff --git a/arch/mips/include/asm/stackframe.h b/arch/mips/include/asm/stackframe.h
index aa430a6c68b2..8bc74d7950fb 100644
--- a/arch/mips/include/asm/stackframe.h
+++ b/arch/mips/include/asm/stackframe.h
@@ -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
diff --git a/arch/mips/kernel/entry.S b/arch/mips/kernel/entry.S
index 1a2aec9dab1b..c9148831d820 100644
--- a/arch/mips/kernel/entry.S
+++ b/arch/mips/kernel/entry.S
@@ -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)
diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
index 743d75927b71..60e288d307ff 100644
--- a/arch/mips/kernel/genex.S
+++ b/arch/mips/kernel/genex.S
@@ -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
diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S
index b825ed4476c7..5f028dbd5961 100644
--- a/arch/mips/kernel/head.S
+++ b/arch/mips/kernel/head.S
@@ -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>
diff --git a/arch/mips/kernel/r4k-bugs64.c b/arch/mips/kernel/r4k-bugs64.c
index 35729c9e6cfa..0384b649877c 100644
--- a/arch/mips/kernel/r4k-bugs64.c
+++ b/arch/mips/kernel/r4k-bugs64.c
@@ -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)
diff --git a/arch/mips/kernel/scall.S b/arch/mips/kernel/scall.S
index 7b35969151de..3bd955ce5462 100644
--- a/arch/mips/kernel/scall.S
+++ b/arch/mips/kernel/scall.S
@@ -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)
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c
index 1ec6a0cf1163..dbcfbaf03558 100644
--- a/arch/mips/kernel/signal.c
+++ b/arch/mips/kernel/signal.c
@@ -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)
{
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 6f07362de5ce..69290e67dd68 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -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);
}
/*
diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c
index df4b708c04a9..fe46016a6afc 100644
--- a/arch/mips/kernel/unaligned.c
+++ b/arch/mips/kernel/unaligned.c
@@ -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
diff --git a/arch/mips/mm/c-octeon.c b/arch/mips/mm/c-octeon.c
index ec2ae501539a..e68c9e6c6480 100644
--- a/arch/mips/mm/c-octeon.c
+++ b/arch/mips/mm/c-octeon.c
@@ -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);
+}
diff --git a/arch/mips/mm/cex-oct.S b/arch/mips/mm/cex-oct.S
index 9029092aa740..7d39087d208b 100644
--- a/arch/mips/mm/cex-oct.S
+++ b/arch/mips/mm/cex-oct.S
@@ -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)
diff --git a/arch/mips/mm/fault.c b/arch/mips/mm/fault.c
index e7abda9c013f..e55bd45a596b 100644
--- a/arch/mips/mm/fault.c
+++ b/arch/mips/mm/fault.c
@@ -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);
}
diff --git a/arch/mips/mm/tlbex-fault.S b/arch/mips/mm/tlbex-fault.S
index 77db401fc620..e16b4aa1fcc4 100644
--- a/arch/mips/mm/tlbex-fault.S
+++ b/arch/mips/mm/tlbex-fault.S
@@ -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
^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH 1/2] mips: convert syscall to generic entry
2021-09-07 6:16 ` [PATCH 1/2] mips: convert syscall " FreeFlyingSheep
@ 2021-09-07 13:48 ` Jiaxun Yang
2021-09-08 2:08 ` 陈飞扬
0 siblings, 1 reply; 15+ messages in thread
From: Jiaxun Yang @ 2021-09-07 13:48 UTC (permalink / raw)
To: FreeFlyingSheep, tsbogend, tglx, peterz, luto, arnd
Cc: Feiyang Chen, linux-mips, linux-arch, chenhuacai, Yanteng Si
在 2021/9/7 14:16, FreeFlyingSheep 写道:
> From: Feiyang Chen <chenfeiyang@loongson.cn>
>
> 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.
Hmm, that would give us overhead of register context on these syscalls.
I guess it's worthy?
>
> Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
> Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
For the code,
Reviewed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
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
> ---
> 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
>
> diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
> index 0cf31a6cbee1..61aa125aa2da 100644
> --- a/arch/mips/Kconfig
> +++ b/arch/mips/Kconfig
> @@ -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
> diff --git a/arch/mips/include/asm/entry-common.h b/arch/mips/include/asm/entry-common.h
> new file mode 100644
> index 000000000000..0fe2a098ded9
> --- /dev/null
> +++ b/arch/mips/include/asm/entry-common.h
> @@ -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
> diff --git a/arch/mips/include/asm/ptrace.h b/arch/mips/include/asm/ptrace.h
> index daf3cf244ea9..1b8f9d2ddc44 100644
> --- a/arch/mips/include/asm/ptrace.h
> +++ b/arch/mips/include/asm/ptrace.h
> @@ -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)
> diff --git a/arch/mips/include/asm/sim.h b/arch/mips/include/asm/sim.h
> deleted file mode 100644
> index 59f31a95facd..000000000000
> --- a/arch/mips/include/asm/sim.h
> +++ /dev/null
> @@ -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 */
> diff --git a/arch/mips/include/asm/syscall.h b/arch/mips/include/asm/syscall.h
> index 25fa651c937d..02ca0d659428 100644
> --- a/arch/mips/include/asm/syscall.h
> +++ b/arch/mips/include/asm/syscall.h
> @@ -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 */
> diff --git a/arch/mips/include/asm/thread_info.h b/arch/mips/include/asm/thread_info.h
> index 0b17aaa9e012..5a5237413065 100644
> --- a/arch/mips/include/asm/thread_info.h
> +++ b/arch/mips/include/asm/thread_info.h
> @@ -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
> diff --git a/arch/mips/include/uapi/asm/ptrace.h b/arch/mips/include/uapi/asm/ptrace.h
> index f3c025445e45..27e2c85398bc 100644
> --- a/arch/mips/include/uapi/asm/ptrace.h
> +++ b/arch/mips/include/uapi/asm/ptrace.h
> @@ -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 */
> diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
> index 814b3da30501..44875660f6ae 100644
> --- a/arch/mips/kernel/Makefile
> +++ b/arch/mips/kernel/Makefile
> @@ -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
> diff --git a/arch/mips/kernel/entry.S b/arch/mips/kernel/entry.S
> index 4b896f5023ff..1a2aec9dab1b 100644
> --- a/arch/mips/kernel/entry.S
> +++ b/arch/mips/kernel/entry.S
> @@ -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)
>
> diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c
> index 6b61be486303..2b4b1fc1ff1b 100644
> --- a/arch/mips/kernel/linux32.c
> +++ b/arch/mips/kernel/linux32.c
> @@ -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>
> diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
> index db7c5be1d4a3..04c08e41cfd3 100644
> --- a/arch/mips/kernel/ptrace.c
> +++ b/arch/mips/kernel/ptrace.c
> @@ -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();
> -}
> diff --git a/arch/mips/kernel/scall.S b/arch/mips/kernel/scall.S
> new file mode 100644
> index 000000000000..7b35969151de
> --- /dev/null
> +++ b/arch/mips/kernel/scall.S
> @@ -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 */
> diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S
> deleted file mode 100644
> index b1b2e106f711..000000000000
> --- a/arch/mips/kernel/scall32-o32.S
> +++ /dev/null
> @@ -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 <ralf@linux-mips.org>
> - * 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>
> diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
> deleted file mode 100644
> index f650c55a17dc..000000000000
> --- a/arch/mips/kernel/scall64-n32.S
> +++ /dev/null
> @@ -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>
> diff --git a/arch/mips/kernel/scall64-n64.S b/arch/mips/kernel/scall64-n64.S
> deleted file mode 100644
> index 5d7bfc65e4d0..000000000000
> --- a/arch/mips/kernel/scall64-n64.S
> +++ /dev/null
> @@ -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>
> diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
> deleted file mode 100644
> index cedc8bd88804..000000000000
> --- a/arch/mips/kernel/scall64-o32.S
> +++ /dev/null
> @@ -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>
> diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c
> index f1e985109da0..1ec6a0cf1163 100644
> --- a/arch/mips/kernel/signal.c
> +++ b/arch/mips/kernel/signal.c
> @@ -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);
> diff --git a/arch/mips/kernel/signal_n32.c b/arch/mips/kernel/signal_n32.c
> index 7bd00fad61af..b52b995a8a9b 100644
> --- a/arch/mips/kernel/signal_n32.c
> +++ b/arch/mips/kernel/signal_n32.c
> @@ -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,
> diff --git a/arch/mips/kernel/signal_o32.c b/arch/mips/kernel/signal_o32.c
> index 299a7a28ca33..9245806e06f1 100644
> --- a/arch/mips/kernel/signal_o32.c
> +++ b/arch/mips/kernel/signal_o32.c
> @@ -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;
> }
> diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c
> index 2afa3eef486a..6dc78648b274 100644
> --- a/arch/mips/kernel/syscall.c
> +++ b/arch/mips/kernel/syscall.c
> @@ -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);
> +}
> diff --git a/arch/mips/kernel/syscalls/syscall_n32.tbl b/arch/mips/kernel/syscalls/syscall_n32.tbl
> index 70e32de2bcaa..d9ae765e51f1 100644
> --- a/arch/mips/kernel/syscalls/syscall_n32.tbl
> +++ b/arch/mips/kernel/syscalls/syscall_n32.tbl
> @@ -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
> diff --git a/arch/mips/kernel/syscalls/syscall_n64.tbl b/arch/mips/kernel/syscalls/syscall_n64.tbl
> index 1ca7bc337932..edec3e82d67a 100644
> --- a/arch/mips/kernel/syscalls/syscall_n64.tbl
> +++ b/arch/mips/kernel/syscalls/syscall_n64.tbl
> @@ -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
> diff --git a/arch/mips/kernel/syscalls/syscall_o32.tbl b/arch/mips/kernel/syscalls/syscall_o32.tbl
> index a61c35edaa74..89a1f267da6a 100644
> --- a/arch/mips/kernel/syscalls/syscall_o32.tbl
> +++ b/arch/mips/kernel/syscalls/syscall_o32.tbl
> @@ -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
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/2] mips: convert syscall to generic entry
2021-09-07 13:48 ` Jiaxun Yang
@ 2021-09-08 2:08 ` 陈飞扬
2021-09-08 7:15 ` Huacai Chen
2021-09-08 8:51 ` Thomas Bogendoerfer
0 siblings, 2 replies; 15+ messages in thread
From: 陈飞扬 @ 2021-09-08 2:08 UTC (permalink / raw)
To: Jiaxun Yang
Cc: tsbogend, tglx, peterz, luto, arnd, Feiyang Chen, linux-mips,
linux-arch, chenhuacai, Yanteng Si
On Tue, 7 Sept 2021 at 21:49, Jiaxun Yang <jiaxun.yang@flygoat.com> wrote:
>
>
> 在 2021/9/7 14:16, FreeFlyingSheep 写道:
> > From: Feiyang Chen <chenfeiyang@loongson.cn>
> >
> > 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.
>
> 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.
> >
> > Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
> > Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
>
> For the code,
>
> Reviewed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
>
> 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
> Thanks.
>
> Jiaxun
>
> > ---
> > 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
> >
> > diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
> > index 0cf31a6cbee1..61aa125aa2da 100644
> > --- a/arch/mips/Kconfig
> > +++ b/arch/mips/Kconfig
> > @@ -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
> > diff --git a/arch/mips/include/asm/entry-common.h b/arch/mips/include/asm/entry-common.h
> > new file mode 100644
> > index 000000000000..0fe2a098ded9
> > --- /dev/null
> > +++ b/arch/mips/include/asm/entry-common.h
> > @@ -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
> > diff --git a/arch/mips/include/asm/ptrace.h b/arch/mips/include/asm/ptrace.h
> > index daf3cf244ea9..1b8f9d2ddc44 100644
> > --- a/arch/mips/include/asm/ptrace.h
> > +++ b/arch/mips/include/asm/ptrace.h
> > @@ -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)
> > diff --git a/arch/mips/include/asm/sim.h b/arch/mips/include/asm/sim.h
> > deleted file mode 100644
> > index 59f31a95facd..000000000000
> > --- a/arch/mips/include/asm/sim.h
> > +++ /dev/null
> > @@ -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 */
> > diff --git a/arch/mips/include/asm/syscall.h b/arch/mips/include/asm/syscall.h
> > index 25fa651c937d..02ca0d659428 100644
> > --- a/arch/mips/include/asm/syscall.h
> > +++ b/arch/mips/include/asm/syscall.h
> > @@ -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 */
> > diff --git a/arch/mips/include/asm/thread_info.h b/arch/mips/include/asm/thread_info.h
> > index 0b17aaa9e012..5a5237413065 100644
> > --- a/arch/mips/include/asm/thread_info.h
> > +++ b/arch/mips/include/asm/thread_info.h
> > @@ -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
> > diff --git a/arch/mips/include/uapi/asm/ptrace.h b/arch/mips/include/uapi/asm/ptrace.h
> > index f3c025445e45..27e2c85398bc 100644
> > --- a/arch/mips/include/uapi/asm/ptrace.h
> > +++ b/arch/mips/include/uapi/asm/ptrace.h
> > @@ -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 */
> > diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
> > index 814b3da30501..44875660f6ae 100644
> > --- a/arch/mips/kernel/Makefile
> > +++ b/arch/mips/kernel/Makefile
> > @@ -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
> > diff --git a/arch/mips/kernel/entry.S b/arch/mips/kernel/entry.S
> > index 4b896f5023ff..1a2aec9dab1b 100644
> > --- a/arch/mips/kernel/entry.S
> > +++ b/arch/mips/kernel/entry.S
> > @@ -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)
> >
> > diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c
> > index 6b61be486303..2b4b1fc1ff1b 100644
> > --- a/arch/mips/kernel/linux32.c
> > +++ b/arch/mips/kernel/linux32.c
> > @@ -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>
> > diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
> > index db7c5be1d4a3..04c08e41cfd3 100644
> > --- a/arch/mips/kernel/ptrace.c
> > +++ b/arch/mips/kernel/ptrace.c
> > @@ -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();
> > -}
> > diff --git a/arch/mips/kernel/scall.S b/arch/mips/kernel/scall.S
> > new file mode 100644
> > index 000000000000..7b35969151de
> > --- /dev/null
> > +++ b/arch/mips/kernel/scall.S
> > @@ -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 */
> > diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S
> > deleted file mode 100644
> > index b1b2e106f711..000000000000
> > --- a/arch/mips/kernel/scall32-o32.S
> > +++ /dev/null
> > @@ -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 <ralf@linux-mips.org>
> > - * 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>
> > diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
> > deleted file mode 100644
> > index f650c55a17dc..000000000000
> > --- a/arch/mips/kernel/scall64-n32.S
> > +++ /dev/null
> > @@ -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>
> > diff --git a/arch/mips/kernel/scall64-n64.S b/arch/mips/kernel/scall64-n64.S
> > deleted file mode 100644
> > index 5d7bfc65e4d0..000000000000
> > --- a/arch/mips/kernel/scall64-n64.S
> > +++ /dev/null
> > @@ -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>
> > diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
> > deleted file mode 100644
> > index cedc8bd88804..000000000000
> > --- a/arch/mips/kernel/scall64-o32.S
> > +++ /dev/null
> > @@ -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>
> > diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c
> > index f1e985109da0..1ec6a0cf1163 100644
> > --- a/arch/mips/kernel/signal.c
> > +++ b/arch/mips/kernel/signal.c
> > @@ -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);
> > diff --git a/arch/mips/kernel/signal_n32.c b/arch/mips/kernel/signal_n32.c
> > index 7bd00fad61af..b52b995a8a9b 100644
> > --- a/arch/mips/kernel/signal_n32.c
> > +++ b/arch/mips/kernel/signal_n32.c
> > @@ -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,
> > diff --git a/arch/mips/kernel/signal_o32.c b/arch/mips/kernel/signal_o32.c
> > index 299a7a28ca33..9245806e06f1 100644
> > --- a/arch/mips/kernel/signal_o32.c
> > +++ b/arch/mips/kernel/signal_o32.c
> > @@ -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;
> > }
> > diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c
> > index 2afa3eef486a..6dc78648b274 100644
> > --- a/arch/mips/kernel/syscall.c
> > +++ b/arch/mips/kernel/syscall.c
> > @@ -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);
> > +}
> > diff --git a/arch/mips/kernel/syscalls/syscall_n32.tbl b/arch/mips/kernel/syscalls/syscall_n32.tbl
> > index 70e32de2bcaa..d9ae765e51f1 100644
> > --- a/arch/mips/kernel/syscalls/syscall_n32.tbl
> > +++ b/arch/mips/kernel/syscalls/syscall_n32.tbl
> > @@ -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
> > diff --git a/arch/mips/kernel/syscalls/syscall_n64.tbl b/arch/mips/kernel/syscalls/syscall_n64.tbl
> > index 1ca7bc337932..edec3e82d67a 100644
> > --- a/arch/mips/kernel/syscalls/syscall_n64.tbl
> > +++ b/arch/mips/kernel/syscalls/syscall_n64.tbl
> > @@ -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
> > diff --git a/arch/mips/kernel/syscalls/syscall_o32.tbl b/arch/mips/kernel/syscalls/syscall_o32.tbl
> > index a61c35edaa74..89a1f267da6a 100644
> > --- a/arch/mips/kernel/syscalls/syscall_o32.tbl
> > +++ b/arch/mips/kernel/syscalls/syscall_o32.tbl
> > @@ -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
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/2] mips: convert syscall to generic entry
2021-09-08 2:08 ` 陈飞扬
@ 2021-09-08 7:15 ` Huacai Chen
2021-09-08 8:51 ` Thomas Bogendoerfer
1 sibling, 0 replies; 15+ messages in thread
From: Huacai Chen @ 2021-09-08 7:15 UTC (permalink / raw)
To: 陈飞扬
Cc: Jiaxun Yang, Thomas Bogendoerfer, Thomas Gleixner,
Peter Zijlstra, Andy Lutomirski, Arnd Bergmann, Feiyang Chen,
open list:MIPS, linux-arch, Yanteng Si
Reviewed-by: Huacai Chen <chenhuacai@kernel.org>
On Wed, Sep 8, 2021 at 10:08 AM 陈飞扬 <chris.chenfeiyang@gmail.com> wrote:
>
> On Tue, 7 Sept 2021 at 21:49, Jiaxun Yang <jiaxun.yang@flygoat.com> wrote:
> >
> >
> > 在 2021/9/7 14:16, FreeFlyingSheep 写道:
> > > From: Feiyang Chen <chenfeiyang@loongson.cn>
> > >
> > > 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.
> >
> > 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.
>
> > >
> > > Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
> > > Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
> >
> > For the code,
> >
> > Reviewed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> >
> > 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
>
> > Thanks.
> >
> > Jiaxun
> >
> > > ---
> > > 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
> > >
> > > diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
> > > index 0cf31a6cbee1..61aa125aa2da 100644
> > > --- a/arch/mips/Kconfig
> > > +++ b/arch/mips/Kconfig
> > > @@ -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
> > > diff --git a/arch/mips/include/asm/entry-common.h b/arch/mips/include/asm/entry-common.h
> > > new file mode 100644
> > > index 000000000000..0fe2a098ded9
> > > --- /dev/null
> > > +++ b/arch/mips/include/asm/entry-common.h
> > > @@ -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
> > > diff --git a/arch/mips/include/asm/ptrace.h b/arch/mips/include/asm/ptrace.h
> > > index daf3cf244ea9..1b8f9d2ddc44 100644
> > > --- a/arch/mips/include/asm/ptrace.h
> > > +++ b/arch/mips/include/asm/ptrace.h
> > > @@ -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)
> > > diff --git a/arch/mips/include/asm/sim.h b/arch/mips/include/asm/sim.h
> > > deleted file mode 100644
> > > index 59f31a95facd..000000000000
> > > --- a/arch/mips/include/asm/sim.h
> > > +++ /dev/null
> > > @@ -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 */
> > > diff --git a/arch/mips/include/asm/syscall.h b/arch/mips/include/asm/syscall.h
> > > index 25fa651c937d..02ca0d659428 100644
> > > --- a/arch/mips/include/asm/syscall.h
> > > +++ b/arch/mips/include/asm/syscall.h
> > > @@ -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 */
> > > diff --git a/arch/mips/include/asm/thread_info.h b/arch/mips/include/asm/thread_info.h
> > > index 0b17aaa9e012..5a5237413065 100644
> > > --- a/arch/mips/include/asm/thread_info.h
> > > +++ b/arch/mips/include/asm/thread_info.h
> > > @@ -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
> > > diff --git a/arch/mips/include/uapi/asm/ptrace.h b/arch/mips/include/uapi/asm/ptrace.h
> > > index f3c025445e45..27e2c85398bc 100644
> > > --- a/arch/mips/include/uapi/asm/ptrace.h
> > > +++ b/arch/mips/include/uapi/asm/ptrace.h
> > > @@ -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 */
> > > diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
> > > index 814b3da30501..44875660f6ae 100644
> > > --- a/arch/mips/kernel/Makefile
> > > +++ b/arch/mips/kernel/Makefile
> > > @@ -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
> > > diff --git a/arch/mips/kernel/entry.S b/arch/mips/kernel/entry.S
> > > index 4b896f5023ff..1a2aec9dab1b 100644
> > > --- a/arch/mips/kernel/entry.S
> > > +++ b/arch/mips/kernel/entry.S
> > > @@ -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)
> > >
> > > diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c
> > > index 6b61be486303..2b4b1fc1ff1b 100644
> > > --- a/arch/mips/kernel/linux32.c
> > > +++ b/arch/mips/kernel/linux32.c
> > > @@ -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>
> > > diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
> > > index db7c5be1d4a3..04c08e41cfd3 100644
> > > --- a/arch/mips/kernel/ptrace.c
> > > +++ b/arch/mips/kernel/ptrace.c
> > > @@ -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();
> > > -}
> > > diff --git a/arch/mips/kernel/scall.S b/arch/mips/kernel/scall.S
> > > new file mode 100644
> > > index 000000000000..7b35969151de
> > > --- /dev/null
> > > +++ b/arch/mips/kernel/scall.S
> > > @@ -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 */
> > > diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S
> > > deleted file mode 100644
> > > index b1b2e106f711..000000000000
> > > --- a/arch/mips/kernel/scall32-o32.S
> > > +++ /dev/null
> > > @@ -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 <ralf@linux-mips.org>
> > > - * 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>
> > > diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
> > > deleted file mode 100644
> > > index f650c55a17dc..000000000000
> > > --- a/arch/mips/kernel/scall64-n32.S
> > > +++ /dev/null
> > > @@ -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>
> > > diff --git a/arch/mips/kernel/scall64-n64.S b/arch/mips/kernel/scall64-n64.S
> > > deleted file mode 100644
> > > index 5d7bfc65e4d0..000000000000
> > > --- a/arch/mips/kernel/scall64-n64.S
> > > +++ /dev/null
> > > @@ -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>
> > > diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
> > > deleted file mode 100644
> > > index cedc8bd88804..000000000000
> > > --- a/arch/mips/kernel/scall64-o32.S
> > > +++ /dev/null
> > > @@ -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>
> > > diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c
> > > index f1e985109da0..1ec6a0cf1163 100644
> > > --- a/arch/mips/kernel/signal.c
> > > +++ b/arch/mips/kernel/signal.c
> > > @@ -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);
> > > diff --git a/arch/mips/kernel/signal_n32.c b/arch/mips/kernel/signal_n32.c
> > > index 7bd00fad61af..b52b995a8a9b 100644
> > > --- a/arch/mips/kernel/signal_n32.c
> > > +++ b/arch/mips/kernel/signal_n32.c
> > > @@ -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,
> > > diff --git a/arch/mips/kernel/signal_o32.c b/arch/mips/kernel/signal_o32.c
> > > index 299a7a28ca33..9245806e06f1 100644
> > > --- a/arch/mips/kernel/signal_o32.c
> > > +++ b/arch/mips/kernel/signal_o32.c
> > > @@ -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;
> > > }
> > > diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c
> > > index 2afa3eef486a..6dc78648b274 100644
> > > --- a/arch/mips/kernel/syscall.c
> > > +++ b/arch/mips/kernel/syscall.c
> > > @@ -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);
> > > +}
> > > diff --git a/arch/mips/kernel/syscalls/syscall_n32.tbl b/arch/mips/kernel/syscalls/syscall_n32.tbl
> > > index 70e32de2bcaa..d9ae765e51f1 100644
> > > --- a/arch/mips/kernel/syscalls/syscall_n32.tbl
> > > +++ b/arch/mips/kernel/syscalls/syscall_n32.tbl
> > > @@ -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
> > > diff --git a/arch/mips/kernel/syscalls/syscall_n64.tbl b/arch/mips/kernel/syscalls/syscall_n64.tbl
> > > index 1ca7bc337932..edec3e82d67a 100644
> > > --- a/arch/mips/kernel/syscalls/syscall_n64.tbl
> > > +++ b/arch/mips/kernel/syscalls/syscall_n64.tbl
> > > @@ -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
> > > diff --git a/arch/mips/kernel/syscalls/syscall_o32.tbl b/arch/mips/kernel/syscalls/syscall_o32.tbl
> > > index a61c35edaa74..89a1f267da6a 100644
> > > --- a/arch/mips/kernel/syscalls/syscall_o32.tbl
> > > +++ b/arch/mips/kernel/syscalls/syscall_o32.tbl
> > > @@ -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
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 2/2] mips: convert irq to generic entry
2021-09-07 6:16 ` [PATCH 2/2] mips: convert irq " FreeFlyingSheep
@ 2021-09-08 7:17 ` Huacai Chen
0 siblings, 0 replies; 15+ messages in thread
From: Huacai Chen @ 2021-09-08 7:17 UTC (permalink / raw)
To: FreeFlyingSheep
Cc: Thomas Bogendoerfer, Thomas Gleixner, Peter Zijlstra,
Andy Lutomirski, Arnd Bergmann, Feiyang Chen, open list:MIPS,
linux-arch, Jiaxun Yang, Yanteng Si
Reviewed-by: Huacai Chen <chenhuacai@kernel.org>
On Tue, Sep 7, 2021 at 2:17 PM FreeFlyingSheep
<chris.chenfeiyang@gmail.com> wrote:
>
> From: Feiyang Chen <chenfeiyang@loongson.cn>
>
> 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).
>
> Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
> Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
> ---
> 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(-)
>
> diff --git a/arch/mips/include/asm/irqflags.h b/arch/mips/include/asm/irqflags.h
> index f5b8300f4573..ee7519b0d23f 100644
> --- a/arch/mips/include/asm/irqflags.h
> +++ b/arch/mips/include/asm/irqflags.h
> @@ -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 */
> diff --git a/arch/mips/include/asm/stackframe.h b/arch/mips/include/asm/stackframe.h
> index aa430a6c68b2..8bc74d7950fb 100644
> --- a/arch/mips/include/asm/stackframe.h
> +++ b/arch/mips/include/asm/stackframe.h
> @@ -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
> diff --git a/arch/mips/kernel/entry.S b/arch/mips/kernel/entry.S
> index 1a2aec9dab1b..c9148831d820 100644
> --- a/arch/mips/kernel/entry.S
> +++ b/arch/mips/kernel/entry.S
> @@ -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)
>
> diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
> index 743d75927b71..60e288d307ff 100644
> --- a/arch/mips/kernel/genex.S
> +++ b/arch/mips/kernel/genex.S
> @@ -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
> diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S
> index b825ed4476c7..5f028dbd5961 100644
> --- a/arch/mips/kernel/head.S
> +++ b/arch/mips/kernel/head.S
> @@ -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>
> diff --git a/arch/mips/kernel/r4k-bugs64.c b/arch/mips/kernel/r4k-bugs64.c
> index 35729c9e6cfa..0384b649877c 100644
> --- a/arch/mips/kernel/r4k-bugs64.c
> +++ b/arch/mips/kernel/r4k-bugs64.c
> @@ -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)
> diff --git a/arch/mips/kernel/scall.S b/arch/mips/kernel/scall.S
> index 7b35969151de..3bd955ce5462 100644
> --- a/arch/mips/kernel/scall.S
> +++ b/arch/mips/kernel/scall.S
> @@ -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)
>
> diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c
> index 1ec6a0cf1163..dbcfbaf03558 100644
> --- a/arch/mips/kernel/signal.c
> +++ b/arch/mips/kernel/signal.c
> @@ -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)
> {
> diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
> index 6f07362de5ce..69290e67dd68 100644
> --- a/arch/mips/kernel/traps.c
> +++ b/arch/mips/kernel/traps.c
> @@ -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);
> }
>
> /*
> diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c
> index df4b708c04a9..fe46016a6afc 100644
> --- a/arch/mips/kernel/unaligned.c
> +++ b/arch/mips/kernel/unaligned.c
> @@ -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
> diff --git a/arch/mips/mm/c-octeon.c b/arch/mips/mm/c-octeon.c
> index ec2ae501539a..e68c9e6c6480 100644
> --- a/arch/mips/mm/c-octeon.c
> +++ b/arch/mips/mm/c-octeon.c
> @@ -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);
> +}
> diff --git a/arch/mips/mm/cex-oct.S b/arch/mips/mm/cex-oct.S
> index 9029092aa740..7d39087d208b 100644
> --- a/arch/mips/mm/cex-oct.S
> +++ b/arch/mips/mm/cex-oct.S
> @@ -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)
> diff --git a/arch/mips/mm/fault.c b/arch/mips/mm/fault.c
> index e7abda9c013f..e55bd45a596b 100644
> --- a/arch/mips/mm/fault.c
> +++ b/arch/mips/mm/fault.c
> @@ -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);
> }
> diff --git a/arch/mips/mm/tlbex-fault.S b/arch/mips/mm/tlbex-fault.S
> index 77db401fc620..e16b4aa1fcc4 100644
> --- a/arch/mips/mm/tlbex-fault.S
> +++ b/arch/mips/mm/tlbex-fault.S
> @@ -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
>
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/2] mips: convert syscall to generic entry
2021-09-08 2:08 ` 陈飞扬
2021-09-08 7:15 ` Huacai Chen
@ 2021-09-08 8:51 ` Thomas Bogendoerfer
2021-09-08 12:41 ` Jiaxun Yang
` (2 more replies)
1 sibling, 3 replies; 15+ messages in thread
From: Thomas Bogendoerfer @ 2021-09-08 8:51 UTC (permalink / raw)
To: 陈飞扬
Cc: Jiaxun Yang, tglx, peterz, luto, arnd, Feiyang Chen, linux-mips,
linux-arch, chenhuacai, Yanteng Si
On Wed, Sep 08, 2021 at 10:08:47AM +0800, 陈飞扬 wrote:
> On Tue, 7 Sept 2021 at 21:49, Jiaxun Yang <jiaxun.yang@flygoat.com> wrote:
> >
> >
> > 在 2021/9/7 14:16, FreeFlyingSheep 写道:
> > > From: Feiyang Chen <chenfeiyang@loongson.cn>
> > >
> > > 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.
> >
> > 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.
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.
--
Crap can work. Given enough thrust pigs will fly, but it's not necessarily a
good idea. [ RFC1925, 2.3 ]
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/2] mips: convert syscall to generic entry
2021-09-08 8:51 ` Thomas Bogendoerfer
@ 2021-09-08 12:41 ` Jiaxun Yang
2021-09-09 12:45 ` Zhou Yanjie
2021-09-13 1:35 ` teng sterling
2021-09-14 1:30 ` Feiyang Chen
2 siblings, 1 reply; 15+ messages in thread
From: Jiaxun Yang @ 2021-09-08 12:41 UTC (permalink / raw)
To: Thomas Bogendoerfer, 陈飞扬
Cc: tglx, peterz, luto, arnd, Feiyang Chen, linux-mips, linux-arch,
chenhuacai, Yanteng Si, zhouyu
在 2021/9/8 16:51, Thomas Bogendoerfer 写道:
> On Wed, Sep 08, 2021 at 10:08:47AM +0800, 陈飞扬 wrote:
>> On Tue, 7 Sept 2021 at 21:49, Jiaxun Yang <jiaxun.yang@flygoat.com> wrote:
>>>
>>> 在 2021/9/7 14:16, FreeFlyingSheep 写道:
>>>> From: Feiyang Chen <chenfeiyang@loongson.cn>
>>>>
>>>> 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.
>>> 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.
> 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
>
> Thomas.
>
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/2] mips: convert syscall to generic entry
2021-09-08 12:41 ` Jiaxun Yang
@ 2021-09-09 12:45 ` Zhou Yanjie
2021-09-13 2:51 ` Zhou Yanjie
2021-09-13 5:16 ` H. Nikolaus Schaller
0 siblings, 2 replies; 15+ messages in thread
From: Zhou Yanjie @ 2021-09-09 12:45 UTC (permalink / raw)
To: Jiaxun Yang, Thomas Bogendoerfer, 陈飞扬,
Paul Cercueil, H. Nikolaus Schaller
Cc: tglx, peterz, luto, arnd, Feiyang Chen, linux-mips, linux-arch,
chenhuacai, Yanteng Si
Hi,
On 2021/9/8 下午8:41, Jiaxun Yang wrote:
>
> 在 2021/9/8 16:51, Thomas Bogendoerfer 写道:
>> On Wed, Sep 08, 2021 at 10:08:47AM +0800, 陈飞扬 wrote:
>>> On Tue, 7 Sept 2021 at 21:49, Jiaxun Yang <jiaxun.yang@flygoat.com>
>>> wrote:
>>>>
>>>> 在 2021/9/7 14:16, FreeFlyingSheep 写道:
>>>>> From: Feiyang Chen <chenfeiyang@loongson.cn>
>>>>>
>>>>> 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.
>>>> 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.
>> 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!
>
> Thanks.
>
> - Jiaxun
>
>>
>> Thomas.
>>
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/2] mips: convert syscall to generic entry
2021-09-08 8:51 ` Thomas Bogendoerfer
2021-09-08 12:41 ` Jiaxun Yang
@ 2021-09-13 1:35 ` teng sterling
2021-09-14 1:30 ` Feiyang Chen
2 siblings, 0 replies; 15+ messages in thread
From: teng sterling @ 2021-09-13 1:35 UTC (permalink / raw)
To: Thomas Bogendoerfer
Cc: 陈飞扬,
Jiaxun Yang, tglx, peterz, luto, arnd, Feiyang Chen, linux-mips,
linux-arch, Huacai Chen, Yanteng Si
Thomas Bogendoerfer <tsbogend@alpha.franken.de> 于2021年9月8日周三 下午5:36写道:
>
> On Wed, Sep 08, 2021 at 10:08:47AM +0800, 陈飞扬 wrote:
> > On Tue, 7 Sept 2021 at 21:49, Jiaxun Yang <jiaxun.yang@flygoat.com> wrote:
> > >
> > >
> > > 在 2021/9/7 14:16, FreeFlyingSheep 写道:
> > > > From: Feiyang Chen <chenfeiyang@loongson.cn>
> > > >
> > > > 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.
> > >
> > > 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.
>
> 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
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/2] mips: convert syscall to generic entry
2021-09-09 12:45 ` Zhou Yanjie
@ 2021-09-13 2:51 ` Zhou Yanjie
2021-09-13 3:06 ` Zhou Yanjie
2021-09-13 5:16 ` H. Nikolaus Schaller
1 sibling, 1 reply; 15+ messages in thread
From: Zhou Yanjie @ 2021-09-13 2:51 UTC (permalink / raw)
To: Jiaxun Yang, Thomas Bogendoerfer, 陈飞扬,
Paul Cercueil, H. Nikolaus Schaller
Cc: tglx, peterz, luto, arnd, Feiyang Chen, linux-mips, linux-arch,
chenhuacai, Yanteng Si
Hi,
On 2021/9/9 下午8:45, Zhou Yanjie wrote:
> Hi,
>
> On 2021/9/8 下午8:41, Jiaxun Yang wrote:
>>
>> 在 2021/9/8 16:51, Thomas Bogendoerfer 写道:
>>> On Wed, Sep 08, 2021 at 10:08:47AM +0800, 陈飞扬 wrote:
>>>> On Tue, 7 Sept 2021 at 21:49, Jiaxun Yang <jiaxun.yang@flygoat.com>
>>>> wrote:
>>>>>
>>>>> 在 2021/9/7 14:16, FreeFlyingSheep 写道:
>>>>>> From: Feiyang Chen <chenfeiyang@loongson.cn>
>>>>>>
>>>>>> 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.
>>>>> 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.
>>> 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.
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!
>
> + Paul could you help with a run on JZ4760 and JZ4770?
>
> + Nikolaus could you help with a run on JZ4730?
>
>
> Thanks and best regards!
>
>
>>
>> Thanks.
>>
>> - Jiaxun
>>
>>>
>>> Thomas.
>>>
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/2] mips: convert syscall to generic entry
2021-09-13 2:51 ` Zhou Yanjie
@ 2021-09-13 3:06 ` Zhou Yanjie
0 siblings, 0 replies; 15+ messages in thread
From: Zhou Yanjie @ 2021-09-13 3:06 UTC (permalink / raw)
To: Zhou Yanjie, Jiaxun Yang, Thomas Bogendoerfer,
陈飞扬,
Paul Cercueil, H. Nikolaus Schaller
Cc: tglx, peterz, luto, arnd, Feiyang Chen, linux-mips, linux-arch,
chenhuacai, Yanteng Si
On 2021/9/13 上午10:51, Zhou Yanjie wrote:
> Hi,
>
> On 2021/9/9 下午8:45, Zhou Yanjie wrote:
>> Hi,
>>
>> On 2021/9/8 下午8:41, Jiaxun Yang wrote:
>>>
>>> 在 2021/9/8 16:51, Thomas Bogendoerfer 写道:
>>>> On Wed, Sep 08, 2021 at 10:08:47AM +0800, 陈飞扬 wrote:
>>>>> On Tue, 7 Sept 2021 at 21:49, Jiaxun Yang
>>>>> <jiaxun.yang@flygoat.com> wrote:
>>>>>>
>>>>>> 在 2021/9/7 14:16, FreeFlyingSheep 写道:
>>>>>>> From: Feiyang Chen <chenfeiyang@loongson.cn>
>>>>>>>
>>>>>>> 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.
>>>>>> 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.
>>>> 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.
>
>
> 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)
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)
>
>
> On the whole, the impact on performance is quite huge.
>
>
> Thanks and best regards!
>
>
>>
>> + Paul could you help with a run on JZ4760 and JZ4770?
>>
>> + Nikolaus could you help with a run on JZ4730?
>>
>>
>> Thanks and best regards!
>>
>>
>>>
>>> Thanks.
>>>
>>> - Jiaxun
>>>
>>>>
>>>> Thomas.
>>>>
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/2] mips: convert syscall to generic entry
2021-09-09 12:45 ` Zhou Yanjie
2021-09-13 2:51 ` Zhou Yanjie
@ 2021-09-13 5:16 ` H. Nikolaus Schaller
1 sibling, 0 replies; 15+ messages in thread
From: H. Nikolaus Schaller @ 2021-09-13 5:16 UTC (permalink / raw)
To: Zhou Yanjie, Jiaxun Yang, Feiyang Chen, Thomas Bogendoerfer,
陈飞扬
Cc: Paul Cercueil, Thomas Gleixner, peterz, luto, Arnd Bergmann,
linux-mips, linux-arch, Huacai Chen, Yanteng Si
Hi,
> Am 09.09.2021 um 14:45 schrieb Zhou Yanjie <zhouyu@wanyeetech.com>:
>
> Hi,
>
> On 2021/9/8 下午8:41, Jiaxun Yang wrote:
>>
>> 在 2021/9/8 16:51, Thomas Bogendoerfer 写道:
>>> On Wed, Sep 08, 2021 at 10:08:47AM +0800, 陈飞扬 wrote:
>>>> On Tue, 7 Sept 2021 at 21:49, Jiaxun Yang <jiaxun.yang@flygoat.com> wrote:
>>>>>
>>>>> 在 2021/9/7 14:16, FreeFlyingSheep 写道:
>>>>>> From: Feiyang Chen <chenfeiyang@loongson.cn>
>>>>>>
>>>>>> 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.
>>>>> 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.
>>> 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?
Have not observed a negative effect on jz4730. Same for jz4780.
But I have not done performance tests.
BR,
Nikolaus
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/2] mips: convert syscall to generic entry
2021-09-08 8:51 ` Thomas Bogendoerfer
2021-09-08 12:41 ` Jiaxun Yang
2021-09-13 1:35 ` teng sterling
@ 2021-09-14 1:30 ` Feiyang Chen
2 siblings, 0 replies; 15+ messages in thread
From: Feiyang Chen @ 2021-09-14 1:30 UTC (permalink / raw)
To: Thomas Bogendoerfer
Cc: Jiaxun Yang, tglx, peterz, luto, arnd, Feiyang Chen, linux-mips,
linux-arch, chenhuacai, Yanteng Si, Zhou Yanjie,
H. Nikolaus Schaller
On Wed, 8 Sept 2021 at 17:28, Thomas Bogendoerfer
<tsbogend@alpha.franken.de> wrote:
>
> On Wed, Sep 08, 2021 at 10:08:47AM +0800, 陈飞扬 wrote:
> > On Tue, 7 Sept 2021 at 21:49, Jiaxun Yang <jiaxun.yang@flygoat.com> wrote:
> > >
> > >
> > > 在 2021/9/7 14:16, FreeFlyingSheep 写道:
> > > > From: Feiyang Chen <chenfeiyang@loongson.cn>
> > > >
> > > > 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.
> > >
> > > 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.
>
> 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
>
> Thomas.
>
> --
> Crap can work. Given enough thrust pigs will fly, but it's not necessarily a
> good idea. [ RFC1925, 2.3 ]
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2021-09-14 1:30 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-09-07 6:16 [PATCH 0/2] mips: convert to generic entry FreeFlyingSheep
2021-09-07 6:16 ` [PATCH 1/2] mips: convert syscall " FreeFlyingSheep
2021-09-07 13:48 ` Jiaxun Yang
2021-09-08 2:08 ` 陈飞扬
2021-09-08 7:15 ` Huacai Chen
2021-09-08 8:51 ` Thomas Bogendoerfer
2021-09-08 12:41 ` Jiaxun Yang
2021-09-09 12:45 ` Zhou Yanjie
2021-09-13 2:51 ` Zhou Yanjie
2021-09-13 3:06 ` Zhou Yanjie
2021-09-13 5:16 ` H. Nikolaus Schaller
2021-09-13 1:35 ` teng sterling
2021-09-14 1:30 ` Feiyang Chen
2021-09-07 6:16 ` [PATCH 2/2] mips: convert irq " FreeFlyingSheep
2021-09-08 7:17 ` Huacai Chen
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).