0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #include <linux/errno.h>
0016 #include <linux/sched.h>
0017 #include <linux/mm.h>
0018 #include <linux/fs.h>
0019 #include <linux/smp.h>
0020 #include <linux/sem.h>
0021 #include <linux/msg.h>
0022 #include <linux/shm.h>
0023 #include <linux/stat.h>
0024 #include <linux/syscalls.h>
0025 #include <linux/mman.h>
0026 #include <linux/file.h>
0027 #include <linux/utsname.h>
0028 #include <linux/personality.h>
0029 #include <linux/unistd.h>
0030 #include <linux/ipc.h>
0031 #include <linux/uaccess.h>
0032 #include <linux/string.h>
0033 #include <linux/thread_info.h>
0034 #include <linux/entry-common.h>
0035
0036 #include <asm/ptrace.h>
0037 #include <asm/vtime.h>
0038
0039 #include "entry.h"
0040
0041
0042
0043
0044
0045
0046
0047 struct s390_mmap_arg_struct {
0048 unsigned long addr;
0049 unsigned long len;
0050 unsigned long prot;
0051 unsigned long flags;
0052 unsigned long fd;
0053 unsigned long offset;
0054 };
0055
0056 SYSCALL_DEFINE1(mmap2, struct s390_mmap_arg_struct __user *, arg)
0057 {
0058 struct s390_mmap_arg_struct a;
0059 int error = -EFAULT;
0060
0061 if (copy_from_user(&a, arg, sizeof(a)))
0062 goto out;
0063 error = ksys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, a.offset);
0064 out:
0065 return error;
0066 }
0067
0068 #ifdef CONFIG_SYSVIPC
0069
0070
0071
0072 SYSCALL_DEFINE5(s390_ipc, uint, call, int, first, unsigned long, second,
0073 unsigned long, third, void __user *, ptr)
0074 {
0075 if (call >> 16)
0076 return -EINVAL;
0077
0078
0079
0080
0081
0082
0083
0084
0085 return ksys_ipc(call, first, second, third, ptr, third);
0086 }
0087 #endif
0088
0089 SYSCALL_DEFINE1(s390_personality, unsigned int, personality)
0090 {
0091 unsigned int ret = current->personality;
0092
0093 if (personality(current->personality) == PER_LINUX32 &&
0094 personality(personality) == PER_LINUX)
0095 personality |= PER_LINUX32;
0096
0097 if (personality != 0xffffffff)
0098 set_personality(personality);
0099
0100 if (personality(ret) == PER_LINUX32)
0101 ret &= ~PER_LINUX32;
0102
0103 return ret;
0104 }
0105
0106 SYSCALL_DEFINE0(ni_syscall)
0107 {
0108 return -ENOSYS;
0109 }
0110
0111 static void do_syscall(struct pt_regs *regs)
0112 {
0113 unsigned long nr;
0114
0115 nr = regs->int_code & 0xffff;
0116 if (!nr) {
0117 nr = regs->gprs[1] & 0xffff;
0118 regs->int_code &= ~0xffffUL;
0119 regs->int_code |= nr;
0120 }
0121
0122 regs->gprs[2] = nr;
0123
0124 if (nr == __NR_restart_syscall && !(current->restart_block.arch_data & 1)) {
0125 regs->psw.addr = current->restart_block.arch_data;
0126 current->restart_block.arch_data = 1;
0127 }
0128 nr = syscall_enter_from_user_mode_work(regs, nr);
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138 if (unlikely(test_and_clear_pt_regs_flag(regs, PIF_SYSCALL_RET_SET)))
0139 goto out;
0140 regs->gprs[2] = -ENOSYS;
0141 if (likely(nr >= NR_syscalls))
0142 goto out;
0143 do {
0144 regs->gprs[2] = current->thread.sys_call_table[nr](regs);
0145 } while (test_and_clear_pt_regs_flag(regs, PIF_EXECVE_PGSTE_RESTART));
0146 out:
0147 syscall_exit_to_user_mode_work(regs);
0148 }
0149
0150 void noinstr __do_syscall(struct pt_regs *regs, int per_trap)
0151 {
0152 add_random_kstack_offset();
0153 enter_from_user_mode(regs);
0154 regs->psw = S390_lowcore.svc_old_psw;
0155 regs->int_code = S390_lowcore.svc_int_code;
0156 update_timer_sys();
0157 if (static_branch_likely(&cpu_has_bear))
0158 current->thread.last_break = regs->last_break;
0159
0160 local_irq_enable();
0161 regs->orig_gpr2 = regs->gprs[2];
0162
0163 if (per_trap)
0164 set_thread_flag(TIF_PER_TRAP);
0165
0166 regs->flags = 0;
0167 set_pt_regs_flag(regs, PIF_SYSCALL);
0168 do_syscall(regs);
0169 exit_to_user_mode();
0170 }