linux/arch/mips/kernel/syscall.c
<<
>>
Prefs
   1/*
   2 * This file is subject to the terms and conditions of the GNU General Public
   3 * License.  See the file "COPYING" in the main directory of this archive
   4 * for more details.
   5 *
   6 * Copyright (C) 1995, 1996, 1997, 2000, 2001, 05 by Ralf Baechle
   7 * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
   8 * Copyright (C) 2001 MIPS Technologies, Inc.
   9 */
  10#include <linux/capability.h>
  11#include <linux/errno.h>
  12#include <linux/linkage.h>
  13#include <linux/fs.h>
  14#include <linux/smp.h>
  15#include <linux/ptrace.h>
  16#include <linux/string.h>
  17#include <linux/syscalls.h>
  18#include <linux/file.h>
  19#include <linux/utsname.h>
  20#include <linux/unistd.h>
  21#include <linux/sem.h>
  22#include <linux/msg.h>
  23#include <linux/shm.h>
  24#include <linux/compiler.h>
  25#include <linux/ipc.h>
  26#include <linux/uaccess.h>
  27#include <linux/slab.h>
  28#include <linux/elf.h>
  29
  30#include <asm/asm.h>
  31#include <asm/branch.h>
  32#include <asm/cachectl.h>
  33#include <asm/cacheflush.h>
  34#include <asm/asm-offsets.h>
  35#include <asm/signal.h>
  36#include <asm/sim.h>
  37#include <asm/shmparam.h>
  38#include <asm/sysmips.h>
  39#include <asm/uaccess.h>
  40#include <asm/switch_to.h>
  41
  42/*
  43 * For historic reasons the pipe(2) syscall on MIPS has an unusual calling
  44 * convention.  It returns results in registers $v0 / $v1 which means there
  45 * is no need for it to do verify the validity of a userspace pointer
  46 * argument.  Historically that used to be expensive in Linux.  These days
  47 * the performance advantage is negligible.
  48 */
  49asmlinkage int sysm_pipe(void)
  50{
  51        int fd[2];
  52        int error = do_pipe_flags(fd, 0);
  53        if (error)
  54                return error;
  55        current_pt_regs()->regs[3] = fd[1];
  56        return fd[0];
  57}
  58
  59SYSCALL_DEFINE6(mips_mmap, unsigned long, addr, unsigned long, len,
  60        unsigned long, prot, unsigned long, flags, unsigned long,
  61        fd, off_t, offset)
  62{
  63        unsigned long result;
  64
  65        result = -EINVAL;
  66        if (offset & ~PAGE_MASK)
  67                goto out;
  68
  69        result = sys_mmap_pgoff(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
  70
  71out:
  72        return result;
  73}
  74
  75SYSCALL_DEFINE6(mips_mmap2, unsigned long, addr, unsigned long, len,
  76        unsigned long, prot, unsigned long, flags, unsigned long, fd,
  77        unsigned long, pgoff)
  78{
  79        if (pgoff & (~PAGE_MASK >> 12))
  80                return -EINVAL;
  81
  82        return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff >> (PAGE_SHIFT-12));
  83}
  84
  85save_static_function(sys_fork);
  86save_static_function(sys_clone);
  87
  88SYSCALL_DEFINE1(set_thread_area, unsigned long, addr)
  89{
  90        struct thread_info *ti = task_thread_info(current);
  91
  92        ti->tp_value = addr;
  93        if (cpu_has_userlocal)
  94                write_c0_userlocal(addr);
  95
  96        return 0;
  97}
  98
  99static inline int mips_atomic_set(unsigned long addr, unsigned long new)
 100{
 101        unsigned long old, tmp;
 102        struct pt_regs *regs;
 103        unsigned int err;
 104
 105        if (unlikely(addr & 3))
 106                return -EINVAL;
 107
 108        if (unlikely(!access_ok(VERIFY_WRITE, addr, 4)))
 109                return -EINVAL;
 110
 111        if (cpu_has_llsc && R10000_LLSC_WAR) {
 112                __asm__ __volatile__ (
 113                "       .set    arch=r4000                              \n"
 114                "       li      %[err], 0                               \n"
 115                "1:     ll      %[old], (%[addr])                       \n"
 116                "       move    %[tmp], %[new]                          \n"
 117                "2:     sc      %[tmp], (%[addr])                       \n"
 118                "       beqzl   %[tmp], 1b                              \n"
 119                "3:                                                     \n"
 120                "       .insn                                           \n"
 121                "       .section .fixup,\"ax\"                          \n"
 122                "4:     li      %[err], %[efault]                       \n"
 123                "       j       3b                                      \n"
 124                "       .previous                                       \n"
 125                "       .section __ex_table,\"a\"                       \n"
 126                "       "STR(PTR)"      1b, 4b                          \n"
 127                "       "STR(PTR)"      2b, 4b                          \n"
 128                "       .previous                                       \n"
 129                "       .set    mips0                                   \n"
 130                : [old] "=&r" (old),
 131                  [err] "=&r" (err),
 132                  [tmp] "=&r" (tmp)
 133                : [addr] "r" (addr),
 134                  [new] "r" (new),
 135                  [efault] "i" (-EFAULT)
 136                : "memory");
 137        } else if (cpu_has_llsc) {
 138                __asm__ __volatile__ (
 139                "       .set    "MIPS_ISA_ARCH_LEVEL"                   \n"
 140                "       li      %[err], 0                               \n"
 141                "1:     ll      %[old], (%[addr])                       \n"
 142                "       move    %[tmp], %[new]                          \n"
 143                "2:     sc      %[tmp], (%[addr])                       \n"
 144                "       bnez    %[tmp], 4f                              \n"
 145                "3:                                                     \n"
 146                "       .insn                                           \n"
 147                "       .subsection 2                                   \n"
 148                "4:     b       1b                                      \n"
 149                "       .previous                                       \n"
 150                "                                                       \n"
 151                "       .section .fixup,\"ax\"                          \n"
 152                "5:     li      %[err], %[efault]                       \n"
 153                "       j       3b                                      \n"
 154                "       .previous                                       \n"
 155                "       .section __ex_table,\"a\"                       \n"
 156                "       "STR(PTR)"      1b, 5b                          \n"
 157                "       "STR(PTR)"      2b, 5b                          \n"
 158                "       .previous                                       \n"
 159                "       .set    mips0                                   \n"
 160                : [old] "=&r" (old),
 161                  [err] "=&r" (err),
 162                  [tmp] "=&r" (tmp)
 163                : [addr] "r" (addr),
 164                  [new] "r" (new),
 165                  [efault] "i" (-EFAULT)
 166                : "memory");
 167        } else {
 168                do {
 169                        preempt_disable();
 170                        ll_bit = 1;
 171                        ll_task = current;
 172                        preempt_enable();
 173
 174                        err = __get_user(old, (unsigned int *) addr);
 175                        err |= __put_user(new, (unsigned int *) addr);
 176                        if (err)
 177                                break;
 178                        rmb();
 179                } while (!ll_bit);
 180        }
 181
 182        if (unlikely(err))
 183                return err;
 184
 185        regs = current_pt_regs();
 186        regs->regs[2] = old;
 187        regs->regs[7] = 0;      /* No error */
 188
 189        /*
 190         * Don't let your children do this ...
 191         */
 192        __asm__ __volatile__(
 193        "       move    $29, %0                                         \n"
 194        "       j       syscall_exit                                    \n"
 195        : /* no outputs */
 196        : "r" (regs));
 197
 198        /* unreached.  Honestly.  */
 199        unreachable();
 200}
 201
 202SYSCALL_DEFINE3(sysmips, long, cmd, long, arg1, long, arg2)
 203{
 204        switch (cmd) {
 205        case MIPS_ATOMIC_SET:
 206                return mips_atomic_set(arg1, arg2);
 207
 208        case MIPS_FIXADE:
 209                if (arg1 & ~3)
 210                        return -EINVAL;
 211
 212                if (arg1 & 1)
 213                        set_thread_flag(TIF_FIXADE);
 214                else
 215                        clear_thread_flag(TIF_FIXADE);
 216                if (arg1 & 2)
 217                        set_thread_flag(TIF_LOGADE);
 218                else
 219                        clear_thread_flag(TIF_LOGADE);
 220
 221                return 0;
 222
 223        case FLUSH_CACHE:
 224                __flush_cache_all();
 225                return 0;
 226        }
 227
 228        return -EINVAL;
 229}
 230
 231/*
 232 * No implemented yet ...
 233 */
 234SYSCALL_DEFINE3(cachectl, char *, addr, int, nbytes, int, op)
 235{
 236        return -ENOSYS;
 237}
 238
 239/*
 240 * If we ever come here the user sp is bad.  Zap the process right away.
 241 * Due to the bad stack signaling wouldn't work.
 242 */
 243asmlinkage void bad_stack(void)
 244{
 245        do_exit(SIGSEGV);
 246}
 247