usercopy.c 8.9 KB

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