^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) * Andreas Schwab, <schwab@issan.informatik.uni-dortmund.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * Lots of code moved from tcp.c and ip.c; see those files
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * for more names.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * 03/02/96 Jes Sorensen, Andreas Schwab, Roman Hodek:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * Fixed some nasty bugs, causing some horrible crashes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * A: At some points, the sum (%0) was used as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * length-counter instead of the length counter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * (%1). Thanks to Roman Hodek for pointing this out.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * B: GCC seems to mess up if one uses too many
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * data-registers to hold input values and one tries to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * specify d0 and d1 as scratch registers. Letting gcc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * choose these registers itself solves the problem.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * 1998/8/31 Andreas Schwab:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * Zero out rest of buffer on exception in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * csum_partial_copy_from_user.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <net/checksum.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * computes a partial checksum, e.g. for TCP/UDP fragments
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) __wsum csum_partial(const void *buff, int len, __wsum sum)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) unsigned long tmp1, tmp2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * Experiments with ethernet and slip connections show that buff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * is aligned on either a 2-byte or 4-byte boundary.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) __asm__("movel %2,%3\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) "btst #1,%3\n\t" /* Check alignment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) "jeq 2f\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) "subql #2,%1\n\t" /* buff%4==2: treat first word */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) "jgt 1f\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) "addql #2,%1\n\t" /* len was == 2, treat only rest */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) "jra 4f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) "1:\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) "addw %2@+,%0\n\t" /* add first word to sum */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) "clrl %3\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) "addxl %3,%0\n" /* add X bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) "2:\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) /* unrolled loop for the main part: do 8 longs at once */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) "movel %1,%3\n\t" /* save len in tmp1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) "lsrl #5,%1\n\t" /* len/32 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) "jeq 2f\n\t" /* not enough... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) "subql #1,%1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) "1:\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) "movel %2@+,%4\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) "addxl %4,%0\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) "movel %2@+,%4\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) "addxl %4,%0\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) "movel %2@+,%4\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) "addxl %4,%0\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) "movel %2@+,%4\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) "addxl %4,%0\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) "movel %2@+,%4\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) "addxl %4,%0\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) "movel %2@+,%4\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) "addxl %4,%0\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) "movel %2@+,%4\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) "addxl %4,%0\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) "movel %2@+,%4\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) "addxl %4,%0\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) "dbra %1,1b\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) "clrl %4\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) "addxl %4,%0\n\t" /* add X bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) "clrw %1\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) "subql #1,%1\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) "jcc 1b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) "2:\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) "movel %3,%1\n\t" /* restore len from tmp1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) "andw #0x1c,%3\n\t" /* number of rest longs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) "jeq 4f\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) "lsrw #2,%3\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) "subqw #1,%3\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) "3:\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) /* loop for rest longs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) "movel %2@+,%4\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) "addxl %4,%0\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) "dbra %3,3b\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) "clrl %4\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) "addxl %4,%0\n" /* add X bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) "4:\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) /* now check for rest bytes that do not fit into longs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) "andw #3,%1\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) "jeq 7f\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) "clrl %4\n\t" /* clear tmp2 for rest bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) "subqw #2,%1\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) "jlt 5f\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) "movew %2@+,%4\n\t" /* have rest >= 2: get word */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) "swap %4\n\t" /* into bits 16..31 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) "tstw %1\n\t" /* another byte? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) "jeq 6f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) "5:\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) "moveb %2@,%4\n\t" /* have odd rest: get byte */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) "lslw #8,%4\n\t" /* into bits 8..15; 16..31 untouched */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) "6:\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) "addl %4,%0\n\t" /* now add rest long to sum */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) "clrl %4\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) "addxl %4,%0\n" /* add X bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) "7:\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) : "=d" (sum), "=d" (len), "=a" (buff),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) "=&d" (tmp1), "=&d" (tmp2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) : "0" (sum), "1" (len), "2" (buff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) return(sum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) EXPORT_SYMBOL(csum_partial);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) * copy from user space while checksumming, with exception handling.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) __wsum
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) csum_and_copy_from_user(const void __user *src, void *dst, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) * GCC doesn't like more than 10 operands for the asm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) * statements so we have to use tmp2 for the error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) * code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) unsigned long tmp1, tmp2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) __wsum sum = ~0U;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) __asm__("movel %2,%4\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) "btst #1,%4\n\t" /* Check alignment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) "jeq 2f\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) "subql #2,%1\n\t" /* buff%4==2: treat first word */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) "jgt 1f\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) "addql #2,%1\n\t" /* len was == 2, treat only rest */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) "jra 4f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) "1:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) "10:\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) "movesw %2@+,%4\n\t" /* add first word to sum */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) "addw %4,%0\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) "movew %4,%3@+\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) "clrl %4\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) "addxl %4,%0\n" /* add X bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) "2:\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) /* unrolled loop for the main part: do 8 longs at once */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) "movel %1,%4\n\t" /* save len in tmp1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) "lsrl #5,%1\n\t" /* len/32 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) "jeq 2f\n\t" /* not enough... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) "subql #1,%1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) "1:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) "11:\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) "movesl %2@+,%5\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) "addxl %5,%0\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) "movel %5,%3@+\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) "12:\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) "movesl %2@+,%5\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) "addxl %5,%0\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) "movel %5,%3@+\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) "13:\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) "movesl %2@+,%5\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) "addxl %5,%0\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) "movel %5,%3@+\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) "14:\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) "movesl %2@+,%5\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) "addxl %5,%0\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) "movel %5,%3@+\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) "15:\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) "movesl %2@+,%5\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) "addxl %5,%0\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) "movel %5,%3@+\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) "16:\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) "movesl %2@+,%5\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) "addxl %5,%0\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) "movel %5,%3@+\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) "17:\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) "movesl %2@+,%5\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) "addxl %5,%0\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) "movel %5,%3@+\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) "18:\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) "movesl %2@+,%5\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) "addxl %5,%0\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) "movel %5,%3@+\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) "dbra %1,1b\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) "clrl %5\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) "addxl %5,%0\n\t" /* add X bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) "clrw %1\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) "subql #1,%1\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) "jcc 1b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) "2:\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) "movel %4,%1\n\t" /* restore len from tmp1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) "andw #0x1c,%4\n\t" /* number of rest longs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) "jeq 4f\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) "lsrw #2,%4\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) "subqw #1,%4\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) "3:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) /* loop for rest longs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) "19:\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) "movesl %2@+,%5\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) "addxl %5,%0\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) "movel %5,%3@+\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) "dbra %4,3b\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) "clrl %5\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) "addxl %5,%0\n" /* add X bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) "4:\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) /* now check for rest bytes that do not fit into longs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) "andw #3,%1\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) "jeq 7f\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) "clrl %5\n\t" /* clear tmp2 for rest bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) "subqw #2,%1\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) "jlt 5f\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) "20:\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) "movesw %2@+,%5\n\t" /* have rest >= 2: get word */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) "movew %5,%3@+\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) "swap %5\n\t" /* into bits 16..31 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) "tstw %1\n\t" /* another byte? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) "jeq 6f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) "5:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) "21:\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) "movesb %2@,%5\n\t" /* have odd rest: get byte */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) "moveb %5,%3@+\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) "lslw #8,%5\n\t" /* into bits 8..15; 16..31 untouched */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) "6:\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) "addl %5,%0\n\t" /* now add rest long to sum */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) "clrl %5\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) "addxl %5,%0\n\t" /* add X bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) "7:\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) ".section .fixup,\"ax\"\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) ".even\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) /* If any exception occurs, return 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) "90:\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) "clrl %0\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) "jra 7b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) ".previous\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) ".section __ex_table,\"a\"\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) ".long 10b,90b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) ".long 11b,90b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) ".long 12b,90b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) ".long 13b,90b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) ".long 14b,90b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) ".long 15b,90b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) ".long 16b,90b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) ".long 17b,90b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) ".long 18b,90b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) ".long 19b,90b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) ".long 20b,90b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) ".long 21b,90b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) ".previous"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) : "=d" (sum), "=d" (len), "=a" (src), "=a" (dst),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) "=&d" (tmp1), "=d" (tmp2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) : "0" (sum), "1" (len), "2" (src), "3" (dst)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) return sum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) EXPORT_SYMBOL(csum_and_copy_from_user);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) * copy from kernel space while checksumming, otherwise like csum_partial
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) __wsum
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) csum_partial_copy_nocheck(const void *src, void *dst, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) unsigned long tmp1, tmp2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) __wsum sum = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) __asm__("movel %2,%4\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) "btst #1,%4\n\t" /* Check alignment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) "jeq 2f\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) "subql #2,%1\n\t" /* buff%4==2: treat first word */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) "jgt 1f\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) "addql #2,%1\n\t" /* len was == 2, treat only rest */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) "jra 4f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) "1:\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) "movew %2@+,%4\n\t" /* add first word to sum */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) "addw %4,%0\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) "movew %4,%3@+\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) "clrl %4\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) "addxl %4,%0\n" /* add X bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) "2:\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) /* unrolled loop for the main part: do 8 longs at once */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) "movel %1,%4\n\t" /* save len in tmp1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) "lsrl #5,%1\n\t" /* len/32 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) "jeq 2f\n\t" /* not enough... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) "subql #1,%1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) "1:\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) "movel %2@+,%5\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) "addxl %5,%0\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) "movel %5,%3@+\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) "movel %2@+,%5\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) "addxl %5,%0\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) "movel %5,%3@+\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) "movel %2@+,%5\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) "addxl %5,%0\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) "movel %5,%3@+\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) "movel %2@+,%5\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) "addxl %5,%0\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) "movel %5,%3@+\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) "movel %2@+,%5\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) "addxl %5,%0\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) "movel %5,%3@+\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) "movel %2@+,%5\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) "addxl %5,%0\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) "movel %5,%3@+\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) "movel %2@+,%5\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) "addxl %5,%0\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) "movel %5,%3@+\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) "movel %2@+,%5\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) "addxl %5,%0\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) "movel %5,%3@+\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) "dbra %1,1b\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) "clrl %5\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) "addxl %5,%0\n\t" /* add X bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) "clrw %1\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) "subql #1,%1\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) "jcc 1b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) "2:\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) "movel %4,%1\n\t" /* restore len from tmp1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) "andw #0x1c,%4\n\t" /* number of rest longs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) "jeq 4f\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) "lsrw #2,%4\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) "subqw #1,%4\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) "3:\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) /* loop for rest longs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) "movel %2@+,%5\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) "addxl %5,%0\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) "movel %5,%3@+\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) "dbra %4,3b\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) "clrl %5\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) "addxl %5,%0\n" /* add X bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) "4:\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) /* now check for rest bytes that do not fit into longs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) "andw #3,%1\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) "jeq 7f\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) "clrl %5\n\t" /* clear tmp2 for rest bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) "subqw #2,%1\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) "jlt 5f\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) "movew %2@+,%5\n\t" /* have rest >= 2: get word */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) "movew %5,%3@+\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) "swap %5\n\t" /* into bits 16..31 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) "tstw %1\n\t" /* another byte? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) "jeq 6f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) "5:\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) "moveb %2@,%5\n\t" /* have odd rest: get byte */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) "moveb %5,%3@+\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) "lslw #8,%5\n" /* into bits 8..15; 16..31 untouched */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) "6:\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) "addl %5,%0\n\t" /* now add rest long to sum */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) "clrl %5\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) "addxl %5,%0\n" /* add X bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) "7:\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) : "=d" (sum), "=d" (len), "=a" (src), "=a" (dst),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) "=&d" (tmp1), "=&d" (tmp2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) : "0" (sum), "1" (len), "2" (src), "3" (dst)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) return(sum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) EXPORT_SYMBOL(csum_partial_copy_nocheck);