Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / arch / x86 / lib / copy_user_64.S
1 /*
2  * Copyright 2008 Vitaly Mayatskikh <vmayatsk@redhat.com>
3  * Copyright 2002 Andi Kleen, SuSE Labs.
4  * Subject to the GNU Public License v2.
5  *
6  * Functions to copy from and to user space.
7  */
8
9 #include <linux/linkage.h>
10 #include <asm/dwarf2.h>
11 #include <asm/current.h>
12 #include <asm/asm-offsets.h>
13 #include <asm/thread_info.h>
14 #include <asm/cpufeature.h>
15 #include <asm/alternative-asm.h>
16 #include <asm/asm.h>
17 #include <asm/smap.h>
18
19         .macro ALIGN_DESTINATION
20         /* check for bad alignment of destination */
21         movl %edi,%ecx
22         andl $7,%ecx
23         jz 102f                         /* already aligned */
24         subl $8,%ecx
25         negl %ecx
26         subl %ecx,%edx
27 100:    movb (%rsi),%al
28 101:    movb %al,(%rdi)
29         incq %rsi
30         incq %rdi
31         decl %ecx
32         jnz 100b
33 102:
34         .section .fixup,"ax"
35 103:    addl %ecx,%edx                  /* ecx is zerorest also */
36         jmp copy_user_handle_tail
37         .previous
38
39         _ASM_EXTABLE(100b,103b)
40         _ASM_EXTABLE(101b,103b)
41         .endm
42
43 /* Standard copy_to_user with segment limit checking */
44 ENTRY(_copy_to_user)
45         CFI_STARTPROC
46         GET_THREAD_INFO(%rax)
47         movq %rdi,%rcx
48         addq %rdx,%rcx
49         jc bad_to_user
50         cmpq TI_addr_limit(%rax),%rcx
51         ja bad_to_user
52         ALTERNATIVE_2 "jmp copy_user_generic_unrolled",         \
53                       "jmp copy_user_generic_string",           \
54                       X86_FEATURE_REP_GOOD,                     \
55                       "jmp copy_user_enhanced_fast_string",     \
56                       X86_FEATURE_ERMS
57         CFI_ENDPROC
58 ENDPROC(_copy_to_user)
59
60 /* Standard copy_from_user with segment limit checking */
61 ENTRY(_copy_from_user)
62         CFI_STARTPROC
63         GET_THREAD_INFO(%rax)
64         movq %rsi,%rcx
65         addq %rdx,%rcx
66         jc bad_from_user
67         cmpq TI_addr_limit(%rax),%rcx
68         ja bad_from_user
69         ALTERNATIVE_2 "jmp copy_user_generic_unrolled",         \
70                       "jmp copy_user_generic_string",           \
71                       X86_FEATURE_REP_GOOD,                     \
72                       "jmp copy_user_enhanced_fast_string",     \
73                       X86_FEATURE_ERMS
74         CFI_ENDPROC
75 ENDPROC(_copy_from_user)
76
77         .section .fixup,"ax"
78         /* must zero dest */
79 ENTRY(bad_from_user)
80 bad_from_user:
81         CFI_STARTPROC
82         movl %edx,%ecx
83         xorl %eax,%eax
84         rep
85         stosb
86 bad_to_user:
87         movl %edx,%eax
88         ret
89         CFI_ENDPROC
90 ENDPROC(bad_from_user)
91         .previous
92
93 /*
94  * copy_user_generic_unrolled - memory copy with exception handling.
95  * This version is for CPUs like P4 that don't have efficient micro
96  * code for rep movsq
97  *
98  * Input:
99  * rdi destination
100  * rsi source
101  * rdx count
102  *
103  * Output:
104  * eax uncopied bytes or 0 if successful.
105  */
106 ENTRY(copy_user_generic_unrolled)
107         CFI_STARTPROC
108         ASM_STAC
109         cmpl $8,%edx
110         jb 20f          /* less then 8 bytes, go to byte copy loop */
111         ALIGN_DESTINATION
112         movl %edx,%ecx
113         andl $63,%edx
114         shrl $6,%ecx
115         jz 17f
116 1:      movq (%rsi),%r8
117 2:      movq 1*8(%rsi),%r9
118 3:      movq 2*8(%rsi),%r10
119 4:      movq 3*8(%rsi),%r11
120 5:      movq %r8,(%rdi)
121 6:      movq %r9,1*8(%rdi)
122 7:      movq %r10,2*8(%rdi)
123 8:      movq %r11,3*8(%rdi)
124 9:      movq 4*8(%rsi),%r8
125 10:     movq 5*8(%rsi),%r9
126 11:     movq 6*8(%rsi),%r10
127 12:     movq 7*8(%rsi),%r11
128 13:     movq %r8,4*8(%rdi)
129 14:     movq %r9,5*8(%rdi)
130 15:     movq %r10,6*8(%rdi)
131 16:     movq %r11,7*8(%rdi)
132         leaq 64(%rsi),%rsi
133         leaq 64(%rdi),%rdi
134         decl %ecx
135         jnz 1b
136 17:     movl %edx,%ecx
137         andl $7,%edx
138         shrl $3,%ecx
139         jz 20f
140 18:     movq (%rsi),%r8
141 19:     movq %r8,(%rdi)
142         leaq 8(%rsi),%rsi
143         leaq 8(%rdi),%rdi
144         decl %ecx
145         jnz 18b
146 20:     andl %edx,%edx
147         jz 23f
148         movl %edx,%ecx
149 21:     movb (%rsi),%al
150 22:     movb %al,(%rdi)
151         incq %rsi
152         incq %rdi
153         decl %ecx
154         jnz 21b
155 23:     xor %eax,%eax
156         ASM_CLAC
157         ret
158
159         .section .fixup,"ax"
160 30:     shll $6,%ecx
161         addl %ecx,%edx
162         jmp 60f
163 40:     leal (%rdx,%rcx,8),%edx
164         jmp 60f
165 50:     movl %ecx,%edx
166 60:     jmp copy_user_handle_tail /* ecx is zerorest also */
167         .previous
168
169         _ASM_EXTABLE(1b,30b)
170         _ASM_EXTABLE(2b,30b)
171         _ASM_EXTABLE(3b,30b)
172         _ASM_EXTABLE(4b,30b)
173         _ASM_EXTABLE(5b,30b)
174         _ASM_EXTABLE(6b,30b)
175         _ASM_EXTABLE(7b,30b)
176         _ASM_EXTABLE(8b,30b)
177         _ASM_EXTABLE(9b,30b)
178         _ASM_EXTABLE(10b,30b)
179         _ASM_EXTABLE(11b,30b)
180         _ASM_EXTABLE(12b,30b)
181         _ASM_EXTABLE(13b,30b)
182         _ASM_EXTABLE(14b,30b)
183         _ASM_EXTABLE(15b,30b)
184         _ASM_EXTABLE(16b,30b)
185         _ASM_EXTABLE(18b,40b)
186         _ASM_EXTABLE(19b,40b)
187         _ASM_EXTABLE(21b,50b)
188         _ASM_EXTABLE(22b,50b)
189         CFI_ENDPROC
190 ENDPROC(copy_user_generic_unrolled)
191
192 /* Some CPUs run faster using the string copy instructions.
193  * This is also a lot simpler. Use them when possible.
194  *
195  * Only 4GB of copy is supported. This shouldn't be a problem
196  * because the kernel normally only writes from/to page sized chunks
197  * even if user space passed a longer buffer.
198  * And more would be dangerous because both Intel and AMD have
199  * errata with rep movsq > 4GB. If someone feels the need to fix
200  * this please consider this.
201  *
202  * Input:
203  * rdi destination
204  * rsi source
205  * rdx count
206  *
207  * Output:
208  * eax uncopied bytes or 0 if successful.
209  */
210 ENTRY(copy_user_generic_string)
211         CFI_STARTPROC
212         ASM_STAC
213         cmpl $8,%edx
214         jb 2f           /* less than 8 bytes, go to byte copy loop */
215         ALIGN_DESTINATION
216         movl %edx,%ecx
217         shrl $3,%ecx
218         andl $7,%edx
219 1:      rep
220         movsq
221 2:      movl %edx,%ecx
222 3:      rep
223         movsb
224         xorl %eax,%eax
225         ASM_CLAC
226         ret
227
228         .section .fixup,"ax"
229 11:     leal (%rdx,%rcx,8),%ecx
230 12:     movl %ecx,%edx          /* ecx is zerorest also */
231         jmp copy_user_handle_tail
232         .previous
233
234         _ASM_EXTABLE(1b,11b)
235         _ASM_EXTABLE(3b,12b)
236         CFI_ENDPROC
237 ENDPROC(copy_user_generic_string)
238
239 /*
240  * Some CPUs are adding enhanced REP MOVSB/STOSB instructions.
241  * It's recommended to use enhanced REP MOVSB/STOSB if it's enabled.
242  *
243  * Input:
244  * rdi destination
245  * rsi source
246  * rdx count
247  *
248  * Output:
249  * eax uncopied bytes or 0 if successful.
250  */
251 ENTRY(copy_user_enhanced_fast_string)
252         CFI_STARTPROC
253         ASM_STAC
254         movl %edx,%ecx
255 1:      rep
256         movsb
257         xorl %eax,%eax
258         ASM_CLAC
259         ret
260
261         .section .fixup,"ax"
262 12:     movl %ecx,%edx          /* ecx is zerorest also */
263         jmp copy_user_handle_tail
264         .previous
265
266         _ASM_EXTABLE(1b,12b)
267         CFI_ENDPROC
268 ENDPROC(copy_user_enhanced_fast_string)