diff options
Diffstat (limited to 'module/zcommon')
-rw-r--r-- | module/zcommon/simd_stat.c | 189 | ||||
-rw-r--r-- | module/zcommon/zfs_prop.c | 6 |
2 files changed, 195 insertions, 0 deletions
diff --git a/module/zcommon/simd_stat.c b/module/zcommon/simd_stat.c new file mode 100644 index 000000000..538f8317a --- /dev/null +++ b/module/zcommon/simd_stat.c @@ -0,0 +1,189 @@ +/* + * 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 2024 Google, Inc. All rights reserved. + */ +#include <sys/zfs_context.h> +#include <sys/kstat.h> +#include <sys/simd.h> + + +#ifdef _KERNEL +#ifdef __linux__ +#include <linux/simd.h> +#endif /* __linux__ */ +kstat_t *simd_stat_kstat; +#endif /* _KERNEL */ + +#ifdef _KERNEL +#define SIMD_STAT_PRINT(s, feat, val) \ + kmem_scnprintf(s + off, MAX(4095-off, 0), "%-16s\t%1d\n", feat, (val)) + +static int +simd_stat_kstat_data(char *buf, size_t size, void *data) +{ + (void) data; + + static char simd_stat_kstat_payload[4096] = {0}; + static int off = 0; +#ifdef __linux__ + if (off == 0) { + off += SIMD_STAT_PRINT(simd_stat_kstat_payload, + "kfpu_allowed", kfpu_allowed()); +#ifdef __x86__ + off += SIMD_STAT_PRINT(simd_stat_kstat_payload, + "kfpu", HAVE_KERNEL_FPU); + off += SIMD_STAT_PRINT(simd_stat_kstat_payload, + "kfpu_internal", HAVE_KERNEL_FPU_INTERNAL); + off += SIMD_STAT_PRINT(simd_stat_kstat_payload, + "__kernel_fpu", HAVE_UNDERSCORE_KERNEL_FPU); + off += SIMD_STAT_PRINT(simd_stat_kstat_payload, + "sse", zfs_sse_available()); + off += SIMD_STAT_PRINT(simd_stat_kstat_payload, + "sse2", zfs_sse2_available()); + off += SIMD_STAT_PRINT(simd_stat_kstat_payload, + "sse3", zfs_sse3_available()); + off += SIMD_STAT_PRINT(simd_stat_kstat_payload, + "ssse3", zfs_ssse3_available()); + off += SIMD_STAT_PRINT(simd_stat_kstat_payload, + "sse41", zfs_sse4_1_available()); + off += SIMD_STAT_PRINT(simd_stat_kstat_payload, + "sse42", zfs_sse4_2_available()); + off += SIMD_STAT_PRINT(simd_stat_kstat_payload, + "avx", zfs_avx_available()); + off += SIMD_STAT_PRINT(simd_stat_kstat_payload, + "avx2", zfs_avx2_available()); + off += SIMD_STAT_PRINT(simd_stat_kstat_payload, + "avx512f", zfs_avx512f_available()); + off += SIMD_STAT_PRINT(simd_stat_kstat_payload, + "avx512cd", zfs_avx512cd_available()); + off += SIMD_STAT_PRINT(simd_stat_kstat_payload, + "avx512er", zfs_avx512er_available()); + off += SIMD_STAT_PRINT(simd_stat_kstat_payload, + "avx512pf", zfs_avx512pf_available()); + off += SIMD_STAT_PRINT(simd_stat_kstat_payload, + "avx512bw", zfs_avx512bw_available()); + off += SIMD_STAT_PRINT(simd_stat_kstat_payload, + "avx512dq", zfs_avx512dq_available()); + off += SIMD_STAT_PRINT(simd_stat_kstat_payload, + "avx512vl", zfs_avx512vl_available()); + off += SIMD_STAT_PRINT(simd_stat_kstat_payload, + "avx512ifma", zfs_avx512ifma_available()); + off += SIMD_STAT_PRINT(simd_stat_kstat_payload, + "avx512vbmi", zfs_avx512vbmi_available()); + off += SIMD_STAT_PRINT(simd_stat_kstat_payload, + "ymm", __ymm_enabled()); + off += SIMD_STAT_PRINT(simd_stat_kstat_payload, + "zmm", __zmm_enabled()); + off += SIMD_STAT_PRINT(simd_stat_kstat_payload, + "bmi1", zfs_bmi1_available()); + off += SIMD_STAT_PRINT(simd_stat_kstat_payload, + "bmi2", zfs_bmi2_available()); + off += SIMD_STAT_PRINT(simd_stat_kstat_payload, + "aes", zfs_aes_available()); + off += SIMD_STAT_PRINT(simd_stat_kstat_payload, + "pclmulqdq", zfs_pclmulqdq_available()); + off += SIMD_STAT_PRINT(simd_stat_kstat_payload, + "movbe", zfs_movbe_available()); + + off += SIMD_STAT_PRINT(simd_stat_kstat_payload, + "osxsave", boot_cpu_has(X86_FEATURE_OSXSAVE)); + off += SIMD_STAT_PRINT(simd_stat_kstat_payload, + "xsaves", static_cpu_has(X86_FEATURE_XSAVES)); + off += SIMD_STAT_PRINT(simd_stat_kstat_payload, + "xsaveopt", static_cpu_has(X86_FEATURE_XSAVEOPT)); + off += SIMD_STAT_PRINT(simd_stat_kstat_payload, + "xsave", static_cpu_has(X86_FEATURE_XSAVE)); + off += SIMD_STAT_PRINT(simd_stat_kstat_payload, + "fxsr", static_cpu_has(X86_FEATURE_FXSR)); +#endif /* __x86__ */ +#if defined(__arm__) || defined(__aarch64__) + off += SIMD_STAT_PRINT(simd_stat_kstat_payload, + "kernel_neon", HAVE_KERNEL_NEON); + off += SIMD_STAT_PRINT(simd_stat_kstat_payload, + "kernel_mode_neon", CONFIG_KERNEL_MODE_NEON); + off += SIMD_STAT_PRINT(simd_stat_kstat_payload, + "neon", zfs_neon_available()); + off += SIMD_STAT_PRINT(simd_stat_kstat_payload, + "sha256", zfs_sha256_available()); +#if defined(__aarch64__) + /* + * This technically can exist on 32b ARM but we don't + * define hooks to check for it and I didn't want to + * learn enough ARM ASM to add one. + */ + off += SIMD_STAT_PRINT(simd_stat_kstat_payload, + "sha512", zfs_sha512_available()); +#endif /* __aarch64__ */ +#endif /* __arm__ */ + /* We want to short-circuit this on unsupported platforms. */ + off += 1; + } + + kmem_scnprintf(buf, MIN(off, size), "%s", simd_stat_kstat_payload); +#endif /* __linux__ */ + return (0); +} +#endif /* _KERNEL */ + +void +simd_stat_init(void) +{ + static boolean_t simd_stat_initialized = B_FALSE; + + if (!simd_stat_initialized) { +#if defined(_KERNEL) + /* Install kstats for all implementations */ + simd_stat_kstat = kstat_create("zfs", 0, "simd", "misc", + KSTAT_TYPE_RAW, 0, KSTAT_FLAG_VIRTUAL); + + + if (simd_stat_kstat != NULL) { + simd_stat_kstat->ks_data = (void*)(uintptr_t)1; + simd_stat_kstat->ks_ndata = 1; + simd_stat_kstat->ks_flags |= KSTAT_FLAG_NO_HEADERS; + kstat_set_raw_ops(simd_stat_kstat, + NULL, + simd_stat_kstat_data, + NULL); + kstat_install(simd_stat_kstat); + } +#endif /* _KERNEL */ + } + /* Finish initialization */ + simd_stat_initialized = B_TRUE; +} + +void +simd_stat_fini(void) +{ +#if defined(_KERNEL) + if (simd_stat_kstat != NULL) { + kstat_delete(simd_stat_kstat); + simd_stat_kstat = NULL; + } +#endif +} + +#ifdef _KERNEL +EXPORT_SYMBOL(simd_stat_init); +EXPORT_SYMBOL(simd_stat_fini); +#endif diff --git a/module/zcommon/zfs_prop.c b/module/zcommon/zfs_prop.c index 10ac13a89..1206210a9 100644 --- a/module/zcommon/zfs_prop.c +++ b/module/zcommon/zfs_prop.c @@ -41,6 +41,7 @@ #include <sys/zfs_ioctl.h> #include <sys/zfs_znode.h> #include <sys/dsl_crypt.h> +#include <sys/simd.h> #include "zfs_prop.h" #include "zfs_deleg.h" @@ -1074,6 +1075,9 @@ EXPORT_SYMBOL(zfs_kfpu_fpregs); extern int __init zcommon_init(void); extern void zcommon_fini(void); +extern void simd_stat_init(void); +extern void simd_stat_fini(void); + int __init zcommon_init(void) { @@ -1082,6 +1086,7 @@ zcommon_init(void) return (error); fletcher_4_init(); + simd_stat_init(); return (0); } @@ -1089,6 +1094,7 @@ zcommon_init(void) void zcommon_fini(void) { + simd_stat_fini(); fletcher_4_fini(); kfpu_fini(); } |