diff --git a/config/kernel-fpu.m4 b/config/kernel-fpu.m4 index 1c5690969..671fe7ea5 100644 --- a/config/kernel-fpu.m4 +++ b/config/kernel-fpu.m4 @@ -1,18 +1,41 @@ +dnl # +dnl # Handle differences in kernel FPU code. dnl # -dnl # 4.2 API change -dnl # asm/i387.h is replaced by asm/fpu/api.h +dnl # Kernel +dnl # 5.0: All kernel fpu functions are GPL only, so we can't use them. +dnl # (nothing defined) +dnl # +dnl # 4.2: Use __kernel_fpu_{begin,end}() +dnl # HAVE_UNDERSCORE_KERNEL_FPU & KERNEL_EXPORTS_X86_FPU +dnl # +dnl # Pre-4.2: Use kernel_fpu_{begin,end}() +dnl # HAVE_KERNEL_FPU & KERNEL_EXPORTS_X86_FPU dnl # AC_DEFUN([ZFS_AC_KERNEL_FPU], [ - AC_MSG_CHECKING([whether asm/fpu/api.h exists]) + AC_MSG_CHECKING([which kernel_fpu function to use]) ZFS_LINUX_TRY_COMPILE([ - #include - #include + #include + #include ],[ - __kernel_fpu_begin(); + kernel_fpu_begin(); + kernel_fpu_end(); ],[ - AC_MSG_RESULT(yes) - AC_DEFINE(HAVE_FPU_API_H, 1, [kernel has interface]) + AC_MSG_RESULT(kernel_fpu_*) + AC_DEFINE(HAVE_KERNEL_FPU, 1, [kernel has kernel_fpu_* functions]) + AC_DEFINE(KERNEL_EXPORTS_X86_FPU, 1, [kernel exports FPU functions]) ],[ - AC_MSG_RESULT(no) + ZFS_LINUX_TRY_COMPILE([ + #include + #include + ],[ + __kernel_fpu_begin(); + __kernel_fpu_end(); + ],[ + AC_MSG_RESULT(__kernel_fpu_*) + AC_DEFINE(HAVE_UNDERSCORE_KERNEL_FPU, 1, [kernel has __kernel_fpu_* functions]) + AC_DEFINE(KERNEL_EXPORTS_X86_FPU, 1, [kernel exports FPU functions]) + ],[ + AC_MSG_RESULT(not exported) + ]) ]) ]) diff --git a/include/linux/simd_x86.h b/include/linux/simd_x86.h index 10ce02e37..5d6fbed35 100644 --- a/include/linux/simd_x86.h +++ b/include/linux/simd_x86.h @@ -81,7 +81,7 @@ #endif #if defined(_KERNEL) -#if defined(HAVE_FPU_API_H) +#if defined(HAVE_UNDERSCORE_KERNEL_FPU) #include #include #define kfpu_begin() \ @@ -94,12 +94,18 @@ __kernel_fpu_end(); \ preempt_enable(); \ } -#else +#elif defined(HAVE_KERNEL_FPU) #include #include #define kfpu_begin() kernel_fpu_begin() #define kfpu_end() kernel_fpu_end() -#endif /* defined(HAVE_FPU_API_H) */ +#else +/* Kernel doesn't export any kernel_fpu_* functions */ +#include /* For kernel xgetbv() */ +#define kfpu_begin() panic("This code should never run") +#define kfpu_end() panic("This code should never run") +#endif /* defined(HAVE_KERNEL_FPU) */ + #else /* * fpu dummy methods for userspace @@ -286,11 +292,13 @@ __simd_state_enabled(const uint64_t state) boolean_t has_osxsave; uint64_t xcr0; -#if defined(_KERNEL) && defined(X86_FEATURE_OSXSAVE) +#if defined(_KERNEL) +#if defined(X86_FEATURE_OSXSAVE) && defined(KERNEL_EXPORTS_X86_FPU) has_osxsave = !!boot_cpu_has(X86_FEATURE_OSXSAVE); -#elif defined(_KERNEL) && !defined(X86_FEATURE_OSXSAVE) - has_osxsave = B_FALSE; #else + has_osxsave = B_FALSE; +#endif +#elif !defined(_KERNEL) has_osxsave = __cpuid_has_osxsave(); #endif @@ -315,8 +323,12 @@ static inline boolean_t zfs_sse_available(void) { #if defined(_KERNEL) +#if defined(KERNEL_EXPORTS_X86_FPU) return (!!boot_cpu_has(X86_FEATURE_XMM)); #else + return (B_FALSE); +#endif +#elif !defined(_KERNEL) return (__cpuid_has_sse()); #endif } @@ -328,8 +340,12 @@ static inline boolean_t zfs_sse2_available(void) { #if defined(_KERNEL) +#if defined(KERNEL_EXPORTS_X86_FPU) return (!!boot_cpu_has(X86_FEATURE_XMM2)); #else + return (B_FALSE); +#endif +#elif !defined(_KERNEL) return (__cpuid_has_sse2()); #endif } @@ -341,8 +357,12 @@ static inline boolean_t zfs_sse3_available(void) { #if defined(_KERNEL) +#if defined(KERNEL_EXPORTS_X86_FPU) return (!!boot_cpu_has(X86_FEATURE_XMM3)); #else + return (B_FALSE); +#endif +#elif !defined(_KERNEL) return (__cpuid_has_sse3()); #endif } @@ -354,8 +374,12 @@ static inline boolean_t zfs_ssse3_available(void) { #if defined(_KERNEL) +#if defined(KERNEL_EXPORTS_X86_FPU) return (!!boot_cpu_has(X86_FEATURE_SSSE3)); #else + return (B_FALSE); +#endif +#elif !defined(_KERNEL) return (__cpuid_has_ssse3()); #endif } @@ -367,8 +391,12 @@ static inline boolean_t zfs_sse4_1_available(void) { #if defined(_KERNEL) +#if defined(KERNEL_EXPORTS_X86_FPU) return (!!boot_cpu_has(X86_FEATURE_XMM4_1)); #else + return (B_FALSE); +#endif +#elif !defined(_KERNEL) return (__cpuid_has_sse4_1()); #endif } @@ -380,8 +408,12 @@ static inline boolean_t zfs_sse4_2_available(void) { #if defined(_KERNEL) +#if defined(KERNEL_EXPORTS_X86_FPU) return (!!boot_cpu_has(X86_FEATURE_XMM4_2)); #else + return (B_FALSE); +#endif +#elif !defined(_KERNEL) return (__cpuid_has_sse4_2()); #endif } @@ -394,8 +426,12 @@ zfs_avx_available(void) { boolean_t has_avx; #if defined(_KERNEL) +#if defined(KERNEL_EXPORTS_X86_FPU) has_avx = !!boot_cpu_has(X86_FEATURE_AVX); #else + has_avx = B_FALSE; +#endif +#elif !defined(_KERNEL) has_avx = __cpuid_has_avx(); #endif @@ -409,11 +445,13 @@ static inline boolean_t zfs_avx2_available(void) { boolean_t has_avx2; -#if defined(_KERNEL) && defined(X86_FEATURE_AVX2) +#if defined(_KERNEL) +#if defined(X86_FEATURE_AVX2) && defined(KERNEL_EXPORTS_X86_FPU) has_avx2 = !!boot_cpu_has(X86_FEATURE_AVX2); -#elif defined(_KERNEL) && !defined(X86_FEATURE_AVX2) - has_avx2 = B_FALSE; #else + has_avx2 = B_FALSE; +#endif +#elif !defined(_KERNEL) has_avx2 = __cpuid_has_avx2(); #endif @@ -426,11 +464,13 @@ zfs_avx2_available(void) static inline boolean_t zfs_bmi1_available(void) { -#if defined(_KERNEL) && defined(X86_FEATURE_BMI1) +#if defined(_KERNEL) +#if defined(X86_FEATURE_BMI1) && defined(KERNEL_EXPORTS_X86_FPU) return (!!boot_cpu_has(X86_FEATURE_BMI1)); -#elif defined(_KERNEL) && !defined(X86_FEATURE_BMI1) - return (B_FALSE); #else + return (B_FALSE); +#endif +#elif !defined(_KERNEL) return (__cpuid_has_bmi1()); #endif } @@ -441,11 +481,13 @@ zfs_bmi1_available(void) static inline boolean_t zfs_bmi2_available(void) { -#if defined(_KERNEL) && defined(X86_FEATURE_BMI2) +#if defined(_KERNEL) +#if defined(X86_FEATURE_BMI2) && defined(KERNEL_EXPORTS_X86_FPU) return (!!boot_cpu_has(X86_FEATURE_BMI2)); -#elif defined(_KERNEL) && !defined(X86_FEATURE_BMI2) - return (B_FALSE); #else + return (B_FALSE); +#endif +#elif !defined(_KERNEL) return (__cpuid_has_bmi2()); #endif } @@ -456,11 +498,13 @@ zfs_bmi2_available(void) static inline boolean_t zfs_aes_available(void) { -#if defined(_KERNEL) && defined(X86_FEATURE_AES) +#if defined(_KERNEL) +#if defined(X86_FEATURE_AES) && defined(KERNEL_EXPORTS_X86_FPU) return (!!boot_cpu_has(X86_FEATURE_AES)); -#elif defined(_KERNEL) && !defined(X86_FEATURE_AES) - return (B_FALSE); #else + return (B_FALSE); +#endif +#elif !defined(_KERNEL) return (__cpuid_has_aes()); #endif } @@ -471,11 +515,13 @@ zfs_aes_available(void) static inline boolean_t zfs_pclmulqdq_available(void) { -#if defined(_KERNEL) && defined(X86_FEATURE_PCLMULQDQ) +#if defined(_KERNEL) +#if defined(X86_FEATURE_PCLMULQDQ) && defined(KERNEL_EXPORTS_X86_FPU) return (!!boot_cpu_has(X86_FEATURE_PCLMULQDQ)); -#elif defined(_KERNEL) && !defined(X86_FEATURE_PCLMULQDQ) - return (B_FALSE); #else + return (B_FALSE); +#endif +#elif !defined(_KERNEL) return (__cpuid_has_pclmulqdq()); #endif } @@ -503,8 +549,12 @@ zfs_avx512f_available(void) { boolean_t has_avx512 = B_FALSE; -#if defined(_KERNEL) && defined(X86_FEATURE_AVX512F) +#if defined(_KERNEL) +#if defined(X86_FEATURE_AVX512F) && defined(KERNEL_EXPORTS_X86_FPU) has_avx512 = !!boot_cpu_has(X86_FEATURE_AVX512F); +#else + has_avx512 = B_FALSE; +#endif #elif !defined(_KERNEL) has_avx512 = __cpuid_has_avx512f(); #endif @@ -518,9 +568,13 @@ zfs_avx512cd_available(void) { boolean_t has_avx512 = B_FALSE; -#if defined(_KERNEL) && defined(X86_FEATURE_AVX512CD) +#if defined(_KERNEL) +#if defined(X86_FEATURE_AVX512CD) && defined(KERNEL_EXPORTS_X86_FPU) has_avx512 = boot_cpu_has(X86_FEATURE_AVX512F) && boot_cpu_has(X86_FEATURE_AVX512CD); +#else + has_avx512 = B_FALSE; +#endif #elif !defined(_KERNEL) has_avx512 = __cpuid_has_avx512cd(); #endif @@ -534,9 +588,13 @@ zfs_avx512er_available(void) { boolean_t has_avx512 = B_FALSE; -#if defined(_KERNEL) && defined(X86_FEATURE_AVX512ER) +#if defined(_KERNEL) +#if defined(X86_FEATURE_AVX512ER) && defined(KERNEL_EXPORTS_X86_FPU) has_avx512 = boot_cpu_has(X86_FEATURE_AVX512F) && boot_cpu_has(X86_FEATURE_AVX512ER); +#else + has_avx512 = B_FALSE; +#endif #elif !defined(_KERNEL) has_avx512 = __cpuid_has_avx512er(); #endif @@ -550,9 +608,13 @@ zfs_avx512pf_available(void) { boolean_t has_avx512 = B_FALSE; -#if defined(_KERNEL) && defined(X86_FEATURE_AVX512PF) +#if defined(_KERNEL) +#if defined(X86_FEATURE_AVX512PF) && defined(KERNEL_EXPORTS_X86_FPU) has_avx512 = boot_cpu_has(X86_FEATURE_AVX512F) && boot_cpu_has(X86_FEATURE_AVX512PF); +#else + has_avx512 = B_FALSE; +#endif #elif !defined(_KERNEL) has_avx512 = __cpuid_has_avx512pf(); #endif @@ -566,9 +628,13 @@ zfs_avx512bw_available(void) { boolean_t has_avx512 = B_FALSE; -#if defined(_KERNEL) && defined(X86_FEATURE_AVX512BW) +#if defined(_KERNEL) +#if defined(X86_FEATURE_AVX512BW) && defined(KERNEL_EXPORTS_X86_FPU) has_avx512 = boot_cpu_has(X86_FEATURE_AVX512F) && boot_cpu_has(X86_FEATURE_AVX512BW); +#else + has_avx512 = B_FALSE; +#endif #elif !defined(_KERNEL) has_avx512 = __cpuid_has_avx512bw(); #endif @@ -582,9 +648,13 @@ zfs_avx512dq_available(void) { boolean_t has_avx512 = B_FALSE; -#if defined(_KERNEL) && defined(X86_FEATURE_AVX512DQ) +#if defined(_KERNEL) +#if defined(X86_FEATURE_AVX512DQ) && defined(KERNEL_EXPORTS_X86_FPU) has_avx512 = boot_cpu_has(X86_FEATURE_AVX512F) && boot_cpu_has(X86_FEATURE_AVX512DQ); +#else + has_avx512 = B_FALSE; +#endif #elif !defined(_KERNEL) has_avx512 = __cpuid_has_avx512dq(); #endif @@ -598,9 +668,13 @@ zfs_avx512vl_available(void) { boolean_t has_avx512 = B_FALSE; -#if defined(_KERNEL) && defined(X86_FEATURE_AVX512VL) +#if defined(_KERNEL) +#if defined(X86_FEATURE_AVX512VL) && defined(KERNEL_EXPORTS_X86_FPU) has_avx512 = boot_cpu_has(X86_FEATURE_AVX512F) && boot_cpu_has(X86_FEATURE_AVX512VL); +#else + has_avx512 = B_FALSE; +#endif #elif !defined(_KERNEL) has_avx512 = __cpuid_has_avx512vl(); #endif @@ -614,9 +688,13 @@ zfs_avx512ifma_available(void) { boolean_t has_avx512 = B_FALSE; -#if defined(_KERNEL) && defined(X86_FEATURE_AVX512IFMA) +#if defined(_KERNEL) +#if defined(X86_FEATURE_AVX512IFMA) && defined(KERNEL_EXPORTS_X86_FPU) has_avx512 = boot_cpu_has(X86_FEATURE_AVX512F) && boot_cpu_has(X86_FEATURE_AVX512IFMA); +#else + has_avx512 = B_FALSE; +#endif #elif !defined(_KERNEL) has_avx512 = __cpuid_has_avx512ifma(); #endif @@ -630,9 +708,13 @@ zfs_avx512vbmi_available(void) { boolean_t has_avx512 = B_FALSE; -#if defined(_KERNEL) && defined(X86_FEATURE_AVX512VBMI) +#if defined(_KERNEL) +#if defined(X86_FEATURE_AVX512VBMI) && defined(KERNEL_EXPORTS_X86_FPU) has_avx512 = boot_cpu_has(X86_FEATURE_AVX512F) && boot_cpu_has(X86_FEATURE_AVX512VBMI); +#else + has_avx512 = B_FALSE; +#endif #elif !defined(_KERNEL) has_avx512 = __cpuid_has_avx512f() && __cpuid_has_avx512vbmi();