]> git.proxmox.com Git - mirror_zfs.git/commitdiff
Add SHA2 SIMD feature tests for libspl
authorTino Reichardt <milky-zfs@mcmilk.de>
Wed, 28 Sep 2022 08:54:35 +0000 (10:54 +0200)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Thu, 2 Mar 2023 21:52:15 +0000 (13:52 -0800)
These are added via HWCAP interface:
- zfs_neon_available() for arm and aarch64
- zfs_sha256_available() for arm and aarch64
- zfs_sha512_available() for aarch64

This one via cpuid() call:
- zfs_shani_available() for x86_64

Tested-by: Rich Ercolani <rincebrain@gmail.com>
Tested-by: Sebastian Gottschall <s.gottschall@dd-wrt.com>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Tino Reichardt <milky-zfs@mcmilk.de>
Closes #13741

lib/libspl/include/Makefile.am
lib/libspl/include/sys/simd.h

index c8b41bbc296e193e68f874c5a80a7675f87d5945..2c1d21edf19d736e547c86e2b82286c233630743 100644 (file)
@@ -46,7 +46,6 @@ libspl_sys_HEADERS = \
        %D%/sys/poll.h \
        %D%/sys/priv.h \
        %D%/sys/processor.h \
-       %D%/sys/sha2.h \
        %D%/sys/simd.h \
        %D%/sys/stack.h \
        %D%/sys/stdtypes.h \
index 2be5173f317c4b8f909720da503d44c926c9d68d..7b06ddf5830593992330478eef5246ccef546518 100644 (file)
 #include <sys/isa_defs.h>
 #include <sys/types.h>
 
+/* including <sys/auxv.h> clashes with AT_UID and others */
+#if defined(__arm__) || defined(__aarch64__) || defined(powerpc)
+#if defined(__FreeBSD__)
+#define        AT_HWCAP        25
+#define        AT_HWCAP2       26
+extern int elf_aux_info(int aux, void *buf, int buflen);
+static inline unsigned long getauxval(unsigned long key)
+{
+       unsigned long val = 0UL;
+
+       if (elf_aux_info((int)key, &val, sizeof (val)) != 0)
+               return (0UL);
+
+       return (val);
+}
+#elif defined(__linux__)
+#define        AT_HWCAP        16
+#define        AT_HWCAP2       26
+extern unsigned long getauxval(unsigned long type);
+#endif /* __linux__ */
+#endif /* arm || aarch64 || powerpc */
+
 #if defined(__x86)
 #include <cpuid.h>
 
@@ -78,7 +100,8 @@ typedef enum cpuid_inst_sets {
        AVX512VL,
        AES,
        PCLMULQDQ,
-       MOVBE
+       MOVBE,
+       SHA_NI
 } cpuid_inst_sets_t;
 
 /*
@@ -103,6 +126,7 @@ typedef struct cpuid_feature_desc {
 #define        _AES_BIT                (1U << 25)
 #define        _PCLMULQDQ_BIT          (1U << 1)
 #define        _MOVBE_BIT              (1U << 22)
+#define        _SHA_NI_BIT             (1U << 29)
 
 /*
  * Descriptions of supported instruction sets
@@ -131,6 +155,7 @@ static const cpuid_feature_desc_t cpuid_features[] = {
        [AES]           = {1U, 0U, _AES_BIT,            ECX     },
        [PCLMULQDQ]     = {1U, 0U, _PCLMULQDQ_BIT,      ECX     },
        [MOVBE]         = {1U, 0U, _MOVBE_BIT,          ECX     },
+       [SHA_NI]        = {7U, 0U, _SHA_NI_BIT,         EBX     },
 };
 
 /*
@@ -204,6 +229,7 @@ CPUID_FEATURE_CHECK(avx512vl, AVX512VL);
 CPUID_FEATURE_CHECK(aes, AES);
 CPUID_FEATURE_CHECK(pclmulqdq, PCLMULQDQ);
 CPUID_FEATURE_CHECK(movbe, MOVBE);
+CPUID_FEATURE_CHECK(shani, SHA_NI);
 
 /*
  * Detect register set support
@@ -345,6 +371,15 @@ zfs_movbe_available(void)
        return (__cpuid_has_movbe());
 }
 
+/*
+ * Check if SHA_NI instruction is available
+ */
+static inline boolean_t
+zfs_shani_available(void)
+{
+       return (__cpuid_has_shani());
+}
+
 /*
  * AVX-512 family of instruction sets:
  *
@@ -443,6 +478,36 @@ zfs_avx512vbmi_available(void)
            __zmm_enabled());
 }
 
+#elif defined(__arm__)
+
+#define        kfpu_allowed()          1
+#define        kfpu_initialize(tsk)    do {} while (0)
+#define        kfpu_begin()            do {} while (0)
+#define        kfpu_end()              do {} while (0)
+
+#define        HWCAP_NEON              0x00001000
+#define        HWCAP2_SHA2             0x00000008
+
+/*
+ * Check if NEON is available
+ */
+static inline boolean_t
+zfs_neon_available(void)
+{
+       unsigned long hwcap = getauxval(AT_HWCAP);
+       return (hwcap & HWCAP_NEON);
+}
+
+/*
+ * Check if SHA2 is available
+ */
+static inline boolean_t
+zfs_sha256_available(void)
+{
+       unsigned long hwcap = getauxval(AT_HWCAP);
+       return (hwcap & HWCAP2_SHA2);
+}
+
 #elif defined(__aarch64__)
 
 #define        kfpu_allowed()          1
