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