123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197 |
- /*
- * arch/v850/kernel/syscalls.c -- Various system-call definitions not
- * defined in machine-independent code
- *
- * Copyright (C) 2001,02 NEC Corporation
- * Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License. See the file COPYING in the main directory of this
- * archive for more details.
- *
- * This file was derived the ppc version, arch/ppc/kernel/syscalls.c
- * ... which was derived from "arch/i386/kernel/sys_i386.c" by Gary Thomas;
- * modified by Cort Dougan (cort@cs.nmt.edu)
- * and Paul Mackerras (paulus@cs.anu.edu.au).
- */
- #include <linux/config.h>
- #include <linux/errno.h>
- #include <linux/mm.h>
- #include <linux/smp.h>
- #include <linux/smp_lock.h>
- #include <linux/syscalls.h>
- #include <linux/sem.h>
- #include <linux/msg.h>
- #include <linux/shm.h>
- #include <linux/stat.h>
- #include <linux/mman.h>
- #include <linux/sys.h>
- #include <linux/ipc.h>
- #include <linux/utsname.h>
- #include <linux/file.h>
- #include <asm/uaccess.h>
- #include <asm/ipc.h>
- #include <asm/semaphore.h>
- /*
- * sys_ipc() is the de-multiplexer for the SysV IPC calls..
- *
- * This is really horribly ugly.
- */
- int
- sys_ipc (uint call, int first, int second, int third, void *ptr, long fifth)
- {
- int version, ret;
- version = call >> 16; /* hack for backward compatibility */
- call &= 0xffff;
- ret = -EINVAL;
- switch (call) {
- case SEMOP:
- ret = sys_semop (first, (struct sembuf *)ptr, second);
- break;
- case SEMGET:
- ret = sys_semget (first, second, third);
- break;
- case SEMCTL:
- {
- union semun fourth;
- if (!ptr)
- break;
- if ((ret = access_ok(VERIFY_READ, ptr, sizeof(long)) ? 0 : -EFAULT)
- || (ret = get_user(fourth.__pad, (void **)ptr)))
- break;
- ret = sys_semctl (first, second, third, fourth);
- break;
- }
- case MSGSND:
- ret = sys_msgsnd (first, (struct msgbuf *) ptr, second, third);
- break;
- case MSGRCV:
- switch (version) {
- case 0: {
- struct ipc_kludge tmp;
- if (!ptr)
- break;
- if ((ret = access_ok(VERIFY_READ, ptr, sizeof(tmp)) ? 0 : -EFAULT)
- || (ret = copy_from_user(&tmp,
- (struct ipc_kludge *) ptr,
- sizeof (tmp))))
- break;
- ret = sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp,
- third);
- break;
- }
- default:
- ret = sys_msgrcv (first, (struct msgbuf *) ptr,
- second, fifth, third);
- break;
- }
- break;
- case MSGGET:
- ret = sys_msgget ((key_t) first, second);
- break;
- case MSGCTL:
- ret = sys_msgctl (first, second, (struct msqid_ds *) ptr);
- break;
- case SHMAT:
- switch (version) {
- default: {
- ulong raddr;
- if ((ret = access_ok(VERIFY_WRITE, (ulong*) third,
- sizeof(ulong)) ? 0 : -EFAULT))
- break;
- ret = do_shmat (first, (char *) ptr, second, &raddr);
- if (ret)
- break;
- ret = put_user (raddr, (ulong *) third);
- break;
- }
- case 1: /* iBCS2 emulator entry point */
- if (!segment_eq(get_fs(), get_ds()))
- break;
- ret = do_shmat (first, (char *) ptr, second,
- (ulong *) third);
- break;
- }
- break;
- case SHMDT:
- ret = sys_shmdt ((char *)ptr);
- break;
- case SHMGET:
- ret = sys_shmget (first, second, third);
- break;
- case SHMCTL:
- ret = sys_shmctl (first, second, (struct shmid_ds *) ptr);
- break;
- }
- return ret;
- }
- /*
- * sys_pipe() is the normal C calling standard for creating
- * a pipe. It's not the way unix traditionally does this, though.
- */
- int sys_pipe (int *fildes)
- {
- int fd[2];
- int error;
- error = do_pipe (fd);
- if (!error) {
- if (copy_to_user (fildes, fd, 2*sizeof (int)))
- error = -EFAULT;
- }
- return error;
- }
- static inline unsigned long
- do_mmap2 (unsigned long addr, size_t len,
- unsigned long prot, unsigned long flags,
- unsigned long fd, unsigned long pgoff)
- {
- struct file * file = NULL;
- int ret = -EBADF;
- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
- if (! (flags & MAP_ANONYMOUS)) {
- if (!(file = fget (fd)))
- goto out;
- }
-
- down_write (¤t->mm->mmap_sem);
- ret = do_mmap_pgoff (file, addr, len, prot, flags, pgoff);
- up_write (¤t->mm->mmap_sem);
- if (file)
- fput (file);
- out:
- return ret;
- }
- unsigned long sys_mmap2 (unsigned long addr, size_t len,
- unsigned long prot, unsigned long flags,
- unsigned long fd, unsigned long pgoff)
- {
- return do_mmap2 (addr, len, prot, flags, fd, pgoff);
- }
- unsigned long sys_mmap (unsigned long addr, size_t len,
- unsigned long prot, unsigned long flags,
- unsigned long fd, off_t offset)
- {
- int err = -EINVAL;
- if (offset & ~PAGE_MASK)
- goto out;
- err = do_mmap2 (addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
- out:
- return err;
- }
|