^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /* SPDX-License-Identifier: GPL-2.0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) #ifndef _PARISC_CHECKSUM_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #define _PARISC_CHECKSUM_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <linux/in6.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * computes the checksum of a memory block at buff, length len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * and adds in "sum" (32-bit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * returns a 32-bit number suitable for feeding into itself
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * or csum_tcpudp_magic
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * this function must be called with even lengths, except
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * for the last fragment, which may be odd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * it's best to have buff aligned on a 32-bit boundary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) extern __wsum csum_partial(const void *, int, __wsum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * Optimized for IP headers, which always checksum on 4 octet boundaries.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * Written by Randolph Chung <tausq@debian.org>, and then mucked with by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * LaMont Jones <lamont@debian.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) unsigned int sum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) unsigned long t0, t1, t2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) __asm__ __volatile__ (
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) " ldws,ma 4(%1), %0\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) " addib,<= -4, %2, 2f\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) "\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) " ldws 4(%1), %4\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) " ldws 8(%1), %5\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) " add %0, %4, %0\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) " ldws,ma 12(%1), %3\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) " addc %0, %5, %0\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) " addc %0, %3, %0\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) "1: ldws,ma 4(%1), %3\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) " addib,< 0, %2, 1b\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) " addc %0, %3, %0\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) "\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) " extru %0, 31, 16, %4\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) " extru %0, 15, 16, %5\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) " addc %4, %5, %0\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) " extru %0, 15, 16, %5\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) " add %0, %5, %0\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) " subi -1, %0, %0\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) "2:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) : "=r" (sum), "=r" (iph), "=r" (ihl), "=r" (t0), "=r" (t1), "=r" (t2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) : "1" (iph), "2" (ihl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) : "memory");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) return (__force __sum16)sum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) * Fold a partial checksum
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) static inline __sum16 csum_fold(__wsum csum)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) u32 sum = (__force u32)csum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) /* add the swapped two 16-bit halves of sum,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) a possible carry from adding the two 16-bit halves,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) will carry from the lower half into the upper half,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) giving us the correct sum in the upper half. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) sum += (sum << 16) + (sum >> 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) return (__force __sum16)(~sum >> 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) __u32 len, __u8 proto,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) __wsum sum)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) __asm__(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) " add %1, %0, %0\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) " addc %2, %0, %0\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) " addc %3, %0, %0\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) " addc %%r0, %0, %0\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) : "=r" (sum)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) : "r" (daddr), "r"(saddr), "r"(proto+len), "0"(sum));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) return sum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) * computes the checksum of the TCP/UDP pseudo-header
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) * returns a 16-bit checksum, already complemented
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) __u32 len, __u8 proto,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) __wsum sum)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) * this routine is used for miscellaneous IP-like checksums, mainly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) * in icmp.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) static inline __sum16 ip_compute_csum(const void *buf, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) return csum_fold (csum_partial(buf, len, 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) #define _HAVE_ARCH_IPV6_CSUM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) const struct in6_addr *daddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) __u32 len, __u8 proto,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) __wsum sum)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) unsigned long t0, t1, t2, t3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) len += proto; /* add 16-bit proto + len */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) __asm__ __volatile__ (
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) #if BITS_PER_LONG > 32
^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) ** We can execute two loads and two adds per cycle on PA 8000.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) ** But add insn's get serialized waiting for the carry bit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) ** Try to keep 4 registers with "live" values ahead of the ALU.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) " ldd,ma 8(%1), %4\n" /* get 1st saddr word */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) " ldd,ma 8(%2), %5\n" /* get 1st daddr word */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) " add %4, %0, %0\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) " ldd,ma 8(%1), %6\n" /* 2nd saddr */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) " ldd,ma 8(%2), %7\n" /* 2nd daddr */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) " add,dc %5, %0, %0\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) " add,dc %6, %0, %0\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) " add,dc %7, %0, %0\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) " add,dc %3, %0, %0\n" /* fold in proto+len | carry bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) " extrd,u %0, 31, 32, %4\n"/* copy upper half down */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) " depdi 0, 31, 32, %0\n"/* clear upper half */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) " add %4, %0, %0\n" /* fold into 32-bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) " addc 0, %0, %0\n" /* add carry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) ** For PA 1.x, the insn order doesn't matter as much.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) ** Insn stream is serialized on the carry bit here too.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) ** result from the previous operation (eg r0 + x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) " ldw,ma 4(%1), %4\n" /* get 1st saddr word */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) " ldw,ma 4(%2), %5\n" /* get 1st daddr word */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) " add %4, %0, %0\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) " ldw,ma 4(%1), %6\n" /* 2nd saddr */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) " addc %5, %0, %0\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) " ldw,ma 4(%2), %7\n" /* 2nd daddr */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) " addc %6, %0, %0\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) " ldw,ma 4(%1), %4\n" /* 3rd saddr */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) " addc %7, %0, %0\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) " ldw,ma 4(%2), %5\n" /* 3rd daddr */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) " addc %4, %0, %0\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) " ldw,ma 4(%1), %6\n" /* 4th saddr */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) " addc %5, %0, %0\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) " ldw,ma 4(%2), %7\n" /* 4th daddr */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) " addc %6, %0, %0\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) " addc %7, %0, %0\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) " addc %3, %0, %0\n" /* fold in proto+len, catch carry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) : "=r" (sum), "=r" (saddr), "=r" (daddr), "=r" (len),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) "=r" (t0), "=r" (t1), "=r" (t2), "=r" (t3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) : "0" (sum), "1" (saddr), "2" (daddr), "3" (len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) : "memory");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) return csum_fold(sum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)