simd.h 1.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
  1. /* SPDX-License-Identifier: GPL-2.0-only */
  2. /*
  3. * Copyright (C) 2017 Linaro Ltd. <[email protected]>
  4. */
  5. #ifndef __ASM_SIMD_H
  6. #define __ASM_SIMD_H
  7. #include <linux/compiler.h>
  8. #include <linux/irqflags.h>
  9. #include <linux/percpu.h>
  10. #include <linux/preempt.h>
  11. #include <linux/types.h>
  12. DECLARE_PER_CPU(bool, fpsimd_context_busy);
  13. #ifdef CONFIG_KERNEL_MODE_NEON
  14. /*
  15. * may_use_simd - whether it is allowable at this time to issue SIMD
  16. * instructions or access the SIMD register file
  17. *
  18. * Callers must not assume that the result remains true beyond the next
  19. * preempt_enable() or return from softirq context.
  20. */
  21. static __must_check inline bool may_use_simd(void)
  22. {
  23. /*
  24. * We must make sure that the SVE has been initialized properly
  25. * before using the SIMD in kernel.
  26. * fpsimd_context_busy is only set while preemption is disabled,
  27. * and is clear whenever preemption is enabled. Since
  28. * this_cpu_read() is atomic w.r.t. preemption, fpsimd_context_busy
  29. * cannot change under our feet -- if it's set we cannot be
  30. * migrated, and if it's clear we cannot be migrated to a CPU
  31. * where it is set.
  32. */
  33. return !in_hardirq() && !irqs_disabled() && !in_nmi() &&
  34. !this_cpu_read(fpsimd_context_busy);
  35. }
  36. #else /* ! CONFIG_KERNEL_MODE_NEON */
  37. static __must_check inline bool may_use_simd(void) {
  38. return false;
  39. }
  40. #endif /* ! CONFIG_KERNEL_MODE_NEON */
  41. #endif