1 // SPDX-License-Identifier: GPL-2.0-only 2 /* CRC32c (Castagnoli), sparc64 crc32c opcode accelerated 3 * 4 * This is based largely upon arch/x86/crypto/crc32c-intel.c 5 * 6 * Copyright (C) 2008 Intel Corporation 7 * Authors: Austin Zhang <austin_zhang@linux.intel.com> 8 * Kent Liu <kent.liu@intel.com> 9 */ 10 11 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 12 13 #include <linux/init.h> 14 #include <linux/module.h> 15 #include <linux/kernel.h> 16 #include <linux/crc32.h> 17 #include <asm/pstate.h> 18 #include <asm/elf.h> 19 20 static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_crc32c_opcode); 21 22 u32 crc32_le_arch(u32 crc, const u8 *data, size_t len) 23 { 24 return crc32_le_base(crc, data, len); 25 } 26 EXPORT_SYMBOL(crc32_le_arch); 27 28 void crc32c_sparc64(u32 *crcp, const u64 *data, size_t len); 29 30 u32 crc32c_arch(u32 crc, const u8 *data, size_t len) 31 { 32 size_t n = -(uintptr_t)data & 7; 33 34 if (!static_branch_likely(&have_crc32c_opcode)) 35 return crc32c_base(crc, data, len); 36 37 if (n) { 38 /* Data isn't 8-byte aligned. Align it. */ 39 n = min(n, len); 40 crc = crc32c_base(crc, data, n); 41 data += n; 42 len -= n; 43 } 44 n = len & ~7U; 45 if (n) { 46 crc32c_sparc64(&crc, (const u64 *)data, n); 47 data += n; 48 len -= n; 49 } 50 if (len) 51 crc = crc32c_base(crc, data, len); 52 return crc; 53 } 54 EXPORT_SYMBOL(crc32c_arch); 55 56 u32 crc32_be_arch(u32 crc, const u8 *data, size_t len) 57 { 58 return crc32_be_base(crc, data, len); 59 } 60 EXPORT_SYMBOL(crc32_be_arch); 61 62 static int __init crc32_sparc_init(void) 63 { 64 unsigned long cfr; 65 66 if (!(sparc64_elf_hwcap & HWCAP_SPARC_CRYPTO)) 67 return 0; 68 69 __asm__ __volatile__("rd %%asr26, %0" : "=r" (cfr)); 70 if (!(cfr & CFR_CRC32C)) 71 return 0; 72 73 static_branch_enable(&have_crc32c_opcode); 74 pr_info("Using sparc64 crc32c opcode optimized CRC32C implementation\n"); 75 return 0; 76 } 77 subsys_initcall(crc32_sparc_init); 78 79 static void __exit crc32_sparc_exit(void) 80 { 81 } 82 module_exit(crc32_sparc_exit); 83 84 u32 crc32_optimizations(void) 85 { 86 if (static_key_enabled(&have_crc32c_opcode)) 87 return CRC32C_OPTIMIZATION; 88 return 0; 89 } 90 EXPORT_SYMBOL(crc32_optimizations); 91 92 MODULE_LICENSE("GPL"); 93 MODULE_DESCRIPTION("CRC32c (Castagnoli), sparc64 crc32c opcode accelerated"); 94