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