xref: /openbmc/linux/arch/x86/lib/copy_page_64.S (revision 59e97e4d)
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