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