diff options
Diffstat (limited to 'arch/mips/kernel/syscall.c')
| -rw-r--r-- | arch/mips/kernel/syscall.c | 337 |
1 files changed, 20 insertions, 317 deletions
diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c index 3f7f466190b..4a4f9dda565 100644 --- a/arch/mips/kernel/syscall.c +++ b/arch/mips/kernel/syscall.c @@ -10,25 +10,22 @@ #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> -#include <linux/slab.h> #include <linux/utsname.h> #include <linux/unistd.h> #include <linux/sem.h> #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/elf.h> #include <asm/asm.h> #include <asm/branch.h> @@ -40,94 +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; - - task_size = STACK_TOP; - - 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 = TASK_UNMAPPED_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); - } + 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, @@ -157,105 +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((char __user *) (long)regs.regs[4]); - error = PTR_ERR(filename); - if (IS_ERR(filename)) - goto out; - error = do_execve(filename, (char __user *__user *) (long)regs.regs[5], - (char __user *__user *) (long)regs.regs[6], ®s); - putname(filename); - -out: - return error; -} - -/* - * Compacrapability ... - */ -SYSCALL_DEFINE1(uname, struct old_utsname __user *, name) -{ - if (name && !copy_to_user(name, utsname(), sizeof (*name))) - return 0; - return -EFAULT; -} - -/* - * Compacrapability ... - */ -SYSCALL_DEFINE1(olduname, struct oldold_utsname __user *, name) -{ - int error; - - if (!name) - return -EFAULT; - if (!access_ok(VERIFY_WRITE, name, sizeof(struct oldold_utsname))) - return -EFAULT; - - error = __copy_to_user(&name->sysname, &utsname()->sysname, - __OLD_UTS_LEN); - error -= __put_user(0, name->sysname + __OLD_UTS_LEN); - error -= __copy_to_user(&name->nodename, &utsname()->nodename, - __OLD_UTS_LEN); - error -= __put_user(0, name->nodename + __OLD_UTS_LEN); - error -= __copy_to_user(&name->release, &utsname()->release, - __OLD_UTS_LEN); - error -= __put_user(0, name->release + __OLD_UTS_LEN); - error -= __copy_to_user(&name->version, &utsname()->version, - __OLD_UTS_LEN); - error -= __put_user(0, name->version + __OLD_UTS_LEN); - error -= __copy_to_user(&name->machine, &utsname()->machine, - __OLD_UTS_LEN); - error = __put_user(0, name->machine + __OLD_UTS_LEN); - error = error ? -EFAULT : 0; - - return error; -} SYSCALL_DEFINE1(set_thread_area, unsigned long, addr) { @@ -268,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)) @@ -282,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" @@ -307,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" @@ -352,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 */ @@ -365,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) @@ -394,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; @@ -407,94 +227,6 @@ _sys_sysmips(nabi_no_regargs struct pt_regs regs) } /* - * sys_ipc() is the de-multiplexer for the SysV IPC calls.. - * - * This is really horribly ugly. - */ -SYSCALL_DEFINE6(ipc, unsigned int, call, int, first, int, second, - unsigned long, third, void __user *, ptr, long, fifth) -{ - int version, ret; - - version = call >> 16; /* hack for backward compatibility */ - call &= 0xffff; - - switch (call) { - case SEMOP: - return sys_semtimedop(first, (struct sembuf __user *)ptr, - second, NULL); - case SEMTIMEDOP: - return sys_semtimedop(first, (struct sembuf __user *)ptr, - second, - (const struct timespec __user *)fifth); - case SEMGET: - return sys_semget(first, second, third); - case SEMCTL: { - union semun fourth; - if (!ptr) - return -EINVAL; - if (get_user(fourth.__pad, (void __user *__user *) ptr)) - return -EFAULT; - return sys_semctl(first, second, third, fourth); - } - - case MSGSND: - return sys_msgsnd(first, (struct msgbuf __user *) ptr, - second, third); - case MSGRCV: - switch (version) { - case 0: { - struct ipc_kludge tmp; - if (!ptr) - return -EINVAL; - - if (copy_from_user(&tmp, - (struct ipc_kludge __user *) ptr, - sizeof(tmp))) - return -EFAULT; - return sys_msgrcv(first, tmp.msgp, second, - tmp.msgtyp, third); - } - default: - return sys_msgrcv(first, - (struct msgbuf __user *) ptr, - second, fifth, third); - } - case MSGGET: - return sys_msgget((key_t) first, second); - case MSGCTL: - return sys_msgctl(first, second, - (struct msqid_ds __user *) ptr); - - case SHMAT: - switch (version) { - default: { - unsigned long raddr; - ret = do_shmat(first, (char __user *) ptr, second, - &raddr); - if (ret) - return ret; - return put_user(raddr, (unsigned long __user *) third); - } - case 1: /* iBCS2 emulator entry point */ - if (!segment_eq(get_fs(), get_ds())) - return -EINVAL; - return do_shmat(first, (char __user *) ptr, second, - (unsigned long *) third); - } - case SHMDT: - return sys_shmdt((char __user *)ptr); - case SHMGET: - return sys_shmget(first, second, third); - case SHMCTL: - return sys_shmctl(first, second, - (struct shmid_ds __user *) ptr); - default: - return -ENOSYS; - } -} - -/* * No implemented yet ... */ SYSCALL_DEFINE3(cachectl, char *, addr, int, nbytes, int, op) @@ -510,32 +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, char *const argv[], 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; -} |
