cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

csum_partial_copy.c (2063B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Network Checksum & Copy routine
      4 *
      5 * Copyright (C) 1999, 2003-2004 Hewlett-Packard Co
      6 *	Stephane Eranian <eranian@hpl.hp.com>
      7 *
      8 * Most of the code has been imported from Linux/Alpha
      9 */
     10
     11#include <linux/module.h>
     12#include <linux/types.h>
     13#include <linux/string.h>
     14
     15#include <net/checksum.h>
     16
     17/*
     18 * XXX Fixme: those 2 inlines are meant for debugging and will go away
     19 */
     20static inline unsigned
     21short from64to16(unsigned long x)
     22{
     23	/* add up 32-bit words for 33 bits */
     24	x = (x & 0xffffffff) + (x >> 32);
     25	/* add up 16-bit and 17-bit words for 17+c bits */
     26	x = (x & 0xffff) + (x >> 16);
     27	/* add up 16-bit and 2-bit for 16+c bit */
     28	x = (x & 0xffff) + (x >> 16);
     29	/* add up carry.. */
     30	x = (x & 0xffff) + (x >> 16);
     31	return x;
     32}
     33
     34static inline
     35unsigned long do_csum_c(const unsigned char * buff, int len, unsigned int psum)
     36{
     37	int odd, count;
     38	unsigned long result = (unsigned long)psum;
     39
     40	if (len <= 0)
     41		goto out;
     42	odd = 1 & (unsigned long) buff;
     43	if (odd) {
     44		result = *buff << 8;
     45		len--;
     46		buff++;
     47	}
     48	count = len >> 1;		/* nr of 16-bit words.. */
     49	if (count) {
     50		if (2 & (unsigned long) buff) {
     51			result += *(unsigned short *) buff;
     52			count--;
     53			len -= 2;
     54			buff += 2;
     55		}
     56		count >>= 1;		/* nr of 32-bit words.. */
     57		if (count) {
     58			if (4 & (unsigned long) buff) {
     59				result += *(unsigned int *) buff;
     60				count--;
     61				len -= 4;
     62				buff += 4;
     63			}
     64			count >>= 1;	/* nr of 64-bit words.. */
     65			if (count) {
     66				unsigned long carry = 0;
     67				do {
     68					unsigned long w = *(unsigned long *) buff;
     69					count--;
     70					buff += 8;
     71					result += carry;
     72					result += w;
     73					carry = (w > result);
     74				} while (count);
     75				result += carry;
     76				result = (result & 0xffffffff) + (result >> 32);
     77			}
     78			if (len & 4) {
     79				result += *(unsigned int *) buff;
     80				buff += 4;
     81			}
     82		}
     83		if (len & 2) {
     84			result += *(unsigned short *) buff;
     85			buff += 2;
     86		}
     87	}
     88	if (len & 1)
     89		result += *buff;
     90
     91	result = from64to16(result);
     92
     93	if (odd)
     94		result = ((result >> 8) & 0xff) | ((result & 0xff) << 8);
     95
     96out:
     97	return result;
     98}