uaccess.h 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. /*
  3. * Copyright (C) 2008-2009 Michal Simek <[email protected]>
  4. * Copyright (C) 2008-2009 PetaLogix
  5. * Copyright (C) 2006 Atmark Techno, Inc.
  6. */
  7. #ifndef _ASM_MICROBLAZE_UACCESS_H
  8. #define _ASM_MICROBLAZE_UACCESS_H
  9. #include <linux/kernel.h>
  10. #include <asm/mmu.h>
  11. #include <asm/page.h>
  12. #include <linux/pgtable.h>
  13. #include <asm/extable.h>
  14. #include <linux/string.h>
  15. #include <asm-generic/access_ok.h>
  16. # define __FIXUP_SECTION ".section .fixup,\"ax\"\n"
  17. # define __EX_TABLE_SECTION ".section __ex_table,\"a\"\n"
  18. extern unsigned long __copy_tofrom_user(void __user *to,
  19. const void __user *from, unsigned long size);
  20. /* Return: number of not copied bytes, i.e. 0 if OK or non-zero if fail. */
  21. static inline unsigned long __must_check __clear_user(void __user *to,
  22. unsigned long n)
  23. {
  24. /* normal memset with two words to __ex_table */
  25. __asm__ __volatile__ ( \
  26. "1: sb r0, %1, r0;" \
  27. " addik %0, %0, -1;" \
  28. " bneid %0, 1b;" \
  29. " addik %1, %1, 1;" \
  30. "2: " \
  31. __EX_TABLE_SECTION \
  32. ".word 1b,2b;" \
  33. ".previous;" \
  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. might_fault();
  43. if (unlikely(!access_ok(to, n)))
  44. return n;
  45. return __clear_user(to, n);
  46. }
  47. /* put_user and get_user macros */
  48. extern long __user_bad(void);
  49. #define __get_user_asm(insn, __gu_ptr, __gu_val, __gu_err) \
  50. ({ \
  51. __asm__ __volatile__ ( \
  52. "1:" insn " %1, %2, r0;" \
  53. " addk %0, r0, r0;" \
  54. "2: " \
  55. __FIXUP_SECTION \
  56. "3: brid 2b;" \
  57. " addik %0, r0, %3;" \
  58. ".previous;" \
  59. __EX_TABLE_SECTION \
  60. ".word 1b,3b;" \
  61. ".previous;" \
  62. : "=&r"(__gu_err), "=r"(__gu_val) \
  63. : "r"(__gu_ptr), "i"(-EFAULT) \
  64. ); \
  65. })
  66. /**
  67. * get_user: - Get a simple variable from user space.
  68. * @x: Variable to store result.
  69. * @ptr: Source address, in user space.
  70. *
  71. * Context: User context only. This function may sleep if pagefaults are
  72. * enabled.
  73. *
  74. * This macro copies a single simple variable from user space to kernel
  75. * space. It supports simple types like char and int, but not larger
  76. * data types like structures or arrays.
  77. *
  78. * @ptr must have pointer-to-simple-variable type, and the result of
  79. * dereferencing @ptr must be assignable to @x without a cast.
  80. *
  81. * Returns zero on success, or -EFAULT on error.
  82. * On error, the variable @x is set to zero.
  83. */
  84. #define get_user(x, ptr) ({ \
  85. const typeof(*(ptr)) __user *__gu_ptr = (ptr); \
  86. access_ok(__gu_ptr, sizeof(*__gu_ptr)) ? \
  87. __get_user(x, __gu_ptr) : -EFAULT; \
  88. })
  89. #define __get_user(x, ptr) \
  90. ({ \
  91. long __gu_err; \
  92. switch (sizeof(*(ptr))) { \
  93. case 1: \
  94. __get_user_asm("lbu", (ptr), x, __gu_err); \
  95. break; \
  96. case 2: \
  97. __get_user_asm("lhu", (ptr), x, __gu_err); \
  98. break; \
  99. case 4: \
  100. __get_user_asm("lw", (ptr), x, __gu_err); \
  101. break; \
  102. case 8: { \
  103. __u64 __x = 0; \
  104. __gu_err = raw_copy_from_user(&__x, ptr, 8) ? \
  105. -EFAULT : 0; \
  106. (x) = (typeof(x))(typeof((x) - (x)))__x; \
  107. break; \
  108. } \
  109. default: \
  110. /* __gu_val = 0; __gu_err = -EINVAL;*/ __gu_err = __user_bad();\
  111. } \
  112. __gu_err; \
  113. })
  114. #define __put_user_asm(insn, __gu_ptr, __gu_val, __gu_err) \
  115. ({ \
  116. __asm__ __volatile__ ( \
  117. "1:" insn " %1, %2, r0;" \
  118. " addk %0, r0, r0;" \
  119. "2: " \
  120. __FIXUP_SECTION \
  121. "3: brid 2b;" \
  122. " addik %0, r0, %3;" \
  123. ".previous;" \
  124. __EX_TABLE_SECTION \
  125. ".word 1b,3b;" \
  126. ".previous;" \
  127. : "=&r"(__gu_err) \
  128. : "r"(__gu_val), "r"(__gu_ptr), "i"(-EFAULT) \
  129. ); \
  130. })
  131. #define __put_user_asm_8(__gu_ptr, __gu_val, __gu_err) \
  132. ({ \
  133. __asm__ __volatile__ (" lwi %0, %1, 0;" \
  134. "1: swi %0, %2, 0;" \
  135. " lwi %0, %1, 4;" \
  136. "2: swi %0, %2, 4;" \
  137. " addk %0, r0, r0;" \
  138. "3: " \
  139. __FIXUP_SECTION \
  140. "4: brid 3b;" \
  141. " addik %0, r0, %3;" \
  142. ".previous;" \
  143. __EX_TABLE_SECTION \
  144. ".word 1b,4b,2b,4b;" \
  145. ".previous;" \
  146. : "=&r"(__gu_err) \
  147. : "r"(&__gu_val), "r"(__gu_ptr), "i"(-EFAULT) \
  148. ); \
  149. })
  150. /**
  151. * put_user: - Write a simple value into user space.
  152. * @x: Value to copy to user space.
  153. * @ptr: Destination address, in user space.
  154. *
  155. * Context: User context only. This function may sleep if pagefaults are
  156. * enabled.
  157. *
  158. * This macro copies a single simple value from kernel space to user
  159. * space. It supports simple types like char and int, but not larger
  160. * data types like structures or arrays.
  161. *
  162. * @ptr must have pointer-to-simple-variable type, and @x must be assignable
  163. * to the result of dereferencing @ptr.
  164. *
  165. * Returns zero on success, or -EFAULT on error.
  166. */
  167. #define put_user(x, ptr) \
  168. __put_user_check((x), (ptr), sizeof(*(ptr)))
  169. #define __put_user_check(x, ptr, size) \
  170. ({ \
  171. typeof(*(ptr)) volatile __pu_val = x; \
  172. typeof(*(ptr)) __user *__pu_addr = (ptr); \
  173. int __pu_err = 0; \
  174. \
  175. if (access_ok(__pu_addr, size)) { \
  176. switch (size) { \
  177. case 1: \
  178. __put_user_asm("sb", __pu_addr, __pu_val, \
  179. __pu_err); \
  180. break; \
  181. case 2: \
  182. __put_user_asm("sh", __pu_addr, __pu_val, \
  183. __pu_err); \
  184. break; \
  185. case 4: \
  186. __put_user_asm("sw", __pu_addr, __pu_val, \
  187. __pu_err); \
  188. break; \
  189. case 8: \
  190. __put_user_asm_8(__pu_addr, __pu_val, __pu_err);\
  191. break; \
  192. default: \
  193. __pu_err = __user_bad(); \
  194. break; \
  195. } \
  196. } else { \
  197. __pu_err = -EFAULT; \
  198. } \
  199. __pu_err; \
  200. })
  201. #define __put_user(x, ptr) \
  202. ({ \
  203. __typeof__(*(ptr)) volatile __gu_val = (x); \
  204. long __gu_err = 0; \
  205. switch (sizeof(__gu_val)) { \
  206. case 1: \
  207. __put_user_asm("sb", (ptr), __gu_val, __gu_err); \
  208. break; \
  209. case 2: \
  210. __put_user_asm("sh", (ptr), __gu_val, __gu_err); \
  211. break; \
  212. case 4: \
  213. __put_user_asm("sw", (ptr), __gu_val, __gu_err); \
  214. break; \
  215. case 8: \
  216. __put_user_asm_8((ptr), __gu_val, __gu_err); \
  217. break; \
  218. default: \
  219. /*__gu_err = -EINVAL;*/ __gu_err = __user_bad(); \
  220. } \
  221. __gu_err; \
  222. })
  223. static inline unsigned long
  224. raw_copy_from_user(void *to, const void __user *from, unsigned long n)
  225. {
  226. return __copy_tofrom_user((__force void __user *)to, from, n);
  227. }
  228. static inline unsigned long
  229. raw_copy_to_user(void __user *to, const void *from, unsigned long n)
  230. {
  231. return __copy_tofrom_user(to, (__force const void __user *)from, n);
  232. }
  233. #define INLINE_COPY_FROM_USER
  234. #define INLINE_COPY_TO_USER
  235. /*
  236. * Copy a null terminated string from userspace.
  237. */
  238. __must_check long strncpy_from_user(char *dst, const char __user *src,
  239. long count);
  240. /*
  241. * Return the size of a string (including the ending 0)
  242. *
  243. * Return 0 on exception, a value greater than N if too long
  244. */
  245. __must_check long strnlen_user(const char __user *sstr, long len);
  246. #endif /* _ASM_MICROBLAZE_UACCESS_H */