^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /* SPDX-License-Identifier: GPL-2.0-or-later */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * INET An implementation of the TCP/IP protocol suite for the LINUX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * operating system. INET is implemented using the BSD Socket
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * interface as the means of communication with the user level.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * IP/TCP/UDP checksumming routines
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Authors: Jorge Cwik, <jorge@laser.satlink.net>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Arnt Gulbrandsen, <agulbra@nvg.unit.no>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Tom May, <ftom@netcom.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * Pentium Pro/II routines:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * Alexander Kjeldaas <astor@guardian.no>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * Finn Arne Gangstad <finnag@guardian.no>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * Lots of code moved from tcp.c and ip.c; see those files
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * for more names.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * Changes: Ingo Molnar, converted csum_partial_copy() to 2.1 exception
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * handling.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * Andi Kleen, add zeroing on error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * converted to pure assembler
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <asm/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <asm/asm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <asm/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * computes a partial checksum, e.g. for TCP/UDP fragments
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) .text
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) .align 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) .globl csum_partial
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #ifndef CONFIG_X86_USE_PPRO_CHECKSUM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * Experiments with Ethernet and SLIP connections show that buff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * is aligned on either a 2-byte or 4-byte boundary. We get at
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * least a twofold speedup on 486 and Pentium if it is 4-byte aligned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * Fortunately, it is easy to convert 2-byte alignment to 4-byte
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * alignment for the unrolled loop.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) csum_partial:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) pushl %esi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) pushl %ebx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) movl 20(%esp),%eax # Function arg: unsigned int sum
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) movl 16(%esp),%ecx # Function arg: int len
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) movl 12(%esp),%esi # Function arg: unsigned char *buff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) testl $2, %esi # Check alignment.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) jz 2f # Jump if alignment is ok.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) subl $2, %ecx # Alignment uses up two bytes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) jae 1f # Jump if we had at least two bytes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) addl $2, %ecx # ecx was < 2. Deal with it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) jmp 4f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) 1: movw (%esi), %bx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) addl $2, %esi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) addw %bx, %ax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) adcl $0, %eax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) movl %ecx, %edx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) shrl $5, %ecx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) jz 2f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) testl %esi, %esi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) 1: movl (%esi), %ebx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) adcl %ebx, %eax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) movl 4(%esi), %ebx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) adcl %ebx, %eax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) movl 8(%esi), %ebx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) adcl %ebx, %eax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) movl 12(%esi), %ebx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) adcl %ebx, %eax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) movl 16(%esi), %ebx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) adcl %ebx, %eax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) movl 20(%esi), %ebx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) adcl %ebx, %eax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) movl 24(%esi), %ebx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) adcl %ebx, %eax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) movl 28(%esi), %ebx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) adcl %ebx, %eax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) lea 32(%esi), %esi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) dec %ecx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) jne 1b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) adcl $0, %eax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) 2: movl %edx, %ecx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) andl $0x1c, %edx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) je 4f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) shrl $2, %edx # This clears CF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) 3: adcl (%esi), %eax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) lea 4(%esi), %esi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) dec %edx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) jne 3b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) adcl $0, %eax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) 4: andl $3, %ecx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) jz 7f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) cmpl $2, %ecx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) jb 5f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) movw (%esi),%cx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) leal 2(%esi),%esi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) je 6f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) shll $16,%ecx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 5: movb (%esi),%cl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 6: addl %ecx,%eax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) adcl $0, %eax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 7:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) popl %ebx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) popl %esi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) ret
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) /* Version for PentiumII/PPro */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) csum_partial:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) pushl %esi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) pushl %ebx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) movl 20(%esp),%eax # Function arg: unsigned int sum
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) movl 16(%esp),%ecx # Function arg: int len
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) movl 12(%esp),%esi # Function arg: const unsigned char *buf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) testl $2, %esi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) jnz 30f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 10:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) movl %ecx, %edx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) movl %ecx, %ebx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) andl $0x7c, %ebx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) shrl $7, %ecx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) addl %ebx,%esi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) shrl $2, %ebx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) negl %ebx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) lea 45f(%ebx,%ebx,2), %ebx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) testl %esi, %esi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) jmp *%ebx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) # Handle 2-byte-aligned regions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 20: addw (%esi), %ax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) lea 2(%esi), %esi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) adcl $0, %eax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) jmp 10b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 30: subl $2, %ecx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) ja 20b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) je 32f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) movzbl (%esi),%ebx # csumming 1 byte, 2-aligned
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) addl %ebx, %eax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) adcl $0, %eax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) jmp 80f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) addw (%esi), %ax # csumming 2 bytes, 2-aligned
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) adcl $0, %eax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) jmp 80f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 40:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) addl -128(%esi), %eax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) adcl -124(%esi), %eax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) adcl -120(%esi), %eax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) adcl -116(%esi), %eax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) adcl -112(%esi), %eax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) adcl -108(%esi), %eax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) adcl -104(%esi), %eax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) adcl -100(%esi), %eax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) adcl -96(%esi), %eax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) adcl -92(%esi), %eax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) adcl -88(%esi), %eax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) adcl -84(%esi), %eax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) adcl -80(%esi), %eax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) adcl -76(%esi), %eax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) adcl -72(%esi), %eax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) adcl -68(%esi), %eax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) adcl -64(%esi), %eax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) adcl -60(%esi), %eax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) adcl -56(%esi), %eax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) adcl -52(%esi), %eax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) adcl -48(%esi), %eax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) adcl -44(%esi), %eax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) adcl -40(%esi), %eax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) adcl -36(%esi), %eax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) adcl -32(%esi), %eax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) adcl -28(%esi), %eax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) adcl -24(%esi), %eax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) adcl -20(%esi), %eax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) adcl -16(%esi), %eax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) adcl -12(%esi), %eax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) adcl -8(%esi), %eax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) adcl -4(%esi), %eax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 45:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) lea 128(%esi), %esi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) adcl $0, %eax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) dec %ecx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) jge 40b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) movl %edx, %ecx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 50: andl $3, %ecx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) jz 80f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) # Handle the last 1-3 bytes without jumping
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) notl %ecx # 1->2, 2->1, 3->0, higher bits are masked
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) movl $0xffffff,%ebx # by the shll and shrl instructions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) shll $3,%ecx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) shrl %cl,%ebx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) andl -128(%esi),%ebx # esi is 4-aligned so should be ok
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) addl %ebx,%eax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) adcl $0,%eax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 80:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) popl %ebx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) popl %esi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) ret
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) EXPORT_SYMBOL(csum_partial)