uaccess_32.h 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. /*
  2. * User space memory access functions
  3. *
  4. * Copyright (C) 1999, 2002 Niibe Yutaka
  5. * Copyright (C) 2003 - 2008 Paul Mundt
  6. *
  7. * Based on:
  8. * MIPS implementation version 1.15 by
  9. * Copyright (C) 1996, 1997, 1998 by Ralf Baechle
  10. * and i386 version.
  11. */
  12. #ifndef __ASM_SH_UACCESS_32_H
  13. #define __ASM_SH_UACCESS_32_H
  14. #define __get_user_size(x,ptr,size,retval) \
  15. do { \
  16. retval = 0; \
  17. switch (size) { \
  18. case 1: \
  19. __get_user_asm(x, ptr, retval, "b"); \
  20. break; \
  21. case 2: \
  22. __get_user_asm(x, ptr, retval, "w"); \
  23. break; \
  24. case 4: \
  25. __get_user_asm(x, ptr, retval, "l"); \
  26. break; \
  27. default: \
  28. __get_user_unknown(); \
  29. break; \
  30. } \
  31. } while (0)
  32. #ifdef CONFIG_MMU
  33. #define __get_user_asm(x, addr, err, insn) \
  34. ({ \
  35. __asm__ __volatile__( \
  36. "1:\n\t" \
  37. "mov." insn " %2, %1\n\t" \
  38. "2:\n" \
  39. ".section .fixup,\"ax\"\n" \
  40. "3:\n\t" \
  41. "mov #0, %1\n\t" \
  42. "mov.l 4f, %0\n\t" \
  43. "jmp @%0\n\t" \
  44. " mov %3, %0\n\t" \
  45. ".balign 4\n" \
  46. "4: .long 2b\n\t" \
  47. ".previous\n" \
  48. ".section __ex_table,\"a\"\n\t" \
  49. ".long 1b, 3b\n\t" \
  50. ".previous" \
  51. :"=&r" (err), "=&r" (x) \
  52. :"m" (__m(addr)), "i" (-EFAULT), "0" (err)); })
  53. #else
  54. #define __get_user_asm(x, addr, err, insn) \
  55. do { \
  56. __asm__ __volatile__ ( \
  57. "mov." insn " %1, %0\n\t" \
  58. : "=&r" (x) \
  59. : "m" (__m(addr)) \
  60. ); \
  61. } while (0)
  62. #endif /* CONFIG_MMU */
  63. extern void __get_user_unknown(void);
  64. #define __put_user_size(x,ptr,size,retval) \
  65. do { \
  66. retval = 0; \
  67. switch (size) { \
  68. case 1: \
  69. __put_user_asm(x, ptr, retval, "b"); \
  70. break; \
  71. case 2: \
  72. __put_user_asm(x, ptr, retval, "w"); \
  73. break; \
  74. case 4: \
  75. __put_user_asm((u32)x, ptr, \
  76. retval, "l"); \
  77. break; \
  78. case 8: \
  79. __put_user_u64(x, ptr, retval); \
  80. break; \
  81. default: \
  82. __put_user_unknown(); \
  83. } \
  84. } while (0)
  85. #ifdef CONFIG_MMU
  86. #define __put_user_asm(x, addr, err, insn) \
  87. do { \
  88. __asm__ __volatile__ ( \
  89. "1:\n\t" \
  90. "mov." insn " %1, %2\n\t" \
  91. "2:\n" \
  92. ".section .fixup,\"ax\"\n" \
  93. "3:\n\t" \
  94. "mov.l 4f, %0\n\t" \
  95. "jmp @%0\n\t" \
  96. " mov %3, %0\n\t" \
  97. ".balign 4\n" \
  98. "4: .long 2b\n\t" \
  99. ".previous\n" \
  100. ".section __ex_table,\"a\"\n\t" \
  101. ".long 1b, 3b\n\t" \
  102. ".previous" \
  103. : "=&r" (err) \
  104. : "r" (x), "m" (__m(addr)), "i" (-EFAULT), \
  105. "0" (err) \
  106. : "memory" \
  107. ); \
  108. } while (0)
  109. #else
  110. #define __put_user_asm(x, addr, err, insn) \
  111. do { \
  112. __asm__ __volatile__ ( \
  113. "mov." insn " %0, %1\n\t" \
  114. : /* no outputs */ \
  115. : "r" (x), "m" (__m(addr)) \
  116. : "memory" \
  117. ); \
  118. } while (0)
  119. #endif /* CONFIG_MMU */
  120. #if defined(CONFIG_CPU_LITTLE_ENDIAN)
  121. #define __put_user_u64(val,addr,retval) \
  122. ({ \
  123. __asm__ __volatile__( \
  124. "1:\n\t" \
  125. "mov.l %R1,%2\n\t" \
  126. "mov.l %S1,%T2\n\t" \
  127. "2:\n" \
  128. ".section .fixup,\"ax\"\n" \
  129. "3:\n\t" \
  130. "mov.l 4f,%0\n\t" \
  131. "jmp @%0\n\t" \
  132. " mov %3,%0\n\t" \
  133. ".balign 4\n" \
  134. "4: .long 2b\n\t" \
  135. ".previous\n" \
  136. ".section __ex_table,\"a\"\n\t" \
  137. ".long 1b, 3b\n\t" \
  138. ".previous" \
  139. : "=r" (retval) \
  140. : "r" (val), "m" (__m(addr)), "i" (-EFAULT), "0" (retval) \
  141. : "memory"); })
  142. #else
  143. #define __put_user_u64(val,addr,retval) \
  144. ({ \
  145. __asm__ __volatile__( \
  146. "1:\n\t" \
  147. "mov.l %S1,%2\n\t" \
  148. "mov.l %R1,%T2\n\t" \
  149. "2:\n" \
  150. ".section .fixup,\"ax\"\n" \
  151. "3:\n\t" \
  152. "mov.l 4f,%0\n\t" \
  153. "jmp @%0\n\t" \
  154. " mov %3,%0\n\t" \
  155. ".balign 4\n" \
  156. "4: .long 2b\n\t" \
  157. ".previous\n" \
  158. ".section __ex_table,\"a\"\n\t" \
  159. ".long 1b, 3b\n\t" \
  160. ".previous" \
  161. : "=r" (retval) \
  162. : "r" (val), "m" (__m(addr)), "i" (-EFAULT), "0" (retval) \
  163. : "memory"); })
  164. #endif
  165. extern void __put_user_unknown(void);
  166. static inline int
  167. __strncpy_from_user(unsigned long __dest, unsigned long __user __src, int __count)
  168. {
  169. __kernel_size_t res;
  170. unsigned long __dummy, _d, _s, _c;
  171. __asm__ __volatile__(
  172. "9:\n"
  173. "mov.b @%2+, %1\n\t"
  174. "cmp/eq #0, %1\n\t"
  175. "bt/s 2f\n"
  176. "1:\n"
  177. "mov.b %1, @%3\n\t"
  178. "dt %4\n\t"
  179. "bf/s 9b\n\t"
  180. " add #1, %3\n\t"
  181. "2:\n\t"
  182. "sub %4, %0\n"
  183. "3:\n"
  184. ".section .fixup,\"ax\"\n"
  185. "4:\n\t"
  186. "mov.l 5f, %1\n\t"
  187. "jmp @%1\n\t"
  188. " mov %9, %0\n\t"
  189. ".balign 4\n"
  190. "5: .long 3b\n"
  191. ".previous\n"
  192. ".section __ex_table,\"a\"\n"
  193. " .balign 4\n"
  194. " .long 9b,4b\n"
  195. ".previous"
  196. : "=r" (res), "=&z" (__dummy), "=r" (_s), "=r" (_d), "=r"(_c)
  197. : "0" (__count), "2" (__src), "3" (__dest), "4" (__count),
  198. "i" (-EFAULT)
  199. : "memory", "t");
  200. return res;
  201. }
  202. /*
  203. * Return the size of a string (including the ending 0 even when we have
  204. * exceeded the maximum string length).
  205. */
  206. static inline long __strnlen_user(const char __user *__s, long __n)
  207. {
  208. unsigned long res;
  209. unsigned long __dummy;
  210. __asm__ __volatile__(
  211. "1:\t"
  212. "mov.b @(%0,%3), %1\n\t"
  213. "cmp/eq %4, %0\n\t"
  214. "bt/s 2f\n\t"
  215. " add #1, %0\n\t"
  216. "tst %1, %1\n\t"
  217. "bf 1b\n\t"
  218. "2:\n"
  219. ".section .fixup,\"ax\"\n"
  220. "3:\n\t"
  221. "mov.l 4f, %1\n\t"
  222. "jmp @%1\n\t"
  223. " mov #0, %0\n"
  224. ".balign 4\n"
  225. "4: .long 2b\n"
  226. ".previous\n"
  227. ".section __ex_table,\"a\"\n"
  228. " .balign 4\n"
  229. " .long 1b,3b\n"
  230. ".previous"
  231. : "=z" (res), "=&r" (__dummy)
  232. : "0" (0), "r" (__s), "r" (__n)
  233. : "t");
  234. return res;
  235. }
  236. #endif /* __ASM_SH_UACCESS_32_H */