include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[safe/jmp/linux-2.6] / arch / mips / kernel / syscall.c
index 343015a..9587abc 100644 (file)
@@ -7,7 +7,6 @@
  * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
  * Copyright (C) 2001 MIPS Technologies, Inc.
  */
-#include <linux/a.out.h>
 #include <linux/capability.h>
 #include <linux/errno.h>
 #include <linux/linkage.h>
@@ -20,7 +19,6 @@
 #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/compiler.h>
 #include <linux/module.h>
 #include <linux/ipc.h>
+#include <linux/uaccess.h>
+#include <linux/slab.h>
 
+#include <asm/asm.h>
 #include <asm/branch.h>
 #include <asm/cachectl.h>
 #include <asm/cacheflush.h>
@@ -92,7 +93,8 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
                 * We do not accept a shared mapping if it would violate
                 * cache aliasing constraints.
                 */
-               if ((flags & MAP_SHARED) && (addr & shm_align_mask))
+               if ((flags & MAP_SHARED) &&
+                   ((addr - (pgoff << PAGE_SHIFT)) & shm_align_mask))
                        return -EINVAL;
                return addr;
        }
@@ -128,34 +130,9 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
        }
 }
 
-/* common code for old and new mmaps */
-static inline unsigned long
-do_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
-        unsigned long flags, unsigned long fd, unsigned long pgoff)
-{
-       unsigned long error = -EBADF;
-       struct file * file = NULL;
-
-       flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
-       if (!(flags & MAP_ANONYMOUS)) {
-               file = fget(fd);
-               if (!file)
-                       goto out;
-       }
-
-       down_write(&current->mm->mmap_sem);
-       error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
-       up_write(&current->mm->mmap_sem);
-
-       if (file)
-               fput(file);
-out:
-       return error;
-}
-
-asmlinkage unsigned long
-old_mmap(unsigned long addr, unsigned long len, int prot,
-       int flags, int fd, off_t offset)
+SYSCALL_DEFINE6(mips_mmap, unsigned long, addr, unsigned long, len,
+       unsigned long, prot, unsigned long, flags, unsigned long,
+       fd, off_t, offset)
 {
        unsigned long result;
 
@@ -163,20 +140,20 @@ old_mmap(unsigned long addr, unsigned long len, int prot,
        if (offset & ~PAGE_MASK)
                goto out;
 
-       result = do_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
+       result = sys_mmap_pgoff(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
 
 out:
        return result;
 }
 
-asmlinkage unsigned long
-sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
-          unsigned long flags, unsigned long fd, unsigned long pgoff)
+SYSCALL_DEFINE6(mips_mmap2, unsigned long, addr, unsigned long, len,
+       unsigned long, prot, unsigned long, flags, unsigned long, fd,
+       unsigned long, pgoff)
 {
        if (pgoff & (~PAGE_MASK >> 12))
                return -EINVAL;
 
-       return do_mmap2(addr, len, prot, flags, fd, pgoff >> (PAGE_SHIFT-12));
+       return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff >> (PAGE_SHIFT-12));
 }
 
 save_static_function(sys_fork);
@@ -238,65 +215,131 @@ out:
        return error;
 }
 
-/*
- * Compacrapability ...
- */
-asmlinkage int sys_uname(struct old_utsname __user * name)
+SYSCALL_DEFINE1(set_thread_area, unsigned long, addr)
 {
-       if (name && !copy_to_user(name, utsname(), sizeof (*name)))
-               return 0;
-       return -EFAULT;
+       struct thread_info *ti = task_thread_info(current);
+
+       ti->tp_value = addr;
+       if (cpu_has_userlocal)
+               write_c0_userlocal(addr);
+
+       return 0;
 }
 
-/*
- * Compacrapability ...
- */
-asmlinkage int sys_olduname(struct oldold_utsname __user * name)
+static inline int mips_atomic_set(struct pt_regs *regs,
+       unsigned long addr, unsigned long new)
 {
-       int error;
+       unsigned long old, tmp;
+       unsigned int err;
 
-       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;
+       if (unlikely(addr & 3))
+               return -EINVAL;
 
-       return error;
-}
+       if (unlikely(!access_ok(VERIFY_WRITE, addr, 4)))
+               return -EINVAL;
 
