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 metag_mmap_check(unsigned long addr,unsigned long len,unsigned long flags)27 int 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 sys_mmap2(unsigned long addr,unsigned long len,unsigned long prot,unsigned long flags,unsigned long fd,unsigned long pgoff)40 asmlinkage 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 sys_metag_setglobalbit(char __user * addr,int mask)53 asmlinkage 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 74 out: 75 __global_unlock2(flags); 76 77 return ret; 78 } 79 80 #define TXDEFR_FPU_MASK ((0x1f << 16) | 0x1f) 81 sys_metag_set_fpu_flags(unsigned int flags)82 asmlinkage 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 sys_metag_set_tls(void __user * ptr)94 asmlinkage 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 sys_metag_get_tls(void)102 asmlinkage void *sys_metag_get_tls(void) 103 { 104 return (__force void *)current->thread.tls_ptr; 105 } 106 sys_truncate64_metag(const char __user * path,unsigned long lo,unsigned long hi)107 asmlinkage 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 sys_ftruncate64_metag(unsigned int fd,unsigned long lo,unsigned long hi)113 asmlinkage 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 sys_fadvise64_64_metag(int fd,unsigned long offs_lo,unsigned long offs_hi,unsigned long len_lo,unsigned long len_hi,int advice)119 asmlinkage 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 sys_readahead_metag(int fd,unsigned long lo,unsigned long hi,size_t count)128 asmlinkage 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 sys_pread64_metag(unsigned long fd,char __user * buf,size_t count,unsigned long lo,unsigned long hi)134 asmlinkage 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 sys_pwrite64_metag(unsigned long fd,char __user * buf,size_t count,unsigned long lo,unsigned long hi)141 asmlinkage 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 sys_sync_file_range_metag(int fd,unsigned long offs_lo,unsigned long offs_hi,unsigned long len_lo,unsigned long len_hi,unsigned int flags)148 asmlinkage 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 */ 177 const void *sys_call_table[__NR_syscalls] = { 178 [0 ... __NR_syscalls-1] = sys_ni_syscall, 179 #include <asm/unistd.h> 180 }; 181