summaryrefslogtreecommitdiff
path: root/arch/mips/include/asm/syscall.h
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/include/asm/syscall.h')
-rw-r--r--arch/mips/include/asm/syscall.h67
1 files changed, 47 insertions, 20 deletions
diff --git a/arch/mips/include/asm/syscall.h b/arch/mips/include/asm/syscall.h
index ebdf4d910af2..d19e67e2aa6a 100644
--- a/arch/mips/include/asm/syscall.h
+++ b/arch/mips/include/asm/syscall.h
@@ -41,6 +41,21 @@ static inline long syscall_get_nr(struct task_struct *task,
return task_thread_info(task)->syscall;
}
+static inline void syscall_set_nr(struct task_struct *task,
+ struct pt_regs *regs,
+ int nr)
+{
+ /*
+ * New syscall number has to be assigned to regs[2] because
+ * it is loaded from there unconditionally after return from
+ * syscall_trace_enter() invocation.
+ *
+ * Consequently, if the syscall was indirect and nr != __NR_syscall,
+ * then after this assignment the syscall will cease to be indirect.
+ */
+ task_thread_info(task)->syscall = regs->regs[2] = nr;
+}
+
static inline void mips_syscall_update_nr(struct task_struct *task,
struct pt_regs *regs)
{
@@ -57,37 +72,38 @@ static inline void mips_syscall_update_nr(struct task_struct *task,
static inline void mips_get_syscall_arg(unsigned long *arg,
struct task_struct *task, struct pt_regs *regs, unsigned int n)
{
- unsigned long usp __maybe_unused = regs->regs[29];
-
+#ifdef CONFIG_32BIT
switch (n) {
case 0: case 1: case 2: case 3:
*arg = regs->regs[4 + n];
-
return;
-
-#ifdef CONFIG_32BIT
case 4: case 5: case 6: case 7:
- get_user(*arg, (int *)usp + n);
+ *arg = regs->args[n];
return;
+ }
+#else
+ *arg = regs->regs[4 + n];
+ if ((IS_ENABLED(CONFIG_MIPS32_O32) &&
+ test_tsk_thread_flag(task, TIF_32BIT_REGS)))
+ *arg = (unsigned int)*arg;
#endif
+}
-#ifdef CONFIG_64BIT
+static inline void mips_set_syscall_arg(unsigned long *arg,
+ struct task_struct *task, struct pt_regs *regs, unsigned int n)
+{
+#ifdef CONFIG_32BIT
+ switch (n) {
+ case 0: case 1: case 2: case 3:
+ regs->regs[4 + n] = *arg;
+ return;
case 4: case 5: case 6: case 7:
-#ifdef CONFIG_MIPS32_O32
- if (test_tsk_thread_flag(task, TIF_32BIT_REGS))
- get_user(*arg, (int *)usp + n);
- else
-#endif
- *arg = regs->regs[4 + n];
-
+ *arg = regs->args[n] = *arg;
return;
-#endif
-
- default:
- BUG();
}
-
- unreachable();
+#else
+ regs->regs[4 + n] = *arg;
+#endif
}
static inline long syscall_get_error(struct task_struct *task,
@@ -136,6 +152,17 @@ static inline void syscall_get_arguments(struct task_struct *task,
mips_get_syscall_arg(args++, task, regs, i++);
}
+static inline void syscall_set_arguments(struct task_struct *task,
+ struct pt_regs *regs,
+ unsigned long *args)
+{
+ unsigned int i = 0;
+ unsigned int n = 6;
+
+ while (n--)
+ mips_set_syscall_arg(args++, task, regs, i++);
+}
+
extern const unsigned long sys_call_table[];
extern const unsigned long sys32_call_table[];
extern const unsigned long sysn32_call_table[];