]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - arch/x86/include/asm/checksum_32.h
License cleanup: add SPDX GPL-2.0 license identifier to files with no license
[mirror_ubuntu-bionic-kernel.git] / arch / x86 / include / asm / checksum_32.h
CommitLineData
b2441318 1/* SPDX-License-Identifier: GPL-2.0 */
1965aae3
PA
2#ifndef _ASM_X86_CHECKSUM_32_H
3#define _ASM_X86_CHECKSUM_32_H
1da177e4
LT
4
5#include <linux/in6.h>
13d4ea09 6#include <linux/uaccess.h>
a9ed8817 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,
01cfbad7 115 __u32 len, __u8 proto,
0883e91a 116 __wsum sum)
1da177e4 117{
0883e91a
JP
118 asm("addl %1, %0 ;\n"
119 "adcl %2, %0 ;\n"
120 "adcl %3, %0 ;\n"
121 "adcl $0, %0 ;\n"
122 : "=r" (sum)
123 : "g" (daddr), "g"(saddr),
124 "g" ((len + proto) << 8), "0" (sum));
125 return sum;
1da177e4
LT
126}
127
128/*
129 * computes the checksum of the TCP/UDP pseudo-header
130 * returns a 16-bit checksum, already complemented
131 */
72685fcd 132static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
01cfbad7 133 __u32 len, __u8 proto,
0883e91a 134 __wsum sum)
1da177e4 135{
0883e91a 136 return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum));
1da177e4
LT
137}
138
139/*
140 * this routine is used for miscellaneous IP-like checksums, mainly
141 * in icmp.c
142 */
143
72685fcd 144static inline __sum16 ip_compute_csum(const void *buff, int len)
1da177e4 145{
0883e91a 146 return csum_fold(csum_partial(buff, len, 0));
1da177e4
LT
147}
148
149#define _HAVE_ARCH_IPV6_CSUM
0883e91a
JP
150static inline __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
151 const struct in6_addr *daddr,
1e940829 152 __u32 len, __u8 proto, __wsum sum)
1da177e4 153{
0883e91a
JP
154 asm("addl 0(%1), %0 ;\n"
155 "adcl 4(%1), %0 ;\n"
156 "adcl 8(%1), %0 ;\n"
157 "adcl 12(%1), %0 ;\n"
158 "adcl 0(%2), %0 ;\n"
159 "adcl 4(%2), %0 ;\n"
160 "adcl 8(%2), %0 ;\n"
161 "adcl 12(%2), %0 ;\n"
162 "adcl %3, %0 ;\n"
163 "adcl %4, %0 ;\n"
164 "adcl $0, %0 ;\n"
165 : "=&r" (sum)
166 : "r" (saddr), "r" (daddr),
392d814d
ST
167 "r" (htonl(len)), "r" (htonl(proto)), "0" (sum)
168 : "memory");
1da177e4
LT
169
170 return csum_fold(sum);
171}
172
173/*
174 * Copy and checksum to user
175 */
176#define HAVE_CSUM_COPY_USER
0883e91a
JP
177static inline __wsum csum_and_copy_to_user(const void *src,
178 void __user *dst,
179 int len, __wsum sum,
180 int *err_ptr)
1da177e4 181{
7263dda4
PA
182 __wsum ret;
183
1da177e4 184 might_sleep();
7263dda4
PA
185 if (access_ok(VERIFY_WRITE, dst, len)) {
186 stac();
187 ret = csum_partial_copy_generic(src, (__force void *)dst,
188 len, sum, NULL, err_ptr);
189 clac();
190 return ret;
191 }
1da177e4
LT
192
193 if (len)
194 *err_ptr = -EFAULT;
195
72685fcd 196 return (__force __wsum)-1; /* invalid checksum */
1da177e4
LT
197}
198
1965aae3 199#endif /* _ASM_X86_CHECKSUM_32_H */