blob: fb903b758da8534847ef3c4c97840d91972abdf4 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Ingo Molnar2c763972011-03-18 10:42:11 +01002 * Copyright 2002, 2003 Andi Kleen, SuSE Labs.
3 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07004 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file COPYING in the main directory of this archive
6 * for more details. No warranty for anything given at all.
7 */
Jan Beulich8d379da2006-09-26 10:52:32 +02008#include <linux/linkage.h>
9#include <asm/dwarf2.h>
10#include <asm/errno.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070011
12/*
13 * Checksum copy with exception handling.
Ingo Molnar2c763972011-03-18 10:42:11 +010014 * On exceptions src_err_ptr or dst_err_ptr is set to -EFAULT and the
Linus Torvalds1da177e2005-04-16 15:20:36 -070015 * destination is zeroed.
Ingo Molnar2c763972011-03-18 10:42:11 +010016 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070017 * Input
18 * rdi source
19 * rsi destination
20 * edx len (32bit)
Ingo Molnar2c763972011-03-18 10:42:11 +010021 * ecx sum (32bit)
Linus Torvalds1da177e2005-04-16 15:20:36 -070022 * r8 src_err_ptr (int)
23 * r9 dst_err_ptr (int)
24 *
25 * Output
26 * eax 64bit sum. undefined in case of exception.
Ingo Molnar2c763972011-03-18 10:42:11 +010027 *
28 * Wrappers need to take care of valid exception sum and zeroing.
Linus Torvalds1da177e2005-04-16 15:20:36 -070029 * They also should align source or destination to 8 bytes.
30 */
31
32 .macro source
3310:
Ingo Molnar2c763972011-03-18 10:42:11 +010034 .section __ex_table, "a"
Linus Torvalds1da177e2005-04-16 15:20:36 -070035 .align 8
Ingo Molnar2c763972011-03-18 10:42:11 +010036 .quad 10b, .Lbad_source
Linus Torvalds1da177e2005-04-16 15:20:36 -070037 .previous
38 .endm
Ingo Molnar2c763972011-03-18 10:42:11 +010039
Linus Torvalds1da177e2005-04-16 15:20:36 -070040 .macro dest
4120:
Ingo Molnar2c763972011-03-18 10:42:11 +010042 .section __ex_table, "a"
Linus Torvalds1da177e2005-04-16 15:20:36 -070043 .align 8
Ingo Molnar2c763972011-03-18 10:42:11 +010044 .quad 20b, .Lbad_dest
Linus Torvalds1da177e2005-04-16 15:20:36 -070045 .previous
46 .endm
Ingo Molnar2c763972011-03-18 10:42:11 +010047
Linus Torvalds1da177e2005-04-16 15:20:36 -070048 .macro ignore L=.Lignore
4930:
Ingo Molnar2c763972011-03-18 10:42:11 +010050 .section __ex_table, "a"
Linus Torvalds1da177e2005-04-16 15:20:36 -070051 .align 8
Ingo Molnar2c763972011-03-18 10:42:11 +010052 .quad 30b, \L
Linus Torvalds1da177e2005-04-16 15:20:36 -070053 .previous
54 .endm
Ingo Molnar2c763972011-03-18 10:42:11 +010055
56
Jan Beulich8d379da2006-09-26 10:52:32 +020057ENTRY(csum_partial_copy_generic)
58 CFI_STARTPROC
Ingo Molnar2c763972011-03-18 10:42:11 +010059 cmpl $3*64, %edx
60 jle .Lignore
Linus Torvalds1da177e2005-04-16 15:20:36 -070061
Ingo Molnar2c763972011-03-18 10:42:11 +010062.Lignore:
63 subq $7*8, %rsp
Jan Beulich8d379da2006-09-26 10:52:32 +020064 CFI_ADJUST_CFA_OFFSET 7*8
Ingo Molnar2c763972011-03-18 10:42:11 +010065 movq %rbx, 2*8(%rsp)
Jan Beulich8d379da2006-09-26 10:52:32 +020066 CFI_REL_OFFSET rbx, 2*8
Ingo Molnar2c763972011-03-18 10:42:11 +010067 movq %r12, 3*8(%rsp)
Jan Beulich8d379da2006-09-26 10:52:32 +020068 CFI_REL_OFFSET r12, 3*8
Ingo Molnar2c763972011-03-18 10:42:11 +010069 movq %r14, 4*8(%rsp)
Jan Beulich8d379da2006-09-26 10:52:32 +020070 CFI_REL_OFFSET r14, 4*8
Ingo Molnar2c763972011-03-18 10:42:11 +010071 movq %r13, 5*8(%rsp)
Jan Beulich8d379da2006-09-26 10:52:32 +020072 CFI_REL_OFFSET r13, 5*8
Ingo Molnar2c763972011-03-18 10:42:11 +010073 movq %rbp, 6*8(%rsp)
Jan Beulich8d379da2006-09-26 10:52:32 +020074 CFI_REL_OFFSET rbp, 6*8
Linus Torvalds1da177e2005-04-16 15:20:36 -070075
Ingo Molnar2c763972011-03-18 10:42:11 +010076 movq %r8, (%rsp)
77 movq %r9, 1*8(%rsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -070078
Ingo Molnar2c763972011-03-18 10:42:11 +010079 movl %ecx, %eax
80 movl %edx, %ecx
Linus Torvalds1da177e2005-04-16 15:20:36 -070081
Ingo Molnar2c763972011-03-18 10:42:11 +010082 xorl %r9d, %r9d
83 movq %rcx, %r12
84
85 shrq $6, %r12
86 jz .Lhandle_tail /* < 64 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070087
88 clc
Ingo Molnar2c763972011-03-18 10:42:11 +010089
Linus Torvalds1da177e2005-04-16 15:20:36 -070090 /* main loop. clear in 64 byte blocks */
91 /* r9: zero, r8: temp2, rbx: temp1, rax: sum, rcx: saved length */
92 /* r11: temp3, rdx: temp4, r12 loopcnt */
93 /* r10: temp5, rbp: temp6, r14 temp7, r13 temp8 */
94 .p2align 4
95.Lloop:
96 source
Ingo Molnar2c763972011-03-18 10:42:11 +010097 movq (%rdi), %rbx
Linus Torvalds1da177e2005-04-16 15:20:36 -070098 source
Ingo Molnar2c763972011-03-18 10:42:11 +010099 movq 8(%rdi), %r8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700100 source
Ingo Molnar2c763972011-03-18 10:42:11 +0100101 movq 16(%rdi), %r11
Linus Torvalds1da177e2005-04-16 15:20:36 -0700102 source
Ingo Molnar2c763972011-03-18 10:42:11 +0100103 movq 24(%rdi), %rdx
Linus Torvalds1da177e2005-04-16 15:20:36 -0700104
105 source
Ingo Molnar2c763972011-03-18 10:42:11 +0100106 movq 32(%rdi), %r10
Linus Torvalds1da177e2005-04-16 15:20:36 -0700107 source
Ingo Molnar2c763972011-03-18 10:42:11 +0100108 movq 40(%rdi), %rbp
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109 source
Ingo Molnar2c763972011-03-18 10:42:11 +0100110 movq 48(%rdi), %r14
Linus Torvalds1da177e2005-04-16 15:20:36 -0700111 source
Ingo Molnar2c763972011-03-18 10:42:11 +0100112 movq 56(%rdi), %r13
113
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114 ignore 2f
115 prefetcht0 5*64(%rdi)
Ingo Molnar2c763972011-03-18 10:42:11 +01001162:
117 adcq %rbx, %rax
118 adcq %r8, %rax
119 adcq %r11, %rax
120 adcq %rdx, %rax
121 adcq %r10, %rax
122 adcq %rbp, %rax
123 adcq %r14, %rax
124 adcq %r13, %rax
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125
126 decl %r12d
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127
128 dest
Ingo Molnar2c763972011-03-18 10:42:11 +0100129 movq %rbx, (%rsi)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130 dest
Ingo Molnar2c763972011-03-18 10:42:11 +0100131 movq %r8, 8(%rsi)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132 dest
Ingo Molnar2c763972011-03-18 10:42:11 +0100133 movq %r11, 16(%rsi)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700134 dest
Ingo Molnar2c763972011-03-18 10:42:11 +0100135 movq %rdx, 24(%rsi)
136
137 dest
138 movq %r10, 32(%rsi)
139 dest
140 movq %rbp, 40(%rsi)
141 dest
142 movq %r14, 48(%rsi)
143 dest
144 movq %r13, 56(%rsi)
145
Linus Torvalds1da177e2005-04-16 15:20:36 -07001463:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700147
Ingo Molnar2c763972011-03-18 10:42:11 +0100148 leaq 64(%rdi), %rdi
149 leaq 64(%rsi), %rsi
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150
Ingo Molnar2c763972011-03-18 10:42:11 +0100151 jnz .Lloop
152
153 adcq %r9, %rax
Linus Torvalds1da177e2005-04-16 15:20:36 -0700154
Lucas De Marchi0d2eb442011-03-17 16:24:16 -0300155 /* do last up to 56 bytes */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700156.Lhandle_tail:
157 /* ecx: count */
Ingo Molnar2c763972011-03-18 10:42:11 +0100158 movl %ecx, %r10d
159 andl $63, %ecx
160 shrl $3, %ecx
161 jz .Lfold
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162 clc
163 .p2align 4
Ingo Molnar2c763972011-03-18 10:42:11 +0100164.Lloop_8:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165 source
Ingo Molnar2c763972011-03-18 10:42:11 +0100166 movq (%rdi), %rbx
167 adcq %rbx, %rax
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168 decl %ecx
169 dest
Ingo Molnar2c763972011-03-18 10:42:11 +0100170 movq %rbx, (%rsi)
171 leaq 8(%rsi), %rsi /* preserve carry */
172 leaq 8(%rdi), %rdi
Linus Torvalds1da177e2005-04-16 15:20:36 -0700173 jnz .Lloop_8
Ingo Molnar2c763972011-03-18 10:42:11 +0100174 adcq %r9, %rax /* add in carry */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700175
176.Lfold:
177 /* reduce checksum to 32bits */
Ingo Molnar2c763972011-03-18 10:42:11 +0100178 movl %eax, %ebx
179 shrq $32, %rax
180 addl %ebx, %eax
181 adcl %r9d, %eax
Linus Torvalds1da177e2005-04-16 15:20:36 -0700182
Ingo Molnar2c763972011-03-18 10:42:11 +0100183 /* do last up to 6 bytes */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184.Lhandle_7:
Ingo Molnar2c763972011-03-18 10:42:11 +0100185 movl %r10d, %ecx
186 andl $7, %ecx
187 shrl $1, %ecx
Linus Torvalds1da177e2005-04-16 15:20:36 -0700188 jz .Lhandle_1
Ingo Molnar2c763972011-03-18 10:42:11 +0100189 movl $2, %edx
190 xorl %ebx, %ebx
191 clc
Linus Torvalds1da177e2005-04-16 15:20:36 -0700192 .p2align 4
Ingo Molnar2c763972011-03-18 10:42:11 +0100193.Lloop_1:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194 source
Ingo Molnar2c763972011-03-18 10:42:11 +0100195 movw (%rdi), %bx
196 adcl %ebx, %eax
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197 decl %ecx
Dave Peterson92ed0222005-07-29 22:59:20 -0700198 dest
Ingo Molnar2c763972011-03-18 10:42:11 +0100199 movw %bx, (%rsi)
200 leaq 2(%rdi), %rdi
201 leaq 2(%rsi), %rsi
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202 jnz .Lloop_1
Ingo Molnar2c763972011-03-18 10:42:11 +0100203 adcl %r9d, %eax /* add in carry */
204
Linus Torvalds1da177e2005-04-16 15:20:36 -0700205 /* handle last odd byte */
206.Lhandle_1:
Ingo Molnar2c763972011-03-18 10:42:11 +0100207 testl $1, %r10d
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208 jz .Lende
Ingo Molnar2c763972011-03-18 10:42:11 +0100209 xorl %ebx, %ebx
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210 source
Ingo Molnar2c763972011-03-18 10:42:11 +0100211 movb (%rdi), %bl
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212 dest
Ingo Molnar2c763972011-03-18 10:42:11 +0100213 movb %bl, (%rsi)
214 addl %ebx, %eax
215 adcl %r9d, %eax /* carry */
216
Jan Beulich8d379da2006-09-26 10:52:32 +0200217 CFI_REMEMBER_STATE
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218.Lende:
Ingo Molnar2c763972011-03-18 10:42:11 +0100219 movq 2*8(%rsp), %rbx
Jan Beulich8d379da2006-09-26 10:52:32 +0200220 CFI_RESTORE rbx
Ingo Molnar2c763972011-03-18 10:42:11 +0100221 movq 3*8(%rsp), %r12
Jan Beulich8d379da2006-09-26 10:52:32 +0200222 CFI_RESTORE r12
Ingo Molnar2c763972011-03-18 10:42:11 +0100223 movq 4*8(%rsp), %r14
Jan Beulich8d379da2006-09-26 10:52:32 +0200224 CFI_RESTORE r14
Ingo Molnar2c763972011-03-18 10:42:11 +0100225 movq 5*8(%rsp), %r13
Jan Beulich8d379da2006-09-26 10:52:32 +0200226 CFI_RESTORE r13
Ingo Molnar2c763972011-03-18 10:42:11 +0100227 movq 6*8(%rsp), %rbp
Jan Beulich8d379da2006-09-26 10:52:32 +0200228 CFI_RESTORE rbp
Ingo Molnar2c763972011-03-18 10:42:11 +0100229 addq $7*8, %rsp
Jan Beulich8d379da2006-09-26 10:52:32 +0200230 CFI_ADJUST_CFA_OFFSET -7*8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700231 ret
Jan Beulich8d379da2006-09-26 10:52:32 +0200232 CFI_RESTORE_STATE
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233
234 /* Exception handlers. Very simple, zeroing is done in the wrappers */
235.Lbad_source:
Ingo Molnar2c763972011-03-18 10:42:11 +0100236 movq (%rsp), %rax
237 testq %rax, %rax
Linus Torvalds1da177e2005-04-16 15:20:36 -0700238 jz .Lende
Ingo Molnar2c763972011-03-18 10:42:11 +0100239 movl $-EFAULT, (%rax)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240 jmp .Lende
Ingo Molnar2c763972011-03-18 10:42:11 +0100241
Linus Torvalds1da177e2005-04-16 15:20:36 -0700242.Lbad_dest:
Ingo Molnar2c763972011-03-18 10:42:11 +0100243 movq 8(%rsp), %rax
244 testq %rax, %rax
245 jz .Lende
246 movl $-EFAULT, (%rax)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700247 jmp .Lende
Jan Beulich8d379da2006-09-26 10:52:32 +0200248 CFI_ENDPROC
249ENDPROC(csum_partial_copy_generic)