Chen Liqin | 6bc9a39 | 2009-06-12 22:01:00 +0800 | [diff] [blame] | 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> |
Chen Liqin | cf52c46 | 2009-08-30 12:33:30 +0800 | [diff] [blame] | 28 | #include <linux/mm.h> |
Chen Liqin | 6bc9a39 | 2009-06-12 22:01:00 +0800 | [diff] [blame] | 29 | #include <linux/mman.h> |
| 30 | #include <linux/module.h> |
Tejun Heo | 5a0e3ad | 2010-03-24 17:04:11 +0900 | [diff] [blame] | 31 | #include <linux/slab.h> |
Chen Liqin | 6bc9a39 | 2009-06-12 22:01:00 +0800 | [diff] [blame] | 32 | #include <linux/unistd.h> |
Arnd Bergmann | 9fb24cc | 2009-06-27 14:50:51 +0200 | [diff] [blame] | 33 | #include <linux/syscalls.h> |
| 34 | #include <asm/syscalls.h> |
Chen Liqin | 6bc9a39 | 2009-06-12 22:01:00 +0800 | [diff] [blame] | 35 | |
Arnd Bergmann | c606747 | 2009-06-27 14:46:35 +0200 | [diff] [blame] | 36 | asmlinkage long |
Chen Liqin | 6bc9a39 | 2009-06-12 22:01:00 +0800 | [diff] [blame] | 37 | sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot, |
| 38 | unsigned long flags, unsigned long fd, unsigned long pgoff) |
| 39 | { |
Al Viro | f8b7256 | 2009-11-30 17:37:04 -0500 | [diff] [blame] | 40 | return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff); |
Chen Liqin | 6bc9a39 | 2009-06-12 22:01:00 +0800 | [diff] [blame] | 41 | } |
| 42 | |
Chen Liqin | cf52c46 | 2009-08-30 12:33:30 +0800 | [diff] [blame] | 43 | asmlinkage long |
| 44 | sys_mmap(unsigned long addr, unsigned long len, unsigned long prot, |
Al Viro | aa65607 | 2009-12-11 06:48:57 -0500 | [diff] [blame] | 45 | unsigned long flags, unsigned long fd, off_t offset) |
Chen Liqin | cf52c46 | 2009-08-30 12:33:30 +0800 | [diff] [blame] | 46 | { |
Al Viro | aa65607 | 2009-12-11 06:48:57 -0500 | [diff] [blame] | 47 | if (unlikely(offset & ~PAGE_MASK)) |
| 48 | return -EINVAL; |
| 49 | return sys_mmap_pgoff(addr, len, prot, flags, fd, offset >> PAGE_SHIFT); |
Chen Liqin | cf52c46 | 2009-08-30 12:33:30 +0800 | [diff] [blame] | 50 | } |
| 51 | |
| 52 | asmlinkage long |
| 53 | score_fork(struct pt_regs *regs) |
| 54 | { |
| 55 | return do_fork(SIGCHLD, regs->regs[0], regs, 0, NULL, NULL); |
| 56 | } |
| 57 | |
Chen Liqin | 6bc9a39 | 2009-06-12 22:01:00 +0800 | [diff] [blame] | 58 | /* |
| 59 | * Clone a task - this clones the calling program thread. |
| 60 | * This is called indirectly via a small wrapper |
| 61 | */ |
Arnd Bergmann | bddc605 | 2009-06-27 15:12:16 +0200 | [diff] [blame] | 62 | asmlinkage long |
| 63 | score_clone(struct pt_regs *regs) |
Chen Liqin | 6bc9a39 | 2009-06-12 22:01:00 +0800 | [diff] [blame] | 64 | { |
| 65 | unsigned long clone_flags; |
| 66 | unsigned long newsp; |
| 67 | int __user *parent_tidptr, *child_tidptr; |
| 68 | |
| 69 | clone_flags = regs->regs[4]; |
| 70 | newsp = regs->regs[5]; |
| 71 | if (!newsp) |
| 72 | newsp = regs->regs[0]; |
| 73 | parent_tidptr = (int __user *)regs->regs[6]; |
Arnd Bergmann | f673c03 | 2009-06-19 11:31:54 +0200 | [diff] [blame] | 74 | child_tidptr = (int __user *)regs->regs[8]; |
Chen Liqin | 6bc9a39 | 2009-06-12 22:01:00 +0800 | [diff] [blame] | 75 | |
| 76 | return do_fork(clone_flags, newsp, regs, 0, |
| 77 | parent_tidptr, child_tidptr); |
| 78 | } |
| 79 | |
Chen Liqin | cf52c46 | 2009-08-30 12:33:30 +0800 | [diff] [blame] | 80 | asmlinkage long |
| 81 | score_vfork(struct pt_regs *regs) |
| 82 | { |
| 83 | return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, |
| 84 | regs->regs[0], regs, 0, NULL, NULL); |
| 85 | } |
| 86 | |
Chen Liqin | 6bc9a39 | 2009-06-12 22:01:00 +0800 | [diff] [blame] | 87 | /* |
| 88 | * sys_execve() executes a new program. |
| 89 | * This is called indirectly via a small wrapper |
| 90 | */ |
Arnd Bergmann | a1f8213 | 2009-06-27 15:05:30 +0200 | [diff] [blame] | 91 | asmlinkage long |
| 92 | score_execve(struct pt_regs *regs) |
Chen Liqin | 6bc9a39 | 2009-06-12 22:01:00 +0800 | [diff] [blame] | 93 | { |
| 94 | int error; |
| 95 | char *filename; |
| 96 | |
Arnd Bergmann | a1f8213 | 2009-06-27 15:05:30 +0200 | [diff] [blame] | 97 | filename = getname((char __user*)regs->regs[4]); |
Chen Liqin | 6bc9a39 | 2009-06-12 22:01:00 +0800 | [diff] [blame] | 98 | error = PTR_ERR(filename); |
| 99 | if (IS_ERR(filename)) |
| 100 | return error; |
| 101 | |
David Howells | d762746 | 2010-08-17 23:52:56 +0100 | [diff] [blame] | 102 | error = do_execve(filename, |
| 103 | (const char __user *const __user *)regs->regs[5], |
| 104 | (const char __user *const __user *)regs->regs[6], |
| 105 | regs); |
Chen Liqin | 6bc9a39 | 2009-06-12 22:01:00 +0800 | [diff] [blame] | 106 | |
| 107 | putname(filename); |
| 108 | return error; |
| 109 | } |
| 110 | |
| 111 | /* |
Chen Liqin | 6bc9a39 | 2009-06-12 22:01:00 +0800 | [diff] [blame] | 112 | * Do a system call from kernel instead of calling sys_execve so we |
| 113 | * end up with proper pt_regs. |
| 114 | */ |
David Howells | d762746 | 2010-08-17 23:52:56 +0100 | [diff] [blame] | 115 | int kernel_execve(const char *filename, |
| 116 | const char *const argv[], |
| 117 | const char *const envp[]) |
Chen Liqin | 6bc9a39 | 2009-06-12 22:01:00 +0800 | [diff] [blame] | 118 | { |
| 119 | register unsigned long __r4 asm("r4") = (unsigned long) filename; |
| 120 | register unsigned long __r5 asm("r5") = (unsigned long) argv; |
| 121 | register unsigned long __r6 asm("r6") = (unsigned long) envp; |
| 122 | register unsigned long __r7 asm("r7"); |
| 123 | |
| 124 | __asm__ __volatile__ (" \n" |
| 125 | "ldi r27, %5 \n" |
| 126 | "syscall \n" |
| 127 | "mv %0, r4 \n" |
| 128 | "mv %1, r7 \n" |
| 129 | : "=&r" (__r4), "=r" (__r7) |
| 130 | : "r" (__r4), "r" (__r5), "r" (__r6), "i" (__NR_execve) |
| 131 | : "r8", "r9", "r10", "r11", "r22", "r23", "r24", "r25", |
| 132 | "r26", "r27", "memory"); |
| 133 | |
| 134 | if (__r7 == 0) |
| 135 | return __r4; |
| 136 | |
| 137 | return -__r4; |
| 138 | } |