linux/arch/h8300/kernel/sys_h8300.c
<<
>>
Prefs
   1/*
   2 * linux/arch/h8300/kernel/sys_h8300.c
   3 *
   4 * This file contains various random system calls that
   5 * have a non-standard calling sequence on the H8/300
   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/fs.h>
  21#include <linux/ipc.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/unistd.h>
  28
  29/* common code for old and new mmaps */
  30static inline long do_mmap2(
  31        unsigned long addr, unsigned long len,
  32        unsigned long prot, unsigned long flags,
  33        unsigned long fd, unsigned long pgoff)
  34{
  35        int error = -EBADF;
  36        struct file * file = NULL;
  37
  38        flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
  39        if (!(flags & MAP_ANONYMOUS)) {
  40                file = fget(fd);
  41                if (!file)
  42                        goto out;
  43        }
  44
  45        down_write(&current->mm->mmap_sem);
  46        error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
  47        up_write(&current->mm->mmap_sem);
  48
  49        if (file)
  50                fput(file);
  51out:
  52        return error;
  53}
  54
  55asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
  56        unsigned long prot, unsigned long flags,
  57        unsigned long fd, unsigned long pgoff)
  58{
  59        return do_mmap2(addr, len, prot, flags, fd, pgoff);
  60}
  61
  62/*
  63 * Perform the select(nd, in, out, ex, tv) and mmap() system
  64 * calls. Linux/m68k cloned Linux/i386, which didn't use to be able to
  65 * handle more than 4 system call parameters, so these system calls
  66 * used a memory block for parameter passing..
  67 */
  68
  69struct mmap_arg_struct {
  70        unsigned long addr;
  71        unsigned long len;
  72        unsigned long prot;
  73        unsigned long flags;
  74        unsigned long fd;
  75        unsigned long offset;
  76};
  77
  78asmlinkage int old_mmap(struct mmap_arg_struct *arg)
  79{
  80        struct mmap_arg_struct a;
  81        int error = -EFAULT;
  82
  83        if (copy_from_user(&a, arg, sizeof(a)))
  84                goto out;
  85
  86        error = -EINVAL;
  87        if (a.offset & ~PAGE_MASK)
  88                goto out;
  89
  90        a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
  91
  92        error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT);
  93out:
  94        return error;
  95}
  96
  97#if 0 /* DAVIDM - do we want this */
  98struct mmap_arg_struct64 {
  99        __u32 addr;
 100        __u32 len;
 101        __u32 prot;
 102        __u32 flags;
 103        __u64 offset; /* 64 bits */
 104        __u32 fd;
 105};
 106
 107asmlinkage long sys_mmap64(struct mmap_arg_struct64 *arg)
 108{
 109        int error = -EFAULT;
 110        struct file * file = NULL;
 111        struct mmap_arg_struct64 a;
 112        unsigned long pgoff;
 113
 114        if (copy_from_user(&a, arg, sizeof(a)))
 115                return -EFAULT;
 116
 117        if ((long)a.offset & ~PAGE_MASK)
 118                return -EINVAL;
 119
 120        pgoff = a.offset >> PAGE_SHIFT;
 121        if ((a.offset >> PAGE_SHIFT) != pgoff)
 122                return -EINVAL;
 123
 124        if (!(a.flags & MAP_ANONYMOUS)) {
 125                error = -EBADF;
 126                file = fget(a.fd);
 127                if (!file)
 128                        goto out;
 129        }
 130        a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
 131
 132        down_write(&current->mm->mmap_sem);
 133        error = do_mmap_pgoff(file, a.addr, a.len, a.prot, a.flags, pgoff);
 134        up_write(&current->mm->mmap_sem);
 135        if (file)
 136                fput(file);
 137out:
 138        return error;
 139}
 140#endif
 141
 142struct sel_arg_struct {
 143        unsigned long n;
 144        fd_set *inp, *outp, *exp;
 145        struct timeval *tvp;
 146};
 147
 148asmlinkage int old_select(struct sel_arg_struct *arg)
 149{
 150        struct sel_arg_struct a;
 151
 152        if (copy_from_user(&a, arg, sizeof(a)))
 153                return -EFAULT;
 154        /* sys_select() does the appropriate kernel locking */
 155        return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp);
 156}
 157
 158/*
 159 * sys_ipc() is the de-multiplexer for the SysV IPC calls..
 160 *
 161 * This is really horribly ugly.
 162 */
 163asmlinkage int sys_ipc (uint call, int first, int second,
 164                        int third, void *ptr, long fifth)
 165{
 166        int version, ret;
 167
 168        version = call >> 16; /* hack for backward compatibility */
 169        call &= 0xffff;
 170
 171        if (call <= SEMCTL)
 172                switch (call) {
 173                case SEMOP:
 174                        return sys_semop (first, (struct sembuf *)ptr, second);
 175                case SEMGET:
 176                        return sys_semget (first, second, third);
 177                case SEMCTL: {
 178                        union semun fourth;
 179                        if (!ptr)
 180                                return -EINVAL;
 181                        if (get_user(fourth.__pad, (void **) ptr))
 182                                return -EFAULT;
 183                        return sys_semctl (first, second, third, fourth);
 184                        }
 185                default:
 186                        return -EINVAL;
 187                }
 188        if (call <= MSGCTL) 
 189                switch (call) {
 190                case MSGSND:
 191                        return sys_msgsnd (first, (struct msgbuf *) ptr, 
 192                                          second, third);
 193                case MSGRCV:
 194                        switch (version) {
 195                        case 0: {
 196                                struct ipc_kludge tmp;
 197                                if (!ptr)
 198                                        return -EINVAL;
 199                                if (copy_from_user (&tmp,
 200                                                    (struct ipc_kludge *)ptr,
 201                                                    sizeof (tmp)))
 202                                        return -EFAULT;
 203                                return sys_msgrcv (first, tmp.msgp, second,
 204                                                   tmp.msgtyp, third);
 205                                }
 206                        default:
 207                                return sys_msgrcv (first,
 208                                                   (struct msgbuf *) ptr,
 209                                                   second, fifth, third);
 210                        }
 211                case MSGGET:
 212                        return sys_msgget ((key_t) first, second);
 213                case MSGCTL:
 214                        return sys_msgctl (first, second,
 215                                           (struct msqid_ds *) ptr);
 216                default:
 217                        return -EINVAL;
 218                }
 219        if (call <= SHMCTL) 
 220                switch (call) {
 221                case SHMAT:
 222                        switch (version) {
 223                        default: {
 224                                ulong raddr;
 225                                ret = do_shmat (first, (char *) ptr,
 226                                                 second, &raddr);
 227                                if (ret)
 228                                        return ret;
 229                                return put_user (raddr, (ulong *) third);
 230                        }
 231                        }
 232                case SHMDT: 
 233                        return sys_shmdt ((char *)ptr);
 234                case SHMGET:
 235                        return sys_shmget (first, second, third);
 236                case SHMCTL:
 237                        return sys_shmctl (first, second,
 238                                           (struct shmid_ds *) ptr);
 239                default:
 240                        return -EINVAL;
 241                }
 242
 243        return -EINVAL;
 244}
 245
 246/* sys_cacheflush -- no support.  */
 247asmlinkage int
 248sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
 249{
 250        return -EINVAL;
 251}
 252
 253asmlinkage int sys_getpagesize(void)
 254{
 255        return PAGE_SIZE;
 256}
 257
 258#if defined(CONFIG_SYSCALL_PRINT)
 259asmlinkage void syscall_print(void *dummy,...)
 260{
 261        struct pt_regs *regs = (struct pt_regs *) ((unsigned char *)&dummy-4);
 262        printk("call %06lx:%ld 1:%08lx,2:%08lx,3:%08lx,ret:%08lx\n",
 263               ((regs->pc)&0xffffff)-2,regs->orig_er0,regs->er1,regs->er2,regs->er3,regs->er0);
 264}
 265#endif
 266
 267/*
 268 * Do a system call from kernel instead of calling sys_execve so we
 269 * end up with proper pt_regs.
 270 */
 271int kernel_execve(const char *filename, char *const argv[], char *const envp[])
 272{
 273        register long res __asm__("er0");
 274        register char *const *_c __asm__("er3") = envp;
 275        register char *const *_b __asm__("er2") = argv;
 276        register const char * _a __asm__("er1") = filename;
 277        __asm__ __volatile__ ("mov.l %1,er0\n\t"
 278                        "trapa  #0\n\t"
 279                        : "=r" (res)
 280                        : "g" (__NR_execve),
 281                          "g" (_a),
 282                          "g" (_b),
 283                          "g" (_c)
 284                        : "cc", "memory");
 285        return res;
 286}
 287
 288
 289