linux/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/module.h>
  16#include <linux/errno.h>
  17#include <linux/sched.h>
  18#include <linux/slab.h>
  19#include <linux/mm.h>
  20#include <linux/sem.h>
  21#include <linux/msg.h>
  22#include <linux/shm.h>
  23#include <linux/stat.h>
  24#include <linux/syscalls.h>
  25#include <linux/mman.h>
  26#include <linux/fs.h>
  27#include <linux/file.h>
  28#include <linux/ipc.h>
  29#include <linux/uaccess.h>
  30
  31struct mmap_arg_struct {
  32        unsigned long addr;
  33        unsigned long len;
  34        unsigned long prot;
  35        unsigned long flags;
  36        unsigned long fd;
  37        unsigned long offset;
  38};
  39
  40asmlinkage int old_mmap(struct mmap_arg_struct __user *arg)
  41{
  42        int error = -EFAULT;
  43        struct mmap_arg_struct a;
  44
  45        if (copy_from_user(&a, arg, sizeof(a)))
  46                goto out;
  47
  48        error = -EINVAL;
  49        if (a.offset & ~PAGE_MASK)
  50                goto out;
  51
  52        error = sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT);
  53out:
  54        return error;
  55}
  56
  57/*
  58 * Perform the select(nd, in, out, ex, tv) and mmap() system
  59 * calls.
  60 */
  61
  62struct sel_arg_struct {
  63        unsigned long n;
  64        fd_set __user *inp, *outp, *exp;
  65        struct timeval __user *tvp;
  66};
  67
  68asmlinkage int old_select(struct sel_arg_struct __user *arg)
  69{
  70        struct sel_arg_struct a;
  71
  72        if (copy_from_user(&a, arg, sizeof(a)))
  73                return -EFAULT;
  74        /* sys_select() does the appropriate kernel locking */
  75        return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp);
  76}
  77
  78#if !defined(CONFIG_AEABI) || defined(CONFIG_OABI_COMPAT)
  79/*
  80 * sys_ipc() is the de-multiplexer for the SysV IPC calls..
  81 *
  82 * This is really horribly ugly.
  83 */
  84asmlinkage int sys_ipc(uint call, int first, int second, int third,
  85                       void __user *ptr, long fifth)
  86{
  87        int version, ret;
  88
  89        version = call >> 16; /* hack for backward compatibility */
  90        call &= 0xffff;
  91
  92        switch (call) {
  93        case SEMOP:
  94                return sys_semtimedop (first, (struct sembuf __user *)ptr, second, NULL);
  95        case SEMTIMEDOP:
  96                return sys_semtimedop(first, (struct sembuf __user *)ptr, second,
  97                                        (const struct timespec __user *)fifth);
  98
  99        case SEMGET:
 100                return sys_semget (first, second, third);
 101        case SEMCTL: {
 102                union semun fourth;
 103                if (!ptr)
 104                        return -EINVAL;
 105                if (get_user(fourth.__pad, (void __user * __user *) ptr))
 106                        return -EFAULT;
 107                return sys_semctl (first, second, third, fourth);
 108        }
 109
 110        case MSGSND:
 111                return sys_msgsnd(first, (struct msgbuf __user *) ptr, 
 112                                  second, third);
 113        case MSGRCV:
 114                switch (version) {
 115                case 0: {
 116                        struct ipc_kludge tmp;
 117                        if (!ptr)
 118                                return -EINVAL;
 119                        if (copy_from_user(&tmp,(struct ipc_kludge __user *)ptr,
 120                                           sizeof (tmp)))
 121                                return -EFAULT;
 122                        return sys_msgrcv (first, tmp.msgp, second,
 123                                           tmp.msgtyp, third);
 124                }
 125                default:
 126                        return sys_msgrcv (first,
 127                                           (struct msgbuf __user *) ptr,
 128                                           second, fifth, third);
 129                }
 130        case MSGGET:
 131                return sys_msgget ((key_t) first, second);
 132        case MSGCTL:
 133                return sys_msgctl(first, second, (struct msqid_ds __user *)ptr);
 134
 135        case SHMAT:
 136                switch (version) {
 137                default: {
 138                        ulong raddr;
 139                        ret = do_shmat(first, (char __user *)ptr, second, &raddr);
 140                        if (ret)
 141                                return ret;
 142                        return put_user(raddr, (ulong __user *)third);
 143                }
 144                case 1: /* Of course, we don't support iBCS2! */
 145                        return -EINVAL;
 146                }
 147        case SHMDT: 
 148                return sys_shmdt ((char __user *)ptr);
 149        case SHMGET:
 150                return sys_shmget (first, second, third);
 151        case SHMCTL:
 152                return sys_shmctl (first, second,
 153                                   (struct shmid_ds __user *) ptr);
 154        default:
 155                return -ENOSYS;
 156        }
 157}
 158#endif
 159
 160/* Fork a new task - this creates a new program thread.
 161 * This is called indirectly via a small wrapper
 162 */
 163asmlinkage int sys_fork(struct pt_regs *regs)
 164{
 165#ifdef CONFIG_MMU
 166        return do_fork(SIGCHLD, regs->ARM_sp, regs, 0, NULL, NULL);
 167#else
 168        /* can not support in nommu mode */
 169        return(-EINVAL);
 170#endif
 171}
 172
 173/* Clone a task - this clones the calling program thread.
 174 * This is called indirectly via a small wrapper
 175 */
 176asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
 177                         int __user *parent_tidptr, int tls_val,
 178                         int __user *child_tidptr, struct pt_regs *regs)
 179{
 180        if (!newsp)
 181                newsp = regs->ARM_sp;
 182
 183        return do_fork(clone_flags, newsp, regs, 0, parent_tidptr, child_tidptr);
 184}
 185
 186asmlinkage int sys_vfork(struct pt_regs *regs)
 187{
 188        return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->ARM_sp, regs, 0, NULL, NULL);
 189}
 190
 191/* sys_execve() executes a new program.
 192 * This is called indirectly via a small wrapper
 193 */
 194asmlinkage int sys_execve(char __user *filenamei, char __user * __user *argv,
 195                          char __user * __user *envp, struct pt_regs *regs)
 196{
 197        int error;
 198        char * filename;
 199
 200        filename = getname(filenamei);
 201        error = PTR_ERR(filename);
 202        if (IS_ERR(filename))
 203                goto out;
 204        error = do_execve(filename, argv, envp, regs);
 205        putname(filename);
 206out:
 207        return error;
 208}
 209
 210int kernel_execve(const char *filename, char *const argv[], char *const envp[])
 211{
 212        struct pt_regs regs;
 213        int ret;
 214
 215        memset(&regs, 0, sizeof(struct pt_regs));
 216        ret = do_execve((char *)filename, (char __user * __user *)argv,
 217                        (char __user * __user *)envp, &regs);
 218        if (ret < 0)
 219                goto out;
 220
 221        /*
 222         * Save argc to the register structure for userspace.
 223         */
 224        regs.ARM_r0 = ret;
 225
 226        /*
 227         * We were successful.  We won't be returning to our caller, but
 228         * instead to user space by manipulating the kernel stack.
 229         */
 230        asm(    "add    r0, %0, %1\n\t"
 231                "mov    r1, %2\n\t"
 232                "mov    r2, %3\n\t"
 233                "bl     memmove\n\t"    /* copy regs to top of stack */
 234                "mov    r8, #0\n\t"     /* not a syscall */
 235                "mov    r9, %0\n\t"     /* thread structure */
 236                "mov    sp, r0\n\t"     /* reposition stack pointer */
 237                "b      ret_to_user"
 238                :
 239                : "r" (current_thread_info()),
 240                  "Ir" (THREAD_START_SP - sizeof(regs)),
 241                  "r" (&regs),
 242                  "Ir" (sizeof(regs))
 243                : "r0", "r1", "r2", "r3", "ip", "lr", "memory");
 244
 245 out:
 246        return ret;
 247}
 248EXPORT_SYMBOL(kernel_execve);
 249
 250/*
 251 * Since loff_t is a 64 bit type we avoid a lot of ABI hassle
 252 * with a different argument ordering.
 253 */
 254asmlinkage long sys_arm_fadvise64_64(int fd, int advice,
 255                                     loff_t offset, loff_t len)
 256{
 257        return sys_fadvise64_64(fd, offset, len, advice);
 258}
 259
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.