@@ -450,28 +515,41 @@ zfs_avx512vbmi_available(void)
 #define        kfpu_begin()            do {} while (0)
 #define        kfpu_end()              do {} while (0)
 
-#elif defined(__powerpc__)
+#define        HWCAP_FP                0x00000001
+#define        HWCAP_SHA2              0x00000040
+#define        HWCAP_SHA512            0x00200000
 
-/* including <sys/auxv.h> clashes with AT_UID and others */
-#if defined(__FreeBSD__)
-#define        AT_HWCAP        25      /* CPU feature flags. */
-#define        AT_HWCAP2       26      /* CPU feature flags 2. */
-extern int elf_aux_info(int aux, void *buf, int buflen);
-static inline unsigned long
-getauxval(unsigned long key)
+/*
+ * Check if NEON is available
+ */
+static inline boolean_t
+zfs_neon_available(void)
 {
-       unsigned long val = 0UL;
+       unsigned long hwcap = getauxval(AT_HWCAP);
+       return (hwcap & HWCAP_FP);
+}
 
-       if (elf_aux_info((int)key, &val, sizeof (val)) != 0)
-               return (0UL);
+/*
+ * Check if SHA2 is available
+ */
+static inline boolean_t
+zfs_sha256_available(void)
+{
+       unsigned long hwcap = getauxval(AT_HWCAP);
+       return (hwcap & HWCAP_SHA2);
+}
 
-       return (val);
+/*
+ * Check if SHA512 is available
+ */
+static inline boolean_t
+zfs_sha512_available(void)
+{
+       unsigned long hwcap = getauxval(AT_HWCAP);
+       return (hwcap & HWCAP_SHA512);
 }
-#elif defined(__linux__)
-#define        AT_HWCAP        16      /* CPU feature flags. */
-#define        AT_HWCAP2       26      /* CPU feature flags 2. */
-extern unsigned long getauxval(unsigned long type);
-#endif
+
+#elif defined(__powerpc__)
 
 #define        kfpu_allowed()          1
 #define        kfpu_initialize(tsk)    do {} while (0)
@@ -479,30 +557,28 @@ extern unsigned long getauxval(unsigned long type);
 #define        kfpu_end()              do {} while (0)
 
 #define        PPC_FEATURE_HAS_ALTIVEC 0x10000000
+#define        PPC_FEATURE_HAS_VSX     0x00000080
+#define        PPC_FEATURE2_ARCH_2_07  0x80000000
+
 static inline boolean_t
 zfs_altivec_available(void)
 {
        unsigned long hwcap = getauxval(AT_HWCAP);
-
        return (hwcap & PPC_FEATURE_HAS_ALTIVEC);
 }
 
-#define        PPC_FEATURE_HAS_VSX     0x00000080
 static inline boolean_t
 zfs_vsx_available(void)
 {
        unsigned long hwcap = getauxval(AT_HWCAP);
-
        return (hwcap & PPC_FEATURE_HAS_VSX);
 }
 
-#define        PPC_FEATURE2_ARCH_2_07  0x80000000
 static inline boolean_t
 zfs_isa207_available(void)
 {
        unsigned long hwcap = getauxval(AT_HWCAP);
        unsigned long hwcap2 = getauxval(AT_HWCAP2);
-
        return ((hwcap & PPC_FEATURE_HAS_VSX) &&
            (hwcap2 & PPC_FEATURE2_ARCH_2_07));
 }