cache.S 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. /*
  2. * Cache maintenance
  3. *
  4. * Copyright (C) 2001 Deep Blue Solutions Ltd.
  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. #include <linux/errno.h>
  20. #include <linux/linkage.h>
  21. #include <linux/init.h>
  22. #include <asm/assembler.h>
  23. #include <asm/cpufeature.h>
  24. #include <asm/alternative.h>
  25. #include "proc-macros.S"
  26. /*
  27. * flush_icache_range(start,end)
  28. *
  29. * Ensure that the I and D caches are coherent within specified region.
  30. * This is typically used when code has been written to a memory region,
  31. * and will be executed.
  32. *
  33. * - start - virtual start address of region
  34. * - end - virtual end address of region
  35. */
  36. ENTRY(flush_icache_range)
  37. /* FALLTHROUGH */
  38. /*
  39. * __flush_cache_user_range(start,end)
  40. *
  41. * Ensure that the I and D caches are coherent within specified region.
  42. * This is typically used when code has been written to a memory region,
  43. * and will be executed.
  44. *
  45. * - start - virtual start address of region
  46. * - end - virtual end address of region
  47. */
  48. ENTRY(__flush_cache_user_range)
  49. dcache_line_size x2, x3
  50. sub x3, x2, #1
  51. bic x4, x0, x3
  52. 1:
  53. USER(9f, dc cvau, x4 ) // clean D line to PoU
  54. add x4, x4, x2
  55. cmp x4, x1
  56. b.lo 1b
  57. dsb ish
  58. icache_line_size x2, x3
  59. sub x3, x2, #1
  60. bic x4, x0, x3
  61. 1:
  62. USER(9f, ic ivau, x4 ) // invalidate I line PoU
  63. add x4, x4, x2
  64. cmp x4, x1
  65. b.lo 1b
  66. dsb ish
  67. isb
  68. mov x0, #0
  69. ret
  70. 9:
  71. mov x0, #-EFAULT
  72. ret
  73. ENDPROC(flush_icache_range)
  74. ENDPROC(__flush_cache_user_range)
  75. /*
  76. * __flush_dcache_area(kaddr, size)
  77. *
  78. * Ensure that any D-cache lines for the interval [kaddr, kaddr+size)
  79. * are cleaned and invalidated to the PoC.
  80. *
  81. * - kaddr - kernel address
  82. * - size - size in question
  83. */
  84. ENTRY(__flush_dcache_area)
  85. dcache_by_line_op civac, sy, x0, x1, x2, x3
  86. ret
  87. ENDPIPROC(__flush_dcache_area)
  88. /*
  89. * __clean_dcache_area_pou(kaddr, size)
  90. *
  91. * Ensure that any D-cache lines for the interval [kaddr, kaddr+size)
  92. * are cleaned to the PoU.
  93. *
  94. * - kaddr - kernel address
  95. * - size - size in question
  96. */
  97. ENTRY(__clean_dcache_area_pou)
  98. dcache_by_line_op cvau, ish, x0, x1, x2, x3
  99. ret
  100. ENDPROC(__clean_dcache_area_pou)
  101. /*
  102. * __inval_cache_range(start, end)
  103. * - start - start address of region
  104. * - end - end address of region
  105. */
  106. ENTRY(__inval_cache_range)
  107. /* FALLTHROUGH */
  108. /*
  109. * __dma_inv_range(start, end)
  110. * - start - virtual start address of region
  111. * - end - virtual end address of region
  112. */
  113. __dma_inv_range:
  114. dcache_line_size x2, x3
  115. sub x3, x2, #1
  116. tst x1, x3 // end cache line aligned?
  117. bic x1, x1, x3
  118. b.eq 1f
  119. dc civac, x1 // clean & invalidate D / U line
  120. 1: tst x0, x3 // start cache line aligned?
  121. bic x0, x0, x3
  122. b.eq 2f
  123. dc civac, x0 // clean & invalidate D / U line
  124. b 3f
  125. 2: dc ivac, x0 // invalidate D / U line
  126. 3: add x0, x0, x2
  127. cmp x0, x1
  128. b.lo 2b
  129. dsb sy
  130. ret
  131. ENDPIPROC(__inval_cache_range)
  132. ENDPROC(__dma_inv_range)
  133. /*
  134. * __dma_clean_range(start, end)
  135. * - start - virtual start address of region
  136. * - end - virtual end address of region
  137. */
  138. __dma_clean_range:
  139. dcache_line_size x2, x3
  140. sub x3, x2, #1
  141. bic x0, x0, x3
  142. 1:
  143. alternative_if_not ARM64_WORKAROUND_CLEAN_CACHE
  144. dc cvac, x0
  145. alternative_else
  146. dc civac, x0
  147. alternative_endif
  148. add x0, x0, x2
  149. cmp x0, x1
  150. b.lo 1b
  151. dsb sy
  152. ret
  153. ENDPROC(__dma_clean_range)
  154. /*
  155. * __dma_flush_range(start, end)
  156. * - start - virtual start address of region
  157. * - end - virtual end address of region
  158. */
  159. ENTRY(__dma_flush_range)
  160. dcache_line_size x2, x3
  161. sub x3, x2, #1
  162. bic x0, x0, x3
  163. 1: dc civac, x0 // clean & invalidate D / U line
  164. add x0, x0, x2
  165. cmp x0, x1
  166. b.lo 1b
  167. dsb sy
  168. ret
  169. ENDPIPROC(__dma_flush_range)
  170. /*
  171. * __dma_map_area(start, size, dir)
  172. * - start - kernel virtual start address
  173. * - size - size of region
  174. * - dir - DMA direction
  175. */
  176. ENTRY(__dma_map_area)
  177. add x1, x1, x0
  178. cmp w2, #DMA_FROM_DEVICE
  179. b.eq __dma_inv_range
  180. b __dma_clean_range
  181. ENDPIPROC(__dma_map_area)
  182. /*
  183. * __dma_unmap_area(start, size, dir)
  184. * - start - kernel virtual start address
  185. * - size - size of region
  186. * - dir - DMA direction
  187. */
  188. ENTRY(__dma_unmap_area)
  189. add x1, x1, x0
  190. cmp w2, #DMA_TO_DEVICE
  191. b.ne __dma_inv_range
  192. ret
  193. ENDPIPROC(__dma_unmap_area)