aboutsummaryrefslogtreecommitdiffstats
path: root/arch/microblaze/include/asm/uaccess.h
diff options
context:
space:
mode:
authorMichal Simek <monstr@monstr.eu>2010-03-22 13:23:45 -0400
committerMichal Simek <monstr@monstr.eu>2010-04-01 02:38:22 -0400
commitcca79120c253451220e589a104bdeb57e4901871 (patch)
treead4fce7fa42b84492b25cd4f8c75e74d97418112 /arch/microblaze/include/asm/uaccess.h
parentef4e277b5d86e56db650137de0b1cd16ded32498 (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/microblaze/include/asm/uaccess.h')
-rw-r--r--arch/microblaze/include/asm/uaccess.h212
1 files changed, 61 insertions, 151 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
114extern 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. */
118static inline unsigned long __must_check __clear_user(void __user *to, 115static 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
149extern long __user_bad(void); 145extern 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
294static 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
308static 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
316static 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
325static 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
296extern 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
353extern 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))