uaccess.h 18 KB

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