]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - arch/x86/include/asm/checksum_32.h
UBUNTU: Ubuntu-4.13.0-45.50
[mirror_ubuntu-artful-kernel.git] / arch / x86 / include / asm / checksum_32.h
CommitLineData
1965aae3
PA
1#ifndef _ASM_X86_CHECKSUM_32_H
2#define _ASM_X86_CHECKSUM_32_H
1da177e4
LT
3
4#include <linux/in6.h>
13d4ea09 5#include <linux/uaccess.h>
a9ed8817 6
1da177e4
LT
7/*
8 * computes the checksum of a memory block at buff, length len,
9 * and adds in "sum" (32-bit)
10 *
11 * returns a 32-bit number suitable for feeding into itself
12 * or csum_tcpudp_magic
13 *
14 * this function must be called with even lengths, except
15 * for the last fragment, which may be odd
16 *
17 * it's best to have buff aligned on a 32-bit boundary
18 */
72685fcd 19asmlinkage __wsum csum_partial(const void *buff, int len, __wsum sum);
1da177e4
LT
20
21/*
22 * the same as csum_partial, but copies from src while it
23 * checksums, and handles user-space pointer exceptions correctly, when needed.
24 *
25 * here even more important to align src and dst on a 32-bit (or even
26 * better 64-bit) boundary
27 */
28
72685fcd 29asmlinkage __wsum csum_partial_copy_generic(const void *src, void *dst,
0883e91a
JP
30 int len, __wsum sum,
31 int *src_err_ptr, int *dst_err_ptr);
1da177e4
LT
32
33/*
34 * Note: when you get a NULL pointer exception here this means someone
35 * passed in an incorrect kernel address to one of these functions.
36 *
37 * If you use these functions directly please don't forget the
e49332bd 38 * access_ok().
1da177e4 39 */
0883e91a
JP
40static inline __wsum csum_partial_copy_nocheck(const void *src, void *dst,
41 int len, __wsum sum)
1da177e4 42{
0883e91a 43 return csum_partial_copy_generic(src, dst, len, sum, NULL, NULL);
1da177e4
LT
44}
45
0883e91a
JP
46static inline __wsum csum_partial_copy_from_user(const void __user *src,
47 void *dst,
48 int len, __wsum sum,
49 int *err_ptr)
1da177e4 50{
7263dda4
PA
51 __wsum ret;
52
1da177e4 53 might_sleep();
7263dda4
PA
54 stac();
55 ret = csum_partial_copy_generic((__force void *)src, dst,
56 len, sum, err_ptr, NULL);
57 clac();
58
59 return ret;
1da177e4
LT
60}
61
62/*
63 * This is a version of ip_compute_csum() optimized for IP headers,
64 * which always checksum on 4 octet boundaries.
65 *
66 * By Jorge Cwik <jorge@laser.satlink.net>, adapted for linux by
67 * Arnt Gulbrandsen.
68 */
72685fcd 69static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
1da177e4
LT
70{
71 unsigned int sum;
72
0883e91a
JP
73 asm volatile("movl (%1), %0 ;\n"
74 "subl $4, %2 ;\n"
75 "jbe 2f ;\n"
76 "addl 4(%1), %0 ;\n"
77 "adcl 8(%1), %0 ;\n"
78 "adcl 12(%1), %0;\n"
79 "1: adcl 16(%1), %0 ;\n"
80 "lea 4(%1), %1 ;\n"
81 "decl %2 ;\n"
82 "jne 1b ;\n"
83 "adcl $0, %0 ;\n"
84 "movl %0, %2 ;\n"
85 "shrl $16, %0 ;\n"
86 "addw %w2, %w0 ;\n"
87 "adcl $0, %0 ;\n"
88 "notl %0 ;\n"
89 "2: ;\n"
2c656491 90 /* Since the input registers which are loaded with iph and ihl
1da177e4
LT
91 are modified, we must also specify them as outputs, or gcc
92 will assume they contain their original values. */
0883e91a
JP
93 : "=r" (sum), "=r" (iph), "=r" (ihl)
94 : "1" (iph), "2" (ihl)
95 : "memory");
72685fcd 96 return (__force __sum16)sum;
1da177e4
LT
97}
98
99/*
100 * Fold a partial checksum
101 */
102
72685fcd 103static inline __sum16 csum_fold(__wsum sum)
1da177e4 104{
0883e91a
JP
105 asm("addl %1, %0 ;\n"
106 "adcl $0xffff, %0 ;\n"
107 : "=r" (sum)
108 : "r" ((__force u32)sum << 16),
109 "0" ((__force u32)sum & 0xffff0000));
72685fcd 110 return (__force __sum16)(~(__force u32)sum >> 16);
1da177e4
LT
111}
112
72685fcd 113static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
01cfbad7 114 __u32 len, __u8 proto,
0883e91a 115 __wsum sum)
1da177e4 116{
0883e91a
JP
117 asm("addl %1, %0 ;\n"
118 "adcl %2, %0 ;\n"
119 "adcl %3, %0 ;\n"
120 "adcl $0, %0 ;\n"
121 : "=r" (sum)
122 : "g" (daddr), "g"(saddr),
123 "g" ((len + proto) << 8), "0" (sum));
124 return sum;
1da177e4
LT
125}
126
127/*
128 * computes the checksum of the TCP/UDP pseudo-header
129 * returns a 16-bit checksum, already complemented
130 */
72685fcd 131static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
01cfbad7 132 __u32 len, __u8 proto,
0883e91a 133 __wsum sum)
1da177e4 134{
0883e91a 135 return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum));
1da177e4
LT
136}
137
138/*
139 * this routine is used for miscellaneous IP-like checksums, mainly
140 * in icmp.c
141 */
142
72685fcd 143static inline __sum16 ip_compute_csum(const void *buff, int len)
1da177e4 144{
0883e91a 145 return csum_fold(csum_partial(buff, len, 0));
1da177e4
LT
146}
147
148#define _HAVE_ARCH_IPV6_CSUM
0883e91a
JP
149static inline __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
150 const struct in6_addr *daddr,
1e940829 151 __u32 len, __u8 proto, __wsum sum)
1da177e4 152{
0883e91a
JP
153 asm("addl 0(%1), %0 ;\n"
154 "adcl 4(%1), %0 ;\n"
155 "adcl 8(%1), %0 ;\n"
156 "adcl 12(%1), %0 ;\n"
157 "adcl 0(%2), %0 ;\n"
158 "adcl 4(%2), %0 ;\n"
159 "adcl 8(%2), %0 ;\n"
160 "adcl 12(%2), %0 ;\n"
161 "adcl %3, %0 ;\n"
162 "adcl %4, %0 ;\n"
163 "adcl $0, %0 ;\n"
164 : "=&r" (sum)
165 : "r" (saddr), "r" (daddr),
392d814d
ST
166 "r" (htonl(len)), "r" (htonl(proto)), "0" (sum)
167 : "memory");
1da177e4
LT
168
169 return csum_fold(sum);
170}
171
172/*
173 * Copy and checksum to user
174 */
175#define HAVE_CSUM_COPY_USER
0883e91a
JP
176static inline __wsum csum_and_copy_to_user(const void *src,
177 void __user *dst,
178 int len, __wsum sum,
179 int *err_ptr)
1da177e4 180{
7263dda4
PA
181 __wsum ret;
182
1da177e4 183 might_sleep();
7263dda4
PA
184 if (access_ok(VERIFY_WRITE, dst, len)) {
185 stac();
186 ret = csum_partial_copy_generic(src, (__force void *)dst,
187 len, sum, NULL, err_ptr);
188 clac();
189 return ret;
190 }
1da177e4
LT
191
192 if (len)
193 *err_ptr = -EFAULT;
194
72685fcd 195 return (__force __wsum)-1; /* invalid checksum */
1da177e4
LT
196}
197
1965aae3 198#endif /* _ASM_X86_CHECKSUM_32_H */