-asmlinkage int sys_set_thread_area(unsigned long addr)
-{
-       struct thread_info *ti = task_thread_info(current);
+       if (cpu_has_llsc && R10000_LLSC_WAR) {
+               __asm__ __volatile__ (
+               "       .set    mips3                                   \n"
+               "       li      %[err], 0                               \n"
+               "1:     ll      %[old], (%[addr])                       \n"
+               "       move    %[tmp], %[new]                          \n"
+               "2:     sc      %[tmp], (%[addr])                       \n"
+               "       beqzl   %[tmp], 1b                              \n"
+               "3:                                                     \n"
+               "       .section .fixup,\"ax\"                          \n"
+               "4:     li      %[err], %[efault]                       \n"
+               "       j       3b                                      \n"
+               "       .previous                                       \n"
+               "       .section __ex_table,\"a\"                       \n"
+               "       "STR(PTR)"      1b, 4b                          \n"
+               "       "STR(PTR)"      2b, 4b                          \n"
+               "       .previous                                       \n"
+               "       .set    mips0                                   \n"
+               : [old] "=&r" (old),
+                 [err] "=&r" (err),
+                 [tmp] "=&r" (tmp)
+               : [addr] "r" (addr),
+                 [new] "r" (new),
+                 [efault] "i" (-EFAULT)
+               : "memory");
+       } else if (cpu_has_llsc) {
+               __asm__ __volatile__ (
+               "       .set    mips3                                   \n"
+               "       li      %[err], 0                               \n"
+               "1:     ll      %[old], (%[addr])                       \n"
+               "       move    %[tmp], %[new]                          \n"
+               "2:     sc      %[tmp], (%[addr])                       \n"
+               "       bnez    %[tmp], 4f                              \n"
+               "3:                                                     \n"
+               "       .subsection 2                                   \n"
+               "4:     b       1b                                      \n"
+               "       .previous                                       \n"
+               "                                                       \n"
+               "       .section .fixup,\"ax\"                          \n"
+               "5:     li      %[err], %[efault]                       \n"
+               "       j       3b                                      \n"
+               "       .previous                                       \n"
+               "       .section __ex_table,\"a\"                       \n"
+               "       "STR(PTR)"      1b, 5b                          \n"
+               "       "STR(PTR)"      2b, 5b                          \n"
+               "       .previous                                       \n"
+               "       .set    mips0                                   \n"
+               : [old] "=&r" (old),
+                 [err] "=&r" (err),
+                 [tmp] "=&r" (tmp)
+               : [addr] "r" (addr),
+                 [new] "r" (new),
+                 [efault] "i" (-EFAULT)
+               : "memory");
+       } else {
+               do {
+                       preempt_disable();
+                       ll_bit = 1;
+                       ll_task = current;
+                       preempt_enable();
+
+                       err = __get_user(old, (unsigned int *) addr);
+                       err |= __put_user(new, (unsigned int *) addr);
+                       if (err)
+                               break;
+                       rmb();
+               } while (!ll_bit);
+       }
 
-       ti->tp_value = addr;
-       if (cpu_has_userlocal)
-               write_c0_userlocal(addr);
+       if (unlikely(err))
+               return err;
 
-       return 0;
+       regs->regs[2] = old;
+       regs->regs[7] = 0;      /* No error */
+
+       /*
+        * Don't let your children do this ...
+        */
+       __asm__ __volatile__(
+       "       move    $29, %0                                         \n"
+       "       j       syscall_exit                                    \n"
+       : /* no outputs */
+       : "r" (regs));
+
+       /* unreached.  Honestly.  */
+       while (1);
 }
 
-asmlinkage int _sys_sysmips(int cmd, long arg1, int arg2, int arg3)
+save_static_function(sys_sysmips);
+static int __used noinline
+_sys_sysmips(nabi_no_regargs struct pt_regs regs)
 {
+       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:
-               printk(KERN_CRIT "How did I get here?\n");
-               return -EINVAL;
+               return mips_atomic_set(&regs, arg1, arg2);
 
        case MIPS_FIXADE:
                if (arg1 & ~3)
@@ -322,97 +365,9 @@ asmlinkage int _sys_sysmips(int cmd, long arg1, int arg2, int arg3)
 }
 
 /*
- * sys_ipc() is the de-multiplexer for the SysV IPC calls..
- *
- * This is really horribly ugly.
- */
-asmlinkage int sys_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 ...
  */
-asmlinkage int sys_cachectl(char *addr, int nbytes, int op)
+SYSCALL_DEFINE3(cachectl, char *, addr, int, nbytes, int, op)
 {
        return -ENOSYS;
 }