MIPS: Fix restart of indirect syscalls
authorEd Swierk <eswierk@skyportsystems.com>
Tue, 13 Jan 2015 05:10:30 +0000 (21:10 -0800)
committerRalf Baechle <ralf@linux-mips.org>
Thu, 15 Jan 2015 23:35:45 +0000 (00:35 +0100)
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>
arch/mips/kernel/scall32-o32.S
arch/mips/kernel/scall64-o32.S

index c5bf845c7dd425ba917b9edd508adaa8c122db6b..6e8de80bb4468c82378d3c4af8ef3d08cefd5cf1 100644 (file)
@@ -181,6 +181,7 @@ illegal_syscall:
        sll     t1, t0, 2
        beqz    v0, einval
        lw      t2, sys_call_table(t1)          # syscall routine
+       sw      a0, PT_R2(sp)                   # call routine directly on restart
 
        /* Some syscalls like execve get their arguments from struct pt_regs
           and claim zero arguments in the syscall table. Thus we have to
index 4fdca4fb7943f69777ae9b2058536eeb538398c0..d07b210fbeff3667f49737dbec9d9d30d3f119ed 100644 (file)
@@ -186,6 +186,7 @@ LEAF(sys32_syscall)
        dsll    t1, t0, 3
        beqz    v0, einval
        ld      t2, sys32_call_table(t1)                # syscall routine
+       sd      a0, PT_R2(sp)           # call routine directly on restart
 
        move    a0, a1                  # shift argument registers
        move    a1, a2