diff --git a/arch/s390/kernel/syscall.c b/arch/s390/kernel/syscall.c index c8df656b08bc..535f3922ffa9 100644 --- a/arch/s390/kernel/syscall.c +++ b/arch/s390/kernel/syscall.c @@ -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); }