1eda14cbcSMatt Macy /*
2eda14cbcSMatt Macy  * CDDL HEADER START
3eda14cbcSMatt Macy  *
4eda14cbcSMatt Macy  * The contents of this file are subject to the terms of the
5eda14cbcSMatt Macy  * Common Development and Distribution License (the "License").
6eda14cbcSMatt Macy  * You may not use this file except in compliance with the License.
7eda14cbcSMatt Macy  *
8eda14cbcSMatt Macy  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9271171e0SMartin Matuska  * or https://opensource.org/licenses/CDDL-1.0.
10eda14cbcSMatt Macy  * See the License for the specific language governing permissions
11eda14cbcSMatt Macy  * and limitations under the License.
12eda14cbcSMatt Macy  *
13eda14cbcSMatt Macy  * When distributing Covered Code, include this CDDL HEADER in each
14eda14cbcSMatt Macy  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15eda14cbcSMatt Macy  * If applicable, add the following below this CDDL HEADER, with the
16eda14cbcSMatt Macy  * fields enclosed by brackets "[]" replaced with your own identifying
17eda14cbcSMatt Macy  * information: Portions Copyright [yyyy] [name of copyright owner]
18eda14cbcSMatt Macy  *
19eda14cbcSMatt Macy  * CDDL HEADER END
20eda14cbcSMatt Macy  */
21eda14cbcSMatt Macy /*
22eda14cbcSMatt Macy  * Copyright (C) 2019 Romain Dolbeau
23eda14cbcSMatt Macy  *           <romain.dolbeau@european-processor-initiative.eu>
24c7046f76SMartin Matuska  * Copyright (C) 2022 Tino Reichardt <milky-zfs@mcmilk.de>
25eda14cbcSMatt Macy  */
26eda14cbcSMatt Macy 
27eda14cbcSMatt Macy /*
28eda14cbcSMatt Macy  * USER API:
29eda14cbcSMatt Macy  *
30eda14cbcSMatt Macy  * Kernel fpu methods:
31eda14cbcSMatt Macy  *	kfpu_allowed()
32eda14cbcSMatt Macy  *	kfpu_begin()
33eda14cbcSMatt Macy  *	kfpu_end()
34eda14cbcSMatt Macy  *	kfpu_init()
35eda14cbcSMatt Macy  *	kfpu_fini()
36eda14cbcSMatt Macy  *
37eda14cbcSMatt Macy  * SIMD support:
38eda14cbcSMatt Macy  *
39eda14cbcSMatt Macy  * Following functions should be called to determine whether CPU feature
40eda14cbcSMatt Macy  * is supported. All functions are usable in kernel and user space.
41eda14cbcSMatt Macy  * If a SIMD algorithm is using more than one instruction set
42eda14cbcSMatt Macy  * all relevant feature test functions should be called.
43eda14cbcSMatt Macy  *
44eda14cbcSMatt Macy  * Supported features:
45eda14cbcSMatt Macy  *   zfs_altivec_available()
46c7046f76SMartin Matuska  *   zfs_vsx_available()
47c7046f76SMartin Matuska  *   zfs_isa207_available()
48eda14cbcSMatt Macy  */
49eda14cbcSMatt Macy 
50eda14cbcSMatt Macy #ifndef _LINUX_SIMD_POWERPC_H
51eda14cbcSMatt Macy #define	_LINUX_SIMD_POWERPC_H
52eda14cbcSMatt Macy 
53eda14cbcSMatt Macy #include <linux/preempt.h>
54eda14cbcSMatt Macy #include <linux/export.h>
55eda14cbcSMatt Macy #include <linux/sched.h>
56eda14cbcSMatt Macy #include <asm/switch_to.h>
57eda14cbcSMatt Macy #include <sys/types.h>
58eda14cbcSMatt Macy #include <linux/version.h>
59eda14cbcSMatt Macy 
60c7046f76SMartin Matuska #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0)
61c7046f76SMartin Matuska #include <asm/cpufeature.h>
62c7046f76SMartin Matuska #else
63c7046f76SMartin Matuska #include <asm/cputable.h>
64c7046f76SMartin Matuska #endif
65c7046f76SMartin Matuska 
66eda14cbcSMatt Macy #define	kfpu_allowed()			1
671f1e2261SMartin Matuska 
681f1e2261SMartin Matuska #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)
69*2a58b312SMartin Matuska #ifdef	CONFIG_ALTIVEC
70*2a58b312SMartin Matuska #define	ENABLE_KERNEL_ALTIVEC	enable_kernel_altivec();
71*2a58b312SMartin Matuska #define	DISABLE_KERNEL_ALTIVEC	disable_kernel_altivec();
72*2a58b312SMartin Matuska #else
73*2a58b312SMartin Matuska #define	ENABLE_KERNEL_ALTIVEC
74*2a58b312SMartin Matuska #define	DISABLE_KERNEL_ALTIVEC
7515f0b8c3SMartin Matuska #endif
76*2a58b312SMartin Matuska #ifdef	CONFIG_VSX
77*2a58b312SMartin Matuska #define	ENABLE_KERNEL_VSX	enable_kernel_vsx();
78*2a58b312SMartin Matuska #define	DISABLE_KERNEL_VSX	disable_kernel_vsx();
79*2a58b312SMartin Matuska #else
80*2a58b312SMartin Matuska #define	ENABLE_KERNEL_VSX
81*2a58b312SMartin Matuska #define	DISABLE_KERNEL_VSX
82*2a58b312SMartin Matuska #endif
83*2a58b312SMartin Matuska #ifdef	CONFIG_SPE
84*2a58b312SMartin Matuska #define	ENABLE_KERNEL_SPE	enable_kernel_spe();
85*2a58b312SMartin Matuska #define	DISABLE_KERNEL_SPE	disable_kernel_spe();
86*2a58b312SMartin Matuska #else
87*2a58b312SMartin Matuska #define	ENABLE_KERNEL_SPE
88*2a58b312SMartin Matuska #define	DISABLE_KERNEL_SPE
89*2a58b312SMartin Matuska #endif
90*2a58b312SMartin Matuska #define	kfpu_begin()				\
91*2a58b312SMartin Matuska 	{					\
92*2a58b312SMartin Matuska 		preempt_disable();		\
93*2a58b312SMartin Matuska 		ENABLE_KERNEL_ALTIVEC		\
94*2a58b312SMartin Matuska 		ENABLE_KERNEL_VSX		\
95*2a58b312SMartin Matuska 		ENABLE_KERNEL_SPE		\
96*2a58b312SMartin Matuska 	}
97*2a58b312SMartin Matuska #define	kfpu_end()				\
98*2a58b312SMartin Matuska 	{					\
99*2a58b312SMartin Matuska 		DISABLE_KERNEL_SPE		\
100*2a58b312SMartin Matuska 		DISABLE_KERNEL_VSX		\
101*2a58b312SMartin Matuska 		DISABLE_KERNEL_ALTIVEC		\
102*2a58b312SMartin Matuska 		preempt_enable();		\
103*2a58b312SMartin Matuska 	}
104eda14cbcSMatt Macy #else
1051f1e2261SMartin Matuska /* seems that before 4.5 no-one bothered */
1061f1e2261SMartin Matuska #define	kfpu_begin()
107eda14cbcSMatt Macy #define	kfpu_end()		preempt_enable()
108*2a58b312SMartin Matuska #endif	/* Linux version >= 4.5 */
109c7046f76SMartin Matuska 
110eda14cbcSMatt Macy #define	kfpu_init()		0
111eda14cbcSMatt Macy #define	kfpu_fini()		((void) 0)
112eda14cbcSMatt Macy 
113eda14cbcSMatt Macy /*
114*2a58b312SMartin Matuska  * Linux 4.7 makes cpu_has_feature to use jump labels on powerpc if
115*2a58b312SMartin Matuska  * CONFIG_JUMP_LABEL_FEATURE_CHECKS is enabled, in this case however it
116*2a58b312SMartin Matuska  * references GPL-only symbol cpu_feature_keys. Therefore we overrides this
117*2a58b312SMartin Matuska  * interface when it is detected being GPL-only.
118*2a58b312SMartin Matuska  */
119*2a58b312SMartin Matuska #if defined(CONFIG_JUMP_LABEL_FEATURE_CHECKS) && \
120*2a58b312SMartin Matuska     defined(HAVE_CPU_HAS_FEATURE_GPL_ONLY)
121*2a58b312SMartin Matuska #define	cpu_has_feature(feature)	early_cpu_has_feature(feature)
122*2a58b312SMartin Matuska #endif
123*2a58b312SMartin Matuska 
124*2a58b312SMartin Matuska /*
125eda14cbcSMatt Macy  * Check if AltiVec instruction set is available
126eda14cbcSMatt Macy  */
127eda14cbcSMatt Macy static inline boolean_t
zfs_altivec_available(void)128eda14cbcSMatt Macy zfs_altivec_available(void)
129eda14cbcSMatt Macy {
130c7046f76SMartin Matuska 	return (cpu_has_feature(CPU_FTR_ALTIVEC));
131eda14cbcSMatt Macy }
132c7046f76SMartin Matuska 
133c7046f76SMartin Matuska /*
134c7046f76SMartin Matuska  * Check if VSX is available
135c7046f76SMartin Matuska  */
136c7046f76SMartin Matuska static inline boolean_t
zfs_vsx_available(void)137c7046f76SMartin Matuska zfs_vsx_available(void)
138c7046f76SMartin Matuska {
139c7046f76SMartin Matuska 	return (cpu_has_feature(CPU_FTR_VSX));
140c7046f76SMartin Matuska }
141c7046f76SMartin Matuska 
142c7046f76SMartin Matuska /*
143c7046f76SMartin Matuska  * Check if POWER ISA 2.07 is available (SHA2)
144c7046f76SMartin Matuska  */
145c7046f76SMartin Matuska static inline boolean_t
zfs_isa207_available(void)146c7046f76SMartin Matuska zfs_isa207_available(void)
147c7046f76SMartin Matuska {
148c7046f76SMartin Matuska 	return (cpu_has_feature(CPU_FTR_ARCH_207S));
149c7046f76SMartin Matuska }
150c7046f76SMartin Matuska 
151eda14cbcSMatt Macy #endif /* _LINUX_SIMD_POWERPC_H */
152