proc-fns.h 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. /* SPDX-License-Identifier: GPL-2.0-only */
  2. /*
  3. * arch/arm/include/asm/proc-fns.h
  4. *
  5. * Copyright (C) 1997-1999 Russell King
  6. * Copyright (C) 2000 Deep Blue Solutions Ltd
  7. */
  8. #ifndef __ASM_PROCFNS_H
  9. #define __ASM_PROCFNS_H
  10. #ifdef __KERNEL__
  11. #include <asm/glue-proc.h>
  12. #include <asm/page.h>
  13. #ifndef __ASSEMBLY__
  14. struct mm_struct;
  15. /*
  16. * Don't change this structure - ASM code relies on it.
  17. */
  18. struct processor {
  19. /* MISC
  20. * get data abort address/flags
  21. */
  22. void (*_data_abort)(unsigned long pc);
  23. /*
  24. * Retrieve prefetch fault address
  25. */
  26. unsigned long (*_prefetch_abort)(unsigned long lr);
  27. /*
  28. * Set up any processor specifics
  29. */
  30. void (*_proc_init)(void);
  31. /*
  32. * Check for processor bugs
  33. */
  34. void (*check_bugs)(void);
  35. /*
  36. * Disable any processor specifics
  37. */
  38. void (*_proc_fin)(void);
  39. /*
  40. * Special stuff for a reset
  41. */
  42. void (*reset)(unsigned long addr, bool hvc) __attribute__((noreturn));
  43. /*
  44. * Idle the processor
  45. */
  46. int (*_do_idle)(void);
  47. /*
  48. * Processor architecture specific
  49. */
  50. /*
  51. * clean a virtual address range from the
  52. * D-cache without flushing the cache.
  53. */
  54. void (*dcache_clean_area)(void *addr, int size);
  55. /*
  56. * Set the page table
  57. */
  58. void (*switch_mm)(phys_addr_t pgd_phys, struct mm_struct *mm);
  59. /*
  60. * Set a possibly extended PTE. Non-extended PTEs should
  61. * ignore 'ext'.
  62. */
  63. #ifdef CONFIG_ARM_LPAE
  64. void (*set_pte_ext)(pte_t *ptep, pte_t pte);
  65. #else
  66. void (*set_pte_ext)(pte_t *ptep, pte_t pte, unsigned int ext);
  67. #endif
  68. /* Suspend/resume */
  69. unsigned int suspend_size;
  70. void (*do_suspend)(void *);
  71. void (*do_resume)(void *);
  72. };
  73. #ifndef MULTI_CPU
  74. static inline void init_proc_vtable(const struct processor *p)
  75. {
  76. }
  77. extern void cpu_proc_init(void);
  78. extern void cpu_proc_fin(void);
  79. extern int cpu_do_idle(void);
  80. extern void cpu_dcache_clean_area(void *, int);
  81. extern void cpu_do_switch_mm(phys_addr_t pgd_phys, struct mm_struct *mm);
  82. #ifdef CONFIG_ARM_LPAE
  83. extern void cpu_set_pte_ext(pte_t *ptep, pte_t pte);
  84. #else
  85. extern void cpu_set_pte_ext(pte_t *ptep, pte_t pte, unsigned int ext);
  86. #endif
  87. extern void cpu_reset(unsigned long addr, bool hvc) __attribute__((noreturn));
  88. /* These three are private to arch/arm/kernel/suspend.c */
  89. extern void cpu_do_suspend(void *);
  90. extern void cpu_do_resume(void *);
  91. #else
  92. extern struct processor processor;
  93. #if defined(CONFIG_BIG_LITTLE) && defined(CONFIG_HARDEN_BRANCH_PREDICTOR)
  94. #include <linux/smp.h>
  95. /*
  96. * This can't be a per-cpu variable because we need to access it before
  97. * per-cpu has been initialised. We have a couple of functions that are
  98. * called in a pre-emptible context, and so can't use smp_processor_id()
  99. * there, hence PROC_TABLE(). We insist in init_proc_vtable() that the
  100. * function pointers for these are identical across all CPUs.
  101. */
  102. extern struct processor *cpu_vtable[];
  103. #define PROC_VTABLE(f) cpu_vtable[smp_processor_id()]->f
  104. #define PROC_TABLE(f) cpu_vtable[0]->f
  105. static inline void init_proc_vtable(const struct processor *p)
  106. {
  107. unsigned int cpu = smp_processor_id();
  108. *cpu_vtable[cpu] = *p;
  109. WARN_ON_ONCE(cpu_vtable[cpu]->dcache_clean_area !=
  110. cpu_vtable[0]->dcache_clean_area);
  111. WARN_ON_ONCE(cpu_vtable[cpu]->set_pte_ext !=
  112. cpu_vtable[0]->set_pte_ext);
  113. }
  114. #else
  115. #define PROC_VTABLE(f) processor.f
  116. #define PROC_TABLE(f) processor.f
  117. static inline void init_proc_vtable(const struct processor *p)
  118. {
  119. processor = *p;
  120. }
  121. #endif
  122. #define cpu_proc_init PROC_VTABLE(_proc_init)
  123. #define cpu_check_bugs PROC_VTABLE(check_bugs)
  124. #define cpu_proc_fin PROC_VTABLE(_proc_fin)
  125. #define cpu_reset PROC_VTABLE(reset)
  126. #define cpu_do_idle PROC_VTABLE(_do_idle)
  127. #define cpu_dcache_clean_area PROC_TABLE(dcache_clean_area)
  128. #define cpu_set_pte_ext PROC_TABLE(set_pte_ext)
  129. #define cpu_do_switch_mm PROC_VTABLE(switch_mm)
  130. /* These two are private to arch/arm/kernel/suspend.c */
  131. #define cpu_do_suspend PROC_VTABLE(do_suspend)
  132. #define cpu_do_resume PROC_VTABLE(do_resume)
  133. #endif
  134. extern void cpu_resume(void);
  135. #include <asm/memory.h>
  136. #ifdef CONFIG_MMU
  137. #define cpu_switch_mm(pgd,mm) cpu_do_switch_mm(virt_to_phys(pgd),mm)
  138. #ifdef CONFIG_ARM_LPAE
  139. #define cpu_get_ttbr(nr) \
  140. ({ \
  141. u64 ttbr; \
  142. __asm__("mrrc p15, " #nr ", %Q0, %R0, c2" \
  143. : "=r" (ttbr)); \
  144. ttbr; \
  145. })
  146. #define cpu_get_pgd() \
  147. ({ \
  148. u64 pg = cpu_get_ttbr(0); \
  149. pg &= ~(PTRS_PER_PGD*sizeof(pgd_t)-1); \
  150. (pgd_t *)phys_to_virt(pg); \
  151. })
  152. #else
  153. #define cpu_get_pgd() \
  154. ({ \
  155. unsigned long pg; \
  156. __asm__("mrc p15, 0, %0, c2, c0, 0" \
  157. : "=r" (pg) : : "cc"); \
  158. pg &= ~0x3fff; \
  159. (pgd_t *)phys_to_virt(pg); \
  160. })
  161. #endif
  162. #else /*!CONFIG_MMU */
  163. #define cpu_switch_mm(pgd,mm) { }
  164. #endif
  165. #endif /* __ASSEMBLY__ */
  166. #endif /* __KERNEL__ */
  167. #endif /* __ASM_PROCFNS_H */