xref: /illumos-gate/usr/src/uts/common/fs/zfs/sys/simd.h (revision a92282e44f968185a6bba094d1e5fece2da819cf)
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