1
2
3
4
5
6
7
8
9
10
11
12
13
14
15#include <arch/chip.h>
16
17
18
19
20
21
22
23#include <linux/linkage.h>
24
25
26
27#define memcpy __memcpy_asm
28#define __copy_to_user_inatomic __copy_to_user_inatomic_asm
29#define __copy_from_user_inatomic __copy_from_user_inatomic_asm
30#define __copy_from_user_zeroing __copy_from_user_zeroing_asm
31#endif
32
33#define IS_MEMCPY 0
34#define IS_COPY_FROM_USER 1
35#define IS_COPY_FROM_USER_ZEROING 2
36#define IS_COPY_TO_USER -1
37
38 .section .text.memcpy_common, "ax"
39 .align 64
40
41
42
43
44
45#define EX \
46 .pushsection __ex_table, "a"; \
47 .word 9f, memcpy_common_fixup; \
48 .popsection; \
49 9
50
51
52
53
54
55
56ENTRY(__copy_from_user_inatomic)
57.type __copy_from_user_inatomic, @function
58 FEEDBACK_ENTER_EXPLICIT(__copy_from_user_inatomic, \
59 .text.memcpy_common, \
60 .Lend_memcpy_common - __copy_from_user_inatomic)
61 { movei r29, IS_COPY_FROM_USER; j memcpy_common }
62 .size __copy_from_user_inatomic, . - __copy_from_user_inatomic
63
64
65
66
67ENTRY(__copy_from_user_zeroing)
68.type __copy_from_user_zeroing, @function
69 FEEDBACK_REENTER(__copy_from_user_inatomic)
70 { movei r29, IS_COPY_FROM_USER_ZEROING; j memcpy_common }
71 .size __copy_from_user_zeroing, . - __copy_from_user_zeroing
72
73
74
75
76
77ENTRY(__copy_to_user_inatomic)
78.type __copy_to_user_inatomic, @function
79 FEEDBACK_REENTER(__copy_from_user_inatomic)
80 { movei r29, IS_COPY_TO_USER; j memcpy_common }
81 .size __copy_to_user_inatomic, . - __copy_to_user_inatomic
82
83ENTRY(memcpy)
84.type memcpy, @function
85 FEEDBACK_REENTER(__copy_from_user_inatomic)
86 { movei r29, IS_MEMCPY }
87 .size memcpy, . - memcpy
88
89
90 .type memcpy_common, @function
91memcpy_common:
92
93
94
95
96
97
98 { sw sp, lr; move r23, r0; or r4, r0, r1 }
99
100
101 { bz r2, .Ldone; andi r4, r4, 3 }
102
103
104 { move r24, r1; move r25, r2 }
105 move r27, lr
106
107
108 { bnz r4, .Lcopy_unaligned_maybe_many; addli r4, r2, -256 }
109
110.Lcheck_aligned_copy_size:
111
112 { blzt r4, .Lcopy_8_check; slti_u r8, r2, 8 }
113
114
115 { andi r6, r1, 63; j .Lcopy_many }
116
117
118
119
120
121
122
123.Lcopy_8_loop:
124
125EX: { lw r3, r1; addi r1, r1, 4; slti_u r8, r2, 16 }
126EX: { lw r4, r1; addi r1, r1, 4 }
127EX: { sw r0, r3; addi r0, r0, 4; addi r2, r2, -4 }
128EX: { sw r0, r4; addi r0, r0, 4; addi r2, r2, -4 }
129.Lcopy_8_check:
130 { bzt r8, .Lcopy_8_loop; slti_u r4, r2, 4 }
131
132
133 { bnzt r4, .Lcheck_odd_stragglers }
134EX: { lw r3, r1; addi r1, r1, 4 }
135EX: { sw r0, r3; addi r0, r0, 4; addi r2, r2, -4 }
136
137.Lcheck_odd_stragglers:
138 { bnz r2, .Lcopy_unaligned_few }
139
140.Ldone:
141
142 { mz r0, r29, r23; jrp lr }
143
144
145
146
147
148
149
150
151
152.Lalign_loop:
153EX: { lw r3, r1; addi r1, r1, 4 }
154 { andi r6, r1, 63 }
155EX: { sw r0, r3; addi r0, r0, 4; addi r2, r2, -4 }
156.Lcopy_many:
157 { bnzt r6, .Lalign_loop; addi r9, r0, 63 }
158
159 { addi r3, r1, 60; andi r9, r9, -64 }
160
161
162
163
164
165#endif
166
167EX: { lw r5, r3; addi r3, r3, 64; movei r4, 1 }
168
169 { bnzt zero, .; move r27, lr }
170EX: { lw r6, r3; addi r3, r3, 64 }
171
172 { bnzt zero, . }
173EX: { lw r7, r3; addi r3, r3, 64 }
174
175
176
177 { bnzt zero, . }
178
179
180
181EX: { lw r28, r9; addi r9, r9, 64 }
182
183 { bnzt zero, . }
184 { prefetch r9; addi r9, r9, 64 }
185
186 { bnzt zero, . }
187 { prefetch r9; addi r9, r9, 64 }
188#endif
189
190 { bz zero, .Lbig_loop2 }
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206.Lbig_loop:
207 { jal .Lcopy_line2; add r15, r1, r2 }
208
209.Lbig_loop2:
210
211EX: { move r12, r5; lw r16, r1 }
212 { bz r4, .Lcopy_8_check; slti_u r8, r2, 8 }
213
214EX: { lw r5, r3; addi r3, r3, 64 }
215 { jal .Lcopy_line }
216
217
218EX: { move r12, r6; lw r16, r1 }
219 { bz r4, .Lcopy_8_check; slti_u r8, r2, 8 }
220
221EX: { lw r6, r3; addi r3, r3, 64 }
222 { jal .Lcopy_line }
223
224
225EX: { move r12, r7; lw r16, r1 }
226 { bz r4, .Lcopy_8_check; slti_u r8, r2, 8 }
227
228EX: { lw r7, r3; addi r3, r3, 64 }
229
230
231
232 { j .Lbig_loop }
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267.Lcopy_line:
268
269
270
271
272
273
274
275
276
277
278
279
280 { add r15, r1, r2 }
281.Lcopy_line2:
282 { slt_u r13, r3, r15; addi r17, r1, 16 }
283
284
285
286
287EX: { lw r17, r17; addi r1, r1, 48; mvz r3, r13, r1 }
288
289
290
291EX: { wh64 r9; addi r9, r9, 64 }
292#else
293
294 { prefetch r9; addi r9, r9, 64 }
295#endif
296
297
298
299
300
301EX: { lw r4, r1; addi r1, r1, 4; addi r20, r1, 16 }
302EX: { lw r8, r1; addi r1, r1, 4; slt_u r13, r20, r15 }
303EX: { lw r11, r1; addi r1, r1, -52; mvz r20, r13, r1 }
304
305
306
307
308EX: { lw r13, r1; addi r1, r1, 4; move zero, r16 }
309EX: { lw r14, r1; addi r1, r1, 4 }
310EX: { lw r15, r1; addi r1, r1, 8; addi r10, r0, 60 }
311
312
313
314
315EX: { lw r19, r1; addi r1, r1, 4; move zero, r17 }
316
317
318
319
320EX: { sw r10, r12 }
321
322
323EX: { lw r10, r1; addi r1, r1, 4 }
324EX: { lw r12, r1; addi r1, r1, 4 }
325
326
327EX: { lw r18, r1; addi r1, r1, 4 }
328
329
330EX: { sw r0, r16; addi r0, r0, 4; add r16, r0, r2 }
331EX: { sw r0, r13; addi r0, r0, 4; andi r16, r16, -64 }
332EX: { sw r0, r14; addi r0, r0, 4; slt_u r16, r9, r16 }
333
334EX: { sw r0, r15; addi r0, r0, 4; addi r13, sp, -64 }
335#else
336
337
338
339
340
341EX: { sw r0, r15; addi r0, r0, 4; andi r13, r0, -64 }
342#endif
343
344EX: { sw r0, r17; addi r0, r0, 4; mvz r9, r16, r13 }
345EX: { sw r0, r19; addi r0, r0, 4 }
346EX: { sw r0, r10; addi r0, r0, 4 }
347EX: { sw r0, r12; addi r0, r0, 4 }
348
349EX: { lw r13, r1; addi r1, r1, 4; move zero, r18 }
350EX: { lw r14, r1; addi r1, r1, 4 }
351EX: { lw r15, r1; move r1, r20 }
352
353
354EX: { sw r0, r18; addi r0, r0, 4 }
355EX: { sw r0, r13; addi r0, r0, 4 }
356EX: { sw r0, r14; addi r0, r0, 4 }
357EX: { sw r0, r15; addi r0, r0, 4 }
358
359
360EX: { sw r0, r4; addi r0, r0, 4 }
361 {
362EX: sw r0, r8
363 addi r0, r0, 4
364
365 shri r4, r2, 7
366 }
367 {
368EX: sw r0, r11
369 addi r0, r0, 8
370
371 addi r2, r2, -64
372 }
373
374 { jrp lr; move lr, r27 }
375
376
377
378
379
380 { info 8 }
381
382 .align 64
383.Lcopy_unaligned_maybe_many:
384
385 { slti_u r8, r2, 20; sub r4, zero, r0 }
386 { bnzt r8, .Lcopy_unaligned_few; andi r4, r4, 3 }
387 { bz r4, .Ldest_is_word_aligned; add r18, r1, r2 }
388
389
390
391
392
393
394
395
396.Lalign_dest_loop:
397EX: { lb_u r3, r1; addi r1, r1, 1; addi r4, r4, -1 }
398EX: { sb r0, r3; addi r0, r0, 1; addi r2, r2, -1 }
399 { bnzt r4, .Lalign_dest_loop; andi r3, r1, 3 }
400
401
402 { bz r3, .Lcheck_aligned_copy_size; addli r4, r2, -256 }
403
404.Ldest_is_word_aligned:
405
406
407EX: { andi r8, r0, 63; lwadd_na r6, r1, 4}
408 { slti_u r9, r2, 64; bz r8, .Ldest_is_L2_line_aligned }
409
410
411
412
413
414
415
416
417
418
419
420.Lcopy_unaligned_src_words:
421EX: { lwadd_na r7, r1, 4; slti_u r8, r2, 4 + 4 }
422
423 { dword_align r6, r7, r1; slti_u r9, r2, 64 + 4 }
424EX: { swadd r0, r6, 4; addi r2, r2, -4 }
425 { bnz r8, .Lcleanup_unaligned_words; andi r8, r0, 63 }
426 { bnzt r8, .Lcopy_unaligned_src_words; move r6, r7 }
427
428
429
430
431
432
433
434
435
436.Ldest_is_L2_line_aligned:
437
438 {
439
440 bnz r9, .Lcleanup_unaligned_words
441 move r7, r6
442 }
443
444
445
446
447 { addi r3, r1, 63 - 4; addi r8, r1, 64 + 63 - 4 }
448 { prefetch r3; move r3, r8; slt_u r8, r8, r18 }
449 { mvz r3, r8, r1; addi r8, r3, 64 }
450 { prefetch r3; move r3, r8; slt_u r8, r8, r18 }
451 { mvz r3, r8, r1; movei r17, 0 }
452
453.Lcopy_unaligned_line:
454
455 { prefetch r3; addi r15, r1, 60; addi r3, r3, 64 }
456
457EX: { lw_na r15, r15; slt_u r8, r3, r18 }
458
459EX: { mvz r3, r8, r1; wh64 r0 }
460
461
462
463
464
465
466
467
468.Lcopy_half_an_unaligned_line:
469EX: {
470
471
472
473
474 move zero, r15
475 lwadd_na r7, r1, 16
476 }
477EX: { lwadd_na r11, r1, 12 }
478EX: { lwadd_na r14, r1, -24 }
479EX: { lwadd_na r8, r1, 4 }
480EX: { lwadd_na r9, r1, 4 }
481EX: {
482 lwadd_na r10, r1, 8
483
484 slti_u r16, r2, 64 + 32
485 }
486EX: { lwadd_na r12, r1, 4; addi r17, r17, 1 }
487EX: { lwadd_na r13, r1, 8; dword_align r6, r7, r1 }
488EX: { swadd r0, r6, 4; dword_align r7, r8, r1 }
489EX: { swadd r0, r7, 4; dword_align r8, r9, r1 }
490EX: { swadd r0, r8, 4; dword_align r9, r10, r1 }
491EX: { swadd r0, r9, 4; dword_align r10, r11, r1 }
492EX: { swadd r0, r10, 4; dword_align r11, r12, r1 }
493EX: { swadd r0, r11, 4; dword_align r12, r13, r1 }
494EX: { swadd r0, r12, 4; dword_align r13, r14, r1 }
495EX: { swadd r0, r13, 4; addi r2, r2, -32 }
496 { move r6, r14; bbst r17, .Lcopy_half_an_unaligned_line }
497
498 { bzt r16, .Lcopy_unaligned_line; move r7, r6 }
499
500
501
502
503
504
505
506.Lcleanup_unaligned_words:
507
508 { bz r2, .Lcopy_unaligned_done; slti_u r8, r2, 4 }
509 { bzt r8, .Lcopy_unaligned_src_words; move r6, r7 }
510
511
512 { addi r1, r1, -4 }
513
514#else
515
516
517 { andi r5, r1, -4; andi r3, r1, 3 }
518EX: { lw r6, r5; addi r5, r5, 4; shli r3, r3, 3 }
519EX: { lw r7, r5; addi r5, r5, 4; sub r4, zero, r3 }
520
521
522
523
524.Lcopy_unaligned_src_loop:
525 { shr r6, r6, r3; shl r8, r7, r4 }
526EX: { lw r7, r5; or r8, r8, r6; move r6, r7 }
527EX: { sw r0, r8; addi r0, r0, 4; addi r2, r2, -4 }
528 { addi r5, r5, 4; slti_u r8, r2, 8 }
529 { bzt r8, .Lcopy_unaligned_src_loop; addi r1, r1, 4 }
530
531 { bz r2, .Lcopy_unaligned_done }
532#endif
533
534
535
536
537
538
539
540
541
542.Lcopy_unaligned_few:
543EX: { lb_u r3, r1; addi r1, r1, 1 }
544EX: { sb r0, r3; addi r0, r0, 1; addi r2, r2, -1 }
545 { bnzt r2, .Lcopy_unaligned_few }
546
547.Lcopy_unaligned_done:
548
549
550 { mz r0, r29, r23; jrp lr }
551
552.Lend_memcpy_common:
553 .size memcpy_common, .Lend_memcpy_common - memcpy_common
554
555 .section .fixup,"ax"
556memcpy_common_fixup:
557 .type memcpy_common_fixup, @function
558
559
560
561
562
563
564
565
566
567
568 { sub r3, r25, r2 }
569
570
571 { add r0, r23, r3; add r1, r24, r3 }
572
573 { bzt r29, memcpy_fixup_loop }
574 { blzt r29, copy_to_user_fixup_loop }
575
576copy_from_user_fixup_loop:
577
578.Lcfu: { lb_u r3, r1; addi r1, r1, 1 }
579 { sb r0, r3; addi r0, r0, 1; addi r2, r2, -1 }
580 { bnzt r2, copy_from_user_fixup_loop }
581
582.Lcopy_from_user_fixup_zero_remainder:
583 { bbs r29, 2f }
584
585 { move r3, r2; bz r2, 2f }
5861: { sb r0, zero; addi r0, r0, 1; addi r3, r3, -1 }
587 { bnzt r3, 1b }
5882: move lr, r27
589 { move r0, r2; jrp lr }
590
591copy_to_user_fixup_loop:
592
593 { lb_u r3, r1; addi r1, r1, 1 }
594.Lctu: { sb r0, r3; addi r0, r0, 1; addi r2, r2, -1 }
595 { bnzt r2, copy_to_user_fixup_loop }
596.Lcopy_to_user_fixup_done:
597 move lr, r27
598 { move r0, r2; jrp lr }
599
600memcpy_fixup_loop:
601
602
603
604 { lb_u r3, r1; addi r1, r1, 1 }
605 { sb r0, r3; addi r0, r0, 1; addi r2, r2, -1 }
606 { bnzt r2, memcpy_fixup_loop }
607
608
609
610
611 move lr, r27
612 { move r0, r23; jrp lr }
613
614 .size memcpy_common_fixup, . - memcpy_common_fixup
615
616 .section __ex_table,"a"
617 .word .Lcfu, .Lcopy_from_user_fixup_zero_remainder
618 .word .Lctu, .Lcopy_to_user_fixup_done
619