uaccess-user.S 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718
  1. /*
  2. * linux/arch/arm26/lib/uaccess-user.S
  3. *
  4. * Copyright (C) 1995, 1996,1997,1998 Russell King
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License version 2 as
  8. * published by the Free Software Foundation.
  9. *
  10. * Routines to block copy data to/from user memory
  11. * These are highly optimised both for the 4k page size
  12. * and for various alignments.
  13. */
  14. #include <linux/linkage.h>
  15. #include <asm/assembler.h>
  16. #include <asm/errno.h>
  17. #include <asm/page.h>
  18. .text
  19. //FIXME - surely this can be done in C not asm, removing the problem of keeping C and asm in sync? (this is a struct uaccess_t)
  20. .globl uaccess_user
  21. uaccess_user:
  22. .word uaccess_user_put_byte
  23. .word uaccess_user_get_byte
  24. .word uaccess_user_put_half
  25. .word uaccess_user_get_half
  26. .word uaccess_user_put_word
  27. .word uaccess_user_get_word
  28. .word uaccess_user_put_dword
  29. .word uaccess_user_copy_from_user
  30. .word uaccess_user_copy_to_user
  31. .word uaccess_user_clear_user
  32. .word uaccess_user_strncpy_from_user
  33. .word uaccess_user_strnlen_user
  34. @ In : r0 = x, r1 = addr, r2 = error
  35. @ Out: r2 = error
  36. uaccess_user_put_byte:
  37. stmfd sp!, {lr}
  38. USER( strbt r0, [r1])
  39. ldmfd sp!, {pc}^
  40. @ In : r0 = x, r1 = addr, r2 = error
  41. @ Out: r2 = error
  42. uaccess_user_put_half:
  43. stmfd sp!, {lr}
  44. USER( strbt r0, [r1], #1)
  45. mov r0, r0, lsr #8
  46. USER( strbt r0, [r1])
  47. ldmfd sp!, {pc}^
  48. @ In : r0 = x, r1 = addr, r2 = error
  49. @ Out: r2 = error
  50. uaccess_user_put_word:
  51. stmfd sp!, {lr}
  52. USER( strt r0, [r1])
  53. ldmfd sp!, {pc}^
  54. @ In : r0 = x, r1 = addr, r2 = error
  55. @ Out: r2 = error
  56. uaccess_user_put_dword:
  57. stmfd sp!, {lr}
  58. USER( strt r0, [r1], #4)
  59. USER( strt r0, [r1], #0)
  60. ldmfd sp!, {pc}^
  61. 9001: mov r2, #-EFAULT
  62. ldmfd sp!, {pc}^
  63. @ In : r0 = addr, r1 = error
  64. @ Out: r0 = x, r1 = error
  65. uaccess_user_get_byte:
  66. stmfd sp!, {lr}
  67. USER( ldrbt r0, [r0])
  68. ldmfd sp!, {pc}^
  69. @ In : r0 = addr, r1 = error
  70. @ Out: r0 = x, r1 = error
  71. uaccess_user_get_half:
  72. stmfd sp!, {lr}
  73. USER( ldrt r0, [r0])
  74. mov r0, r0, lsl #16
  75. mov r0, r0, lsr #16
  76. ldmfd sp!, {pc}^
  77. @ In : r0 = addr, r1 = error
  78. @ Out: r0 = x, r1 = error
  79. uaccess_user_get_word:
  80. stmfd sp!, {lr}
  81. USER( ldrt r0, [r0])
  82. ldmfd sp!, {pc}^
  83. 9001: mov r1, #-EFAULT
  84. ldmfd sp!, {pc}^
  85. /* Prototype: int uaccess_user_copy_to_user(void *to, const char *from, size_t n)
  86. * Purpose : copy a block to user memory from kernel memory
  87. * Params : to - user memory
  88. * : from - kernel memory
  89. * : n - number of bytes to copy
  90. * Returns : Number of bytes NOT copied.
  91. */
  92. .c2u_dest_not_aligned:
  93. rsb ip, ip, #4
  94. cmp ip, #2
  95. ldrb r3, [r1], #1
  96. USER( strbt r3, [r0], #1) @ May fault
  97. ldrgeb r3, [r1], #1
  98. USER( strgebt r3, [r0], #1) @ May fault
  99. ldrgtb r3, [r1], #1
  100. USER( strgtbt r3, [r0], #1) @ May fault
  101. sub r2, r2, ip
  102. b .c2u_dest_aligned
  103. ENTRY(uaccess_user_copy_to_user)
  104. stmfd sp!, {r2, r4 - r7, lr}
  105. cmp r2, #4
  106. blt .c2u_not_enough
  107. ands ip, r0, #3
  108. bne .c2u_dest_not_aligned
  109. .c2u_dest_aligned:
  110. ands ip, r1, #3
  111. bne .c2u_src_not_aligned
  112. /*
  113. * Seeing as there has to be at least 8 bytes to copy, we can
  114. * copy one word, and force a user-mode page fault...
  115. */
  116. .c2u_0fupi: subs r2, r2, #4
  117. addmi ip, r2, #4
  118. bmi .c2u_0nowords
  119. ldr r3, [r1], #4
  120. USER( strt r3, [r0], #4) @ May fault
  121. mov ip, r0, lsl #32 - PAGE_SHIFT @ On each page, use a ld/st??t instruction
  122. rsb ip, ip, #0
  123. movs ip, ip, lsr #32 - PAGE_SHIFT
  124. beq .c2u_0fupi
  125. /*
  126. * ip = max no. of bytes to copy before needing another "strt" insn
  127. */
  128. cmp r2, ip
  129. movlt ip, r2
  130. sub r2, r2, ip
  131. subs ip, ip, #32
  132. blt .c2u_0rem8lp
  133. .c2u_0cpy8lp: ldmia r1!, {r3 - r6}
  134. stmia r0!, {r3 - r6} @ Shouldnt fault
  135. ldmia r1!, {r3 - r6}
  136. stmia r0!, {r3 - r6} @ Shouldnt fault
  137. subs ip, ip, #32
  138. bpl .c2u_0cpy8lp
  139. .c2u_0rem8lp: cmn ip, #16
  140. ldmgeia r1!, {r3 - r6}
  141. stmgeia r0!, {r3 - r6} @ Shouldnt fault
  142. tst ip, #8
  143. ldmneia r1!, {r3 - r4}
  144. stmneia r0!, {r3 - r4} @ Shouldnt fault
  145. tst ip, #4
  146. ldrne r3, [r1], #4
  147. strnet r3, [r0], #4 @ Shouldnt fault
  148. ands ip, ip, #3
  149. beq .c2u_0fupi
  150. .c2u_0nowords: teq ip, #0
  151. beq .c2u_finished
  152. .c2u_nowords: cmp ip, #2
  153. ldrb r3, [r1], #1
  154. USER( strbt r3, [r0], #1) @ May fault
  155. ldrgeb r3, [r1], #1
  156. USER( strgebt r3, [r0], #1) @ May fault
  157. ldrgtb r3, [r1], #1
  158. USER( strgtbt r3, [r0], #1) @ May fault
  159. b .c2u_finished
  160. .c2u_not_enough:
  161. movs ip, r2
  162. bne .c2u_nowords
  163. .c2u_finished: mov r0, #0
  164. LOADREGS(fd,sp!,{r2, r4 - r7, pc})
  165. .c2u_src_not_aligned:
  166. bic r1, r1, #3
  167. ldr r7, [r1], #4
  168. cmp ip, #2
  169. bgt .c2u_3fupi
  170. beq .c2u_2fupi
  171. .c2u_1fupi: subs r2, r2, #4
  172. addmi ip, r2, #4
  173. bmi .c2u_1nowords
  174. mov r3, r7, pull #8
  175. ldr r7, [r1], #4
  176. orr r3, r3, r7, push #24
  177. USER( strt r3, [r0], #4) @ May fault
  178. mov ip, r0, lsl #32 - PAGE_SHIFT
  179. rsb ip, ip, #0
  180. movs ip, ip, lsr #32 - PAGE_SHIFT
  181. beq .c2u_1fupi
  182. cmp r2, ip
  183. movlt ip, r2
  184. sub r2, r2, ip
  185. subs ip, ip, #16
  186. blt .c2u_1rem8lp
  187. .c2u_1cpy8lp: mov r3, r7, pull #8
  188. ldmia r1!, {r4 - r7}
  189. orr r3, r3, r4, push #24
  190. mov r4, r4, pull #8
  191. orr r4, r4, r5, push #24
  192. mov r5, r5, pull #8
  193. orr r5, r5, r6, push #24
  194. mov r6, r6, pull #8
  195. orr r6, r6, r7, push #24
  196. stmia r0!, {r3 - r6} @ Shouldnt fault
  197. subs ip, ip, #16
  198. bpl .c2u_1cpy8lp
  199. .c2u_1rem8lp: tst ip, #8
  200. movne r3, r7, pull #8
  201. ldmneia r1!, {r4, r7}
  202. orrne r3, r3, r4, push #24
  203. movne r4, r4, pull #8
  204. orrne r4, r4, r7, push #24
  205. stmneia r0!, {r3 - r4} @ Shouldnt fault
  206. tst ip, #4
  207. movne r3, r7, pull #8
  208. ldrne r7, [r1], #4
  209. orrne r3, r3, r7, push #24
  210. strnet r3, [r0], #4 @ Shouldnt fault
  211. ands ip, ip, #3
  212. beq .c2u_1fupi
  213. .c2u_1nowords: mov r3, r7, lsr #byte(1)
  214. teq ip, #0
  215. beq .c2u_finished
  216. cmp ip, #2
  217. USER( strbt r3, [r0], #1) @ May fault
  218. movge r3, r7, lsr #byte(2)
  219. USER( strgebt r3, [r0], #1) @ May fault
  220. movgt r3, r7, lsr #byte(3)
  221. USER( strgtbt r3, [r0], #1) @ May fault
  222. b .c2u_finished
  223. .c2u_2fupi: subs r2, r2, #4
  224. addmi ip, r2, #4
  225. bmi .c2u_2nowords
  226. mov r3, r7, pull #16
  227. ldr r7, [r1], #4
  228. orr r3, r3, r7, push #16
  229. USER( strt r3, [r0], #4) @ May fault
  230. mov ip, r0, lsl #32 - PAGE_SHIFT
  231. rsb ip, ip, #0
  232. movs ip, ip, lsr #32 - PAGE_SHIFT
  233. beq .c2u_2fupi
  234. cmp r2, ip
  235. movlt ip, r2
  236. sub r2, r2, ip
  237. subs ip, ip, #16
  238. blt .c2u_2rem8lp
  239. .c2u_2cpy8lp: mov r3, r7, pull #16
  240. ldmia r1!, {r4 - r7}
  241. orr r3, r3, r4, push #16
  242. mov r4, r4, pull #16
  243. orr r4, r4, r5, push #16
  244. mov r5, r5, pull #16
  245. orr r5, r5, r6, push #16
  246. mov r6, r6, pull #16
  247. orr r6, r6, r7, push #16
  248. stmia r0!, {r3 - r6} @ Shouldnt fault
  249. subs ip, ip, #16
  250. bpl .c2u_2cpy8lp
  251. .c2u_2rem8lp: tst ip, #8
  252. movne r3, r7, pull #16
  253. ldmneia r1!, {r4, r7}
  254. orrne r3, r3, r4, push #16
  255. movne r4, r4, pull #16
  256. orrne r4, r4, r7, push #16
  257. stmneia r0!, {r3 - r4} @ Shouldnt fault
  258. tst ip, #4
  259. movne r3, r7, pull #16
  260. ldrne r7, [r1], #4
  261. orrne r3, r3, r7, push #16
  262. strnet r3, [r0], #4 @ Shouldnt fault
  263. ands ip, ip, #3
  264. beq .c2u_2fupi
  265. .c2u_2nowords: mov r3, r7, lsr #byte(2)
  266. teq ip, #0
  267. beq .c2u_finished
  268. cmp ip, #2
  269. USER( strbt r3, [r0], #1) @ May fault
  270. movge r3, r7, lsr #byte(3)
  271. USER( strgebt r3, [r0], #1) @ May fault
  272. ldrgtb r3, [r1], #0
  273. USER( strgtbt r3, [r0], #1) @ May fault
  274. b .c2u_finished
  275. .c2u_3fupi: subs r2, r2, #4
  276. addmi ip, r2, #4
  277. bmi .c2u_3nowords
  278. mov r3, r7, pull #24
  279. ldr r7, [r1], #4
  280. orr r3, r3, r7, push #8
  281. USER( strt r3, [r0], #4) @ May fault
  282. mov ip, r0, lsl #32 - PAGE_SHIFT
  283. rsb ip, ip, #0
  284. movs ip, ip, lsr #32 - PAGE_SHIFT
  285. beq .c2u_3fupi
  286. cmp r2, ip
  287. movlt ip, r2
  288. sub r2, r2, ip
  289. subs ip, ip, #16
  290. blt .c2u_3rem8lp
  291. .c2u_3cpy8lp: mov r3, r7, pull #24
  292. ldmia r1!, {r4 - r7}
  293. orr r3, r3, r4, push #8
  294. mov r4, r4, pull #24
  295. orr r4, r4, r5, push #8
  296. mov r5, r5, pull #24
  297. orr r5, r5, r6, push #8
  298. mov r6, r6, pull #24
  299. orr r6, r6, r7, push #8
  300. stmia r0!, {r3 - r6} @ Shouldnt fault
  301. subs ip, ip, #16
  302. bpl .c2u_3cpy8lp
  303. .c2u_3rem8lp: tst ip, #8
  304. movne r3, r7, pull #24
  305. ldmneia r1!, {r4, r7}
  306. orrne r3, r3, r4, push #8
  307. movne r4, r4, pull #24
  308. orrne r4, r4, r7, push #8
  309. stmneia r0!, {r3 - r4} @ Shouldnt fault
  310. tst ip, #4
  311. movne r3, r7, pull #24
  312. ldrne r7, [r1], #4
  313. orrne r3, r3, r7, push #8
  314. strnet r3, [r0], #4 @ Shouldnt fault
  315. ands ip, ip, #3
  316. beq .c2u_3fupi
  317. .c2u_3nowords: mov r3, r7, lsr #byte(3)
  318. teq ip, #0
  319. beq .c2u_finished
  320. cmp ip, #2
  321. USER( strbt r3, [r0], #1) @ May fault
  322. ldrgeb r3, [r1], #1
  323. USER( strgebt r3, [r0], #1) @ May fault
  324. ldrgtb r3, [r1], #0
  325. USER( strgtbt r3, [r0], #1) @ May fault
  326. b .c2u_finished
  327. .section .fixup,"ax"
  328. .align 0
  329. 9001: LOADREGS(fd,sp!, {r0, r4 - r7, pc})
  330. .previous
  331. /* Prototype: unsigned long uaccess_user_copy_from_user(void *to,const void *from,unsigned long n);
  332. * Purpose : copy a block from user memory to kernel memory
  333. * Params : to - kernel memory
  334. * : from - user memory
  335. * : n - number of bytes to copy
  336. * Returns : Number of bytes NOT copied.
  337. */
  338. .cfu_dest_not_aligned:
  339. rsb ip, ip, #4
  340. cmp ip, #2
  341. USER( ldrbt r3, [r1], #1) @ May fault
  342. strb r3, [r0], #1
  343. USER( ldrgebt r3, [r1], #1) @ May fault
  344. strgeb r3, [r0], #1
  345. USER( ldrgtbt r3, [r1], #1) @ May fault
  346. strgtb r3, [r0], #1
  347. sub r2, r2, ip
  348. b .cfu_dest_aligned
  349. ENTRY(uaccess_user_copy_from_user)
  350. stmfd sp!, {r0, r2, r4 - r7, lr}
  351. cmp r2, #4
  352. blt .cfu_not_enough
  353. ands ip, r0, #3
  354. bne .cfu_dest_not_aligned
  355. .cfu_dest_aligned:
  356. ands ip, r1, #3
  357. bne .cfu_src_not_aligned
  358. /*
  359. * Seeing as there has to be at least 8 bytes to copy, we can
  360. * copy one word, and force a user-mode page fault...
  361. */
  362. .cfu_0fupi: subs r2, r2, #4
  363. addmi ip, r2, #4
  364. bmi .cfu_0nowords
  365. USER( ldrt r3, [r1], #4)
  366. str r3, [r0], #4
  367. mov ip, r1, lsl #32 - PAGE_SHIFT @ On each page, use a ld/st??t instruction
  368. rsb ip, ip, #0
  369. movs ip, ip, lsr #32 - PAGE_SHIFT
  370. beq .cfu_0fupi
  371. /*
  372. * ip = max no. of bytes to copy before needing another "strt" insn
  373. */
  374. cmp r2, ip
  375. movlt ip, r2
  376. sub r2, r2, ip
  377. subs ip, ip, #32
  378. blt .cfu_0rem8lp
  379. .cfu_0cpy8lp: ldmia r1!, {r3 - r6} @ Shouldnt fault
  380. stmia r0!, {r3 - r6}
  381. ldmia r1!, {r3 - r6} @ Shouldnt fault
  382. stmia r0!, {r3 - r6}
  383. subs ip, ip, #32
  384. bpl .cfu_0cpy8lp
  385. .cfu_0rem8lp: cmn ip, #16
  386. ldmgeia r1!, {r3 - r6} @ Shouldnt fault
  387. stmgeia r0!, {r3 - r6}
  388. tst ip, #8
  389. ldmneia r1!, {r3 - r4} @ Shouldnt fault
  390. stmneia r0!, {r3 - r4}
  391. tst ip, #4
  392. ldrnet r3, [r1], #4 @ Shouldnt fault
  393. strne r3, [r0], #4
  394. ands ip, ip, #3
  395. beq .cfu_0fupi
  396. .cfu_0nowords: teq ip, #0
  397. beq .cfu_finished
  398. .cfu_nowords: cmp ip, #2
  399. USER( ldrbt r3, [r1], #1) @ May fault
  400. strb r3, [r0], #1
  401. USER( ldrgebt r3, [r1], #1) @ May fault
  402. strgeb r3, [r0], #1
  403. USER( ldrgtbt r3, [r1], #1) @ May fault
  404. strgtb r3, [r0], #1
  405. b .cfu_finished
  406. .cfu_not_enough:
  407. movs ip, r2
  408. bne .cfu_nowords
  409. .cfu_finished: mov r0, #0
  410. add sp, sp, #8
  411. LOADREGS(fd,sp!,{r4 - r7, pc})
  412. .cfu_src_not_aligned:
  413. bic r1, r1, #3
  414. USER( ldrt r7, [r1], #4) @ May fault
  415. cmp ip, #2
  416. bgt .cfu_3fupi
  417. beq .cfu_2fupi
  418. .cfu_1fupi: subs r2, r2, #4
  419. addmi ip, r2, #4
  420. bmi .cfu_1nowords
  421. mov r3, r7, pull #8
  422. USER( ldrt r7, [r1], #4) @ May fault
  423. orr r3, r3, r7, push #24
  424. str r3, [r0], #4
  425. mov ip, r1, lsl #32 - PAGE_SHIFT
  426. rsb ip, ip, #0
  427. movs ip, ip, lsr #32 - PAGE_SHIFT
  428. beq .cfu_1fupi
  429. cmp r2, ip
  430. movlt ip, r2
  431. sub r2, r2, ip
  432. subs ip, ip, #16
  433. blt .cfu_1rem8lp
  434. .cfu_1cpy8lp: mov r3, r7, pull #8
  435. ldmia r1!, {r4 - r7} @ Shouldnt fault
  436. orr r3, r3, r4, push #24
  437. mov r4, r4, pull #8
  438. orr r4, r4, r5, push #24
  439. mov r5, r5, pull #8
  440. orr r5, r5, r6, push #24
  441. mov r6, r6, pull #8
  442. orr r6, r6, r7, push #24
  443. stmia r0!, {r3 - r6}
  444. subs ip, ip, #16
  445. bpl .cfu_1cpy8lp
  446. .cfu_1rem8lp: tst ip, #8
  447. movne r3, r7, pull #8
  448. ldmneia r1!, {r4, r7} @ Shouldnt fault
  449. orrne r3, r3, r4, push #24
  450. movne r4, r4, pull #8
  451. orrne r4, r4, r7, push #24
  452. stmneia r0!, {r3 - r4}
  453. tst ip, #4
  454. movne r3, r7, pull #8
  455. USER( ldrnet r7, [r1], #4) @ May fault
  456. orrne r3, r3, r7, push #24
  457. strne r3, [r0], #4
  458. ands ip, ip, #3
  459. beq .cfu_1fupi
  460. .cfu_1nowords: mov r3, r7, lsr #byte(1)
  461. teq ip, #0
  462. beq .cfu_finished
  463. cmp ip, #2
  464. strb r3, [r0], #1
  465. movge r3, r7, lsr #byte(2)
  466. strgeb r3, [r0], #1
  467. movgt r3, r7, lsr #byte(3)
  468. strgtb r3, [r0], #1
  469. b .cfu_finished
  470. .cfu_2fupi: subs r2, r2, #4
  471. addmi ip, r2, #4
  472. bmi .cfu_2nowords
  473. mov r3, r7, pull #16
  474. USER( ldrt r7, [r1], #4) @ May fault
  475. orr r3, r3, r7, push #16
  476. str r3, [r0], #4
  477. mov ip, r1, lsl #32 - PAGE_SHIFT
  478. rsb ip, ip, #0
  479. movs ip, ip, lsr #32 - PAGE_SHIFT
  480. beq .cfu_2fupi
  481. cmp r2, ip
  482. movlt ip, r2
  483. sub r2, r2, ip
  484. subs ip, ip, #16
  485. blt .cfu_2rem8lp
  486. .cfu_2cpy8lp: mov r3, r7, pull #16
  487. ldmia r1!, {r4 - r7} @ Shouldnt fault
  488. orr r3, r3, r4, push #16
  489. mov r4, r4, pull #16
  490. orr r4, r4, r5, push #16
  491. mov r5, r5, pull #16
  492. orr r5, r5, r6, push #16
  493. mov r6, r6, pull #16
  494. orr r6, r6, r7, push #16
  495. stmia r0!, {r3 - r6}
  496. subs ip, ip, #16
  497. bpl .cfu_2cpy8lp
  498. .cfu_2rem8lp: tst ip, #8
  499. movne r3, r7, pull #16
  500. ldmneia r1!, {r4, r7} @ Shouldnt fault
  501. orrne r3, r3, r4, push #16
  502. movne r4, r4, pull #16
  503. orrne r4, r4, r7, push #16
  504. stmneia r0!, {r3 - r4}
  505. tst ip, #4
  506. movne r3, r7, pull #16
  507. USER( ldrnet r7, [r1], #4) @ May fault
  508. orrne r3, r3, r7, push #16
  509. strne r3, [r0], #4
  510. ands ip, ip, #3
  511. beq .cfu_2fupi
  512. .cfu_2nowords: mov r3, r7, lsr #byte(2)
  513. teq ip, #0
  514. beq .cfu_finished
  515. cmp ip, #2
  516. strb r3, [r0], #1
  517. movge r3, r7, lsr #byte(3)
  518. strgeb r3, [r0], #1
  519. USER( ldrgtbt r3, [r1], #0) @ May fault
  520. strgtb r3, [r0], #1
  521. b .cfu_finished
  522. .cfu_3fupi: subs r2, r2, #4
  523. addmi ip, r2, #4
  524. bmi .cfu_3nowords
  525. mov r3, r7, pull #24
  526. USER( ldrt r7, [r1], #4) @ May fault
  527. orr r3, r3, r7, push #8
  528. str r3, [r0], #4
  529. mov ip, r1, lsl #32 - PAGE_SHIFT
  530. rsb ip, ip, #0
  531. movs ip, ip, lsr #32 - PAGE_SHIFT
  532. beq .cfu_3fupi
  533. cmp r2, ip
  534. movlt ip, r2
  535. sub r2, r2, ip
  536. subs ip, ip, #16
  537. blt .cfu_3rem8lp
  538. .cfu_3cpy8lp: mov r3, r7, pull #24
  539. ldmia r1!, {r4 - r7} @ Shouldnt fault
  540. orr r3, r3, r4, push #8
  541. mov r4, r4, pull #24
  542. orr r4, r4, r5, push #8
  543. mov r5, r5, pull #24
  544. orr r5, r5, r6, push #8
  545. mov r6, r6, pull #24
  546. orr r6, r6, r7, push #8
  547. stmia r0!, {r3 - r6}
  548. subs ip, ip, #16
  549. bpl .cfu_3cpy8lp
  550. .cfu_3rem8lp: tst ip, #8
  551. movne r3, r7, pull #24
  552. ldmneia r1!, {r4, r7} @ Shouldnt fault
  553. orrne r3, r3, r4, push #8
  554. movne r4, r4, pull #24
  555. orrne r4, r4, r7, push #8
  556. stmneia r0!, {r3 - r4}
  557. tst ip, #4
  558. movne r3, r7, pull #24
  559. USER( ldrnet r7, [r1], #4) @ May fault
  560. orrne r3, r3, r7, push #8
  561. strne r3, [r0], #4
  562. ands ip, ip, #3
  563. beq .cfu_3fupi
  564. .cfu_3nowords: mov r3, r7, lsr #byte(3)
  565. teq ip, #0
  566. beq .cfu_finished
  567. cmp ip, #2
  568. strb r3, [r0], #1
  569. USER( ldrgebt r3, [r1], #1) @ May fault
  570. strgeb r3, [r0], #1
  571. USER( ldrgtbt r3, [r1], #1) @ May fault
  572. strgtb r3, [r0], #1
  573. b .cfu_finished
  574. .section .fixup,"ax"
  575. .align 0
  576. /*
  577. * We took an exception. r0 contains a pointer to
  578. * the byte not copied.
  579. */
  580. 9001: ldr r2, [sp], #4 @ void *to
  581. sub r2, r0, r2 @ bytes copied
  582. ldr r1, [sp], #4 @ unsigned long count
  583. subs r4, r1, r2 @ bytes left to copy
  584. movne r1, r4
  585. blne __memzero
  586. mov r0, r4
  587. LOADREGS(fd,sp!, {r4 - r7, pc})
  588. .previous
  589. /* Prototype: int uaccess_user_clear_user(void *addr, size_t sz)
  590. * Purpose : clear some user memory
  591. * Params : addr - user memory address to clear
  592. * : sz - number of bytes to clear
  593. * Returns : number of bytes NOT cleared
  594. */
  595. ENTRY(uaccess_user_clear_user)
  596. stmfd sp!, {r1, lr}
  597. mov r2, #0
  598. cmp r1, #4
  599. blt 2f
  600. ands ip, r0, #3
  601. beq 1f
  602. cmp ip, #2
  603. USER( strbt r2, [r0], #1)
  604. USER( strlebt r2, [r0], #1)
  605. USER( strltbt r2, [r0], #1)
  606. rsb ip, ip, #4
  607. sub r1, r1, ip @ 7 6 5 4 3 2 1
  608. 1: subs r1, r1, #8 @ -1 -2 -3 -4 -5 -6 -7
  609. USER( strplt r2, [r0], #4)
  610. USER( strplt r2, [r0], #4)
  611. bpl 1b
  612. adds r1, r1, #4 @ 3 2 1 0 -1 -2 -3
  613. USER( strplt r2, [r0], #4)
  614. 2: tst r1, #2 @ 1x 1x 0x 0x 1x 1x 0x
  615. USER( strnebt r2, [r0], #1)
  616. USER( strnebt r2, [r0], #1)
  617. tst r1, #1 @ x1 x0 x1 x0 x1 x0 x1
  618. USER( strnebt r2, [r0], #1)
  619. mov r0, #0
  620. LOADREGS(fd,sp!, {r1, pc})
  621. .section .fixup,"ax"
  622. .align 0
  623. 9001: LOADREGS(fd,sp!, {r0, pc})
  624. .previous
  625. /*
  626. * Copy a string from user space to kernel space.
  627. * r0 = dst, r1 = src, r2 = byte length
  628. * returns the number of characters copied (strlen of copied string),
  629. * -EFAULT on exception, or "len" if we fill the whole buffer
  630. */
  631. ENTRY(uaccess_user_strncpy_from_user)
  632. save_lr
  633. mov ip, r1
  634. 1: subs r2, r2, #1
  635. USER( ldrplbt r3, [r1], #1)
  636. bmi 2f
  637. strb r3, [r0], #1
  638. teq r3, #0
  639. bne 1b
  640. sub r1, r1, #1 @ take NUL character out of count
  641. 2: sub r0, r1, ip
  642. restore_pc
  643. .section .fixup,"ax"
  644. .align 0
  645. 9001: mov r3, #0
  646. strb r3, [r0, #0] @ null terminate
  647. mov r0, #-EFAULT
  648. restore_pc
  649. .previous
  650. /* Prototype: unsigned long uaccess_user_strnlen_user(const char *str, long n)
  651. * Purpose : get length of a string in user memory
  652. * Params : str - address of string in user memory
  653. * Returns : length of string *including terminator*
  654. * or zero on exception, or n + 1 if too long
  655. */
  656. ENTRY(uaccess_user_strnlen_user)
  657. save_lr
  658. mov r2, r0
  659. 1:
  660. USER( ldrbt r3, [r0], #1)
  661. teq r3, #0
  662. beq 2f
  663. subs r1, r1, #1
  664. bne 1b
  665. add r0, r0, #1
  666. 2: sub r0, r0, r2
  667. restore_pc
  668. .section .fixup,"ax"
  669. .align 0
  670. 9001: mov r0, #0
  671. restore_pc
  672. .previous