| Michal Simek | 7dcbbb2 | 2009-03-27 14:25:28 +0100 | [diff] [blame] | 1 | /* | 
 | 2 |  * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu> | 
 | 3 |  * Copyright (C) 2007-2009 PetaLogix | 
 | 4 |  * Copyright (C) 2007 John Williams <john.williams@petalogix.com> | 
 | 5 |  * | 
 | 6 |  * Copyright (C) 2006 Atmark Techno, Inc. | 
 | 7 |  *	Yasushi SHOJI <yashi@atmark-techno.com> | 
 | 8 |  *	Tetsuya OHKAWA <tetsuya@atmark-techno.com> | 
 | 9 |  * | 
 | 10 |  * This file is subject to the terms and conditions of the GNU General Public | 
 | 11 |  * License. See the file "COPYING" in the main directory of this archive | 
 | 12 |  * for more details. | 
 | 13 |  */ | 
 | 14 |  | 
 | 15 | #include <linux/errno.h> | 
 | 16 | #include <linux/mm.h> | 
 | 17 | #include <linux/smp.h> | 
| Michal Simek | 7dcbbb2 | 2009-03-27 14:25:28 +0100 | [diff] [blame] | 18 | #include <linux/syscalls.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/sys.h> | 
 | 25 | #include <linux/ipc.h> | 
| Michal Simek | 7dcbbb2 | 2009-03-27 14:25:28 +0100 | [diff] [blame] | 26 | #include <linux/file.h> | 
 | 27 | #include <linux/module.h> | 
 | 28 | #include <linux/err.h> | 
 | 29 | #include <linux/fs.h> | 
| Michal Simek | 7dcbbb2 | 2009-03-27 14:25:28 +0100 | [diff] [blame] | 30 | #include <linux/semaphore.h> | 
| Michal Simek | 7dcbbb2 | 2009-03-27 14:25:28 +0100 | [diff] [blame] | 31 | #include <linux/uaccess.h> | 
 | 32 | #include <linux/unistd.h> | 
| Tejun Heo | 5a0e3ad | 2010-03-24 17:04:11 +0900 | [diff] [blame] | 33 | #include <linux/slab.h> | 
| Michal Simek | 7dcbbb2 | 2009-03-27 14:25:28 +0100 | [diff] [blame] | 34 |  | 
 | 35 | #include <asm/syscalls.h> | 
| Michal Simek | 7dcbbb2 | 2009-03-27 14:25:28 +0100 | [diff] [blame] | 36 |  | 
| Arnd Bergmann | e513588 | 2009-06-18 19:55:30 +0200 | [diff] [blame] | 37 | asmlinkage long microblaze_vfork(struct pt_regs *regs) | 
| Michal Simek | 7dcbbb2 | 2009-03-27 14:25:28 +0100 | [diff] [blame] | 38 | { | 
 | 39 | 	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->r1, | 
 | 40 | 						regs, 0, NULL, NULL); | 
 | 41 | } | 
 | 42 |  | 
| Michal Simek | 4302e52 | 2011-02-07 12:22:55 +0100 | [diff] [blame] | 43 | asmlinkage long microblaze_clone(int flags, unsigned long stack, | 
 | 44 | 							struct pt_regs *regs) | 
| Michal Simek | 7dcbbb2 | 2009-03-27 14:25:28 +0100 | [diff] [blame] | 45 | { | 
 | 46 | 	if (!stack) | 
 | 47 | 		stack = regs->r1; | 
 | 48 | 	return do_fork(flags, stack, regs, 0, NULL, NULL); | 
 | 49 | } | 
 | 50 |  | 
| David Howells | d762746 | 2010-08-17 23:52:56 +0100 | [diff] [blame] | 51 | asmlinkage long microblaze_execve(const char __user *filenamei, | 
 | 52 | 				  const char __user *const __user *argv, | 
 | 53 | 				  const char __user *const __user *envp, | 
 | 54 | 				  struct pt_regs *regs) | 
| Michal Simek | 7dcbbb2 | 2009-03-27 14:25:28 +0100 | [diff] [blame] | 55 | { | 
 | 56 | 	int error; | 
 | 57 | 	char *filename; | 
 | 58 |  | 
 | 59 | 	filename = getname(filenamei); | 
 | 60 | 	error = PTR_ERR(filename); | 
 | 61 | 	if (IS_ERR(filename)) | 
 | 62 | 		goto out; | 
 | 63 | 	error = do_execve(filename, argv, envp, regs); | 
 | 64 | 	putname(filename); | 
 | 65 | out: | 
 | 66 | 	return error; | 
 | 67 | } | 
 | 68 |  | 
| Arnd Bergmann | e513588 | 2009-06-18 19:55:30 +0200 | [diff] [blame] | 69 | asmlinkage long sys_mmap(unsigned long addr, unsigned long len, | 
| Michal Simek | 7dcbbb2 | 2009-03-27 14:25:28 +0100 | [diff] [blame] | 70 | 			unsigned long prot, unsigned long flags, | 
| Arnd Bergmann | e513588 | 2009-06-18 19:55:30 +0200 | [diff] [blame] | 71 | 			unsigned long fd, off_t pgoff) | 
| Michal Simek | 7dcbbb2 | 2009-03-27 14:25:28 +0100 | [diff] [blame] | 72 | { | 
| Al Viro | f8b7256 | 2009-11-30 17:37:04 -0500 | [diff] [blame] | 73 | 	if (pgoff & ~PAGE_MASK) | 
 | 74 | 		return -EINVAL; | 
| Michal Simek | 7dcbbb2 | 2009-03-27 14:25:28 +0100 | [diff] [blame] | 75 |  | 
| Al Viro | f8b7256 | 2009-11-30 17:37:04 -0500 | [diff] [blame] | 76 | 	return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff >> PAGE_SHIFT); | 
| Michal Simek | 7dcbbb2 | 2009-03-27 14:25:28 +0100 | [diff] [blame] | 77 | } | 
 | 78 |  | 
 | 79 | /* | 
 | 80 |  * Do a system call from kernel instead of calling sys_execve so we | 
 | 81 |  * end up with proper pt_regs. | 
 | 82 |  */ | 
| David Howells | d762746 | 2010-08-17 23:52:56 +0100 | [diff] [blame] | 83 | int kernel_execve(const char *filename, | 
 | 84 | 		  const char *const argv[], | 
 | 85 | 		  const char *const envp[]) | 
| Michal Simek | 7dcbbb2 | 2009-03-27 14:25:28 +0100 | [diff] [blame] | 86 | { | 
 | 87 | 	register const char *__a __asm__("r5") = filename; | 
 | 88 | 	register const void *__b __asm__("r6") = argv; | 
 | 89 | 	register const void *__c __asm__("r7") = envp; | 
 | 90 | 	register unsigned long __syscall __asm__("r12") = __NR_execve; | 
 | 91 | 	register unsigned long __ret __asm__("r3"); | 
 | 92 | 	__asm__ __volatile__ ("brki r14, 0x8" | 
 | 93 | 			: "=r" (__ret), "=r" (__syscall) | 
 | 94 | 			: "1" (__syscall), "r" (__a), "r" (__b), "r" (__c) | 
 | 95 | 			: "r4", "r8", "r9", | 
 | 96 | 			"r10", "r11", "r14", "cc", "memory"); | 
 | 97 | 	return __ret; | 
 | 98 | } |