vfs: Remove KFS, blockdev and devfs
[akaros.git] / kern / src / net / ptclbsum.c
1 /* Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
2  * Portions Copyright © 1997-1999 Vita Nuova Limited
3  * Portions Copyright © 2000-2007 Vita Nuova Holdings Limited
4  *                                (www.vitanuova.com)
5  * Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
6  *
7  * Modified for the Akaros operating system:
8  * Copyright (c) 2013-2014 The Regents of the University of California
9  * Copyright (c) 2013-2015 Google Inc.
10  *
11  * Permission is hereby granted, free of charge, to any person obtaining a copy
12  * of this software and associated documentation files (the "Software"), to deal
13  * in the Software without restriction, including without limitation the rights
14  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15  * copies of the Software, and to permit persons to whom the Software is
16  * furnished to do so, subject to the following conditions:
17  *
18  * The above copyright notice and this permission notice shall be included in
19  * all copies or substantial portions of the Software.
20  *
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
24  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27  * SOFTWARE. */
28
29 #include <vfs.h>
30 #include <slab.h>
31 #include <kmalloc.h>
32 #include <kref.h>
33 #include <string.h>
34 #include <stdio.h>
35 #include <assert.h>
36 #include <error.h>
37 #include <cpio.h>
38 #include <pmap.h>
39 #include <smp.h>
40 #include <net/ip.h>
41 #include <endian.h>
42
43 static short endian = 1;
44 static uint8_t *aendian = (uint8_t *) & endian;
45 #define LITTLE  *aendian
46
47
48 #ifdef CONFIG_X86
49
50 /* $NetBSD: in_cksum.c,v 1.7 1997/09/02 13:18:15 thorpej Exp $ */
51
52 /*-
53  * Copyright (c) 1988, 1992, 1993
54  *      The Regents of the University of California.  All rights reserved.
55  * Copyright (c) 1996
56  *      Matt Thomas <matt@3am-software.com>
57  *
58  * Redistribution and use in source and binary forms, with or without
59  * modification, are permitted provided that the following conditions
60  * are met:
61  * 1. Redistributions of source code must retain the above copyright
62  *    notice, this list of conditions and the following disclaimer.
63  * 2. Redistributions in binary form must reproduce the above copyright
64  *    notice, this list of conditions and the following disclaimer in the
65  *    documentation and/or other materials provided with the distribution.
66  * 3. All advertising materials mentioning features or use of this software
67  *    must display the following acknowledgement:
68  *      This product includes software developed by the University of
69  *      California, Berkeley and its contributors.
70  * 4. Neither the name of the University nor the names of its contributors
71  *    may be used to endorse or promote products derived from this software
72  *    without specific prior written permission.
73  *
74  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
75  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
76  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
77  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
78  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
79  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
80  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
81  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
82  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
83  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
84  * SUCH DAMAGE.
85  *
86  *      @(#)in_cksum.c  8.1 (Berkeley) 6/10/93
87  */
88
89 /*
90  * Checksum routine for Internet Protocol family headers
91  *    (Portable Alpha version).
92  *
93  * This routine is very heavily used in the network
94  * code and should be modified for each CPU to be as fast as possible.
95  */
96
97 #define ADDCARRY(x)  (x > 65535 ? x -= 65535 : x)
98 #define REDUCE32                                                          \
99     {                                                                     \
100         q_util.q = sum;                                                   \
101         sum = q_util.s[0] + q_util.s[1] + q_util.s[2] + q_util.s[3];      \
102     }
103 #define REDUCE16                                                          \
104     {                                                                     \
105         q_util.q = sum;                                                   \
106         l_util.l = q_util.s[0] + q_util.s[1] + q_util.s[2] + q_util.s[3]; \
107         sum = l_util.s[0] + l_util.s[1];                                  \
108         ADDCARRY(sum);                                                    \
109     }
110
111 static const uint32_t in_masks[] = {
112         /*0 bytes*/ /*1 byte*/  /*2 bytes*/ /*3 bytes*/
113         0x00000000, 0x000000FF, 0x0000FFFF, 0x00FFFFFF, /* offset 0 */
114         0x00000000, 0x0000FF00, 0x00FFFF00, 0xFFFFFF00, /* offset 1 */
115         0x00000000, 0x00FF0000, 0xFFFF0000, 0xFFFF0000, /* offset 2 */
116         0x00000000, 0xFF000000, 0xFF000000, 0xFF000000, /* offset 3 */
117 };
118
119 union l_util {
120         uint16_t s[2];
121         uint32_t l;
122 };
123 union q_util {
124         uint16_t s[4];
125         uint32_t l[2];
126         uint64_t q;
127 };
128
129 static uint64_t
130 in_cksumdata(const void *buf, int len)
131 {
132         const uint32_t *lw = (const uint32_t *) buf;
133         uint64_t sum = 0;
134         uint64_t prefilled;
135         int offset;
136         union q_util q_util;
137
138         if ((3 & (long) lw) == 0 && len == 20) {
139              sum = (uint64_t) lw[0] + lw[1] + lw[2] + lw[3] + lw[4];
140              REDUCE32;
141              return sum;
142         }
143
144         if ((offset = 3 & (long) lw) != 0) {
145                 const uint32_t *masks = in_masks + (offset << 2);
146                 lw = (uint32_t *) (((long) lw) - offset);
147                 sum = *lw++ & masks[len >= 3 ? 3 : len];
148                 len -= 4 - offset;
149                 if (len <= 0) {
150                         REDUCE32;
151                         return sum;
152                 }
153         }
154 #if 0
155         /*
156          * Force to cache line boundary.
157          */
158         offset = 32 - (0x1f & (long) lw);
159         if (offset < 32 && len > offset) {
160                 len -= offset;
161                 if (4 & offset) {
162                         sum += (uint64_t) lw[0];
163                         lw += 1;
164                 }
165                 if (8 & offset) {
166                         sum += (uint64_t) lw[0] + lw[1];
167                         lw += 2;
168                 }
169                 if (16 & offset) {
170                         sum += (uint64_t) lw[0] + lw[1] + lw[2] + lw[3];
171                         lw += 4;
172                 }
173         }
174 #endif
175         /*
176          * access prefilling to start load of next cache line.
177          * then add current cache line
178          * save result of prefilling for loop iteration.
179          */
180         prefilled = lw[0];
181         while ((len -= 32) >= 4) {
182                 uint64_t prefilling = lw[8];
183                 sum += prefilled + lw[1] + lw[2] + lw[3]
184                         + lw[4] + lw[5] + lw[6] + lw[7];
185                 lw += 8;
186                 prefilled = prefilling;
187         }
188         if (len >= 0) {
189                 sum += prefilled + lw[1] + lw[2] + lw[3]
190                         + lw[4] + lw[5] + lw[6] + lw[7];
191                 lw += 8;
192         } else {
193                 len += 32;
194         }
195         while ((len -= 16) >= 0) {
196                 sum += (uint64_t) lw[0] + lw[1] + lw[2] + lw[3];
197                 lw += 4;
198         }
199         len += 16;
200         while ((len -= 4) >= 0) {
201                 sum += (uint64_t) *lw++;
202         }
203         len += 4;
204         if (len > 0)
205                 sum += (uint64_t) (in_masks[len] & *lw);
206         REDUCE32;
207         return sum;
208 }
209 uint16_t ptclbsum(uint8_t * addr, int len)
210 {
211         uint64_t sum = in_cksumdata(addr, len);
212         union q_util q_util;
213         union l_util l_util;
214         if ((uintptr_t)addr & 1)
215                 sum <<= 8;
216         REDUCE16;
217         return cpu_to_be16(sum);
218 }
219 #else
220 uint16_t ptclbsum(uint8_t * addr, int len)
221 {
222         uint32_t losum, hisum, mdsum, x;
223         uint32_t t1, t2;
224
225         losum = 0;
226         hisum = 0;
227         mdsum = 0;
228
229         x = 0;
230         if ((uintptr_t) addr & 1) {
231                 if (len) {
232                         hisum += addr[0];
233                         len--;
234                         addr++;
235                 }
236                 x = 1;
237         }
238         while (len >= 16) {
239                 t1 = *(uint16_t *) (addr + 0);
240                 t2 = *(uint16_t *) (addr + 2);
241                 mdsum += t1;
242                 t1 = *(uint16_t *) (addr + 4);
243                 mdsum += t2;
244                 t2 = *(uint16_t *) (addr + 6);
245                 mdsum += t1;
246                 t1 = *(uint16_t *) (addr + 8);
247                 mdsum += t2;
248                 t2 = *(uint16_t *) (addr + 10);
249                 mdsum += t1;
250                 t1 = *(uint16_t *) (addr + 12);
251                 mdsum += t2;
252                 t2 = *(uint16_t *) (addr + 14);
253                 mdsum += t1;
254                 mdsum += t2;
255                 len -= 16;
256                 addr += 16;
257         }
258         while (len >= 2) {
259                 mdsum += *(uint16_t *) addr;
260                 len -= 2;
261                 addr += 2;
262         }
263         if (x) {
264                 if (len)
265                         losum += addr[0];
266                 if (LITTLE)
267                         losum += mdsum;
268                 else
269                         hisum += mdsum;
270         } else {
271                 if (len)
272                         hisum += addr[0];
273                 if (LITTLE)
274                         hisum += mdsum;
275                 else
276                         losum += mdsum;
277         }
278
279         losum += hisum >> 8;
280         losum += (hisum & 0xff) << 8;
281         while ((hisum = losum >> 16))
282                 losum = hisum + (losum & 0xffff);
283
284         return losum & 0xffff;
285 }
286 #endif