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 | |
| parent | ef4e277b5d86e56db650137de0b1cd16ded32498 (diff) | |
microblaze: uaccess: Move functions to generic location
noMMU and MMU use them.
Signed-off-by: Michal Simek <monstr@monstr.eu>
| -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 | } | ||
