11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * linux/arch/sh/kernel/sys_sh.c 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * This file contains various random system calls that 51da177e4SLinus Torvalds * have a non-standard calling sequence on the Linux/SuperH 61da177e4SLinus Torvalds * platform. 71da177e4SLinus Torvalds * 81da177e4SLinus Torvalds * Taken from i386 version. 91da177e4SLinus Torvalds */ 101da177e4SLinus Torvalds #include <linux/errno.h> 111da177e4SLinus Torvalds #include <linux/sched.h> 121da177e4SLinus Torvalds #include <linux/mm.h> 131da177e4SLinus Torvalds #include <linux/smp.h> 141da177e4SLinus Torvalds #include <linux/sem.h> 151da177e4SLinus Torvalds #include <linux/msg.h> 161da177e4SLinus Torvalds #include <linux/shm.h> 171da177e4SLinus Torvalds #include <linux/stat.h> 181da177e4SLinus Torvalds #include <linux/syscalls.h> 191da177e4SLinus Torvalds #include <linux/mman.h> 201da177e4SLinus Torvalds #include <linux/file.h> 211da177e4SLinus Torvalds #include <linux/utsname.h> 22f3c25758SPaul Mundt #include <linux/module.h> 23e06c4e57SPaul Mundt #include <linux/fs.h> 24cba4fbbfSAdrian Bunk #include <linux/ipc.h> 25fa43972fSPaul Mundt #include <asm/syscalls.h> 261da177e4SLinus Torvalds #include <asm/uaccess.h> 27fe74290dSArnd Bergmann #include <asm/unistd.h> 28*6d243dd3SStuart Menefy #include <asm/cacheflush.h> 29*6d243dd3SStuart Menefy #include <asm/cachectl.h> 301da177e4SLinus Torvalds 311da177e4SLinus Torvalds static inline long 321da177e4SLinus Torvalds do_mmap2(unsigned long addr, unsigned long len, unsigned long prot, 331da177e4SLinus Torvalds unsigned long flags, int fd, unsigned long pgoff) 341da177e4SLinus Torvalds { 351da177e4SLinus Torvalds int error = -EBADF; 361da177e4SLinus Torvalds struct file *file = NULL; 371da177e4SLinus Torvalds 381da177e4SLinus Torvalds flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); 391da177e4SLinus Torvalds if (!(flags & MAP_ANONYMOUS)) { 401da177e4SLinus Torvalds file = fget(fd); 411da177e4SLinus Torvalds if (!file) 421da177e4SLinus Torvalds goto out; 431da177e4SLinus Torvalds } 441da177e4SLinus Torvalds 451da177e4SLinus Torvalds down_write(¤t->mm->mmap_sem); 461da177e4SLinus Torvalds error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); 471da177e4SLinus Torvalds up_write(¤t->mm->mmap_sem); 481da177e4SLinus Torvalds 491da177e4SLinus Torvalds if (file) 501da177e4SLinus Torvalds fput(file); 511da177e4SLinus Torvalds out: 521da177e4SLinus Torvalds return error; 531da177e4SLinus Torvalds } 541da177e4SLinus Torvalds 551da177e4SLinus Torvalds asmlinkage int old_mmap(unsigned long addr, unsigned long len, 561da177e4SLinus Torvalds unsigned long prot, unsigned long flags, 571da177e4SLinus Torvalds int fd, unsigned long off) 581da177e4SLinus Torvalds { 591da177e4SLinus Torvalds if (off & ~PAGE_MASK) 601da177e4SLinus Torvalds return -EINVAL; 611da177e4SLinus Torvalds return do_mmap2(addr, len, prot, flags, fd, off>>PAGE_SHIFT); 621da177e4SLinus Torvalds } 631da177e4SLinus Torvalds 641da177e4SLinus Torvalds asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, 651da177e4SLinus Torvalds unsigned long prot, unsigned long flags, 661da177e4SLinus Torvalds unsigned long fd, unsigned long pgoff) 671da177e4SLinus Torvalds { 688c31813fSToshinobu Sugioka /* 698c31813fSToshinobu Sugioka * The shift for mmap2 is constant, regardless of PAGE_SIZE 708c31813fSToshinobu Sugioka * setting. 718c31813fSToshinobu Sugioka */ 728c31813fSToshinobu Sugioka if (pgoff & ((1 << (PAGE_SHIFT - 12)) - 1)) 738c31813fSToshinobu Sugioka return -EINVAL; 748c31813fSToshinobu Sugioka 758c31813fSToshinobu Sugioka pgoff >>= PAGE_SHIFT - 12; 768c31813fSToshinobu Sugioka 771da177e4SLinus Torvalds return do_mmap2(addr, len, prot, flags, fd, pgoff); 781da177e4SLinus Torvalds } 791da177e4SLinus Torvalds 801da177e4SLinus Torvalds /* 811da177e4SLinus Torvalds * sys_ipc() is the de-multiplexer for the SysV IPC calls.. 821da177e4SLinus Torvalds * 831da177e4SLinus Torvalds * This is really horribly ugly. 841da177e4SLinus Torvalds */ 851da177e4SLinus Torvalds asmlinkage int sys_ipc(uint call, int first, int second, 861da177e4SLinus Torvalds int third, void __user *ptr, long fifth) 871da177e4SLinus Torvalds { 881da177e4SLinus Torvalds int version, ret; 891da177e4SLinus Torvalds 901da177e4SLinus Torvalds version = call >> 16; /* hack for backward compatibility */ 911da177e4SLinus Torvalds call &= 0xffff; 921da177e4SLinus Torvalds 933c31bf73SYoshihiro Shimoda if (call <= SEMTIMEDOP) 941da177e4SLinus Torvalds switch (call) { 951da177e4SLinus Torvalds case SEMOP: 96bcb28e42SPaul Mundt return sys_semtimedop(first, 97bcb28e42SPaul Mundt (struct sembuf __user *)ptr, 981da177e4SLinus Torvalds second, NULL); 991da177e4SLinus Torvalds case SEMTIMEDOP: 100bcb28e42SPaul Mundt return sys_semtimedop(first, 101bcb28e42SPaul Mundt (struct sembuf __user *)ptr, second, 1021da177e4SLinus Torvalds (const struct timespec __user *)fifth); 1031da177e4SLinus Torvalds case SEMGET: 1041da177e4SLinus Torvalds return sys_semget (first, second, third); 1051da177e4SLinus Torvalds case SEMCTL: { 1061da177e4SLinus Torvalds union semun fourth; 1071da177e4SLinus Torvalds if (!ptr) 1081da177e4SLinus Torvalds return -EINVAL; 109fa43972fSPaul Mundt if (get_user(fourth.__pad, (void __user * __user *) ptr)) 1101da177e4SLinus Torvalds return -EFAULT; 1111da177e4SLinus Torvalds return sys_semctl (first, second, third, fourth); 1121da177e4SLinus Torvalds } 1131da177e4SLinus Torvalds default: 1141da177e4SLinus Torvalds return -EINVAL; 1151da177e4SLinus Torvalds } 1161da177e4SLinus Torvalds 1171da177e4SLinus Torvalds if (call <= MSGCTL) 1181da177e4SLinus Torvalds switch (call) { 1191da177e4SLinus Torvalds case MSGSND: 1201da177e4SLinus Torvalds return sys_msgsnd (first, (struct msgbuf __user *) ptr, 1211da177e4SLinus Torvalds second, third); 1221da177e4SLinus Torvalds case MSGRCV: 1231da177e4SLinus Torvalds switch (version) { 124bcb28e42SPaul Mundt case 0: 125bcb28e42SPaul Mundt { 1261da177e4SLinus Torvalds struct ipc_kludge tmp; 127bcb28e42SPaul Mundt 1281da177e4SLinus Torvalds if (!ptr) 1291da177e4SLinus Torvalds return -EINVAL; 1301da177e4SLinus Torvalds 1311da177e4SLinus Torvalds if (copy_from_user(&tmp, 1321da177e4SLinus Torvalds (struct ipc_kludge __user *) ptr, 1331da177e4SLinus Torvalds sizeof (tmp))) 1341da177e4SLinus Torvalds return -EFAULT; 135bcb28e42SPaul Mundt 1361da177e4SLinus Torvalds return sys_msgrcv (first, tmp.msgp, second, 1371da177e4SLinus Torvalds tmp.msgtyp, third); 1381da177e4SLinus Torvalds } 1391da177e4SLinus Torvalds default: 1401da177e4SLinus Torvalds return sys_msgrcv (first, 1411da177e4SLinus Torvalds (struct msgbuf __user *) ptr, 1421da177e4SLinus Torvalds second, fifth, third); 1431da177e4SLinus Torvalds } 1441da177e4SLinus Torvalds case MSGGET: 1451da177e4SLinus Torvalds return sys_msgget ((key_t) first, second); 1461da177e4SLinus Torvalds case MSGCTL: 1471da177e4SLinus Torvalds return sys_msgctl (first, second, 1481da177e4SLinus Torvalds (struct msqid_ds __user *) ptr); 1491da177e4SLinus Torvalds default: 1501da177e4SLinus Torvalds return -EINVAL; 1511da177e4SLinus Torvalds } 1521da177e4SLinus Torvalds if (call <= SHMCTL) 1531da177e4SLinus Torvalds switch (call) { 1541da177e4SLinus Torvalds case SHMAT: 1551da177e4SLinus Torvalds switch (version) { 1561da177e4SLinus Torvalds default: { 1571da177e4SLinus Torvalds ulong raddr; 1581da177e4SLinus Torvalds ret = do_shmat (first, (char __user *) ptr, 1591da177e4SLinus Torvalds second, &raddr); 1601da177e4SLinus Torvalds if (ret) 1611da177e4SLinus Torvalds return ret; 1621da177e4SLinus Torvalds return put_user (raddr, (ulong __user *) third); 1631da177e4SLinus Torvalds } 1641da177e4SLinus Torvalds case 1: /* iBCS2 emulator entry point */ 1651da177e4SLinus Torvalds if (!segment_eq(get_fs(), get_ds())) 1661da177e4SLinus Torvalds return -EINVAL; 1671da177e4SLinus Torvalds return do_shmat (first, (char __user *) ptr, 1681da177e4SLinus Torvalds second, (ulong *) third); 1691da177e4SLinus Torvalds } 1701da177e4SLinus Torvalds case SHMDT: 1711da177e4SLinus Torvalds return sys_shmdt ((char __user *)ptr); 1721da177e4SLinus Torvalds case SHMGET: 1731da177e4SLinus Torvalds return sys_shmget (first, second, third); 1741da177e4SLinus Torvalds case SHMCTL: 1751da177e4SLinus Torvalds return sys_shmctl (first, second, 1761da177e4SLinus Torvalds (struct shmid_ds __user *) ptr); 1771da177e4SLinus Torvalds default: 1781da177e4SLinus Torvalds return -EINVAL; 1791da177e4SLinus Torvalds } 1801da177e4SLinus Torvalds 1811da177e4SLinus Torvalds return -EINVAL; 1821da177e4SLinus Torvalds } 1831da177e4SLinus Torvalds 184*6d243dd3SStuart Menefy /* sys_cacheflush -- flush (part of) the processor cache. */ 185*6d243dd3SStuart Menefy asmlinkage int sys_cacheflush(unsigned long addr, unsigned long len, int op) 186*6d243dd3SStuart Menefy { 187*6d243dd3SStuart Menefy struct vm_area_struct *vma; 188*6d243dd3SStuart Menefy 189*6d243dd3SStuart Menefy if ((op < 0) || (op > (CACHEFLUSH_D_PURGE|CACHEFLUSH_I))) 190*6d243dd3SStuart Menefy return -EINVAL; 191*6d243dd3SStuart Menefy 192*6d243dd3SStuart Menefy /* 193*6d243dd3SStuart Menefy * Verify that the specified address region actually belongs 194*6d243dd3SStuart Menefy * to this process. 195*6d243dd3SStuart Menefy */ 196*6d243dd3SStuart Menefy if (addr + len < addr) 197*6d243dd3SStuart Menefy return -EFAULT; 198*6d243dd3SStuart Menefy 199*6d243dd3SStuart Menefy down_read(¤t->mm->mmap_sem); 200*6d243dd3SStuart Menefy vma = find_vma (current->mm, addr); 201*6d243dd3SStuart Menefy if (vma == NULL || addr < vma->vm_start || addr + len > vma->vm_end) { 202*6d243dd3SStuart Menefy up_read(¤t->mm->mmap_sem); 203*6d243dd3SStuart Menefy return -EFAULT; 204*6d243dd3SStuart Menefy } 205*6d243dd3SStuart Menefy 206*6d243dd3SStuart Menefy switch (op & CACHEFLUSH_D_PURGE) { 207*6d243dd3SStuart Menefy case CACHEFLUSH_D_INVAL: 208*6d243dd3SStuart Menefy __flush_invalidate_region((void *)addr, len); 209*6d243dd3SStuart Menefy break; 210*6d243dd3SStuart Menefy case CACHEFLUSH_D_WB: 211*6d243dd3SStuart Menefy __flush_wback_region((void *)addr, len); 212*6d243dd3SStuart Menefy break; 213*6d243dd3SStuart Menefy case CACHEFLUSH_D_PURGE: 214*6d243dd3SStuart Menefy __flush_purge_region((void *)addr, len); 215*6d243dd3SStuart Menefy break; 216*6d243dd3SStuart Menefy } 217*6d243dd3SStuart Menefy 218*6d243dd3SStuart Menefy if (op & CACHEFLUSH_I) 219*6d243dd3SStuart Menefy flush_cache_all(); 220*6d243dd3SStuart Menefy 221*6d243dd3SStuart Menefy up_read(¤t->mm->mmap_sem); 222*6d243dd3SStuart Menefy return 0; 223*6d243dd3SStuart Menefy } 224*6d243dd3SStuart Menefy 225fa43972fSPaul Mundt asmlinkage int sys_uname(struct old_utsname __user *name) 2261da177e4SLinus Torvalds { 2271da177e4SLinus Torvalds int err; 2281da177e4SLinus Torvalds if (!name) 2291da177e4SLinus Torvalds return -EFAULT; 2301da177e4SLinus Torvalds down_read(&uts_sem); 231e9ff3990SSerge E. Hallyn err = copy_to_user(name, utsname(), sizeof(*name)); 2321da177e4SLinus Torvalds up_read(&uts_sem); 2331da177e4SLinus Torvalds return err?-EFAULT:0; 2341da177e4SLinus Torvalds } 235