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/export.h>
  16#include <linux/errno.h>
  17#include <linux/sched.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/syscalls.h>
  24#include <linux/mman.h>
  25#include <linux/fs.h>
  26#include <linux/file.h>
  27#include <linux/ipc.h>
  28#include <linux/uaccess.h>
  29#include <linux/slab.h>
  30
  31/* Fork a new task - this creates a new program thread.
  32 * This is called indirectly via a small wrapper
  33 */
  34asmlinkage int sys_fork(struct pt_regs *regs)
  35{
  36#ifdef CONFIG_MMU
  37        return do_fork(SIGCHLD, regs->ARM_sp, regs, 0, NULL, NULL);
  38#else
  39        /* can not support in nommu mode */
  40        return(-EINVAL);
  41#endif
  42}
  43
  44/* Clone a task - this clones the calling program thread.
  45 * This is called indirectly via a small wrapper
  46 */
  47asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
  48                         int __user *parent_tidptr, int tls_val,
  49                         int __user *child_tidptr, struct pt_regs *regs)
  50{
  51        if (!newsp)
  52                newsp = regs->ARM_sp;
  53
  54        return do_fork(clone_flags, newsp, regs, 0, parent_tidptr, child_tidptr);
  55}
  56
  57asmlinkage int sys_vfork(struct pt_regs *regs)
  58{
  59        return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->ARM_sp, regs, 0, NULL, NULL);
  60}
  61
  62/* sys_execve() executes a new program.
  63 * This is called indirectly via a small wrapper
  64 */
  65asmlinkage int sys_execve(const char __user *filenamei,
  66                          const char __user *const __user *argv,
  67                          const char __user *const __user *envp, struct pt_regs *regs)
  68{
  69        int error;
  70        char * filename;
  71
  72        filename = getname(filenamei);
  73        error = PTR_ERR(filename);
  74        if (IS_ERR(filename))
  75                goto out;
  76        error = do_execve(filename, argv, envp, regs);
  77        putname(filename);
  78out:
  79        return error;
  80}
  81
  82int kernel_execve(const char *filename,
  83                  const char *const argv[],
  84                  const char *const envp[])
  85{
  86        struct pt_regs regs;
  87        int ret;
  88
  89        memset(&regs, 0, sizeof(struct pt_regs));
  90        ret = do_execve(filename,
  91                        (const char __user *const __user *)argv,
  92                        (const char __user *const __user *)envp, &regs);
  93        if (ret < 0)
  94                goto out;
  95
  96        /*
  97         * Save argc to the register structure for userspace.
  98         */
  99        regs.ARM_r0 = ret;
 100
 101        /*
 102         * We were successful.  We won't be returning to our caller, but
 103         * instead to user space by manipulating the kernel stack.
 104         */
 105        asm(    "add    r0, %0, %1\n\t"
 106                "mov    r1, %2\n\t"
 107                "mov    r2, %3\n\t"
 108                "bl     memmove\n\t"    /* copy regs to top of stack */
 109                "mov    r8, #0\n\t"     /* not a syscall */
 110                "mov    r9, %0\n\t"     /* thread structure */
 111                "mov    sp, r0\n\t"     /* reposition stack pointer */
 112                "b      ret_to_user"
 113                :
 114                : "r" (current_thread_info()),
 115                  "Ir" (THREAD_START_SP - sizeof(regs)),
 116                  "r" (&regs),
 117                  "Ir" (sizeof(regs))
 118                : "r0", "r1", "r2", "r3", "ip", "lr", "memory");
 119
 120 out:
 121        return ret;
 122}
 123EXPORT_SYMBOL(kernel_execve);
 124
 125/*
 126 * Since loff_t is a 64 bit type we avoid a lot of ABI hassle
 127 * with a different argument ordering.
 128 */
 129asmlinkage long sys_arm_fadvise64_64(int fd, int advice,
 130                                     loff_t offset, loff_t len)
 131{
 132        return sys_fadvise64_64(fd, offset, len, advice);
 133}
 134