linux/arch/m68knommu/kernel/sys_m68k.c
<<
>>
Prefs
   1/*
   2 * linux/arch/m68knommu/kernel/sys_m68k.c
   3 *
   4 * This file contains various random system calls that
   5 * have a non-standard calling sequence on the Linux/m68k
   6 * platform.
   7 */
   8
   9#include <linux/errno.h>
  10#include <linux/sched.h>
  11#include <linux/mm.h>
  12#include <linux/smp.h>
  13#include <linux/sem.h>
  14#include <linux/msg.h>
  15#include <linux/shm.h>
  16#include <linux/stat.h>
  17#include <linux/syscalls.h>
  18#include <linux/mman.h>
  19#include <linux/file.h>
  20#include <linux/ipc.h>
  21#include <linux/fs.h>
  22
  23#include <asm/setup.h>
  24#include <asm/uaccess.h>
  25#include <asm/cachectl.h>
  26#include <asm/traps.h>
  27#include <asm/cacheflush.h>
  28#include <asm/unistd.h>
  29
  30/* common code for old and new mmaps */
  31static inline long do_mmap2(
  32        unsigned long addr, unsigned long len,
  33        unsigned long prot, unsigned long flags,
  34        unsigned long fd, unsigned long pgoff)
  35{
  36        int error = -EBADF;
  37        struct file * file = NULL;
  38
  39        flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
  40        if (!(flags & MAP_ANONYMOUS)) {
  41                file = fget(fd);
  42                if (!file)
  43                        goto out;
  44        }
  45
  46        down_write(&current->mm->mmap_sem);
  47        error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
  48        up_write(&current->mm->mmap_sem);
  49
  50        if (file)
  51                fput(file);
  52out:
  53        return error;
  54}
  55
  56asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
  57        unsigned long prot, unsigned long flags,
  58        unsigned long fd, unsigned long pgoff)
  59{
  60        return do_mmap2(addr, len, prot, flags, fd, pgoff);
  61}
  62
  63/*
  64 * Perform the select(nd, in, out, ex, tv) and mmap() system
  65 * calls. Linux/m68k cloned Linux/i386, which didn't use to be able to
  66 * handle more than 4 system call parameters, so these system calls
  67 * used a memory block for parameter passing..
  68 */
  69
  70struct mmap_arg_struct {
  71        unsigned long addr;
  72        unsigned long len;
  73        unsigned long prot;
  74        unsigned long flags;
  75        unsigned long fd;
  76        unsigned long offset;
  77};
  78
  79asmlinkage int old_mmap(struct mmap_arg_struct *arg)
  80{
  81        struct mmap_arg_struct a;
  82        int error = -EFAULT;
  83
  84        if (copy_from_user(&a, arg, sizeof(a)))
  85                goto out;
  86
  87        error = -EINVAL;
  88        if (a.offset & ~PAGE_MASK)
  89                goto out;
  90
  91        a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
  92
  93        error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT);
  94out:
  95        return error;
  96}
  97
  98struct sel_arg_struct {
  99        unsigned long n;
 100        fd_set *inp, *outp, *exp;
 101        struct timeval *tvp;
 102};
 103
 104asmlinkage int old_select(struct sel_arg_struct *arg)
 105{
 106        struct sel_arg_struct a;
 107
 108        if (copy_from_user(&a, arg, sizeof(a)))
 109                return -EFAULT;
 110        /* sys_select() does the appropriate kernel locking */
 111        return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp);
 112}
 113
 114/*
 115 * sys_ipc() is the de-multiplexer for the SysV IPC calls..
 116 *
 117 * This is really horribly ugly.
 118 */
 119asmlinkage int sys_ipc (uint call, int first, int second,
 120                        int third, void *ptr, long fifth)
 121{
 122        int version, ret;
 123
 124        version = call >> 16; /* hack for backward compatibility */
 125        call &= 0xffff;
 126
 127        if (call <= SEMCTL)
 128                switch (call) {
 129                case SEMOP:
 130                        return sys_semop (first, (struct sembuf *)ptr, second);
 131                case SEMGET:
 132                        return sys_semget (first, second, third);
 133                case SEMCTL: {
 134                        union semun fourth;
 135                        if (!ptr)
 136                                return -EINVAL;
 137                        if (get_user(fourth.__pad, (void **) ptr))
 138                                return -EFAULT;
 139                        return sys_semctl (first, second, third, fourth);
 140                        }
 141                default:
 142                        return -EINVAL;
 143                }
 144        if (call <= MSGCTL) 
 145                switch (call) {
 146                case MSGSND:
 147                        return sys_msgsnd (first, (struct msgbuf *) ptr, 
 148                                          second, third);
 149                case MSGRCV:
 150                        switch (version) {
 151                        case 0: {
 152                                struct ipc_kludge tmp;
 153                                if (!ptr)
 154                                        return -EINVAL;
 155                                if (copy_from_user (&tmp,
 156                                                    (struct ipc_kludge *)ptr,
 157                                                    sizeof (tmp)))
 158                                        return -EFAULT;
 159                                return sys_msgrcv (first, tmp.msgp, second,
 160                                                   tmp.msgtyp, third);
 161                                }
 162                        default:
 163                                return sys_msgrcv (first,
 164                                                   (struct msgbuf *) ptr,
 165                                                   second, fifth, third);
 166                        }
 167                case MSGGET:
 168                        return sys_msgget ((key_t) first, second);
 169                case MSGCTL:
 170                        return sys_msgctl (first, second,
 171                                           (struct msqid_ds *) ptr);
 172                default:
 173                        return -EINVAL;
 174                }
 175        if (call <= SHMCTL)
 176                switch (call) {
 177                case SHMAT:
 178                        switch (version) {
 179                        default: {
 180                                ulong raddr;
 181                                ret = do_shmat (first, ptr, second, &raddr);
 182                                if (ret)
 183                                        return ret;
 184                                return put_user (raddr, (ulong __user *) third);
 185                        }
 186                        }
 187                case SHMDT:
 188                        return sys_shmdt (ptr);
 189                case SHMGET:
 190                        return sys_shmget (first, second, third);
 191                case SHMCTL:
 192                        return sys_shmctl (first, second, ptr);
 193                default:
 194                        return -ENOSYS;
 195                }
 196
 197        return -EINVAL;
 198}
 199
 200/* sys_cacheflush -- flush (part of) the processor cache.  */
 201asmlinkage int
 202sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
 203{
 204        flush_cache_all();
 205        return(0);
 206}
 207
 208asmlinkage int sys_getpagesize(void)
 209{
 210        return PAGE_SIZE;
 211}
 212
 213/*
 214 * Do a system call from kernel instead of calling sys_execve so we
 215 * end up with proper pt_regs.
 216 */
 217int kernel_execve(const char *filename, char *const argv[], char *const envp[])
 218{
 219        register long __res asm ("%d0") = __NR_execve;
 220        register long __a asm ("%d1") = (long)(filename);
 221        register long __b asm ("%d2") = (long)(argv);
 222        register long __c asm ("%d3") = (long)(envp);
 223        asm volatile ("trap  #0" : "+d" (__res)
 224                        : "d" (__a), "d" (__b), "d" (__c));
 225        return __res;
 226}
 227