diff --git a/config/Rules.am b/config/Rules.am index f8626f368..5117929ca 100644 --- a/config/Rules.am +++ b/config/Rules.am @@ -7,6 +7,7 @@ PHONY = AM_CPPFLAGS = \ -include $(top_builddir)/zfs_config.h \ + -include $(top_srcdir)/include/sys/simd_config.h \ -I$(top_builddir)/include \ -I$(top_srcdir)/include \ -I$(top_srcdir)/lib/libspl/include \ diff --git a/include/Makefile.am b/include/Makefile.am index ccca7cb59..a084247e0 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -82,6 +82,7 @@ COMMON_H = \ sys/sa.h \ sys/sa_impl.h \ sys/sha2.h \ + sys/simd_config.h \ sys/skein.h \ sys/spa.h \ sys/spa_checkpoint.h \ diff --git a/include/sys/simd_config.h b/include/sys/simd_config.h new file mode 100644 index 000000000..fe4fe38a0 --- /dev/null +++ b/include/sys/simd_config.h @@ -0,0 +1,102 @@ +// SPDX-License-Identifier: CDDL-1.0 +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or https://opensource.org/licenses/CDDL-1.0. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 2026, TrueNAS. + */ + +#ifndef _SYS_SIMD_CONFIG_H +#define _SYS_SIMD_CONFIG_H + +/* + * Goal: a HAVE_SIMD(x) macro that expands to either 1 or 0 depending on + * the availabilty of that extension on the wanted toolchain. + * + * We need to allow the following: + * - #define HAVE_TOOLCHAIN_AVX 1 (zfs_config.h, detected by configure) + * - #undef HAVE_TOOLCHAIN_AVX (zfs_config.h, probed but not detected) + * - -DHAVE_TOOLCHAIN_AVX (Makefile.bsd) + * + * For completeness, we also allow disabling by defined HAVE_TOOLCHAIN_AVX=0. + * + * The "obvious" implementation of this would be a macro that includes + * defined(...) in its expansion, but unfortunately that is not portable, and + * can produce compiler warnings (see -Wexpansion-to-defined). So we need to + * build our own version. + */ + +/* + * 1. Expand incoming token to its defined value, if anything: + * eg HAVE_SIMD(AVX) + * -> _zfs_deftrue(HAVE_TOOLCHAIN_AVX) + * or -> __zfs_deftrue() (HAVE_TOOLCHAIN_AVX defined) + * or -> __zfs_deftrue(1) (HAVE_TOOLCHAIN_AVX = 1) + * -> __zfs_deftrue(0) (HAVE_TOOLCHAIN_AVX = 0) + * or -> __zfs_deftrue(HAVE_TOOLCHAIN_AVX) (HAVE_TOOLCHAIN_AVX undef) + */ +#define _zfs_deftrue(x) __zfs_deftrue(x) + +/* + * 2. Replace know values with a token that we control: + * __zfs_deftrue() + * -> ___zfs_deftrue(___zfs_deftrue_arg_) + * __zfs_deftrue(1) + * -> ___zfs_deftrue(___zfs_deftrue_arg_1) + * __zfs_deftrue(0) + * -> ___zfs_deftrue(___zfs_deftrue_arg_0) + * __zfs_deftrue(HAVE_TOOLCHAIN_AVX) + * -> ___zfs_deftrue(___zfs_deftrue_arg_HAVE_TOOLCHAIN_AVX) + */ +#define __zfs_deftrue(v) ___zfs_deftrue(___zfs_deftrue_arg_##v) + +/* + * 3. Expand the incoming token into positional parameters for the next call: + * ___zfs_deftrue(___zfs_deftrue_arg_0) + * -> ____zfs_deftrue(0, 0, 0) + * ___zfs_deftrue(___zfs_deftrue_arg_1) + * -> ____zfs_deftrue(0, 1, 0) + * ___zfs_deftrue(___zfs_deftrue_arg_HAVE_TOOLCHAIN_AVX) + * -> ____zfs_deftrue(___zfs_deftrue_arg_HAVE_TOOLCHAIN_AVX, 0) + */ +#define ___zfs_deftrue_arg_ 0, 1 +#define ___zfs_deftrue_arg_1 0, 1 +#define ___zfs_deftrue_arg_0 0, 0 +#define ___zfs_deftrue(t, ...) ____zfs_deftrue(t, 0) + +/* + * 4. Emit the second argument, either the original value or the default 0. + * ____zfs_deftrue(0, 0, 0) -> 0 + * ____zfs_deftrue(0, 1, 0) -> 1 + * ____zfs_deftrue(___zfs_deftrue_arg_HAVE_TOOLCHAIN_AVX, 0) -> 0 + */ +#define ____zfs_deftrue(_n, v, ...) v + +/* + * The Linux kernel requires a specific toolchain. Everything else uses the + * regular compiler toolchain. + */ +#if defined(_KERNEL) && defined(__linux__) +#define HAVE_SIMD(ext) _zfs_deftrue(HAVE_KERNEL_##ext) +#else +#define HAVE_SIMD(ext) _zfs_deftrue(HAVE_TOOLCHAIN_##ext) +#endif + +#endif diff --git a/module/Kbuild.in b/module/Kbuild.in index de093df3d..47e739ea4 100644 --- a/module/Kbuild.in +++ b/module/Kbuild.in @@ -11,6 +11,7 @@ zfs_include = @abs_top_srcdir@/include icp_include = @abs_srcdir@/icp/include zstd_include = @abs_srcdir@/zstd/include ZFS_MODULE_CFLAGS += -include @abs_top_builddir@/zfs_config.h +ZFS_MODULE_CFLAGS += -include $(zfs_include)/sys/simd_config.h ZFS_MODULE_CFLAGS += -I@abs_top_builddir@/include src = @abs_srcdir@ obj = @abs_builddir@ @@ -19,6 +20,7 @@ zfs_include = $(srctree)/include/zfs icp_include = $(src)/icp/include zstd_include = $(src)/zstd/include ZFS_MODULE_CFLAGS += -include $(zfs_include)/zfs_config.h +ZFS_MODULE_CFLAGS += -include $(zfs_include)/sys/simd_config.h endif ZFS_MODULE_CFLAGS += -I$(zfs_include)/os/linux/kernel diff --git a/module/Makefile.bsd b/module/Makefile.bsd index 825586451..30cf741b9 100644 --- a/module/Makefile.bsd +++ b/module/Makefile.bsd @@ -38,6 +38,7 @@ CFLAGS+= -I${INCDIR}/os/freebsd CFLAGS+= -I${INCDIR}/os/freebsd/spl CFLAGS+= -I${INCDIR}/os/freebsd/zfs CFLAGS+= -I${SRCDIR}/zstd/include +CFLAGS+= -include ${INCDIR}/sys/simd_config.h CFLAGS+= -include ${INCDIR}/os/freebsd/spl/sys/ccompile.h CFLAGS+= -I${.CURDIR} @@ -46,8 +47,10 @@ CFLAGS+= -D__KERNEL__ -DFREEBSD_NAMECACHE -DBUILDING_ZFS -D__BSD_VISIBLE=1 \ -D_SYS_VMEM_H_ -DKDTRACE_HOOKS -DCOMPAT_FREEBSD11 .if ${MACHINE_ARCH} == "amd64" -CFLAGS+= -D__x86_64 -DHAVE_SSE2 -DHAVE_SSSE3 -DHAVE_SSE4_1 \ - -DHAVE_AVX -DHAVE_AVX2 -DHAVE_AVX512F -DHAVE_AVX512VL -DHAVE_AVX512BW +CFLAGS+= -D__x86_64 -DHAVE_TOOLCHAIN_SSE2 -DHAVE_TOOLCHAIN_SSSE3 \ + -DHAVE_TOOLCHAIN_SSE4_1 -DHAVE_TOOLCHAIN_AVX -DHAVE_TOOLCHAIN_AVX2 \ + -DHAVE_TOOLCHAIN_AVX512F -DHAVE_TOOLCHAIN_AVX512VL \ + -DHAVE_TOOLCHAIN_AVX512BW .endif .if defined(WITH_DEBUG) && ${WITH_DEBUG} == "true"