usercopy.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. /*
  2. * User address space access functions.
  3. * The non inlined parts of asm-m32r/uaccess.h are here.
  4. *
  5. * Copyright 1997 Andi Kleen <ak@muc.de>
  6. * Copyright 1997 Linus Torvalds
  7. * Copyright 2001, 2002, 2004 Hirokazu Takata
  8. */
  9. #include <linux/prefetch.h>
  10. #include <linux/string.h>
  11. #include <linux/thread_info.h>
  12. #include <asm/uaccess.h>
  13. unsigned long
  14. __generic_copy_to_user(void __user *to, const void *from, unsigned long n)
  15. {
  16. prefetch(from);
  17. if (access_ok(VERIFY_WRITE, to, n))
  18. __copy_user(to,from,n);
  19. return n;
  20. }
  21. unsigned long
  22. __generic_copy_from_user(void *to, const void __user *from, unsigned long n)
  23. {
  24. prefetchw(to);
  25. if (access_ok(VERIFY_READ, from, n))
  26. __copy_user_zeroing(to,from,n);
  27. else
  28. memset(to, 0, n);
  29. return n;
  30. }
  31. /*
  32. * Copy a null terminated string from userspace.
  33. */
  34. #ifdef CONFIG_ISA_DUAL_ISSUE
  35. #define __do_strncpy_from_user(dst,src,count,res) \
  36. do { \
  37. int __d0, __d1, __d2; \
  38. __asm__ __volatile__( \
  39. " beqz %1, 2f\n" \
  40. " .fillinsn\n" \
  41. "0: ldb r14, @%3 || addi %3, #1\n" \
  42. " stb r14, @%4 || addi %4, #1\n" \
  43. " beqz r14, 1f\n" \
  44. " addi %1, #-1\n" \
  45. " bnez %1, 0b\n" \
  46. " .fillinsn\n" \
  47. "1: sub %0, %1\n" \
  48. " .fillinsn\n" \
  49. "2:\n" \
  50. ".section .fixup,\"ax\"\n" \
  51. " .balign 4\n" \
  52. "3: seth r14, #high(2b)\n" \
  53. " or3 r14, r14, #low(2b)\n" \
  54. " jmp r14 || ldi %0, #%5\n" \
  55. ".previous\n" \
  56. ".section __ex_table,\"a\"\n" \
  57. " .balign 4\n" \
  58. " .long 0b,3b\n" \
  59. ".previous" \
  60. : "=&r"(res), "=&r"(count), "=&r" (__d0), "=&r" (__d1), \
  61. "=&r" (__d2) \
  62. : "i"(-EFAULT), "0"(count), "1"(count), "3"(src), \
  63. "4"(dst) \
  64. : "r14", "cbit", "memory"); \
  65. } while (0)
  66. #else /* not CONFIG_ISA_DUAL_ISSUE */
  67. #define __do_strncpy_from_user(dst,src,count,res) \
  68. do { \
  69. int __d0, __d1, __d2; \
  70. __asm__ __volatile__( \
  71. " beqz %1, 2f\n" \
  72. " .fillinsn\n" \
  73. "0: ldb r14, @%3\n" \
  74. " stb r14, @%4\n" \
  75. " addi %3, #1\n" \
  76. " addi %4, #1\n" \
  77. " beqz r14, 1f\n" \
  78. " addi %1, #-1\n" \
  79. " bnez %1, 0b\n" \
  80. " .fillinsn\n" \
  81. "1: sub %0, %1\n" \
  82. " .fillinsn\n" \
  83. "2:\n" \
  84. ".section .fixup,\"ax\"\n" \
  85. " .balign 4\n" \
  86. "3: ldi %0, #%5\n" \
  87. " seth r14, #high(2b)\n" \
  88. " or3 r14, r14, #low(2b)\n" \
  89. " jmp r14\n" \
  90. ".previous\n" \
  91. ".section __ex_table,\"a\"\n" \
  92. " .balign 4\n" \
  93. " .long 0b,3b\n" \
  94. ".previous" \
  95. : "=&r"(res), "=&r"(count), "=&r" (__d0), "=&r" (__d1), \
  96. "=&r" (__d2) \
  97. : "i"(-EFAULT), "0"(count), "1"(count), "3"(src), \
  98. "4"(dst) \
  99. : "r14", "cbit", "memory"); \
  100. } while (0)
  101. #endif /* CONFIG_ISA_DUAL_ISSUE */
  102. long
  103. __strncpy_from_user(char *dst, const char __user *src, long count)
  104. {
  105. long res;
  106. __do_strncpy_from_user(dst, src, count, res);
  107. return res;
  108. }
  109. long
  110. strncpy_from_user(char *dst, const char __user *src, long count)
  111. {
  112. long res = -EFAULT;
  113. if (access_ok(VERIFY_READ, src, 1))
  114. __do_strncpy_from_user(dst, src, count, res);
  115. return res;
  116. }
  117. /*
  118. * Zero Userspace
  119. */
  120. #ifdef CONFIG_ISA_DUAL_ISSUE
  121. #define __do_clear_user(addr,size) \
  122. do { \
  123. int __dst, __c; \
  124. __asm__ __volatile__( \
  125. " beqz %1, 9f\n" \
  126. " and3 r14, %0, #3\n" \
  127. " bnez r14, 2f\n" \
  128. " and3 r14, %1, #3\n" \
  129. " bnez r14, 2f\n" \
  130. " and3 %1, %1, #3\n" \
  131. " beqz %2, 2f\n" \
  132. " addi %0, #-4\n" \
  133. " .fillinsn\n" \
  134. "0: ; word clear \n" \
  135. " st %6, @+%0 || addi %2, #-1\n" \
  136. " bnez %2, 0b\n" \
  137. " beqz %1, 9f\n" \
  138. " .fillinsn\n" \
  139. "2: ; byte clear \n" \
  140. " stb %6, @%0 || addi %1, #-1\n" \
  141. " addi %0, #1\n" \
  142. " bnez %1, 2b\n" \
  143. " .fillinsn\n" \
  144. "9:\n" \
  145. ".section .fixup,\"ax\"\n" \
  146. " .balign 4\n" \
  147. "4: slli %2, #2\n" \
  148. " seth r14, #high(9b)\n" \
  149. " or3 r14, r14, #low(9b)\n" \
  150. " jmp r14 || add %1, %2\n" \
  151. ".previous\n" \
  152. ".section __ex_table,\"a\"\n" \
  153. " .balign 4\n" \
  154. " .long 0b,4b\n" \
  155. " .long 2b,9b\n" \
  156. ".previous\n" \
  157. : "=&r"(__dst), "=&r"(size), "=&r"(__c) \
  158. : "0"(addr), "1"(size), "2"(size / 4), "r"(0) \
  159. : "r14", "cbit", "memory"); \
  160. } while (0)
  161. #else /* not CONFIG_ISA_DUAL_ISSUE */
  162. #define __do_clear_user(addr,size) \
  163. do { \
  164. int __dst, __c; \
  165. __asm__ __volatile__( \
  166. " beqz %1, 9f\n" \
  167. " and3 r14, %0, #3\n" \
  168. " bnez r14, 2f\n" \
  169. " and3 r14, %1, #3\n" \
  170. " bnez r14, 2f\n" \
  171. " and3 %1, %1, #3\n" \
  172. " beqz %2, 2f\n" \
  173. " addi %0, #-4\n" \
  174. " .fillinsn\n" \
  175. "0: st %6, @+%0 ; word clear \n" \
  176. " addi %2, #-1\n" \
  177. " bnez %2, 0b\n" \
  178. " beqz %1, 9f\n" \
  179. " .fillinsn\n" \
  180. "2: stb %6, @%0 ; byte clear \n" \
  181. " addi %1, #-1\n" \
  182. " addi %0, #1\n" \
  183. " bnez %1, 2b\n" \
  184. " .fillinsn\n" \
  185. "9:\n" \
  186. ".section .fixup,\"ax\"\n" \
  187. " .balign 4\n" \
  188. "4: slli %2, #2\n" \
  189. " add %1, %2\n" \
  190. " seth r14, #high(9b)\n" \
  191. " or3 r14, r14, #low(9b)\n" \
  192. " jmp r14\n" \
  193. ".previous\n" \
  194. ".section __ex_table,\"a\"\n" \
  195. " .balign 4\n" \
  196. " .long 0b,4b\n" \
  197. " .long 2b,9b\n" \
  198. ".previous\n" \
  199. : "=&r"(__dst), "=&r"(size), "=&r"(__c) \
  200. : "0"(addr), "1"(size), "2"(size / 4), "r"(0) \
  201. : "r14", "cbit", "memory"); \
  202. } while (0)
  203. #endif /* not CONFIG_ISA_DUAL_ISSUE */
  204. unsigned long
  205. clear_user(void __user *to, unsigned long n)
  206. {
  207. if (access_ok(VERIFY_WRITE, to, n))
  208. __do_clear_user(to, n);
  209. return n;
  210. }
  211. unsigned long
  212. __clear_user(void __user *to, unsigned long n)
  213. {
  214. __do_clear_user(to, n);
  215. return n;
  216. }
  217. /*
  218. * Return the size of a string (including the ending 0)
  219. *
  220. * Return 0 on exception, a value greater than N if too long
  221. */
  222. #ifdef CONFIG_ISA_DUAL_ISSUE
  223. long strnlen_user(const char __user *s, long n)
  224. {
  225. unsigned long mask = -__addr_ok(s);
  226. unsigned long res;
  227. __asm__ __volatile__(
  228. " and %0, %5 || mv r1, %1\n"
  229. " beqz %0, strnlen_exit\n"
  230. " and3 r0, %1, #3\n"
  231. " bnez r0, strnlen_byte_loop\n"
  232. " cmpui %0, #4\n"
  233. " bc strnlen_byte_loop\n"
  234. "strnlen_word_loop:\n"
  235. "0: ld r0, @%1+\n"
  236. " pcmpbz r0\n"
  237. " bc strnlen_last_bytes_fixup\n"
  238. " addi %0, #-4\n"
  239. " beqz %0, strnlen_exit\n"
  240. " bgtz %0, strnlen_word_loop\n"
  241. "strnlen_last_bytes:\n"
  242. " mv %0, %4\n"
  243. "strnlen_last_bytes_fixup:\n"
  244. " addi %1, #-4\n"
  245. "strnlen_byte_loop:\n"
  246. "1: ldb r0, @%1 || addi %0, #-1\n"
  247. " beqz r0, strnlen_exit\n"
  248. " addi %1, #1\n"
  249. " bnez %0, strnlen_byte_loop\n"
  250. "strnlen_exit:\n"
  251. " sub %1, r1\n"
  252. " add3 %0, %1, #1\n"
  253. " .fillinsn\n"
  254. "9:\n"
  255. ".section .fixup,\"ax\"\n"
  256. " .balign 4\n"
  257. "4: addi %1, #-4\n"
  258. " .fillinsn\n"
  259. "5: seth r1, #high(9b)\n"
  260. " or3 r1, r1, #low(9b)\n"
  261. " jmp r1 || ldi %0, #0\n"
  262. ".previous\n"
  263. ".section __ex_table,\"a\"\n"
  264. " .balign 4\n"
  265. " .long 0b,4b\n"
  266. " .long 1b,5b\n"
  267. ".previous"
  268. : "=&r" (res), "=r" (s)
  269. : "0" (n), "1" (s), "r" (n & 3), "r" (mask), "r"(0x01010101)
  270. : "r0", "r1", "cbit");
  271. /* NOTE: strnlen_user() algorithm:
  272. * {
  273. * char *p;
  274. * for (p = s; n-- && *p != '\0'; ++p)
  275. * ;
  276. * return p - s + 1;
  277. * }
  278. */
  279. /* NOTE: If a null char. exists, return 0.
  280. * if ((x - 0x01010101) & ~x & 0x80808080)\n"
  281. * return 0;\n"
  282. */
  283. return res & mask;
  284. }
  285. #else /* not CONFIG_ISA_DUAL_ISSUE */
  286. long strnlen_user(const char __user *s, long n)
  287. {
  288. unsigned long mask = -__addr_ok(s);
  289. unsigned long res;
  290. __asm__ __volatile__(
  291. " and %0, %5\n"
  292. " mv r1, %1\n"
  293. " beqz %0, strnlen_exit\n"
  294. " and3 r0, %1, #3\n"
  295. " bnez r0, strnlen_byte_loop\n"
  296. " cmpui %0, #4\n"
  297. " bc strnlen_byte_loop\n"
  298. " sll3 r3, %6, #7\n"
  299. "strnlen_word_loop:\n"
  300. "0: ld r0, @%1+\n"
  301. " not r2, r0\n"
  302. " sub r0, %6\n"
  303. " and r2, r3\n"
  304. " and r2, r0\n"
  305. " bnez r2, strnlen_last_bytes_fixup\n"
  306. " addi %0, #-4\n"
  307. " beqz %0, strnlen_exit\n"
  308. " bgtz %0, strnlen_word_loop\n"
  309. "strnlen_last_bytes:\n"
  310. " mv %0, %4\n"
  311. "strnlen_last_bytes_fixup:\n"
  312. " addi %1, #-4\n"
  313. "strnlen_byte_loop:\n"
  314. "1: ldb r0, @%1\n"
  315. " addi %0, #-1\n"
  316. " beqz r0, strnlen_exit\n"
  317. " addi %1, #1\n"
  318. " bnez %0, strnlen_byte_loop\n"
  319. "strnlen_exit:\n"
  320. " sub %1, r1\n"
  321. " add3 %0, %1, #1\n"
  322. " .fillinsn\n"
  323. "9:\n"
  324. ".section .fixup,\"ax\"\n"
  325. " .balign 4\n"
  326. "4: addi %1, #-4\n"
  327. " .fillinsn\n"
  328. "5: ldi %0, #0\n"
  329. " seth r1, #high(9b)\n"
  330. " or3 r1, r1, #low(9b)\n"
  331. " jmp r1\n"
  332. ".previous\n"
  333. ".section __ex_table,\"a\"\n"
  334. " .balign 4\n"
  335. " .long 0b,4b\n"
  336. " .long 1b,5b\n"
  337. ".previous"
  338. : "=&r" (res), "=r" (s)
  339. : "0" (n), "1" (s), "r" (n & 3), "r" (mask), "r"(0x01010101)
  340. : "r0", "r1", "r2", "r3", "cbit");
  341. /* NOTE: strnlen_user() algorithm:
  342. * {
  343. * char *p;
  344. * for (p = s; n-- && *p != '\0'; ++p)
  345. * ;
  346. * return p - s + 1;
  347. * }
  348. */
  349. /* NOTE: If a null char. exists, return 0.
  350. * if ((x - 0x01010101) & ~x & 0x80808080)\n"
  351. * return 0;\n"
  352. */
  353. return res & mask;
  354. }
  355. #endif /* CONFIG_ISA_DUAL_ISSUE */