diff options
author | Michal Simek <monstr@monstr.eu> | 2010-03-22 13:23:45 -0400 |
---|---|---|
committer | Michal Simek <monstr@monstr.eu> | 2010-04-01 02:38:22 -0400 |
commit | cca79120c253451220e589a104bdeb57e4901871 (patch) | |
tree | ad4fce7fa42b84492b25cd4f8c75e74d97418112 /arch | |
parent | ef4e277b5d86e56db650137de0b1cd16ded32498 (diff) |
microblaze: uaccess: Move functions to generic location
noMMU and MMU use them.
Signed-off-by: Michal Simek <monstr@monstr.eu>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/microblaze/include/asm/uaccess.h | 212 | ||||
-rw-r--r-- | arch/microblaze/lib/Makefile | 1 | ||||
-rw-r--r-- | arch/microblaze/lib/uaccess.c | 48 |
3 files changed, 61 insertions, 200 deletions
diff --git a/arch/microblaze/include/asm/uaccess.h b/arch/microblaze/include/asm/uaccess.h index 4f17950d0a0e..34b79feb1ff1 100644 --- a/arch/microblaze/include/asm/uaccess.h +++ b/arch/microblaze/include/asm/uaccess.h | |||
@@ -111,9 +111,6 @@ static inline int ___range_ok(unsigned long addr, unsigned long size) | |||
111 | # define __EX_TABLE_SECTION ".section .discard,\"a\"\n" | 111 | # define __EX_TABLE_SECTION ".section .discard,\"a\"\n" |
112 | #endif | 112 | #endif |
113 | 113 | ||
114 | extern unsigned long __copy_tofrom_user(void __user *to, | ||
115 | const void __user *from, unsigned long size); | ||
116 | |||
117 | /* Return: number of not copied bytes, i.e. 0 if OK or non-zero if fail. */ | 114 | /* Return: number of not copied bytes, i.e. 0 if OK or non-zero if fail. */ |
118 | static inline unsigned long __must_check __clear_user(void __user *to, | 115 | static inline unsigned long __must_check __clear_user(void __user *to, |
119 | unsigned long n) | 116 | unsigned long n) |
@@ -144,8 +141,7 @@ static inline unsigned long __must_check clear_user(void __user *to, | |||
144 | return __clear_user(to, n); | 141 | return __clear_user(to, n); |
145 | } | 142 | } |
146 | 143 | ||
147 | #ifndef CONFIG_MMU | 144 | /* put_user and get_user macros */ |
148 | |||
149 | extern long __user_bad(void); | 145 | extern long __user_bad(void); |
150 | 146 | ||
151 | #define __get_user_asm(insn, __gu_ptr, __gu_val, __gu_err) \ | 147 | #define __get_user_asm(insn, __gu_ptr, __gu_val, __gu_err) \ |
@@ -251,6 +247,23 @@ extern long __user_bad(void); | |||
251 | ); \ | 247 | ); \ |
252 | }) | 248 | }) |
253 | 249 | ||
250 | /** | ||
251 | * put_user: - Write a simple value into user space. | ||
252 | * @x: Value to copy to user space. | ||
253 | * @ptr: Destination address, in user space. | ||
254 | * | ||
255 | * Context: User context only. This function may sleep. | ||
256 | * | ||
257 | * This macro copies a single simple value from kernel space to user | ||
258 | * space. It supports simple types like char and int, but not larger | ||
259 | * data types like structures or arrays. | ||
260 | * | ||
261 | * @ptr must have pointer-to-simple-variable type, and @x must be assignable | ||
262 | * to the result of dereferencing @ptr. | ||
263 | * | ||
264 | * Returns zero on success, or -EFAULT on error. | ||
265 | */ | ||
266 | |||
254 | #define __put_user(x, ptr) \ | 267 | #define __put_user(x, ptr) \ |
255 | ({ \ | 268 | ({ \ |
256 | __typeof__(*(ptr)) volatile __gu_val = (x); \ | 269 | __typeof__(*(ptr)) volatile __gu_val = (x); \ |
@@ -274,8 +287,48 @@ extern long __user_bad(void); | |||
274 | __gu_err; \ | 287 | __gu_err; \ |
275 | }) | 288 | }) |
276 | 289 | ||
290 | #ifndef CONFIG_MMU | ||
291 | |||
277 | #define put_user(x, ptr) __put_user((x), (ptr)) | 292 | #define put_user(x, ptr) __put_user((x), (ptr)) |
278 | 293 | ||
294 | static inline long strnlen_user(const char __user *src, long count) | ||
295 | { | ||
296 | return strlen(src) + 1; | ||
297 | } | ||
298 | |||
299 | #define __do_strncpy_from_user(dst, src, count, res) \ | ||
300 | do { \ | ||
301 | char *tmp; \ | ||
302 | strncpy(dst, src, count); \ | ||
303 | for (tmp = dst; *tmp && count > 0; tmp++, count--) \ | ||
304 | ; \ | ||
305 | res = (tmp - dst); \ | ||
306 | } while (0) | ||
307 | |||
308 | static inline long __strncpy_from_user(char *dst, | ||
309 | const char __user *src, long count) | ||
310 | { | ||
311 | long res; | ||
312 | __do_strncpy_from_user(dst, src, count, res); | ||
313 | return res; | ||
314 | } | ||
315 | |||
316 | static inline long strncpy_from_user(char *dst, | ||
317 | const char __user *src, long count) | ||
318 | { | ||
319 | long res = -EFAULT; | ||
320 | if (access_ok(VERIFY_READ, src, 1)) | ||
321 | __do_strncpy_from_user(dst, src, count, res); | ||
322 | return res; | ||
323 | } | ||
324 | |||
325 | static inline unsigned long __copy_tofrom_user(void __user *to, | ||
326 | const void __user *from, unsigned long size) | ||
327 | { | ||
328 | memcpy(to, from, size); | ||
329 | return 0; | ||
330 | } | ||
331 | |||
279 | #define copy_to_user(to, from, n) (memcpy((to), (from), (n)), 0) | 332 | #define copy_to_user(to, from, n) (memcpy((to), (from), (n)), 0) |
280 | #define copy_from_user(to, from, n) (memcpy((to), (from), (n)), 0) | 333 | #define copy_from_user(to, from, n) (memcpy((to), (from), (n)), 0) |
281 | 334 | ||
@@ -291,158 +344,15 @@ extern long strnlen_user(const char *src, long count); | |||
291 | 344 | ||
292 | #else /* CONFIG_MMU */ | 345 | #else /* CONFIG_MMU */ |
293 | 346 | ||
294 | /* put_user and get_user macros */ | ||
295 | |||
296 | extern long __user_bad(void); | ||
297 | |||
298 | #define __get_user_asm(insn, __gu_ptr, __gu_val, __gu_err) \ | ||
299 | ({ \ | ||
300 | __asm__ __volatile__ ( \ | ||
301 | "1:" insn " %1, %2, r0;" \ | ||
302 | " addk %0, r0, r0;" \ | ||
303 | "2: " \ | ||
304 | __FIXUP_SECTION \ | ||
305 | "3: brid 2b; " \ | ||
306 | " addik %0, r0, %3;" \ | ||
307 | ".previous;" \ | ||
308 | __EX_TABLE_SECTION \ | ||
309 | ".word 1b,3b;" \ | ||
310 | ".previous;" \ | ||
311 | : "=&r"(__gu_err), "=r"(__gu_val) \ | ||
312 | : "r"(__gu_ptr), "i"(-EFAULT) \ | ||
313 | ); \ | ||
314 | }) | ||
315 | |||
316 | #define __get_user(x, ptr) \ | ||
317 | ({ \ | ||
318 | unsigned long __gu_val; \ | ||
319 | /*unsigned long __gu_ptr = (unsigned long)(ptr);*/ \ | ||
320 | long __gu_err; \ | ||
321 | switch (sizeof(*(ptr))) { \ | ||
322 | case 1: \ | ||
323 | __get_user_asm("lbu", (ptr), __gu_val, __gu_err); \ | ||
324 | break; \ | ||
325 | case 2: \ | ||
326 | __get_user_asm("lhu", (ptr), __gu_val, __gu_err); \ | ||
327 | break; \ | ||
328 | case 4: \ | ||
329 | __get_user_asm("lw", (ptr), __gu_val, __gu_err); \ | ||
330 | break; \ | ||
331 | default: \ | ||
332 | /* __gu_val = 0; __gu_err = -EINVAL;*/ __gu_err = __user_bad();\ | ||
333 | } \ | ||
334 | x = (__typeof__(*(ptr))) __gu_val; \ | ||
335 | __gu_err; \ | ||
336 | }) | ||
337 | |||
338 | /** | ||
339 | * get_user: - Get a simple variable from user space. | ||
340 | * @x: Variable to store result. | ||
341 | * @ptr: Source address, in user space. | ||
342 | * | ||
343 | * Context: User context only. This function may sleep. | ||
344 | * | ||
345 | * This macro copies a single simple variable from user space to kernel | ||
346 | * space. It supports simple types like char and int, but not larger | ||
347 | * data types like structures or arrays. | ||
348 | * | ||
349 | * @ptr must have pointer-to-simple-variable type, and the result of | ||
350 | * dereferencing @ptr must be assignable to @x without a cast. | ||
351 | * | ||
352 | * Returns zero on success, or -EFAULT on error. | ||
353 | * On error, the variable @x is set to zero. | ||
354 | */ | ||
355 | |||
356 | #define get_user(x, ptr) \ | ||
357 | ({ \ | ||
358 | access_ok(VERIFY_READ, (ptr), sizeof(*(ptr))) \ | ||
359 | ? __get_user((x), (ptr)) : -EFAULT; \ | ||
360 | }) | ||
361 | |||
362 | /** | ||
363 | * put_user: - Write a simple value into user space. | ||
364 | * @x: Value to copy to user space. | ||
365 | * @ptr: Destination address, in user space. | ||
366 | * | ||
367 | * Context: User context only. This function may sleep. | ||
368 | * | ||
369 | * This macro copies a single simple value from kernel space to user | ||
370 | * space. It supports simple types like char and int, but not larger | ||
371 | * data types like structures or arrays. | ||
372 | * | ||
373 | * @ptr must have pointer-to-simple-variable type, and @x must be assignable | ||
374 | * to the result of dereferencing @ptr. | ||
375 | * | ||
376 | * Returns zero on success, or -EFAULT on error. | ||
377 | */ | ||
378 | |||
379 | #define __put_user_asm(insn, __gu_ptr, __gu_val, __gu_err) \ | ||
380 | ({ \ | ||
381 | __asm__ __volatile__ ( \ | ||
382 | "1:" insn " %1, %2, r0;" \ | ||
383 | " addk %0, r0, r0;" \ | ||
384 | "2: " \ | ||
385 | __FIXUP_SECTION \ | ||
386 | "3: brid 2b;" \ | ||
387 | " addik %0, r0, %3;" \ | ||
388 | ".previous;" \ | ||
389 | __EX_TABLE_SECTION \ | ||
390 | ".word 1b,3b;" \ | ||
391 | ".previous;" \ | ||
392 | : "=&r"(__gu_err) \ | ||
393 | : "r"(__gu_val), "r"(__gu_ptr), "i"(-EFAULT) \ | ||
394 | ); \ | ||
395 | }) | ||
396 | |||
397 | #define __put_user_asm_8(__gu_ptr, __gu_val, __gu_err) \ | ||
398 | ({ \ | ||
399 | __asm__ __volatile__ (" lwi %0, %1, 0;" \ | ||
400 | "1: swi %0, %2, 0;" \ | ||
401 | " lwi %0, %1, 4;" \ | ||
402 | "2: swi %0, %2, 4;" \ | ||
403 | " addk %0, r0, r0;" \ | ||
404 | "3: " \ | ||
405 | __FIXUP_SECTION \ | ||
406 | "4: brid 3b;" \ | ||
407 | " addik %0, r0, %3;" \ | ||
408 | ".previous;" \ | ||
409 | __EX_TABLE_SECTION \ | ||
410 | ".word 1b,4b,2b,4b;" \ | ||
411 | ".previous;" \ | ||
412 | : "=&r"(__gu_err) \ | ||
413 | : "r"(&__gu_val), "r"(__gu_ptr), "i"(-EFAULT) \ | ||
414 | ); \ | ||
415 | }) | ||
416 | |||
417 | #define __put_user(x, ptr) \ | ||
418 | ({ \ | ||
419 | __typeof__(*(ptr)) volatile __gu_val = (x); \ | ||
420 | long __gu_err = 0; \ | ||
421 | switch (sizeof(__gu_val)) { \ | ||
422 | case 1: \ | ||
423 | __put_user_asm("sb", (ptr), __gu_val, __gu_err); \ | ||
424 | break; \ | ||
425 | case 2: \ | ||
426 | __put_user_asm("sh", (ptr), __gu_val, __gu_err); \ | ||
427 | break; \ | ||
428 | case 4: \ | ||
429 | __put_user_asm("sw", (ptr), __gu_val, __gu_err); \ | ||
430 | break; \ | ||
431 | case 8: \ | ||
432 | __put_user_asm_8((ptr), __gu_val, __gu_err); \ | ||
433 | break; \ | ||
434 | default: \ | ||
435 | /*__gu_err = -EINVAL;*/ __gu_err = __user_bad(); \ | ||
436 | } \ | ||
437 | __gu_err; \ | ||
438 | }) | ||
439 | |||
440 | #define put_user(x, ptr) \ | 347 | #define put_user(x, ptr) \ |
441 | ({ \ | 348 | ({ \ |
442 | access_ok(VERIFY_WRITE, (ptr), sizeof(*(ptr))) \ | 349 | access_ok(VERIFY_WRITE, (ptr), sizeof(*(ptr))) \ |
443 | ? __put_user((x), (ptr)) : -EFAULT; \ | 350 | ? __put_user((x), (ptr)) : -EFAULT; \ |
444 | }) | 351 | }) |
445 | 352 | ||
353 | extern unsigned long __copy_tofrom_user(void __user *to, | ||
354 | const void __user *from, unsigned long size); | ||
355 | |||
446 | #define __copy_from_user(to, from, n) \ | 356 | #define __copy_from_user(to, from, n) \ |
447 | __copy_tofrom_user((__force void __user *)(to), \ | 357 | __copy_tofrom_user((__force void __user *)(to), \ |
448 | (void __user *)(from), (n)) | 358 | (void __user *)(from), (n)) |
diff --git a/arch/microblaze/lib/Makefile b/arch/microblaze/lib/Makefile index b579db068c06..59322a2717ae 100644 --- a/arch/microblaze/lib/Makefile +++ b/arch/microblaze/lib/Makefile | |||
@@ -10,5 +10,4 @@ else | |||
10 | lib-y += memcpy.o memmove.o | 10 | lib-y += memcpy.o memmove.o |
11 | endif | 11 | endif |
12 | 12 | ||
13 | lib-$(CONFIG_NO_MMU) += uaccess.o | ||
14 | lib-$(CONFIG_MMU) += uaccess_old.o | 13 | lib-$(CONFIG_MMU) += uaccess_old.o |
diff --git a/arch/microblaze/lib/uaccess.c b/arch/microblaze/lib/uaccess.c deleted file mode 100644 index a853fe089c44..000000000000 --- a/arch/microblaze/lib/uaccess.c +++ /dev/null | |||
@@ -1,48 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2006 Atmark Techno, Inc. | ||
3 | * | ||
4 | * This file is subject to the terms and conditions of the GNU General Public | ||
5 | * License. See the file "COPYING" in the main directory of this archive | ||
6 | * for more details. | ||
7 | */ | ||
8 | |||
9 | #include <linux/string.h> | ||
10 | #include <asm/uaccess.h> | ||
11 | |||
12 | #include <asm/bug.h> | ||
13 | |||
14 | long strnlen_user(const char __user *src, long count) | ||
15 | { | ||
16 | return strlen(src) + 1; | ||
17 | } | ||
18 | |||
19 | #define __do_strncpy_from_user(dst, src, count, res) \ | ||
20 | do { \ | ||
21 | char *tmp; \ | ||
22 | strncpy(dst, src, count); \ | ||
23 | for (tmp = dst; *tmp && count > 0; tmp++, count--) \ | ||
24 | ; \ | ||
25 | res = (tmp - dst); \ | ||
26 | } while (0) | ||
27 | |||
28 | long __strncpy_from_user(char *dst, const char __user *src, long count) | ||
29 | { | ||
30 | long res; | ||
31 | __do_strncpy_from_user(dst, src, count, res); | ||
32 | return res; | ||
33 | } | ||
34 | |||
35 | long strncpy_from_user(char *dst, const char __user *src, long count) | ||
36 | { | ||
37 | long res = -EFAULT; | ||
38 | if (access_ok(VERIFY_READ, src, 1)) | ||
39 | __do_strncpy_from_user(dst, src, count, res); | ||
40 | return res; | ||
41 | } | ||
42 | |||
43 | unsigned long __copy_tofrom_user(void __user *to, | ||
44 | const void __user *from, unsigned long size) | ||
45 | { | ||
46 | memcpy(to, from, size); | ||
47 | return 0; | ||
48 | } | ||