Skip to content

Commit 511484f

Browse files
committed
riscv/crc64: add Zbc optimized CRC64 functions
Wire up crc64_be_arch() and crc64_nvme_arch() for 64-bit RISC-V using crc-clmul-template.h. This greatly improves the performance of these CRCs on Zbc-capable CPUs in 64-bit kernels. These optimized CRC64 functions are not yet supported in 32-bit kernels, since crc-clmul-template.h assumes that the CRC fits in an unsigned long. That implementation limitation could be addressed, but it would add a fair bit of complexity, so it has been omitted for now. Tested-by: Björn Töpel <[email protected]> Acked-by: Alexandre Ghiti <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Eric Biggers <[email protected]>
1 parent 8bf3e17 commit 511484f

File tree

7 files changed

+112
-1
lines changed

7 files changed

+112
-1
lines changed

arch/riscv/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ config RISCV
2525
select ARCH_ENABLE_THP_MIGRATION if TRANSPARENT_HUGEPAGE
2626
select ARCH_HAS_BINFMT_FLAT
2727
select ARCH_HAS_CRC32 if RISCV_ISA_ZBC
28+
select ARCH_HAS_CRC64 if 64BIT && RISCV_ISA_ZBC
2829
select ARCH_HAS_CRC_T10DIF if RISCV_ISA_ZBC
2930
select ARCH_HAS_CURRENT_STACK_POINTER
3031
select ARCH_HAS_DEBUG_VIRTUAL if MMU

arch/riscv/lib/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ lib-$(CONFIG_64BIT) += tishift.o
1717
lib-$(CONFIG_RISCV_ISA_ZICBOZ) += clear_page.o
1818
obj-$(CONFIG_CRC32_ARCH) += crc32-riscv.o
1919
crc32-riscv-y := crc32.o crc32_msb.o crc32_lsb.o
20+
obj-$(CONFIG_CRC64_ARCH) += crc64-riscv.o
21+
crc64-riscv-y := crc64.o crc64_msb.o crc64_lsb.o
2022
obj-$(CONFIG_CRC_T10DIF_ARCH) += crc-t10dif-riscv.o
2123
crc-t10dif-riscv-y := crc-t10dif.o crc16_msb.o
2224
obj-$(CONFIG_FUNCTION_ERROR_INJECTION) += error-inject.o

arch/riscv/lib/crc-clmul-consts.h

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
/*
33
* CRC constants generated by:
44
*
5-
* ./scripts/gen-crc-consts.py riscv_clmul crc16_msb_0x8bb7,crc32_msb_0x04c11db7,crc32_lsb_0xedb88320,crc32_lsb_0x82f63b78
5+
* ./scripts/gen-crc-consts.py riscv_clmul crc16_msb_0x8bb7,crc32_msb_0x04c11db7,crc32_lsb_0xedb88320,crc32_lsb_0x82f63b78,crc64_msb_0x42f0e1eba9ea3693,crc64_lsb_0x9a6c9329ac4bc9b5
66
*
77
* Do not edit manually.
88
*/
@@ -88,3 +88,35 @@ static const struct crc_clmul_consts crc32_lsb_0x82f63b78_consts __maybe_unused
8888
.barrett_reduction_const_2 = 0x82f63b78, /* (G - x^32) * x^0 */
8989
#endif
9090
};
91+
92+
/*
93+
* Constants generated for most-significant-bit-first CRC-64 using
94+
* G(x) = x^64 + x^62 + x^57 + x^55 + x^54 + x^53 + x^52 + x^47 + x^46 + x^45 +
95+
* x^40 + x^39 + x^38 + x^37 + x^35 + x^33 + x^32 + x^31 + x^29 + x^27 +
96+
* x^24 + x^23 + x^22 + x^21 + x^19 + x^17 + x^13 + x^12 + x^10 + x^9 +
97+
* x^7 + x^4 + x^1 + x^0
98+
*/
99+
#ifdef CONFIG_64BIT
100+
static const struct crc_clmul_consts crc64_msb_0x42f0e1eba9ea3693_consts __maybe_unused = {
101+
.fold_across_2_longs_const_hi = 0x4eb938a7d257740e, /* x^192 mod G */
102+
.fold_across_2_longs_const_lo = 0x05f5c3c7eb52fab6, /* x^128 mod G */
103+
.barrett_reduction_const_1 = 0xabc694e836627c39, /* floor(x^127 / G) */
104+
.barrett_reduction_const_2 = 0x42f0e1eba9ea3693, /* G - x^64 */
105+
};
106+
#endif
107+
108+
/*
109+
* Constants generated for least-significant-bit-first CRC-64 using
110+
* G(x) = x^64 + x^63 + x^61 + x^59 + x^58 + x^56 + x^55 + x^52 + x^49 + x^48 +
111+
* x^47 + x^46 + x^44 + x^41 + x^37 + x^36 + x^34 + x^32 + x^31 + x^28 +
112+
* x^26 + x^23 + x^22 + x^19 + x^16 + x^13 + x^12 + x^10 + x^9 + x^6 +
113+
* x^4 + x^3 + x^0
114+
*/
115+
#ifdef CONFIG_64BIT
116+
static const struct crc_clmul_consts crc64_lsb_0x9a6c9329ac4bc9b5_consts __maybe_unused = {
117+
.fold_across_2_longs_const_hi = 0xeadc41fd2ba3d420, /* x^191 mod G */
118+
.fold_across_2_longs_const_lo = 0x21e9761e252621ac, /* x^127 mod G */
119+
.barrett_reduction_const_1 = 0x27ecfa329aef9f77, /* floor(x^127 / G) */
120+
.barrett_reduction_const_2 = 0x9a6c9329ac4bc9b5, /* (G - x^64) * x^0 */
121+
};
122+
#endif

