Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
checksum_64.h
Go to the documentation of this file.
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 
22 static 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 <[email protected]>, adapted for linux by
37  * Arnt Gulbrandsen.
38  */
39 
45 static 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 
86 static inline __wsum
87 csum_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 
112 static 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 
129 extern __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 */
136 extern __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 
141 extern __wsum csum_partial_copy_from_user(const void __user *src, void *dst,
142  int len, __wsum isum, int *errp);
143 extern __wsum csum_partial_copy_to_user(const void *src, void __user *dst,
144  int len, __wsum isum, int *errp);
145 extern __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 
160 extern __sum16 ip_compute_csum(const void *buff, int len);
161 
175 struct in6_addr;
176 
177 #define _HAVE_ARCH_IPV6_CSUM 1
178 extern __sum16
179 csum_ipv6_magic(const struct in6_addr *saddr, const struct in6_addr *daddr,
180  __u32 len, unsigned short proto, __wsum sum);
181 
182 static 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 */