blob: 2419d5fefae30ac2453fabf71c633ede013d2e4a [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>
H. Peter Anvin015e6f12012-04-20 12:19:51 -070011#include <asm/asm.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070012
13/*
14 * Checksum copy with exception handling.
Ingo Molnar2c763972011-03-18 10:42:11 +010015 * On exceptions src_err_ptr or dst_err_ptr is set to -EFAULT and the
Linus Torvalds1da177e2005-04-16 15:20:36 -070016 * destination is zeroed.
Ingo Molnar2c763972011-03-18 10:42:11 +010017 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070018 * Input
19 * rdi source
20 * rsi destination
21 * edx len (32bit)
Ingo Molnar2c763972011-03-18 10:42:11 +010022 * ecx sum (32bit)
Linus Torvalds1da177e2005-04-16 15:20:36 -070023 * r8 src_err_ptr (int)
24 * r9 dst_err_ptr (int)
25 *
26 * Output
27 * eax 64bit sum. undefined in case of exception.
Ingo Molnar2c763972011-03-18 10:42:11 +010028 *
29 * Wrappers need to take care of valid exception sum and zeroing.
Linus Torvalds1da177e2005-04-16 15:20:36 -070030 * They also should align source or destination to 8 bytes.
31 */
32
33 .macro source
3410:
H. Peter Anvin015e6f12012-04-20 12:19:51 -070035 _ASM_EXTABLE(10b, .Lbad_source)
Linus Torvalds1da177e2005-04-16 15:20:36 -070036 .endm
Ingo Molnar2c763972011-03-18 10:42:11 +010037
Linus Torvalds1da177e2005-04-16 15:20:36 -070038 .macro dest
3920:
H. Peter Anvin015e6f12012-04-20 12:19:51 -070040 _ASM_EXTABLE(20b, .Lbad_dest)
Linus Torvalds1da177e2005-04-16 15:20:36 -070041 .endm
Ingo Molnar2c763972011-03-18 10:42:11 +010042
Linus Torvalds1da177e2005-04-16 15:20:36 -070043 .macro ignore L=.Lignore
4430:
H. Peter Anvin015e6f12012-04-20 12:19:51 -070045 _ASM_EXTABLE(30b, \L)
Linus Torvalds1da177e2005-04-16 15:20:36 -070046 .endm
Ingo Molnar2c763972011-03-18 10:42:11 +010047
48
Jan Beulich8d379da2006-09-26 10:52:32 +020049ENTRY(csum_partial_copy_generic)
50 CFI_STARTPROC
Ingo Molnar2c763972011-03-18 10:42:11 +010051 cmpl $3*64, %edx
52 jle .Lignore
Linus Torvalds1da177e2005-04-16 15:20:36 -070053
Ingo Molnar2c763972011-03-18 10:42:11 +010054.Lignore:
55 subq $7*8, %rsp
Jan Beulich8d379da2006-09-26 10:52:32 +020056 CFI_ADJUST_CFA_OFFSET 7*8
Ingo Molnar2c763972011-03-18 10:42:11 +010057 movq %rbx, 2*8(%rsp)
Jan Beulich8d379da2006-09-26 10:52:32 +020058 CFI_REL_OFFSET rbx, 2*8
Ingo Molnar2c763972011-03-18 10:42:11 +010059 movq %r12, 3*8(%rsp)
Jan Beulich8d379da2006-09-26 10:52:32 +020060 CFI_REL_OFFSET r12, 3*8
Ingo Molnar2c763972011-03-18 10:42:11 +010061 movq %r14, 4*8(%rsp)
Jan Beulich8d379da2006-09-26 10:52:32 +020062 CFI_REL_OFFSET r14, 4*8
Ingo Molnar2c763972011-03-18 10:42:11 +010063 movq %r13, 5*8(%rsp)
Jan Beulich8d379da2006-09-26 10:52:32 +020064 CFI_REL_OFFSET r13, 5*8
Ingo Molnar2c763972011-03-18 10:42:11 +010065 movq %rbp, 6*8(%rsp)
Jan Beulich8d379da2006-09-26 10:52:32 +020066 CFI_REL_OFFSET rbp, 6*8
Linus Torvalds1da177e2005-04-16 15:20:36 -070067
Ingo Molnar2c763972011-03-18 10:42:11 +010068 movq %r8, (%rsp)
69 movq %r9, 1*8(%rsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -070070
Ingo Molnar2c763972011-03-18 10:42:11 +010071 movl %ecx, %eax
72 movl %edx, %ecx
Linus Torvalds1da177e2005-04-16 15:20:36 -070073
Ingo Molnar2c763972011-03-18 10:42:11 +010074 xorl %r9d, %r9d
75 movq %rcx, %r12
76
77 shrq $6, %r12
78 jz .Lhandle_tail /* < 64 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070079
80 clc
Ingo Molnar2c763972011-03-18 10:42:11 +010081
Linus Torvalds1da177e2005-04-16 15:20:36 -070082 /* main loop. clear in 64 byte blocks */
83 /* r9: zero, r8: temp2, rbx: temp1, rax: sum, rcx: saved length */
84 /* r11: temp3, rdx: temp4, r12 loopcnt */
85 /* r10: temp5, rbp: temp6, r14 temp7, r13 temp8 */
86 .p2align 4
87.Lloop:
88 source
Ingo Molnar2c763972011-03-18 10:42:11 +010089 movq (%rdi), %rbx
Linus Torvalds1da177e2005-04-16 15:20:36 -070090 source
Ingo Molnar2c763972011-03-18 10:42:11 +010091 movq 8(%rdi), %r8
Linus Torvalds1da177e2005-04-16 15:20:36 -070092 source
Ingo Molnar2c763972011-03-18 10:42:11 +010093 movq 16(%rdi), %r11
Linus Torvalds1da177e2005-04-16 15:20:36 -070094 source
Ingo Molnar2c763972011-03-18 10:42:11 +010095 movq 24(%rdi), %rdx
Linus Torvalds1da177e2005-04-16 15:20:36 -070096
97 source
Ingo Molnar2c763972011-03-18 10:42:11 +010098 movq 32(%rdi), %r10
Linus Torvalds1da177e2005-04-16 15:20:36 -070099 source
Ingo Molnar2c763972011-03-18 10:42:11 +0100100 movq 40(%rdi), %rbp
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101 source
Ingo Molnar2c763972011-03-18 10:42:11 +0100102 movq 48(%rdi), %r14
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103 source
Ingo Molnar2c763972011-03-18 10:42:11 +0100104 movq 56(%rdi), %r13
105
Linus Torvalds1da177e2005-04-16 15:20:36 -0700106 ignore 2f
107 prefetcht0 5*64(%rdi)
Ingo Molnar2c763972011-03-18 10:42:11 +01001082:
109 adcq %rbx, %rax
110 adcq %r8, %rax
111 adcq %r11, %rax
112 adcq %rdx, %rax
113 adcq %r10, %rax
114 adcq %rbp, %rax
115 adcq %r14, %rax
116 adcq %r13, %rax
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117
118 decl %r12d
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119
120 dest
Ingo Molnar2c763972011-03-18 10:42:11 +0100121 movq %rbx, (%rsi)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700122 dest
Ingo Molnar2c763972011-03-18 10:42:11 +0100123 movq %r8, 8(%rsi)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700124 dest
Ingo Molnar2c763972011-03-18 10:42:11 +0100125 movq %r11, 16(%rsi)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126 dest
Ingo Molnar2c763972011-03-18 10:42:11 +0100127 movq %rdx, 24(%rsi)
128
129 dest
130 movq %r10, 32(%rsi)
131 dest
132 movq %rbp, 40(%rsi)
133 dest
134 movq %r14, 48(%rsi)
135 dest
136 movq %r13, 56(%rsi)
137
Linus Torvalds1da177e2005-04-16 15:20:36 -07001383:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139
Ingo Molnar2c763972011-03-18 10:42:11 +0100140 leaq 64(%rdi), %rdi
141 leaq 64(%rsi), %rsi
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142
Ingo Molnar2c763972011-03-18 10:42:11 +0100143 jnz .Lloop
144
145 adcq %r9, %rax
Linus Torvalds1da177e2005-04-16 15:20:36 -0700146
Lucas De Marchi0d2eb442011-03-17 16:24:16 -0300147 /* do last up to 56 bytes */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700148.Lhandle_tail:
149 /* ecx: count */
Ingo Molnar2c763972011-03-18 10:42:11 +0100150 movl %ecx, %r10d
151 andl $63, %ecx
152 shrl $3, %ecx
153 jz .Lfold
Linus Torvalds1da177e2005-04-16 15:20:36 -0700154 clc
155 .p2align 4
Ingo Molnar2c763972011-03-18 10:42:11 +0100156.Lloop_8:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700157 source
Ingo Molnar2c763972011-03-18 10:42:11 +0100158 movq (%rdi), %rbx
159 adcq %rbx, %rax
Linus Torvalds1da177e2005-04-16 15:20:36 -0700160 decl %ecx
161 dest
Ingo Molnar2c763972011-03-18 10:42:11 +0100162 movq %rbx, (%rsi)
163 leaq 8(%rsi), %rsi /* preserve carry */
164 leaq 8(%rdi), %rdi
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165 jnz .Lloop_8
Ingo Molnar2c763972011-03-18 10:42:11 +0100166 adcq %r9, %rax /* add in carry */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700167
168.Lfold:
169 /* reduce checksum to 32bits */
Ingo Molnar2c763972011-03-18 10:42:11 +0100170 movl %eax, %ebx
171 shrq $32, %rax
172 addl %ebx, %eax
173 adcl %r9d, %eax
Linus Torvalds1da177e2005-04-16 15:20:36 -0700174
Ingo Molnar2c763972011-03-18 10:42:11 +0100175 /* do last up to 6 bytes */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700176.Lhandle_7:
Ingo Molnar2c763972011-03-18 10:42:11 +0100177 movl %r10d, %ecx
178 andl $7, %ecx
179 shrl $1, %ecx
Linus Torvalds1da177e2005-04-16 15:20:36 -0700180 jz .Lhandle_1
Ingo Molnar2c763972011-03-18 10:42:11 +0100181 movl $2, %edx
182 xorl %ebx, %ebx
183 clc
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184 .p2align 4
Ingo Molnar2c763972011-03-18 10:42:11 +0100185.Lloop_1:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700186 source
Ingo Molnar2c763972011-03-18 10:42:11 +0100187 movw (%rdi), %bx
188 adcl %ebx, %eax
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189 decl %ecx
Dave Peterson92ed0222005-07-29 22:59:20 -0700190 dest
Ingo Molnar2c763972011-03-18 10:42:11 +0100191 movw %bx, (%rsi)
192 leaq 2(%rdi), %rdi
193 leaq 2(%rsi), %rsi
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194 jnz .Lloop_1
Ingo Molnar2c763972011-03-18 10:42:11 +0100195 adcl %r9d, %eax /* add in carry */
196
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197 /* handle last odd byte */
198.Lhandle_1:
Ingo Molnar2c763972011-03-18 10:42:11 +0100199 testl $1, %r10d
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200 jz .Lende
Ingo Molnar2c763972011-03-18 10:42:11 +0100201 xorl %ebx, %ebx
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202 source
Ingo Molnar2c763972011-03-18 10:42:11 +0100203 movb (%rdi), %bl
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204 dest
Ingo Molnar2c763972011-03-18 10:42:11 +0100205 movb %bl, (%rsi)
206 addl %ebx, %eax
207 adcl %r9d, %eax /* carry */
208
Jan Beulich8d379da2006-09-26 10:52:32 +0200209 CFI_REMEMBER_STATE
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210.Lende:
Ingo Molnar2c763972011-03-18 10:42:11 +0100211 movq 2*8(%rsp), %rbx
Jan Beulich8d379da2006-09-26 10:52:32 +0200212 CFI_RESTORE rbx
Ingo Molnar2c763972011-03-18 10:42:11 +0100213 movq 3*8(%rsp), %r12
Jan Beulich8d379da2006-09-26 10:52:32 +0200214 CFI_RESTORE r12
Ingo Molnar2c763972011-03-18 10:42:11 +0100215 movq 4*8(%rsp), %r14
Jan Beulich8d379da2006-09-26 10:52:32 +0200216 CFI_RESTORE r14
Ingo Molnar2c763972011-03-18 10:42:11 +0100217 movq 5*8(%rsp), %r13
Jan Beulich8d379da2006-09-26 10:52:32 +0200218 CFI_RESTORE r13
Ingo Molnar2c763972011-03-18 10:42:11 +0100219 movq 6*8(%rsp), %rbp
Jan Beulich8d379da2006-09-26 10:52:32 +0200220 CFI_RESTORE rbp
Ingo Molnar2c763972011-03-18 10:42:11 +0100221 addq $7*8, %rsp
Jan Beulich8d379da2006-09-26 10:52:32 +0200222 CFI_ADJUST_CFA_OFFSET -7*8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700223 ret
Jan Beulich8d379da2006-09-26 10:52:32 +0200224 CFI_RESTORE_STATE
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225
226 /* Exception handlers. Very simple, zeroing is done in the wrappers */
227.Lbad_source:
Ingo Molnar2c763972011-03-18 10:42:11 +0100228 movq (%rsp), %rax
229 testq %rax, %rax
Linus Torvalds1da177e2005-04-16 15:20:36 -0700230 jz .Lende
Ingo Molnar2c763972011-03-18 10:42:11 +0100231 movl $-EFAULT, (%rax)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700232 jmp .Lende
Ingo Molnar2c763972011-03-18 10:42:11 +0100233
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234.Lbad_dest:
Ingo Molnar2c763972011-03-18 10:42:11 +0100235 movq 8(%rsp), %rax
236 testq %rax, %rax
237 jz .Lende
238 movl $-EFAULT, (%rax)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239 jmp .Lende
Jan Beulich8d379da2006-09-26 10:52:32 +0200240 CFI_ENDPROC
241ENDPROC(csum_partial_copy_generic)