simd.h 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. /* SPDX-License-Identifier: GPL-2.0-only */
  2. /*
  3. * Copyright (C) 2017 Linaro Ltd. <ard.biesheuvel@linaro.org>
  4. */
  5. #ifndef __ASM_SIMD_H
  6. #define __ASM_SIMD_H
  7. #include <linux/cleanup.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 <asm/neon.h>
  14. #ifdef CONFIG_KERNEL_MODE_NEON
  15. /*
  16. * may_use_simd - whether it is allowable at this time to issue SIMD
  17. * instructions or access the SIMD register file
  18. *
  19. * Callers must not assume that the result remains true beyond the next
  20. * preempt_enable() or return from softirq context.
  21. */
  22. static __must_check inline bool may_use_simd(void)
  23. {
  24. /*
  25. * We must make sure that the SVE has been initialized properly
  26. * before using the SIMD in kernel.
  27. */
  28. return !WARN_ON(!system_capabilities_finalized()) &&
  29. system_supports_fpsimd() &&
  30. !in_hardirq() && !in_nmi();
  31. }
  32. #else /* ! CONFIG_KERNEL_MODE_NEON */
  33. static __must_check inline bool may_use_simd(void) {
  34. return false;
  35. }
  36. #endif /* ! CONFIG_KERNEL_MODE_NEON */
  37. DEFINE_LOCK_GUARD_1(ksimd,
  38. struct user_fpsimd_state,
  39. kernel_neon_begin(_T->lock),
  40. kernel_neon_end(_T->lock))
  41. #define __scoped_ksimd(_label) \
  42. for (struct user_fpsimd_state __uninitialized __st; \
  43. true; ({ goto _label; })) \
  44. if (0) { \
  45. _label: break; \
  46. } else scoped_guard(ksimd, &__st)
  47. #define scoped_ksimd() __scoped_ksimd(__UNIQUE_ID(label))
  48. #endif