uaccess.S 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565
  1. /*
  2. * linux/arch/arm/lib/uaccess.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/domain.h>
  18. .text
  19. #define PAGE_SHIFT 12
  20. /* Prototype: int __copy_to_user(void *to, const char *from, size_t n)
  21. * Purpose : copy a block to user memory from kernel memory
  22. * Params : to - user memory
  23. * : from - kernel memory
  24. * : n - number of bytes to copy
  25. * Returns : Number of bytes NOT copied.
  26. */
  27. .Lc2u_dest_not_aligned:
  28. rsb ip, ip, #4
  29. cmp ip, #2
  30. ldrb r3, [r1], #1
  31. USER( TUSER( strb) r3, [r0], #1) @ May fault
  32. ldrgeb r3, [r1], #1
  33. USER( TUSER( strgeb) r3, [r0], #1) @ May fault
  34. ldrgtb r3, [r1], #1
  35. USER( TUSER( strgtb) r3, [r0], #1) @ May fault
  36. sub r2, r2, ip
  37. b .Lc2u_dest_aligned
  38. ENTRY(__copy_to_user)
  39. stmfd sp!, {r2, r4 - r7, lr}
  40. cmp r2, #4
  41. blt .Lc2u_not_enough
  42. ands ip, r0, #3
  43. bne .Lc2u_dest_not_aligned
  44. .Lc2u_dest_aligned:
  45. ands ip, r1, #3
  46. bne .Lc2u_src_not_aligned
  47. /*
  48. * Seeing as there has to be at least 8 bytes to copy, we can
  49. * copy one word, and force a user-mode page fault...
  50. */
  51. .Lc2u_0fupi: subs r2, r2, #4
  52. addmi ip, r2, #4
  53. bmi .Lc2u_0nowords
  54. ldr r3, [r1], #4
  55. USER( TUSER( str) r3, [r0], #4) @ May fault
  56. mov ip, r0, lsl #32 - PAGE_SHIFT @ On each page, use a ld/st??t instruction
  57. rsb ip, ip, #0
  58. movs ip, ip, lsr #32 - PAGE_SHIFT
  59. beq .Lc2u_0fupi
  60. /*
  61. * ip = max no. of bytes to copy before needing another "strt" insn
  62. */
  63. cmp r2, ip
  64. movlt ip, r2
  65. sub r2, r2, ip
  66. subs ip, ip, #32
  67. blt .Lc2u_0rem8lp
  68. .Lc2u_0cpy8lp: ldmia r1!, {r3 - r6}
  69. stmia r0!, {r3 - r6} @ Shouldnt fault
  70. ldmia r1!, {r3 - r6}
  71. subs ip, ip, #32
  72. stmia r0!, {r3 - r6} @ Shouldnt fault
  73. bpl .Lc2u_0cpy8lp
  74. .Lc2u_0rem8lp: cmn ip, #16
  75. ldmgeia r1!, {r3 - r6}
  76. stmgeia r0!, {r3 - r6} @ Shouldnt fault
  77. tst ip, #8
  78. ldmneia r1!, {r3 - r4}
  79. stmneia r0!, {r3 - r4} @ Shouldnt fault
  80. tst ip, #4
  81. ldrne r3, [r1], #4
  82. TUSER( strne) r3, [r0], #4 @ Shouldnt fault
  83. ands ip, ip, #3
  84. beq .Lc2u_0fupi
  85. .Lc2u_0nowords: teq ip, #0
  86. beq .Lc2u_finished
  87. .Lc2u_nowords: cmp ip, #2
  88. ldrb r3, [r1], #1
  89. USER( TUSER( strb) r3, [r0], #1) @ May fault
  90. ldrgeb r3, [r1], #1
  91. USER( TUSER( strgeb) r3, [r0], #1) @ May fault
  92. ldrgtb r3, [r1], #1
  93. USER( TUSER( strgtb) r3, [r0], #1) @ May fault
  94. b .Lc2u_finished
  95. .Lc2u_not_enough:
  96. movs ip, r2
  97. bne .Lc2u_nowords
  98. .Lc2u_finished: mov r0, #0
  99. ldmfd sp!, {r2, r4 - r7, pc}
  100. .Lc2u_src_not_aligned:
  101. bic r1, r1, #3
  102. ldr r7, [r1], #4
  103. cmp ip, #2
  104. bgt .Lc2u_3fupi
  105. beq .Lc2u_2fupi
  106. .Lc2u_1fupi: subs r2, r2, #4
  107. addmi ip, r2, #4
  108. bmi .Lc2u_1nowords
  109. mov r3, r7, pull #8
  110. ldr r7, [r1], #4
  111. orr r3, r3, r7, push #24
  112. USER( TUSER( str) r3, [r0], #4) @ May fault
  113. mov ip, r0, lsl #32 - PAGE_SHIFT
  114. rsb ip, ip, #0
  115. movs ip, ip, lsr #32 - PAGE_SHIFT
  116. beq .Lc2u_1fupi
  117. cmp r2, ip
  118. movlt ip, r2
  119. sub r2, r2, ip
  120. subs ip, ip, #16
  121. blt .Lc2u_1rem8lp
  122. .Lc2u_1cpy8lp: mov r3, r7, pull #8
  123. ldmia r1!, {r4 - r7}
  124. subs ip, ip, #16
  125. orr r3, r3, r4, push #24
  126. mov r4, r4, pull #8
  127. orr r4, r4, r5, push #24
  128. mov r5, r5, pull #8
  129. orr r5, r5, r6, push #24
  130. mov r6, r6, pull #8
  131. orr r6, r6, r7, push #24
  132. stmia r0!, {r3 - r6} @ Shouldnt fault
  133. bpl .Lc2u_1cpy8lp
  134. .Lc2u_1rem8lp: tst ip, #8
  135. movne r3, r7, pull #8
  136. ldmneia r1!, {r4, r7}
  137. orrne r3, r3, r4, push #24
  138. movne r4, r4, pull #8
  139. orrne r4, r4, r7, push #24
  140. stmneia r0!, {r3 - r4} @ Shouldnt fault
  141. tst ip, #4
  142. movne r3, r7, pull #8
  143. ldrne r7, [r1], #4
  144. orrne r3, r3, r7, push #24
  145. TUSER( strne) r3, [r0], #4 @ Shouldnt fault
  146. ands ip, ip, #3
  147. beq .Lc2u_1fupi
  148. .Lc2u_1nowords: mov r3, r7, get_byte_1
  149. teq ip, #0
  150. beq .Lc2u_finished
  151. cmp ip, #2
  152. USER( TUSER( strb) r3, [r0], #1) @ May fault
  153. movge r3, r7, get_byte_2
  154. USER( TUSER( strgeb) r3, [r0], #1) @ May fault
  155. movgt r3, r7, get_byte_3
  156. USER( TUSER( strgtb) r3, [r0], #1) @ May fault
  157. b .Lc2u_finished
  158. .Lc2u_2fupi: subs r2, r2, #4
  159. addmi ip, r2, #4
  160. bmi .Lc2u_2nowords
  161. mov r3, r7, pull #16
  162. ldr r7, [r1], #4
  163. orr r3, r3, r7, push #16
  164. USER( TUSER( str) r3, [r0], #4) @ May fault
  165. mov ip, r0, lsl #32 - PAGE_SHIFT
  166. rsb ip, ip, #0
  167. movs ip, ip, lsr #32 - PAGE_SHIFT
  168. beq .Lc2u_2fupi
  169. cmp r2, ip
  170. movlt ip, r2
  171. sub r2, r2, ip
  172. subs ip, ip, #16
  173. blt .Lc2u_2rem8lp
  174. .Lc2u_2cpy8lp: mov r3, r7, pull #16
  175. ldmia r1!, {r4 - r7}
  176. subs ip, ip, #16
  177. orr r3, r3, r4, push #16
  178. mov r4, r4, pull #16
  179. orr r4, r4, r5, push #16
  180. mov r5, r5, pull #16
  181. orr r5, r5, r6, push #16
  182. mov r6, r6, pull #16
  183. orr r6, r6, r7, push #16
  184. stmia r0!, {r3 - r6} @ Shouldnt fault
  185. bpl .Lc2u_2cpy8lp
  186. .Lc2u_2rem8lp: tst ip, #8
  187. movne r3, r7, pull #16
  188. ldmneia r1!, {r4, r7}
  189. orrne r3, r3, r4, push #16
  190. movne r4, r4, pull #16
  191. orrne r4, r4, r7, push #16
  192. stmneia r0!, {r3 - r4} @ Shouldnt fault
  193. tst ip, #4
  194. movne r3, r7, pull #16
  195. ldrne r7, [r1], #4
  196. orrne r3, r3, r7, push #16
  197. TUSER( strne) r3, [r0], #4 @ Shouldnt fault
  198. ands ip, ip, #3
  199. beq .Lc2u_2fupi
  200. .Lc2u_2nowords: mov r3, r7, get_byte_2
  201. teq ip, #0
  202. beq .Lc2u_finished
  203. cmp ip, #2
  204. USER( TUSER( strb) r3, [r0], #1) @ May fault
  205. movge r3, r7, get_byte_3
  206. USER( TUSER( strgeb) r3, [r0], #1) @ May fault
  207. ldrgtb r3, [r1], #0
  208. USER( TUSER( strgtb) r3, [r0], #1) @ May fault
  209. b .Lc2u_finished
  210. .Lc2u_3fupi: subs r2, r2, #4
  211. addmi ip, r2, #4
  212. bmi .Lc2u_3nowords
  213. mov r3, r7, pull #24
  214. ldr r7, [r1], #4
  215. orr r3, r3, r7, push #8
  216. USER( TUSER( str) r3, [r0], #4) @ May fault
  217. mov ip, r0, lsl #32 - PAGE_SHIFT
  218. rsb ip, ip, #0
  219. movs ip, ip, lsr #32 - PAGE_SHIFT
  220. beq .Lc2u_3fupi
  221. cmp r2, ip
  222. movlt ip, r2
  223. sub r2, r2, ip
  224. subs ip, ip, #16
  225. blt .Lc2u_3rem8lp
  226. .Lc2u_3cpy8lp: mov r3, r7, pull #24
  227. ldmia r1!, {r4 - r7}
  228. subs ip, ip, #16
  229. orr r3, r3, r4, push #8
  230. mov r4, r4, pull #24
  231. orr r4, r4, r5, push #8
  232. mov r5, r5, pull #24
  233. orr r5, r5, r6, push #8
  234. mov r6, r6, pull #24
  235. orr r6, r6, r7, push #8
  236. stmia r0!, {r3 - r6} @ Shouldnt fault
  237. bpl .Lc2u_3cpy8lp
  238. .Lc2u_3rem8lp: tst ip, #8
  239. movne r3, r7, pull #24
  240. ldmneia r1!, {r4, r7}
  241. orrne r3, r3, r4, push #8
  242. movne r4, r4, pull #24
  243. orrne r4, r4, r7, push #8
  244. stmneia r0!, {r3 - r4} @ Shouldnt fault
  245. tst ip, #4
  246. movne r3, r7, pull #24
  247. ldrne r7, [r1], #4
  248. orrne r3, r3, r7, push #8
  249. TUSER( strne) r3, [r0], #4 @ Shouldnt fault
  250. ands ip, ip, #3
  251. beq .Lc2u_3fupi
  252. .Lc2u_3nowords: mov r3, r7, get_byte_3
  253. teq ip, #0
  254. beq .Lc2u_finished
  255. cmp ip, #2
  256. USER( TUSER( strb) r3, [r0], #1) @ May fault
  257. ldrgeb r3, [r1], #1
  258. USER( TUSER( strgeb) r3, [r0], #1) @ May fault
  259. ldrgtb r3, [r1], #0
  260. USER( TUSER( strgtb) r3, [r0], #1) @ May fault
  261. b .Lc2u_finished
  262. ENDPROC(__copy_to_user)
  263. .pushsection .fixup,"ax"
  264. .align 0
  265. 9001: ldmfd sp!, {r0, r4 - r7, pc}
  266. .popsection
  267. /* Prototype: unsigned long __copy_from_user(void *to,const void *from,unsigned long n);
  268. * Purpose : copy a block from user memory to kernel memory
  269. * Params : to - kernel memory
  270. * : from - user memory
  271. * : n - number of bytes to copy
  272. * Returns : Number of bytes NOT copied.
  273. */
  274. .Lcfu_dest_not_aligned:
  275. rsb ip, ip, #4
  276. cmp ip, #2
  277. USER( TUSER( ldrb) r3, [r1], #1) @ May fault
  278. strb r3, [r0], #1
  279. USER( TUSER( ldrgeb) r3, [r1], #1) @ May fault
  280. strgeb r3, [r0], #1
  281. USER( TUSER( ldrgtb) r3, [r1], #1) @ May fault
  282. strgtb r3, [r0], #1
  283. sub r2, r2, ip
  284. b .Lcfu_dest_aligned
  285. ENTRY(__copy_from_user)
  286. stmfd sp!, {r0, r2, r4 - r7, lr}
  287. cmp r2, #4
  288. blt .Lcfu_not_enough
  289. ands ip, r0, #3
  290. bne .Lcfu_dest_not_aligned
  291. .Lcfu_dest_aligned:
  292. ands ip, r1, #3
  293. bne .Lcfu_src_not_aligned
  294. /*
  295. * Seeing as there has to be at least 8 bytes to copy, we can
  296. * copy one word, and force a user-mode page fault...
  297. */
  298. .Lcfu_0fupi: subs r2, r2, #4
  299. addmi ip, r2, #4
  300. bmi .Lcfu_0nowords
  301. USER( TUSER( ldr) r3, [r1], #4)
  302. str r3, [r0], #4
  303. mov ip, r1, lsl #32 - PAGE_SHIFT @ On each page, use a ld/st??t instruction
  304. rsb ip, ip, #0
  305. movs ip, ip, lsr #32 - PAGE_SHIFT
  306. beq .Lcfu_0fupi
  307. /*
  308. * ip = max no. of bytes to copy before needing another "strt" insn
  309. */
  310. cmp r2, ip
  311. movlt ip, r2
  312. sub r2, r2, ip
  313. subs ip, ip, #32
  314. blt .Lcfu_0rem8lp
  315. .Lcfu_0cpy8lp: ldmia r1!, {r3 - r6} @ Shouldnt fault
  316. stmia r0!, {r3 - r6}
  317. ldmia r1!, {r3 - r6} @ Shouldnt fault
  318. subs ip, ip, #32
  319. stmia r0!, {r3 - r6}
  320. bpl .Lcfu_0cpy8lp
  321. .Lcfu_0rem8lp: cmn ip, #16
  322. ldmgeia r1!, {r3 - r6} @ Shouldnt fault
  323. stmgeia r0!, {r3 - r6}
  324. tst ip, #8
  325. ldmneia r1!, {r3 - r4} @ Shouldnt fault
  326. stmneia r0!, {r3 - r4}
  327. tst ip, #4
  328. TUSER( ldrne) r3, [r1], #4 @ Shouldnt fault
  329. strne r3, [r0], #4
  330. ands ip, ip, #3
  331. beq .Lcfu_0fupi
  332. .Lcfu_0nowords: teq ip, #0
  333. beq .Lcfu_finished
  334. .Lcfu_nowords: cmp ip, #2
  335. USER( TUSER( ldrb) r3, [r1], #1) @ May fault
  336. strb r3, [r0], #1
  337. USER( TUSER( ldrgeb) r3, [r1], #1) @ May fault
  338. strgeb r3, [r0], #1
  339. USER( TUSER( ldrgtb) r3, [r1], #1) @ May fault
  340. strgtb r3, [r0], #1
  341. b .Lcfu_finished
  342. .Lcfu_not_enough:
  343. movs ip, r2
  344. bne .Lcfu_nowords
  345. .Lcfu_finished: mov r0, #0
  346. add sp, sp, #8
  347. ldmfd sp!, {r4 - r7, pc}
  348. .Lcfu_src_not_aligned:
  349. bic r1, r1, #3
  350. USER( TUSER( ldr) r7, [r1], #4) @ May fault
  351. cmp ip, #2
  352. bgt .Lcfu_3fupi
  353. beq .Lcfu_2fupi
  354. .Lcfu_1fupi: subs r2, r2, #4
  355. addmi ip, r2, #4
  356. bmi .Lcfu_1nowords
  357. mov r3, r7, pull #8
  358. USER( TUSER( ldr) r7, [r1], #4) @ May fault
  359. orr r3, r3, r7, push #24
  360. str r3, [r0], #4
  361. mov ip, r1, lsl #32 - PAGE_SHIFT
  362. rsb ip, ip, #0
  363. movs ip, ip, lsr #32 - PAGE_SHIFT
  364. beq .Lcfu_1fupi
  365. cmp r2, ip
  366. movlt ip, r2
  367. sub r2, r2, ip
  368. subs ip, ip, #16
  369. blt .Lcfu_1rem8lp
  370. .Lcfu_1cpy8lp: mov r3, r7, pull #8
  371. ldmia r1!, {r4 - r7} @ Shouldnt fault
  372. subs ip, ip, #16
  373. orr r3, r3, r4, push #24
  374. mov r4, r4, pull #8
  375. orr r4, r4, r5, push #24
  376. mov r5, r5, pull #8
  377. orr r5, r5, r6, push #24
  378. mov r6, r6, pull #8
  379. orr r6, r6, r7, push #24
  380. stmia r0!, {r3 - r6}
  381. bpl .Lcfu_1cpy8lp
  382. .Lcfu_1rem8lp: tst ip, #8
  383. movne r3, r7, pull #8
  384. ldmneia r1!, {r4, r7} @ Shouldnt fault
  385. orrne r3, r3, r4, push #24
  386. movne r4, r4, pull #8
  387. orrne r4, r4, r7, push #24
  388. stmneia r0!, {r3 - r4}
  389. tst ip, #4
  390. movne r3, r7, pull #8
  391. USER( TUSER( ldrne) r7, [r1], #4) @ May fault
  392. orrne r3, r3, r7, push #24
  393. strne r3, [r0], #4
  394. ands ip, ip, #3
  395. beq .Lcfu_1fupi
  396. .Lcfu_1nowords: mov r3, r7, get_byte_1
  397. teq ip, #0
  398. beq .Lcfu_finished
  399. cmp ip, #2
  400. strb r3, [r0], #1
  401. movge r3, r7, get_byte_2
  402. strgeb r3, [r0], #1
  403. movgt r3, r7, get_byte_3
  404. strgtb r3, [r0], #1
  405. b .Lcfu_finished
  406. .Lcfu_2fupi: subs r2, r2, #4
  407. addmi ip, r2, #4
  408. bmi .Lcfu_2nowords
  409. mov r3, r7, pull #16
  410. USER( TUSER( ldr) r7, [r1], #4) @ May fault
  411. orr r3, r3, r7, push #16
  412. str r3, [r0], #4
  413. mov ip, r1, lsl #32 - PAGE_SHIFT
  414. rsb ip, ip, #0
  415. movs ip, ip, lsr #32 - PAGE_SHIFT
  416. beq .Lcfu_2fupi
  417. cmp r2, ip
  418. movlt ip, r2
  419. sub r2, r2, ip
  420. subs ip, ip, #16
  421. blt .Lcfu_2rem8lp
  422. .Lcfu_2cpy8lp: mov r3, r7, pull #16
  423. ldmia r1!, {r4 - r7} @ Shouldnt fault
  424. subs ip, ip, #16
  425. orr r3, r3, r4, push #16
  426. mov r4, r4, pull #16
  427. orr r4, r4, r5, push #16
  428. mov r5, r5, pull #16
  429. orr r5, r5, r6, push #16
  430. mov r6, r6, pull #16
  431. orr r6, r6, r7, push #16
  432. stmia r0!, {r3 - r6}
  433. bpl .Lcfu_2cpy8lp
  434. .Lcfu_2rem8lp: tst ip, #8
  435. movne r3, r7, pull #16
  436. ldmneia r1!, {r4, r7} @ Shouldnt fault
  437. orrne r3, r3, r4, push #16
  438. movne r4, r4, pull #16
  439. orrne r4, r4, r7, push #16
  440. stmneia r0!, {r3 - r4}
  441. tst ip, #4
  442. movne r3, r7, pull #16
  443. USER( TUSER( ldrne) r7, [r1], #4) @ May fault
  444. orrne r3, r3, r7, push #16
  445. strne r3, [r0], #4
  446. ands ip, ip, #3
  447. beq .Lcfu_2fupi
  448. .Lcfu_2nowords: mov r3, r7, get_byte_2
  449. teq ip, #0
  450. beq .Lcfu_finished
  451. cmp ip, #2
  452. strb r3, [r0], #1
  453. movge r3, r7, get_byte_3
  454. strgeb r3, [r0], #1
  455. USER( TUSER( ldrgtb) r3, [r1], #0) @ May fault
  456. strgtb r3, [r0], #1
  457. b .Lcfu_finished
  458. .Lcfu_3fupi: subs r2, r2, #4
  459. addmi ip, r2, #4
  460. bmi .Lcfu_3nowords
  461. mov r3, r7, pull #24
  462. USER( TUSER( ldr) r7, [r1], #4) @ May fault
  463. orr r3, r3, r7, push #8
  464. str r3, [r0], #4
  465. mov ip, r1, lsl #32 - PAGE_SHIFT
  466. rsb ip, ip, #0
  467. movs ip, ip, lsr #32 - PAGE_SHIFT
  468. beq .Lcfu_3fupi
  469. cmp r2, ip
  470. movlt ip, r2
  471. sub r2, r2, ip
  472. subs ip, ip, #16
  473. blt .Lcfu_3rem8lp
  474. .Lcfu_3cpy8lp: mov r3, r7, pull #24
  475. ldmia r1!, {r4 - r7} @ Shouldnt fault
  476. orr r3, r3, r4, push #8
  477. mov r4, r4, pull #24
  478. orr r4, r4, r5, push #8
  479. mov r5, r5, pull #24
  480. orr r5, r5, r6, push #8
  481. mov r6, r6, pull #24
  482. orr r6, r6, r7, push #8
  483. stmia r0!, {r3 - r6}
  484. subs ip, ip, #16
  485. bpl .Lcfu_3cpy8lp
  486. .Lcfu_3rem8lp: tst ip, #8
  487. movne r3, r7, pull #24
  488. ldmneia r1!, {r4, r7} @ Shouldnt fault
  489. orrne r3, r3, r4, push #8
  490. movne r4, r4, pull #24
  491. orrne r4, r4, r7, push #8
  492. stmneia r0!, {r3 - r4}
  493. tst ip, #4
  494. movne r3, r7, pull #24
  495. USER( TUSER( ldrne) r7, [r1], #4) @ May fault
  496. orrne r3, r3, r7, push #8
  497. strne r3, [r0], #4
  498. ands ip, ip, #3
  499. beq .Lcfu_3fupi
  500. .Lcfu_3nowords: mov r3, r7, get_byte_3
  501. teq ip, #0
  502. beq .Lcfu_finished
  503. cmp ip, #2
  504. strb r3, [r0], #1
  505. USER( TUSER( ldrgeb) r3, [r1], #1) @ May fault
  506. strgeb r3, [r0], #1
  507. USER( TUSER( ldrgtb) r3, [r1], #1) @ May fault
  508. strgtb r3, [r0], #1
  509. b .Lcfu_finished
  510. ENDPROC(__copy_from_user)
  511. .pushsection .fixup,"ax"
  512. .align 0
  513. /*
  514. * We took an exception. r0 contains a pointer to
  515. * the byte not copied.
  516. */
  517. 9001: ldr r2, [sp], #4 @ void *to
  518. sub r2, r0, r2 @ bytes copied
  519. ldr r1, [sp], #4 @ unsigned long count
  520. subs r4, r1, r2 @ bytes left to copy
  521. movne r1, r4
  522. blne __memzero
  523. mov r0, r4
  524. ldmfd sp!, {r4 - r7, pc}
  525. .popsection