linux/arch/x86/include/asm/checksum_64.h
<<
>>
Prefs
   1#ifndef _ASM_X86_CHECKSUM_64_H
   2#define _ASM_X86_CHECKSUM_64_H
   3
   4/*
   5 * Checksums for x86-64
   6 * Copyright 2002 by Andi Kleen, SuSE Labs
   7 * with some code from asm-x86/checksum.h
   8 */
   9
  10#include <linux/compiler.h>
  11#include <asm/uaccess.h>
  12#include <asm/byteorder.h>
  13
  14/**
  15 * csum_fold - Fold and invert a 32bit checksum.
  16 * sum: 32bit unfolded sum
  17 *
  18 * Fold a 32bit running checksum to 16bit and invert it. This is usually
  19 * the last step before putting a checksum into a packet.
  20 * Make sure not to mix with 64bit checksums.
  21 */
  22static inline __sum16 csum_fold(__wsum sum)
  23{
  24        asm("  addl %1,%0\n"
  25            "  adcl $0xffff,%0"
  26            : "=r" (sum)
  27            : "r" ((__force u32)sum << 16),
  28              "0" ((__force u32)sum & 0xffff0000));
  29        return (__force __sum16)(~(__force u32)sum >> 16);
  30}
  31
  32/*
  33 *      This is a version of ip_compute_csum() optimized for IP headers,
  34 *      which always checksum on 4 octet boundaries.
  35 *
  36 *      By Jorge Cwik <jorge@laser.satlink.net>, adapted for linux by
  37 *      Arnt Gulbrandsen.
  38 */
  39
  40/**
  41 * ip_fast_csum - Compute the IPv4 header checksum efficiently.
  42 * iph: ipv4 header
  43 * ihl: length of header / 4
  44 */
  45static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
  46{
  47        unsigned int sum;
  48
  49        asm("  movl (%1), %0\n"
  50            "  subl $4, %2\n"
  51            "  jbe 2f\n"
  52            "  addl 4(%1), %0\n"
  53            "  adcl 8(%1), %0\n"
  54            "  adcl 12(%1), %0\n"
  55            "1: adcl 16(%1), %0\n"
  56            "  lea 4(%1), %1\n"
  57            "  decl %2\n"
  58            "  jne      1b\n"
  59            "  adcl $0, %0\n"
  60            "  movl %0, %2\n"
  61            "  shrl $16, %0\n"
  62            "  addw %w2, %w0\n"
  63            "  adcl $0, %0\n"
  64            "  notl %0\n"
  65            "2:"
  66        /* Since the input registers which are loaded with iph and ihl
  67           are modified, we must also specify them as outputs, or gcc
  68           will assume they contain their original values. */
  69            : "=r" (sum), "=r" (iph), "=r" (ihl)
  70            : "1" (iph), "2" (ihl)
  71            : "memory");
  72        return (__force __sum16)sum;
  73}
  74
  75/**
  76 * csum_tcpup_nofold - Compute an IPv4 pseudo header checksum.
  77 * @saddr: source address
  78 * @daddr: destination address
  79 * @len: length of packet
  80 * @proto: ip protocol of packet
  81 * @sum: initial sum to be added in (32bit unfolded)
  82 *
  83 * Returns the pseudo header checksum the input data. Result is
  84 * 32bit unfolded.
  85 */
  86static inline __wsum
  87csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len,
  88                   unsigned short proto, __wsum sum)
  89{
  90        asm("  addl %1, %0\n"
  91            "  adcl %2, %0\n"
  92            "  adcl %3, %0\n"
  93            "  adcl $0, %0\n"
  94            : "=r" (sum)
  95            : "g" (daddr), "g" (saddr),
  96              "g" ((len + proto)<<8), "0" (sum));
  97        return sum;
  98}
  99
 100
 101/**
 102 * csum_tcpup_magic - Compute an IPv4 pseudo header checksum.
 103 * @saddr: source address
 104 * @daddr: destination address
 105 * @len: length of packet
 106 * @proto: ip protocol of packet
 107 * @sum: initial sum to be added in (32bit unfolded)
 108 *
 109 * Returns the 16bit pseudo header checksum the input data already
 110 * complemented and ready to be filled in.
 111 */
 112static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
 113                                        unsigned short len,
 114                                        unsigned short proto, __wsum sum)
 115{
 116        return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum));
 117}
 118
 119/**
 120 * csum_partial - Compute an internet checksum.
 121 * @buff: buffer to be checksummed
 122 * @len: length of buffer.
 123 * @sum: initial sum to be added in (32bit unfolded)
 124 *
 125 * Returns the 32bit unfolded internet checksum of the buffer.
 126 * Before filling it in it needs to be csum_fold()'ed.
 127 * buff should be aligned to a 64bit boundary if possible.
 128 */
 129extern __wsum csum_partial(const void *buff, int len, __wsum sum);
 130
 131#define  _HAVE_ARCH_COPY_AND_CSUM_FROM_USER 1
 132#define HAVE_CSUM_COPY_USER 1
 133
 134
 135/* Do not call this directly. Use the wrappers below */
 136extern __visible __wsum csum_partial_copy_generic(const void *src, const void *dst,
 137                                        int len, __wsum sum,
 138                                        int *src_err_ptr, int *dst_err_ptr);
 139
 140
 141extern __wsum csum_partial_copy_from_user(const void __user *src, void *dst,
 142                                          int len, __wsum isum, int *errp);
 143extern __wsum csum_partial_copy_to_user(const void *src, void __user *dst,
 144                                        int len, __wsum isum, int *errp);
 145extern __wsum csum_partial_copy_nocheck(const void *src, void *dst,
 146                                        int len, __wsum sum);
 147
 148/* Old names. To be removed. */
 149#define csum_and_copy_to_user csum_partial_copy_to_user
 150#define csum_and_copy_from_user csum_partial_copy_from_user
 151
 152/**
 153 * ip_compute_csum - Compute an 16bit IP checksum.
 154 * @buff: buffer address.
 155 * @len: length of buffer.
 156 *
 157 * Returns the 16bit folded/inverted checksum of the passed buffer.
 158 * Ready to fill in.
 159 */
 160extern __sum16 ip_compute_csum(const void *buff, int len);
 161
 162/**
 163 * csum_ipv6_magic - Compute checksum of an IPv6 pseudo header.
 164 * @saddr: source address
 165 * @daddr: destination address
 166 * @len: length of packet
 167 * @proto: protocol of packet
 168 * @sum: initial sum (32bit unfolded) to be added in
 169 *
 170 * Computes an IPv6 pseudo header checksum. This sum is added the checksum
 171 * into UDP/TCP packets and contains some link layer information.
 172 * Returns the unfolded 32bit checksum.
 173 */
 174
 175struct in6_addr;
 176
 177#define _HAVE_ARCH_IPV6_CSUM 1
 178extern __sum16
 179csum_ipv6_magic(const struct in6_addr *saddr, const struct in6_addr *daddr,
 180                __u32 len, unsigned short proto, __wsum sum);
 181
 182static inline unsigned add32_with_carry(unsigned a, unsigned b)
 183{
 184        asm("addl %2,%0\n\t"
 185            "adcl $0,%0"
 186            : "=r" (a)
 187            : "0" (a), "r" (b));
 188        return a;
 189}
 190
 191#endif /* _ASM_X86_CHECKSUM_64_H */
 192