cache_helpers.S 8.0 KB

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