1 // SPDX-License-Identifier: GPL-2.0-only
3 * x86-optimized CRC32 functions
5 * Copyright (C) 2008 Intel Corporation
6 * Copyright 2012 Xyratex Technology Limited
7 * Copyright 2024 Google LLC
10 #include <asm/cpufeatures.h>
12 #include <crypto/internal/simd.h>
13 #include <linux/crc32.h>
14 #include <linux/linkage.h>
15 #include <linux/module.h>
17 /* minimum size of buffer for crc32_pclmul_le_16 */
18 #define CRC32_PCLMUL_MIN_LEN 64
20 static DEFINE_STATIC_KEY_FALSE(have_crc32
);
21 static DEFINE_STATIC_KEY_FALSE(have_pclmulqdq
);
23 u32
crc32_pclmul_le_16(u32 crc
, const u8
*buffer
, size_t len
);
25 u32
crc32_le_arch(u32 crc
, const u8
*p
, size_t len
)
27 if (len
>= CRC32_PCLMUL_MIN_LEN
+ 15 &&
28 static_branch_likely(&have_pclmulqdq
) && crypto_simd_usable()) {
29 size_t n
= -(uintptr_t)p
& 15;
31 /* align p to 16-byte boundary */
33 crc
= crc32_le_base(crc
, p
, n
);
37 n
= round_down(len
, 16);
39 crc
= crc32_pclmul_le_16(crc
, p
, n
);
45 crc
= crc32_le_base(crc
, p
, len
);
48 EXPORT_SYMBOL(crc32_le_arch
);
51 #define CRC32_INST "crc32q %1, %q0"
53 #define CRC32_INST "crc32l %1, %0"
57 * Use carryless multiply version of crc32c when buffer size is >= 512 to
58 * account for FPU state save/restore overhead.
60 #define CRC32C_PCLMUL_BREAKEVEN 512
62 asmlinkage u32
crc32c_x86_3way(u32 crc
, const u8
*buffer
, size_t len
);
64 u32
crc32c_le_arch(u32 crc
, const u8
*p
, size_t len
)
68 if (!static_branch_likely(&have_crc32
))
69 return crc32c_le_base(crc
, p
, len
);
71 if (IS_ENABLED(CONFIG_X86_64
) && len
>= CRC32C_PCLMUL_BREAKEVEN
&&
72 static_branch_likely(&have_pclmulqdq
) && crypto_simd_usable()) {
74 crc
= crc32c_x86_3way(crc
, p
, len
);
79 for (num_longs
= len
/ sizeof(unsigned long);
80 num_longs
!= 0; num_longs
--, p
+= sizeof(unsigned long))
81 asm(CRC32_INST
: "+r" (crc
) : "rm" (*(unsigned long *)p
));
83 for (len
%= sizeof(unsigned long); len
; len
--, p
++)
84 asm("crc32b %1, %0" : "+r" (crc
) : "rm" (*p
));
88 EXPORT_SYMBOL(crc32c_le_arch
);
90 u32
crc32_be_arch(u32 crc
, const u8
*p
, size_t len
)
92 return crc32_be_base(crc
, p
, len
);
94 EXPORT_SYMBOL(crc32_be_arch
);
96 static int __init
crc32_x86_init(void)
98 if (boot_cpu_has(X86_FEATURE_XMM4_2
))
99 static_branch_enable(&have_crc32
);
100 if (boot_cpu_has(X86_FEATURE_PCLMULQDQ
))
101 static_branch_enable(&have_pclmulqdq
);
104 arch_initcall(crc32_x86_init
);
106 static void __exit
crc32_x86_exit(void)
109 module_exit(crc32_x86_exit
);
111 u32
crc32_optimizations(void)
113 u32 optimizations
= 0;
115 if (static_key_enabled(&have_crc32
))
116 optimizations
|= CRC32C_OPTIMIZATION
;
117 if (static_key_enabled(&have_pclmulqdq
))
118 optimizations
|= CRC32_LE_OPTIMIZATION
;
119 return optimizations
;
121 EXPORT_SYMBOL(crc32_optimizations
);
123 MODULE_DESCRIPTION("x86-optimized CRC32 functions");
124 MODULE_LICENSE("GPL");