Commit e3c7a8d7 authored by Sven Schnelle's avatar Sven Schnelle Committed by Vasily Gorbik

s390: move restart of execve() syscall

On s390, execve might have to be restarted for PGSTE binaries
like kvm. In the past this was done via the PIF_SYSCALL_RESTART
bit. However, with the recent changes, syscalls are now restarted
differently. Now that execve() is the only call that might get
restarted via PIF_SYSCALL_RESTART, move the loop to do_syscall().
This also has the advantage that the restart is no longer visible
to userspace.
Signed-off-by: default avatarSven Schnelle <svens@linux.ibm.com>
Reviewed-by: default avatarHeiko Carstens <hca@linux.ibm.com>
Signed-off-by: default avatarVasily Gorbik <gor@linux.ibm.com>
parent fbf50f47
...@@ -162,6 +162,14 @@ static inline int test_pt_regs_flag(struct pt_regs *regs, int flag) ...@@ -162,6 +162,14 @@ static inline int test_pt_regs_flag(struct pt_regs *regs, int flag)
return !!(regs->flags & (1UL << flag)); return !!(regs->flags & (1UL << flag));
} }
static inline int test_and_clear_pt_regs_flag(struct pt_regs *regs, int flag)
{
int ret = test_pt_regs_flag(regs, flag);
clear_pt_regs_flag(regs, flag);
return ret;
}
/* /*
* These are defined as per linux/ptrace.h, which see. * These are defined as per linux/ptrace.h, which see.
*/ */
......
...@@ -134,13 +134,15 @@ static void do_syscall(struct pt_regs *regs) ...@@ -134,13 +134,15 @@ static void do_syscall(struct pt_regs *regs)
* work, the ptrace code sets PIF_SYSCALL_RET_SET, which is checked here * work, the ptrace code sets PIF_SYSCALL_RET_SET, which is checked here
* and if set, the syscall will be skipped. * and if set, the syscall will be skipped.
*/ */
if (!test_pt_regs_flag(regs, PIF_SYSCALL_RET_SET)) { if (unlikely(test_and_clear_pt_regs_flag(regs, PIF_SYSCALL_RET_SET)))
regs->gprs[2] = -ENOSYS; goto out;
if (likely(nr < NR_syscalls)) regs->gprs[2] = -ENOSYS;
regs->gprs[2] = current->thread.sys_call_table[nr](regs); if (likely(nr >= NR_syscalls))
} else { goto out;
clear_pt_regs_flag(regs, PIF_SYSCALL_RET_SET); do {
} regs->gprs[2] = current->thread.sys_call_table[nr](regs);
} while (test_and_clear_pt_regs_flag(regs, PIF_SYSCALL_RESTART));
out:
syscall_exit_to_user_mode_work(regs); syscall_exit_to_user_mode_work(regs);
} }
...@@ -158,13 +160,8 @@ void noinstr __do_syscall(struct pt_regs *regs, int per_trap) ...@@ -158,13 +160,8 @@ void noinstr __do_syscall(struct pt_regs *regs, int per_trap)
if (per_trap) if (per_trap)
set_thread_flag(TIF_PER_TRAP); set_thread_flag(TIF_PER_TRAP);
for (;;) { regs->flags = 0;
regs->flags = 0; set_pt_regs_flag(regs, PIF_SYSCALL);
set_pt_regs_flag(regs, PIF_SYSCALL); do_syscall(regs);
do_syscall(regs);
if (!test_pt_regs_flag(regs, PIF_SYSCALL_RESTART))
break;
local_irq_enable();
}
exit_to_user_mode(); exit_to_user_mode();
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment