diff options
Diffstat (limited to 'include/os/linux/kernel/linux/simd_aarch64.h')
-rw-r--r-- | include/os/linux/kernel/linux/simd_aarch64.h | 84 |
1 files changed, 76 insertions, 8 deletions
diff --git a/include/os/linux/kernel/linux/simd_aarch64.h b/include/os/linux/kernel/linux/simd_aarch64.h index 50937e97ced1..123a0c72bc6a 100644 --- a/include/os/linux/kernel/linux/simd_aarch64.h +++ b/include/os/linux/kernel/linux/simd_aarch64.h @@ -6,7 +6,7 @@ * 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 http://www.opensolaris.org/os/licensing. + * or https://opensource.org/licenses/CDDL-1.0. * See the License for the specific language governing permissions * and limitations under the License. * @@ -18,8 +18,11 @@ * * CDDL HEADER END */ + /* * Copyright (C) 2016 Romain Dolbeau <romain@dolbeau.org>. + * Copyright (C) 2022 Tino Reichardt <milky-zfs@mcmilk.de> + * Copyright (C) 2022 Sebastian Gottschall <s.gottschall@dd-wrt.com> */ /* @@ -31,24 +34,89 @@ * kfpu_end() * kfpu_init() * kfpu_fini() + * + * SIMD support: + * + * Following functions should be called to determine whether CPU feature + * is supported. All functions are usable in kernel and user space. + * If a SIMD algorithm is using more than one instruction set + * all relevant feature test functions should be called. + * + * Supported features: + * zfs_neon_available() + * zfs_sha256_available() + * zfs_sha512_available() */ #ifndef _LINUX_SIMD_AARCH64_H #define _LINUX_SIMD_AARCH64_H -#include <sys/isa_defs.h> - -#if defined(__aarch64__) - #include <sys/types.h> #include <asm/neon.h> +#include <asm/elf.h> +#include <asm/hwcap.h> +#include <linux/version.h> + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0) +#include <asm/sysreg.h> +#else +#define sys_reg(op0, op1, crn, crm, op2) ( \ + ((op0) << Op0_shift) | \ + ((op1) << Op1_shift) | \ + ((crn) << CRn_shift) | \ + ((crm) << CRm_shift) | \ + ((op2) << Op2_shift)) +#endif +#define ID_AA64PFR0_EL1 sys_reg(3, 0, 0, 1, 0) +#define ID_AA64ISAR0_EL1 sys_reg(3, 0, 0, 6, 0) + +#if (defined(HAVE_KERNEL_NEON) && defined(CONFIG_KERNEL_MODE_NEON)) #define kfpu_allowed() 1 #define kfpu_begin() kernel_neon_begin() #define kfpu_end() kernel_neon_end() -#define kfpu_init() 0 -#define kfpu_fini() ((void) 0) +#else +#define kfpu_allowed() 0 +#define kfpu_begin() do {} while (0) +#define kfpu_end() do {} while (0) +#endif +#define kfpu_init() (0) +#define kfpu_fini() do {} while (0) + +#define get_ftr(id) { \ + unsigned long __val; \ + asm("mrs %0, "#id : "=r" (__val)); \ + __val; \ +} -#endif /* __aarch64__ */ +/* + * Check if NEON is available + */ +static inline boolean_t +zfs_neon_available(void) +{ + unsigned long ftr = ((get_ftr(ID_AA64PFR0_EL1)) >> 16) & 0xf; + return (ftr == 0 || ftr == 1); +} + +/* + * Check if SHA256 is available + */ +static inline boolean_t +zfs_sha256_available(void) +{ + unsigned long ftr = ((get_ftr(ID_AA64ISAR0_EL1)) >> 12) & 0x3; + return (ftr & 0x1); +} + +/* + * Check if SHA512 is available + */ +static inline boolean_t +zfs_sha512_available(void) +{ + unsigned long ftr = ((get_ftr(ID_AA64ISAR0_EL1)) >> 12) & 0x3; + return (ftr & 0x2); +} #endif /* _LINUX_SIMD_AARCH64_H */ |