linux/arch/score/kernel/sys_score.c
<<
>>
Prefs
   1/*
   2 * arch/score/kernel/syscall.c
   3 *
   4 * Score Processor version.
   5 *
   6 * Copyright (C) 2009 Sunplus Core Technology Co., Ltd.
   7 *  Chen Liqin <liqin.chen@sunplusct.com>
   8 *  Lennox Wu <lennox.wu@sunplusct.com>
   9 *
  10 * This program is free software; you can redistribute it and/or modify
  11 * it under the terms of the GNU General Public License as published by
  12 * the Free Software Foundation; either version 2 of the License, or
  13 * (at your option) any later version.
  14 *
  15 * This program is distributed in the hope that it will be useful,
  16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18 * GNU General Public License for more details.
  19 *
  20 * You should have received a copy of the GNU General Public License
  21 * along with this program; if not, see the file COPYING, or write
  22 * to the Free Software Foundation, Inc.,
  23 * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  24 */
  25
  26#include <linux/file.h>
  27#include <linux/fs.h>
  28#include <linux/mm.h>
  29#include <linux/mman.h>
  30#include <linux/module.h>
  31#include <linux/unistd.h>
  32#include <linux/syscalls.h>
  33#include <asm/syscalls.h>
  34
  35asmlinkage long 
  36sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
  37          unsigned long flags, unsigned long fd, unsigned long pgoff)
  38{
  39        int error = -EBADF;
  40        struct file *file = NULL;
  41
  42        if (pgoff & (~PAGE_MASK >> 12))
  43                return -EINVAL;
  44
  45        flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
  46        if (!(flags & MAP_ANONYMOUS)) {
  47                file = fget(fd);
  48                if (!file)
  49                        return error;
  50        }
  51
  52        down_write(&current->mm->mmap_sem);
  53        error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
  54        up_write(&current->mm->mmap_sem);
  55
  56        if (file)
  57                fput(file);
  58
  59        return error;
  60}
  61
  62asmlinkage long
  63sys_mmap(unsigned long addr, unsigned long len, unsigned long prot,
  64        unsigned long flags, unsigned long fd, off_t pgoff)
  65{
  66        return sys_mmap2(addr, len, prot, flags, fd, pgoff >> PAGE_SHIFT);
  67}
  68
  69asmlinkage long
  70score_fork(struct pt_regs *regs)
  71{
  72        return do_fork(SIGCHLD, regs->regs[0], regs, 0, NULL, NULL);
  73}
  74
  75/*
  76 * Clone a task - this clones the calling program thread.
  77 * This is called indirectly via a small wrapper
  78 */
  79asmlinkage long
  80score_clone(struct pt_regs *regs)
  81{
  82        unsigned long clone_flags;
  83        unsigned long newsp;
  84        int __user *parent_tidptr, *child_tidptr;
  85
  86        clone_flags = regs->regs[4];
  87        newsp = regs->regs[5];
  88        if (!newsp)
  89                newsp = regs->regs[0];
  90        parent_tidptr = (int __user *)regs->regs[6];
  91        child_tidptr = (int __user *)regs->regs[8];
  92
  93        return do_fork(clone_flags, newsp, regs, 0,
  94                        parent_tidptr, child_tidptr);
  95}
  96
  97asmlinkage long
  98score_vfork(struct pt_regs *regs)
  99{
 100        return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD,
 101                        regs->regs[0], regs, 0, NULL, NULL);
 102}
 103
 104/*
 105 * sys_execve() executes a new program.
 106 * This is called indirectly via a small wrapper
 107 */
 108asmlinkage long
 109score_execve(struct pt_regs *regs)
 110{
 111        int error;
 112        char *filename;
 113
 114        filename = getname((char __user*)regs->regs[4]);
 115        error = PTR_ERR(filename);
 116        if (IS_ERR(filename))
 117                return error;
 118
 119        error = do_execve(filename, (char __user *__user*)regs->regs[5],
 120                          (char __user *__user *) regs->regs[6], regs);
 121
 122        putname(filename);
 123        return error;
 124}
 125
 126/*
 127 * Do a system call from kernel instead of calling sys_execve so we
 128 * end up with proper pt_regs.
 129 */
 130int kernel_execve(const char *filename, char *const argv[], char *const envp[])
 131{
 132        register unsigned long __r4 asm("r4") = (unsigned long) filename;
 133        register unsigned long __r5 asm("r5") = (unsigned long) argv;
 134        register unsigned long __r6 asm("r6") = (unsigned long) envp;
 135        register unsigned long __r7 asm("r7");
 136
 137        __asm__ __volatile__ (" \n"
 138                "ldi    r27, %5         \n"
 139                "syscall                \n"
 140                "mv     %0, r4          \n"
 141                "mv     %1, r7          \n"
 142                : "=&r" (__r4), "=r" (__r7)
 143                : "r" (__r4), "r" (__r5), "r" (__r6), "i" (__NR_execve)
 144                : "r8", "r9", "r10", "r11", "r22", "r23", "r24", "r25",
 145                  "r26", "r27", "memory");
 146
 147        if (__r7 == 0)
 148                return __r4;
 149
 150        return -__r4;
 151}
 152