uaccess.h 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748
  1. /*
  2. * Authors: Hans-Peter Nilsson (hp@axis.com)
  3. *
  4. */
  5. #ifndef _CRIS_ARCH_UACCESS_H
  6. #define _CRIS_ARCH_UACCESS_H
  7. /*
  8. * We don't tell gcc that we are accessing memory, but this is OK
  9. * because we do not write to any memory gcc knows about, so there
  10. * are no aliasing issues.
  11. *
  12. * Note that PC at a fault is the address *at* the faulting
  13. * instruction for CRISv32.
  14. */
  15. #define __put_user_asm(x, addr, err, op) \
  16. __asm__ __volatile__( \
  17. "2: "op" %1,[%2]\n" \
  18. "4:\n" \
  19. " .section .fixup,\"ax\"\n" \
  20. "3: move.d %3,%0\n" \
  21. " jump 4b\n" \
  22. " nop\n" \
  23. " .previous\n" \
  24. " .section __ex_table,\"a\"\n" \
  25. " .dword 2b,3b\n" \
  26. " .previous\n" \
  27. : "=r" (err) \
  28. : "r" (x), "r" (addr), "g" (-EFAULT), "0" (err))
  29. #define __put_user_asm_64(x, addr, err) do { \
  30. int dummy_for_put_user_asm_64_; \
  31. __asm__ __volatile__( \
  32. "2: move.d %M2,[%1+]\n" \
  33. "4: move.d %H2,[%1]\n" \
  34. "5:\n" \
  35. " .section .fixup,\"ax\"\n" \
  36. "3: move.d %4,%0\n" \
  37. " jump 5b\n" \
  38. " .previous\n" \
  39. " .section __ex_table,\"a\"\n" \
  40. " .dword 2b,3b\n" \
  41. " .dword 4b,3b\n" \
  42. " .previous\n" \
  43. : "=r" (err), "=b" (dummy_for_put_user_asm_64_) \
  44. : "r" (x), "1" (addr), "g" (-EFAULT), \
  45. "0" (err)); \
  46. } while (0)
  47. /* See comment before __put_user_asm. */
  48. #define __get_user_asm(x, addr, err, op) \
  49. __asm__ __volatile__( \
  50. "2: "op" [%2],%1\n" \
  51. "4:\n" \
  52. " .section .fixup,\"ax\"\n" \
  53. "3: move.d %3,%0\n" \
  54. " jump 4b\n" \
  55. " moveq 0,%1\n" \
  56. " .previous\n" \
  57. " .section __ex_table,\"a\"\n" \
  58. " .dword 2b,3b\n" \
  59. " .previous\n" \
  60. : "=r" (err), "=r" (x) \
  61. : "r" (addr), "g" (-EFAULT), "0" (err))
  62. #define __get_user_asm_64(x, addr, err) do { \
  63. int dummy_for_get_user_asm_64_; \
  64. __asm__ __volatile__( \
  65. "2: move.d [%2+],%M1\n" \
  66. "4: move.d [%2],%H1\n" \
  67. "5:\n" \
  68. " .section .fixup,\"ax\"\n" \
  69. "3: move.d %4,%0\n" \
  70. " jump 5b\n" \
  71. " moveq 0,%1\n" \
  72. " .previous\n" \
  73. " .section __ex_table,\"a\"\n" \
  74. " .dword 2b,3b\n" \
  75. " .dword 4b,3b\n" \
  76. " .previous\n" \
  77. : "=r" (err), "=r" (x), \
  78. "=b" (dummy_for_get_user_asm_64_) \
  79. : "2" (addr), "g" (-EFAULT), "0" (err));\
  80. } while (0)
  81. /*
  82. * Copy a null terminated string from userspace.
  83. *
  84. * Must return:
  85. * -EFAULT for an exception
  86. * count if we hit the buffer limit
  87. * bytes copied if we hit a null byte
  88. * (without the null byte)
  89. */
  90. extern inline long
  91. __do_strncpy_from_user(char *dst, const char *src, long count)
  92. {
  93. long res;
  94. if (count == 0)
  95. return 0;
  96. /*
  97. * Currently, in 2.4.0-test9, most ports use a simple byte-copy loop.
  98. * So do we.
  99. *
  100. * This code is deduced from:
  101. *
  102. * char tmp2;
  103. * long tmp1, tmp3;
  104. * tmp1 = count;
  105. * while ((*dst++ = (tmp2 = *src++)) != 0
  106. * && --tmp1)
  107. * ;
  108. *
  109. * res = count - tmp1;
  110. *
  111. * with tweaks.
  112. */
  113. __asm__ __volatile__ (
  114. " move.d %3,%0\n"
  115. "5: move.b [%2+],$acr\n"
  116. "1: beq 2f\n"
  117. " move.b $acr,[%1+]\n"
  118. " subq 1,%0\n"
  119. "2: bne 1b\n"
  120. " move.b [%2+],$acr\n"
  121. " sub.d %3,%0\n"
  122. " neg.d %0,%0\n"
  123. "3:\n"
  124. " .section .fixup,\"ax\"\n"
  125. "4: move.d %7,%0\n"
  126. " jump 3b\n"
  127. " nop\n"
  128. /* The address for a fault at the first move is trivial.
  129. The address for a fault at the second move is that of
  130. the preceding branch insn, since the move insn is in
  131. its delay-slot. That address is also a branch
  132. target. Just so you don't get confused... */
  133. " .previous\n"
  134. " .section __ex_table,\"a\"\n"
  135. " .dword 5b,4b\n"
  136. " .dword 2b,4b\n"
  137. " .previous"
  138. : "=r" (res), "=b" (dst), "=b" (src), "=r" (count)
  139. : "3" (count), "1" (dst), "2" (src), "g" (-EFAULT)
  140. : "acr");
  141. return res;
  142. }
  143. /* A few copy asms to build up the more complex ones from.
  144. Note again, a post-increment is performed regardless of whether a bus
  145. fault occurred in that instruction, and PC for a faulted insn is the
  146. address for the insn, or for the preceding branch when in a delay-slot. */
  147. #define __asm_copy_user_cont(to, from, ret, COPY, FIXUP, TENTRY) \
  148. __asm__ __volatile__ ( \
  149. COPY \
  150. "1:\n" \
  151. " .section .fixup,\"ax\"\n" \
  152. FIXUP \
  153. " .previous\n" \
  154. " .section __ex_table,\"a\"\n" \
  155. TENTRY \
  156. " .previous\n" \
  157. : "=b" (to), "=b" (from), "=r" (ret) \
  158. : "0" (to), "1" (from), "2" (ret) \
  159. : "acr", "memory")
  160. #define __asm_copy_from_user_1(to, from, ret) \
  161. __asm_copy_user_cont(to, from, ret, \
  162. "2: move.b [%1+],$acr\n" \
  163. " move.b $acr,[%0+]\n", \
  164. "3: addq 1,%2\n" \
  165. " jump 1b\n" \
  166. " clear.b [%0+]\n", \
  167. " .dword 2b,3b\n")
  168. #define __asm_copy_from_user_2x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
  169. __asm_copy_user_cont(to, from, ret, \
  170. COPY \
  171. "2: move.w [%1+],$acr\n" \
  172. " move.w $acr,[%0+]\n", \
  173. FIXUP \
  174. "3: addq 2,%2\n" \
  175. " jump 1b\n" \
  176. " clear.w [%0+]\n", \
  177. TENTRY \
  178. " .dword 2b,3b\n")
  179. #define __asm_copy_from_user_2(to, from, ret) \
  180. __asm_copy_from_user_2x_cont(to, from, ret, "", "", "")
  181. #define __asm_copy_from_user_3(to, from, ret) \
  182. __asm_copy_from_user_2x_cont(to, from, ret, \
  183. "4: move.b [%1+],$acr\n" \
  184. " move.b $acr,[%0+]\n", \
  185. "5: addq 1,%2\n" \
  186. " clear.b [%0+]\n", \
  187. " .dword 4b,5b\n")
  188. #define __asm_copy_from_user_4x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
  189. __asm_copy_user_cont(to, from, ret, \
  190. COPY \
  191. "2: move.d [%1+],$acr\n" \
  192. " move.d $acr,[%0+]\n", \
  193. FIXUP \
  194. "3: addq 4,%2\n" \
  195. " jump 1b\n" \
  196. " clear.d [%0+]\n", \
  197. TENTRY \
  198. " .dword 2b,3b\n")
  199. #define __asm_copy_from_user_4(to, from, ret) \
  200. __asm_copy_from_user_4x_cont(to, from, ret, "", "", "")
  201. #define __asm_copy_from_user_5(to, from, ret) \
  202. __asm_copy_from_user_4x_cont(to, from, ret, \
  203. "4: move.b [%1+],$acr\n" \
  204. " move.b $acr,[%0+]\n", \
  205. "5: addq 1,%2\n" \
  206. " clear.b [%0+]\n", \
  207. " .dword 4b,5b\n")
  208. #define __asm_copy_from_user_6x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
  209. __asm_copy_from_user_4x_cont(to, from, ret, \
  210. COPY \
  211. "4: move.w [%1+],$acr\n" \
  212. " move.w $acr,[%0+]\n", \
  213. FIXUP \
  214. "5: addq 2,%2\n" \
  215. " clear.w [%0+]\n", \
  216. TENTRY \
  217. " .dword 4b,5b\n")
  218. #define __asm_copy_from_user_6(to, from, ret) \
  219. __asm_copy_from_user_6x_cont(to, from, ret, "", "", "")
  220. #define __asm_copy_from_user_7(to, from, ret) \
  221. __asm_copy_from_user_6x_cont(to, from, ret, \
  222. "6: move.b [%1+],$acr\n" \
  223. " move.b $acr,[%0+]\n", \
  224. "7: addq 1,%2\n" \
  225. " clear.b [%0+]\n", \
  226. " .dword 6b,7b\n")
  227. #define __asm_copy_from_user_8x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
  228. __asm_copy_from_user_4x_cont(to, from, ret, \
  229. COPY \
  230. "4: move.d [%1+],$acr\n" \
  231. " move.d $acr,[%0+]\n", \
  232. FIXUP \
  233. "5: addq 4,%2\n" \
  234. " clear.d [%0+]\n", \
  235. TENTRY \
  236. " .dword 4b,5b\n")
  237. #define __asm_copy_from_user_8(to, from, ret) \
  238. __asm_copy_from_user_8x_cont(to, from, ret, "", "", "")
  239. #define __asm_copy_from_user_9(to, from, ret) \
  240. __asm_copy_from_user_8x_cont(to, from, ret, \
  241. "6: move.b [%1+],$acr\n" \
  242. " move.b $acr,[%0+]\n", \
  243. "7: addq 1,%2\n" \
  244. " clear.b [%0+]\n", \
  245. " .dword 6b,7b\n")
  246. #define __asm_copy_from_user_10x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
  247. __asm_copy_from_user_8x_cont(to, from, ret, \
  248. COPY \
  249. "6: move.w [%1+],$acr\n" \
  250. " move.w $acr,[%0+]\n", \
  251. FIXUP \
  252. "7: addq 2,%2\n" \
  253. " clear.w [%0+]\n", \
  254. TENTRY \
  255. " .dword 6b,7b\n")
  256. #define __asm_copy_from_user_10(to, from, ret) \
  257. __asm_copy_from_user_10x_cont(to, from, ret, "", "", "")
  258. #define __asm_copy_from_user_11(to, from, ret) \
  259. __asm_copy_from_user_10x_cont(to, from, ret, \
  260. "8: move.b [%1+],$acr\n" \
  261. " move.b $acr,[%0+]\n", \
  262. "9: addq 1,%2\n" \
  263. " clear.b [%0+]\n", \
  264. " .dword 8b,9b\n")
  265. #define __asm_copy_from_user_12x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
  266. __asm_copy_from_user_8x_cont(to, from, ret, \
  267. COPY \
  268. "6: move.d [%1+],$acr\n" \
  269. " move.d $acr,[%0+]\n", \
  270. FIXUP \
  271. "7: addq 4,%2\n" \
  272. " clear.d [%0+]\n", \
  273. TENTRY \
  274. " .dword 6b,7b\n")
  275. #define __asm_copy_from_user_12(to, from, ret) \
  276. __asm_copy_from_user_12x_cont(to, from, ret, "", "", "")
  277. #define __asm_copy_from_user_13(to, from, ret) \
  278. __asm_copy_from_user_12x_cont(to, from, ret, \
  279. "8: move.b [%1+],$acr\n" \
  280. " move.b $acr,[%0+]\n", \
  281. "9: addq 1,%2\n" \
  282. " clear.b [%0+]\n", \
  283. " .dword 8b,9b\n")
  284. #define __asm_copy_from_user_14x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
  285. __asm_copy_from_user_12x_cont(to, from, ret, \
  286. COPY \
  287. "8: move.w [%1+],$acr\n" \
  288. " move.w $acr,[%0+]\n", \
  289. FIXUP \
  290. "9: addq 2,%2\n" \
  291. " clear.w [%0+]\n", \
  292. TENTRY \
  293. " .dword 8b,9b\n")
  294. #define __asm_copy_from_user_14(to, from, ret) \
  295. __asm_copy_from_user_14x_cont(to, from, ret, "", "", "")
  296. #define __asm_copy_from_user_15(to, from, ret) \
  297. __asm_copy_from_user_14x_cont(to, from, ret, \
  298. "10: move.b [%1+],$acr\n" \
  299. " move.b $acr,[%0+]\n", \
  300. "11: addq 1,%2\n" \
  301. " clear.b [%0+]\n", \
  302. " .dword 10b,11b\n")
  303. #define __asm_copy_from_user_16x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
  304. __asm_copy_from_user_12x_cont(to, from, ret, \
  305. COPY \
  306. "8: move.d [%1+],$acr\n" \
  307. " move.d $acr,[%0+]\n", \
  308. FIXUP \
  309. "9: addq 4,%2\n" \
  310. " clear.d [%0+]\n", \
  311. TENTRY \
  312. " .dword 8b,9b\n")
  313. #define __asm_copy_from_user_16(to, from, ret) \
  314. __asm_copy_from_user_16x_cont(to, from, ret, "", "", "")
  315. #define __asm_copy_from_user_20x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
  316. __asm_copy_from_user_16x_cont(to, from, ret, \
  317. COPY \
  318. "10: move.d [%1+],$acr\n" \
  319. " move.d $acr,[%0+]\n", \
  320. FIXUP \
  321. "11: addq 4,%2\n" \
  322. " clear.d [%0+]\n", \
  323. TENTRY \
  324. " .dword 10b,11b\n")
  325. #define __asm_copy_from_user_20(to, from, ret) \
  326. __asm_copy_from_user_20x_cont(to, from, ret, "", "", "")
  327. #define __asm_copy_from_user_24x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
  328. __asm_copy_from_user_20x_cont(to, from, ret, \
  329. COPY \
  330. "12: move.d [%1+],$acr\n" \
  331. " move.d $acr,[%0+]\n", \
  332. FIXUP \
  333. "13: addq 4,%2\n" \
  334. " clear.d [%0+]\n", \
  335. TENTRY \
  336. " .dword 12b,13b\n")
  337. #define __asm_copy_from_user_24(to, from, ret) \
  338. __asm_copy_from_user_24x_cont(to, from, ret, "", "", "")
  339. /* And now, the to-user ones. */
  340. #define __asm_copy_to_user_1(to, from, ret) \
  341. __asm_copy_user_cont(to, from, ret, \
  342. " move.b [%1+],$acr\n" \
  343. "2: move.b $acr,[%0+]\n", \
  344. "3: jump 1b\n" \
  345. " addq 1,%2\n", \
  346. " .dword 2b,3b\n")
  347. #define __asm_copy_to_user_2x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
  348. __asm_copy_user_cont(to, from, ret, \
  349. COPY \
  350. " move.w [%1+],$acr\n" \
  351. "2: move.w $acr,[%0+]\n", \
  352. FIXUP \
  353. "3: jump 1b\n" \
  354. " addq 2,%2\n", \
  355. TENTRY \
  356. " .dword 2b,3b\n")
  357. #define __asm_copy_to_user_2(to, from, ret) \
  358. __asm_copy_to_user_2x_cont(to, from, ret, "", "", "")
  359. #define __asm_copy_to_user_3(to, from, ret) \
  360. __asm_copy_to_user_2x_cont(to, from, ret, \
  361. " move.b [%1+],$acr\n" \
  362. "4: move.b $acr,[%0+]\n", \
  363. "5: addq 1,%2\n", \
  364. " .dword 4b,5b\n")
  365. #define __asm_copy_to_user_4x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
  366. __asm_copy_user_cont(to, from, ret, \
  367. COPY \
  368. " move.d [%1+],$acr\n" \
  369. "2: move.d $acr,[%0+]\n", \
  370. FIXUP \
  371. "3: jump 1b\n" \
  372. " addq 4,%2\n", \
  373. TENTRY \
  374. " .dword 2b,3b\n")
  375. #define __asm_copy_to_user_4(to, from, ret) \
  376. __asm_copy_to_user_4x_cont(to, from, ret, "", "", "")
  377. #define __asm_copy_to_user_5(to, from, ret) \
  378. __asm_copy_to_user_4x_cont(to, from, ret, \
  379. " move.b [%1+],$acr\n" \
  380. "4: move.b $acr,[%0+]\n", \
  381. "5: addq 1,%2\n", \
  382. " .dword 4b,5b\n")
  383. #define __asm_copy_to_user_6x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
  384. __asm_copy_to_user_4x_cont(to, from, ret, \
  385. COPY \
  386. " move.w [%1+],$acr\n" \
  387. "4: move.w $acr,[%0+]\n", \
  388. FIXUP \
  389. "5: addq 2,%2\n", \
  390. TENTRY \
  391. " .dword 4b,5b\n")
  392. #define __asm_copy_to_user_6(to, from, ret) \
  393. __asm_copy_to_user_6x_cont(to, from, ret, "", "", "")
  394. #define __asm_copy_to_user_7(to, from, ret) \
  395. __asm_copy_to_user_6x_cont(to, from, ret, \
  396. " move.b [%1+],$acr\n" \
  397. "6: move.b $acr,[%0+]\n", \
  398. "7: addq 1,%2\n", \
  399. " .dword 6b,7b\n")
  400. #define __asm_copy_to_user_8x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
  401. __asm_copy_to_user_4x_cont(to, from, ret, \
  402. COPY \
  403. " move.d [%1+],$acr\n" \
  404. "4: move.d $acr,[%0+]\n", \
  405. FIXUP \
  406. "5: addq 4,%2\n", \
  407. TENTRY \
  408. " .dword 4b,5b\n")
  409. #define __asm_copy_to_user_8(to, from, ret) \
  410. __asm_copy_to_user_8x_cont(to, from, ret, "", "", "")
  411. #define __asm_copy_to_user_9(to, from, ret) \
  412. __asm_copy_to_user_8x_cont(to, from, ret, \
  413. " move.b [%1+],$acr\n" \
  414. "6: move.b $acr,[%0+]\n", \
  415. "7: addq 1,%2\n", \
  416. " .dword 6b,7b\n")
  417. #define __asm_copy_to_user_10x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
  418. __asm_copy_to_user_8x_cont(to, from, ret, \
  419. COPY \
  420. " move.w [%1+],$acr\n" \
  421. "6: move.w $acr,[%0+]\n", \
  422. FIXUP \
  423. "7: addq 2,%2\n", \
  424. TENTRY \
  425. " .dword 6b,7b\n")
  426. #define __asm_copy_to_user_10(to, from, ret) \
  427. __asm_copy_to_user_10x_cont(to, from, ret, "", "", "")
  428. #define __asm_copy_to_user_11(to, from, ret) \
  429. __asm_copy_to_user_10x_cont(to, from, ret, \
  430. " move.b [%1+],$acr\n" \
  431. "8: move.b $acr,[%0+]\n", \
  432. "9: addq 1,%2\n", \
  433. " .dword 8b,9b\n")
  434. #define __asm_copy_to_user_12x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
  435. __asm_copy_to_user_8x_cont(to, from, ret, \
  436. COPY \
  437. " move.d [%1+],$acr\n" \
  438. "6: move.d $acr,[%0+]\n", \
  439. FIXUP \
  440. "7: addq 4,%2\n", \
  441. TENTRY \
  442. " .dword 6b,7b\n")
  443. #define __asm_copy_to_user_12(to, from, ret) \
  444. __asm_copy_to_user_12x_cont(to, from, ret, "", "", "")
  445. #define __asm_copy_to_user_13(to, from, ret) \
  446. __asm_copy_to_user_12x_cont(to, from, ret, \
  447. " move.b [%1+],$acr\n" \
  448. "8: move.b $acr,[%0+]\n", \
  449. "9: addq 1,%2\n", \
  450. " .dword 8b,9b\n")
  451. #define __asm_copy_to_user_14x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
  452. __asm_copy_to_user_12x_cont(to, from, ret, \
  453. COPY \
  454. " move.w [%1+],$acr\n" \
  455. "8: move.w $acr,[%0+]\n", \
  456. FIXUP \
  457. "9: addq 2,%2\n", \
  458. TENTRY \
  459. " .dword 8b,9b\n")
  460. #define __asm_copy_to_user_14(to, from, ret) \
  461. __asm_copy_to_user_14x_cont(to, from, ret, "", "", "")
  462. #define __asm_copy_to_user_15(to, from, ret) \
  463. __asm_copy_to_user_14x_cont(to, from, ret, \
  464. " move.b [%1+],$acr\n" \
  465. "10: move.b $acr,[%0+]\n", \
  466. "11: addq 1,%2\n", \
  467. " .dword 10b,11b\n")
  468. #define __asm_copy_to_user_16x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
  469. __asm_copy_to_user_12x_cont(to, from, ret, \
  470. COPY \
  471. " move.d [%1+],$acr\n" \
  472. "8: move.d $acr,[%0+]\n", \
  473. FIXUP \
  474. "9: addq 4,%2\n", \
  475. TENTRY \
  476. " .dword 8b,9b\n")
  477. #define __asm_copy_to_user_16(to, from, ret) \
  478. __asm_copy_to_user_16x_cont(to, from, ret, "", "", "")
  479. #define __asm_copy_to_user_20x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
  480. __asm_copy_to_user_16x_cont(to, from, ret, \
  481. COPY \
  482. " move.d [%1+],$acr\n" \
  483. "10: move.d $acr,[%0+]\n", \
  484. FIXUP \
  485. "11: addq 4,%2\n", \
  486. TENTRY \
  487. " .dword 10b,11b\n")
  488. #define __asm_copy_to_user_20(to, from, ret) \
  489. __asm_copy_to_user_20x_cont(to, from, ret, "", "", "")
  490. #define __asm_copy_to_user_24x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
  491. __asm_copy_to_user_20x_cont(to, from, ret, \
  492. COPY \
  493. " move.d [%1+],$acr\n" \
  494. "12: move.d $acr,[%0+]\n", \
  495. FIXUP \
  496. "13: addq 4,%2\n", \
  497. TENTRY \
  498. " .dword 12b,13b\n")
  499. #define __asm_copy_to_user_24(to, from, ret) \
  500. __asm_copy_to_user_24x_cont(to, from, ret, "", "", "")
  501. /* Define a few clearing asms with exception handlers. */
  502. /* This frame-asm is like the __asm_copy_user_cont one, but has one less
  503. input. */
  504. #define __asm_clear(to, ret, CLEAR, FIXUP, TENTRY) \
  505. __asm__ __volatile__ ( \
  506. CLEAR \
  507. "1:\n" \
  508. " .section .fixup,\"ax\"\n" \
  509. FIXUP \
  510. " .previous\n" \
  511. " .section __ex_table,\"a\"\n" \
  512. TENTRY \
  513. " .previous" \
  514. : "=b" (to), "=r" (ret) \
  515. : "0" (to), "1" (ret) \
  516. : "memory")
  517. #define __asm_clear_1(to, ret) \
  518. __asm_clear(to, ret, \
  519. "2: clear.b [%0+]\n", \
  520. "3: jump 1b\n" \
  521. " addq 1,%1\n", \
  522. " .dword 2b,3b\n")
  523. #define __asm_clear_2(to, ret) \
  524. __asm_clear(to, ret, \
  525. "2: clear.w [%0+]\n", \
  526. "3: jump 1b\n" \
  527. " addq 2,%1\n", \
  528. " .dword 2b,3b\n")
  529. #define __asm_clear_3(to, ret) \
  530. __asm_clear(to, ret, \
  531. "2: clear.w [%0+]\n" \
  532. "3: clear.b [%0+]\n", \
  533. "4: addq 2,%1\n" \
  534. "5: jump 1b\n" \
  535. " addq 1,%1\n", \
  536. " .dword 2b,4b\n" \
  537. " .dword 3b,5b\n")
  538. #define __asm_clear_4x_cont(to, ret, CLEAR, FIXUP, TENTRY) \
  539. __asm_clear(to, ret, \
  540. CLEAR \
  541. "2: clear.d [%0+]\n", \
  542. FIXUP \
  543. "3: jump 1b\n" \
  544. " addq 4,%1\n", \
  545. TENTRY \
  546. " .dword 2b,3b\n")
  547. #define __asm_clear_4(to, ret) \
  548. __asm_clear_4x_cont(to, ret, "", "", "")
  549. #define __asm_clear_8x_cont(to, ret, CLEAR, FIXUP, TENTRY) \
  550. __asm_clear_4x_cont(to, ret, \
  551. CLEAR \
  552. "4: clear.d [%0+]\n", \
  553. FIXUP \
  554. "5: addq 4,%1\n", \
  555. TENTRY \
  556. " .dword 4b,5b\n")
  557. #define __asm_clear_8(to, ret) \
  558. __asm_clear_8x_cont(to, ret, "", "", "")
  559. #define __asm_clear_12x_cont(to, ret, CLEAR, FIXUP, TENTRY) \
  560. __asm_clear_8x_cont(to, ret, \
  561. CLEAR \
  562. "6: clear.d [%0+]\n", \
  563. FIXUP \
  564. "7: addq 4,%1\n", \
  565. TENTRY \
  566. " .dword 6b,7b\n")
  567. #define __asm_clear_12(to, ret) \
  568. __asm_clear_12x_cont(to, ret, "", "", "")
  569. #define __asm_clear_16x_cont(to, ret, CLEAR, FIXUP, TENTRY) \
  570. __asm_clear_12x_cont(to, ret, \
  571. CLEAR \
  572. "8: clear.d [%0+]\n", \
  573. FIXUP \
  574. "9: addq 4,%1\n", \
  575. TENTRY \
  576. " .dword 8b,9b\n")
  577. #define __asm_clear_16(to, ret) \
  578. __asm_clear_16x_cont(to, ret, "", "", "")
  579. #define __asm_clear_20x_cont(to, ret, CLEAR, FIXUP, TENTRY) \
  580. __asm_clear_16x_cont(to, ret, \
  581. CLEAR \
  582. "10: clear.d [%0+]\n", \
  583. FIXUP \
  584. "11: addq 4,%1\n", \
  585. TENTRY \
  586. " .dword 10b,11b\n")
  587. #define __asm_clear_20(to, ret) \
  588. __asm_clear_20x_cont(to, ret, "", "", "")
  589. #define __asm_clear_24x_cont(to, ret, CLEAR, FIXUP, TENTRY) \
  590. __asm_clear_20x_cont(to, ret, \
  591. CLEAR \
  592. "12: clear.d [%0+]\n", \
  593. FIXUP \
  594. "13: addq 4,%1\n", \
  595. TENTRY \
  596. " .dword 12b,13b\n")
  597. #define __asm_clear_24(to, ret) \
  598. __asm_clear_24x_cont(to, ret, "", "", "")
  599. /*
  600. * Return the size of a string (including the ending 0)
  601. *
  602. * Return length of string in userspace including terminating 0
  603. * or 0 for error. Return a value greater than N if too long.
  604. */
  605. extern inline long
  606. strnlen_user(const char *s, long n)
  607. {
  608. long res, tmp1;
  609. if (!access_ok(VERIFY_READ, s, 0))
  610. return 0;
  611. /*
  612. * This code is deduced from:
  613. *
  614. * tmp1 = n;
  615. * while (tmp1-- > 0 && *s++)
  616. * ;
  617. *
  618. * res = n - tmp1;
  619. *
  620. * (with tweaks).
  621. */
  622. __asm__ __volatile__ (
  623. " move.d %1,$acr\n"
  624. " cmpq 0,$acr\n"
  625. "0:\n"
  626. " ble 1f\n"
  627. " subq 1,$acr\n"
  628. "4: test.b [%0+]\n"
  629. " bne 0b\n"
  630. " cmpq 0,$acr\n"
  631. "1:\n"
  632. " move.d %1,%0\n"
  633. " sub.d $acr,%0\n"
  634. "2:\n"
  635. " .section .fixup,\"ax\"\n"
  636. "3: jump 2b\n"
  637. " clear.d %0\n"
  638. " .previous\n"
  639. " .section __ex_table,\"a\"\n"
  640. " .dword 4b,3b\n"
  641. " .previous\n"
  642. : "=r" (res), "=r" (tmp1)
  643. : "0" (s), "1" (n)
  644. : "acr");
  645. return res;
  646. }
  647. #endif