simd.h 1.7 KB

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