11f1e2261SMartin Matuska /*
21f1e2261SMartin Matuska * CDDL HEADER START
31f1e2261SMartin Matuska *
41f1e2261SMartin Matuska * The contents of this file are subject to the terms of the
51f1e2261SMartin Matuska * Common Development and Distribution License (the "License").
61f1e2261SMartin Matuska * You may not use this file except in compliance with the License.
71f1e2261SMartin Matuska *
81f1e2261SMartin Matuska * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9271171e0SMartin Matuska * or https://opensource.org/licenses/CDDL-1.0.
101f1e2261SMartin Matuska * See the License for the specific language governing permissions
111f1e2261SMartin Matuska * and limitations under the License.
121f1e2261SMartin Matuska *
131f1e2261SMartin Matuska * When distributing Covered Code, include this CDDL HEADER in each
141f1e2261SMartin Matuska * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
151f1e2261SMartin Matuska * If applicable, add the following below this CDDL HEADER, with the
161f1e2261SMartin Matuska * fields enclosed by brackets "[]" replaced with your own identifying
171f1e2261SMartin Matuska * information: Portions Copyright [yyyy] [name of copyright owner]
181f1e2261SMartin Matuska *
191f1e2261SMartin Matuska * CDDL HEADER END
201f1e2261SMartin Matuska */
211f1e2261SMartin Matuska
221f1e2261SMartin Matuska /*
231f1e2261SMartin Matuska * Copyright (c) 2021-2022 Tino Reichardt <milky-zfs@mcmilk.de>
241f1e2261SMartin Matuska */
251f1e2261SMartin Matuska
262a58b312SMartin Matuska #include <sys/simd.h>
271f1e2261SMartin Matuska #include <sys/zfs_context.h>
282a58b312SMartin Matuska #include <sys/zfs_impl.h>
292a58b312SMartin Matuska #include <sys/blake3.h>
301f1e2261SMartin Matuska
311f1e2261SMartin Matuska #include "blake3_impl.h"
321f1e2261SMartin Matuska
33*6c8358cdSWarner Losh #if !defined(OMIT_SIMD) && (defined(__aarch64__) || \
342a58b312SMartin Matuska (defined(__x86_64) && defined(HAVE_SSE2)) || \
35*6c8358cdSWarner Losh (defined(__PPC64__) && defined(__LITTLE_ENDIAN__)))
36*6c8358cdSWarner Losh #define USE_SIMD
37*6c8358cdSWarner Losh #endif
382a58b312SMartin Matuska
39*6c8358cdSWarner Losh #ifdef USE_SIMD
402a58b312SMartin Matuska extern void ASMABI zfs_blake3_compress_in_place_sse2(uint32_t cv[8],
412a58b312SMartin Matuska const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len,
422a58b312SMartin Matuska uint64_t counter, uint8_t flags);
432a58b312SMartin Matuska
442a58b312SMartin Matuska extern void ASMABI zfs_blake3_compress_xof_sse2(const uint32_t cv[8],
452a58b312SMartin Matuska const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len,
462a58b312SMartin Matuska uint64_t counter, uint8_t flags, uint8_t out[64]);
472a58b312SMartin Matuska
482a58b312SMartin Matuska extern void ASMABI zfs_blake3_hash_many_sse2(const uint8_t * const *inputs,
492a58b312SMartin Matuska size_t num_inputs, size_t blocks, const uint32_t key[8],
502a58b312SMartin Matuska uint64_t counter, boolean_t increment_counter, uint8_t flags,
512a58b312SMartin Matuska uint8_t flags_start, uint8_t flags_end, uint8_t *out);
522a58b312SMartin Matuska
blake3_compress_in_place_sse2(uint32_t cv[8],const uint8_t block[BLAKE3_BLOCK_LEN],uint8_t block_len,uint64_t counter,uint8_t flags)532a58b312SMartin Matuska static void blake3_compress_in_place_sse2(uint32_t cv[8],
542a58b312SMartin Matuska const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len,
552a58b312SMartin Matuska uint64_t counter, uint8_t flags) {
562a58b312SMartin Matuska kfpu_begin();
572a58b312SMartin Matuska zfs_blake3_compress_in_place_sse2(cv, block, block_len, counter,
582a58b312SMartin Matuska flags);
592a58b312SMartin Matuska kfpu_end();
602a58b312SMartin Matuska }
612a58b312SMartin Matuska
blake3_compress_xof_sse2(const uint32_t cv[8],const uint8_t block[BLAKE3_BLOCK_LEN],uint8_t block_len,uint64_t counter,uint8_t flags,uint8_t out[64])622a58b312SMartin Matuska static void blake3_compress_xof_sse2(const uint32_t cv[8],
632a58b312SMartin Matuska const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len,
642a58b312SMartin Matuska uint64_t counter, uint8_t flags, uint8_t out[64]) {
652a58b312SMartin Matuska kfpu_begin();
662a58b312SMartin Matuska zfs_blake3_compress_xof_sse2(cv, block, block_len, counter, flags,
672a58b312SMartin Matuska out);
682a58b312SMartin Matuska kfpu_end();
692a58b312SMartin Matuska }
702a58b312SMartin Matuska
blake3_hash_many_sse2(const uint8_t * const * inputs,size_t num_inputs,size_t blocks,const uint32_t key[8],uint64_t counter,boolean_t increment_counter,uint8_t flags,uint8_t flags_start,uint8_t flags_end,uint8_t * out)712a58b312SMartin Matuska static void blake3_hash_many_sse2(const uint8_t * const *inputs,
722a58b312SMartin Matuska size_t num_inputs, size_t blocks, const uint32_t key[8],
732a58b312SMartin Matuska uint64_t counter, boolean_t increment_counter, uint8_t flags,
742a58b312SMartin Matuska uint8_t flags_start, uint8_t flags_end, uint8_t *out) {
752a58b312SMartin Matuska kfpu_begin();
762a58b312SMartin Matuska zfs_blake3_hash_many_sse2(inputs, num_inputs, blocks, key, counter,
772a58b312SMartin Matuska increment_counter, flags, flags_start, flags_end, out);
782a58b312SMartin Matuska kfpu_end();
792a58b312SMartin Matuska }
802a58b312SMartin Matuska
blake3_is_sse2_supported(void)812a58b312SMartin Matuska static boolean_t blake3_is_sse2_supported(void)
822a58b312SMartin Matuska {
832a58b312SMartin Matuska #if defined(__x86_64)
842a58b312SMartin Matuska return (kfpu_allowed() && zfs_sse2_available());
852a58b312SMartin Matuska #elif defined(__PPC64__)
862a58b312SMartin Matuska return (kfpu_allowed() && zfs_vsx_available());
872a58b312SMartin Matuska #else
882a58b312SMartin Matuska return (kfpu_allowed());
892a58b312SMartin Matuska #endif
902a58b312SMartin Matuska }
912a58b312SMartin Matuska
922a58b312SMartin Matuska const blake3_ops_t blake3_sse2_impl = {
932a58b312SMartin Matuska .compress_in_place = blake3_compress_in_place_sse2,
942a58b312SMartin Matuska .compress_xof = blake3_compress_xof_sse2,
952a58b312SMartin Matuska .hash_many = blake3_hash_many_sse2,
962a58b312SMartin Matuska .is_supported = blake3_is_sse2_supported,
972a58b312SMartin Matuska .degree = 4,
982a58b312SMartin Matuska .name = "sse2"
992a58b312SMartin Matuska };
1002a58b312SMartin Matuska #endif
1012a58b312SMartin Matuska
102*6c8358cdSWarner Losh #ifdef USE_SIMD
1032a58b312SMartin Matuska
1042a58b312SMartin Matuska extern void ASMABI zfs_blake3_compress_in_place_sse41(uint32_t cv[8],
1052a58b312SMartin Matuska const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len,
1062a58b312SMartin Matuska uint64_t counter, uint8_t flags);
1072a58b312SMartin Matuska
1082a58b312SMartin Matuska extern void ASMABI zfs_blake3_compress_xof_sse41(const uint32_t cv[8],
1092a58b312SMartin Matuska const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len,
1102a58b312SMartin Matuska uint64_t counter, uint8_t flags, uint8_t out[64]);
1112a58b312SMartin Matuska
1122a58b312SMartin Matuska extern void ASMABI zfs_blake3_hash_many_sse41(const uint8_t * const *inputs,
1132a58b312SMartin Matuska size_t num_inputs, size_t blocks, const uint32_t key[8],
1142a58b312SMartin Matuska uint64_t counter, boolean_t increment_counter, uint8_t flags,
1152a58b312SMartin Matuska uint8_t flags_start, uint8_t flags_end, uint8_t *out);
1162a58b312SMartin Matuska
blake3_compress_in_place_sse41(uint32_t cv[8],const uint8_t block[BLAKE3_BLOCK_LEN],uint8_t block_len,uint64_t counter,uint8_t flags)1172a58b312SMartin Matuska static void blake3_compress_in_place_sse41(uint32_t cv[8],
1182a58b312SMartin Matuska const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len,
1192a58b312SMartin Matuska uint64_t counter, uint8_t flags) {
1202a58b312SMartin Matuska kfpu_begin();
1212a58b312SMartin Matuska zfs_blake3_compress_in_place_sse41(cv, block, block_len, counter,
1222a58b312SMartin Matuska flags);
1232a58b312SMartin Matuska kfpu_end();
1242a58b312SMartin Matuska }
1252a58b312SMartin Matuska
blake3_compress_xof_sse41(const uint32_t cv[8],const uint8_t block[BLAKE3_BLOCK_LEN],uint8_t block_len,uint64_t counter,uint8_t flags,uint8_t out[64])1262a58b312SMartin Matuska static void blake3_compress_xof_sse41(const uint32_t cv[8],
1272a58b312SMartin Matuska const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len,
1282a58b312SMartin Matuska uint64_t counter, uint8_t flags, uint8_t out[64]) {
1292a58b312SMartin Matuska kfpu_begin();
1302a58b312SMartin Matuska zfs_blake3_compress_xof_sse41(cv, block, block_len, counter, flags,
1312a58b312SMartin Matuska out);
1322a58b312SMartin Matuska kfpu_end();
1332a58b312SMartin Matuska }
1342a58b312SMartin Matuska
blake3_hash_many_sse41(const uint8_t * const * inputs,size_t num_inputs,size_t blocks,const uint32_t key[8],uint64_t counter,boolean_t increment_counter,uint8_t flags,uint8_t flags_start,uint8_t flags_end,uint8_t * out)1352a58b312SMartin Matuska static void blake3_hash_many_sse41(const uint8_t * const *inputs,
1362a58b312SMartin Matuska size_t num_inputs, size_t blocks, const uint32_t key[8],
1372a58b312SMartin Matuska uint64_t counter, boolean_t increment_counter, uint8_t flags,
1382a58b312SMartin Matuska uint8_t flags_start, uint8_t flags_end, uint8_t *out) {
1392a58b312SMartin Matuska kfpu_begin();
1402a58b312SMartin Matuska zfs_blake3_hash_many_sse41(inputs, num_inputs, blocks, key, counter,
1412a58b312SMartin Matuska increment_counter, flags, flags_start, flags_end, out);
1422a58b312SMartin Matuska kfpu_end();
1432a58b312SMartin Matuska }
1442a58b312SMartin Matuska
blake3_is_sse41_supported(void)1452a58b312SMartin Matuska static boolean_t blake3_is_sse41_supported(void)
1462a58b312SMartin Matuska {
1472a58b312SMartin Matuska #if defined(__x86_64)
1482a58b312SMartin Matuska return (kfpu_allowed() && zfs_sse4_1_available());
1492a58b312SMartin Matuska #elif defined(__PPC64__)
1502a58b312SMartin Matuska return (kfpu_allowed() && zfs_vsx_available());
1512a58b312SMartin Matuska #else
1522a58b312SMartin Matuska return (kfpu_allowed());
1532a58b312SMartin Matuska #endif
1542a58b312SMartin Matuska }
1552a58b312SMartin Matuska
1562a58b312SMartin Matuska const blake3_ops_t blake3_sse41_impl = {
1572a58b312SMartin Matuska .compress_in_place = blake3_compress_in_place_sse41,
1582a58b312SMartin Matuska .compress_xof = blake3_compress_xof_sse41,
1592a58b312SMartin Matuska .hash_many = blake3_hash_many_sse41,
1602a58b312SMartin Matuska .is_supported = blake3_is_sse41_supported,
1612a58b312SMartin Matuska .degree = 4,
1622a58b312SMartin Matuska .name = "sse41"
1632a58b312SMartin Matuska };
1642a58b312SMartin Matuska #endif
1652a58b312SMartin Matuska
1662a58b312SMartin Matuska #if defined(__x86_64) && defined(HAVE_SSE4_1) && defined(HAVE_AVX2)
1672a58b312SMartin Matuska extern void ASMABI zfs_blake3_hash_many_avx2(const uint8_t * const *inputs,
1682a58b312SMartin Matuska size_t num_inputs, size_t blocks, const uint32_t key[8],
1692a58b312SMartin Matuska uint64_t counter, boolean_t increment_counter, uint8_t flags,
1702a58b312SMartin Matuska uint8_t flags_start, uint8_t flags_end, uint8_t *out);
1712a58b312SMartin Matuska
blake3_hash_many_avx2(const uint8_t * const * inputs,size_t num_inputs,size_t blocks,const uint32_t key[8],uint64_t counter,boolean_t increment_counter,uint8_t flags,uint8_t flags_start,uint8_t flags_end,uint8_t * out)1722a58b312SMartin Matuska static void blake3_hash_many_avx2(const uint8_t * const *inputs,
1732a58b312SMartin Matuska size_t num_inputs, size_t blocks, const uint32_t key[8],
1742a58b312SMartin Matuska uint64_t counter, boolean_t increment_counter, uint8_t flags,
1752a58b312SMartin Matuska uint8_t flags_start, uint8_t flags_end, uint8_t *out) {
1762a58b312SMartin Matuska kfpu_begin();
1772a58b312SMartin Matuska zfs_blake3_hash_many_avx2(inputs, num_inputs, blocks, key, counter,
1782a58b312SMartin Matuska increment_counter, flags, flags_start, flags_end, out);
1792a58b312SMartin Matuska kfpu_end();
1802a58b312SMartin Matuska }
1812a58b312SMartin Matuska
blake3_is_avx2_supported(void)1822a58b312SMartin Matuska static boolean_t blake3_is_avx2_supported(void)
1832a58b312SMartin Matuska {
1842a58b312SMartin Matuska return (kfpu_allowed() && zfs_sse4_1_available() &&
1852a58b312SMartin Matuska zfs_avx2_available());
1862a58b312SMartin Matuska }
1872a58b312SMartin Matuska
1882a58b312SMartin Matuska const blake3_ops_t
1892a58b312SMartin Matuska blake3_avx2_impl = {
1902a58b312SMartin Matuska .compress_in_place = blake3_compress_in_place_sse41,
1912a58b312SMartin Matuska .compress_xof = blake3_compress_xof_sse41,
1922a58b312SMartin Matuska .hash_many = blake3_hash_many_avx2,
1932a58b312SMartin Matuska .is_supported = blake3_is_avx2_supported,
1942a58b312SMartin Matuska .degree = 8,
1952a58b312SMartin Matuska .name = "avx2"
1962a58b312SMartin Matuska };
1972a58b312SMartin Matuska #endif
1982a58b312SMartin Matuska
1992a58b312SMartin Matuska #if defined(__x86_64) && defined(HAVE_AVX512F) && defined(HAVE_AVX512VL)
2002a58b312SMartin Matuska extern void ASMABI zfs_blake3_compress_in_place_avx512(uint32_t cv[8],
2012a58b312SMartin Matuska const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len,
2022a58b312SMartin Matuska uint64_t counter, uint8_t flags);
2032a58b312SMartin Matuska
2042a58b312SMartin Matuska extern void ASMABI zfs_blake3_compress_xof_avx512(const uint32_t cv[8],
2052a58b312SMartin Matuska const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len,
2062a58b312SMartin Matuska uint64_t counter, uint8_t flags, uint8_t out[64]);
2072a58b312SMartin Matuska
2082a58b312SMartin Matuska extern void ASMABI zfs_blake3_hash_many_avx512(const uint8_t * const *inputs,
2092a58b312SMartin Matuska size_t num_inputs, size_t blocks, const uint32_t key[8],
2102a58b312SMartin Matuska uint64_t counter, boolean_t increment_counter, uint8_t flags,
2112a58b312SMartin Matuska uint8_t flags_start, uint8_t flags_end, uint8_t *out);
2122a58b312SMartin Matuska
blake3_compress_in_place_avx512(uint32_t cv[8],const uint8_t block[BLAKE3_BLOCK_LEN],uint8_t block_len,uint64_t counter,uint8_t flags)2132a58b312SMartin Matuska static void blake3_compress_in_place_avx512(uint32_t cv[8],
2142a58b312SMartin Matuska const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len,
2152a58b312SMartin Matuska uint64_t counter, uint8_t flags) {
2162a58b312SMartin Matuska kfpu_begin();
2172a58b312SMartin Matuska zfs_blake3_compress_in_place_avx512(cv, block, block_len, counter,
2182a58b312SMartin Matuska flags);
2192a58b312SMartin Matuska kfpu_end();
2202a58b312SMartin Matuska }
2212a58b312SMartin Matuska
blake3_compress_xof_avx512(const uint32_t cv[8],const uint8_t block[BLAKE3_BLOCK_LEN],uint8_t block_len,uint64_t counter,uint8_t flags,uint8_t out[64])2222a58b312SMartin Matuska static void blake3_compress_xof_avx512(const uint32_t cv[8],
2232a58b312SMartin Matuska const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len,
2242a58b312SMartin Matuska uint64_t counter, uint8_t flags, uint8_t out[64]) {
2252a58b312SMartin Matuska kfpu_begin();
2262a58b312SMartin Matuska zfs_blake3_compress_xof_avx512(cv, block, block_len, counter, flags,
2272a58b312SMartin Matuska out);
2282a58b312SMartin Matuska kfpu_end();
2292a58b312SMartin Matuska }
2302a58b312SMartin Matuska
blake3_hash_many_avx512(const uint8_t * const * inputs,size_t num_inputs,size_t blocks,const uint32_t key[8],uint64_t counter,boolean_t increment_counter,uint8_t flags,uint8_t flags_start,uint8_t flags_end,uint8_t * out)2312a58b312SMartin Matuska static void blake3_hash_many_avx512(const uint8_t * const *inputs,
2322a58b312SMartin Matuska size_t num_inputs, size_t blocks, const uint32_t key[8],
2332a58b312SMartin Matuska uint64_t counter, boolean_t increment_counter, uint8_t flags,
2342a58b312SMartin Matuska uint8_t flags_start, uint8_t flags_end, uint8_t *out) {
2352a58b312SMartin Matuska kfpu_begin();
2362a58b312SMartin Matuska zfs_blake3_hash_many_avx512(inputs, num_inputs, blocks, key, counter,
2372a58b312SMartin Matuska increment_counter, flags, flags_start, flags_end, out);
2382a58b312SMartin Matuska kfpu_end();
2392a58b312SMartin Matuska }
2402a58b312SMartin Matuska
blake3_is_avx512_supported(void)2412a58b312SMartin Matuska static boolean_t blake3_is_avx512_supported(void)
2422a58b312SMartin Matuska {
2432a58b312SMartin Matuska return (kfpu_allowed() && zfs_avx512f_available() &&
2442a58b312SMartin Matuska zfs_avx512vl_available());
2452a58b312SMartin Matuska }
2462a58b312SMartin Matuska
2472a58b312SMartin Matuska const blake3_ops_t blake3_avx512_impl = {
2482a58b312SMartin Matuska .compress_in_place = blake3_compress_in_place_avx512,
2492a58b312SMartin Matuska .compress_xof = blake3_compress_xof_avx512,
2502a58b312SMartin Matuska .hash_many = blake3_hash_many_avx512,
2512a58b312SMartin Matuska .is_supported = blake3_is_avx512_supported,
2522a58b312SMartin Matuska .degree = 16,
2532a58b312SMartin Matuska .name = "avx512"
2542a58b312SMartin Matuska };
2552a58b312SMartin Matuska #endif
2562a58b312SMartin Matuska
2572a58b312SMartin Matuska extern const blake3_ops_t blake3_generic_impl;
2582a58b312SMartin Matuska
259c7046f76SMartin Matuska static const blake3_ops_t *const blake3_impls[] = {
2601f1e2261SMartin Matuska &blake3_generic_impl,
261*6c8358cdSWarner Losh #ifdef USE_SIMD
2621f1e2261SMartin Matuska #if defined(__aarch64__) || \
2631f1e2261SMartin Matuska (defined(__x86_64) && defined(HAVE_SSE2)) || \
2641f1e2261SMartin Matuska (defined(__PPC64__) && defined(__LITTLE_ENDIAN__))
2651f1e2261SMartin Matuska &blake3_sse2_impl,
2661f1e2261SMartin Matuska #endif
2671f1e2261SMartin Matuska #if defined(__aarch64__) || \
2681f1e2261SMartin Matuska (defined(__x86_64) && defined(HAVE_SSE4_1)) || \
2691f1e2261SMartin Matuska (defined(__PPC64__) && defined(__LITTLE_ENDIAN__))
2701f1e2261SMartin Matuska &blake3_sse41_impl,
2711f1e2261SMartin Matuska #endif
2721f1e2261SMartin Matuska #if defined(__x86_64) && defined(HAVE_SSE4_1) && defined(HAVE_AVX2)
2731f1e2261SMartin Matuska &blake3_avx2_impl,
2741f1e2261SMartin Matuska #endif
2751f1e2261SMartin Matuska #if defined(__x86_64) && defined(HAVE_AVX512F) && defined(HAVE_AVX512VL)
2761f1e2261SMartin Matuska &blake3_avx512_impl,
2771f1e2261SMartin Matuska #endif
278*6c8358cdSWarner Losh #endif
2791f1e2261SMartin Matuska };
2801f1e2261SMartin Matuska
2812a58b312SMartin Matuska /* use the generic implementation functions */
2822a58b312SMartin Matuska #define IMPL_NAME "blake3"
2832a58b312SMartin Matuska #define IMPL_OPS_T blake3_ops_t
2842a58b312SMartin Matuska #define IMPL_ARRAY blake3_impls
2852a58b312SMartin Matuska #define IMPL_GET_OPS blake3_get_ops
2862a58b312SMartin Matuska #define ZFS_IMPL_OPS zfs_blake3_ops
2872a58b312SMartin Matuska #include <generic_impl.c>
2881f1e2261SMartin Matuska
2892a58b312SMartin Matuska #ifdef _KERNEL
2901f1e2261SMartin Matuska void **blake3_per_cpu_ctx;
2911f1e2261SMartin Matuska
2921f1e2261SMartin Matuska void
blake3_per_cpu_ctx_init(void)2931f1e2261SMartin Matuska blake3_per_cpu_ctx_init(void)
2941f1e2261SMartin Matuska {
2951f1e2261SMartin Matuska /*
2961f1e2261SMartin Matuska * Create "The Godfather" ptr to hold all blake3 ctx
2971f1e2261SMartin Matuska */
2981f1e2261SMartin Matuska blake3_per_cpu_ctx = kmem_alloc(max_ncpus * sizeof (void *), KM_SLEEP);
2991f1e2261SMartin Matuska for (int i = 0; i < max_ncpus; i++) {
3001f1e2261SMartin Matuska blake3_per_cpu_ctx[i] = kmem_alloc(sizeof (BLAKE3_CTX),
3011f1e2261SMartin Matuska KM_SLEEP);
3021f1e2261SMartin Matuska }
3031f1e2261SMartin Matuska }
3041f1e2261SMartin Matuska
3051f1e2261SMartin Matuska void
blake3_per_cpu_ctx_fini(void)3061f1e2261SMartin Matuska blake3_per_cpu_ctx_fini(void)
3071f1e2261SMartin Matuska {
3081f1e2261SMartin Matuska for (int i = 0; i < max_ncpus; i++) {
3091f1e2261SMartin Matuska memset(blake3_per_cpu_ctx[i], 0, sizeof (BLAKE3_CTX));
3101f1e2261SMartin Matuska kmem_free(blake3_per_cpu_ctx[i], sizeof (BLAKE3_CTX));
3111f1e2261SMartin Matuska }
3121f1e2261SMartin Matuska memset(blake3_per_cpu_ctx, 0, max_ncpus * sizeof (void *));
3131f1e2261SMartin Matuska kmem_free(blake3_per_cpu_ctx, max_ncpus * sizeof (void *));
3141f1e2261SMartin Matuska }
3151f1e2261SMartin Matuska
316c7046f76SMartin Matuska #define IMPL_FMT(impl, i) (((impl) == (i)) ? "[%s] " : "%s ")
3171f1e2261SMartin Matuska
318c7046f76SMartin Matuska #if defined(__linux__)
3191f1e2261SMartin Matuska
3201f1e2261SMartin Matuska static int
blake3_param_get(char * buffer,zfs_kernel_param_t * unused)321c7046f76SMartin Matuska blake3_param_get(char *buffer, zfs_kernel_param_t *unused)
3221f1e2261SMartin Matuska {
3232a58b312SMartin Matuska const uint32_t impl = IMPL_READ(generic_impl_chosen);
3241f1e2261SMartin Matuska char *fmt;
325c7046f76SMartin Matuska int cnt = 0;
3261f1e2261SMartin Matuska
3271f1e2261SMartin Matuska /* cycling */
328c7046f76SMartin Matuska fmt = IMPL_FMT(impl, IMPL_CYCLE);
329bb2d13b6SMartin Matuska cnt += kmem_scnprintf(buffer + cnt, PAGE_SIZE - cnt, fmt, "cycle");
3301f1e2261SMartin Matuska
331c7046f76SMartin Matuska /* list fastest */
332c7046f76SMartin Matuska fmt = IMPL_FMT(impl, IMPL_FASTEST);
333bb2d13b6SMartin Matuska cnt += kmem_scnprintf(buffer + cnt, PAGE_SIZE - cnt, fmt, "fastest");
3341f1e2261SMartin Matuska
335c7046f76SMartin Matuska /* list all supported implementations */
3362a58b312SMartin Matuska generic_impl_init();
3372a58b312SMartin Matuska for (uint32_t i = 0; i < generic_supp_impls_cnt; ++i) {
338c7046f76SMartin Matuska fmt = IMPL_FMT(impl, i);
339bb2d13b6SMartin Matuska cnt += kmem_scnprintf(buffer + cnt, PAGE_SIZE - cnt, fmt,
3402a58b312SMartin Matuska blake3_impls[i]->name);
3411f1e2261SMartin Matuska }
3421f1e2261SMartin Matuska
3431f1e2261SMartin Matuska return (cnt);
3441f1e2261SMartin Matuska }
3451f1e2261SMartin Matuska
346c7046f76SMartin Matuska static int
blake3_param_set(const char * val,zfs_kernel_param_t * unused)347c7046f76SMartin Matuska blake3_param_set(const char *val, zfs_kernel_param_t *unused)
348c7046f76SMartin Matuska {
349c7046f76SMartin Matuska (void) unused;
3502a58b312SMartin Matuska return (generic_impl_setname(val));
351c7046f76SMartin Matuska }
352c7046f76SMartin Matuska
353c7046f76SMartin Matuska #elif defined(__FreeBSD__)
354c7046f76SMartin Matuska
355c7046f76SMartin Matuska #include <sys/sbuf.h>
356c7046f76SMartin Matuska
357c7046f76SMartin Matuska static int
blake3_param(ZFS_MODULE_PARAM_ARGS)358c7046f76SMartin Matuska blake3_param(ZFS_MODULE_PARAM_ARGS)
359c7046f76SMartin Matuska {
360c7046f76SMartin Matuska int err;
361c7046f76SMartin Matuska
3622a58b312SMartin Matuska generic_impl_init();
363c7046f76SMartin Matuska if (req->newptr == NULL) {
3642a58b312SMartin Matuska const uint32_t impl = IMPL_READ(generic_impl_chosen);
365c7046f76SMartin Matuska const int init_buflen = 64;
366c7046f76SMartin Matuska const char *fmt;
367c7046f76SMartin Matuska struct sbuf *s;
368c7046f76SMartin Matuska
369c7046f76SMartin Matuska s = sbuf_new_for_sysctl(NULL, NULL, init_buflen, req);
370c7046f76SMartin Matuska
371c7046f76SMartin Matuska /* cycling */
372c7046f76SMartin Matuska fmt = IMPL_FMT(impl, IMPL_CYCLE);
373c7046f76SMartin Matuska (void) sbuf_printf(s, fmt, "cycle");
374c7046f76SMartin Matuska
375c7046f76SMartin Matuska /* list fastest */
376c7046f76SMartin Matuska fmt = IMPL_FMT(impl, IMPL_FASTEST);
377c7046f76SMartin Matuska (void) sbuf_printf(s, fmt, "fastest");
378c7046f76SMartin Matuska
379c7046f76SMartin Matuska /* list all supported implementations */
3802a58b312SMartin Matuska for (uint32_t i = 0; i < generic_supp_impls_cnt; ++i) {
381c7046f76SMartin Matuska fmt = IMPL_FMT(impl, i);
3822a58b312SMartin Matuska (void) sbuf_printf(s, fmt, generic_supp_impls[i]->name);
383c7046f76SMartin Matuska }
384c7046f76SMartin Matuska
385c7046f76SMartin Matuska err = sbuf_finish(s);
386c7046f76SMartin Matuska sbuf_delete(s);
387c7046f76SMartin Matuska
388c7046f76SMartin Matuska return (err);
389c7046f76SMartin Matuska }
390c7046f76SMartin Matuska
391c7046f76SMartin Matuska char buf[16];
392c7046f76SMartin Matuska
393c7046f76SMartin Matuska err = sysctl_handle_string(oidp, buf, sizeof (buf), req);
394c7046f76SMartin Matuska if (err) {
395c7046f76SMartin Matuska return (err);
396c7046f76SMartin Matuska }
397c7046f76SMartin Matuska
3982a58b312SMartin Matuska return (-generic_impl_setname(buf));
399c7046f76SMartin Matuska }
400c7046f76SMartin Matuska #endif
401c7046f76SMartin Matuska
402c7046f76SMartin Matuska #undef IMPL_FMT
403c7046f76SMartin Matuska
404c7046f76SMartin Matuska ZFS_MODULE_VIRTUAL_PARAM_CALL(zfs, zfs_, blake3_impl,
405c7046f76SMartin Matuska blake3_param_set, blake3_param_get, ZMOD_RW, \
406c7046f76SMartin Matuska "Select BLAKE3 implementation.");
4071f1e2261SMartin Matuska #endif
408