1 /* 2 * linux/arch/sh/kernel/sys_sh.c 3 * 4 * This file contains various random system calls that 5 * have a non-standard calling sequence on the Linux/SuperH 6 * platform. 7 * 8 * Taken from i386 version. 9 */ 10 #include <linux/errno.h> 11 #include <linux/sched.h> 12 #include <linux/mm.h> 13 #include <linux/smp.h> 14 #include <linux/sem.h> 15 #include <linux/msg.h> 16 #include <linux/shm.h> 17 #include <linux/stat.h> 18 #include <linux/syscalls.h> 19 #include <linux/mman.h> 20 #include <linux/file.h> 21 #include <linux/utsname.h> 22 #include <linux/module.h> 23 #include <linux/fs.h> 24 #include <linux/ipc.h> 25 #include <asm/syscalls.h> 26 #include <asm/uaccess.h> 27 #include <asm/unistd.h> 28 29 static inline long 30 do_mmap2(unsigned long addr, unsigned long len, unsigned long prot, 31 unsigned long flags, int fd, unsigned long pgoff) 32 { 33 int error = -EBADF; 34 struct file *file = NULL; 35 36 flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); 37 if (!(flags & MAP_ANONYMOUS)) { 38 file = fget(fd); 39 if (!file) 40 goto out; 41 } 42 43 down_write(¤t->mm->mmap_sem); 44 error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); 45 up_write(¤t->mm->mmap_sem); 46 47 if (file) 48 fput(file); 49 out: 50 return error; 51 } 52 53 asmlinkage int old_mmap(unsigned long addr, unsigned long len, 54 unsigned long prot, unsigned long flags, 55 int fd, unsigned long off) 56 { 57 if (off & ~PAGE_MASK) 58 return -EINVAL; 59 return do_mmap2(addr, len, prot, flags, fd, off>>PAGE_SHIFT); 60 } 61 62 asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, 63 unsigned long prot, unsigned long flags, 64 unsigned long fd, unsigned long pgoff) 65 { 66 /* 67 * The shift for mmap2 is constant, regardless of PAGE_SIZE 68 * setting. 69 */ 70 if (pgoff & ((1 << (PAGE_SHIFT - 12)) - 1)) 71 return -EINVAL; 72 73 pgoff >>= PAGE_SHIFT - 12; 74 75 return do_mmap2(addr, len, prot, flags, fd, pgoff); 76 } 77 78 /* 79 * sys_ipc() is the de-multiplexer for the SysV IPC calls.. 80 * 81 * This is really horribly ugly. 82 */ 83 asmlinkage int sys_ipc(uint call, int first, int second, 84 int third, void __user *ptr, long fifth) 85 { 86 int version, ret; 87 88 version = call >> 16; /* hack for backward compatibility */ 89 call &= 0xffff; 90 91 if (call <= SEMTIMEDOP) 92 switch (call) { 93 case SEMOP: 94 return sys_semtimedop(first, 95 (struct sembuf __user *)ptr, 96 second, NULL); 97 case SEMTIMEDOP: 98 return sys_semtimedop(first, 99 (struct sembuf __user *)ptr, second, 100 (const struct timespec __user *)fifth); 101 case SEMGET: 102 return sys_semget (first, second, third); 103 case SEMCTL: { 104 union semun fourth; 105 if (!ptr) 106 return -EINVAL; 107 if (get_user(fourth.__pad, (void __user * __user *) ptr)) 108 return -EFAULT; 109 return sys_semctl (first, second, third, fourth); 110 } 111 default: 112 return -EINVAL; 113 } 114 115 if (call <= MSGCTL) 116 switch (call) { 117 case MSGSND: 118 return sys_msgsnd (first, (struct msgbuf __user *) ptr, 119 second, third); 120 case MSGRCV: 121 switch (version) { 122 case 0: 123 { 124 struct ipc_kludge tmp; 125 126 if (!ptr) 127 return -EINVAL; 128 129 if (copy_from_user(&tmp, 130 (struct ipc_kludge __user *) ptr, 131 sizeof (tmp))) 132 return -EFAULT; 133 134 return sys_msgrcv (first, tmp.msgp, second, 135 tmp.msgtyp, third); 136 } 137 default: 138 return sys_msgrcv (first, 139 (struct msgbuf __user *) ptr, 140 second, fifth, third); 141 } 142 case MSGGET: 143 return sys_msgget ((key_t) first, second); 144 case MSGCTL: 145 return sys_msgctl (first, second, 146 (struct msqid_ds __user *) ptr); 147 default: 148 return -EINVAL; 149 } 150 if (call <= SHMCTL) 151 switch (call) { 152 case SHMAT: 153 switch (version) { 154 default: { 155 ulong raddr; 156 ret = do_shmat (first, (char __user *) ptr, 157 second, &raddr); 158 if (ret) 159 return ret; 160 return put_user (raddr, (ulong __user *) third); 161 } 162 case 1: /* iBCS2 emulator entry point */ 163 if (!segment_eq(get_fs(), get_ds())) 164 return -EINVAL; 165 return do_shmat (first, (char __user *) ptr, 166 second, (ulong *) third); 167 } 168 case SHMDT: 169 return sys_shmdt ((char __user *)ptr); 170 case SHMGET: 171 return sys_shmget (first, second, third); 172 case SHMCTL: 173 return sys_shmctl (first, second, 174 (struct shmid_ds __user *) ptr); 175 default: 176 return -EINVAL; 177 } 178 179 return -EINVAL; 180 } 181 182 asmlinkage int sys_uname(struct old_utsname __user *name) 183 { 184 int err; 185 if (!name) 186 return -EFAULT; 187 down_read(&uts_sem); 188 err = copy_to_user(name, utsname(), sizeof(*name)); 189 up_read(&uts_sem); 190 return err?-EFAULT:0; 191 } 192