mirror of
https://github.com/torvalds/linux.git
synced 2026-05-30 10:04:04 +02:00
s390/syscall: Merge __do_syscall() and do_syscall()
The compiler inlines do_syscall() into __do_syscall(). Therefore do this in C code as well, since this makes the code easier to understand. Also adjust and add various unlikely() and likely() annotations. Furthermore this allows to replace the separate exit_to_user_mode() and syscall_exit_to_user_mode_work() calls with a combined syscall_exit_to_user_mode() call which results in slightly better code. Acked-by: Vasily Gorbik <gor@linux.ibm.com> Signed-off-by: Heiko Carstens <hca@linux.ibm.com> Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
This commit is contained in:
parent
b46525437e
commit
a0f2a8d051
|
|
@ -82,47 +82,10 @@ SYSCALL_DEFINE0(ni_syscall)
|
|||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static void do_syscall(struct pt_regs *regs)
|
||||
void noinstr __do_syscall(struct pt_regs *regs, int per_trap)
|
||||
{
|
||||
unsigned long nr;
|
||||
|
||||
nr = regs->int_code & 0xffff;
|
||||
if (!nr) {
|
||||
nr = regs->gprs[1] & 0xffff;
|
||||
regs->int_code &= ~0xffffUL;
|
||||
regs->int_code |= nr;
|
||||
}
|
||||
|
||||
regs->gprs[2] = nr;
|
||||
|
||||
if (nr == __NR_restart_syscall && !(current->restart_block.arch_data & 1)) {
|
||||
regs->psw.addr = current->restart_block.arch_data;
|
||||
current->restart_block.arch_data = 1;
|
||||
}
|
||||
nr = syscall_enter_from_user_mode_work(regs, nr);
|
||||
|
||||
/*
|
||||
* In the s390 ptrace ABI, both the syscall number and the return value
|
||||
* use gpr2. However, userspace puts the syscall number either in the
|
||||
* svc instruction itself, or uses gpr1. To make at least skipping syscalls
|
||||
* work, the ptrace code sets PIF_SYSCALL_RET_SET, which is checked here
|
||||
* and if set, the syscall will be skipped.
|
||||
*/
|
||||
|
||||
if (unlikely(test_and_clear_pt_regs_flag(regs, PIF_SYSCALL_RET_SET)))
|
||||
goto out;
|
||||
regs->gprs[2] = -ENOSYS;
|
||||
if (likely(nr >= NR_syscalls))
|
||||
goto out;
|
||||
do {
|
||||
regs->gprs[2] = current->thread.sys_call_table[nr](regs);
|
||||
} while (test_and_clear_pt_regs_flag(regs, PIF_EXECVE_PGSTE_RESTART));
|
||||
out:
|
||||
syscall_exit_to_user_mode_work(regs);
|
||||
}
|
||||
|
||||
void noinstr __do_syscall(struct pt_regs *regs, int per_trap)
|
||||
{
|
||||
add_random_kstack_offset();
|
||||
enter_from_user_mode(regs);
|
||||
regs->psw = get_lowcore()->svc_old_psw;
|
||||
|
|
@ -130,15 +93,39 @@ void noinstr __do_syscall(struct pt_regs *regs, int per_trap)
|
|||
update_timer_sys();
|
||||
if (cpu_has_bear())
|
||||
current->thread.last_break = regs->last_break;
|
||||
|
||||
local_irq_enable();
|
||||
regs->orig_gpr2 = regs->gprs[2];
|
||||
|
||||
if (per_trap)
|
||||
if (unlikely(per_trap))
|
||||
set_thread_flag(TIF_PER_TRAP);
|
||||
|
||||
regs->flags = 0;
|
||||
set_pt_regs_flag(regs, PIF_SYSCALL);
|
||||
do_syscall(regs);
|
||||
exit_to_user_mode();
|
||||
nr = regs->int_code & 0xffff;
|
||||
if (likely(!nr)) {
|
||||
nr = regs->gprs[1] & 0xffff;
|
||||
regs->int_code &= ~0xffffUL;
|
||||
regs->int_code |= nr;
|
||||
}
|
||||
regs->gprs[2] = nr;
|
||||
if (nr == __NR_restart_syscall && !(current->restart_block.arch_data & 1)) {
|
||||
regs->psw.addr = current->restart_block.arch_data;
|
||||
current->restart_block.arch_data = 1;
|
||||
}
|
||||
nr = syscall_enter_from_user_mode_work(regs, nr);
|
||||
/*
|
||||
* In the s390 ptrace ABI, both the syscall number and the return value
|
||||
* use gpr2. However, userspace puts the syscall number either in the
|
||||
* svc instruction itself, or uses gpr1. To make at least skipping syscalls
|
||||
* work, the ptrace code sets PIF_SYSCALL_RET_SET, which is checked here
|
||||
* and if set, the syscall will be skipped.
|
||||
*/
|
||||
if (unlikely(test_and_clear_pt_regs_flag(regs, PIF_SYSCALL_RET_SET)))
|
||||
goto out;
|
||||
regs->gprs[2] = -ENOSYS;
|
||||
if (unlikely(nr >= NR_syscalls))
|
||||
goto out;
|
||||
do {
|
||||
regs->gprs[2] = current->thread.sys_call_table[nr](regs);
|
||||
} while (test_and_clear_pt_regs_flag(regs, PIF_EXECVE_PGSTE_RESTART));
|
||||
out:
|
||||
syscall_exit_to_user_mode(regs);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user