~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/include/asm-mips/checksum.h

Version: ~ [ linux-5.13-rc5 ] ~ [ linux-5.12.9 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.42 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.124 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.193 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.235 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.271 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.271 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.18.140 ] ~ [ linux-3.16.85 ] ~ [ linux-3.14.79 ] ~ [ linux-3.12.74 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * This file is subject to the terms and conditions of the GNU General Public
  3  * License.  See the file "COPYING" in the main directory of this archive
  4  * for more details.
  5  *
  6  * Copyright (C) 1995, 96, 97, 98, 99, 2001 by Ralf Baechle
  7  * Copyright (C) 1999 Silicon Graphics, Inc.
  8  * Copyright (C) 2001 Thiemo Seufer.
  9  * Copyright (C) 2002 Maciej W. Rozycki
 10  */
 11 #ifndef _ASM_CHECKSUM_H
 12 #define _ASM_CHECKSUM_H
 13 
 14 #include <linux/config.h>
 15 #include <linux/in6.h>
 16 
 17 #include <asm/uaccess.h>
 18 
 19 /*
 20  * computes the checksum of a memory block at buff, length len,
 21  * and adds in "sum" (32-bit)
 22  *
 23  * returns a 32-bit number suitable for feeding into itself
 24  * or csum_tcpudp_magic
 25  *
 26  * this function must be called with even lengths, except
 27  * for the last fragment, which may be odd
 28  *
 29  * it's best to have buff aligned on a 32-bit boundary
 30  */
 31 unsigned int csum_partial(const unsigned char *buff, int len, unsigned int sum);
 32 
 33 /*
 34  * this is a new version of the above that records errors it finds in *errp,
 35  * but continues and zeros the rest of the buffer.
 36  */
 37 unsigned int csum_partial_copy_from_user(const char *src, char *dst, int len,
 38                                          unsigned int sum, int *errp);
 39 
 40 /*
 41  * Copy and checksum to user
 42  */
 43 #define HAVE_CSUM_COPY_USER
 44 static inline unsigned int csum_and_copy_to_user (const char *src, char *dst,
 45                                                   int len, int sum,
 46                                                   int *err_ptr)
 47 {
 48         sum = csum_partial(src, len, sum);
 49 
 50         if (copy_to_user(dst, src, len)) {
 51                 *err_ptr = -EFAULT;
 52                 return -1;
 53         }
 54 
 55         return sum;
 56 }
 57 
 58 /*
 59  * the same as csum_partial, but copies from user space (but on MIPS
 60  * we have just one address space, so this is identical to the above)
 61  */
 62 unsigned int csum_partial_copy_nocheck(const char *src, char *dst, int len,
 63                                        unsigned int sum);
 64 
 65 /*
 66  *      Fold a partial checksum without adding pseudo headers
 67  */
 68 static inline unsigned short int csum_fold(unsigned int sum)
 69 {
 70         __asm__(
 71         ".set\tnoat\t\t\t# csum_fold\n\t"
 72         "sll\t$1,%0,16\n\t"
 73         "addu\t%0,$1\n\t"
 74         "sltu\t$1,%0,$1\n\t"
 75         "srl\t%0,%0,16\n\t"
 76         "addu\t%0,$1\n\t"
 77         "xori\t%0,0xffff\n\t"
 78         ".set\tat"
 79         : "=r" (sum)
 80         : "" (sum));
 81 
 82         return sum;
 83 }
 84 
 85 /*
 86  *      This is a version of ip_compute_csum() optimized for IP headers,
 87  *      which always checksum on 4 octet boundaries.
 88  *
 89  *      By Jorge Cwik <jorge@laser.satlink.net>, adapted for linux by
 90  *      Arnt Gulbrandsen.
 91  */
 92 static inline unsigned short ip_fast_csum(unsigned char *iph,
 93                                           unsigned int ihl)
 94 {
 95         unsigned int dummy, sum;
 96 
 97         /*
 98          * This is for 32-bit processors ...  but works just fine for 64-bit
 99          * processors for now ...  XXX
100          */
101         __asm__ __volatile__(
102         ".set\tnoreorder\t\t\t# ip_fast_csum\n\t"
103         ".set\tnoat\n\t"
104         "lw\t%0, (%1)\n\t"
105         "subu\t%2, 4\n\t"
106         "sll\t%2, 2\n\t"
107         "lw\t%3, 4(%1)\n\t"
108         "addu\t%2, %1\n\t"
109         "addu\t%0, %3\n\t"
110         "sltu\t$1, %0, %3\n\t"
111         "lw\t%3, 8(%1)\n\t"
112         "addu\t%0, $1\n\t"
113         "addu\t%0, %3\n\t"
114         "sltu\t$1, %0, %3\n\t"
115         "lw\t%3, 12(%1)\n\t"
116         "addu\t%0, $1\n\t"
117         "addu\t%0, %3\n\t"
118         "sltu\t$1, %0, %3\n\t"
119         "addu\t%0, $1\n"
120 
121         "1:\tlw\t%3, 16(%1)\n\t"
122         "addiu\t%1, 4\n\t"
123         "addu\t%0, %3\n\t"
124         "sltu\t$1, %0, %3\n\t"
125         "bne\t%2, %1, 1b\n\t"
126         " addu\t%0, $1\n"
127 
128         "2:\t.set\tat\n\t"
129         ".set\treorder"
130         : "=&r" (sum), "=&r" (iph), "=&r" (ihl), "=&r" (dummy)
131         : "1" (iph), "2" (ihl));
132 
133         return csum_fold(sum);
134 }
135 
136 /*
137  * computes the checksum of the TCP/UDP pseudo-header
138  * returns a 16-bit checksum, already complemented
139  */
140 static inline unsigned int csum_tcpudp_nofold(unsigned int saddr,
141         unsigned int daddr, unsigned short len, unsigned short proto,
142         unsigned int sum)
143 {
144         __asm__(
145         ".set\tnoat\t\t\t# csum_tcpudp_nofold\n\t"
146 #ifdef CONFIG_MIPS32
147         "addu\t%0, %2\n\t"
148         "sltu\t$1, %0, %2\n\t"
149         "addu\t%0, $1\n\t"
150 
151         "addu\t%0, %3\n\t"
152         "sltu\t$1, %0, %3\n\t"
153         "addu\t%0, $1\n\t"
154 
155         "addu\t%0, %4\n\t"
156         "sltu\t$1, %0, %4\n\t"
157         "addu\t%0, $1\n\t"
158 #endif
159 #ifdef CONFIG_MIPS64
160         "daddu\t%0, %2\n\t"
161         "daddu\t%0, %3\n\t"
162         "daddu\t%0, %4\n\t"
163         "dsll32\t$1, %0, 0\n\t"
164         "daddu\t%0, $1\n\t"
165         "dsrl32\t%0, %0, 0\n\t"
166 #endif
167         ".set\tat"
168         : "=r" (sum)
169         : "" (daddr), "r"(saddr),
170 #ifdef __MIPSEL__
171           "r" ((ntohs(len)<<16)+proto*256),
172 #else
173           "r" (((proto)<<16)+len),
174 #endif
175           "r" (sum));
176 
177         return sum;
178 }
179 
180 /*
181  * computes the checksum of the TCP/UDP pseudo-header
182  * returns a 16-bit checksum, already complemented
183  */
184 static inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
185                                                    unsigned long daddr,
186                                                    unsigned short len,
187                                                    unsigned short proto,
188                                                    unsigned int sum)
189 {
190         return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum));
191 }
192 
193 /*
194  * this routine is used for miscellaneous IP-like checksums, mainly
195  * in icmp.c
196  */
197 static inline unsigned short ip_compute_csum(unsigned char * buff, int len)
198 {
199         return csum_fold(csum_partial(buff, len, 0));
200 }
201 
202 #define _HAVE_ARCH_IPV6_CSUM
203 static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
204                                                      struct in6_addr *daddr,
205                                                      __u32 len,
206                                                      unsigned short proto,
207                                                      unsigned int sum)
208 {
209         __asm__(
210         ".set\tpush\t\t\t# csum_ipv6_magic\n\t"
211         ".set\tnoreorder\n\t"
212         ".set\tnoat\n\t"
213         "addu\t%0, %5\t\t\t# proto (long in network byte order)\n\t"
214         "sltu\t$1, %0, %5\n\t"
215         "addu\t%0, $1\n\t"
216 
217         "addu\t%0, %6\t\t\t# csum\n\t"
218         "sltu\t$1, %0, %6\n\t"
219         "lw\t%1, 0(%2)\t\t\t# four words source address\n\t"
220         "addu\t%0, $1\n\t"
221         "addu\t%0, %1\n\t"
222         "sltu\t$1, %0, %1\n\t"
223 
224         "lw\t%1, 4(%2)\n\t"
225         "addu\t%0, $1\n\t"
226         "addu\t%0, %1\n\t"
227         "sltu\t$1, %0, %1\n\t"
228 
229         "lw\t%1, 8(%2)\n\t"
230         "addu\t%0, $1\n\t"
231         "addu\t%0, %1\n\t"
232         "sltu\t$1, %0, %1\n\t"
233 
234         "lw\t%1, 12(%2)\n\t"
235         "addu\t%0, $1\n\t"
236         "addu\t%0, %1\n\t"
237         "sltu\t$1, %0, %1\n\t"
238 
239         "lw\t%1, 0(%3)\n\t"
240         "addu\t%0, $1\n\t"
241         "addu\t%0, %1\n\t"
242         "sltu\t$1, %0, %1\n\t"
243 
244         "lw\t%1, 4(%3)\n\t"
245         "addu\t%0, $1\n\t"
246         "addu\t%0, %1\n\t"
247         "sltu\t$1, %0, %1\n\t"
248 
249         "lw\t%1, 8(%3)\n\t"
250         "addu\t%0, $1\n\t"
251         "addu\t%0, %1\n\t"
252         "sltu\t$1, %0, %1\n\t"
253 
254         "lw\t%1, 12(%3)\n\t"
255         "addu\t%0, $1\n\t"
256         "addu\t%0, %1\n\t"
257         "sltu\t$1, %0, %1\n\t"
258 
259         "addu\t%0, $1\t\t\t# Add final carry\n\t"
260         ".set\tpop"
261         : "=r" (sum), "=r" (proto)
262         : "r" (saddr), "r" (daddr),
263           "" (htonl(len)), "1" (htonl(proto)), "r" (sum));
264 
265         return csum_fold(sum);
266 }
267 
268 #endif /* _ASM_CHECKSUM_H */
269 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp