Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.16 244 lines 5.7 kB view raw
1/* SPDX-License-Identifier: GPL-2.0 */ 2#ifndef _ASM_SCORE_CHECKSUM_H 3#define _ASM_SCORE_CHECKSUM_H 4 5#include <linux/in6.h> 6#include <linux/uaccess.h> 7 8/* 9 * computes the checksum of a memory block at buff, length len, 10 * and adds in "sum" (32-bit) 11 * 12 * returns a 32-bit number suitable for feeding into itself 13 * or csum_tcpudp_magic 14 * 15 * this function must be called with even lengths, except 16 * for the last fragment, which may be odd 17 * 18 * it's best to have buff aligned on a 32-bit boundary 19 */ 20unsigned int csum_partial(const void *buff, int len, __wsum sum); 21unsigned int csum_partial_copy_from_user(const char *src, char *dst, int len, 22 unsigned int sum, int *csum_err); 23unsigned int csum_partial_copy(const char *src, char *dst, 24 int len, unsigned int sum); 25 26/* 27 * this is a new version of the above that records errors it finds in *errp, 28 * but continues and zeros the rest of the buffer. 29 */ 30 31/* 32 * Copy and checksum to user 33 */ 34#define HAVE_CSUM_COPY_USER 35static inline 36__wsum csum_and_copy_to_user(const void *src, void __user *dst, int len, 37 __wsum sum, int *err_ptr) 38{ 39 sum = csum_partial(src, len, sum); 40 if (copy_to_user(dst, src, len)) { 41 *err_ptr = -EFAULT; 42 return (__force __wsum) -1; /* invalid checksum */ 43 } 44 return sum; 45} 46 47 48#define csum_partial_copy_nocheck csum_partial_copy 49/* 50 * Fold a partial checksum without adding pseudo headers 51 */ 52 53static inline __sum16 csum_fold(__wsum sum) 54{ 55 /* the while loop is unnecessary really, it's always enough with two 56 iterations */ 57 __asm__ __volatile__( 58 ".set volatile\n\t" 59 ".set\tr1\n\t" 60 "slli\tr1,%0, 16\n\t" 61 "add\t%0,%0, r1\n\t" 62 "cmp.c\tr1, %0\n\t" 63 "srli\t%0, %0, 16\n\t" 64 "bleu\t1f\n\t" 65 "addi\t%0, 0x1\n\t" 66 "1:ldi\tr30, 0xffff\n\t" 67 "xor\t%0, %0, r30\n\t" 68 "slli\t%0, %0, 16\n\t" 69 "srli\t%0, %0, 16\n\t" 70 ".set\tnor1\n\t" 71 ".set optimize\n\t" 72 : "=r" (sum) 73 : "0" (sum)); 74 return sum; 75} 76 77/* 78 * This is a version of ip_compute_csum() optimized for IP headers, 79 * which always checksum on 4 octet boundaries. 80 * 81 * By Jorge Cwik <jorge@laser.satlink.net>, adapted for linux by 82 * Arnt Gulbrandsen. 83 */ 84static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl) 85{ 86 unsigned int sum; 87 unsigned long dummy; 88 89 __asm__ __volatile__( 90 ".set volatile\n\t" 91 ".set\tnor1\n\t" 92 "lw\t%0, [%1]\n\t" 93 "subri\t%2, %2, 4\n\t" 94 "slli\t%2, %2, 2\n\t" 95 "lw\t%3, [%1, 4]\n\t" 96 "add\t%2, %2, %1\n\t" 97 "add\t%0, %0, %3\n\t" 98 "cmp.c\t%3, %0\n\t" 99 "lw\t%3, [%1, 8]\n\t" 100 "bleu\t1f\n\t" 101 "addi\t%0, 0x1\n\t" 102 "1:\n\t" 103 "add\t%0, %0, %3\n\t" 104 "cmp.c\t%3, %0\n\t" 105 "lw\t%3, [%1, 12]\n\t" 106 "bleu\t1f\n\t" 107 "addi\t%0, 0x1\n\t" 108 "1:add\t%0, %0, %3\n\t" 109 "cmp.c\t%3, %0\n\t" 110 "bleu\t1f\n\t" 111 "addi\t%0, 0x1\n" 112 113 "1:\tlw\t%3, [%1, 16]\n\t" 114 "addi\t%1, 4\n\t" 115 "add\t%0, %0, %3\n\t" 116 "cmp.c\t%3, %0\n\t" 117 "bleu\t2f\n\t" 118 "addi\t%0, 0x1\n" 119 "2:cmp.c\t%2, %1\n\t" 120 "bne\t1b\n\t" 121 122 ".set\tr1\n\t" 123 ".set optimize\n\t" 124 : "=&r" (sum), "=&r" (iph), "=&r" (ihl), "=&r" (dummy) 125 : "1" (iph), "2" (ihl)); 126 127 return csum_fold(sum); 128} 129 130static inline __wsum 131csum_tcpudp_nofold(__be32 saddr, __be32 daddr, __u32 len, 132 __u8 proto, __wsum sum) 133{ 134 unsigned long tmp = (len + proto) << 8; 135 __asm__ __volatile__( 136 ".set volatile\n\t" 137 "add\t%0, %0, %2\n\t" 138 "cmp.c\t%2, %0\n\t" 139 "bleu\t1f\n\t" 140 "addi\t%0, 0x1\n\t" 141 "1:\n\t" 142 "add\t%0, %0, %3\n\t" 143 "cmp.c\t%3, %0\n\t" 144 "bleu\t1f\n\t" 145 "addi\t%0, 0x1\n\t" 146 "1:\n\t" 147 "add\t%0, %0, %4\n\t" 148 "cmp.c\t%4, %0\n\t" 149 "bleu\t1f\n\t" 150 "addi\t%0, 0x1\n\t" 151 "1:\n\t" 152 ".set optimize\n\t" 153 : "=r" (sum) 154 : "0" (daddr), "r"(saddr), 155 "r" (tmp), 156 "r" (sum)); 157 return sum; 158} 159 160/* 161 * computes the checksum of the TCP/UDP pseudo-header 162 * returns a 16-bit checksum, already complemented 163 */ 164static inline __sum16 165csum_tcpudp_magic(__be32 saddr, __be32 daddr, __u32 len, 166 __u8 proto, __wsum sum) 167{ 168 return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum)); 169} 170 171/* 172 * this routine is used for miscellaneous IP-like checksums, mainly 173 * in icmp.c 174 */ 175 176static inline unsigned short ip_compute_csum(const void *buff, int len) 177{ 178 return csum_fold(csum_partial(buff, len, 0)); 179} 180 181#define _HAVE_ARCH_IPV6_CSUM 182static inline __sum16 csum_ipv6_magic(const struct in6_addr *saddr, 183 const struct in6_addr *daddr, 184 __u32 len, __u8 proto, __wsum sum) 185{ 186 __asm__ __volatile__( 187 ".set\tvolatile\t\t\t# csum_ipv6_magic\n\t" 188 "add\t%0, %0, %5\t\t\t# proto (long in network byte order)\n\t" 189 "cmp.c\t%5, %0\n\t" 190 "bleu 1f\n\t" 191 "addi\t%0, 0x1\n\t" 192 "1:add\t%0, %0, %6\t\t\t# csum\n\t" 193 "cmp.c\t%6, %0\n\t" 194 "lw\t%1, [%2, 0]\t\t\t# four words source address\n\t" 195 "bleu 1f\n\t" 196 "addi\t%0, 0x1\n\t" 197 "1:add\t%0, %0, %1\n\t" 198 "cmp.c\t%1, %0\n\t" 199 "1:lw\t%1, [%2, 4]\n\t" 200 "bleu 1f\n\t" 201 "addi\t%0, 0x1\n\t" 202 "1:add\t%0, %0, %1\n\t" 203 "cmp.c\t%1, %0\n\t" 204 "lw\t%1, [%2,8]\n\t" 205 "bleu 1f\n\t" 206 "addi\t%0, 0x1\n\t" 207 "1:add\t%0, %0, %1\n\t" 208 "cmp.c\t%1, %0\n\t" 209 "lw\t%1, [%2, 12]\n\t" 210 "bleu 1f\n\t" 211 "addi\t%0, 0x1\n\t" 212 "1:add\t%0, %0,%1\n\t" 213 "cmp.c\t%1, %0\n\t" 214 "lw\t%1, [%3, 0]\n\t" 215 "bleu 1f\n\t" 216 "addi\t%0, 0x1\n\t" 217 "1:add\t%0, %0, %1\n\t" 218 "cmp.c\t%1, %0\n\t" 219 "lw\t%1, [%3, 4]\n\t" 220 "bleu 1f\n\t" 221 "addi\t%0, 0x1\n\t" 222 "1:add\t%0, %0, %1\n\t" 223 "cmp.c\t%1, %0\n\t" 224 "lw\t%1, [%3, 8]\n\t" 225 "bleu 1f\n\t" 226 "addi\t%0, 0x1\n\t" 227 "1:add\t%0, %0, %1\n\t" 228 "cmp.c\t%1, %0\n\t" 229 "lw\t%1, [%3, 12]\n\t" 230 "bleu 1f\n\t" 231 "addi\t%0, 0x1\n\t" 232 "1:add\t%0, %0, %1\n\t" 233 "cmp.c\t%1, %0\n\t" 234 "bleu 1f\n\t" 235 "addi\t%0, 0x1\n\t" 236 "1:\n\t" 237 ".set\toptimize" 238 : "=r" (sum), "=r" (proto) 239 : "r" (saddr), "r" (daddr), 240 "0" (htonl(len)), "1" (htonl(proto)), "r" (sum)); 241 242 return csum_fold(sum); 243} 244#endif /* _ASM_SCORE_CHECKSUM_H */