Path: blob/main/sys/contrib/openzfs/module/zcommon/simd_stat.c
48383 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*/21/*22* Copyright 2024 Google, Inc. All rights reserved.23*/24#include <sys/zfs_context.h>25#include <sys/kstat.h>26#include <sys/simd.h>272829#ifdef _KERNEL30#ifdef __linux__31#include <linux/simd.h>32#endif /* __linux__ */33kstat_t *simd_stat_kstat;34#endif /* _KERNEL */3536#ifdef _KERNEL37/* Sometimes, we don't define these at all. */38#ifndef HAVE_KERNEL_FPU39#define HAVE_KERNEL_FPU (0)40#endif41#ifndef HAVE_KERNEL_NEON42#define HAVE_KERNEL_NEON (0)43#endif44#ifndef HAVE_KERNEL_FPU_INTERNAL45#define HAVE_KERNEL_FPU_INTERNAL (0)46#endif47#ifndef HAVE_UNDERSCORE_KERNEL_FPU48#define HAVE_UNDERSCORE_KERNEL_FPU (0)49#endif5051#define SIMD_STAT_PRINT(s, feat, val) \52kmem_scnprintf(s + off, MAX(4095-off, 0), "%-16s\t%1d\n", feat, (val))5354static int55simd_stat_kstat_data(char *buf, size_t size, void *data)56{57(void) data;5859static char simd_stat_kstat_payload[4096] = {0};60static int off = 0;61#ifdef __linux__62if (off == 0) {63off += SIMD_STAT_PRINT(simd_stat_kstat_payload,64"kfpu_allowed", kfpu_allowed());65#if defined(__x86_64__) || defined(__i386__)66off += SIMD_STAT_PRINT(simd_stat_kstat_payload,67"kfpu", HAVE_KERNEL_FPU);68off += SIMD_STAT_PRINT(simd_stat_kstat_payload,69"kfpu_internal", HAVE_KERNEL_FPU_INTERNAL);70off += SIMD_STAT_PRINT(simd_stat_kstat_payload,71"__kernel_fpu", HAVE_UNDERSCORE_KERNEL_FPU);72off += SIMD_STAT_PRINT(simd_stat_kstat_payload,73"sse", zfs_sse_available());74off += SIMD_STAT_PRINT(simd_stat_kstat_payload,75"sse2", zfs_sse2_available());76off += SIMD_STAT_PRINT(simd_stat_kstat_payload,77"sse3", zfs_sse3_available());78off += SIMD_STAT_PRINT(simd_stat_kstat_payload,79"ssse3", zfs_ssse3_available());80off += SIMD_STAT_PRINT(simd_stat_kstat_payload,81"sse41", zfs_sse4_1_available());82off += SIMD_STAT_PRINT(simd_stat_kstat_payload,83"sse42", zfs_sse4_2_available());84off += SIMD_STAT_PRINT(simd_stat_kstat_payload,85"avx", zfs_avx_available());86off += SIMD_STAT_PRINT(simd_stat_kstat_payload,87"avx2", zfs_avx2_available());88off += SIMD_STAT_PRINT(simd_stat_kstat_payload,89"avx512f", zfs_avx512f_available());90off += SIMD_STAT_PRINT(simd_stat_kstat_payload,91"avx512cd", zfs_avx512cd_available());92off += SIMD_STAT_PRINT(simd_stat_kstat_payload,93"avx512er", zfs_avx512er_available());94off += SIMD_STAT_PRINT(simd_stat_kstat_payload,95"avx512pf", zfs_avx512pf_available());96off += SIMD_STAT_PRINT(simd_stat_kstat_payload,97"avx512bw", zfs_avx512bw_available());98off += SIMD_STAT_PRINT(simd_stat_kstat_payload,99"avx512dq", zfs_avx512dq_available());100off += SIMD_STAT_PRINT(simd_stat_kstat_payload,101"avx512vl", zfs_avx512vl_available());102off += SIMD_STAT_PRINT(simd_stat_kstat_payload,103"avx512ifma", zfs_avx512ifma_available());104off += SIMD_STAT_PRINT(simd_stat_kstat_payload,105"avx512vbmi", zfs_avx512vbmi_available());106off += SIMD_STAT_PRINT(simd_stat_kstat_payload,107"ymm", __ymm_enabled());108off += SIMD_STAT_PRINT(simd_stat_kstat_payload,109"zmm", __zmm_enabled());110off += SIMD_STAT_PRINT(simd_stat_kstat_payload,111"bmi1", zfs_bmi1_available());112off += SIMD_STAT_PRINT(simd_stat_kstat_payload,113"bmi2", zfs_bmi2_available());114off += SIMD_STAT_PRINT(simd_stat_kstat_payload,115"aes", zfs_aes_available());116off += SIMD_STAT_PRINT(simd_stat_kstat_payload,117"pclmulqdq", zfs_pclmulqdq_available());118off += SIMD_STAT_PRINT(simd_stat_kstat_payload,119"movbe", zfs_movbe_available());120off += SIMD_STAT_PRINT(simd_stat_kstat_payload,121"vaes", zfs_vaes_available());122off += SIMD_STAT_PRINT(simd_stat_kstat_payload,123"vpclmulqdq", zfs_vpclmulqdq_available());124125off += SIMD_STAT_PRINT(simd_stat_kstat_payload,126"osxsave", boot_cpu_has(X86_FEATURE_OSXSAVE));127off += SIMD_STAT_PRINT(simd_stat_kstat_payload,128"xsaves", static_cpu_has(X86_FEATURE_XSAVES));129off += SIMD_STAT_PRINT(simd_stat_kstat_payload,130"xsaveopt", static_cpu_has(X86_FEATURE_XSAVEOPT));131off += SIMD_STAT_PRINT(simd_stat_kstat_payload,132"xsave", static_cpu_has(X86_FEATURE_XSAVE));133off += SIMD_STAT_PRINT(simd_stat_kstat_payload,134"fxsr", static_cpu_has(X86_FEATURE_FXSR));135#endif /* __x86__ */136#if defined(__arm__) || defined(__aarch64__)137off += SIMD_STAT_PRINT(simd_stat_kstat_payload,138"kernel_neon", HAVE_KERNEL_NEON);139#if defined(CONFIG_KERNEL_MODE_NEON)140off += SIMD_STAT_PRINT(simd_stat_kstat_payload,141"kernel_mode_neon", CONFIG_KERNEL_MODE_NEON);142#endif /* CONFIG_KERNEL_MODE_NEON */143off += SIMD_STAT_PRINT(simd_stat_kstat_payload,144"neon", zfs_neon_available());145off += SIMD_STAT_PRINT(simd_stat_kstat_payload,146"sha256", zfs_sha256_available());147#if defined(__aarch64__)148/*149* This technically can exist on 32b ARM but we don't150* define hooks to check for it and I didn't want to151* learn enough ARM ASM to add one.152*/153off += SIMD_STAT_PRINT(simd_stat_kstat_payload,154"sha512", zfs_sha512_available());155#endif /* __aarch64__ */156#endif /* __arm__ */157/* We want to short-circuit this on unsupported platforms. */158off += 1;159}160161kmem_scnprintf(buf, MIN(off, size), "%s", simd_stat_kstat_payload);162#endif /* __linux__ */163return (0);164}165#endif /* _KERNEL */166167void168simd_stat_init(void)169{170static boolean_t simd_stat_initialized = B_FALSE;171172if (!simd_stat_initialized) {173#if defined(_KERNEL)174/* Install kstats for all implementations */175simd_stat_kstat = kstat_create("zfs", 0, "simd", "misc",176KSTAT_TYPE_RAW, 0, KSTAT_FLAG_VIRTUAL);177178179if (simd_stat_kstat != NULL) {180simd_stat_kstat->ks_data = (void*)(uintptr_t)1;181simd_stat_kstat->ks_ndata = 1;182simd_stat_kstat->ks_flags |= KSTAT_FLAG_NO_HEADERS;183kstat_set_raw_ops(simd_stat_kstat,184NULL,185simd_stat_kstat_data,186NULL);187kstat_install(simd_stat_kstat);188}189#endif /* _KERNEL */190}191/* Finish initialization */192simd_stat_initialized = B_TRUE;193}194195void196simd_stat_fini(void)197{198#if defined(_KERNEL)199if (simd_stat_kstat != NULL) {200kstat_delete(simd_stat_kstat);201simd_stat_kstat = NULL;202}203#endif204}205206#ifdef _KERNEL207EXPORT_SYMBOL(simd_stat_init);208EXPORT_SYMBOL(simd_stat_fini);209#endif210211212