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 return do_mmap2(addr, len, prot, flags, fd, pgoff); 67 } 68 69 /* 70 * sys_ipc() is the de-multiplexer for the SysV IPC calls.. 71 * 72 * This is really horribly ugly. 73 */ 74 asmlinkage int sys_ipc(uint call, int first, int second, 75 int third, void __user *ptr, long fifth) 76 { 77 int version, ret; 78 79 version = call >> 16; /* hack for backward compatibility */ 80 call &= 0xffff; 81 82 trace_mark(kernel_arch_ipc_call, "call %u first %d", call, first); 83 84 if (call <= SEMTIMEDOP) 85 switch (call) { 86 case SEMOP: 87 return sys_semtimedop(first, 88 (struct sembuf __user *)ptr, 89 second, NULL); 90 case SEMTIMEDOP: 91 return sys_semtimedop(first, 92 (struct sembuf __user *)ptr, second, 93 (const struct timespec __user *)fifth); 94 case SEMGET: 95 return sys_semget (first, second, third); 96 case SEMCTL: { 97 union semun fourth; 98 if (!ptr) 99 return -EINVAL; 100 if (get_user(fourth.__pad, (void __user * __user *) ptr)) 101 return -EFAULT; 102 return sys_semctl (first, second, third, fourth); 103 } 104 default: 105 return -EINVAL; 106 } 107 108 if (call <= MSGCTL) 109 switch (call) { 110 case MSGSND: 111 return sys_msgsnd (first, (struct msgbuf __user *) ptr, 112 second, third); 113 case MSGRCV: 114 switch (version) { 115 case 0: 116 { 117 struct ipc_kludge tmp; 118 119 if (!ptr) 120 return -EINVAL; 121 122 if (copy_from_user(&tmp, 123 (struct ipc_kludge __user *) ptr, 124 sizeof (tmp))) 125 return -EFAULT; 126 127 return sys_msgrcv (first, tmp.msgp, second, 128 tmp.msgtyp, third); 129 } 130 default: 131 return sys_msgrcv (first, 132 (struct msgbuf __user *) ptr, 133 second, fifth, third); 134 } 135 case MSGGET: 136 return sys_msgget ((key_t) first, second); 137 case MSGCTL: 138 return sys_msgctl (first, second, 139 (struct msqid_ds __user *) ptr); 140 default: 141 return -EINVAL; 142 } 143 if (call <= SHMCTL) 144 switch (call) { 145 case SHMAT: 146 switch (version) { 147 default: { 148 ulong raddr; 149 ret = do_shmat (first, (char __user *) ptr, 150 second, &raddr); 151 if (ret) 152 return ret; 153 return put_user (raddr, (ulong __user *) third); 154 } 155 case 1: /* iBCS2 emulator entry point */ 156 if (!segment_eq(get_fs(), get_ds())) 157 return -EINVAL; 158 return do_shmat (first, (char __user *) ptr, 159 second, (ulong *) third); 160 } 161 case SHMDT: 162 return sys_shmdt ((char __user *)ptr); 163 case SHMGET: 164 return sys_shmget (first, second, third); 165 case SHMCTL: 166 return sys_shmctl (first, second, 167 (struct shmid_ds __user *) ptr); 168 default: 169 return -EINVAL; 170 } 171 172 return -EINVAL; 173 } 174 175 asmlinkage int sys_uname(struct old_utsname __user *name) 176 { 177 int err; 178 if (!name) 179 return -EFAULT; 180 down_read(&uts_sem); 181 err = copy_to_user(name, utsname(), sizeof(*name)); 182 up_read(&uts_sem); 183 return err?-EFAULT:0; 184 } 185