uaccess.h 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. /* SPDX-License-Identifier: GPL-2.0-or-later */
  2. /*
  3. * OpenRISC Linux
  4. *
  5. * Linux architectural port borrowing liberally from similar works of
  6. * others. All original copyrights apply as per the original source
  7. * declaration.
  8. *
  9. * OpenRISC implementation:
  10. * Copyright (C) 2003 Matjaz Breskvar <[email protected]>
  11. * Copyright (C) 2010-2011 Jonas Bonn <[email protected]>
  12. * et al.
  13. */
  14. #ifndef __ASM_OPENRISC_UACCESS_H
  15. #define __ASM_OPENRISC_UACCESS_H
  16. /*
  17. * User space memory access functions
  18. */
  19. #include <linux/prefetch.h>
  20. #include <linux/string.h>
  21. #include <asm/page.h>
  22. #include <asm/extable.h>
  23. #include <asm-generic/access_ok.h>
  24. /*
  25. * These are the main single-value transfer routines. They automatically
  26. * use the right size if we just have the right pointer type.
  27. *
  28. * This gets kind of ugly. We want to return _two_ values in "get_user()"
  29. * and yet we don't want to do any pointers, because that is too much
  30. * of a performance impact. Thus we have a few rather ugly macros here,
  31. * and hide all the uglyness from the user.
  32. *
  33. * The "__xxx" versions of the user access functions are versions that
  34. * do not verify the address space, that must have been done previously
  35. * with a separate "access_ok()" call (this is used when we do multiple
  36. * accesses to the same area of user memory).
  37. *
  38. * As we use the same address space for kernel and user data on the
  39. * PowerPC, we can just do these as direct assignments. (Of course, the
  40. * exception handling means that it's no longer "just"...)
  41. */
  42. #define get_user(x, ptr) \
  43. __get_user_check((x), (ptr), sizeof(*(ptr)))
  44. #define put_user(x, ptr) \
  45. __put_user_check((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)))
  46. #define __get_user(x, ptr) \
  47. __get_user_nocheck((x), (ptr), sizeof(*(ptr)))
  48. #define __put_user(x, ptr) \
  49. __put_user_nocheck((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)))
  50. extern long __put_user_bad(void);
  51. #define __put_user_nocheck(x, ptr, size) \
  52. ({ \
  53. long __pu_err; \
  54. __put_user_size((x), (ptr), (size), __pu_err); \
  55. __pu_err; \
  56. })
  57. #define __put_user_check(x, ptr, size) \
  58. ({ \
  59. long __pu_err = -EFAULT; \
  60. __typeof__(*(ptr)) __user *__pu_addr = (ptr); \
  61. if (access_ok(__pu_addr, size)) \
  62. __put_user_size((x), __pu_addr, (size), __pu_err); \
  63. __pu_err; \
  64. })
  65. #define __put_user_size(x, ptr, size, retval) \
  66. do { \
  67. retval = 0; \
  68. switch (size) { \
  69. case 1: __put_user_asm(x, ptr, retval, "l.sb"); break; \
  70. case 2: __put_user_asm(x, ptr, retval, "l.sh"); break; \
  71. case 4: __put_user_asm(x, ptr, retval, "l.sw"); break; \
  72. case 8: __put_user_asm2(x, ptr, retval); break; \
  73. default: __put_user_bad(); \
  74. } \
  75. } while (0)
  76. struct __large_struct {
  77. unsigned long buf[100];
  78. };
  79. #define __m(x) (*(struct __large_struct *)(x))
  80. /*
  81. * We don't tell gcc that we are accessing memory, but this is OK
  82. * because we do not write to any memory gcc knows about, so there
  83. * are no aliasing issues.
  84. */
  85. #define __put_user_asm(x, addr, err, op) \
  86. __asm__ __volatile__( \
  87. "1: "op" 0(%2),%1\n" \
  88. "2:\n" \
  89. ".section .fixup,\"ax\"\n" \
  90. "3: l.addi %0,r0,%3\n" \
  91. " l.j 2b\n" \
  92. " l.nop\n" \
  93. ".previous\n" \
  94. ".section __ex_table,\"a\"\n" \
  95. " .align 2\n" \
  96. " .long 1b,3b\n" \
  97. ".previous" \
  98. : "=r"(err) \
  99. : "r"(x), "r"(addr), "i"(-EFAULT), "0"(err))
  100. #define __put_user_asm2(x, addr, err) \
  101. __asm__ __volatile__( \
  102. "1: l.sw 0(%2),%1\n" \
  103. "2: l.sw 4(%2),%H1\n" \
  104. "3:\n" \
  105. ".section .fixup,\"ax\"\n" \
  106. "4: l.addi %0,r0,%3\n" \
  107. " l.j 3b\n" \
  108. " l.nop\n" \
  109. ".previous\n" \
  110. ".section __ex_table,\"a\"\n" \
  111. " .align 2\n" \
  112. " .long 1b,4b\n" \
  113. " .long 2b,4b\n" \
  114. ".previous" \
  115. : "=r"(err) \
  116. : "r"(x), "r"(addr), "i"(-EFAULT), "0"(err))
  117. #define __get_user_nocheck(x, ptr, size) \
  118. ({ \
  119. long __gu_err; \
  120. __get_user_size((x), (ptr), (size), __gu_err); \
  121. __gu_err; \
  122. })
  123. #define __get_user_check(x, ptr, size) \
  124. ({ \
  125. long __gu_err = -EFAULT; \
  126. const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \
  127. if (access_ok(__gu_addr, size)) \
  128. __get_user_size((x), __gu_addr, (size), __gu_err); \
  129. else \
  130. (x) = (__typeof__(*(ptr))) 0; \
  131. __gu_err; \
  132. })
  133. extern long __get_user_bad(void);
  134. #define __get_user_size(x, ptr, size, retval) \
  135. do { \
  136. retval = 0; \
  137. switch (size) { \
  138. case 1: __get_user_asm(x, ptr, retval, "l.lbz"); break; \
  139. case 2: __get_user_asm(x, ptr, retval, "l.lhz"); break; \
  140. case 4: __get_user_asm(x, ptr, retval, "l.lwz"); break; \
  141. case 8: __get_user_asm2(x, ptr, retval); break; \
  142. default: (x) = (__typeof__(*(ptr)))__get_user_bad(); \
  143. } \
  144. } while (0)
  145. #define __get_user_asm(x, addr, err, op) \
  146. { \
  147. unsigned long __gu_tmp; \
  148. __asm__ __volatile__( \
  149. "1: "op" %1,0(%2)\n" \
  150. "2:\n" \
  151. ".section .fixup,\"ax\"\n" \
  152. "3: l.addi %0,r0,%3\n" \
  153. " l.addi %1,r0,0\n" \
  154. " l.j 2b\n" \
  155. " l.nop\n" \
  156. ".previous\n" \
  157. ".section __ex_table,\"a\"\n" \
  158. " .align 2\n" \
  159. " .long 1b,3b\n" \
  160. ".previous" \
  161. : "=r"(err), "=r"(__gu_tmp) \
  162. : "r"(addr), "i"(-EFAULT), "0"(err)); \
  163. (x) = (__typeof__(*(addr)))__gu_tmp; \
  164. }
  165. #define __get_user_asm2(x, addr, err) \
  166. { \
  167. unsigned long long __gu_tmp; \
  168. __asm__ __volatile__( \
  169. "1: l.lwz %1,0(%2)\n" \
  170. "2: l.lwz %H1,4(%2)\n" \
  171. "3:\n" \
  172. ".section .fixup,\"ax\"\n" \
  173. "4: l.addi %0,r0,%3\n" \
  174. " l.addi %1,r0,0\n" \
  175. " l.addi %H1,r0,0\n" \
  176. " l.j 3b\n" \
  177. " l.nop\n" \
  178. ".previous\n" \
  179. ".section __ex_table,\"a\"\n" \
  180. " .align 2\n" \
  181. " .long 1b,4b\n" \
  182. " .long 2b,4b\n" \
  183. ".previous" \
  184. : "=r"(err), "=&r"(__gu_tmp) \
  185. : "r"(addr), "i"(-EFAULT), "0"(err)); \
  186. (x) = (__typeof__(*(addr)))( \
  187. (__typeof__((x)-(x)))__gu_tmp); \
  188. }
  189. /* more complex routines */
  190. extern unsigned long __must_check
  191. __copy_tofrom_user(void *to, const void *from, unsigned long size);
  192. static inline unsigned long
  193. raw_copy_from_user(void *to, const void __user *from, unsigned long size)
  194. {
  195. return __copy_tofrom_user(to, (__force const void *)from, size);
  196. }
  197. static inline unsigned long
  198. raw_copy_to_user(void __user *to, const void *from, unsigned long size)
  199. {
  200. return __copy_tofrom_user((__force void *)to, from, size);
  201. }
  202. #define INLINE_COPY_FROM_USER
  203. #define INLINE_COPY_TO_USER
  204. extern unsigned long __clear_user(void __user *addr, unsigned long size);
  205. static inline __must_check unsigned long
  206. clear_user(void __user *addr, unsigned long size)
  207. {
  208. if (likely(access_ok(addr, size)))
  209. size = __clear_user(addr, size);
  210. return size;
  211. }
  212. extern long strncpy_from_user(char *dest, const char __user *src, long count);
  213. extern __must_check long strnlen_user(const char __user *str, long n);
  214. #endif /* __ASM_OPENRISC_UACCESS_H */