1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright 2020 Joyent, Inc. 14 */ 15 16 #ifndef _SIMD_H 17 #define _SIMD_H 18 19 #if defined(__amd64__) || defined(__i386__) 20 21 22 #define kfpu_allowed() 1 23 #define kfpu_initialize(tsk) do {} while (0) 24 #define kfpu_init() (0) 25 #define kfpu_fini() do {} while (0) 26 27 #ifdef _KERNEL 28 #include <sys/x86_archext.h> 29 #include <sys/archsystm.h> 30 #include <sys/kfpu.h> 31 #include <sys/proc.h> 32 #include <sys/disp.h> 33 #include <sys/cpuvar.h> 34 35 static inline void 36 kfpu_begin(void) 37 { 38 if (curthread->t_lwp != NULL && (curthread->t_procp->p_flag & SSYS)) { 39 kernel_fpu_begin(NULL, KFPU_USE_LWP); 40 } else { 41 kpreempt_disable(); 42 kernel_fpu_begin(NULL, KFPU_NO_STATE); 43 } 44 } 45 46 static inline void 47 kfpu_end(void) 48 { 49 if (curthread->t_lwp != NULL && (curthread->t_procp->p_flag & SSYS)) { 50 kernel_fpu_end(NULL, KFPU_USE_LWP); 51 } else { 52 kernel_fpu_end(NULL, KFPU_NO_STATE); 53 kpreempt_enable(); 54 } 55 } 56 57 /* 58 * Check if various vector instruction sets are available. 59 */ 60 61 static inline boolean_t 62 zfs_sse_available(void) 63 { 64 return (is_x86_feature(x86_featureset, X86FSET_SSE)); 65 } 66 67 static inline boolean_t 68 zfs_sse2_available(void) 69 { 70 return (is_x86_feature(x86_featureset, X86FSET_SSE2)); 71 } 72 73 static inline boolean_t 74 zfs_sse3_available(void) 75 { 76 return (is_x86_feature(x86_featureset, X86FSET_SSE3)); 77 } 78 79 static inline boolean_t 80 zfs_ssse3_available(void) 81 { 82 return (is_x86_feature(x86_featureset, X86FSET_SSSE3)); 83 } 84 85 static inline boolean_t 86 zfs_avx_available(void) 87 { 88 return (is_x86_feature(x86_featureset, X86FSET_AVX)); 89 } 90 91 static inline boolean_t 92 zfs_avx2_available(void) 93 { 94 return (is_x86_feature(x86_featureset, X86FSET_AVX2)); 95 } 96 97 #else /* ! _KERNEL */ 98 99 #include <sys/auxv.h> 100 #include <sys/auxv_386.h> 101 102 #define kfpu_begin() do {} while (0) 103 #define kfpu_end() do {} while (0) 104 105 /* 106 * User-level check if various vector instruction sets are available. 107 */ 108 109 static inline boolean_t 110 zfs_sse_available(void) 111 { 112 uint32_t u = 0; 113 114 (void) getisax(&u, 1); 115 return ((u & AV_386_SSE) != 0); 116 } 117 118 static inline boolean_t 119 zfs_sse2_available(void) 120 { 121 uint32_t u = 0; 122 123 (void) getisax(&u, 1); 124 return ((u & AV_386_SSE2) != 0); 125 } 126 127 static inline boolean_t 128 zfs_sse3_available(void) 129 { 130 uint32_t u = 0; 131 132 (void) getisax(&u, 1); 133 return ((u & AV_386_SSE3) != 0); 134 } 135 136 static inline boolean_t 137 zfs_ssse3_available(void) 138 { 139 uint32_t u = 0; 140 141 (void) getisax(&u, 1); 142 return ((u & AV_386_SSSE3) != 0); 143 } 144 145 static inline boolean_t 146 zfs_avx_available(void) 147 { 148 uint_t u = 0; 149 150 (void) getisax(&u, 1); 151 return ((u & AV_386_AVX) != 0); 152 } 153 154 static inline boolean_t 155 zfs_avx2_available(void) 156 { 157 uint32_t u[2] = { 0 }; 158 159 (void) getisax((uint32_t *)&u, 2); 160 return ((u[1] & AV_386_2_AVX2) != 0); 161 } 162 163 #endif /* _KERNEL */ 164 165 166 #else 167 168 /* Non-x86 CPUs currently always disallow kernel FPU support */ 169 #define kfpu_allowed() 0 170 #define kfpu_initialize(tsk) do {} while (0) 171 #define kfpu_begin() do {} while (0) 172 #define kfpu_end() do {} while (0) 173 #define kfpu_init() (0) 174 #define kfpu_fini() do {} while (0) 175 #endif 176 177 #endif /* _SIMD_H */ 178