Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / arch / metag / kernel / sys_metag.c
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
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
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
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
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
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
102 asmlinkage void *sys_metag_get_tls(void)
103 {
104         return (__force void *)current->thread.tls_ptr;
105 }
106
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
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
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
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
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
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
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 };