]>
Commit | Line | Data |
---|---|---|
373cd784 JH |
1 | #ifndef __METAG_UACCESS_H |
2 | #define __METAG_UACCESS_H | |
3 | ||
4 | /* | |
5 | * User space memory access functions | |
6 | */ | |
7 | #include <linux/sched.h> | |
8 | ||
9 | #define VERIFY_READ 0 | |
10 | #define VERIFY_WRITE 1 | |
11 | ||
12 | /* | |
13 | * The fs value determines whether argument validity checking should be | |
14 | * performed or not. If get_fs() == USER_DS, checking is performed, with | |
15 | * get_fs() == KERNEL_DS, checking is bypassed. | |
16 | * | |
17 | * For historical reasons, these macros are grossly misnamed. | |
18 | */ | |
19 | ||
20 | #define MAKE_MM_SEG(s) ((mm_segment_t) { (s) }) | |
21 | ||
22 | #define KERNEL_DS MAKE_MM_SEG(0xFFFFFFFF) | |
23 | #define USER_DS MAKE_MM_SEG(PAGE_OFFSET) | |
24 | ||
25 | #define get_ds() (KERNEL_DS) | |
26 | #define get_fs() (current_thread_info()->addr_limit) | |
27 | #define set_fs(x) (current_thread_info()->addr_limit = (x)) | |
28 | ||
29 | #define segment_eq(a, b) ((a).seg == (b).seg) | |
30 | ||
31 | #define __kernel_ok (segment_eq(get_fs(), KERNEL_DS)) | |
32 | /* | |
33 | * Explicitly allow NULL pointers here. Parts of the kernel such | |
34 | * as readv/writev use access_ok to validate pointers, but want | |
35 | * to allow NULL pointers for various reasons. NULL pointers are | |
36 | * safe to allow through because the first page is not mappable on | |
37 | * Meta. | |
38 | * | |
39 | * We also wish to avoid letting user code access the system area | |
40 | * and the kernel half of the address space. | |
41 | */ | |
42 | #define __user_bad(addr, size) (((addr) > 0 && (addr) < META_MEMORY_BASE) || \ | |
43 | ((addr) > PAGE_OFFSET && \ | |
44 | (addr) < LINCORE_BASE)) | |
45 | ||
46 | static inline int __access_ok(unsigned long addr, unsigned long size) | |
47 | { | |
48 | return __kernel_ok || !__user_bad(addr, size); | |
49 | } | |
50 | ||
51 | #define access_ok(type, addr, size) __access_ok((unsigned long)(addr), \ | |
52 | (unsigned long)(size)) | |
53 | ||
54 | static inline int verify_area(int type, const void *addr, unsigned long size) | |
55 | { | |
56 | return access_ok(type, addr, size) ? 0 : -EFAULT; | |
57 | } | |
58 | ||
59 | /* | |
60 | * The exception table consists of pairs of addresses: the first is the | |
61 | * address of an instruction that is allowed to fault, and the second is | |
62 | * the address at which the program should continue. No registers are | |
63 | * modified, so it is entirely up to the continuation code to figure out | |
64 | * what to do. | |
65 | * | |
66 | * All the routines below use bits of fixup code that are out of line | |
67 | * with the main instruction path. This means when everything is well, | |
68 | * we don't even have to jump over them. Further, they do not intrude | |
69 | * on our cache or tlb entries. | |
70 | */ | |
71 | struct exception_table_entry { | |
72 | unsigned long insn, fixup; | |
73 | }; | |
74 | ||
75 | extern int fixup_exception(struct pt_regs *regs); | |
76 | ||
77 | /* | |
78 | * These are the main single-value transfer routines. They automatically | |
79 | * use the right size if we just have the right pointer type. | |
80 | */ | |
81 | ||
82 | #define put_user(x, ptr) \ | |
83 | __put_user_check((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr))) | |
84 | #define __put_user(x, ptr) \ | |
85 | __put_user_nocheck((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr))) | |
86 | ||
87 | extern void __put_user_bad(void); | |
88 | ||
89 | #define __put_user_nocheck(x, ptr, size) \ | |
90 | ({ \ | |
91 | long __pu_err; \ | |
92 | __put_user_size((x), (ptr), (size), __pu_err); \ | |
93 | __pu_err; \ | |
94 | }) | |
95 | ||
96 | #define __put_user_check(x, ptr, size) \ | |
97 | ({ \ | |
98 | long __pu_err = -EFAULT; \ | |
99 | __typeof__(*(ptr)) __user *__pu_addr = (ptr); \ | |
100 | if (access_ok(VERIFY_WRITE, __pu_addr, size)) \ | |
101 | __put_user_size((x), __pu_addr, (size), __pu_err); \ | |
102 | __pu_err; \ | |
103 | }) | |
104 | ||
105 | extern long __put_user_asm_b(unsigned int x, void __user *addr); | |
106 | extern long __put_user_asm_w(unsigned int x, void __user *addr); | |
107 | extern long __put_user_asm_d(unsigned int x, void __user *addr); | |
108 | extern long __put_user_asm_l(unsigned long long x, void __user *addr); | |
109 | ||
9ef8dc16 MT |
110 | #define __put_user_size(x, ptr, size, retval) \ |
111 | do { \ | |
112 | retval = 0; \ | |
113 | switch (size) { \ | |
373cd784 | 114 | case 1: \ |
9ef8dc16 MT |
115 | retval = __put_user_asm_b((__force unsigned int)x, ptr);\ |
116 | break; \ | |
373cd784 | 117 | case 2: \ |
9ef8dc16 MT |
118 | retval = __put_user_asm_w((__force unsigned int)x, ptr);\ |
119 | break; \ | |
373cd784 | 120 | case 4: \ |
9ef8dc16 MT |
121 | retval = __put_user_asm_d((__force unsigned int)x, ptr);\ |
122 | break; \ | |
373cd784 | 123 | case 8: \ |
9ef8dc16 MT |
124 | retval = __put_user_asm_l((__force unsigned long long)x,\ |
125 | ptr); \ | |
126 | break; \ | |
373cd784 JH |
127 | default: \ |
128 | __put_user_bad(); \ | |
129 | } \ | |
130 | } while (0) | |
131 | ||
132 | #define get_user(x, ptr) \ | |
133 | __get_user_check((x), (ptr), sizeof(*(ptr))) | |
134 | #define __get_user(x, ptr) \ | |
135 | __get_user_nocheck((x), (ptr), sizeof(*(ptr))) | |
136 | ||
137 | extern long __get_user_bad(void); | |
138 | ||
139 | #define __get_user_nocheck(x, ptr, size) \ | |
140 | ({ \ | |
141 | long __gu_err, __gu_val; \ | |
142 | __get_user_size(__gu_val, (ptr), (size), __gu_err); \ | |
8f4e4c1a | 143 | (x) = (__force __typeof__(*(ptr)))__gu_val; \ |
373cd784 JH |
144 | __gu_err; \ |
145 | }) | |
146 | ||
147 | #define __get_user_check(x, ptr, size) \ | |
148 | ({ \ | |
149 | long __gu_err = -EFAULT, __gu_val = 0; \ | |
150 | const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ | |
151 | if (access_ok(VERIFY_READ, __gu_addr, size)) \ | |
152 | __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \ | |
8f4e4c1a | 153 | (x) = (__force __typeof__(*(ptr)))__gu_val; \ |
373cd784 JH |
154 | __gu_err; \ |
155 | }) | |
156 | ||
157 | extern unsigned char __get_user_asm_b(const void __user *addr, long *err); | |
158 | extern unsigned short __get_user_asm_w(const void __user *addr, long *err); | |
159 | extern unsigned int __get_user_asm_d(const void __user *addr, long *err); | |
160 | ||
161 | #define __get_user_size(x, ptr, size, retval) \ | |
162 | do { \ | |
163 | retval = 0; \ | |
164 | switch (size) { \ | |
165 | case 1: \ | |
166 | x = __get_user_asm_b(ptr, &retval); break; \ | |
167 | case 2: \ | |
168 | x = __get_user_asm_w(ptr, &retval); break; \ | |
169 | case 4: \ | |
170 | x = __get_user_asm_d(ptr, &retval); break; \ | |
171 | default: \ | |
172 | (x) = __get_user_bad(); \ | |
173 | } \ | |
174 | } while (0) | |
175 | ||
176 | /* | |
177 | * Copy a null terminated string from userspace. | |
178 | * | |
179 | * Must return: | |
180 | * -EFAULT for an exception | |
181 | * count if we hit the buffer limit | |
182 | * bytes copied if we hit a null byte | |
183 | * (without the null byte) | |
184 | */ | |
185 | ||
186 | extern long __must_check __strncpy_from_user(char *dst, const char __user *src, | |
187 | long count); | |
188 | ||
189 | #define strncpy_from_user(dst, src, count) __strncpy_from_user(dst, src, count) | |
190 | ||
191 | /* | |
192 | * Return the size of a string (including the ending 0) | |
193 | * | |
194 | * Return 0 on exception, a value greater than N if too long | |
195 | */ | |
196 | extern long __must_check strnlen_user(const char __user *src, long count); | |
197 | ||
198 | #define strlen_user(str) strnlen_user(str, 32767) | |
199 | ||
563ddc10 JH |
200 | extern unsigned long raw_copy_from_user(void *to, const void __user *from, |
201 | unsigned long n); | |
373cd784 JH |
202 | |
203 | static inline unsigned long | |
204 | copy_from_user(void *to, const void __user *from, unsigned long n) | |
205 | { | |
563ddc10 | 206 | unsigned long res = n; |
8ae95ed4 | 207 | if (likely(access_ok(VERIFY_READ, from, n))) |
563ddc10 JH |
208 | res = raw_copy_from_user(to, from, n); |
209 | if (unlikely(res)) | |
210 | memset(to + (n - res), 0, res); | |
211 | return res; | |
373cd784 JH |
212 | } |
213 | ||
563ddc10 | 214 | #define __copy_from_user(to, from, n) raw_copy_from_user(to, from, n) |
373cd784 JH |
215 | #define __copy_from_user_inatomic __copy_from_user |
216 | ||
217 | extern unsigned long __must_check __copy_user(void __user *to, | |
218 | const void *from, | |
219 | unsigned long n); | |
220 | ||
221 | static inline unsigned long copy_to_user(void __user *to, const void *from, | |
222 | unsigned long n) | |
223 | { | |
224 | if (access_ok(VERIFY_WRITE, to, n)) | |
225 | return __copy_user(to, from, n); | |
226 | return n; | |
227 | } | |
228 | ||
229 | #define __copy_to_user(to, from, n) __copy_user(to, from, n) | |
230 | #define __copy_to_user_inatomic __copy_to_user | |
231 | ||
232 | /* | |
233 | * Zero Userspace | |
234 | */ | |
235 | ||
236 | extern unsigned long __must_check __do_clear_user(void __user *to, | |
237 | unsigned long n); | |
238 | ||
239 | static inline unsigned long clear_user(void __user *to, unsigned long n) | |
240 | { | |
241 | if (access_ok(VERIFY_WRITE, to, n)) | |
242 | return __do_clear_user(to, n); | |
243 | return n; | |
244 | } | |
245 | ||
246 | #define __clear_user(to, n) __do_clear_user(to, n) | |
247 | ||
248 | #endif /* _METAG_UACCESS_H */ |