current.h 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. /* SPDX-License-Identifier: GPL-2.0-only */
  2. /*
  3. * Copyright (c) 2021 Keith Packard <[email protected]>
  4. * Copyright (c) 2021 Google, LLC <[email protected]>
  5. */
  6. #ifndef _ASM_ARM_CURRENT_H
  7. #define _ASM_ARM_CURRENT_H
  8. #ifndef __ASSEMBLY__
  9. #include <asm/insn.h>
  10. struct task_struct;
  11. extern struct task_struct *__current;
  12. static __always_inline __attribute_const__ struct task_struct *get_current(void)
  13. {
  14. struct task_struct *cur;
  15. #if __has_builtin(__builtin_thread_pointer) && \
  16. defined(CONFIG_CURRENT_POINTER_IN_TPIDRURO) && \
  17. !(defined(CONFIG_THUMB2_KERNEL) && \
  18. defined(CONFIG_CC_IS_CLANG) && CONFIG_CLANG_VERSION < 130001)
  19. /*
  20. * Use the __builtin helper when available - this results in better
  21. * code, especially when using GCC in combination with the per-task
  22. * stack protector, as the compiler will recognize that it needs to
  23. * load the TLS register only once in every function.
  24. *
  25. * Clang < 13.0.1 gets this wrong for Thumb2 builds:
  26. * https://github.com/ClangBuiltLinux/linux/issues/1485
  27. */
  28. cur = __builtin_thread_pointer();
  29. #elif defined(CONFIG_CURRENT_POINTER_IN_TPIDRURO) || defined(CONFIG_SMP)
  30. asm("0: mrc p15, 0, %0, c13, c0, 3 \n\t"
  31. #ifdef CONFIG_CPU_V6
  32. "1: \n\t"
  33. " .subsection 1 \n\t"
  34. #if defined(CONFIG_ARM_HAS_GROUP_RELOCS) && \
  35. !(defined(MODULE) && defined(CONFIG_ARM_MODULE_PLTS))
  36. "2: " LOAD_SYM_ARMV6(%0, __current) " \n\t"
  37. " b 1b \n\t"
  38. #else
  39. "2: ldr %0, 3f \n\t"
  40. " ldr %0, [%0] \n\t"
  41. " b 1b \n\t"
  42. "3: .long __current \n\t"
  43. #endif
  44. " .previous \n\t"
  45. " .pushsection \".alt.smp.init\", \"a\" \n\t"
  46. " .long 0b - . \n\t"
  47. " b . + (2b - 0b) \n\t"
  48. " .popsection \n\t"
  49. #endif
  50. : "=r"(cur));
  51. #elif __LINUX_ARM_ARCH__>= 7 || \
  52. !defined(CONFIG_ARM_HAS_GROUP_RELOCS) || \
  53. (defined(MODULE) && defined(CONFIG_ARM_MODULE_PLTS))
  54. cur = __current;
  55. #else
  56. asm(LOAD_SYM_ARMV6(%0, __current) : "=r"(cur));
  57. #endif
  58. return cur;
  59. }
  60. #define current get_current()
  61. #endif /* __ASSEMBLY__ */
  62. #endif /* _ASM_ARM_CURRENT_H */