linux/arch/metag/kernel/sys_metag.c
<<
>>
Prefs
   1/*
   2 * This file contains various random system calls that
   3 * have a non-standard calling sequence on the Linux/Meta
   4 * platform.
   5 */
   6
   7#include <linux/errno.h>
   8#include <linux/sched.h>
   9#include <linux/mm.h>
  10#include <linux/syscalls.h>
  11#include <linux/mman.h>
  12#include <linux/file.h>
  13#include <linux/fs.h>
  14#include <linux/uaccess.h>
  15#include <linux/unistd.h>
  16#include <asm/cacheflush.h>
  17#include <asm/core_reg.h>
  18#include <asm/global_lock.h>
  19#include <asm/switch.h>
  20#include <asm/syscall.h>
  21#include <asm/syscalls.h>
  22#include <asm/user_gateway.h>
  23
  24#define merge_64(hi, lo) ((((unsigned long long)(hi)) << 32) + \
  25                          ((lo) & 0xffffffffUL))
  26
  27int metag_mmap_check(unsigned long addr, unsigned long len,
  28                     unsigned long flags)
  29{
  30        /* We can't have people trying to write to the bottom of the
  31         * memory map, there are mysterious unspecified things there that
  32         * we don't want people trampling on.
  33         */
  34        if ((flags & MAP_FIXED) && (addr < TASK_UNMAPPED_BASE))
  35                return -EINVAL;
  36
  37        return 0;
  38}
  39
  40asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
  41                          unsigned long prot, unsigned long flags,
  42                          unsigned long fd, unsigned long pgoff)
  43{
  44        /* The shift for mmap2 is constant, regardless of PAGE_SIZE setting. */
  45        if (pgoff & ((1 << (PAGE_SHIFT - 12)) - 1))
  46                return -EINVAL;
  47
  48        pgoff >>= PAGE_SHIFT - 12;
  49
  50        return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff);
  51}
  52
  53asmlinkage int sys_metag_setglobalbit(char __user *addr, int mask)
  54{
  55        char tmp;
  56        int ret = 0;
  57        unsigned int flags;
  58
  59        if (!((__force unsigned int)addr >= LINCORE_BASE))
  60                return -EFAULT;
  61
  62        __global_lock2(flags);
  63
  64        metag_data_cache_flush((__force void *)addr, sizeof(mask));
  65
  66        ret = __get_user(tmp, addr);
  67        if (ret)
  68                goto out;
  69        tmp |= mask;
  70        ret = __put_user(tmp, addr);
  71
  72        metag_data_cache_flush((__force void *)addr, sizeof(mask));
  73
  74out:
  75        __global_unlock2(flags);
  76
  77        return ret;
  78}
  79
  80#define TXDEFR_FPU_MASK ((0x1f << 16) | 0x1f)
  81
  82asmlinkage void sys_metag_set_fpu_flags(unsigned int flags)
  83{
  84        unsigned int temp;
  85
  86        flags &= TXDEFR_FPU_MASK;
  87
  88        temp = __core_reg_get(TXDEFR);
  89        temp &= ~TXDEFR_FPU_MASK;
  90        temp |= flags;
  91        __core_reg_set(TXDEFR, temp);
  92}
  93
  94asmlinkage int sys_metag_set_tls(void __user *ptr)
  95{
  96        current->thread.tls_ptr = ptr;
  97        set_gateway_tls(ptr);
  98
  99        return 0;
 100}
 101
 102asmlinkage void *sys_metag_get_tls(void)
 103{
 104        return (__force void *)current->thread.tls_ptr;
 105}
 106
 107asmlinkage long sys_truncate64_metag(const char __user *path, unsigned long lo,
 108                                     unsigned long hi)
 109{
 110        return sys_truncate64(path, merge_64(hi, lo));
 111}
 112
 113asmlinkage long sys_ftruncate64_metag(unsigned int fd, unsigned long lo,
 114                                      unsigned long hi)
 115{
 116        return sys_ftruncate64(fd, merge_64(hi, lo));
 117}
 118
 119asmlinkage long sys_fadvise64_64_metag(int fd, unsigned long offs_lo,
 120                                       unsigned long offs_hi,
 121                                       unsigned long len_lo,
 122                                       unsigned long len_hi, int advice)
 123{
 124        return sys_fadvise64_64(fd, merge_64(offs_hi, offs_lo),
 125                                merge_64(len_hi, len_lo), advice);
 126}
 127
 128asmlinkage long sys_readahead_metag(int fd, unsigned long lo, unsigned long hi,
 129                                    size_t count)
 130{
 131        return sys_readahead(fd, merge_64(hi, lo), count);
 132}
 133
 134asmlinkage ssize_t sys_pread64_metag(unsigned long fd, char __user *buf,
 135                                     size_t count, unsigned long lo,
 136                                     unsigned long hi)
 137{
 138        return sys_pread64(fd, buf, count, merge_64(hi, lo));
 139}
 140
 141asmlinkage ssize_t sys_pwrite64_metag(unsigned long fd, char __user *buf,
 142                                      size_t count, unsigned long lo,
 143                                      unsigned long hi)
 144{
 145        return sys_pwrite64(fd, buf, count, merge_64(hi, lo));
 146}
 147
 148asmlinkage long sys_sync_file_range_metag(int fd, unsigned long offs_lo,
 149                                          unsigned long offs_hi,
 150                                          unsigned long len_lo,
 151                                          unsigned long len_hi,
 152                                          unsigned int flags)
 153{
 154        return sys_sync_file_range(fd, merge_64(offs_hi, offs_lo),
 155                                   merge_64(len_hi, len_lo), flags);
 156}
 157
 158/* Provide the actual syscall number to call mapping. */
 159#undef __SYSCALL
 160#define __SYSCALL(nr, call) [nr] = (call),
 161
 162/*
 163 * We need wrappers for anything with unaligned 64bit arguments
 164 */
 165#define sys_truncate64          sys_truncate64_metag
 166#define sys_ftruncate64         sys_ftruncate64_metag
 167#define sys_fadvise64_64        sys_fadvise64_64_metag
 168#define sys_readahead           sys_readahead_metag
 169#define sys_pread64             sys_pread64_metag
 170#define sys_pwrite64            sys_pwrite64_metag
 171#define sys_sync_file_range     sys_sync_file_range_metag
 172
 173/*
 174 * Note that we can't include <linux/unistd.h> here since the header
 175 * guard will defeat us; <asm/unistd.h> checks for __SYSCALL as well.
 176 */
 177const void *sys_call_table[__NR_syscalls] = {
 178        [0 ... __NR_syscalls-1] = sys_ni_syscall,
 179#include <asm/unistd.h>
 180};
 181