cache_helpers.S 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. /*
  2. * Copyright (c) 2013-2022, Arm Limited and Contributors. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. #include <arch.h>
  7. #include <asm_macros.S>
  8. .globl flush_dcache_range
  9. .globl flush_dcache_to_popa_range
  10. .globl clean_dcache_range
  11. .globl inv_dcache_range
  12. .globl dcsw_op_louis
  13. .globl dcsw_op_all
  14. .globl dcsw_op_level1
  15. .globl dcsw_op_level2
  16. .globl dcsw_op_level3
  17. /*
  18. * This macro can be used for implementing various data cache operations `op`
  19. */
  20. .macro do_dcache_maintenance_by_mva op
  21. /* Exit early if size is zero */
  22. cbz x1, exit_loop_\op
  23. dcache_line_size x2, x3
  24. add x1, x0, x1
  25. sub x3, x2, #1
  26. bic x0, x0, x3
  27. loop_\op:
  28. dc \op, x0
  29. add x0, x0, x2
  30. cmp x0, x1
  31. b.lo loop_\op
  32. dsb sy
  33. exit_loop_\op:
  34. ret
  35. .endm
  36. .macro check_plat_can_cmo
  37. #if CONDITIONAL_CMO
  38. mov x3, x30
  39. mov x2, x0
  40. bl plat_can_cmo
  41. mov x30, x3
  42. cbnz x0, 1f
  43. ret
  44. 1:
  45. mov x0, x2
  46. #endif
  47. .endm
  48. /* ------------------------------------------
  49. * Clean+Invalidate from base address till
  50. * size. 'x0' = addr, 'x1' = size
  51. * ------------------------------------------
  52. */
  53. func flush_dcache_range
  54. check_plat_can_cmo
  55. do_dcache_maintenance_by_mva civac
  56. endfunc flush_dcache_range
  57. /* ------------------------------------------
  58. * Clean from base address till size.
  59. * 'x0' = addr, 'x1' = size
  60. * ------------------------------------------
  61. */
  62. func clean_dcache_range
  63. check_plat_can_cmo
  64. do_dcache_maintenance_by_mva cvac
  65. endfunc clean_dcache_range
  66. /* ------------------------------------------
  67. * Invalidate from base address till
  68. * size. 'x0' = addr, 'x1' = size
  69. * ------------------------------------------
  70. */
  71. func inv_dcache_range
  72. check_plat_can_cmo
  73. do_dcache_maintenance_by_mva ivac
  74. endfunc inv_dcache_range
  75. /*
  76. * On implementations with FEAT_MTE2,
  77. * Root firmware must issue DC_CIGDPAPA instead of DC_CIPAPA ,
  78. * in order to additionally clean and invalidate Allocation Tags
  79. * associated with the affected locations.
  80. *
  81. * ------------------------------------------
  82. * Clean+Invalidate by PA to POPA
  83. * from base address till size.
  84. * 'x0' = addr, 'x1' = size
  85. * ------------------------------------------
  86. */
  87. func flush_dcache_to_popa_range
  88. /* Exit early if size is zero */
  89. cbz x1, exit_loop_dc_cipapa
  90. check_plat_can_cmo
  91. dcache_line_size x2, x3
  92. sub x3, x2, #1
  93. bic x0, x0, x3
  94. add x1, x1, x0
  95. loop_dc_cipapa:
  96. sys #6, c7, c14, #1, x0 /* DC CIPAPA,<Xt> */
  97. add x0, x0, x2
  98. cmp x0, x1
  99. b.lo loop_dc_cipapa
  100. dsb osh
  101. exit_loop_dc_cipapa:
  102. ret
  103. endfunc flush_dcache_to_popa_range
  104. /* ---------------------------------------------------------------
  105. * Data cache operations by set/way to the level specified
  106. *
  107. * The main function, do_dcsw_op requires:
  108. * x0: The operation type (0-2), as defined in arch.h
  109. * x3: The last cache level to operate on
  110. * x9: clidr_el1
  111. * x10: The cache level to begin operation from
  112. * and will carry out the operation on each data cache from level 0
  113. * to the level in x3 in sequence
  114. *
  115. * The dcsw_op macro sets up the x3 and x9 parameters based on
  116. * clidr_el1 cache information before invoking the main function
  117. * ---------------------------------------------------------------
  118. */
  119. .macro dcsw_op shift, fw, ls
  120. mrs x9, clidr_el1
  121. ubfx x3, x9, \shift, \fw
  122. lsl x3, x3, \ls
  123. mov x10, xzr
  124. b do_dcsw_op
  125. .endm
  126. func do_dcsw_op
  127. cbz x3, exit
  128. mrs x12, ID_AA64MMFR2_EL1 // stash FEAT_CCIDX identifier in x12
  129. ubfx x12, x12, #ID_AA64MMFR2_EL1_CCIDX_SHIFT, #ID_AA64MMFR2_EL1_CCIDX_LENGTH
  130. adr x14, dcsw_loop_table // compute inner loop address
  131. add x14, x14, x0, lsl #5 // inner loop is 8x32-bit instructions
  132. #if ENABLE_BTI
  133. add x14, x14, x0, lsl #2 // inner loop is + "bti j" instruction
  134. #endif
  135. mov x0, x9
  136. mov w8, #1
  137. loop1:
  138. add x2, x10, x10, lsr #1 // work out 3x current cache level
  139. lsr x1, x0, x2 // extract cache type bits from clidr
  140. and x1, x1, #7 // mask the bits for current cache only
  141. cmp x1, #2 // see what cache we have at this level
  142. b.lo level_done // nothing to do if no cache or icache
  143. msr csselr_el1, x10 // select current cache level in csselr
  144. isb // isb to sych the new cssr&csidr
  145. mrs x1, ccsidr_el1 // read the new ccsidr
  146. and x2, x1, #7 // extract the length of the cache lines
  147. add x2, x2, #4 // add 4 (line length offset)
  148. cbz x12, 1f // check for FEAT_CCIDX for Associativity
  149. ubfx x4, x1, #3, #21 // x4 = associativity CCSIDR_EL1[23:3]
  150. b 2f
  151. 1:
  152. ubfx x4, x1, #3, #10 // x4 = associativity CCSIDR_EL1[12:3]
  153. 2:
  154. clz w5, w4 // bit position of way size increment
  155. lsl w9, w4, w5 // w9 = aligned max way number
  156. lsl w16, w8, w5 // w16 = way number loop decrement
  157. orr w9, w10, w9 // w9 = combine way and cache number
  158. cbz x12, 3f // check for FEAT_CCIDX for NumSets
  159. ubfx x6, x1, #32, #24 // x6 (w6) = numsets CCSIDR_EL1[55:32]
  160. // ISA will not allow x->w ubfx
  161. b 4f
  162. 3:
  163. ubfx w6, w1, #13, #15 // w6 = numsets CCSIDR_EL1[27:13]
  164. 4:
  165. lsl w17, w8, w2 // w17 = set number loop decrement
  166. dsb sy // barrier before we start this level
  167. br x14 // jump to DC operation specific loop
  168. .macro dcsw_loop _op
  169. #if ENABLE_BTI
  170. bti j
  171. #endif
  172. loop2_\_op:
  173. lsl w7, w6, w2 // w7 = aligned max set number
  174. loop3_\_op:
  175. orr w11, w9, w7 // combine cache, way and set number
  176. dc \_op, x11
  177. subs w7, w7, w17 // decrement set number
  178. b.hs loop3_\_op
  179. subs x9, x9, x16 // decrement way number
  180. b.hs loop2_\_op
  181. b level_done
  182. .endm
  183. level_done:
  184. add x10, x10, #2 // increment cache number
  185. cmp x3, x10
  186. b.hi loop1
  187. msr csselr_el1, xzr // select cache level 0 in csselr
  188. dsb sy // barrier to complete final cache operation
  189. isb
  190. exit:
  191. ret
  192. endfunc do_dcsw_op
  193. dcsw_loop_table:
  194. dcsw_loop isw
  195. dcsw_loop cisw
  196. dcsw_loop csw
  197. func dcsw_op_louis
  198. check_plat_can_cmo
  199. dcsw_op #LOUIS_SHIFT, #CLIDR_FIELD_WIDTH, #LEVEL_SHIFT
  200. endfunc dcsw_op_louis
  201. func dcsw_op_all
  202. check_plat_can_cmo
  203. dcsw_op #LOC_SHIFT, #CLIDR_FIELD_WIDTH, #LEVEL_SHIFT
  204. endfunc dcsw_op_all
  205. /* ---------------------------------------------------------------
  206. * Helper macro for data cache operations by set/way for the
  207. * level specified
  208. * ---------------------------------------------------------------
  209. */
  210. .macro dcsw_op_level level
  211. mrs x9, clidr_el1
  212. mov x3, \level
  213. sub x10, x3, #2
  214. b do_dcsw_op
  215. .endm
  216. /* ---------------------------------------------------------------
  217. * Data cache operations by set/way for level 1 cache
  218. *
  219. * The main function, do_dcsw_op requires:
  220. * x0: The operation type (0-2), as defined in arch.h
  221. * ---------------------------------------------------------------
  222. */
  223. func dcsw_op_level1
  224. check_plat_can_cmo
  225. dcsw_op_level #(1 << LEVEL_SHIFT)
  226. endfunc dcsw_op_level1
  227. /* ---------------------------------------------------------------
  228. * Data cache operations by set/way for level 2 cache
  229. *
  230. * The main function, do_dcsw_op requires:
  231. * x0: The operation type (0-2), as defined in arch.h
  232. * ---------------------------------------------------------------
  233. */
  234. func dcsw_op_level2
  235. check_plat_can_cmo
  236. dcsw_op_level #(2 << LEVEL_SHIFT)
  237. endfunc dcsw_op_level2
  238. /* ---------------------------------------------------------------
  239. * Data cache operations by set/way for level 3 cache
  240. *
  241. * The main function, do_dcsw_op requires:
  242. * x0: The operation type (0-2), as defined in arch.h
  243. * ---------------------------------------------------------------
  244. */
  245. func dcsw_op_level3
  246. check_plat_can_cmo
  247. dcsw_op_level #(3 << LEVEL_SHIFT)
  248. endfunc dcsw_op_level3