ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / arch / x86_64 / lib / copy_user.S
1 /* Copyright 2002 Andi Kleen, SuSE Labs.
2  * Subject to the GNU Public License v2.
3  * 
4  * Functions to copy from and to user space.            
5  */              
6
7 #define FIX_ALIGNMENT 1
8                 
9         #include <asm/current.h>
10         #include <asm/offset.h>
11         #include <asm/thread_info.h>
12         #include <asm/cpufeature.h>
13
14 /* Standard copy_to_user with segment limit checking */         
15         .globl copy_to_user
16         .p2align 4      
17 copy_to_user:
18         GET_THREAD_INFO(%rax)
19         movq %rdi,%rcx
20         addq %rdx,%rcx
21         jc  bad_to_user
22         cmpq threadinfo_addr_limit(%rax),%rcx
23         jae bad_to_user
24 2:      
25         .byte 0xe9      /* 32bit jump */
26         .long .Lcug-1f
27 1:
28
29         .section .altinstr_replacement,"ax"
30 3:      .byte 0xe9                      /* replacement jmp with 8 bit immediate */
31         .long copy_user_generic_c-1b    /* offset */
32         .previous
33         .section .altinstructions,"a"
34         .align 8
35         .quad  2b
36         .quad  3b
37         .byte  X86_FEATURE_K8_C
38         .byte  5
39         .byte  5
40         .previous
41
42 /* Standard copy_from_user with segment limit checking */       
43         .globl copy_from_user
44         .p2align 4      
45 copy_from_user:
46         GET_THREAD_INFO(%rax)
47         movq %rsi,%rcx
48         addq %rdx,%rcx
49         jc  bad_from_user
50         cmpq threadinfo_addr_limit(%rax),%rcx
51         jae  bad_from_user
52         /* FALL THROUGH to copy_user_generic */
53         
54         .section .fixup,"ax"
55         /* must zero dest */
56 bad_from_user:
57         movl %edx,%ecx
58         xorl %eax,%eax
59         rep
60         stosb
61 bad_to_user:
62         movl    %edx,%eax
63         ret
64         .previous
65         
66                 
67 /*
68  * copy_user_generic - memory copy with exception handling.
69  *      
70  * Input:       
71  * rdi destination
72  * rsi source
73  * rdx count
74  *
75  * Output:              
76  * eax uncopied bytes or 0 if successfull. 
77  */
78         .globl copy_user_generic        
79         .p2align 4
80 copy_user_generic:      
81         .byte 0x66,0x66,0x90    /* 5 byte nop for replacement jump */   
82         .byte 0x66,0x90
83 1:              
84         .section .altinstr_replacement,"ax"
85 2:      .byte 0xe9                   /* near jump with 32bit immediate */
86         .long copy_user_generic_c-1b /* offset */
87         .previous
88         .section .altinstructions,"a"
89         .align 8
90         .quad  copy_user_generic
91         .quad  2b
92         .byte  X86_FEATURE_K8_C
93         .byte  5
94         .byte  5
95         .previous
96 .Lcug:  
97         pushq %rbx
98         xorl %eax,%eax          /*zero for the exception handler */
99
100 #ifdef FIX_ALIGNMENT
101         /* check for bad alignment of destination */
102         movl %edi,%ecx
103         andl $7,%ecx
104         jnz  .Lbad_alignment
105 .Lafter_bad_alignment:
106 #endif
107
108         movq %rdx,%rcx
109
110         movl $64,%ebx   
111         shrq $6,%rdx
112         decq %rdx
113         js   .Lhandle_tail
114         
115         .p2align 4
116 .Lloop:
117 .Ls1:   movq (%rsi),%r11
118 .Ls2:   movq 1*8(%rsi),%r8
119 .Ls3:   movq 2*8(%rsi),%r9
120 .Ls4:   movq 3*8(%rsi),%r10
121 .Ld1:   movq %r11,(%rdi)
122 .Ld2:   movq %r8,1*8(%rdi)
123 .Ld3:   movq %r9,2*8(%rdi)
124 .Ld4:   movq %r10,3*8(%rdi)
125                 
126 .Ls5:   movq 4*8(%rsi),%r11
127 .Ls6:   movq 5*8(%rsi),%r8
128 .Ls7:   movq 6*8(%rsi),%r9
129 .Ls8:   movq 7*8(%rsi),%r10
130 .Ld5:   movq %r11,4*8(%rdi)
131 .Ld6:   movq %r8,5*8(%rdi)
132 .Ld7:   movq %r9,6*8(%rdi)
133 .Ld8:   movq %r10,7*8(%rdi)
134         
135         decq %rdx
136
137         leaq 64(%rsi),%rsi
138         leaq 64(%rdi),%rdi
139         
140         jns  .Lloop
141
142         .p2align 4
143 .Lhandle_tail:
144         movl %ecx,%edx
145         andl $63,%ecx
146         shrl $3,%ecx
147         jz   .Lhandle_7
148         movl $8,%ebx
149         .p2align 4
150 .Lloop_8:
151 .Ls9:   movq (%rsi),%r8
152 .Ld9:   movq %r8,(%rdi)
153         decl %ecx
154         leaq 8(%rdi),%rdi
155         leaq 8(%rsi),%rsi
156         jnz .Lloop_8
157         
158 .Lhandle_7:             
159         movl %edx,%ecx  
160         andl $7,%ecx
161         jz   .Lende
162         .p2align 4
163 .Lloop_1:
164 .Ls10:  movb (%rsi),%bl
165 .Ld10:  movb %bl,(%rdi)
166         incq %rdi
167         incq %rsi
168         decl %ecx
169         jnz .Lloop_1
170                         
171 .Lende:
172         popq %rbx
173         ret     
174
175 #ifdef FIX_ALIGNMENT                            
176         /* align destination */
177         .p2align 4
178 .Lbad_alignment:
179         movl $8,%r9d
180         subl %ecx,%r9d
181         movl %r9d,%ecx
182         subq %r9,%rdx
183         jz   .Lsmall_align
184         js   .Lsmall_align
185 .Lalign_1:              
186 .Ls11:  movb (%rsi),%bl
187 .Ld11:  movb %bl,(%rdi)
188         incq %rsi
189         incq %rdi
190         decl %ecx
191         jnz .Lalign_1
192         jmp .Lafter_bad_alignment
193 .Lsmall_align:
194         addq %r9,%rdx
195         jmp .Lhandle_7
196 #endif
197         
198         /* table sorted by exception address */ 
199         .section __ex_table,"a"
200         .align 8
201         .quad .Ls1,.Ls1e
202         .quad .Ls2,.Ls2e
203         .quad .Ls3,.Ls3e
204         .quad .Ls4,.Ls4e        
205         .quad .Ld1,.Ls1e
206         .quad .Ld2,.Ls2e
207         .quad .Ld3,.Ls3e
208         .quad .Ld4,.Ls4e
209         .quad .Ls5,.Ls5e
210         .quad .Ls6,.Ls6e
211         .quad .Ls7,.Ls7e
212         .quad .Ls8,.Ls8e        
213         .quad .Ld5,.Ls5e
214         .quad .Ld6,.Ls6e
215         .quad .Ld7,.Ls7e
216         .quad .Ld8,.Ls8e
217         .quad .Ls9,.Le_quad
218         .quad .Ld9,.Le_quad
219         .quad .Ls10,.Le_byte
220         .quad .Ld10,.Le_byte
221 #ifdef FIX_ALIGNMENT    
222         .quad .Ls11,.Le_byte
223         .quad .Ld11,.Le_byte
224 #endif
225         .quad .Le5,.Le_zero
226         .previous
227
228         /* compute 64-offset for main loop. 8 bytes accuracy with error on the 
229            pessimistic side. this is gross. it would be better to fix the 
230            interface. */        
231         /* eax: zero, ebx: 64 */
232 .Ls1e:  addl $8,%eax
233 .Ls2e:  addl $8,%eax
234 .Ls3e:  addl $8,%eax
235 .Ls4e:  addl $8,%eax
236 .Ls5e:  addl $8,%eax
237 .Ls6e:  addl $8,%eax
238 .Ls7e:  addl $8,%eax
239 .Ls8e:  addl $8,%eax
240         addq %rbx,%rdi  /* +64 */
241         subq %rax,%rdi  /* correct destination with computed offset */
242
243         shlq $6,%rdx    /* loop counter * 64 (stride length) */
244         addq %rax,%rdx  /* add offset to loopcnt */
245         andl $63,%ecx   /* remaining bytes */
246         addq %rcx,%rdx  /* add them */
247         jmp .Lzero_rest
248
249         /* exception on quad word loop in tail handling */
250         /* ecx: loopcnt/8, %edx: length, rdi: correct */
251 .Le_quad:
252         shll $3,%ecx
253         andl $7,%edx
254         addl %ecx,%edx
255         /* edx: bytes to zero, rdi: dest, eax:zero */
256 .Lzero_rest:
257         movq %rdx,%rcx
258 .Le_byte:
259         xorl %eax,%eax
260 .Le5:   rep 
261         stosb
262         /* when there is another exception while zeroing the rest just return */
263 .Le_zero:               
264         movq %rdx,%rax
265         jmp .Lende
266
267         /* C stepping K8 run faster using the string copy instructions.
268            This is also a lot simpler. Use them when possible.
269            Patch in jmps to this code instead of copying it fully
270            to avoid unwanted aliasing in the exception tables. */
271                 
272  /* rdi destination
273   * rsi source
274   * rdx count
275   *
276   * Output:             
277   * eax uncopied bytes or 0 if successfull.
278   */                    
279 copy_user_generic_c:
280         movl %edx,%ecx
281         shrl $3,%ecx
282         andl $7,%edx    
283 1:      rep 
284         movsq 
285         movl %edx,%ecx
286 2:      rep
287         movsb
288 4:      movl %ecx,%eax
289         ret
290 3:      lea (%rdx,%rcx,8),%rax
291         ret
292         
293         .section __ex_table,"a"
294         .quad 1b,3b
295         .quad 2b,4b
296         .previous