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/utsname.h>
  21#include <linux/fs.h>
  22#include <linux/ipc.h>
  23
  24#include <asm/setup.h>
  25#include <asm/uaccess.h>
  26#include <asm/cachectl.h>
  27#include <asm/traps.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
  98#if 0 /* DAVIDM - do we want this */
  99struct mmap_arg_struct64 {
 100        __u32 addr;
 101        __u32 len;
 102        __u32 prot;
 103        __u32 flags;
 104        __u64 offset; /* 64 bits */
 105        __u32 fd;
 106};
 107
 108asmlinkage long sys_mmap64(struct mmap_arg_struct64 *arg)
 109{
 110        int error = -EFAULT;
 111        struct file * file = NULL;
 112        struct mmap_arg_struct64 a;
 113        unsigned long pgoff;
 114
 115        if (copy_from_user(&a, arg, sizeof(a)))
 116                return -EFAULT;
 117
 118        if ((long)a.offset & ~PAGE_MASK)
 119                return -EINVAL;
 120
 121        pgoff = a.offset >> PAGE_SHIFT;
 122        if ((a.offset >> PAGE_SHIFT) != pgoff)
 123                return -EINVAL;
 124
 125        if (!(a.flags & MAP_ANONYMOUS)) {
 126                error = -EBADF;
 127                file = fget(a.fd);
 128                if (!file)
 129                        goto out;
 130        }
 131        a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
 132
 133        down_write(&current->mm->mmap_sem);
 134        error = do_mmap_pgoff(file, a.addr, a.len, a.prot, a.flags, pgoff);
 135        up_write(&current->mm->mmap_sem);
 136        if (file)
 137                fput(file);
 138out:
 139        return error;
 140}
 141#endif
 142
 143struct sel_arg_struct {
 144        unsigned long n;
 145        fd_set *inp, *outp, *exp;
 146        struct timeval *tvp;
 147};
 148
 149asmlinkage int old_select(struct sel_arg_struct *arg)
 150{
 151        struct sel_arg_struct a;
 152
 153        if (copy_from_user(&a, arg, sizeof(a)))
 154                return -EFAULT;
 155        /* sys_select() does the appropriate kernel locking */
 156        return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp);
 157}
 158
 159/*
 160 * sys_ipc() is the de-multiplexer for the SysV IPC calls..
 161 *
 162 * This is really horribly ugly.
 163 */
 164asmlinkage int sys_ipc (uint call, int first, int second,
 165                        int third, void *ptr, long fifth)
 166{
 167        int version, ret;
 168
 169        version = call >> 16; /* hack for backward compatibility */
 170        call &= 0xffff;
 171
 172        if (call <= SEMCTL)
 173                switch (call) {
 174                case SEMOP:
 175                        return sys_semop (first, (struct sembuf *)ptr, second);
 176                case SEMGET:
 177                        return sys_semget (first, second, third);
 178                case SEMCTL: {
 179                        union semun fourth;
 180                        if (!ptr)
 181                                return -EINVAL;
 182                        if (get_user(fourth.__pad, (void **) ptr))
 183                                return -EFAULT;
 184                        return sys_semctl (first, second, third, fourth);
 185                        }
 186                default:
 187                        return -EINVAL;
 188                }
 189        if (call <= MSGCTL) 
 190                switch (call) {
 191                case MSGSND:
 192                        return sys_msgsnd (first, (struct msgbuf *) ptr, 
 193                                          second, third);
 194                case MSGRCV:
 195                        switch (version) {
 196                        case 0: {
 197                                struct ipc_kludge tmp;
 198                                if (!ptr)
 199                                        return -EINVAL;
 200                                if (copy_from_user (&tmp,
 201                                                    (struct ipc_kludge *)ptr,
 202                                                    sizeof (tmp)))
 203                                        return -EFAULT;
 204                                return sys_msgrcv (first, tmp.msgp, second,
 205                                                   tmp.msgtyp, third);
 206                                }
 207                        default:
 208                                return sys_msgrcv (first,
 209                                                   (struct msgbuf *) ptr,
 210                                                   second, fifth, third);
 211                        }
 212                case MSGGET:
 213                        return sys_msgget ((key_t) first, second);
 214                case MSGCTL:
 215                        return sys_msgctl (first, second,
 216                                           (struct msqid_ds *) ptr);
 217                default:
 218                        return -EINVAL;
 219                }
 220        if (call <= SHMCTL) 
 221                switch (call) {
 222                case SHMAT:
 223                        switch (version) {
 224                        default: {
 225                                ulong raddr;
 226                                ret = do_shmat (first, (char *) ptr,
 227                                                 second, &raddr);
 228                                if (ret)
 229                                        return ret;
 230                                return put_user (raddr, (ulong *) third);
 231                        }
 232                        }
 233                case SHMDT: 
 234                        return sys_shmdt ((char *)ptr);
 235                case SHMGET:
 236                        return sys_shmget (first, second, third);
 237                case SHMCTL:
 238                        return sys_shmctl (first, second,
 239                                           (struct shmid_ds *) ptr);
 240                default:
 241                        return -EINVAL;
 242                }
 243
 244        return -EINVAL;
 245}
 246
 247/* sys_cacheflush -- no support.  */
 248asmlinkage int
 249sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
 250{
 251        return -EINVAL;
 252}
 253
 254asmlinkage int sys_getpagesize(void)
 255{
 256        return PAGE_SIZE;
 257}
 258
 259#if defined(CONFIG_SYSCALL_PRINT)
 260asmlinkage void syscall_print(void *dummy,...)
 261{
 262        struct pt_regs *regs = (struct pt_regs *) ((unsigned char *)&dummy-4);
 263        printk("call %06lx:%ld 1:%08lx,2:%08lx,3:%08lx,ret:%08lx\n",
 264               ((regs->pc)&0xffffff)-2,regs->orig_er0,regs->er1,regs->er2,regs->er3,regs->er0);
 265}
 266#endif
 267
 268/*
 269 * Do a system call from kernel instead of calling sys_execve so we
 270 * end up with proper pt_regs.
 271 */
 272int kernel_execve(const char *filename, char *const argv[], char *const envp[])
 273{
 274        register long res __asm__("er0");
 275        register char *const *_c __asm__("er3") = envp;
 276        register char *const *_b __asm__("er2") = argv;
 277        register const char * _a __asm__("er1") = filename;
 278        __asm__ __volatile__ ("mov.l %1,er0\n\t"
 279                        "trapa  #0\n\t"
 280                        : "=r" (res)
 281                        : "g" (__NR_execve),
 282                          "g" (_a),
 283                          "g" (_b),
 284                          "g" (_c)
 285                        : "cc", "memory");
 286        return res;
 287}
 288
 289
 290
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.