1*9b2d720eSEric Biggers // SPDX-License-Identifier: GPL-2.0-only 2*9b2d720eSEric Biggers /* CRC32c (Castagnoli), sparc64 crc32c opcode accelerated 3*9b2d720eSEric Biggers * 4*9b2d720eSEric Biggers * This is based largely upon arch/x86/crypto/crc32c-intel.c 5*9b2d720eSEric Biggers * 6*9b2d720eSEric Biggers * Copyright (C) 2008 Intel Corporation 7*9b2d720eSEric Biggers * Authors: Austin Zhang <austin_zhang@linux.intel.com> 8*9b2d720eSEric Biggers * Kent Liu <kent.liu@intel.com> 9*9b2d720eSEric Biggers */ 10*9b2d720eSEric Biggers 11*9b2d720eSEric Biggers #include <asm/pstate.h> 12*9b2d720eSEric Biggers #include <asm/elf.h> 13*9b2d720eSEric Biggers 14*9b2d720eSEric Biggers static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_crc32c_opcode); 15*9b2d720eSEric Biggers 16*9b2d720eSEric Biggers #define crc32_le_arch crc32_le_base /* not implemented on this arch */ 17*9b2d720eSEric Biggers #define crc32_be_arch crc32_be_base /* not implemented on this arch */ 18*9b2d720eSEric Biggers 19*9b2d720eSEric Biggers void crc32c_sparc64(u32 *crcp, const u64 *data, size_t len); 20*9b2d720eSEric Biggers 21*9b2d720eSEric Biggers static inline u32 crc32c_arch(u32 crc, const u8 *data, size_t len) 22*9b2d720eSEric Biggers { 23*9b2d720eSEric Biggers size_t n = -(uintptr_t)data & 7; 24*9b2d720eSEric Biggers 25*9b2d720eSEric Biggers if (!static_branch_likely(&have_crc32c_opcode)) 26*9b2d720eSEric Biggers return crc32c_base(crc, data, len); 27*9b2d720eSEric Biggers 28*9b2d720eSEric Biggers if (n) { 29*9b2d720eSEric Biggers /* Data isn't 8-byte aligned. Align it. */ 30*9b2d720eSEric Biggers n = min(n, len); 31*9b2d720eSEric Biggers crc = crc32c_base(crc, data, n); 32*9b2d720eSEric Biggers data += n; 33*9b2d720eSEric Biggers len -= n; 34*9b2d720eSEric Biggers } 35*9b2d720eSEric Biggers n = len & ~7U; 36*9b2d720eSEric Biggers if (n) { 37*9b2d720eSEric Biggers crc32c_sparc64(&crc, (const u64 *)data, n); 38*9b2d720eSEric Biggers data += n; 39*9b2d720eSEric Biggers len -= n; 40*9b2d720eSEric Biggers } 41*9b2d720eSEric Biggers if (len) 42*9b2d720eSEric Biggers crc = crc32c_base(crc, data, len); 43*9b2d720eSEric Biggers return crc; 44*9b2d720eSEric Biggers } 45*9b2d720eSEric Biggers 46*9b2d720eSEric Biggers #define crc32_mod_init_arch crc32_mod_init_arch 47*9b2d720eSEric Biggers static inline void crc32_mod_init_arch(void) 48*9b2d720eSEric Biggers { 49*9b2d720eSEric Biggers unsigned long cfr; 50*9b2d720eSEric Biggers 51*9b2d720eSEric Biggers if (!(sparc64_elf_hwcap & HWCAP_SPARC_CRYPTO)) 52*9b2d720eSEric Biggers return; 53*9b2d720eSEric Biggers 54*9b2d720eSEric Biggers __asm__ __volatile__("rd %%asr26, %0" : "=r" (cfr)); 55*9b2d720eSEric Biggers if (!(cfr & CFR_CRC32C)) 56*9b2d720eSEric Biggers return; 57*9b2d720eSEric Biggers 58*9b2d720eSEric Biggers static_branch_enable(&have_crc32c_opcode); 59*9b2d720eSEric Biggers pr_info("Using sparc64 crc32c opcode optimized CRC32C implementation\n"); 60*9b2d720eSEric Biggers } 61*9b2d720eSEric Biggers 62*9b2d720eSEric Biggers static inline u32 crc32_optimizations_arch(void) 63*9b2d720eSEric Biggers { 64*9b2d720eSEric Biggers if (static_key_enabled(&have_crc32c_opcode)) 65*9b2d720eSEric Biggers return CRC32C_OPTIMIZATION; 66*9b2d720eSEric Biggers return 0; 67*9b2d720eSEric Biggers } 68