linux-old/arch/arm/kernel/sys_arm.c
<<
>>
Prefs
   1/*
   2 *  linux/arch/arm/kernel/sys_arm.c
   3 *
   4 *  Copyright (C) People who wrote linux/arch/i386/kernel/sys_i386.c
   5 *  Copyright (C) 1995, 1996 Russell King.
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License version 2 as
   9 * published by the Free Software Foundation.
  10 *
  11 *  This file contains various random system calls that
  12 *  have a non-standard calling sequence on the Linux/arm
  13 *  platform.
  14 */
  15#include <linux/errno.h>
  16#include <linux/sched.h>
  17#include <linux/slab.h>
  18#include <linux/mm.h>
  19#include <linux/sem.h>
  20#include <linux/msg.h>
  21#include <linux/shm.h>
  22#include <linux/stat.h>
  23#include <linux/mman.h>
  24#include <linux/fs.h>
  25#include <linux/file.h>
  26#include <linux/utsname.h>
  27
  28#include <asm/uaccess.h>
  29#include <asm/ipc.h>
  30
  31extern unsigned long do_mremap(unsigned long addr, unsigned long old_len,
  32                               unsigned long new_len, unsigned long flags,
  33                               unsigned long new_addr);
  34
  35/*
  36 * sys_pipe() is the normal C calling standard for creating
  37 * a pipe. It's not the way unix traditionally does this, though.
  38 */
  39asmlinkage int sys_pipe(unsigned long * fildes)
  40{
  41        int fd[2];
  42        int error;
  43
  44        error = do_pipe(fd);
  45        if (!error) {
  46                if (copy_to_user(fildes, fd, 2*sizeof(int)))
  47                        error = -EFAULT;
  48        }
  49        return error;
  50}
  51
  52/* common code for old and new mmaps */
  53inline long do_mmap2(
  54        unsigned long addr, unsigned long len,
  55        unsigned long prot, unsigned long flags,
  56        unsigned long fd, unsigned long pgoff)
  57{
  58        int error = -EINVAL;
  59        struct file * file = NULL;
  60
  61        flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
  62
  63        /*
  64         * If we are doing a fixed mapping, and address < PAGE_SIZE,
  65         * then deny it.
  66         */
  67        if (flags & MAP_FIXED && addr < PAGE_SIZE && vectors_base() == 0)
  68                goto out;
  69
  70        error = -EBADF;
  71        if (!(flags & MAP_ANONYMOUS)) {
  72                file = fget(fd);
  73                if (!file)
  74                        goto out;
  75        }
  76
  77        down_write(&current->mm->mmap_sem);
  78        error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
  79        up_write(&current->mm->mmap_sem);
  80
  81        if (file)
  82                fput(file);
  83out:
  84        return error;
  85}
  86
  87struct mmap_arg_struct {
  88        unsigned long addr;
  89        unsigned long len;
  90        unsigned long prot;
  91        unsigned long flags;
  92        unsigned long fd;
  93        unsigned long offset;
  94};
  95
  96asmlinkage int old_mmap(struct mmap_arg_struct *arg)
  97{
  98        int error = -EFAULT;
  99        struct mmap_arg_struct a;
 100
 101        if (copy_from_user(&a, arg, sizeof(a)))
 102                goto out;;
 103
 104        error = -EINVAL;
 105        if (a.offset & ~PAGE_MASK)
 106                goto out;
 107
 108        error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT);
 109out:
 110        return error;
 111}
 112
 113asmlinkage unsigned long
 114sys_arm_mremap(unsigned long addr, unsigned long old_len,
 115               unsigned long new_len, unsigned long flags,
 116               unsigned long new_addr)
 117{
 118        unsigned long ret = -EINVAL;
 119
 120        /*
 121         * If we are doing a fixed mapping, and address < PAGE_SIZE,
 122         * then deny it.
 123         */
 124        if (flags & MREMAP_FIXED && new_addr < PAGE_SIZE &&
 125            vectors_base() == 0)
 126                goto out;
 127
 128        down_write(&current->mm->mmap_sem);
 129        ret = do_mremap(addr, old_len, new_len, flags, new_addr);
 130        up_write(&current->mm->mmap_sem);
 131
 132out:
 133        return ret;
 134}
 135
 136/*
 137 * Perform the select(nd, in, out, ex, tv) and mmap() system
 138 * calls.
 139 */
 140extern asmlinkage int sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
 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, int third, void *ptr, long fifth)
 164{
 165        int version, ret;
 166
 167        version = call >> 16; /* hack for backward compatibility */
 168        call &= 0xffff;
 169
 170        switch (call) {
 171        case SEMOP:
 172                return sys_semop (first, (struct sembuf *)ptr, second);
 173        case SEMGET:
 174                return sys_semget (first, second, third);
 175        case SEMCTL: {
 176                union semun fourth;
 177                if (!ptr)
 178                        return -EINVAL;
 179                if (get_user(fourth.__pad, (void **) ptr))
 180                        return -EFAULT;
 181                return sys_semctl (first, second, third, fourth);
 182        }
 183
 184        case MSGSND:
 185                return sys_msgsnd (first, (struct msgbuf *) ptr, 
 186                                   second, third);
 187        case MSGRCV:
 188                switch (version) {
 189                case 0: {
 190                        struct ipc_kludge tmp;
 191                        if (!ptr)
 192                                return -EINVAL;
 193                        if (copy_from_user(&tmp,(struct ipc_kludge *) ptr,
 194                                           sizeof (tmp)))
 195                                return -EFAULT;
 196                        return sys_msgrcv (first, tmp.msgp, second,
 197                                           tmp.msgtyp, third);
 198                }
 199                default:
 200                        return sys_msgrcv (first,
 201                                           (struct msgbuf *) ptr,
 202                                           second, fifth, third);
 203                }
 204        case MSGGET:
 205                return sys_msgget ((key_t) first, second);
 206        case MSGCTL:
 207                return sys_msgctl (first, second, (struct msqid_ds *) ptr);
 208
 209        case SHMAT:
 210                switch (version) {
 211                default: {
 212                        ulong raddr;
 213                        ret = sys_shmat (first, (char *) ptr, second, &raddr);
 214                        if (ret)
 215                                return ret;
 216                        return put_user (raddr, (ulong *) third);
 217                }
 218                case 1: /* iBCS2 emulator entry point */
 219                        if (!segment_eq(get_fs(), get_ds()))
 220                                return -EINVAL;
 221                        return sys_shmat (first, (char *) ptr,
 222                                          second, (ulong *) third);
 223                }
 224        case SHMDT: 
 225                return sys_shmdt ((char *)ptr);
 226        case SHMGET:
 227                return sys_shmget (first, second, third);
 228        case SHMCTL:
 229                return sys_shmctl (first, second,
 230                                   (struct shmid_ds *) ptr);
 231        default:
 232                return -EINVAL;
 233        }
 234}
 235
 236/* Fork a new task - this creates a new program thread.
 237 * This is called indirectly via a small wrapper
 238 */
 239asmlinkage int sys_fork(struct pt_regs *regs)
 240{
 241        return do_fork(SIGCHLD, regs->ARM_sp, regs, 0);
 242}
 243
 244/* Clone a task - this clones the calling program thread.
 245 * This is called indirectly via a small wrapper
 246 */
 247asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, struct pt_regs *regs)
 248{
 249        if (!newsp)
 250                newsp = regs->ARM_sp;
 251        return do_fork(clone_flags, newsp, regs, 0);
 252}
 253
 254asmlinkage int sys_vfork(struct pt_regs *regs)
 255{
 256        return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->ARM_sp, regs, 0);
 257}
 258
 259/* sys_execve() executes a new program.
 260 * This is called indirectly via a small wrapper
 261 */
 262asmlinkage int sys_execve(char *filenamei, char **argv, char **envp, struct pt_regs *regs)
 263{
 264        int error;
 265        char * filename;
 266
 267        filename = getname(filenamei);
 268        error = PTR_ERR(filename);
 269        if (IS_ERR(filename))
 270                goto out;
 271        error = do_execve(filename, argv, envp, regs);
 272        putname(filename);
 273out:
 274        return error;
 275}
 276
 277asmlinkage int sys_pause(void)
 278{
 279        current->state = TASK_INTERRUPTIBLE;
 280        schedule();
 281        return -ERESTARTNOHAND;
 282}
 283
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.