1
0

tlbflush.h 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. /*
  2. * Based on arch/arm/include/asm/tlbflush.h
  3. *
  4. * Copyright (C) 1999-2003 Russell King
  5. * Copyright (C) 2012 ARM Ltd.
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License version 2 as
  9. * published by the Free Software Foundation.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #ifndef __ASM_TLBFLUSH_H
  20. #define __ASM_TLBFLUSH_H
  21. #ifndef __ASSEMBLY__
  22. #include <linux/sched.h>
  23. #include <asm/cputype.h>
  24. #include <asm/mmu.h>
  25. /*
  26. * Raw TLBI operations.
  27. *
  28. * Where necessary, use the __tlbi() macro to avoid asm()
  29. * boilerplate. Drivers and most kernel code should use the TLB
  30. * management routines in preference to the macro below.
  31. *
  32. * The macro can be used as __tlbi(op) or __tlbi(op, arg), depending
  33. * on whether a particular TLBI operation takes an argument or
  34. * not. The macros handles invoking the asm with or without the
  35. * register argument as appropriate.
  36. */
  37. #define __TLBI_0(op, arg) asm ("tlbi " #op "\n" \
  38. ALTERNATIVE("nop\n nop", \
  39. "dsb ish\n tlbi " #op, \
  40. ARM64_WORKAROUND_REPEAT_TLBI, \
  41. CONFIG_QCOM_FALKOR_ERRATUM_1009) \
  42. : : )
  43. #define __TLBI_1(op, arg) asm ("tlbi " #op ", %0\n" \
  44. ALTERNATIVE("nop\n nop", \
  45. "dsb ish\n tlbi " #op ", %0", \
  46. ARM64_WORKAROUND_REPEAT_TLBI, \
  47. CONFIG_QCOM_FALKOR_ERRATUM_1009) \
  48. : : "r" (arg))
  49. #define __TLBI_N(op, arg, n, ...) __TLBI_##n(op, arg)
  50. #define __tlbi(op, ...) __TLBI_N(op, ##__VA_ARGS__, 1, 0)
  51. #define __tlbi_user(op, arg) do { \
  52. if (arm64_kernel_unmapped_at_el0()) \
  53. __tlbi(op, (arg) | USER_ASID_FLAG); \
  54. } while (0)
  55. /* This macro creates a properly formatted VA operand for the TLBI */
  56. #define __TLBI_VADDR(addr, asid) \
  57. ({ \
  58. unsigned long __ta = (addr) >> 12; \
  59. __ta &= GENMASK_ULL(43, 0); \
  60. __ta |= (unsigned long)(asid) << 48; \
  61. __ta; \
  62. })
  63. /*
  64. * TLB Management
  65. * ==============
  66. *
  67. * The TLB specific code is expected to perform whatever tests it needs
  68. * to determine if it should invalidate the TLB for each call. Start
  69. * addresses are inclusive and end addresses are exclusive; it is safe to
  70. * round these addresses down.
  71. *
  72. * flush_tlb_all()
  73. *
  74. * Invalidate the entire TLB.
  75. *
  76. * flush_tlb_mm(mm)
  77. *
  78. * Invalidate all TLB entries in a particular address space.
  79. * - mm - mm_struct describing address space
  80. *
  81. * flush_tlb_range(mm,start,end)
  82. *
  83. * Invalidate a range of TLB entries in the specified address
  84. * space.
  85. * - mm - mm_struct describing address space
  86. * - start - start address (may not be aligned)
  87. * - end - end address (exclusive, may not be aligned)
  88. *
  89. * flush_tlb_page(vaddr,vma)
  90. *
  91. * Invalidate the specified page in the specified address range.
  92. * - vaddr - virtual address (may not be aligned)
  93. * - vma - vma_struct describing address range
  94. *
  95. * flush_kern_tlb_page(kaddr)
  96. *
  97. * Invalidate the TLB entry for the specified page. The address
  98. * will be in the kernels virtual memory space. Current uses
  99. * only require the D-TLB to be invalidated.
  100. * - kaddr - Kernel virtual memory address
  101. */
  102. static inline void local_flush_tlb_all(void)
  103. {
  104. dsb(nshst);
  105. __tlbi(vmalle1);
  106. dsb(nsh);
  107. isb();
  108. }
  109. static inline void flush_tlb_all(void)
  110. {
  111. dsb(ishst);
  112. __tlbi(vmalle1is);
  113. dsb(ish);
  114. isb();
  115. }
  116. static inline void flush_tlb_mm(struct mm_struct *mm)
  117. {
  118. unsigned long asid = __TLBI_VADDR(0, ASID(mm));
  119. dsb(ishst);
  120. __tlbi(aside1is, asid);
  121. __tlbi_user(aside1is, asid);
  122. dsb(ish);
  123. }
  124. static inline void flush_tlb_page(struct vm_area_struct *vma,
  125. unsigned long uaddr)
  126. {
  127. unsigned long addr = __TLBI_VADDR(uaddr, ASID(vma->vm_mm));
  128. dsb(ishst);
  129. __tlbi(vale1is, addr);
  130. __tlbi_user(vale1is, addr);
  131. dsb(ish);
  132. }
  133. /*
  134. * This is meant to avoid soft lock-ups on large TLB flushing ranges and not
  135. * necessarily a performance improvement.
  136. */
  137. #define MAX_TLB_RANGE (1024UL << PAGE_SHIFT)
  138. static inline void __flush_tlb_range(struct vm_area_struct *vma,
  139. unsigned long start, unsigned long end,
  140. bool last_level)
  141. {
  142. unsigned long asid = ASID(vma->vm_mm);
  143. unsigned long addr;
  144. if ((end - start) > MAX_TLB_RANGE) {
  145. flush_tlb_mm(vma->vm_mm);
  146. return;
  147. }
  148. start = __TLBI_VADDR(start, asid);
  149. end = __TLBI_VADDR(end, asid);
  150. dsb(ishst);
  151. for (addr = start; addr < end; addr += 1 << (PAGE_SHIFT - 12)) {
  152. if (last_level) {
  153. __tlbi(vale1is, addr);
  154. __tlbi_user(vale1is, addr);
  155. } else {
  156. __tlbi(vae1is, addr);
  157. __tlbi_user(vae1is, addr);
  158. }
  159. }
  160. dsb(ish);
  161. }
  162. static inline void flush_tlb_range(struct vm_area_struct *vma,
  163. unsigned long start, unsigned long end)
  164. {
  165. __flush_tlb_range(vma, start, end, false);
  166. }
  167. static inline void flush_tlb_kernel_range(unsigned long start, unsigned long end)
  168. {
  169. unsigned long addr;
  170. if ((end - start) > MAX_TLB_RANGE) {
  171. flush_tlb_all();
  172. return;
  173. }
  174. start = __TLBI_VADDR(start, 0);
  175. end = __TLBI_VADDR(end, 0);
  176. dsb(ishst);
  177. for (addr = start; addr < end; addr += 1 << (PAGE_SHIFT - 12))
  178. __tlbi(vaae1is, addr);
  179. dsb(ish);
  180. isb();
  181. }
  182. /*
  183. * Used to invalidate the TLB (walk caches) corresponding to intermediate page
  184. * table levels (pgd/pud/pmd).
  185. */
  186. static inline void __flush_tlb_pgtable(struct mm_struct *mm,
  187. unsigned long uaddr)
  188. {
  189. unsigned long addr = __TLBI_VADDR(uaddr, ASID(mm));
  190. __tlbi(vae1is, addr);
  191. __tlbi_user(vae1is, addr);
  192. dsb(ish);
  193. }
  194. static inline void __flush_tlb_kernel_pgtable(unsigned long kaddr)
  195. {
  196. unsigned long addr = __TLBI_VADDR(kaddr, 0);
  197. __tlbi(vaae1is, addr);
  198. dsb(ish);
  199. isb();
  200. }
  201. #endif
  202. #endif