diff options
Diffstat (limited to 'arch/mips/kernel/syscall.c')
| -rw-r--r-- | arch/mips/kernel/syscall.c | 258 |
1 files changed, 18 insertions, 240 deletions
diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c index 1dc6edff45e..4a4f9dda565 100644 --- a/arch/mips/kernel/syscall.c +++ b/arch/mips/kernel/syscall.c @@ -10,12 +10,9 @@ #include <linux/capability.h> #include <linux/errno.h> #include <linux/linkage.h> -#include <linux/mm.h> #include <linux/fs.h> #include <linux/smp.h> -#include <linux/mman.h> #include <linux/ptrace.h> -#include <linux/sched.h> #include <linux/string.h> #include <linux/syscalls.h> #include <linux/file.h> @@ -25,11 +22,9 @@ #include <linux/msg.h> #include <linux/shm.h> #include <linux/compiler.h> -#include <linux/module.h> #include <linux/ipc.h> #include <linux/uaccess.h> #include <linux/slab.h> -#include <linux/random.h> #include <linux/elf.h> #include <asm/asm.h> @@ -42,143 +37,23 @@ #include <asm/shmparam.h> #include <asm/sysmips.h> #include <asm/uaccess.h> +#include <asm/switch_to.h> /* * For historic reasons the pipe(2) syscall on MIPS has an unusual calling - * convention. It returns results in registers $v0 / $v1 which means there + * convention. It returns results in registers $v0 / $v1 which means there * is no need for it to do verify the validity of a userspace pointer - * argument. Historically that used to be expensive in Linux. These days + * argument. Historically that used to be expensive in Linux. These days * the performance advantage is negligible. */ -asmlinkage int sysm_pipe(nabi_no_regargs volatile struct pt_regs regs) +asmlinkage int sysm_pipe(void) { int fd[2]; - int error, res; - - error = do_pipe_flags(fd, 0); - if (error) { - res = error; - goto out; - } - regs.regs[3] = fd[1]; - res = fd[0]; -out: - return res; -} - -unsigned long shm_align_mask = PAGE_SIZE - 1; /* Sane caches */ - -EXPORT_SYMBOL(shm_align_mask); - -#define COLOUR_ALIGN(addr,pgoff) \ - ((((addr) + shm_align_mask) & ~shm_align_mask) + \ - (((pgoff) << PAGE_SHIFT) & shm_align_mask)) - -unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, - unsigned long len, unsigned long pgoff, unsigned long flags) -{ - struct vm_area_struct * vmm; - int do_color_align; - unsigned long task_size; - -#ifdef CONFIG_32BIT - task_size = TASK_SIZE; -#else /* Must be CONFIG_64BIT*/ - task_size = test_thread_flag(TIF_32BIT_ADDR) ? TASK_SIZE32 : TASK_SIZE; -#endif - - if (len > task_size) - return -ENOMEM; - - if (flags & MAP_FIXED) { - /* Even MAP_FIXED mappings must reside within task_size. */ - if (task_size - len < addr) - return -EINVAL; - - /* - * We do not accept a shared mapping if it would violate - * cache aliasing constraints. - */ - if ((flags & MAP_SHARED) && - ((addr - (pgoff << PAGE_SHIFT)) & shm_align_mask)) - return -EINVAL; - return addr; - } - - do_color_align = 0; - if (filp || (flags & MAP_SHARED)) - do_color_align = 1; - if (addr) { - if (do_color_align) - addr = COLOUR_ALIGN(addr, pgoff); - else - addr = PAGE_ALIGN(addr); - vmm = find_vma(current->mm, addr); - if (task_size - len >= addr && - (!vmm || addr + len <= vmm->vm_start)) - return addr; - } - addr = current->mm->mmap_base; - if (do_color_align) - addr = COLOUR_ALIGN(addr, pgoff); - else - addr = PAGE_ALIGN(addr); - - for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) { - /* At this point: (!vmm || addr < vmm->vm_end). */ - if (task_size - len < addr) - return -ENOMEM; - if (!vmm || addr + len <= vmm->vm_start) - return addr; - addr = vmm->vm_end; - if (do_color_align) - addr = COLOUR_ALIGN(addr, pgoff); - } -} - -void arch_pick_mmap_layout(struct mm_struct *mm) -{ - unsigned long random_factor = 0UL; - - if (current->flags & PF_RANDOMIZE) { - random_factor = get_random_int(); - random_factor = random_factor << PAGE_SHIFT; - if (TASK_IS_32BIT_ADDR) - random_factor &= 0xfffffful; - else - random_factor &= 0xffffffful; - } - - mm->mmap_base = TASK_UNMAPPED_BASE + random_factor; - mm->get_unmapped_area = arch_get_unmapped_area; - mm->unmap_area = arch_unmap_area; -} - -static inline unsigned long brk_rnd(void) -{ - unsigned long rnd = get_random_int(); - - rnd = rnd << PAGE_SHIFT; - /* 8MB for 32bit, 256MB for 64bit */ - if (TASK_IS_32BIT_ADDR) - rnd = rnd & 0x7ffffful; - else - rnd = rnd & 0xffffffful; - - return rnd; -} - -unsigned long arch_randomize_brk(struct mm_struct *mm) -{ - unsigned long base = mm->brk; - unsigned long ret; - - ret = PAGE_ALIGN(base + brk_rnd()); - - if (ret < mm->brk) - return mm->brk; - - return ret; + int error = do_pipe_flags(fd, 0); + if (error) + return error; + current_pt_regs()->regs[3] = fd[1]; + return fd[0]; } SYSCALL_DEFINE6(mips_mmap, unsigned long, addr, unsigned long, len, @@ -208,65 +83,7 @@ SYSCALL_DEFINE6(mips_mmap2, unsigned long, addr, unsigned long, len, } save_static_function(sys_fork); -static int __used noinline -_sys_fork(nabi_no_regargs struct pt_regs regs) -{ - return do_fork(SIGCHLD, regs.regs[29], ®s, 0, NULL, NULL); -} - save_static_function(sys_clone); -static int __used noinline -_sys_clone(nabi_no_regargs struct pt_regs regs) -{ - unsigned long clone_flags; - unsigned long newsp; - int __user *parent_tidptr, *child_tidptr; - - clone_flags = regs.regs[4]; - newsp = regs.regs[5]; - if (!newsp) - newsp = regs.regs[29]; - parent_tidptr = (int __user *) regs.regs[6]; -#ifdef CONFIG_32BIT - /* We need to fetch the fifth argument off the stack. */ - child_tidptr = NULL; - if (clone_flags & (CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID)) { - int __user *__user *usp = (int __user *__user *) regs.regs[29]; - if (regs.regs[2] == __NR_syscall) { - if (get_user (child_tidptr, &usp[5])) - return -EFAULT; - } - else if (get_user (child_tidptr, &usp[4])) - return -EFAULT; - } -#else - child_tidptr = (int __user *) regs.regs[8]; -#endif - return do_fork(clone_flags, newsp, ®s, 0, - parent_tidptr, child_tidptr); -} - -/* - * sys_execve() executes a new program. - */ -asmlinkage int sys_execve(nabi_no_regargs struct pt_regs regs) -{ - int error; - char * filename; - - filename = getname((const char __user *) (long)regs.regs[4]); - error = PTR_ERR(filename); - if (IS_ERR(filename)) - goto out; - error = do_execve(filename, - (const char __user *const __user *) (long)regs.regs[5], - (const char __user *const __user *) (long)regs.regs[6], - ®s); - putname(filename); - -out: - return error; -} SYSCALL_DEFINE1(set_thread_area, unsigned long, addr) { @@ -279,10 +96,10 @@ SYSCALL_DEFINE1(set_thread_area, unsigned long, addr) return 0; } -static inline int mips_atomic_set(struct pt_regs *regs, - unsigned long addr, unsigned long new) +static inline int mips_atomic_set(unsigned long addr, unsigned long new) { unsigned long old, tmp; + struct pt_regs *regs; unsigned int err; if (unlikely(addr & 3)) @@ -293,7 +110,7 @@ static inline int mips_atomic_set(struct pt_regs *regs, if (cpu_has_llsc && R10000_LLSC_WAR) { __asm__ __volatile__ ( - " .set mips3 \n" + " .set arch=r4000 \n" " li %[err], 0 \n" "1: ll %[old], (%[addr]) \n" " move %[tmp], %[new] \n" @@ -318,7 +135,7 @@ static inline int mips_atomic_set(struct pt_regs *regs, : "memory"); } else if (cpu_has_llsc) { __asm__ __volatile__ ( - " .set mips3 \n" + " .set arch=r4000 \n" " li %[err], 0 \n" "1: ll %[old], (%[addr]) \n" " move %[tmp], %[new] \n" @@ -363,6 +180,7 @@ static inline int mips_atomic_set(struct pt_regs *regs, if (unlikely(err)) return err; + regs = current_pt_regs(); regs->regs[2] = old; regs->regs[7] = 0; /* No error */ @@ -376,23 +194,14 @@ static inline int mips_atomic_set(struct pt_regs *regs, : "r" (regs)); /* unreached. Honestly. */ - while (1); + unreachable(); } -save_static_function(sys_sysmips); -static int __used noinline -_sys_sysmips(nabi_no_regargs struct pt_regs regs) +SYSCALL_DEFINE3(sysmips, long, cmd, long, arg1, long, arg2) { - long cmd, arg1, arg2, arg3; - - cmd = regs.regs[4]; - arg1 = regs.regs[5]; - arg2 = regs.regs[6]; - arg3 = regs.regs[7]; - switch (cmd) { case MIPS_ATOMIC_SET: - return mips_atomic_set(®s, arg1, arg2); + return mips_atomic_set(arg1, arg2); case MIPS_FIXADE: if (arg1 & ~3) @@ -405,7 +214,7 @@ _sys_sysmips(nabi_no_regargs struct pt_regs regs) if (arg1 & 2) set_thread_flag(TIF_LOGADE); else - clear_thread_flag(TIF_FIXADE); + clear_thread_flag(TIF_LOGADE); return 0; @@ -433,34 +242,3 @@ asmlinkage void bad_stack(void) { do_exit(SIGSEGV); } - -/* - * 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, - const char *const argv[], - const char *const envp[]) -{ - register unsigned long __a0 asm("$4") = (unsigned long) filename; - register unsigned long __a1 asm("$5") = (unsigned long) argv; - register unsigned long __a2 asm("$6") = (unsigned long) envp; - register unsigned long __a3 asm("$7"); - unsigned long __v0; - - __asm__ volatile (" \n" - " .set noreorder \n" - " li $2, %5 # __NR_execve \n" - " syscall \n" - " move %0, $2 \n" - " .set reorder \n" - : "=&r" (__v0), "=r" (__a3) - : "r" (__a0), "r" (__a1), "r" (__a2), "i" (__NR_execve) - : "$2", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", - "memory"); - - if (__a3 == 0) - return __v0; - - return -__v0; -} |
