1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 /* 3 * Copyright (C) 2017 Linaro Ltd. <ard.biesheuvel@linaro.org> 4 * Copyright (C) 2023 SiFive 5 */ 6 7 #ifndef __ASM_SIMD_H 8 #define __ASM_SIMD_H 9 10 #include <linux/compiler.h> 11 #include <linux/irqflags.h> 12 #include <linux/percpu.h> 13 #include <linux/preempt.h> 14 #include <linux/types.h> 15 #include <linux/thread_info.h> 16 17 #include <asm/vector.h> 18 19 #ifdef CONFIG_RISCV_ISA_V 20 /* 21 * may_use_simd - whether it is allowable at this time to issue vector 22 * instructions or access the vector register file 23 * 24 * Callers must not assume that the result remains true beyond the next 25 * preempt_enable() or return from softirq context. 26 */ 27 static __must_check inline bool may_use_simd(void) 28 { 29 /* 30 * RISCV_KERNEL_MODE_V is only set while preemption is disabled, 31 * and is clear whenever preemption is enabled. 32 */ 33 if (in_hardirq() || in_nmi()) 34 return false; 35 36 /* 37 * Nesting is acheived in preempt_v by spreading the control for 38 * preemptible and non-preemptible kernel-mode Vector into two fields. 39 * Always try to match with prempt_v if kernel V-context exists. Then, 40 * fallback to check non preempt_v if nesting happens, or if the config 41 * is not set. 42 */ 43 if (IS_ENABLED(CONFIG_RISCV_ISA_V_PREEMPTIVE) && current->thread.kernel_vstate.datap) { 44 if (!riscv_preempt_v_started(current)) 45 return true; 46 } 47 /* 48 * Non-preemptible kernel-mode Vector temporarily disables bh. So we 49 * must not return true on irq_disabled(). Otherwise we would fail the 50 * lockdep check calling local_bh_enable() 51 */ 52 return !irqs_disabled() && !(riscv_v_flags() & RISCV_KERNEL_MODE_V); 53 } 54 55 #else /* ! CONFIG_RISCV_ISA_V */ 56 57 static __must_check inline bool may_use_simd(void) 58 { 59 return false; 60 } 61 62 #endif /* ! CONFIG_RISCV_ISA_V */ 63 64 #endif 65