xref: /freebsd-src/sys/contrib/openzfs/module/icp/algs/sha2/sha512_impl.c (revision 3494f7c019fc6558a99f63b7f647373b89bcde92)
12a58b312SMartin Matuska /*
22a58b312SMartin Matuska  * CDDL HEADER START
32a58b312SMartin Matuska  *
42a58b312SMartin Matuska  * The contents of this file are subject to the terms of the
52a58b312SMartin Matuska  * Common Development and Distribution License (the "License").
62a58b312SMartin Matuska  * You may not use this file except in compliance with the License.
72a58b312SMartin Matuska  *
82a58b312SMartin Matuska  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
92a58b312SMartin Matuska  * or https://opensource.org/licenses/CDDL-1.0.
102a58b312SMartin Matuska  * See the License for the specific language governing permissions
112a58b312SMartin Matuska  * and limitations under the License.
122a58b312SMartin Matuska  *
132a58b312SMartin Matuska  * When distributing Covered Code, include this CDDL HEADER in each
142a58b312SMartin Matuska  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
152a58b312SMartin Matuska  * If applicable, add the following below this CDDL HEADER, with the
162a58b312SMartin Matuska  * fields enclosed by brackets "[]" replaced with your own identifying
172a58b312SMartin Matuska  * information: Portions Copyright [yyyy] [name of copyright owner]
182a58b312SMartin Matuska  *
192a58b312SMartin Matuska  * CDDL HEADER END
202a58b312SMartin Matuska  */
212a58b312SMartin Matuska 
222a58b312SMartin Matuska /*
232a58b312SMartin Matuska  * Copyright (c) 2022 Tino Reichardt <milky-zfs@mcmilk.de>
242a58b312SMartin Matuska  */
252a58b312SMartin Matuska 
262a58b312SMartin Matuska #include <sys/simd.h>
272a58b312SMartin Matuska #include <sys/zfs_context.h>
282a58b312SMartin Matuska #include <sys/zfs_impl.h>
292a58b312SMartin Matuska #include <sys/sha2.h>
302a58b312SMartin Matuska 
312a58b312SMartin Matuska #include <sha2/sha2_impl.h>
322a58b312SMartin Matuska #include <sys/asm_linkage.h>
332a58b312SMartin Matuska 
342a58b312SMartin Matuska #define	TF(E, N) \
352a58b312SMartin Matuska 	extern void ASMABI E(uint64_t s[8], const void *, size_t); \
362a58b312SMartin Matuska 	static inline void N(uint64_t s[8], const void *d, size_t b) { \
372a58b312SMartin Matuska 	kfpu_begin(); E(s, d, b); kfpu_end(); \
382a58b312SMartin Matuska }
392a58b312SMartin Matuska 
402a58b312SMartin Matuska /* some implementation is always okay */
sha2_is_supported(void)412a58b312SMartin Matuska static inline boolean_t sha2_is_supported(void)
422a58b312SMartin Matuska {
432a58b312SMartin Matuska 	return (B_TRUE);
442a58b312SMartin Matuska }
452a58b312SMartin Matuska 
462a58b312SMartin Matuska #if defined(__x86_64)
472a58b312SMartin Matuska 
482a58b312SMartin Matuska /* Users of ASMABI requires all calls to be from wrappers */
492a58b312SMartin Matuska extern void ASMABI
502a58b312SMartin Matuska zfs_sha512_transform_x64(uint64_t s[8], const void *, size_t);
512a58b312SMartin Matuska 
522a58b312SMartin Matuska static inline void
tf_sha512_transform_x64(uint64_t s[8],const void * d,size_t b)532a58b312SMartin Matuska tf_sha512_transform_x64(uint64_t s[8], const void *d, size_t b)
542a58b312SMartin Matuska {
552a58b312SMartin Matuska 	zfs_sha512_transform_x64(s, d, b);
562a58b312SMartin Matuska }
572a58b312SMartin Matuska const sha512_ops_t sha512_x64_impl = {
582a58b312SMartin Matuska 	.is_supported = sha2_is_supported,
592a58b312SMartin Matuska 	.transform = tf_sha512_transform_x64,
602a58b312SMartin Matuska 	.name = "x64"
612a58b312SMartin Matuska };
622a58b312SMartin Matuska 
632a58b312SMartin Matuska #if defined(HAVE_AVX)
sha2_have_avx(void)642a58b312SMartin Matuska static boolean_t sha2_have_avx(void)
652a58b312SMartin Matuska {
662a58b312SMartin Matuska 	return (kfpu_allowed() && zfs_avx_available());
672a58b312SMartin Matuska }
682a58b312SMartin Matuska 
692a58b312SMartin Matuska TF(zfs_sha512_transform_avx, tf_sha512_avx);
702a58b312SMartin Matuska const sha512_ops_t sha512_avx_impl = {
712a58b312SMartin Matuska 	.is_supported = sha2_have_avx,
722a58b312SMartin Matuska 	.transform = tf_sha512_avx,
732a58b312SMartin Matuska 	.name = "avx"
742a58b312SMartin Matuska };
752a58b312SMartin Matuska #endif
762a58b312SMartin Matuska 
772a58b312SMartin Matuska #if defined(HAVE_AVX2)
sha2_have_avx2(void)782a58b312SMartin Matuska static boolean_t sha2_have_avx2(void)
792a58b312SMartin Matuska {
802a58b312SMartin Matuska 	return (kfpu_allowed() && zfs_avx2_available());
812a58b312SMartin Matuska }
822a58b312SMartin Matuska 
832a58b312SMartin Matuska TF(zfs_sha512_transform_avx2, tf_sha512_avx2);
842a58b312SMartin Matuska const sha512_ops_t sha512_avx2_impl = {
852a58b312SMartin Matuska 	.is_supported = sha2_have_avx2,
862a58b312SMartin Matuska 	.transform = tf_sha512_avx2,
872a58b312SMartin Matuska 	.name = "avx2"
882a58b312SMartin Matuska };
892a58b312SMartin Matuska #endif
902a58b312SMartin Matuska 
91*3494f7c0SMartin Matuska #elif defined(__aarch64__) || defined(__arm__)
922a58b312SMartin Matuska extern void zfs_sha512_block_armv7(uint64_t s[8], const void *, size_t);
932a58b312SMartin Matuska const sha512_ops_t sha512_armv7_impl = {
942a58b312SMartin Matuska 	.is_supported = sha2_is_supported,
952a58b312SMartin Matuska 	.transform = zfs_sha512_block_armv7,
962a58b312SMartin Matuska 	.name = "armv7"
972a58b312SMartin Matuska };
982a58b312SMartin Matuska 
99*3494f7c0SMartin Matuska #if defined(__aarch64__)
sha512_have_armv8ce(void)1002a58b312SMartin Matuska static boolean_t sha512_have_armv8ce(void)
1012a58b312SMartin Matuska {
1022a58b312SMartin Matuska 	return (kfpu_allowed() && zfs_sha512_available());
1032a58b312SMartin Matuska }
1042a58b312SMartin Matuska 
1052a58b312SMartin Matuska TF(zfs_sha512_block_armv8, tf_sha512_armv8ce);
1062a58b312SMartin Matuska const sha512_ops_t sha512_armv8_impl = {
1072a58b312SMartin Matuska 	.is_supported = sha512_have_armv8ce,
1082a58b312SMartin Matuska 	.transform = tf_sha512_armv8ce,
1092a58b312SMartin Matuska 	.name = "armv8-ce"
1102a58b312SMartin Matuska };
111*3494f7c0SMartin Matuska #endif
1122a58b312SMartin Matuska 
113*3494f7c0SMartin Matuska #if defined(__arm__) && __ARM_ARCH > 6
sha512_have_neon(void)1142a58b312SMartin Matuska static boolean_t sha512_have_neon(void)
1152a58b312SMartin Matuska {
1162a58b312SMartin Matuska 	return (kfpu_allowed() && zfs_neon_available());
1172a58b312SMartin Matuska }
1182a58b312SMartin Matuska 
1192a58b312SMartin Matuska TF(zfs_sha512_block_neon, tf_sha512_neon);
1202a58b312SMartin Matuska const sha512_ops_t sha512_neon_impl = {
1212a58b312SMartin Matuska 	.is_supported = sha512_have_neon,
1222a58b312SMartin Matuska 	.transform = tf_sha512_neon,
1232a58b312SMartin Matuska 	.name = "neon"
1242a58b312SMartin Matuska };
125*3494f7c0SMartin Matuska #endif
1262a58b312SMartin Matuska 
1272a58b312SMartin Matuska #elif defined(__PPC64__)
1282a58b312SMartin Matuska TF(zfs_sha512_ppc, tf_sha512_ppc);
1292a58b312SMartin Matuska const sha512_ops_t sha512_ppc_impl = {
1302a58b312SMartin Matuska 	.is_supported = sha2_is_supported,
1312a58b312SMartin Matuska 	.transform = tf_sha512_ppc,
1322a58b312SMartin Matuska 	.name = "ppc"
1332a58b312SMartin Matuska };
1342a58b312SMartin Matuska 
sha512_have_isa207(void)1352a58b312SMartin Matuska static boolean_t sha512_have_isa207(void)
1362a58b312SMartin Matuska {
1372a58b312SMartin Matuska 	return (kfpu_allowed() && zfs_isa207_available());
1382a58b312SMartin Matuska }
1392a58b312SMartin Matuska 
1402a58b312SMartin Matuska TF(zfs_sha512_power8, tf_sha512_power8);
1412a58b312SMartin Matuska const sha512_ops_t sha512_power8_impl = {
1422a58b312SMartin Matuska 	.is_supported = sha512_have_isa207,
1432a58b312SMartin Matuska 	.transform = tf_sha512_power8,
1442a58b312SMartin Matuska 	.name = "power8"
1452a58b312SMartin Matuska };
1462a58b312SMartin Matuska #endif /* __PPC64__ */
1472a58b312SMartin Matuska 
1482a58b312SMartin Matuska /* the two generic ones */
1492a58b312SMartin Matuska extern const sha512_ops_t sha512_generic_impl;
1502a58b312SMartin Matuska 
1512a58b312SMartin Matuska /* array with all sha512 implementations */
1522a58b312SMartin Matuska static const sha512_ops_t *const sha512_impls[] = {
1532a58b312SMartin Matuska 	&sha512_generic_impl,
1542a58b312SMartin Matuska #if defined(__x86_64)
1552a58b312SMartin Matuska 	&sha512_x64_impl,
1562a58b312SMartin Matuska #endif
1572a58b312SMartin Matuska #if defined(__x86_64) && defined(HAVE_AVX)
1582a58b312SMartin Matuska 	&sha512_avx_impl,
1592a58b312SMartin Matuska #endif
1602a58b312SMartin Matuska #if defined(__x86_64) && defined(HAVE_AVX2)
1612a58b312SMartin Matuska 	&sha512_avx2_impl,
1622a58b312SMartin Matuska #endif
163*3494f7c0SMartin Matuska #if defined(__aarch64__) || defined(__arm__)
1642a58b312SMartin Matuska 	&sha512_armv7_impl,
165*3494f7c0SMartin Matuska #if defined(__aarch64__)
1662a58b312SMartin Matuska 	&sha512_armv8_impl,
1672a58b312SMartin Matuska #endif
1682a58b312SMartin Matuska #if defined(__arm__) && __ARM_ARCH > 6
1692a58b312SMartin Matuska 	&sha512_neon_impl,
1702a58b312SMartin Matuska #endif
171*3494f7c0SMartin Matuska #endif
1722a58b312SMartin Matuska #if defined(__PPC64__)
1732a58b312SMartin Matuska 	&sha512_ppc_impl,
1742a58b312SMartin Matuska 	&sha512_power8_impl,
1752a58b312SMartin Matuska #endif /* __PPC64__ */
1762a58b312SMartin Matuska };
1772a58b312SMartin Matuska 
1782a58b312SMartin Matuska /* use the generic implementation functions */
1792a58b312SMartin Matuska #define	IMPL_NAME		"sha512"
1802a58b312SMartin Matuska #define	IMPL_OPS_T		sha512_ops_t
1812a58b312SMartin Matuska #define	IMPL_ARRAY		sha512_impls
1822a58b312SMartin Matuska #define	IMPL_GET_OPS		sha512_get_ops
1832a58b312SMartin Matuska #define	ZFS_IMPL_OPS		zfs_sha512_ops
1842a58b312SMartin Matuska #include <generic_impl.c>
1852a58b312SMartin Matuska 
1862a58b312SMartin Matuska #ifdef _KERNEL
1872a58b312SMartin Matuska 
1882a58b312SMartin Matuska #define	IMPL_FMT(impl, i)	(((impl) == (i)) ? "[%s] " : "%s ")
1892a58b312SMartin Matuska 
1902a58b312SMartin Matuska #if defined(__linux__)
1912a58b312SMartin Matuska 
1922a58b312SMartin Matuska static int
sha512_param_get(char * buffer,zfs_kernel_param_t * unused)1932a58b312SMartin Matuska sha512_param_get(char *buffer, zfs_kernel_param_t *unused)
1942a58b312SMartin Matuska {
1952a58b312SMartin Matuska 	const uint32_t impl = IMPL_READ(generic_impl_chosen);
1962a58b312SMartin Matuska 	char *fmt;
1972a58b312SMartin Matuska 	int cnt = 0;
1982a58b312SMartin Matuska 
1992a58b312SMartin Matuska 	/* cycling */
2002a58b312SMartin Matuska 	fmt = IMPL_FMT(impl, IMPL_CYCLE);
2012a58b312SMartin Matuska 	cnt += sprintf(buffer + cnt, fmt, "cycle");
2022a58b312SMartin Matuska 
2032a58b312SMartin Matuska 	/* list fastest */
2042a58b312SMartin Matuska 	fmt = IMPL_FMT(impl, IMPL_FASTEST);
2052a58b312SMartin Matuska 	cnt += sprintf(buffer + cnt, fmt, "fastest");
2062a58b312SMartin Matuska 
2072a58b312SMartin Matuska 	/* list all supported implementations */
2082a58b312SMartin Matuska 	generic_impl_init();
2092a58b312SMartin Matuska 	for (uint32_t i = 0; i < generic_supp_impls_cnt; ++i) {
2102a58b312SMartin Matuska 		fmt = IMPL_FMT(impl, i);
2112a58b312SMartin Matuska 		cnt += sprintf(buffer + cnt, fmt,
2122a58b312SMartin Matuska 		    generic_supp_impls[i]->name);
2132a58b312SMartin Matuska 	}
2142a58b312SMartin Matuska 
2152a58b312SMartin Matuska 	return (cnt);
2162a58b312SMartin Matuska }
2172a58b312SMartin Matuska 
2182a58b312SMartin Matuska static int
sha512_param_set(const char * val,zfs_kernel_param_t * unused)2192a58b312SMartin Matuska sha512_param_set(const char *val, zfs_kernel_param_t *unused)
2202a58b312SMartin Matuska {
2212a58b312SMartin Matuska 	(void) unused;
2222a58b312SMartin Matuska 	return (generic_impl_setname(val));
2232a58b312SMartin Matuska }
2242a58b312SMartin Matuska 
2252a58b312SMartin Matuska #elif defined(__FreeBSD__)
2262a58b312SMartin Matuska 
2272a58b312SMartin Matuska #include <sys/sbuf.h>
2282a58b312SMartin Matuska 
2292a58b312SMartin Matuska static int
sha512_param(ZFS_MODULE_PARAM_ARGS)2302a58b312SMartin Matuska sha512_param(ZFS_MODULE_PARAM_ARGS)
2312a58b312SMartin Matuska {
2322a58b312SMartin Matuska 	int err;
2332a58b312SMartin Matuska 
2342a58b312SMartin Matuska 	generic_impl_init();
2352a58b312SMartin Matuska 	if (req->newptr == NULL) {
2362a58b312SMartin Matuska 		const uint32_t impl = IMPL_READ(generic_impl_chosen);
2372a58b312SMartin Matuska 		const int init_buflen = 64;
2382a58b312SMartin Matuska 		const char *fmt;
2392a58b312SMartin Matuska 		struct sbuf *s;
2402a58b312SMartin Matuska 
2412a58b312SMartin Matuska 		s = sbuf_new_for_sysctl(NULL, NULL, init_buflen, req);
2422a58b312SMartin Matuska 
2432a58b312SMartin Matuska 		/* cycling */
2442a58b312SMartin Matuska 		fmt = IMPL_FMT(impl, IMPL_CYCLE);
2452a58b312SMartin Matuska 		(void) sbuf_printf(s, fmt, "cycle");
2462a58b312SMartin Matuska 
2472a58b312SMartin Matuska 		/* list fastest */
2482a58b312SMartin Matuska 		fmt = IMPL_FMT(impl, IMPL_FASTEST);
2492a58b312SMartin Matuska 		(void) sbuf_printf(s, fmt, "fastest");
2502a58b312SMartin Matuska 
2512a58b312SMartin Matuska 		/* list all supported implementations */
2522a58b312SMartin Matuska 		for (uint32_t i = 0; i < generic_supp_impls_cnt; ++i) {
2532a58b312SMartin Matuska 			fmt = IMPL_FMT(impl, i);
2542a58b312SMartin Matuska 			(void) sbuf_printf(s, fmt, generic_supp_impls[i]->name);
2552a58b312SMartin Matuska 		}
2562a58b312SMartin Matuska 
2572a58b312SMartin Matuska 		err = sbuf_finish(s);
2582a58b312SMartin Matuska 		sbuf_delete(s);
2592a58b312SMartin Matuska 
2602a58b312SMartin Matuska 		return (err);
2612a58b312SMartin Matuska 	}
2622a58b312SMartin Matuska 
2632a58b312SMartin Matuska 	/* we got module parameter */
2642a58b312SMartin Matuska 	char buf[16];
2652a58b312SMartin Matuska 
2662a58b312SMartin Matuska 	err = sysctl_handle_string(oidp, buf, sizeof (buf), req);
2672a58b312SMartin Matuska 	if (err) {
2682a58b312SMartin Matuska 		return (err);
2692a58b312SMartin Matuska 	}
2702a58b312SMartin Matuska 
2712a58b312SMartin Matuska 	return (-generic_impl_setname(buf));
2722a58b312SMartin Matuska }
2732a58b312SMartin Matuska #endif
2742a58b312SMartin Matuska 
2752a58b312SMartin Matuska #undef IMPL_FMT
2762a58b312SMartin Matuska 
2772a58b312SMartin Matuska ZFS_MODULE_VIRTUAL_PARAM_CALL(zfs, zfs_, sha512_impl,
2782a58b312SMartin Matuska     sha512_param_set, sha512_param_get, ZMOD_RW, \
2792a58b312SMartin Matuska 	"Select SHA512 implementation.");
2802a58b312SMartin Matuska #endif
2812a58b312SMartin Matuska 
2822a58b312SMartin Matuska #undef TF
283