uaccess.h 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. /*
  2. * User space memory access functions for Nios II
  3. *
  4. * Copyright (C) 2010-2011, Tobias Klauser <[email protected]>
  5. * Copyright (C) 2009, Wind River Systems Inc
  6. * Implemented by [email protected] and [email protected]
  7. *
  8. * This file is subject to the terms and conditions of the GNU General Public
  9. * License. See the file "COPYING" in the main directory of this archive
  10. * for more details.
  11. */
  12. #ifndef _ASM_NIOS2_UACCESS_H
  13. #define _ASM_NIOS2_UACCESS_H
  14. #include <linux/string.h>
  15. #include <asm/page.h>
  16. #include <asm/extable.h>
  17. #include <asm-generic/access_ok.h>
  18. # define __EX_TABLE_SECTION ".section __ex_table,\"a\"\n"
  19. /*
  20. * Zero Userspace
  21. */
  22. static inline unsigned long __must_check __clear_user(void __user *to,
  23. unsigned long n)
  24. {
  25. __asm__ __volatile__ (
  26. "1: stb zero, 0(%1)\n"
  27. " addi %0, %0, -1\n"
  28. " addi %1, %1, 1\n"
  29. " bne %0, zero, 1b\n"
  30. "2:\n"
  31. __EX_TABLE_SECTION
  32. ".word 1b, 2b\n"
  33. ".previous\n"
  34. : "=r" (n), "=r" (to)
  35. : "0" (n), "1" (to)
  36. );
  37. return n;
  38. }
  39. static inline unsigned long __must_check clear_user(void __user *to,
  40. unsigned long n)
  41. {
  42. if (!access_ok(to, n))
  43. return n;
  44. return __clear_user(to, n);
  45. }
  46. extern unsigned long
  47. raw_copy_from_user(void *to, const void __user *from, unsigned long n);
  48. extern unsigned long
  49. raw_copy_to_user(void __user *to, const void *from, unsigned long n);
  50. #define INLINE_COPY_FROM_USER
  51. #define INLINE_COPY_TO_USER
  52. extern long strncpy_from_user(char *__to, const char __user *__from,
  53. long __len);
  54. extern __must_check long strnlen_user(const char __user *s, long n);
  55. /* Optimized macros */
  56. #define __get_user_asm(val, insn, addr, err) \
  57. { \
  58. unsigned long __gu_val; \
  59. __asm__ __volatile__( \
  60. " movi %0, %3\n" \
  61. "1: " insn " %1, 0(%2)\n" \
  62. " movi %0, 0\n" \
  63. "2:\n" \
  64. " .section __ex_table,\"a\"\n" \
  65. " .word 1b, 2b\n" \
  66. " .previous" \
  67. : "=&r" (err), "=r" (__gu_val) \
  68. : "r" (addr), "i" (-EFAULT)); \
  69. val = (__force __typeof__(*(addr)))__gu_val; \
  70. }
  71. extern void __get_user_unknown(void);
  72. #define __get_user_8(val, ptr, err) do { \
  73. u64 __val = 0; \
  74. err = 0; \
  75. if (raw_copy_from_user(&(__val), ptr, sizeof(val))) { \
  76. err = -EFAULT; \
  77. } else { \
  78. val = (typeof(val))(typeof((val) - (val)))__val; \
  79. } \
  80. } while (0)
  81. #define __get_user_common(val, size, ptr, err) \
  82. do { \
  83. switch (size) { \
  84. case 1: \
  85. __get_user_asm(val, "ldbu", ptr, err); \
  86. break; \
  87. case 2: \
  88. __get_user_asm(val, "ldhu", ptr, err); \
  89. break; \
  90. case 4: \
  91. __get_user_asm(val, "ldw", ptr, err); \
  92. break; \
  93. case 8: \
  94. __get_user_8(val, ptr, err); \
  95. break; \
  96. default: \
  97. __get_user_unknown(); \
  98. break; \
  99. } \
  100. } while (0)
  101. #define __get_user(x, ptr) \
  102. ({ \
  103. long __gu_err = -EFAULT; \
  104. const __typeof__(*(ptr)) __user *__gu_ptr = (ptr); \
  105. __get_user_common(x, sizeof(*(ptr)), __gu_ptr, __gu_err); \
  106. __gu_err; \
  107. })
  108. #define get_user(x, ptr) \
  109. ({ \
  110. long __gu_err = -EFAULT; \
  111. const __typeof__(*(ptr)) __user *__gu_ptr = (ptr); \
  112. if (access_ok( __gu_ptr, sizeof(*__gu_ptr))) \
  113. __get_user_common(x, sizeof(*__gu_ptr), \
  114. __gu_ptr, __gu_err); \
  115. __gu_err; \
  116. })
  117. #define __put_user_asm(val, insn, ptr, err) \
  118. { \
  119. __asm__ __volatile__( \
  120. " movi %0, %3\n" \
  121. "1: " insn " %1, 0(%2)\n" \
  122. " movi %0, 0\n" \
  123. "2:\n" \
  124. " .section __ex_table,\"a\"\n" \
  125. " .word 1b, 2b\n" \
  126. " .previous\n" \
  127. : "=&r" (err) \
  128. : "r" (val), "r" (ptr), "i" (-EFAULT)); \
  129. }
  130. #define __put_user_common(__pu_val, __pu_ptr) \
  131. ({ \
  132. long __pu_err = -EFAULT; \
  133. switch (sizeof(*__pu_ptr)) { \
  134. case 1: \
  135. __put_user_asm(__pu_val, "stb", __pu_ptr, __pu_err); \
  136. break; \
  137. case 2: \
  138. __put_user_asm(__pu_val, "sth", __pu_ptr, __pu_err); \
  139. break; \
  140. case 4: \
  141. __put_user_asm(__pu_val, "stw", __pu_ptr, __pu_err); \
  142. break; \
  143. default: \
  144. /* XXX: This looks wrong... */ \
  145. __pu_err = 0; \
  146. if (__copy_to_user(__pu_ptr, &(__pu_val), \
  147. sizeof(*__pu_ptr))) \
  148. __pu_err = -EFAULT; \
  149. break; \
  150. } \
  151. __pu_err; \
  152. })
  153. #define __put_user(x, ptr) \
  154. ({ \
  155. __auto_type __pu_ptr = (ptr); \
  156. typeof(*__pu_ptr) __pu_val = (typeof(*__pu_ptr))(x); \
  157. __put_user_common(__pu_val, __pu_ptr); \
  158. })
  159. #define put_user(x, ptr) \
  160. ({ \
  161. __auto_type __pu_ptr = (ptr); \
  162. typeof(*__pu_ptr) __pu_val = (typeof(*__pu_ptr))(x); \
  163. access_ok(__pu_ptr, sizeof(*__pu_ptr)) ? \
  164. __put_user_common(__pu_val, __pu_ptr) : \
  165. -EFAULT; \
  166. })
  167. #endif /* _ASM_NIOS2_UACCESS_H */