cache-v7.S 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460
  1. /* SPDX-License-Identifier: GPL-2.0-only */
  2. /*
  3. * linux/arch/arm/mm/cache-v7.S
  4. *
  5. * Copyright (C) 2001 Deep Blue Solutions Ltd.
  6. * Copyright (C) 2005 ARM Ltd.
  7. *
  8. * This is the "shell" of the ARMv7 processor support.
  9. */
  10. #include <linux/linkage.h>
  11. #include <linux/init.h>
  12. #include <linux/cfi_types.h>
  13. #include <asm/assembler.h>
  14. #include <asm/errno.h>
  15. #include <asm/unwind.h>
  16. #include <asm/hardware/cache-b15-rac.h>
  17. #include "proc-macros.S"
  18. .arch armv7-a
  19. #ifdef CONFIG_CPU_ICACHE_MISMATCH_WORKAROUND
  20. .globl icache_size
  21. .data
  22. .align 2
  23. icache_size:
  24. .long 64
  25. .text
  26. #endif
  27. /*
  28. * The secondary kernel init calls v7_flush_dcache_all before it enables
  29. * the L1; however, the L1 comes out of reset in an undefined state, so
  30. * the clean + invalidate performed by v7_flush_dcache_all causes a bunch
  31. * of cache lines with uninitialized data and uninitialized tags to get
  32. * written out to memory, which does really unpleasant things to the main
  33. * processor. We fix this by performing an invalidate, rather than a
  34. * clean + invalidate, before jumping into the kernel.
  35. *
  36. * This function needs to be called for both secondary cores startup and
  37. * primary core resume procedures.
  38. */
  39. ENTRY(v7_invalidate_l1)
  40. mov r0, #0
  41. mcr p15, 2, r0, c0, c0, 0 @ select L1 data cache in CSSELR
  42. isb
  43. mrc p15, 1, r0, c0, c0, 0 @ read cache geometry from CCSIDR
  44. movw r3, #0x3ff
  45. and r3, r3, r0, lsr #3 @ 'Associativity' in CCSIDR[12:3]
  46. clz r1, r3 @ WayShift
  47. mov r2, #1
  48. mov r3, r3, lsl r1 @ NumWays-1 shifted into bits [31:...]
  49. movs r1, r2, lsl r1 @ #1 shifted left by same amount
  50. moveq r1, #1 @ r1 needs value > 0 even if only 1 way
  51. and r2, r0, #0x7
  52. add r2, r2, #4 @ SetShift
  53. 1: movw ip, #0x7fff
  54. and r0, ip, r0, lsr #13 @ 'NumSets' in CCSIDR[27:13]
  55. 2: mov ip, r0, lsl r2 @ NumSet << SetShift
  56. orr ip, ip, r3 @ Reg = (Temp<<WayShift)|(NumSets<<SetShift)
  57. mcr p15, 0, ip, c7, c6, 2
  58. subs r0, r0, #1 @ Set--
  59. bpl 2b
  60. subs r3, r3, r1 @ Way--
  61. bcc 3f
  62. mrc p15, 1, r0, c0, c0, 0 @ re-read cache geometry from CCSIDR
  63. b 1b
  64. 3: dsb st
  65. isb
  66. ret lr
  67. ENDPROC(v7_invalidate_l1)
  68. /*
  69. * v7_flush_icache_all()
  70. *
  71. * Flush the whole I-cache.
  72. *
  73. * Registers:
  74. * r0 - set to 0
  75. */
  76. SYM_TYPED_FUNC_START(v7_flush_icache_all)
  77. mov r0, #0
  78. ALT_SMP(mcr p15, 0, r0, c7, c1, 0) @ invalidate I-cache inner shareable
  79. ALT_UP(mcr p15, 0, r0, c7, c5, 0) @ I+BTB cache invalidate
  80. ret lr
  81. SYM_FUNC_END(v7_flush_icache_all)
  82. /*
  83. * v7_flush_dcache_louis()
  84. *
  85. * Flush the D-cache up to the Level of Unification Inner Shareable
  86. *
  87. * Corrupted registers: r0-r6, r9-r10
  88. */
  89. ENTRY(v7_flush_dcache_louis)
  90. dmb @ ensure ordering with previous memory accesses
  91. mrc p15, 1, r0, c0, c0, 1 @ read clidr, r0 = clidr
  92. ALT_SMP(mov r3, r0, lsr #20) @ move LoUIS into position
  93. ALT_UP( mov r3, r0, lsr #26) @ move LoUU into position
  94. ands r3, r3, #7 << 1 @ extract LoU*2 field from clidr
  95. bne start_flush_levels @ LoU != 0, start flushing
  96. #ifdef CONFIG_ARM_ERRATA_643719
  97. ALT_SMP(mrc p15, 0, r2, c0, c0, 0) @ read main ID register
  98. ALT_UP( ret lr) @ LoUU is zero, so nothing to do
  99. movw r1, #:lower16:(0x410fc090 >> 4) @ ID of ARM Cortex A9 r0p?
  100. movt r1, #:upper16:(0x410fc090 >> 4)
  101. teq r1, r2, lsr #4 @ test for errata affected core and if so...
  102. moveq r3, #1 << 1 @ fix LoUIS value
  103. beq start_flush_levels @ start flushing cache levels
  104. #endif
  105. ret lr
  106. ENDPROC(v7_flush_dcache_louis)
  107. /*
  108. * v7_flush_dcache_all()
  109. *
  110. * Flush the whole D-cache.
  111. *
  112. * Corrupted registers: r0-r6, r9-r10
  113. *
  114. * - mm - mm_struct describing address space
  115. */
  116. ENTRY(v7_flush_dcache_all)
  117. dmb @ ensure ordering with previous memory accesses
  118. mrc p15, 1, r0, c0, c0, 1 @ read clidr
  119. mov r3, r0, lsr #23 @ move LoC into position
  120. ands r3, r3, #7 << 1 @ extract LoC*2 from clidr
  121. beq finished @ if loc is 0, then no need to clean
  122. start_flush_levels:
  123. mov r10, #0 @ start clean at cache level 0
  124. flush_levels:
  125. add r2, r10, r10, lsr #1 @ work out 3x current cache level
  126. mov r1, r0, lsr r2 @ extract cache type bits from clidr
  127. and r1, r1, #7 @ mask of the bits for current cache only
  128. cmp r1, #2 @ see what cache we have at this level
  129. blt skip @ skip if no cache, or just i-cache
  130. #ifdef CONFIG_PREEMPTION
  131. save_and_disable_irqs_notrace r9 @ make cssr&csidr read atomic
  132. #endif
  133. mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr
  134. isb @ isb to sych the new cssr&csidr
  135. mrc p15, 1, r1, c0, c0, 0 @ read the new csidr
  136. #ifdef CONFIG_PREEMPTION
  137. restore_irqs_notrace r9
  138. #endif
  139. and r2, r1, #7 @ extract the length of the cache lines
  140. add r2, r2, #4 @ add 4 (line length offset)
  141. movw r4, #0x3ff
  142. ands r4, r4, r1, lsr #3 @ find maximum number on the way size
  143. clz r5, r4 @ find bit position of way size increment
  144. movw r6, #0x7fff
  145. and r1, r6, r1, lsr #13 @ extract max number of the index size
  146. mov r6, #1
  147. movne r4, r4, lsl r5 @ # of ways shifted into bits [31:...]
  148. movne r6, r6, lsl r5 @ 1 shifted left by same amount
  149. loop1:
  150. mov r9, r1 @ create working copy of max index
  151. loop2:
  152. mov r5, r9, lsl r2 @ factor set number into r5
  153. orr r5, r5, r4 @ factor way number into r5
  154. orr r5, r5, r10 @ factor cache level into r5
  155. mcr p15, 0, r5, c7, c14, 2 @ clean & invalidate by set/way
  156. subs r9, r9, #1 @ decrement the index
  157. bge loop2
  158. subs r4, r4, r6 @ decrement the way
  159. bcs loop1
  160. skip:
  161. add r10, r10, #2 @ increment cache number
  162. cmp r3, r10
  163. #ifdef CONFIG_ARM_ERRATA_814220
  164. dsb
  165. #endif
  166. bgt flush_levels
  167. finished:
  168. mov r10, #0 @ switch back to cache level 0
  169. mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr
  170. dsb st
  171. isb
  172. ret lr
  173. ENDPROC(v7_flush_dcache_all)
  174. /*
  175. * v7_flush_cache_all()
  176. *
  177. * Flush the entire cache system.
  178. * The data cache flush is now achieved using atomic clean / invalidates
  179. * working outwards from L1 cache. This is done using Set/Way based cache
  180. * maintenance instructions.
  181. * The instruction cache can still be invalidated back to the point of
  182. * unification in a single instruction.
  183. *
  184. */
  185. SYM_TYPED_FUNC_START(v7_flush_kern_cache_all)
  186. stmfd sp!, {r4-r6, r9-r10, lr}
  187. bl v7_flush_dcache_all
  188. mov r0, #0
  189. ALT_SMP(mcr p15, 0, r0, c7, c1, 0) @ invalidate I-cache inner shareable
  190. ALT_UP(mcr p15, 0, r0, c7, c5, 0) @ I+BTB cache invalidate
  191. ldmfd sp!, {r4-r6, r9-r10, lr}
  192. ret lr
  193. SYM_FUNC_END(v7_flush_kern_cache_all)
  194. /*
  195. * v7_flush_kern_cache_louis(void)
  196. *
  197. * Flush the data cache up to Level of Unification Inner Shareable.
  198. * Invalidate the I-cache to the point of unification.
  199. */
  200. SYM_TYPED_FUNC_START(v7_flush_kern_cache_louis)
  201. stmfd sp!, {r4-r6, r9-r10, lr}
  202. bl v7_flush_dcache_louis
  203. mov r0, #0
  204. ALT_SMP(mcr p15, 0, r0, c7, c1, 0) @ invalidate I-cache inner shareable
  205. ALT_UP(mcr p15, 0, r0, c7, c5, 0) @ I+BTB cache invalidate
  206. ldmfd sp!, {r4-r6, r9-r10, lr}
  207. ret lr
  208. SYM_FUNC_END(v7_flush_kern_cache_louis)
  209. /*
  210. * v7_flush_cache_all()
  211. *
  212. * Flush all TLB entries in a particular address space
  213. *
  214. * - mm - mm_struct describing address space
  215. */
  216. SYM_TYPED_FUNC_START(v7_flush_user_cache_all)
  217. ret lr
  218. SYM_FUNC_END(v7_flush_user_cache_all)
  219. /*
  220. * v7_flush_cache_range(start, end, flags)
  221. *
  222. * Flush a range of TLB entries in the specified address space.
  223. *
  224. * - start - start address (may not be aligned)
  225. * - end - end address (exclusive, may not be aligned)
  226. * - flags - vm_area_struct flags describing address space
  227. *
  228. * It is assumed that:
  229. * - we have a VIPT cache.
  230. */
  231. SYM_TYPED_FUNC_START(v7_flush_user_cache_range)
  232. ret lr
  233. SYM_FUNC_END(v7_flush_user_cache_range)
  234. /*
  235. * v7_coherent_kern_range(start,end)
  236. *
  237. * Ensure that the I and D caches are coherent within specified
  238. * region. This is typically used when code has been written to
  239. * a memory region, and will be executed.
  240. *
  241. * - start - virtual start address of region
  242. * - end - virtual end address of region
  243. *
  244. * It is assumed that:
  245. * - the Icache does not read data from the write buffer
  246. */
  247. SYM_TYPED_FUNC_START(v7_coherent_kern_range)
  248. #ifdef CONFIG_CFI /* Fallthrough if !CFI */
  249. b v7_coherent_user_range
  250. #endif
  251. SYM_FUNC_END(v7_coherent_kern_range)
  252. /*
  253. * v7_coherent_user_range(start,end)
  254. *
  255. * Ensure that the I and D caches are coherent within specified
  256. * region. This is typically used when code has been written to
  257. * a memory region, and will be executed.
  258. *
  259. * - start - virtual start address of region
  260. * - end - virtual end address of region
  261. *
  262. * It is assumed that:
  263. * - the Icache does not read data from the write buffer
  264. */
  265. SYM_TYPED_FUNC_START(v7_coherent_user_range)
  266. UNWIND(.fnstart )
  267. dcache_line_size r2, r3
  268. sub r3, r2, #1
  269. bic r12, r0, r3
  270. #ifdef CONFIG_ARM_ERRATA_764369
  271. ALT_SMP(W(dsb))
  272. ALT_UP(W(nop))
  273. #endif
  274. 1:
  275. USER( mcr p15, 0, r12, c7, c11, 1 ) @ clean D line to the point of unification
  276. add r12, r12, r2
  277. cmp r12, r1
  278. blo 1b
  279. dsb ishst
  280. #ifdef CONFIG_CPU_ICACHE_MISMATCH_WORKAROUND
  281. ldr r3, =icache_size
  282. ldr r2, [r3, #0]
  283. #else
  284. icache_line_size r2, r3
  285. #endif
  286. sub r3, r2, #1
  287. bic r12, r0, r3
  288. 2:
  289. USER( mcr p15, 0, r12, c7, c5, 1 ) @ invalidate I line
  290. add r12, r12, r2
  291. cmp r12, r1
  292. blo 2b
  293. mov r0, #0
  294. ALT_SMP(mcr p15, 0, r0, c7, c1, 6) @ invalidate BTB Inner Shareable
  295. ALT_UP(mcr p15, 0, r0, c7, c5, 6) @ invalidate BTB
  296. dsb ishst
  297. isb
  298. ret lr
  299. /*
  300. * Fault handling for the cache operation above. If the virtual address in r0
  301. * isn't mapped, fail with -EFAULT.
  302. */
  303. 9001:
  304. #ifdef CONFIG_ARM_ERRATA_775420
  305. dsb
  306. #endif
  307. mov r0, #-EFAULT
  308. ret lr
  309. UNWIND(.fnend )
  310. SYM_FUNC_END(v7_coherent_user_range)
  311. /*
  312. * v7_flush_kern_dcache_area(void *addr, size_t size)
  313. *
  314. * Ensure that the data held in the page kaddr is written back
  315. * to the page in question.
  316. *
  317. * - addr - kernel address
  318. * - size - region size
  319. */
  320. SYM_TYPED_FUNC_START(v7_flush_kern_dcache_area)
  321. dcache_line_size r2, r3
  322. add r1, r0, r1
  323. sub r3, r2, #1
  324. bic r0, r0, r3
  325. #ifdef CONFIG_ARM_ERRATA_764369
  326. ALT_SMP(W(dsb))
  327. ALT_UP(W(nop))
  328. #endif
  329. 1:
  330. mcr p15, 0, r0, c7, c14, 1 @ clean & invalidate D line / unified line
  331. add r0, r0, r2
  332. cmp r0, r1
  333. blo 1b
  334. dsb st
  335. ret lr
  336. SYM_FUNC_END(v7_flush_kern_dcache_area)
  337. /*
  338. * v7_dma_inv_range(start,end)
  339. *
  340. * Invalidate the data cache within the specified region; we will
  341. * be performing a DMA operation in this region and we want to
  342. * purge old data in the cache.
  343. *
  344. * - start - virtual start address of region
  345. * - end - virtual end address of region
  346. */
  347. v7_dma_inv_range:
  348. dcache_line_size r2, r3
  349. sub r3, r2, #1
  350. tst r0, r3
  351. bic r0, r0, r3
  352. #ifdef CONFIG_ARM_ERRATA_764369
  353. ALT_SMP(W(dsb))
  354. ALT_UP(W(nop))
  355. #endif
  356. mcrne p15, 0, r0, c7, c14, 1 @ clean & invalidate D / U line
  357. addne r0, r0, r2
  358. tst r1, r3
  359. bic r1, r1, r3
  360. mcrne p15, 0, r1, c7, c14, 1 @ clean & invalidate D / U line
  361. cmp r0, r1
  362. 1:
  363. mcrlo p15, 0, r0, c7, c6, 1 @ invalidate D / U line
  364. addlo r0, r0, r2
  365. cmplo r0, r1
  366. blo 1b
  367. dsb st
  368. ret lr
  369. ENDPROC(v7_dma_inv_range)
  370. /*
  371. * v7_dma_clean_range(start,end)
  372. * - start - virtual start address of region
  373. * - end - virtual end address of region
  374. */
  375. v7_dma_clean_range:
  376. dcache_line_size r2, r3
  377. sub r3, r2, #1
  378. bic r0, r0, r3
  379. #ifdef CONFIG_ARM_ERRATA_764369
  380. ALT_SMP(W(dsb))
  381. ALT_UP(W(nop))
  382. #endif
  383. 1:
  384. mcr p15, 0, r0, c7, c10, 1 @ clean D / U line
  385. add r0, r0, r2
  386. cmp r0, r1
  387. blo 1b
  388. dsb st
  389. ret lr
  390. ENDPROC(v7_dma_clean_range)
  391. /*
  392. * v7_dma_flush_range(start,end)
  393. * - start - virtual start address of region
  394. * - end - virtual end address of region
  395. */
  396. SYM_TYPED_FUNC_START(v7_dma_flush_range)
  397. dcache_line_size r2, r3
  398. sub r3, r2, #1
  399. bic r0, r0, r3
  400. #ifdef CONFIG_ARM_ERRATA_764369
  401. ALT_SMP(W(dsb))
  402. ALT_UP(W(nop))
  403. #endif
  404. 1:
  405. mcr p15, 0, r0, c7, c14, 1 @ clean & invalidate D / U line
  406. add r0, r0, r2
  407. cmp r0, r1
  408. blo 1b
  409. dsb st
  410. ret lr
  411. SYM_FUNC_END(v7_dma_flush_range)
  412. /*
  413. * dma_map_area(start, size, dir)
  414. * - start - kernel virtual start address
  415. * - size - size of region
  416. * - dir - DMA direction
  417. */
  418. SYM_TYPED_FUNC_START(v7_dma_map_area)
  419. add r1, r1, r0
  420. teq r2, #DMA_FROM_DEVICE
  421. beq v7_dma_inv_range
  422. b v7_dma_clean_range
  423. SYM_FUNC_END(v7_dma_map_area)
  424. /*
  425. * dma_unmap_area(start, size, dir)
  426. * - start - kernel virtual start address
  427. * - size - size of region
  428. * - dir - DMA direction
  429. */
  430. SYM_TYPED_FUNC_START(v7_dma_unmap_area)
  431. add r1, r1, r0
  432. teq r2, #DMA_TO_DEVICE
  433. bne v7_dma_inv_range
  434. ret lr
  435. SYM_FUNC_END(v7_dma_unmap_area)