1185f3d38SThomas Gleixner/* Written 2003 by Andi Kleen, based on a kernel by Evandro Menezes */ 2185f3d38SThomas Gleixner 3185f3d38SThomas Gleixner#include <linux/linkage.h> 4185f3d38SThomas Gleixner#include <asm/dwarf2.h> 559e97e4dSAndy Lutomirski#include <asm/alternative-asm.h> 6185f3d38SThomas Gleixner 7185f3d38SThomas Gleixner ALIGN 8185f3d38SThomas Gleixnercopy_page_c: 9185f3d38SThomas Gleixner CFI_STARTPROC 10185f3d38SThomas Gleixner movl $4096/8,%ecx 11185f3d38SThomas Gleixner rep movsq 12185f3d38SThomas Gleixner ret 13185f3d38SThomas Gleixner CFI_ENDPROC 14185f3d38SThomas GleixnerENDPROC(copy_page_c) 15185f3d38SThomas Gleixner 16185f3d38SThomas Gleixner/* Don't use streaming store because it's better when the target 17185f3d38SThomas Gleixner ends up in cache. */ 18185f3d38SThomas Gleixner 19185f3d38SThomas Gleixner/* Could vary the prefetch distance based on SMP/UP */ 20185f3d38SThomas Gleixner 21185f3d38SThomas GleixnerENTRY(copy_page) 22185f3d38SThomas Gleixner CFI_STARTPROC 23185f3d38SThomas Gleixner subq $3*8,%rsp 24185f3d38SThomas Gleixner CFI_ADJUST_CFA_OFFSET 3*8 25185f3d38SThomas Gleixner movq %rbx,(%rsp) 26185f3d38SThomas Gleixner CFI_REL_OFFSET rbx, 0 27185f3d38SThomas Gleixner movq %r12,1*8(%rsp) 28185f3d38SThomas Gleixner CFI_REL_OFFSET r12, 1*8 29185f3d38SThomas Gleixner movq %r13,2*8(%rsp) 30185f3d38SThomas Gleixner CFI_REL_OFFSET r13, 2*8 31185f3d38SThomas Gleixner 32185f3d38SThomas Gleixner movl $(4096/64)-5,%ecx 33185f3d38SThomas Gleixner .p2align 4 34185f3d38SThomas Gleixner.Loop64: 35185f3d38SThomas Gleixner dec %rcx 36185f3d38SThomas Gleixner 37185f3d38SThomas Gleixner movq (%rsi), %rax 38185f3d38SThomas Gleixner movq 8 (%rsi), %rbx 39185f3d38SThomas Gleixner movq 16 (%rsi), %rdx 40185f3d38SThomas Gleixner movq 24 (%rsi), %r8 41185f3d38SThomas Gleixner movq 32 (%rsi), %r9 42185f3d38SThomas Gleixner movq 40 (%rsi), %r10 43185f3d38SThomas Gleixner movq 48 (%rsi), %r11 44185f3d38SThomas Gleixner movq 56 (%rsi), %r12 45185f3d38SThomas Gleixner 46185f3d38SThomas Gleixner prefetcht0 5*64(%rsi) 47185f3d38SThomas Gleixner 48185f3d38SThomas Gleixner movq %rax, (%rdi) 49185f3d38SThomas Gleixner movq %rbx, 8 (%rdi) 50185f3d38SThomas Gleixner movq %rdx, 16 (%rdi) 51185f3d38SThomas Gleixner movq %r8, 24 (%rdi) 52185f3d38SThomas Gleixner movq %r9, 32 (%rdi) 53185f3d38SThomas Gleixner movq %r10, 40 (%rdi) 54185f3d38SThomas Gleixner movq %r11, 48 (%rdi) 55185f3d38SThomas Gleixner movq %r12, 56 (%rdi) 56185f3d38SThomas Gleixner 57185f3d38SThomas Gleixner leaq 64 (%rsi), %rsi 58185f3d38SThomas Gleixner leaq 64 (%rdi), %rdi 59185f3d38SThomas Gleixner 60185f3d38SThomas Gleixner jnz .Loop64 61185f3d38SThomas Gleixner 62185f3d38SThomas Gleixner movl $5,%ecx 63185f3d38SThomas Gleixner .p2align 4 64185f3d38SThomas Gleixner.Loop2: 65185f3d38SThomas Gleixner decl %ecx 66185f3d38SThomas Gleixner 67185f3d38SThomas Gleixner movq (%rsi), %rax 68185f3d38SThomas Gleixner movq 8 (%rsi), %rbx 69185f3d38SThomas Gleixner movq 16 (%rsi), %rdx 70185f3d38SThomas Gleixner movq 24 (%rsi), %r8 71185f3d38SThomas Gleixner movq 32 (%rsi), %r9 72185f3d38SThomas Gleixner movq 40 (%rsi), %r10 73185f3d38SThomas Gleixner movq 48 (%rsi), %r11 74185f3d38SThomas Gleixner movq 56 (%rsi), %r12 75185f3d38SThomas Gleixner 76185f3d38SThomas Gleixner movq %rax, (%rdi) 77185f3d38SThomas Gleixner movq %rbx, 8 (%rdi) 78185f3d38SThomas Gleixner movq %rdx, 16 (%rdi) 79185f3d38SThomas Gleixner movq %r8, 24 (%rdi) 80185f3d38SThomas Gleixner movq %r9, 32 (%rdi) 81185f3d38SThomas Gleixner movq %r10, 40 (%rdi) 82185f3d38SThomas Gleixner movq %r11, 48 (%rdi) 83185f3d38SThomas Gleixner movq %r12, 56 (%rdi) 84185f3d38SThomas Gleixner 85185f3d38SThomas Gleixner leaq 64(%rdi),%rdi 86185f3d38SThomas Gleixner leaq 64(%rsi),%rsi 87185f3d38SThomas Gleixner 88185f3d38SThomas Gleixner jnz .Loop2 89185f3d38SThomas Gleixner 90185f3d38SThomas Gleixner movq (%rsp),%rbx 91185f3d38SThomas Gleixner CFI_RESTORE rbx 92185f3d38SThomas Gleixner movq 1*8(%rsp),%r12 93185f3d38SThomas Gleixner CFI_RESTORE r12 94185f3d38SThomas Gleixner movq 2*8(%rsp),%r13 95185f3d38SThomas Gleixner CFI_RESTORE r13 96185f3d38SThomas Gleixner addq $3*8,%rsp 97185f3d38SThomas Gleixner CFI_ADJUST_CFA_OFFSET -3*8 98185f3d38SThomas Gleixner ret 99185f3d38SThomas Gleixner.Lcopy_page_end: 100185f3d38SThomas Gleixner CFI_ENDPROC 101185f3d38SThomas GleixnerENDPROC(copy_page) 102185f3d38SThomas Gleixner 103185f3d38SThomas Gleixner /* Some CPUs run faster using the string copy instructions. 104185f3d38SThomas Gleixner It is also a lot simpler. Use this when possible */ 105185f3d38SThomas Gleixner 106185f3d38SThomas Gleixner#include <asm/cpufeature.h> 107185f3d38SThomas Gleixner 108185f3d38SThomas Gleixner .section .altinstr_replacement,"ax" 109185f3d38SThomas Gleixner1: .byte 0xeb /* jmp <disp8> */ 110185f3d38SThomas Gleixner .byte (copy_page_c - copy_page) - (2f - 1b) /* offset */ 111185f3d38SThomas Gleixner2: 112185f3d38SThomas Gleixner .previous 113185f3d38SThomas Gleixner .section .altinstructions,"a" 11459e97e4dSAndy Lutomirski altinstruction_entry copy_page, 1b, X86_FEATURE_REP_GOOD, \ 11559e97e4dSAndy Lutomirski .Lcopy_page_end-copy_page, 2b-1b 116185f3d38SThomas Gleixner .previous 117