sys_microblaze.c 3.1 KB
Newer Older
M
Michal Simek 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
/*
 * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu>
 * Copyright (C) 2007-2009 PetaLogix
 * Copyright (C) 2007 John Williams <john.williams@petalogix.com>
 *
 * Copyright (C) 2006 Atmark Techno, Inc.
 *	Yasushi SHOJI <yashi@atmark-techno.com>
 *	Tetsuya OHKAWA <tetsuya@atmark-techno.com>
 *
 * This file is subject to the terms and conditions of the GNU General Public
 * License. See the file "COPYING" in the main directory of this archive
 * for more details.
 */

#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/syscalls.h>
#include <linux/sem.h>
#include <linux/msg.h>
#include <linux/shm.h>
#include <linux/stat.h>
#include <linux/mman.h>
#include <linux/sys.h>
#include <linux/ipc.h>
#include <linux/utsname.h>
#include <linux/file.h>
#include <linux/module.h>
#include <linux/err.h>
#include <linux/fs.h>
#include <linux/semaphore.h>
#include <linux/uaccess.h>
#include <linux/unistd.h>

#include <asm/syscalls.h>

37
asmlinkage long microblaze_vfork(struct pt_regs *regs)
M
Michal Simek 已提交
38 39 40 41 42
{
	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->r1,
						regs, 0, NULL, NULL);
}

43
asmlinkage long microblaze_clone(int flags, unsigned long stack, struct pt_regs *regs)
M
Michal Simek 已提交
44 45 46 47 48 49
{
	if (!stack)
		stack = regs->r1;
	return do_fork(flags, stack, regs, 0, NULL, NULL);
}

50
asmlinkage long microblaze_execve(char __user *filenamei, char __user *__user *argv,
M
Michal Simek 已提交
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
			char __user *__user *envp, struct pt_regs *regs)
{
	int error;
	char *filename;

	filename = getname(filenamei);
	error = PTR_ERR(filename);
	if (IS_ERR(filename))
		goto out;
	error = do_execve(filename, argv, envp, regs);
	putname(filename);
out:
	return error;
}

66 67
asmlinkage long
sys_mmap2(unsigned long addr, unsigned long len,
M
Michal Simek 已提交
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
	unsigned long prot, unsigned long flags,
	unsigned long fd, unsigned long pgoff)
{
	struct file *file = NULL;
	int ret = -EBADF;

	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
	if (!(flags & MAP_ANONYMOUS)) {
		file = fget(fd);
		if (!file) {
			printk(KERN_INFO "no fd in mmap\r\n");
			goto out;
		}
	}

	down_write(&current->mm->mmap_sem);
	ret = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
	up_write(&current->mm->mmap_sem);
	if (file)
		fput(file);
out:
	return ret;
}

92
asmlinkage long sys_mmap(unsigned long addr, unsigned long len,
M
Michal Simek 已提交
93
			unsigned long prot, unsigned long flags,
94
			unsigned long fd, off_t pgoff)
M
Michal Simek 已提交
95 96 97
{
	int err = -EINVAL;

98
	if (pgoff & ~PAGE_MASK) {
M
Michal Simek 已提交
99 100 101 102
		printk(KERN_INFO "no pagemask in mmap\r\n");
		goto out;
	}

103
	err = sys_mmap2(addr, len, prot, flags, fd, pgoff >> PAGE_SHIFT);
M
Michal Simek 已提交
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
out:
	return err;
}

/*
 * Do a system call from kernel instead of calling sys_execve so we
 * end up with proper pt_regs.
 */
int kernel_execve(const char *filename, char *const argv[], char *const envp[])
{
	register const char *__a __asm__("r5") = filename;
	register const void *__b __asm__("r6") = argv;
	register const void *__c __asm__("r7") = envp;
	register unsigned long __syscall __asm__("r12") = __NR_execve;
	register unsigned long __ret __asm__("r3");
	__asm__ __volatile__ ("brki r14, 0x8"
			: "=r" (__ret), "=r" (__syscall)
			: "1" (__syscall), "r" (__a), "r" (__b), "r" (__c)
			: "r4", "r8", "r9",
			"r10", "r11", "r14", "cc", "memory");
	return __ret;
}