arch/riscv/lib/crc-clmul.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,11 @@ u32 crc32_msb_clmul(u32 crc, const void *p, size_t len,
1313
const struct crc_clmul_consts *consts);
1414
u32 crc32_lsb_clmul(u32 crc, const void *p, size_t len,
1515
const struct crc_clmul_consts *consts);
16+
#ifdef CONFIG_64BIT
17+
u64 crc64_msb_clmul(u64 crc, const void *p, size_t len,
18+
const struct crc_clmul_consts *consts);
19+
u64 crc64_lsb_clmul(u64 crc, const void *p, size_t len,
20+
const struct crc_clmul_consts *consts);
21+
#endif
1622

1723
#endif /* _RISCV_CRC_CLMUL_H */

arch/riscv/lib/crc64.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// SPDX-License-Identifier: GPL-2.0-or-later
2+
/*
3+
* RISC-V optimized CRC64 functions
4+
*
5+
* Copyright 2025 Google LLC
6+
*/
7+
8+
#include <asm/hwcap.h>
9+
#include <asm/alternative-macros.h>
10+
#include <linux/crc64.h>
11+
#include <linux/module.h>
12+
13+
#include "crc-clmul.h"
14+
15+
u64 crc64_be_arch(u64 crc, const u8 *p, size_t len)
16+
{
17+
if (riscv_has_extension_likely(RISCV_ISA_EXT_ZBC))
18+
return crc64_msb_clmul(crc, p, len,
19+
&crc64_msb_0x42f0e1eba9ea3693_consts);
20+
return crc64_be_generic(crc, p, len);
21+
}
22+
EXPORT_SYMBOL(crc64_be_arch);
23+
24+
u64 crc64_nvme_arch(u64 crc, const u8 *p, size_t len)
25+
{
26+
if (riscv_has_extension_likely(RISCV_ISA_EXT_ZBC))
27+
return crc64_lsb_clmul(crc, p, len,
28+
&crc64_lsb_0x9a6c9329ac4bc9b5_consts);
29+
return crc64_nvme_generic(crc, p, len);
30+
}
31+
EXPORT_SYMBOL(crc64_nvme_arch);
32+
33+
MODULE_DESCRIPTION("RISC-V optimized CRC64 functions");
34+
MODULE_LICENSE("GPL");

arch/riscv/lib/crc64_lsb.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// SPDX-License-Identifier: GPL-2.0-or-later
2+
/*
3+
* RISC-V optimized least-significant-bit-first CRC64
4+
*
5+
* Copyright 2025 Google LLC
6+
*/
7+
8+
#include "crc-clmul.h"
9+
10+
typedef u64 crc_t;
11+
#define LSB_CRC 1
12+
#include "crc-clmul-template.h"
13+
14+
u64 crc64_lsb_clmul(u64 crc, const void *p, size_t len,
15+
const struct crc_clmul_consts *consts)
16+
{
17+
return crc_clmul(crc, p, len, consts);
18+
}

arch/riscv/lib/crc64_msb.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// SPDX-License-Identifier: GPL-2.0-or-later
2+
/*
3+
* RISC-V optimized most-significant-bit-first CRC64
4+
*
5+
* Copyright 2025 Google LLC
6+
*/
7+
8+
#include "crc-clmul.h"
9+
10+
typedef u64 crc_t;
11+
#define LSB_CRC 0
12+
#include "crc-clmul-template.h"
13+
14+
u64 crc64_msb_clmul(u64 crc, const void *p, size_t len,
15+
const struct crc_clmul_consts *consts)
16+
{
17+
return crc_clmul(crc, p, len, consts);
18+
}

0 commit comments

Comments
 (0)