Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

lib/crc: x86: Reorganize crc-pclmul static_call initialization

Reorganize the crc-pclmul static_call initialization to place more of
the logic in the *_mod_init_arch() functions instead of in the
INIT_CRC_PCLMUL macro. This provides the flexibility to do more than a
single static_call update for each CPU feature check. Right away,
optimize crc64_mod_init_arch() to check the CPU features just once
instead of twice, doing both the crc64_msb and crc64_lsb static_call
updates together. A later commit will also use this to initialize an
additional static_key when crc32_lsb_vpclmul_avx512() is enabled.

Acked-by: Ard Biesheuvel <ardb@kernel.org>
Link: https://lore.kernel.org/r/20250719224938.126512-2-ebiggers@kernel.org
Signed-off-by: Eric Biggers <ebiggers@kernel.org>

+44 -21
+14 -17
lib/crc/x86/crc-pclmul-template.h
··· 25 25 const void *consts_ptr); \ 26 26 DEFINE_STATIC_CALL(prefix##_pclmul, prefix##_pclmul_sse) 27 27 28 - #define INIT_CRC_PCLMUL(prefix) \ 29 - do { \ 30 - if (boot_cpu_has(X86_FEATURE_VPCLMULQDQ) && \ 31 - boot_cpu_has(X86_FEATURE_AVX2) && \ 32 - cpu_has_xfeatures(XFEATURE_MASK_YMM, NULL)) { \ 33 - if (boot_cpu_has(X86_FEATURE_AVX512BW) && \ 34 - boot_cpu_has(X86_FEATURE_AVX512VL) && \ 35 - !boot_cpu_has(X86_FEATURE_PREFER_YMM) && \ 36 - cpu_has_xfeatures(XFEATURE_MASK_AVX512, NULL)) { \ 37 - static_call_update(prefix##_pclmul, \ 38 - prefix##_vpclmul_avx512); \ 39 - } else { \ 40 - static_call_update(prefix##_pclmul, \ 41 - prefix##_vpclmul_avx2); \ 42 - } \ 43 - } \ 44 - } while (0) 28 + static inline bool have_vpclmul(void) 29 + { 30 + return boot_cpu_has(X86_FEATURE_VPCLMULQDQ) && 31 + boot_cpu_has(X86_FEATURE_AVX2) && 32 + cpu_has_xfeatures(XFEATURE_MASK_YMM, NULL); 33 + } 34 + 35 + static inline bool have_avx512(void) 36 + { 37 + return boot_cpu_has(X86_FEATURE_AVX512BW) && 38 + boot_cpu_has(X86_FEATURE_AVX512VL) && 39 + !boot_cpu_has(X86_FEATURE_PREFER_YMM) && 40 + cpu_has_xfeatures(XFEATURE_MASK_AVX512, NULL); 41 + } 45 42 46 43 /* 47 44 * Call a [V]PCLMULQDQ optimized CRC function if the data length is at least 16
+8 -1
lib/crc/x86/crc-t10dif.h
··· 23 23 { 24 24 if (boot_cpu_has(X86_FEATURE_PCLMULQDQ)) { 25 25 static_branch_enable(&have_pclmulqdq); 26 - INIT_CRC_PCLMUL(crc16_msb); 26 + if (have_vpclmul()) { 27 + if (have_avx512()) 28 + static_call_update(crc16_msb_pclmul, 29 + crc16_msb_vpclmul_avx512); 30 + else 31 + static_call_update(crc16_msb_pclmul, 32 + crc16_msb_vpclmul_avx2); 33 + } 27 34 } 28 35 }
+9 -1
lib/crc/x86/crc32.h
··· 77 77 static_branch_enable(&have_crc32); 78 78 if (boot_cpu_has(X86_FEATURE_PCLMULQDQ)) { 79 79 static_branch_enable(&have_pclmulqdq); 80 - INIT_CRC_PCLMUL(crc32_lsb); 80 + if (have_vpclmul()) { 81 + if (have_avx512()) { 82 + static_call_update(crc32_lsb_pclmul, 83 + crc32_lsb_vpclmul_avx512); 84 + } else { 85 + static_call_update(crc32_lsb_pclmul, 86 + crc32_lsb_vpclmul_avx2); 87 + } 88 + } 81 89 } 82 90 } 83 91
+13 -2
lib/crc/x86/crc64.h
··· 31 31 { 32 32 if (boot_cpu_has(X86_FEATURE_PCLMULQDQ)) { 33 33 static_branch_enable(&have_pclmulqdq); 34 - INIT_CRC_PCLMUL(crc64_msb); 35 - INIT_CRC_PCLMUL(crc64_lsb); 34 + if (have_vpclmul()) { 35 + if (have_avx512()) { 36 + static_call_update(crc64_msb_pclmul, 37 + crc64_msb_vpclmul_avx512); 38 + static_call_update(crc64_lsb_pclmul, 39 + crc64_lsb_vpclmul_avx512); 40 + } else { 41 + static_call_update(crc64_msb_pclmul, 42 + crc64_msb_vpclmul_avx2); 43 + static_call_update(crc64_lsb_pclmul, 44 + crc64_lsb_vpclmul_avx2); 45 + } 46 + } 36 47 } 37 48 }