Path: blob/main/sys/contrib/openzfs/module/icp/algs/sha2/sha512_impl.c
48674 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(uint64_t s[8], const void *, size_t); \36static inline void N(uint64_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(__aarch64__) || defined(__arm__) || defined(__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_sha512_transform_x64(uint64_t s[8], const void *, size_t);5455static inline void56tf_sha512_transform_x64(uint64_t s[8], const void *d, size_t b)57{58zfs_sha512_transform_x64(s, d, b);59}60const sha512_ops_t sha512_x64_impl = {61.is_supported = sha2_is_supported,62.transform = tf_sha512_transform_x64,63.name = "x64"64};6566#if defined(HAVE_AVX)67static boolean_t sha2_have_avx(void)68{69return (kfpu_allowed() && zfs_avx_available());70}7172TF(zfs_sha512_transform_avx, tf_sha512_avx);73const sha512_ops_t sha512_avx_impl = {74.is_supported = sha2_have_avx,75.transform = tf_sha512_avx,76.name = "avx"77};78#endif7980#if defined(HAVE_AVX2)81static boolean_t sha2_have_avx2(void)82{83return (kfpu_allowed() && zfs_avx2_available());84}8586TF(zfs_sha512_transform_avx2, tf_sha512_avx2);87const sha512_ops_t sha512_avx2_impl = {88.is_supported = sha2_have_avx2,89.transform = tf_sha512_avx2,90.name = "avx2"91};92#endif9394#elif defined(__aarch64__) || defined(__arm__)95extern void zfs_sha512_block_armv7(uint64_t s[8], const void *, size_t);96const sha512_ops_t sha512_armv7_impl = {97.is_supported = sha2_is_supported,98.transform = zfs_sha512_block_armv7,99.name = "armv7"100};101102#if defined(__aarch64__)103static boolean_t sha512_have_armv8ce(void)104{105return (kfpu_allowed() && zfs_sha512_available());106}107108TF(zfs_sha512_block_armv8, tf_sha512_armv8ce);109const sha512_ops_t sha512_armv8_impl = {110.is_supported = sha512_have_armv8ce,111.transform = tf_sha512_armv8ce,112.name = "armv8-ce"113};114#endif115116#if defined(__arm__) && __ARM_ARCH > 6117static boolean_t sha512_have_neon(void)118{119return (kfpu_allowed() && zfs_neon_available());120}121122TF(zfs_sha512_block_neon, tf_sha512_neon);123const sha512_ops_t sha512_neon_impl = {124.is_supported = sha512_have_neon,125.transform = tf_sha512_neon,126.name = "neon"127};128#endif129130#elif defined(__PPC64__)131TF(zfs_sha512_ppc, tf_sha512_ppc);132const sha512_ops_t sha512_ppc_impl = {133.is_supported = sha2_is_supported,134.transform = tf_sha512_ppc,135.name = "ppc"136};137138static boolean_t sha512_have_isa207(void)139{140return (kfpu_allowed() && zfs_isa207_available());141}142143TF(zfs_sha512_power8, tf_sha512_power8);144const sha512_ops_t sha512_power8_impl = {145.is_supported = sha512_have_isa207,146.transform = tf_sha512_power8,147.name = "power8"148};149#endif /* __PPC64__ */150151/* the two generic ones */152extern const sha512_ops_t sha512_generic_impl;153154/* array with all sha512 implementations */155static const sha512_ops_t *const sha512_impls[] = {156&sha512_generic_impl,157#if defined(__x86_64)158&sha512_x64_impl,159#endif160#if defined(__x86_64) && defined(HAVE_AVX)161&sha512_avx_impl,162#endif163#if defined(__x86_64) && defined(HAVE_AVX2)164&sha512_avx2_impl,165#endif166#if defined(__aarch64__) || defined(__arm__)167&sha512_armv7_impl,168#if defined(__aarch64__)169&sha512_armv8_impl,170#endif171#if defined(__arm__) && __ARM_ARCH > 6172&sha512_neon_impl,173#endif174#endif175#if defined(__PPC64__)176&sha512_ppc_impl,177&sha512_power8_impl,178#endif /* __PPC64__ */179};180181/* use the generic implementation functions */182#define IMPL_NAME "sha512"183#define IMPL_OPS_T sha512_ops_t184#define IMPL_ARRAY sha512_impls185#define IMPL_GET_OPS sha512_get_ops186#define ZFS_IMPL_OPS zfs_sha512_ops187#include <generic_impl.c>188189#ifdef _KERNEL190191#define IMPL_FMT(impl, i) (((impl) == (i)) ? "[%s] " : "%s ")192193#if defined(__linux__)194195static int196sha512_param_get(char *buffer, zfs_kernel_param_t *unused)197{198const uint32_t impl = IMPL_READ(generic_impl_chosen);199char *fmt;200int cnt = 0;201202/* cycling */203fmt = IMPL_FMT(impl, IMPL_CYCLE);204cnt += sprintf(buffer + cnt, fmt, "cycle");205206/* list fastest */207fmt = IMPL_FMT(impl, IMPL_FASTEST);208cnt += sprintf(buffer + cnt, fmt, "fastest");209210/* list all supported implementations */211generic_impl_init();212for (uint32_t i = 0; i < generic_supp_impls_cnt; ++i) {213fmt = IMPL_FMT(impl, i);214cnt += sprintf(buffer + cnt, fmt,215generic_supp_impls[i]->name);216}217218return (cnt);219}220221static int222sha512_param_set(const char *val, zfs_kernel_param_t *unused)223{224(void) unused;225return (generic_impl_setname(val));226}227228#elif defined(__FreeBSD__)229230#include <sys/sbuf.h>231232static int233sha512_param(ZFS_MODULE_PARAM_ARGS)234{235int err;236237generic_impl_init();238if (req->newptr == NULL) {239const uint32_t impl = IMPL_READ(generic_impl_chosen);240const int init_buflen = 64;241const char *fmt;242struct sbuf *s;243244s = sbuf_new_for_sysctl(NULL, NULL, init_buflen, req);245246/* cycling */247fmt = IMPL_FMT(impl, IMPL_CYCLE);248(void) sbuf_printf(s, fmt, "cycle");249250/* list fastest */251fmt = IMPL_FMT(impl, IMPL_FASTEST);252(void) sbuf_printf(s, fmt, "fastest");253254/* list all supported implementations */255for (uint32_t i = 0; i < generic_supp_impls_cnt; ++i) {256fmt = IMPL_FMT(impl, i);257(void) sbuf_printf(s, fmt, generic_supp_impls[i]->name);258}259260err = sbuf_finish(s);261sbuf_delete(s);262263return (err);264}265266/* we got module parameter */267char buf[16];268269err = sysctl_handle_string(oidp, buf, sizeof (buf), req);270if (err) {271return (err);272}273274return (-generic_impl_setname(buf));275}276#endif277278#undef IMPL_FMT279280ZFS_MODULE_VIRTUAL_PARAM_CALL(zfs, zfs_, sha512_impl,281sha512_param_set, sha512_param_get, ZMOD_RW, \282"Select SHA512 implementation.");283#endif284285#undef TF286287288