1/* sys_frv.c: FRV arch-specific syscall wrappers 2 * 3 * Copyright (C) 2003-5 Red Hat, Inc. All Rights Reserved. 4 * Written by David Howells (dhowells@redhat.com) 5 * - Derived from arch/m68k/kernel/sys_m68k.c 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License 9 * as published by the Free Software Foundation; either version 10 * 2 of the License, or (at your option) any later version. 11 */ 12 13#include <linux/errno.h> 14#include <linux/sched.h> 15#include <linux/mm.h> 16#include <linux/smp.h> 17#include <linux/sem.h> 18#include <linux/msg.h> 19#include <linux/shm.h> 20#include <linux/stat.h> 21#include <linux/mman.h> 22#include <linux/file.h> 23#include <linux/utsname.h> 24#include <linux/syscalls.h> 25 26#include <asm/setup.h> 27#include <asm/uaccess.h> 28#include <asm/ipc.h> 29 30/* 31 * sys_pipe() is the normal C calling standard for creating 32 * a pipe. It's not the way unix traditionally does this, though. 33 */ 34asmlinkage long sys_pipe(unsigned long __user * fildes) 35{ 36 int fd[2]; 37 int error; 38 39 error = do_pipe(fd); 40 if (!error) { 41 if (copy_to_user(fildes, fd, 2*sizeof(int))) 42 error = -EFAULT; 43 } 44 return error; 45} 46 47asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, 48 unsigned long prot, unsigned long flags, 49 unsigned long fd, unsigned long pgoff) 50{ 51 int error = -EBADF; 52 struct file * file = NULL; 53 54 flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); 55 if (!(flags & MAP_ANONYMOUS)) { 56 file = fget(fd); 57 if (!file) 58 goto out; 59 } 60 61 /* As with sparc32, make sure the shift for mmap2 is constant 62 (12), no matter what PAGE_SIZE we have.... */ 63 64 /* But unlike sparc32, don't just silently break if we're 65 trying to map something we can't */ 66 if (pgoff & ((1<<(PAGE_SHIFT-12))-1)) 67 return -EINVAL; 68 69 pgoff >>= (PAGE_SHIFT - 12); 70 71 down_write(¤t->mm->mmap_sem); 72 error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); 73 up_write(¤t->mm->mmap_sem); 74 75 if (file) 76 fput(file); 77out: 78 return error; 79} 80 81 82/* 83 * sys_ipc() is the de-multiplexer for the SysV IPC calls.. 84 * 85 * This is really horribly ugly. 86 */ 87asmlinkage long sys_ipc(unsigned long call, 88 unsigned long first, 89 unsigned long second, 90 unsigned long third, 91 void __user *ptr, 92 unsigned long fifth) 93{ 94 int version, ret; 95 96 version = call >> 16; /* hack for backward compatibility */ 97 call &= 0xffff; 98 99 switch (call) { 100 case SEMOP: 101 return sys_semtimedop(first, (struct sembuf __user *)ptr, second, NULL); 102 case SEMTIMEDOP: 103 return sys_semtimedop(first, (struct sembuf __user *)ptr, second, 104 (const struct timespec __user *)fifth); 105 106 case SEMGET: 107 return sys_semget (first, second, third); 108 case SEMCTL: { 109 union semun fourth; 110 if (!ptr) 111 return -EINVAL; 112 if (get_user(fourth.__pad, (void * __user *) ptr)) 113 return -EFAULT; 114 return sys_semctl (first, second, third, fourth); 115 } 116 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 struct ipc_kludge tmp; 124 if (!ptr) 125 return -EINVAL; 126 127 if (copy_from_user(&tmp, 128 (struct ipc_kludge __user *) ptr, 129 sizeof (tmp))) 130 return -EFAULT; 131 return sys_msgrcv (first, tmp.msgp, second, 132 tmp.msgtyp, third); 133 } 134 default: 135 return sys_msgrcv (first, 136 (struct msgbuf __user *) ptr, 137 second, fifth, third); 138 } 139 case MSGGET: 140 return sys_msgget ((key_t) first, second); 141 case MSGCTL: 142 return sys_msgctl (first, second, (struct msqid_ds __user *) ptr); 143 144 case SHMAT: 145 switch (version) { 146 default: { 147 ulong raddr; 148 ret = do_shmat (first, (char __user *) ptr, second, &raddr); 149 if (ret) 150 return ret; 151 return put_user (raddr, (ulong __user *) third); 152 } 153 case 1: /* iBCS2 emulator entry point */ 154 if (!segment_eq(get_fs(), get_ds())) 155 return -EINVAL; 156 /* The "(ulong *) third" is valid _only_ because of the kernel segment thing */ 157 return do_shmat (first, (char __user *) ptr, second, (ulong *) third); 158 } 159 case SHMDT: 160 return sys_shmdt ((char __user *)ptr); 161 case SHMGET: 162 return sys_shmget (first, second, third); 163 case SHMCTL: 164 return sys_shmctl (first, second, 165 (struct shmid_ds __user *) ptr); 166 default: 167 return -ENOSYS; 168 } 169} 170