Commit | Line | Data |
---|---|---|
26025bbf JH |
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 | }; |