aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorEd Swierk <eswierk@skyportsystems.com>2015-01-13 00:10:30 -0500
committerRalf Baechle <ralf@linux-mips.org>2015-01-15 18:35:45 -0500
commite967ef022e00bb7c2e5b1a42007abfdd52055050 (patch)
tree45fa2dc40061ba9e77af3fd2b7ec8fe074bf7f7d /arch
parentfd75a33e0002d2f850c67c775df47c4d479c20c1 (diff)
MIPS: Fix restart of indirect syscalls
When 32-bit MIPS userspace invokes a syscall indirectly via syscall(number, arg1, ..., arg7), the kernel looks up the actual syscall based on the given number, shifts the other arguments to the left, and jumps to the syscall. If the syscall is interrupted by a signal and indicates it needs to be restarted by the kernel (by returning ERESTARTNOINTR for example), the syscall must be called directly, since the number is no longer the first argument, and the other arguments are now staged for a direct call. Before shifting the arguments, store the syscall number in pt_regs->regs[2]. This gets copied temporarily into pt_regs->regs[0] after the syscall returns. If the syscall needs to be restarted, handle_signal()/do_signal() copies the number back to pt_regs->reg[2], which ends up in $v0 once control returns to userspace. Signed-off-by: Ed Swierk <eswierk@skyportsystems.com> Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/8929/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/mips/kernel/scall32-o32.S1
-rw-r--r--arch/mips/kernel/scall64-o32.S1
2 files changed, 2 insertions, 0 deletions
diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S
index c5bf845c7dd4..6e8de80bb446 100644
--- a/arch/mips/kernel/scall32-o32.S
+++ b/arch/mips/kernel/scall32-o32.S
@@ -181,6 +181,7 @@ illegal_syscall:
181 sll t1, t0, 2 181 sll t1, t0, 2
182 beqz v0, einval 182 beqz v0, einval
183 lw t2, sys_call_table(t1) # syscall routine 183 lw t2, sys_call_table(t1) # syscall routine
184 sw a0, PT_R2(sp) # call routine directly on restart
184 185
185 /* Some syscalls like execve get their arguments from struct pt_regs 186 /* Some syscalls like execve get their arguments from struct pt_regs
186 and claim zero arguments in the syscall table. Thus we have to 187 and claim zero arguments in the syscall table. Thus we have to
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
index 4fdca4fb7943..d07b210fbeff 100644
--- a/arch/mips/kernel/scall64-o32.S
+++ b/arch/mips/kernel/scall64-o32.S
@@ -186,6 +186,7 @@ LEAF(sys32_syscall)
186 dsll t1, t0, 3 186 dsll t1, t0, 3
187 beqz v0, einval 187 beqz v0, einval
188 ld t2, sys32_call_table(t1) # syscall routine 188 ld t2, sys32_call_table(t1) # syscall routine
189 sd a0, PT_R2(sp) # call routine directly on restart
189 190
190 move a0, a1 # shift argument registers 191 move a0, a1 # shift argument registers
191 move a1, a2 192 move a1, a2