1f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg#ifndef __SPARC64_CHECKSUM_H 2f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg#define __SPARC64_CHECKSUM_H 3f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg 4f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg/* checksum.h: IP/UDP/TCP checksum routines on the V9. 5f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg * 6f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg * Copyright(C) 1995 Linus Torvalds 7f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg * Copyright(C) 1995 Miguel de Icaza 8f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg * Copyright(C) 1996 David S. Miller 9f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg * Copyright(C) 1996 Eddie C. Dost 10f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg * Copyright(C) 1997 Jakub Jelinek 11f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg * 12f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg * derived from: 13f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg * Alpha checksum c-code 14f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg * ix86 inline assembly 15f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg * RFC1071 Computing the Internet Checksum 16f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg */ 17f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg 18f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg#include <linux/in6.h> 19f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg#include <asm/uaccess.h> 20f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg 21f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg/* computes the checksum of a memory block at buff, length len, 22f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg * and adds in "sum" (32-bit) 23f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg * 24f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg * returns a 32-bit number suitable for feeding into itself 25f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg * or csum_tcpudp_magic 26f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg * 27f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg * this function must be called with even lengths, except 28f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg * for the last fragment, which may be odd 29f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg * 30f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg * it's best to have buff aligned on a 32-bit boundary 31f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg */ 32f05a68653e56ca2f23bccf7e50be69486886f052Sam Ravnborg__wsum csum_partial(const void * buff, int len, __wsum sum); 33f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg 34f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg/* the same as csum_partial, but copies from user space while it 35f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg * checksums 36f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg * 37f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg * here even more important to align src and dst on a 32-bit (or even 38f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg * better 64-bit) boundary 39f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg */ 40f05a68653e56ca2f23bccf7e50be69486886f052Sam Ravnborg__wsum csum_partial_copy_nocheck(const void *src, void *dst, 41f05a68653e56ca2f23bccf7e50be69486886f052Sam Ravnborg int len, __wsum sum); 42f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg 43f05a68653e56ca2f23bccf7e50be69486886f052Sam Ravnborglong __csum_partial_copy_from_user(const void __user *src, 44f05a68653e56ca2f23bccf7e50be69486886f052Sam Ravnborg void *dst, int len, 45f05a68653e56ca2f23bccf7e50be69486886f052Sam Ravnborg __wsum sum); 46f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg 47f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborgstatic inline __wsum 48f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborgcsum_partial_copy_from_user(const void __user *src, 49f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg void *dst, int len, 50f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg __wsum sum, int *err) 51f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg{ 52f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg long ret = __csum_partial_copy_from_user(src, dst, len, sum); 53f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg if (ret < 0) 54f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg *err = -EFAULT; 55f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg return (__force __wsum) ret; 56f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg} 57f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg 58f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg/* 59f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg * Copy and checksum to user 60f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg */ 61f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg#define HAVE_CSUM_COPY_USER 62f05a68653e56ca2f23bccf7e50be69486886f052Sam Ravnborglong __csum_partial_copy_to_user(const void *src, 63f05a68653e56ca2f23bccf7e50be69486886f052Sam Ravnborg void __user *dst, int len, 64f05a68653e56ca2f23bccf7e50be69486886f052Sam Ravnborg __wsum sum); 65f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg 66f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborgstatic inline __wsum 67f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborgcsum_and_copy_to_user(const void *src, 68f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg void __user *dst, int len, 69f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg __wsum sum, int *err) 70f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg{ 71f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg long ret = __csum_partial_copy_to_user(src, dst, len, sum); 72f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg if (ret < 0) 73f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg *err = -EFAULT; 74f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg return (__force __wsum) ret; 75f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg} 76f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg 77f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg/* ihl is always 5 or greater, almost always is 5, and iph is word aligned 78f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg * the majority of the time. 79f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg */ 80f05a68653e56ca2f23bccf7e50be69486886f052Sam Ravnborg__sum16 ip_fast_csum(const void *iph, unsigned int ihl); 81f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg 82f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg/* Fold a partial checksum without adding pseudo headers. */ 83f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborgstatic inline __sum16 csum_fold(__wsum sum) 84f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg{ 85f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg unsigned int tmp; 86f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg 87f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg __asm__ __volatile__( 88f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg" addcc %0, %1, %1\n" 89f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg" srl %1, 16, %1\n" 90f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg" addc %1, %%g0, %1\n" 91f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg" xnor %%g0, %1, %0\n" 92f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg : "=&r" (sum), "=r" (tmp) 93f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg : "0" (sum), "1" ((__force u32)sum<<16) 94f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg : "cc"); 95f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg return (__force __sum16)sum; 96f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg} 97f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg 98f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborgstatic inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, 99f05a68653e56ca2f23bccf7e50be69486886f052Sam Ravnborg unsigned int len, 100f05a68653e56ca2f23bccf7e50be69486886f052Sam Ravnborg unsigned short proto, 101f05a68653e56ca2f23bccf7e50be69486886f052Sam Ravnborg __wsum sum) 102f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg{ 103f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg __asm__ __volatile__( 104f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg" addcc %1, %0, %0\n" 105f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg" addccc %2, %0, %0\n" 106f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg" addccc %3, %0, %0\n" 107f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg" addc %0, %%g0, %0\n" 108f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg : "=r" (sum), "=r" (saddr) 109f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg : "r" (daddr), "r" (proto + len), "0" (sum), "1" (saddr) 110f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg : "cc"); 111f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg return sum; 112f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg} 113f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg 114f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg/* 115f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg * computes the checksum of the TCP/UDP pseudo-header 116f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg * returns a 16-bit checksum, already complemented 117f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg */ 118f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborgstatic inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr, 119f05a68653e56ca2f23bccf7e50be69486886f052Sam Ravnborg unsigned short len, 120f05a68653e56ca2f23bccf7e50be69486886f052Sam Ravnborg unsigned short proto, 121f05a68653e56ca2f23bccf7e50be69486886f052Sam Ravnborg __wsum sum) 122f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg{ 123f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum)); 124f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg} 125f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg 126f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg#define _HAVE_ARCH_IPV6_CSUM 127f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg 128f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborgstatic inline __sum16 csum_ipv6_magic(const struct in6_addr *saddr, 129f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg const struct in6_addr *daddr, 130f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg __u32 len, unsigned short proto, 131f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg __wsum sum) 132f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg{ 133f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg __asm__ __volatile__ ( 134f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg" addcc %3, %4, %%g7\n" 135f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg" addccc %5, %%g7, %%g7\n" 136f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg" lduw [%2 + 0x0c], %%g2\n" 137f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg" lduw [%2 + 0x08], %%g3\n" 138f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg" addccc %%g2, %%g7, %%g7\n" 139f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg" lduw [%2 + 0x04], %%g2\n" 140f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg" addccc %%g3, %%g7, %%g7\n" 141f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg" lduw [%2 + 0x00], %%g3\n" 142f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg" addccc %%g2, %%g7, %%g7\n" 143f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg" lduw [%1 + 0x0c], %%g2\n" 144f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg" addccc %%g3, %%g7, %%g7\n" 145f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg" lduw [%1 + 0x08], %%g3\n" 146f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg" addccc %%g2, %%g7, %%g7\n" 147f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg" lduw [%1 + 0x04], %%g2\n" 148f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg" addccc %%g3, %%g7, %%g7\n" 149f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg" lduw [%1 + 0x00], %%g3\n" 150f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg" addccc %%g2, %%g7, %%g7\n" 151f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg" addccc %%g3, %%g7, %0\n" 152f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg" addc 0, %0, %0\n" 153f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg : "=&r" (sum) 154f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg : "r" (saddr), "r" (daddr), "r"(htonl(len)), 155f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg "r"(htonl(proto)), "r"(sum) 156f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg : "g2", "g3", "g7", "cc"); 157f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg 158f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg return csum_fold(sum); 159f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg} 160f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg 161f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg/* this routine is used for miscellaneous IP-like checksums, mainly in icmp.c */ 162f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborgstatic inline __sum16 ip_compute_csum(const void *buff, int len) 163f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg{ 164f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg return csum_fold(csum_partial(buff, len, 0)); 165f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg} 166f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg 16720fce54fa74a55ad1e821b61612393d7159b6af8Tom Herbert#define HAVE_ARCH_CSUM_ADD 16820fce54fa74a55ad1e821b61612393d7159b6af8Tom Herbertstatic inline __wsum csum_add(__wsum csum, __wsum addend) 16920fce54fa74a55ad1e821b61612393d7159b6af8Tom Herbert{ 17020fce54fa74a55ad1e821b61612393d7159b6af8Tom Herbert __asm__ __volatile__( 17120fce54fa74a55ad1e821b61612393d7159b6af8Tom Herbert "addcc %0, %1, %0\n" 17220fce54fa74a55ad1e821b61612393d7159b6af8Tom Herbert "addx %0, %%g0, %0" 17320fce54fa74a55ad1e821b61612393d7159b6af8Tom Herbert : "=r" (csum) 17420fce54fa74a55ad1e821b61612393d7159b6af8Tom Herbert : "r" (addend), "0" (csum)); 17520fce54fa74a55ad1e821b61612393d7159b6af8Tom Herbert 17620fce54fa74a55ad1e821b61612393d7159b6af8Tom Herbert return csum; 17720fce54fa74a55ad1e821b61612393d7159b6af8Tom Herbert} 17820fce54fa74a55ad1e821b61612393d7159b6af8Tom Herbert 179f5e706ad886b6a5eb59637830110b09ccebf01c5Sam Ravnborg#endif /* !(__SPARC64_CHECKSUM_H) */ 180