memcpy.S 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699
  1. /*
  2. * This file is subject to the terms and conditions of the GNU General Public
  3. * License. See the file "COPYING" in the main directory of this archive
  4. * for more details.
  5. *
  6. * Unified implementation of memcpy, memmove and the __copy_user backend.
  7. *
  8. * Copyright (C) 1998, 99, 2000, 01, 2002 Ralf Baechle (ralf@gnu.org)
  9. * Copyright (C) 1999, 2000, 01, 2002 Silicon Graphics, Inc.
  10. * Copyright (C) 2002 Broadcom, Inc.
  11. * memcpy/copy_user author: Mark Vandevoorde
  12. * Copyright (C) 2007 Maciej W. Rozycki
  13. * Copyright (C) 2014 Imagination Technologies Ltd.
  14. *
  15. * Mnemonic names for arguments to memcpy/__copy_user
  16. */
  17. /*
  18. * Hack to resolve longstanding prefetch issue
  19. *
  20. * Prefetching may be fatal on some systems if we're prefetching beyond the
  21. * end of memory on some systems. It's also a seriously bad idea on non
  22. * dma-coherent systems.
  23. */
  24. #ifdef CONFIG_DMA_NONCOHERENT
  25. #undef CONFIG_CPU_HAS_PREFETCH
  26. #endif
  27. #ifdef CONFIG_MIPS_MALTA
  28. #undef CONFIG_CPU_HAS_PREFETCH
  29. #endif
  30. #include <asm/asm.h>
  31. #include <asm/asm-offsets.h>
  32. #include <asm/export.h>
  33. #include <asm/regdef.h>
  34. #define dst a0
  35. #define src a1
  36. #define len a2
  37. /*
  38. * Spec
  39. *
  40. * memcpy copies len bytes from src to dst and sets v0 to dst.
  41. * It assumes that
  42. * - src and dst don't overlap
  43. * - src is readable
  44. * - dst is writable
  45. * memcpy uses the standard calling convention
  46. *
  47. * __copy_user copies up to len bytes from src to dst and sets a2 (len) to
  48. * the number of uncopied bytes due to an exception caused by a read or write.
  49. * __copy_user assumes that src and dst don't overlap, and that the call is
  50. * implementing one of the following:
  51. * copy_to_user
  52. * - src is readable (no exceptions when reading src)
  53. * copy_from_user
  54. * - dst is writable (no exceptions when writing dst)
  55. * __copy_user uses a non-standard calling convention; see
  56. * include/asm-mips/uaccess.h
  57. *
  58. * When an exception happens on a load, the handler must
  59. # ensure that all of the destination buffer is overwritten to prevent
  60. * leaking information to user mode programs.
  61. */
  62. /*
  63. * Implementation
  64. */
  65. /*
  66. * The exception handler for loads requires that:
  67. * 1- AT contain the address of the byte just past the end of the source
  68. * of the copy,
  69. * 2- src_entry <= src < AT, and
  70. * 3- (dst - src) == (dst_entry - src_entry),
  71. * The _entry suffix denotes values when __copy_user was called.
  72. *
  73. * (1) is set up up by uaccess.h and maintained by not writing AT in copy_user
  74. * (2) is met by incrementing src by the number of bytes copied
  75. * (3) is met by not doing loads between a pair of increments of dst and src
  76. *
  77. * The exception handlers for stores adjust len (if necessary) and return.
  78. * These handlers do not need to overwrite any data.
  79. *
  80. * For __rmemcpy and memmove an exception is always a kernel bug, therefore
  81. * they're not protected.
  82. */
  83. /* Instruction type */
  84. #define LD_INSN 1
  85. #define ST_INSN 2
  86. /* Pretech type */
  87. #define SRC_PREFETCH 1
  88. #define DST_PREFETCH 2
  89. #define LEGACY_MODE 1
  90. #define EVA_MODE 2
  91. #define USEROP 1
  92. #define KERNELOP 2
  93. /*
  94. * Wrapper to add an entry in the exception table
  95. * in case the insn causes a memory exception.
  96. * Arguments:
  97. * insn : Load/store instruction
  98. * type : Instruction type
  99. * reg : Register
  100. * addr : Address
  101. * handler : Exception handler
  102. */
  103. #define EXC(insn, type, reg, addr, handler) \
  104. .if \mode == LEGACY_MODE; \
  105. 9: insn reg, addr; \
  106. .section __ex_table,"a"; \
  107. PTR 9b, handler; \
  108. .previous; \
  109. /* This is assembled in EVA mode */ \
  110. .else; \
  111. /* If loading from user or storing to user */ \
  112. .if ((\from == USEROP) && (type == LD_INSN)) || \
  113. ((\to == USEROP) && (type == ST_INSN)); \
  114. 9: __BUILD_EVA_INSN(insn##e, reg, addr); \
  115. .section __ex_table,"a"; \
  116. PTR 9b, handler; \
  117. .previous; \
  118. .else; \
  119. /* \
  120. * Still in EVA, but no need for \
  121. * exception handler or EVA insn \
  122. */ \
  123. insn reg, addr; \
  124. .endif; \
  125. .endif
  126. /*
  127. * Only on the 64-bit kernel we can made use of 64-bit registers.
  128. */
  129. #ifdef CONFIG_64BIT
  130. #define USE_DOUBLE
  131. #endif
  132. #ifdef USE_DOUBLE
  133. #define LOADK ld /* No exception */
  134. #define LOAD(reg, addr, handler) EXC(ld, LD_INSN, reg, addr, handler)
  135. #define LOADL(reg, addr, handler) EXC(ldl, LD_INSN, reg, addr, handler)
  136. #define LOADR(reg, addr, handler) EXC(ldr, LD_INSN, reg, addr, handler)
  137. #define STOREL(reg, addr, handler) EXC(sdl, ST_INSN, reg, addr, handler)
  138. #define STORER(reg, addr, handler) EXC(sdr, ST_INSN, reg, addr, handler)
  139. #define STORE(reg, addr, handler) EXC(sd, ST_INSN, reg, addr, handler)
  140. #define ADD daddu
  141. #define SUB dsubu
  142. #define SRL dsrl
  143. #define SRA dsra
  144. #define SLL dsll
  145. #define SLLV dsllv
  146. #define SRLV dsrlv
  147. #define NBYTES 8
  148. #define LOG_NBYTES 3
  149. /*
  150. * As we are sharing code base with the mips32 tree (which use the o32 ABI
  151. * register definitions). We need to redefine the register definitions from
  152. * the n64 ABI register naming to the o32 ABI register naming.
  153. */
  154. #undef t0
  155. #undef t1
  156. #undef t2
  157. #undef t3
  158. #define t0 $8
  159. #define t1 $9
  160. #define t2 $10
  161. #define t3 $11
  162. #define t4 $12
  163. #define t5 $13
  164. #define t6 $14
  165. #define t7 $15
  166. #else
  167. #define LOADK lw /* No exception */
  168. #define LOAD(reg, addr, handler) EXC(lw, LD_INSN, reg, addr, handler)
  169. #define LOADL(reg, addr, handler) EXC(lwl, LD_INSN, reg, addr, handler)
  170. #define LOADR(reg, addr, handler) EXC(lwr, LD_INSN, reg, addr, handler)
  171. #define STOREL(reg, addr, handler) EXC(swl, ST_INSN, reg, addr, handler)
  172. #define STORER(reg, addr, handler) EXC(swr, ST_INSN, reg, addr, handler)
  173. #define STORE(reg, addr, handler) EXC(sw, ST_INSN, reg, addr, handler)
  174. #define ADD addu
  175. #define SUB subu
  176. #define SRL srl
  177. #define SLL sll
  178. #define SRA sra
  179. #define SLLV sllv
  180. #define SRLV srlv
  181. #define NBYTES 4
  182. #define LOG_NBYTES 2
  183. #endif /* USE_DOUBLE */
  184. #define LOADB(reg, addr, handler) EXC(lb, LD_INSN, reg, addr, handler)
  185. #define STOREB(reg, addr, handler) EXC(sb, ST_INSN, reg, addr, handler)
  186. #define _PREF(hint, addr, type) \
  187. .if \mode == LEGACY_MODE; \
  188. PREF(hint, addr); \
  189. .else; \
  190. .if ((\from == USEROP) && (type == SRC_PREFETCH)) || \
  191. ((\to == USEROP) && (type == DST_PREFETCH)); \
  192. /* \
  193. * PREFE has only 9 bits for the offset \
  194. * compared to PREF which has 16, so it may \
  195. * need to use the $at register but this \
  196. * register should remain intact because it's \
  197. * used later on. Therefore use $v1. \
  198. */ \
  199. .set at=v1; \
  200. PREFE(hint, addr); \
  201. .set noat; \
  202. .else; \
  203. PREF(hint, addr); \
  204. .endif; \
  205. .endif
  206. #define PREFS(hint, addr) _PREF(hint, addr, SRC_PREFETCH)
  207. #define PREFD(hint, addr) _PREF(hint, addr, DST_PREFETCH)
  208. #ifdef CONFIG_CPU_LITTLE_ENDIAN
  209. #define LDFIRST LOADR
  210. #define LDREST LOADL
  211. #define STFIRST STORER
  212. #define STREST STOREL
  213. #define SHIFT_DISCARD SLLV
  214. #else
  215. #define LDFIRST LOADL
  216. #define LDREST LOADR
  217. #define STFIRST STOREL
  218. #define STREST STORER
  219. #define SHIFT_DISCARD SRLV
  220. #endif
  221. #define FIRST(unit) ((unit)*NBYTES)
  222. #define REST(unit) (FIRST(unit)+NBYTES-1)
  223. #define UNIT(unit) FIRST(unit)
  224. #define ADDRMASK (NBYTES-1)
  225. .text
  226. .set noreorder
  227. #ifndef CONFIG_CPU_DADDI_WORKAROUNDS
  228. .set noat
  229. #else
  230. .set at=v1
  231. #endif
  232. .align 5
  233. /*
  234. * Macro to build the __copy_user common code
  235. * Arguments:
  236. * mode : LEGACY_MODE or EVA_MODE
  237. * from : Source operand. USEROP or KERNELOP
  238. * to : Destination operand. USEROP or KERNELOP
  239. */
  240. .macro __BUILD_COPY_USER mode, from, to
  241. /* initialize __memcpy if this the first time we execute this macro */
  242. .ifnotdef __memcpy
  243. .set __memcpy, 1
  244. .hidden __memcpy /* make sure it does not leak */
  245. .endif
  246. /*
  247. * Note: dst & src may be unaligned, len may be 0
  248. * Temps
  249. */
  250. #define rem t8
  251. R10KCBARRIER(0(ra))
  252. /*
  253. * The "issue break"s below are very approximate.
  254. * Issue delays for dcache fills will perturb the schedule, as will
  255. * load queue full replay traps, etc.
  256. *
  257. * If len < NBYTES use byte operations.
  258. */
  259. PREFS( 0, 0(src) )
  260. PREFD( 1, 0(dst) )
  261. sltu t2, len, NBYTES
  262. and t1, dst, ADDRMASK
  263. PREFS( 0, 1*32(src) )
  264. PREFD( 1, 1*32(dst) )
  265. bnez t2, .Lcopy_bytes_checklen\@
  266. and t0, src, ADDRMASK
  267. PREFS( 0, 2*32(src) )
  268. PREFD( 1, 2*32(dst) )
  269. #ifndef CONFIG_CPU_MIPSR6
  270. bnez t1, .Ldst_unaligned\@
  271. nop
  272. bnez t0, .Lsrc_unaligned_dst_aligned\@
  273. #else
  274. or t0, t0, t1
  275. bnez t0, .Lcopy_unaligned_bytes\@
  276. #endif
  277. /*
  278. * use delay slot for fall-through
  279. * src and dst are aligned; need to compute rem
  280. */
  281. .Lboth_aligned\@:
  282. SRL t0, len, LOG_NBYTES+3 # +3 for 8 units/iter
  283. beqz t0, .Lcleanup_both_aligned\@ # len < 8*NBYTES
  284. and rem, len, (8*NBYTES-1) # rem = len % (8*NBYTES)
  285. PREFS( 0, 3*32(src) )
  286. PREFD( 1, 3*32(dst) )
  287. .align 4
  288. 1:
  289. R10KCBARRIER(0(ra))
  290. LOAD(t0, UNIT(0)(src), .Ll_exc\@)
  291. LOAD(t1, UNIT(1)(src), .Ll_exc_copy\@)
  292. LOAD(t2, UNIT(2)(src), .Ll_exc_copy\@)
  293. LOAD(t3, UNIT(3)(src), .Ll_exc_copy\@)
  294. SUB len, len, 8*NBYTES
  295. LOAD(t4, UNIT(4)(src), .Ll_exc_copy\@)
  296. LOAD(t7, UNIT(5)(src), .Ll_exc_copy\@)
  297. STORE(t0, UNIT(0)(dst), .Ls_exc_p8u\@)
  298. STORE(t1, UNIT(1)(dst), .Ls_exc_p7u\@)
  299. LOAD(t0, UNIT(6)(src), .Ll_exc_copy\@)
  300. LOAD(t1, UNIT(7)(src), .Ll_exc_copy\@)
  301. ADD src, src, 8*NBYTES
  302. ADD dst, dst, 8*NBYTES
  303. STORE(t2, UNIT(-6)(dst), .Ls_exc_p6u\@)
  304. STORE(t3, UNIT(-5)(dst), .Ls_exc_p5u\@)
  305. STORE(t4, UNIT(-4)(dst), .Ls_exc_p4u\@)
  306. STORE(t7, UNIT(-3)(dst), .Ls_exc_p3u\@)
  307. STORE(t0, UNIT(-2)(dst), .Ls_exc_p2u\@)
  308. STORE(t1, UNIT(-1)(dst), .Ls_exc_p1u\@)
  309. PREFS( 0, 8*32(src) )
  310. PREFD( 1, 8*32(dst) )
  311. bne len, rem, 1b
  312. nop
  313. /*
  314. * len == rem == the number of bytes left to copy < 8*NBYTES
  315. */
  316. .Lcleanup_both_aligned\@:
  317. beqz len, .Ldone\@
  318. sltu t0, len, 4*NBYTES
  319. bnez t0, .Lless_than_4units\@
  320. and rem, len, (NBYTES-1) # rem = len % NBYTES
  321. /*
  322. * len >= 4*NBYTES
  323. */
  324. LOAD( t0, UNIT(0)(src), .Ll_exc\@)
  325. LOAD( t1, UNIT(1)(src), .Ll_exc_copy\@)
  326. LOAD( t2, UNIT(2)(src), .Ll_exc_copy\@)
  327. LOAD( t3, UNIT(3)(src), .Ll_exc_copy\@)
  328. SUB len, len, 4*NBYTES
  329. ADD src, src, 4*NBYTES
  330. R10KCBARRIER(0(ra))
  331. STORE(t0, UNIT(0)(dst), .Ls_exc_p4u\@)
  332. STORE(t1, UNIT(1)(dst), .Ls_exc_p3u\@)
  333. STORE(t2, UNIT(2)(dst), .Ls_exc_p2u\@)
  334. STORE(t3, UNIT(3)(dst), .Ls_exc_p1u\@)
  335. .set reorder /* DADDI_WAR */
  336. ADD dst, dst, 4*NBYTES
  337. beqz len, .Ldone\@
  338. .set noreorder
  339. .Lless_than_4units\@:
  340. /*
  341. * rem = len % NBYTES
  342. */
  343. beq rem, len, .Lcopy_bytes\@
  344. nop
  345. 1:
  346. R10KCBARRIER(0(ra))
  347. LOAD(t0, 0(src), .Ll_exc\@)
  348. ADD src, src, NBYTES
  349. SUB len, len, NBYTES
  350. STORE(t0, 0(dst), .Ls_exc_p1u\@)
  351. .set reorder /* DADDI_WAR */
  352. ADD dst, dst, NBYTES
  353. bne rem, len, 1b
  354. .set noreorder
  355. #ifndef CONFIG_CPU_MIPSR6
  356. /*
  357. * src and dst are aligned, need to copy rem bytes (rem < NBYTES)
  358. * A loop would do only a byte at a time with possible branch
  359. * mispredicts. Can't do an explicit LOAD dst,mask,or,STORE
  360. * because can't assume read-access to dst. Instead, use
  361. * STREST dst, which doesn't require read access to dst.
  362. *
  363. * This code should perform better than a simple loop on modern,
  364. * wide-issue mips processors because the code has fewer branches and
  365. * more instruction-level parallelism.
  366. */
  367. #define bits t2
  368. beqz len, .Ldone\@
  369. ADD t1, dst, len # t1 is just past last byte of dst
  370. li bits, 8*NBYTES
  371. SLL rem, len, 3 # rem = number of bits to keep
  372. LOAD(t0, 0(src), .Ll_exc\@)
  373. SUB bits, bits, rem # bits = number of bits to discard
  374. SHIFT_DISCARD t0, t0, bits
  375. STREST(t0, -1(t1), .Ls_exc\@)
  376. jr ra
  377. move len, zero
  378. .Ldst_unaligned\@:
  379. /*
  380. * dst is unaligned
  381. * t0 = src & ADDRMASK
  382. * t1 = dst & ADDRMASK; T1 > 0
  383. * len >= NBYTES
  384. *
  385. * Copy enough bytes to align dst
  386. * Set match = (src and dst have same alignment)
  387. */
  388. #define match rem
  389. LDFIRST(t3, FIRST(0)(src), .Ll_exc\@)
  390. ADD t2, zero, NBYTES
  391. LDREST(t3, REST(0)(src), .Ll_exc_copy\@)
  392. SUB t2, t2, t1 # t2 = number of bytes copied
  393. xor match, t0, t1
  394. R10KCBARRIER(0(ra))
  395. STFIRST(t3, FIRST(0)(dst), .Ls_exc\@)
  396. beq len, t2, .Ldone\@
  397. SUB len, len, t2
  398. ADD dst, dst, t2
  399. beqz match, .Lboth_aligned\@
  400. ADD src, src, t2
  401. .Lsrc_unaligned_dst_aligned\@:
  402. SRL t0, len, LOG_NBYTES+2 # +2 for 4 units/iter
  403. PREFS( 0, 3*32(src) )
  404. beqz t0, .Lcleanup_src_unaligned\@
  405. and rem, len, (4*NBYTES-1) # rem = len % 4*NBYTES
  406. PREFD( 1, 3*32(dst) )
  407. 1:
  408. /*
  409. * Avoid consecutive LD*'s to the same register since some mips
  410. * implementations can't issue them in the same cycle.
  411. * It's OK to load FIRST(N+1) before REST(N) because the two addresses
  412. * are to the same unit (unless src is aligned, but it's not).
  413. */
  414. R10KCBARRIER(0(ra))
  415. LDFIRST(t0, FIRST(0)(src), .Ll_exc\@)
  416. LDFIRST(t1, FIRST(1)(src), .Ll_exc_copy\@)
  417. SUB len, len, 4*NBYTES
  418. LDREST(t0, REST(0)(src), .Ll_exc_copy\@)
  419. LDREST(t1, REST(1)(src), .Ll_exc_copy\@)
  420. LDFIRST(t2, FIRST(2)(src), .Ll_exc_copy\@)
  421. LDFIRST(t3, FIRST(3)(src), .Ll_exc_copy\@)
  422. LDREST(t2, REST(2)(src), .Ll_exc_copy\@)
  423. LDREST(t3, REST(3)(src), .Ll_exc_copy\@)
  424. PREFS( 0, 9*32(src) ) # 0 is PREF_LOAD (not streamed)
  425. ADD src, src, 4*NBYTES
  426. #ifdef CONFIG_CPU_SB1
  427. nop # improves slotting
  428. #endif
  429. STORE(t0, UNIT(0)(dst), .Ls_exc_p4u\@)
  430. STORE(t1, UNIT(1)(dst), .Ls_exc_p3u\@)
  431. STORE(t2, UNIT(2)(dst), .Ls_exc_p2u\@)
  432. STORE(t3, UNIT(3)(dst), .Ls_exc_p1u\@)
  433. PREFD( 1, 9*32(dst) ) # 1 is PREF_STORE (not streamed)
  434. .set reorder /* DADDI_WAR */
  435. ADD dst, dst, 4*NBYTES
  436. bne len, rem, 1b
  437. .set noreorder
  438. .Lcleanup_src_unaligned\@:
  439. beqz len, .Ldone\@
  440. and rem, len, NBYTES-1 # rem = len % NBYTES
  441. beq rem, len, .Lcopy_bytes\@
  442. nop
  443. 1:
  444. R10KCBARRIER(0(ra))
  445. LDFIRST(t0, FIRST(0)(src), .Ll_exc\@)
  446. LDREST(t0, REST(0)(src), .Ll_exc_copy\@)
  447. ADD src, src, NBYTES
  448. SUB len, len, NBYTES
  449. STORE(t0, 0(dst), .Ls_exc_p1u\@)
  450. .set reorder /* DADDI_WAR */
  451. ADD dst, dst, NBYTES
  452. bne len, rem, 1b
  453. .set noreorder
  454. #endif /* !CONFIG_CPU_MIPSR6 */
  455. .Lcopy_bytes_checklen\@:
  456. beqz len, .Ldone\@
  457. nop
  458. .Lcopy_bytes\@:
  459. /* 0 < len < NBYTES */
  460. R10KCBARRIER(0(ra))
  461. #define COPY_BYTE(N) \
  462. LOADB(t0, N(src), .Ll_exc\@); \
  463. SUB len, len, 1; \
  464. beqz len, .Ldone\@; \
  465. STOREB(t0, N(dst), .Ls_exc_p1\@)
  466. COPY_BYTE(0)
  467. COPY_BYTE(1)
  468. #ifdef USE_DOUBLE
  469. COPY_BYTE(2)
  470. COPY_BYTE(3)
  471. COPY_BYTE(4)
  472. COPY_BYTE(5)
  473. #endif
  474. LOADB(t0, NBYTES-2(src), .Ll_exc\@)
  475. SUB len, len, 1
  476. jr ra
  477. STOREB(t0, NBYTES-2(dst), .Ls_exc_p1\@)
  478. .Ldone\@:
  479. jr ra
  480. nop
  481. #ifdef CONFIG_CPU_MIPSR6
  482. .Lcopy_unaligned_bytes\@:
  483. 1:
  484. COPY_BYTE(0)
  485. COPY_BYTE(1)
  486. COPY_BYTE(2)
  487. COPY_BYTE(3)
  488. COPY_BYTE(4)
  489. COPY_BYTE(5)
  490. COPY_BYTE(6)
  491. COPY_BYTE(7)
  492. ADD src, src, 8
  493. b 1b
  494. ADD dst, dst, 8
  495. #endif /* CONFIG_CPU_MIPSR6 */
  496. .if __memcpy == 1
  497. END(memcpy)
  498. .set __memcpy, 0
  499. .hidden __memcpy
  500. .endif
  501. .Ll_exc_copy\@:
  502. /*
  503. * Copy bytes from src until faulting load address (or until a
  504. * lb faults)
  505. *
  506. * When reached by a faulting LDFIRST/LDREST, THREAD_BUADDR($28)
  507. * may be more than a byte beyond the last address.
  508. * Hence, the lb below may get an exception.
  509. *
  510. * Assumes src < THREAD_BUADDR($28)
  511. */
  512. LOADK t0, TI_TASK($28)
  513. nop
  514. LOADK t0, THREAD_BUADDR(t0)
  515. 1:
  516. LOADB(t1, 0(src), .Ll_exc\@)
  517. ADD src, src, 1
  518. sb t1, 0(dst) # can't fault -- we're copy_from_user
  519. .set reorder /* DADDI_WAR */
  520. ADD dst, dst, 1
  521. bne src, t0, 1b
  522. .set noreorder
  523. .Ll_exc\@:
  524. LOADK t0, TI_TASK($28)
  525. nop
  526. LOADK t0, THREAD_BUADDR(t0) # t0 is just past last good address
  527. nop
  528. SUB len, AT, t0 # len number of uncopied bytes
  529. jr ra
  530. nop
  531. #define SEXC(n) \
  532. .set reorder; /* DADDI_WAR */ \
  533. .Ls_exc_p ## n ## u\@: \
  534. ADD len, len, n*NBYTES; \
  535. jr ra; \
  536. .set noreorder
  537. SEXC(8)
  538. SEXC(7)
  539. SEXC(6)
  540. SEXC(5)
  541. SEXC(4)
  542. SEXC(3)
  543. SEXC(2)
  544. SEXC(1)
  545. .Ls_exc_p1\@:
  546. .set reorder /* DADDI_WAR */
  547. ADD len, len, 1
  548. jr ra
  549. .set noreorder
  550. .Ls_exc\@:
  551. jr ra
  552. nop
  553. .endm
  554. .align 5
  555. LEAF(memmove)
  556. EXPORT_SYMBOL(memmove)
  557. ADD t0, a0, a2
  558. ADD t1, a1, a2
  559. sltu t0, a1, t0 # dst + len <= src -> memcpy
  560. sltu t1, a0, t1 # dst >= src + len -> memcpy
  561. and t0, t1
  562. beqz t0, .L__memcpy
  563. move v0, a0 /* return value */
  564. beqz a2, .Lr_out
  565. END(memmove)
  566. /* fall through to __rmemcpy */
  567. LEAF(__rmemcpy) /* a0=dst a1=src a2=len */
  568. sltu t0, a1, a0
  569. beqz t0, .Lr_end_bytes_up # src >= dst
  570. nop
  571. ADD a0, a2 # dst = dst + len
  572. ADD a1, a2 # src = src + len
  573. .Lr_end_bytes:
  574. R10KCBARRIER(0(ra))
  575. lb t0, -1(a1)
  576. SUB a2, a2, 0x1
  577. sb t0, -1(a0)
  578. SUB a1, a1, 0x1
  579. .set reorder /* DADDI_WAR */
  580. SUB a0, a0, 0x1
  581. bnez a2, .Lr_end_bytes
  582. .set noreorder
  583. .Lr_out:
  584. jr ra
  585. move a2, zero
  586. .Lr_end_bytes_up:
  587. R10KCBARRIER(0(ra))
  588. lb t0, (a1)
  589. SUB a2, a2, 0x1
  590. sb t0, (a0)
  591. ADD a1, a1, 0x1
  592. .set reorder /* DADDI_WAR */
  593. ADD a0, a0, 0x1
  594. bnez a2, .Lr_end_bytes_up
  595. .set noreorder
  596. jr ra
  597. move a2, zero
  598. END(__rmemcpy)
  599. /*
  600. * A combined memcpy/__copy_user
  601. * __copy_user sets len to 0 for success; else to an upper bound of
  602. * the number of uncopied bytes.
  603. * memcpy sets v0 to dst.
  604. */
  605. .align 5
  606. LEAF(memcpy) /* a0=dst a1=src a2=len */
  607. EXPORT_SYMBOL(memcpy)
  608. move v0, dst /* return value */
  609. .L__memcpy:
  610. FEXPORT(__copy_user)
  611. EXPORT_SYMBOL(__copy_user)
  612. /* Legacy Mode, user <-> user */
  613. __BUILD_COPY_USER LEGACY_MODE USEROP USEROP
  614. #ifdef CONFIG_EVA
  615. /*
  616. * For EVA we need distinct symbols for reading and writing to user space.
  617. * This is because we need to use specific EVA instructions to perform the
  618. * virtual <-> physical translation when a virtual address is actually in user
  619. * space
  620. */
  621. /*
  622. * __copy_from_user (EVA)
  623. */
  624. LEAF(__copy_from_user_eva)
  625. EXPORT_SYMBOL(__copy_from_user_eva)
  626. __BUILD_COPY_USER EVA_MODE USEROP KERNELOP
  627. END(__copy_from_user_eva)
  628. /*
  629. * __copy_to_user (EVA)
  630. */
  631. LEAF(__copy_to_user_eva)
  632. EXPORT_SYMBOL(__copy_to_user_eva)
  633. __BUILD_COPY_USER EVA_MODE KERNELOP USEROP
  634. END(__copy_to_user_eva)
  635. /*
  636. * __copy_in_user (EVA)
  637. */
  638. LEAF(__copy_in_user_eva)
  639. EXPORT_SYMBOL(__copy_in_user_eva)
  640. __BUILD_COPY_USER EVA_MODE USEROP USEROP
  641. END(__copy_in_user_eva)
  642. #endif