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    mips3                                   \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                "       .section .fixup,\"ax\"                          \n"
 121                "4:     li      %[err], %[efault]                       \n"
 122                "       j       3b                                      \n"
 123                "       .previous                                       \n"
 124                "       .section __ex_table,\"a\"                       \n"
 125                "       "STR(PTR)"      1b, 4b                          \n"
 126                "       "STR(PTR)"      2b, 4b                          \n"
 127                "       .previous                                       \n"
 128                "       .set    mips0                                   \n"
 129                : [old] "=&r" (old),
 130                  [err] "=&r" (err),
 131                  [tmp] "=&r" (tmp)
 132                : [addr] "r" (addr),
 133                  [new] "r" (new),
 134                  [efault] "i" (-EFAULT)
 135                : "memory");
 136        } else if (cpu_has_llsc) {
 137                __asm__ __volatile__ (
 138                "       .set    mips3                                   \n"
 139                "       li      %[err], 0                               \n"
 140                "1:     ll      %[old], (%[addr])                       \n"
 141                "       move    %[tmp], %[new]                          \n"
 142                "2:     sc      %[tmp], (%[addr])                       \n"
 143                "       bnez    %[tmp], 4f                              \n"
 144                "3:                                                     \n"
 145                "       .subsection 2                                   \n"
 146                "4:     b       1b                                      \n"
 147                "       .previous                                       \n"
 148                "                                                       \n"
 149                "       .section .fixup,\"ax\"                          \n"
 150                "5:     li      %[err], %[efault]                       \n"
 151                "       j       3b                                      \n"
 152                "       .previous                                       \n"
 153                "       .section __ex_table,\"a\"                       \n"
 154                "       "STR(PTR)"      1b, 5b                          \n"
 155                "       "STR(PTR)"      2b, 5b                          \n"
 156                "       .previous                                       \n"
 157                "       .set    mips0                                   \n"
 158                : [old] "=&r" (old),
 159                  [err] "=&r" (err),
 160                  [tmp] "=&r" (tmp)
 161                : [addr] "r" (addr),
 162                  [new] "r" (new),
 163                  [efault] "i" (-EFAULT)
 164                : "memory");
 165        } else {
 166                do {
 167                        preempt_disable();
 168                        ll_bit = 1;
 169                        ll_task = current;
 170                        preempt_enable();
 171
 172                        err = __get_user(old, (unsigned int *) addr);
 173                        err |= __put_user(new, (unsigned int *) addr);
 174                        if (err)
 175                                break;
 176                        rmb();
 177                } while (!ll_bit);
 178        }
 179
 180        if (unlikely(err))
 181                return err;
 182
 183        regs = current_pt_regs();
 184        regs->regs[2] = old;
 185        regs->regs[7] = 0;      /* No error */
 186
 187        /*
 188         * Don't let your children do this ...
 189         */
 190        __asm__ __volatile__(
 191        "       move    $29, %0                                         \n"
 192        "       j       syscall_exit                                    \n"
 193        : /* no outputs */
 194        : "r" (regs));
 195
 196        /* unreached.  Honestly.  */
 197        unreachable();
 198}
 199
 200SYSCALL_DEFINE3(sysmips, long, cmd, long, arg1, long, arg2)
 201{
 202        switch (cmd) {
 203        case MIPS_ATOMIC_SET:
 204                return mips_atomic_set(arg1, arg2);
 205
 206        case MIPS_FIXADE:
 207                if (arg1 & ~3)
 208                        return -EINVAL;
 209
 210                if (arg1 & 1)
 211                        set_thread_flag(TIF_FIXADE);
 212                else
 213                        clear_thread_flag(TIF_FIXADE);
 214                if (arg1 & 2)
 215                        set_thread_flag(TIF_LOGADE);
 216                else
 217                        clear_thread_flag(TIF_LOGADE);
 218
 219                return 0;
 220
 221        case FLUSH_CACHE:
 222                __flush_cache_all();
 223                return 0;
 224        }
 225
 226        return -EINVAL;
 227}
 228
 229/*
 230 * No implemented yet ...
 231 */
 232SYSCALL_DEFINE3(cachectl, char *, addr, int, nbytes, int, op)
 233{
 234        return -ENOSYS;
 235}
 236
 237/*
 238 * If we ever come here the user sp is bad.  Zap the process right away.
 239 * Due to the bad stack signaling wouldn't work.
 240 */
 241asmlinkage void bad_stack(void)
 242{
 243        do_exit(SIGSEGV);
 244}
 245