1*2b7531b2SEric Biggers // SPDX-License-Identifier: GPL-2.0-only
2*2b7531b2SEric Biggers
3*2b7531b2SEric Biggers #include <asm/alternative.h>
4*2b7531b2SEric Biggers #include <asm/cpufeature.h>
5*2b7531b2SEric Biggers #include <asm/neon.h>
6*2b7531b2SEric Biggers #include <asm/simd.h>
7*2b7531b2SEric Biggers
8*2b7531b2SEric Biggers #include <crypto/internal/simd.h>
9*2b7531b2SEric Biggers
10*2b7531b2SEric Biggers // The minimum input length to consider the 4-way interleaved code path
11*2b7531b2SEric Biggers static const size_t min_len = 1024;
12*2b7531b2SEric Biggers
13*2b7531b2SEric Biggers asmlinkage u32 crc32_le_arm64(u32 crc, unsigned char const *p, size_t len);
14*2b7531b2SEric Biggers asmlinkage u32 crc32c_le_arm64(u32 crc, unsigned char const *p, size_t len);
15*2b7531b2SEric Biggers asmlinkage u32 crc32_be_arm64(u32 crc, unsigned char const *p, size_t len);
16*2b7531b2SEric Biggers
17*2b7531b2SEric Biggers asmlinkage u32 crc32_le_arm64_4way(u32 crc, unsigned char const *p, size_t len);
18*2b7531b2SEric Biggers asmlinkage u32 crc32c_le_arm64_4way(u32 crc, unsigned char const *p, size_t len);
19*2b7531b2SEric Biggers asmlinkage u32 crc32_be_arm64_4way(u32 crc, unsigned char const *p, size_t len);
20*2b7531b2SEric Biggers
crc32_le_arch(u32 crc,const u8 * p,size_t len)21*2b7531b2SEric Biggers static inline u32 crc32_le_arch(u32 crc, const u8 *p, size_t len)
22*2b7531b2SEric Biggers {
23*2b7531b2SEric Biggers if (!alternative_has_cap_likely(ARM64_HAS_CRC32))
24*2b7531b2SEric Biggers return crc32_le_base(crc, p, len);
25*2b7531b2SEric Biggers
26*2b7531b2SEric Biggers if (len >= min_len && cpu_have_named_feature(PMULL) && crypto_simd_usable()) {
27*2b7531b2SEric Biggers kernel_neon_begin();
28*2b7531b2SEric Biggers crc = crc32_le_arm64_4way(crc, p, len);
29*2b7531b2SEric Biggers kernel_neon_end();
30*2b7531b2SEric Biggers
31*2b7531b2SEric Biggers p += round_down(len, 64);
32*2b7531b2SEric Biggers len %= 64;
33*2b7531b2SEric Biggers
34*2b7531b2SEric Biggers if (!len)
35*2b7531b2SEric Biggers return crc;
36*2b7531b2SEric Biggers }
37*2b7531b2SEric Biggers
38*2b7531b2SEric Biggers return crc32_le_arm64(crc, p, len);
39*2b7531b2SEric Biggers }
40*2b7531b2SEric Biggers
crc32c_arch(u32 crc,const u8 * p,size_t len)41*2b7531b2SEric Biggers static inline u32 crc32c_arch(u32 crc, const u8 *p, size_t len)
42*2b7531b2SEric Biggers {
43*2b7531b2SEric Biggers if (!alternative_has_cap_likely(ARM64_HAS_CRC32))
44*2b7531b2SEric Biggers return crc32c_base(crc, p, len);
45*2b7531b2SEric Biggers
46*2b7531b2SEric Biggers if (len >= min_len && cpu_have_named_feature(PMULL) && crypto_simd_usable()) {
47*2b7531b2SEric Biggers kernel_neon_begin();
48*2b7531b2SEric Biggers crc = crc32c_le_arm64_4way(crc, p, len);
49*2b7531b2SEric Biggers kernel_neon_end();
50*2b7531b2SEric Biggers
51*2b7531b2SEric Biggers p += round_down(len, 64);
52*2b7531b2SEric Biggers len %= 64;
53*2b7531b2SEric Biggers
54*2b7531b2SEric Biggers if (!len)
55*2b7531b2SEric Biggers return crc;
56*2b7531b2SEric Biggers }
57*2b7531b2SEric Biggers
58*2b7531b2SEric Biggers return crc32c_le_arm64(crc, p, len);
59*2b7531b2SEric Biggers }
60*2b7531b2SEric Biggers
crc32_be_arch(u32 crc,const u8 * p,size_t len)61*2b7531b2SEric Biggers static inline u32 crc32_be_arch(u32 crc, const u8 *p, size_t len)
62*2b7531b2SEric Biggers {
63*2b7531b2SEric Biggers if (!alternative_has_cap_likely(ARM64_HAS_CRC32))
64*2b7531b2SEric Biggers return crc32_be_base(crc, p, len);
65*2b7531b2SEric Biggers
66*2b7531b2SEric Biggers if (len >= min_len && cpu_have_named_feature(PMULL) && crypto_simd_usable()) {
67*2b7531b2SEric Biggers kernel_neon_begin();
68*2b7531b2SEric Biggers crc = crc32_be_arm64_4way(crc, p, len);
69*2b7531b2SEric Biggers kernel_neon_end();
70*2b7531b2SEric Biggers
71*2b7531b2SEric Biggers p += round_down(len, 64);
72*2b7531b2SEric Biggers len %= 64;
73*2b7531b2SEric Biggers
74*2b7531b2SEric Biggers if (!len)
75*2b7531b2SEric Biggers return crc;
76*2b7531b2SEric Biggers }
77*2b7531b2SEric Biggers
78*2b7531b2SEric Biggers return crc32_be_arm64(crc, p, len);
79*2b7531b2SEric Biggers }
80*2b7531b2SEric Biggers
crc32_optimizations_arch(void)81*2b7531b2SEric Biggers static inline u32 crc32_optimizations_arch(void)
82*2b7531b2SEric Biggers {
83*2b7531b2SEric Biggers if (alternative_has_cap_likely(ARM64_HAS_CRC32))
84*2b7531b2SEric Biggers return CRC32_LE_OPTIMIZATION |
85*2b7531b2SEric Biggers CRC32_BE_OPTIMIZATION |
86*2b7531b2SEric Biggers CRC32C_OPTIMIZATION;
87*2b7531b2SEric Biggers return 0;
88*2b7531b2SEric Biggers }
89