percpu.h 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. /* SPDX-License-Identifier: GPL-2.0-only */
  2. /*
  3. * Copyright 2012 Calxeda, Inc.
  4. */
  5. #ifndef _ASM_ARM_PERCPU_H_
  6. #define _ASM_ARM_PERCPU_H_
  7. #include <asm/insn.h>
  8. register unsigned long current_stack_pointer asm ("sp");
  9. /*
  10. * Same as asm-generic/percpu.h, except that we store the per cpu offset
  11. * in the TPIDRPRW. TPIDRPRW only exists on V6K and V7
  12. */
  13. #ifdef CONFIG_SMP
  14. static inline void set_my_cpu_offset(unsigned long off)
  15. {
  16. extern unsigned int smp_on_up;
  17. if (IS_ENABLED(CONFIG_CPU_V6) && !smp_on_up)
  18. return;
  19. /* Set TPIDRPRW */
  20. asm volatile("mcr p15, 0, %0, c13, c0, 4" : : "r" (off) : "memory");
  21. }
  22. static __always_inline unsigned long __my_cpu_offset(void)
  23. {
  24. unsigned long off;
  25. /*
  26. * Read TPIDRPRW.
  27. * We want to allow caching the value, so avoid using volatile and
  28. * instead use a fake stack read to hazard against barrier().
  29. */
  30. asm("0: mrc p15, 0, %0, c13, c0, 4 \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, __per_cpu_offset) " \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 __per_cpu_offset \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" (off)
  51. : "Q" (*(const unsigned long *)current_stack_pointer));
  52. return off;
  53. }
  54. #define __my_cpu_offset __my_cpu_offset()
  55. #else
  56. #define set_my_cpu_offset(x) do {} while(0)
  57. #endif /* CONFIG_SMP */
  58. #include <asm-generic/percpu.h>
  59. #endif /* _ASM_ARM_PERCPU_H_ */