more debug output
[linux-2.4.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         #include <linux/config.h>
8         
9 /* #define FIX_ALIGNMENT 1 */
10
11         #include <asm/current.h>
12         #include <asm/offset.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_CURRENT(%rax)
19         movq %rdi,%rcx
20         addq %rdx,%rcx
21         jc  bad_to_user
22         cmpq tsk_addr_limit(%rax),%rcx
23         jae bad_to_user
24         jmp copy_user_generic
25
26 /* Standard copy_from_user with segment limit checking */       
27         .globl copy_from_user
28         .p2align 4      
29 copy_from_user:
30         GET_CURRENT(%rax)
31         movq %rsi,%rcx
32         addq %rdx,%rcx
33         jc  bad_from_user
34         cmpq tsk_addr_limit(%rax),%rcx
35         jae  bad_from_user
36         /* FALL THROUGH to copy_user_generic */
37         
38         .section .fixup,"ax"
39         /* must zero dest */
40 bad_from_user:
41         movl %edx,%ecx
42         xorl %eax,%eax
43         rep
44         stosb
45 bad_to_user:
46         movl    %edx,%eax
47         ret
48         .previous
49         
50 /*
51  * copy_user_generic - memory copy with exception handling.
52  *      
53  * Input:       
54  * rdi destination
55  * rsi source
56  * rdx count
57  *
58  * Output:              
59  * eax uncopied bytes or 0 if successfull. 
60  */
61         .globl copy_user_generic        
62         .p2align 4
63 copy_user_generic:      
64         prefetcht0 (%rsi)
65 #ifdef CONFIG_MK8
66         prefetchw (%rdi)
67 #endif
68         pushq %rbx
69         xorl %eax,%eax          /*zero for the exception handler */
70
71 #ifdef FIX_ALIGNMENT
72         /* check for bad alignment of destination */
73         movl %edi,%ecx
74         andl $7,%ecx
75         jnz  .Lbad_alignment
76 .Lafter_bad_alignment:
77 #endif
78
79         movq %rdx,%rcx
80
81         movl $64,%ebx   
82         shrq $6,%rdx
83         decq %rdx
84         js   .Lhandle_tail
85         
86         .p2align 4
87 .Lloop:
88 .Ls1:   movq (%rsi),%r11
89 .Ls2:   movq 1*8(%rsi),%r8
90 .Ls3:   movq 2*8(%rsi),%r9
91 .Ls4:   movq 3*8(%rsi),%r10
92 .Ld1:   movq %r11,(%rdi)
93 .Ld2:   movq %r8,1*8(%rdi)
94 .Ld3:   movq %r9,2*8(%rdi)
95 .Ld4:   movq %r10,3*8(%rdi)
96                 
97 .Ls5:   movq 4*8(%rsi),%r11
98 .Ls6:   movq 5*8(%rsi),%r8
99 .Ls7:   movq 6*8(%rsi),%r9
100 .Ls8:   movq 7*8(%rsi),%r10
101 .Ld5:   movq %r11,4*8(%rdi)
102 .Ld6:   movq %r8,5*8(%rdi)
103 .Ld7:   movq %r9,6*8(%rdi)
104 .Ld8:   movq %r10,7*8(%rdi)
105         
106         decq %rdx
107
108         leaq 64(%rsi),%rsi
109         leaq 64(%rdi),%rdi
110         
111         jns  .Lloop
112
113         .p2align 4
114 .Lhandle_tail:
115         movl %ecx,%edx
116         andl $63,%ecx
117         shrl $3,%ecx
118         jz   .Lhandle_7
119         movl $8,%ebx
120         .p2align 4
121 .Lloop_8:
122 .Ls9:   movq (%rsi),%r8
123 .Ld9:   movq %r8,(%rdi)
124         decl %ecx
125         leaq 8(%rdi),%rdi
126         leaq 8(%rsi),%rsi
127         jnz .Lloop_8
128         
129 .Lhandle_7:             
130         movl %edx,%ecx  
131         andl $7,%ecx
132         jz   .Lende
133         .p2align 4
134 .Lloop_1:
135 .Ls10:  movb (%rsi),%bl
136 .Ld10:  movb %bl,(%rdi)
137         incq %rdi
138         incq %rsi
139         decl %ecx
140         jnz .Lloop_1
141                         
142 .Lende:
143         popq %rbx
144         ret     
145
146 #ifdef FIX_ALIGNMENT                            
147         /* align destination */
148         .p2align 4
149 .Lbad_alignment:
150         movl $8,%r9d
151         subl %ecx,%r9d
152         movl %r9d,%ecx
153         subq %r9,%rdx
154         jz   .Lsmall_align
155         js   .Lsmall_align
156 .Lalign_1:              
157 .Ls11:  movb (%rsi),%bl
158 .Ld11:  movb %bl,(%rdi)
159         incq %rsi
160         incq %rdi
161         decl %ecx
162         jnz .Lalign_1
163         jmp .Lafter_bad_alignment
164 .Lsmall_align:
165         addq %r9,%rdx
166         jmp .Lhandle_7
167 #endif
168         
169         /* table sorted by exception address */ 
170         .section __ex_table,"a"
171         .align 8
172         .quad .Ls1,.Ls1e
173         .quad .Ls2,.Ls2e
174         .quad .Ls3,.Ls3e
175         .quad .Ls4,.Ls4e        
176         .quad .Ld1,.Ls1e
177         .quad .Ld2,.Ls2e
178         .quad .Ld3,.Ls3e
179         .quad .Ld4,.Ls4e
180         .quad .Ls5,.Ls5e
181         .quad .Ls6,.Ls6e
182         .quad .Ls7,.Ls7e
183         .quad .Ls8,.Ls8e        
184         .quad .Ld5,.Ls5e
185         .quad .Ld6,.Ls6e
186         .quad .Ld7,.Ls7e
187         .quad .Ld8,.Ls8e
188         .quad .Ls9,.Le_quad
189         .quad .Ld9,.Le_quad
190         .quad .Ls10,.Le_byte
191         .quad .Ld10,.Le_byte
192 #ifdef FIX_ALIGNMENT    
193         .quad .Ls11,.Le_byte
194         .quad .Ld11,.Le_byte
195 #endif
196         .quad .Le5,.Le_zero
197         .previous
198
199         /* compute 64-offset for main loop. 8 bytes accuracy with error on the 
200            pessimistic side. this is gross. it would be better to fix the 
201            interface. */        
202         /* eax: zero, ebx: 64 */
203 .Ls1e:  addl $8,%eax
204 .Ls2e:  addl $8,%eax
205 .Ls3e:  addl $8,%eax
206 .Ls4e:  addl $8,%eax
207 .Ls5e:  addl $8,%eax
208 .Ls6e:  addl $8,%eax
209 .Ls7e:  addl $8,%eax
210 .Ls8e:  addl $8,%eax
211         addq %rbx,%rdi  /* +64 */
212         subq %rax,%rdi  /* correct destination with computed offset */
213
214         shlq $6,%rdx    /* loop counter * 64 (stride length) */
215         addq %rax,%rdx  /* add offset to loopcnt */
216         andl $63,%ecx   /* remaining bytes */
217         addq %rcx,%rdx  /* add them */
218         jmp .Lzero_rest
219
220         /* exception on quad word loop in tail handling */
221         /* ecx: loopcnt/8, %edx: length, rdi: correct */
222 .Le_quad:
223         shll $3,%ecx
224         andl $7,%edx
225         addl %ecx,%edx
226         /* edx: bytes to zero, rdi: dest, eax:zero */
227 .Lzero_rest:
228         movq %rdx,%rcx
229 .Le_byte:
230         xorl %eax,%eax
231 .Le5:   rep 
232         stosb
233         /* when there is another exception while zeroing the rest just return */
234 .Le_zero:               
235         movq %rdx,%rax
236         jmp .Lende