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