Path: blob/main/sys/contrib/openzfs/module/icp/algs/sha2/sha256_impl.c
48676 views
// SPDX-License-Identifier: CDDL-1.01/*2* CDDL HEADER START3*4* The contents of this file are subject to the terms of the5* Common Development and Distribution License (the "License").6* You may not use this file except in compliance with the License.7*8* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE9* or https://opensource.org/licenses/CDDL-1.0.10* See the License for the specific language governing permissions11* and limitations under the License.12*13* When distributing Covered Code, include this CDDL HEADER in each14* file and include the License file at usr/src/OPENSOLARIS.LICENSE.15* If applicable, add the following below this CDDL HEADER, with the16* fields enclosed by brackets "[]" replaced with your own identifying17* information: Portions Copyright [yyyy] [name of copyright owner]18*19* CDDL HEADER END20*/2122/*23* Copyright (c) 2022 Tino Reichardt <[email protected]>24*/2526#include <sys/simd.h>27#include <sys/zfs_context.h>28#include <sys/zfs_impl.h>29#include <sys/sha2.h>3031#include <sha2/sha2_impl.h>32#include <sys/asm_linkage.h>3334#define TF(E, N) \35extern void ASMABI E(uint32_t s[8], const void *, size_t); \36static inline void N(uint32_t s[8], const void *d, size_t b) { \37kfpu_begin(); E(s, d, b); kfpu_end(); \38}3940#if defined(__x86_64) || defined(__aarch64__) || defined(__arm__) || \41defined(__PPC64__)42/* some implementation is always okay */43static inline boolean_t sha2_is_supported(void)44{45return (B_TRUE);46}47#endif4849#if defined(__x86_64)5051/* Users of ASMABI requires all calls to be from wrappers */52extern void ASMABI53zfs_sha256_transform_x64(uint32_t s[8], const void *, size_t);5455static inline void56tf_sha256_transform_x64(uint32_t s[8], const void *d, size_t b)57{58zfs_sha256_transform_x64(s, d, b);59}6061const sha256_ops_t sha256_x64_impl = {62.is_supported = sha2_is_supported,63.transform = tf_sha256_transform_x64,64.name = "x64"65};6667#if defined(HAVE_SSSE3)68static boolean_t sha2_have_ssse3(void)69{70return (kfpu_allowed() && zfs_ssse3_available());71}7273TF(zfs_sha256_transform_ssse3, tf_sha256_ssse3);74const sha256_ops_t sha256_ssse3_impl = {75.is_supported = sha2_have_ssse3,76.transform = tf_sha256_ssse3,77.name = "ssse3"78};79#endif8081#if defined(HAVE_AVX)82static boolean_t sha2_have_avx(void)83{84return (kfpu_allowed() && zfs_avx_available());85}8687TF(zfs_sha256_transform_avx, tf_sha256_avx);88const sha256_ops_t sha256_avx_impl = {89.is_supported = sha2_have_avx,90.transform = tf_sha256_avx,91.name = "avx"92};93#endif9495#if defined(HAVE_AVX2)96static boolean_t sha2_have_avx2(void)97{98return (kfpu_allowed() && zfs_avx2_available());99}100101TF(zfs_sha256_transform_avx2, tf_sha256_avx2);102const sha256_ops_t sha256_avx2_impl = {103.is_supported = sha2_have_avx2,104.transform = tf_sha256_avx2,105.name = "avx2"106};107#endif108109#if defined(HAVE_SSE4_1)110static boolean_t sha2_have_shani(void)111{112return (kfpu_allowed() && zfs_sse4_1_available() && \113zfs_shani_available());114}115116TF(zfs_sha256_transform_shani, tf_sha256_shani);117const sha256_ops_t sha256_shani_impl = {118.is_supported = sha2_have_shani,119.transform = tf_sha256_shani,120.name = "shani"121};122#endif123124#elif defined(__aarch64__) || defined(__arm__)125extern void zfs_sha256_block_armv7(uint32_t s[8], const void *, size_t);126const sha256_ops_t sha256_armv7_impl = {127.is_supported = sha2_is_supported,128.transform = zfs_sha256_block_armv7,129.name = "armv7"130};131132#if __ARM_ARCH > 6133static boolean_t sha256_have_neon(void)134{135return (kfpu_allowed() && zfs_neon_available());136}137138static boolean_t sha256_have_armv8ce(void)139{140return (kfpu_allowed() && zfs_sha256_available());141}142143TF(zfs_sha256_block_neon, tf_sha256_neon);144const sha256_ops_t sha256_neon_impl = {145.is_supported = sha256_have_neon,146.transform = tf_sha256_neon,147.name = "neon"148};149150TF(zfs_sha256_block_armv8, tf_sha256_armv8ce);151const sha256_ops_t sha256_armv8_impl = {152.is_supported = sha256_have_armv8ce,153.transform = tf_sha256_armv8ce,154.name = "armv8-ce"155};156#endif157158#elif defined(__PPC64__)159static boolean_t sha256_have_isa207(void)160{161return (kfpu_allowed() && zfs_isa207_available());162}163164TF(zfs_sha256_ppc, tf_sha256_ppc);165const sha256_ops_t sha256_ppc_impl = {166.is_supported = sha2_is_supported,167.transform = tf_sha256_ppc,168.name = "ppc"169};170171TF(zfs_sha256_power8, tf_sha256_power8);172const sha256_ops_t sha256_power8_impl = {173.is_supported = sha256_have_isa207,174.transform = tf_sha256_power8,175.name = "power8"176};177#endif /* __PPC64__ */178179/* the two generic ones */180extern const sha256_ops_t sha256_generic_impl;181182/* array with all sha256 implementations */183static const sha256_ops_t *const sha256_impls[] = {184&sha256_generic_impl,185#if defined(__x86_64)186&sha256_x64_impl,187#endif188#if defined(__x86_64) && defined(HAVE_SSSE3)189&sha256_ssse3_impl,190#endif191#if defined(__x86_64) && defined(HAVE_AVX)192&sha256_avx_impl,193#endif194#if defined(__x86_64) && defined(HAVE_AVX2)195&sha256_avx2_impl,196#endif197#if defined(__x86_64) && defined(HAVE_SSE4_1)198&sha256_shani_impl,199#endif200#if defined(__aarch64__) || defined(__arm__)201&sha256_armv7_impl,202#if __ARM_ARCH > 6203&sha256_neon_impl,204&sha256_armv8_impl,205#endif206#endif207#if defined(__PPC64__)208&sha256_ppc_impl,209&sha256_power8_impl,210#endif /* __PPC64__ */211};212213/* use the generic implementation functions */214#define IMPL_NAME "sha256"215#define IMPL_OPS_T sha256_ops_t216#define IMPL_ARRAY sha256_impls217#define IMPL_GET_OPS sha256_get_ops218#define ZFS_IMPL_OPS zfs_sha256_ops219#include <generic_impl.c>220221#ifdef _KERNEL222223#define IMPL_FMT(impl, i) (((impl) == (i)) ? "[%s] " : "%s ")224225#if defined(__linux__)226227static int228sha256_param_get(char *buffer, zfs_kernel_param_t *unused)229{230const uint32_t impl = IMPL_READ(generic_impl_chosen);231char *fmt;232int cnt = 0;233234/* cycling */235fmt = IMPL_FMT(impl, IMPL_CYCLE);236cnt += sprintf(buffer + cnt, fmt, "cycle");237238/* list fastest */239fmt = IMPL_FMT(impl, IMPL_FASTEST);240cnt += sprintf(buffer + cnt, fmt, "fastest");241242/* list all supported implementations */243generic_impl_init();244for (uint32_t i = 0; i < generic_supp_impls_cnt; ++i) {245fmt = IMPL_FMT(impl, i);246cnt += sprintf(buffer + cnt, fmt,247generic_supp_impls[i]->name);248}249250return (cnt);251}252253static int254sha256_param_set(const char *val, zfs_kernel_param_t *unused)255{256(void) unused;257return (generic_impl_setname(val));258}259260#elif defined(__FreeBSD__)261262#include <sys/sbuf.h>263264static int265sha256_param(ZFS_MODULE_PARAM_ARGS)266{267int err;268269generic_impl_init();270if (req->newptr == NULL) {271const uint32_t impl = IMPL_READ(generic_impl_chosen);272const int init_buflen = 64;273const char *fmt;274struct sbuf *s;275276s = sbuf_new_for_sysctl(NULL, NULL, init_buflen, req);277278/* cycling */279fmt = IMPL_FMT(impl, IMPL_CYCLE);280(void) sbuf_printf(s, fmt, "cycle");281282/* list fastest */283fmt = IMPL_FMT(impl, IMPL_FASTEST);284(void) sbuf_printf(s, fmt, "fastest");285286/* list all supported implementations */287for (uint32_t i = 0; i < generic_supp_impls_cnt; ++i) {288fmt = IMPL_FMT(impl, i);289(void) sbuf_printf(s, fmt, generic_supp_impls[i]->name);290}291292err = sbuf_finish(s);293sbuf_delete(s);294295return (err);296}297298char buf[16];299300err = sysctl_handle_string(oidp, buf, sizeof (buf), req);301if (err) {302return (err);303}304305return (-generic_impl_setname(buf));306}307#endif308309#undef IMPL_FMT310311ZFS_MODULE_VIRTUAL_PARAM_CALL(zfs, zfs_, sha256_impl,312sha256_param_set, sha256_param_get, ZMOD_RW, \313"Select SHA256 implementation.");314#endif315316#undef TF317318319