Path: blob/master/arch/x86/include/asm/checksum_64.h
10821 views
#ifndef _ASM_X86_CHECKSUM_64_H1#define _ASM_X86_CHECKSUM_64_H23/*4* Checksums for x86-645* Copyright 2002 by Andi Kleen, SuSE Labs6* with some code from asm-x86/checksum.h7*/89#include <linux/compiler.h>10#include <asm/uaccess.h>11#include <asm/byteorder.h>1213/**14* csum_fold - Fold and invert a 32bit checksum.15* sum: 32bit unfolded sum16*17* Fold a 32bit running checksum to 16bit and invert it. This is usually18* the last step before putting a checksum into a packet.19* Make sure not to mix with 64bit checksums.20*/21static inline __sum16 csum_fold(__wsum sum)22{23asm(" addl %1,%0\n"24" adcl $0xffff,%0"25: "=r" (sum)26: "r" ((__force u32)sum << 16),27"0" ((__force u32)sum & 0xffff0000));28return (__force __sum16)(~(__force u32)sum >> 16);29}3031/*32* This is a version of ip_compute_csum() optimized for IP headers,33* which always checksum on 4 octet boundaries.34*35* By Jorge Cwik <[email protected]>, adapted for linux by36* Arnt Gulbrandsen.37*/3839/**40* ip_fast_csum - Compute the IPv4 header checksum efficiently.41* iph: ipv4 header42* ihl: length of header / 443*/44static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)45{46unsigned int sum;4748asm(" movl (%1), %0\n"49" subl $4, %2\n"50" jbe 2f\n"51" addl 4(%1), %0\n"52" adcl 8(%1), %0\n"53" adcl 12(%1), %0\n"54"1: adcl 16(%1), %0\n"55" lea 4(%1), %1\n"56" decl %2\n"57" jne 1b\n"58" adcl $0, %0\n"59" movl %0, %2\n"60" shrl $16, %0\n"61" addw %w2, %w0\n"62" adcl $0, %0\n"63" notl %0\n"64"2:"65/* Since the input registers which are loaded with iph and ihl66are modified, we must also specify them as outputs, or gcc67will assume they contain their original values. */68: "=r" (sum), "=r" (iph), "=r" (ihl)69: "1" (iph), "2" (ihl)70: "memory");71return (__force __sum16)sum;72}7374/**75* csum_tcpup_nofold - Compute an IPv4 pseudo header checksum.76* @saddr: source address77* @daddr: destination address78* @len: length of packet79* @proto: ip protocol of packet80* @sum: initial sum to be added in (32bit unfolded)81*82* Returns the pseudo header checksum the input data. Result is83* 32bit unfolded.84*/85static inline __wsum86csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len,87unsigned short proto, __wsum sum)88{89asm(" addl %1, %0\n"90" adcl %2, %0\n"91" adcl %3, %0\n"92" adcl $0, %0\n"93: "=r" (sum)94: "g" (daddr), "g" (saddr),95"g" ((len + proto)<<8), "0" (sum));96return sum;97}9899100/**101* csum_tcpup_magic - Compute an IPv4 pseudo header checksum.102* @saddr: source address103* @daddr: destination address104* @len: length of packet105* @proto: ip protocol of packet106* @sum: initial sum to be added in (32bit unfolded)107*108* Returns the 16bit pseudo header checksum the input data already109* complemented and ready to be filled in.110*/111static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,112unsigned short len,113unsigned short proto, __wsum sum)114{115return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum));116}117118/**119* csum_partial - Compute an internet checksum.120* @buff: buffer to be checksummed121* @len: length of buffer.122* @sum: initial sum to be added in (32bit unfolded)123*124* Returns the 32bit unfolded internet checksum of the buffer.125* Before filling it in it needs to be csum_fold()'ed.126* buff should be aligned to a 64bit boundary if possible.127*/128extern __wsum csum_partial(const void *buff, int len, __wsum sum);129130#define _HAVE_ARCH_COPY_AND_CSUM_FROM_USER 1131#define HAVE_CSUM_COPY_USER 1132133134/* Do not call this directly. Use the wrappers below */135extern __wsum csum_partial_copy_generic(const void *src, const void *dst,136int len, __wsum sum,137int *src_err_ptr, int *dst_err_ptr);138139140extern __wsum csum_partial_copy_from_user(const void __user *src, void *dst,141int len, __wsum isum, int *errp);142extern __wsum csum_partial_copy_to_user(const void *src, void __user *dst,143int len, __wsum isum, int *errp);144extern __wsum csum_partial_copy_nocheck(const void *src, void *dst,145int len, __wsum sum);146147/* Old names. To be removed. */148#define csum_and_copy_to_user csum_partial_copy_to_user149#define csum_and_copy_from_user csum_partial_copy_from_user150151/**152* ip_compute_csum - Compute an 16bit IP checksum.153* @buff: buffer address.154* @len: length of buffer.155*156* Returns the 16bit folded/inverted checksum of the passed buffer.157* Ready to fill in.158*/159extern __sum16 ip_compute_csum(const void *buff, int len);160161/**162* csum_ipv6_magic - Compute checksum of an IPv6 pseudo header.163* @saddr: source address164* @daddr: destination address165* @len: length of packet166* @proto: protocol of packet167* @sum: initial sum (32bit unfolded) to be added in168*169* Computes an IPv6 pseudo header checksum. This sum is added the checksum170* into UDP/TCP packets and contains some link layer information.171* Returns the unfolded 32bit checksum.172*/173174struct in6_addr;175176#define _HAVE_ARCH_IPV6_CSUM 1177extern __sum16178csum_ipv6_magic(const struct in6_addr *saddr, const struct in6_addr *daddr,179__u32 len, unsigned short proto, __wsum sum);180181static inline unsigned add32_with_carry(unsigned a, unsigned b)182{183asm("addl %2,%0\n\t"184"adcl $0,%0"185: "=r" (a)186: "0" (a), "r" (b));187return a;188}189190#endif /* _ASM_X86_CHECKSUM_64_H */191192193