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 #include <linux/preempt.h> 54 #include <linux/export.h> 55 #include <linux/sched.h> 56 #include <asm/switch_to.h> 57 #include <sys/types.h> 58 #include <linux/version.h> 59 60 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0) 61 #include <asm/cpufeature.h> 62 #else 63 #include <asm/cputable.h> 64 #endif 65 66 #define kfpu_allowed() 1 67 68 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0) 69 #ifdef CONFIG_ALTIVEC 70 #define ENABLE_KERNEL_ALTIVEC enable_kernel_altivec(); 71 #define DISABLE_KERNEL_ALTIVEC disable_kernel_altivec(); 72 #else 73 #define ENABLE_KERNEL_ALTIVEC 74 #define DISABLE_KERNEL_ALTIVEC 75 #endif 76 #ifdef CONFIG_VSX 77 #define ENABLE_KERNEL_VSX enable_kernel_vsx(); 78 #define DISABLE_KERNEL_VSX disable_kernel_vsx(); 79 #else 80 #define ENABLE_KERNEL_VSX 81 #define DISABLE_KERNEL_VSX 82 #endif 83 #ifdef CONFIG_SPE 84 #define ENABLE_KERNEL_SPE enable_kernel_spe(); 85 #define DISABLE_KERNEL_SPE disable_kernel_spe(); 86 #else 87 #define ENABLE_KERNEL_SPE 88 #define DISABLE_KERNEL_SPE 89 #endif 90 #define kfpu_begin() \ 91 { \ 92 preempt_disable(); \ 93 ENABLE_KERNEL_ALTIVEC \ 94 ENABLE_KERNEL_VSX \ 95 ENABLE_KERNEL_SPE \ 96 } 97 #define kfpu_end() \ 98 { \ 99 DISABLE_KERNEL_SPE \ 100 DISABLE_KERNEL_VSX \ 101 DISABLE_KERNEL_ALTIVEC \ 102 preempt_enable(); \ 103 } 104 #else 105 /* seems that before 4.5 no-one bothered */ 106 #define kfpu_begin() 107 #define kfpu_end() preempt_enable() 108 #endif /* Linux version >= 4.5 */ 109 110 #define kfpu_init() 0 111 #define kfpu_fini() ((void) 0) 112 113 /* 114 * Linux 4.7 makes cpu_has_feature to use jump labels on powerpc if 115 * CONFIG_JUMP_LABEL_FEATURE_CHECKS is enabled, in this case however it 116 * references GPL-only symbol cpu_feature_keys. Therefore we overrides this 117 * interface when it is detected being GPL-only. 118 */ 119 #if defined(CONFIG_JUMP_LABEL_FEATURE_CHECKS) && \ 120 defined(HAVE_CPU_HAS_FEATURE_GPL_ONLY) 121 #define cpu_has_feature(feature) early_cpu_has_feature(feature) 122 #endif 123 124 /* 125 * Check if AltiVec instruction set is available 126 */ 127 static inline boolean_t zfs_altivec_available(void)128zfs_altivec_available(void) 129 { 130 return (cpu_has_feature(CPU_FTR_ALTIVEC)); 131 } 132 133 /* 134 * Check if VSX is available 135 */ 136 static inline boolean_t zfs_vsx_available(void)137zfs_vsx_available(void) 138 { 139 return (cpu_has_feature(CPU_FTR_VSX)); 140 } 141 142 /* 143 * Check if POWER ISA 2.07 is available (SHA2) 144 */ 145 static inline boolean_t zfs_isa207_available(void)146zfs_isa207_available(void) 147 { 148 return (cpu_has_feature(CPU_FTR_ARCH_207S)); 149 } 150 151 #endif /* _LINUX_SIMD_POWERPC_H */ 152