-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathchecksum.h
67 lines (59 loc) · 1.77 KB
/
checksum.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
/*
* Checksum related methods.
*
* Copyright 2015-2016 Regents of the University of California,
* UCSD Non-Volatile Systems Lab, Andiry Xu <[email protected]>
* Copyright 2012-2013 Intel Corporation
* Copyright 2009-2011 Marco Stornelli <[email protected]>
* Copyright 2003 Sony Corporation
* Copyright 2003 Matsushita Electric Industrial Co., Ltd.
* 2003-2004 (c) MontaVista Software, Inc. , Steve Longerbeam
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#ifndef __CHECKSUM_H_
#define __CHECKSUM_H_
#include <linux/types.h>
#include <linux/crc32c.h>
static inline u32 nova_crc32c(u32 crc, const u8 *data, size_t len)
{
u8 *ptr = (u8 *) data;
u64 acc = crc; /* accumulator, crc32c value in lower 32b */
u32 csum;
/* x86 instruction crc32 is part of SSE-4.2 */
if (static_cpu_has(X86_FEATURE_XMM4_2)) {
/* This inline assembly implementation should be equivalent
* to the kernel's crc32c_intel_le_hw() function used by
* crc32c(), but this performs better on test machines.
*/
while (len > 8) {
asm volatile(/* 64b quad words */
"crc32q (%1), %0"
: "=r" (acc)
: "r" (ptr), "0" (acc)
);
ptr += 8;
len -= 8;
}
while (len > 0) {
asm volatile(/* trailing bytes */
"crc32b (%1), %0"
: "=r" (acc)
: "r" (ptr), "0" (acc)
);
ptr++;
len--;
}
csum = (u32) acc;
} else {
/* The kernel's crc32c() function should also detect and use the
* crc32 instruction of SSE-4.2. But calling in to this function
* is about 3x to 5x slower than the inline assembly version on
* some test machines.
*/
csum = crc32c(crc, data, len);
}
return csum;
}
#endif // __CHECKSUM_H_