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