hypersparc.S 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. /*
  3. * hypersparc.S: High speed Hypersparc mmu/cache operations.
  4. *
  5. * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
  6. */
  7. #include <asm/ptrace.h>
  8. #include <asm/psr.h>
  9. #include <asm/asm-offsets.h>
  10. #include <asm/asi.h>
  11. #include <asm/page.h>
  12. #include <asm/pgtsrmmu.h>
  13. #include <linux/init.h>
  14. .text
  15. .align 4
  16. .globl hypersparc_flush_cache_all, hypersparc_flush_cache_mm
  17. .globl hypersparc_flush_cache_range, hypersparc_flush_cache_page
  18. .globl hypersparc_flush_page_to_ram
  19. .globl hypersparc_flush_page_for_dma, hypersparc_flush_sig_insns
  20. .globl hypersparc_flush_tlb_all, hypersparc_flush_tlb_mm
  21. .globl hypersparc_flush_tlb_range, hypersparc_flush_tlb_page
  22. hypersparc_flush_cache_all:
  23. WINDOW_FLUSH(%g4, %g5)
  24. sethi %hi(vac_cache_size), %g4
  25. ld [%g4 + %lo(vac_cache_size)], %g5
  26. sethi %hi(vac_line_size), %g1
  27. ld [%g1 + %lo(vac_line_size)], %g2
  28. 1:
  29. subcc %g5, %g2, %g5 ! hyper_flush_unconditional_combined
  30. bne 1b
  31. sta %g0, [%g5] ASI_M_FLUSH_CTX
  32. retl
  33. sta %g0, [%g0] ASI_M_FLUSH_IWHOLE ! hyper_flush_whole_icache
  34. /* We expand the window flush to get maximum performance. */
  35. hypersparc_flush_cache_mm:
  36. #ifndef CONFIG_SMP
  37. ld [%o0 + AOFF_mm_context], %g1
  38. cmp %g1, -1
  39. be hypersparc_flush_cache_mm_out
  40. #endif
  41. WINDOW_FLUSH(%g4, %g5)
  42. sethi %hi(vac_line_size), %g1
  43. ld [%g1 + %lo(vac_line_size)], %o1
  44. sethi %hi(vac_cache_size), %g2
  45. ld [%g2 + %lo(vac_cache_size)], %o0
  46. add %o1, %o1, %g1
  47. add %o1, %g1, %g2
  48. add %o1, %g2, %g3
  49. add %o1, %g3, %g4
  50. add %o1, %g4, %g5
  51. add %o1, %g5, %o4
  52. add %o1, %o4, %o5
  53. /* BLAMMO! */
  54. 1:
  55. subcc %o0, %o5, %o0 ! hyper_flush_cache_user
  56. sta %g0, [%o0 + %g0] ASI_M_FLUSH_USER
  57. sta %g0, [%o0 + %o1] ASI_M_FLUSH_USER
  58. sta %g0, [%o0 + %g1] ASI_M_FLUSH_USER
  59. sta %g0, [%o0 + %g2] ASI_M_FLUSH_USER
  60. sta %g0, [%o0 + %g3] ASI_M_FLUSH_USER
  61. sta %g0, [%o0 + %g4] ASI_M_FLUSH_USER
  62. sta %g0, [%o0 + %g5] ASI_M_FLUSH_USER
  63. bne 1b
  64. sta %g0, [%o0 + %o4] ASI_M_FLUSH_USER
  65. hypersparc_flush_cache_mm_out:
  66. retl
  67. nop
  68. /* The things we do for performance... */
  69. hypersparc_flush_cache_range:
  70. ld [%o0 + VMA_VM_MM], %o0
  71. #ifndef CONFIG_SMP
  72. ld [%o0 + AOFF_mm_context], %g1
  73. cmp %g1, -1
  74. be hypersparc_flush_cache_range_out
  75. #endif
  76. WINDOW_FLUSH(%g4, %g5)
  77. sethi %hi(vac_line_size), %g1
  78. ld [%g1 + %lo(vac_line_size)], %o4
  79. sethi %hi(vac_cache_size), %g2
  80. ld [%g2 + %lo(vac_cache_size)], %o3
  81. /* Here comes the fun part... */
  82. add %o2, (PAGE_SIZE - 1), %o2
  83. andn %o1, (PAGE_SIZE - 1), %o1
  84. add %o4, %o4, %o5
  85. andn %o2, (PAGE_SIZE - 1), %o2
  86. add %o4, %o5, %g1
  87. sub %o2, %o1, %g4
  88. add %o4, %g1, %g2
  89. sll %o3, 2, %g5
  90. add %o4, %g2, %g3
  91. cmp %g4, %g5
  92. add %o4, %g3, %g4
  93. blu 0f
  94. add %o4, %g4, %g5
  95. add %o4, %g5, %g7
  96. /* Flush entire user space, believe it or not this is quicker
  97. * than page at a time flushings for range > (cache_size<<2).
  98. */
  99. 1:
  100. subcc %o3, %g7, %o3
  101. sta %g0, [%o3 + %g0] ASI_M_FLUSH_USER
  102. sta %g0, [%o3 + %o4] ASI_M_FLUSH_USER
  103. sta %g0, [%o3 + %o5] ASI_M_FLUSH_USER
  104. sta %g0, [%o3 + %g1] ASI_M_FLUSH_USER
  105. sta %g0, [%o3 + %g2] ASI_M_FLUSH_USER
  106. sta %g0, [%o3 + %g3] ASI_M_FLUSH_USER
  107. sta %g0, [%o3 + %g4] ASI_M_FLUSH_USER
  108. bne 1b
  109. sta %g0, [%o3 + %g5] ASI_M_FLUSH_USER
  110. retl
  111. nop
  112. /* Below our threshold, flush one page at a time. */
  113. 0:
  114. ld [%o0 + AOFF_mm_context], %o0
  115. mov SRMMU_CTX_REG, %g7
  116. lda [%g7] ASI_M_MMUREGS, %o3
  117. sta %o0, [%g7] ASI_M_MMUREGS
  118. add %o2, -PAGE_SIZE, %o0
  119. 1:
  120. or %o0, 0x400, %g7
  121. lda [%g7] ASI_M_FLUSH_PROBE, %g7
  122. orcc %g7, 0, %g0
  123. be,a 3f
  124. mov %o0, %o2
  125. add %o4, %g5, %g7
  126. 2:
  127. sub %o2, %g7, %o2
  128. sta %g0, [%o2 + %g0] ASI_M_FLUSH_PAGE
  129. sta %g0, [%o2 + %o4] ASI_M_FLUSH_PAGE
  130. sta %g0, [%o2 + %o5] ASI_M_FLUSH_PAGE
  131. sta %g0, [%o2 + %g1] ASI_M_FLUSH_PAGE
  132. sta %g0, [%o2 + %g2] ASI_M_FLUSH_PAGE
  133. sta %g0, [%o2 + %g3] ASI_M_FLUSH_PAGE
  134. andcc %o2, 0xffc, %g0
  135. sta %g0, [%o2 + %g4] ASI_M_FLUSH_PAGE
  136. bne 2b
  137. sta %g0, [%o2 + %g5] ASI_M_FLUSH_PAGE
  138. 3:
  139. cmp %o2, %o1
  140. bne 1b
  141. add %o2, -PAGE_SIZE, %o0
  142. mov SRMMU_FAULT_STATUS, %g5
  143. lda [%g5] ASI_M_MMUREGS, %g0
  144. mov SRMMU_CTX_REG, %g7
  145. sta %o3, [%g7] ASI_M_MMUREGS
  146. hypersparc_flush_cache_range_out:
  147. retl
  148. nop
  149. /* HyperSparc requires a valid mapping where we are about to flush
  150. * in order to check for a physical tag match during the flush.
  151. */
  152. /* Verified, my ass... */
  153. hypersparc_flush_cache_page:
  154. ld [%o0 + VMA_VM_MM], %o0
  155. ld [%o0 + AOFF_mm_context], %g2
  156. #ifndef CONFIG_SMP
  157. cmp %g2, -1
  158. be hypersparc_flush_cache_page_out
  159. #endif
  160. WINDOW_FLUSH(%g4, %g5)
  161. sethi %hi(vac_line_size), %g1
  162. ld [%g1 + %lo(vac_line_size)], %o4
  163. mov SRMMU_CTX_REG, %o3
  164. andn %o1, (PAGE_SIZE - 1), %o1
  165. lda [%o3] ASI_M_MMUREGS, %o2
  166. sta %g2, [%o3] ASI_M_MMUREGS
  167. or %o1, 0x400, %o5
  168. lda [%o5] ASI_M_FLUSH_PROBE, %g1
  169. orcc %g0, %g1, %g0
  170. be 2f
  171. add %o4, %o4, %o5
  172. sub %o1, -PAGE_SIZE, %o1
  173. add %o4, %o5, %g1
  174. add %o4, %g1, %g2
  175. add %o4, %g2, %g3
  176. add %o4, %g3, %g4
  177. add %o4, %g4, %g5
  178. add %o4, %g5, %g7
  179. /* BLAMMO! */
  180. 1:
  181. sub %o1, %g7, %o1
  182. sta %g0, [%o1 + %g0] ASI_M_FLUSH_PAGE
  183. sta %g0, [%o1 + %o4] ASI_M_FLUSH_PAGE
  184. sta %g0, [%o1 + %o5] ASI_M_FLUSH_PAGE
  185. sta %g0, [%o1 + %g1] ASI_M_FLUSH_PAGE
  186. sta %g0, [%o1 + %g2] ASI_M_FLUSH_PAGE
  187. sta %g0, [%o1 + %g3] ASI_M_FLUSH_PAGE
  188. andcc %o1, 0xffc, %g0
  189. sta %g0, [%o1 + %g4] ASI_M_FLUSH_PAGE
  190. bne 1b
  191. sta %g0, [%o1 + %g5] ASI_M_FLUSH_PAGE
  192. 2:
  193. mov SRMMU_FAULT_STATUS, %g7
  194. mov SRMMU_CTX_REG, %g4
  195. lda [%g7] ASI_M_MMUREGS, %g0
  196. sta %o2, [%g4] ASI_M_MMUREGS
  197. hypersparc_flush_cache_page_out:
  198. retl
  199. nop
  200. hypersparc_flush_sig_insns:
  201. flush %o1
  202. retl
  203. flush %o1 + 4
  204. /* HyperSparc is copy-back. */
  205. hypersparc_flush_page_to_ram:
  206. sethi %hi(vac_line_size), %g1
  207. ld [%g1 + %lo(vac_line_size)], %o4
  208. andn %o0, (PAGE_SIZE - 1), %o0
  209. add %o4, %o4, %o5
  210. or %o0, 0x400, %g7
  211. lda [%g7] ASI_M_FLUSH_PROBE, %g5
  212. add %o4, %o5, %g1
  213. orcc %g5, 0, %g0
  214. be 2f
  215. add %o4, %g1, %g2
  216. add %o4, %g2, %g3
  217. sub %o0, -PAGE_SIZE, %o0
  218. add %o4, %g3, %g4
  219. add %o4, %g4, %g5
  220. add %o4, %g5, %g7
  221. /* BLAMMO! */
  222. 1:
  223. sub %o0, %g7, %o0
  224. sta %g0, [%o0 + %g0] ASI_M_FLUSH_PAGE
  225. sta %g0, [%o0 + %o4] ASI_M_FLUSH_PAGE
  226. sta %g0, [%o0 + %o5] ASI_M_FLUSH_PAGE
  227. sta %g0, [%o0 + %g1] ASI_M_FLUSH_PAGE
  228. sta %g0, [%o0 + %g2] ASI_M_FLUSH_PAGE
  229. sta %g0, [%o0 + %g3] ASI_M_FLUSH_PAGE
  230. andcc %o0, 0xffc, %g0
  231. sta %g0, [%o0 + %g4] ASI_M_FLUSH_PAGE
  232. bne 1b
  233. sta %g0, [%o0 + %g5] ASI_M_FLUSH_PAGE
  234. 2:
  235. mov SRMMU_FAULT_STATUS, %g1
  236. retl
  237. lda [%g1] ASI_M_MMUREGS, %g0
  238. /* HyperSparc is IO cache coherent. */
  239. hypersparc_flush_page_for_dma:
  240. retl
  241. nop
  242. /* It was noted that at boot time a TLB flush all in a delay slot
  243. * can deliver an illegal instruction to the processor if the timing
  244. * is just right...
  245. */
  246. hypersparc_flush_tlb_all:
  247. mov 0x400, %g1
  248. sta %g0, [%g1] ASI_M_FLUSH_PROBE
  249. retl
  250. nop
  251. hypersparc_flush_tlb_mm:
  252. mov SRMMU_CTX_REG, %g1
  253. ld [%o0 + AOFF_mm_context], %o1
  254. lda [%g1] ASI_M_MMUREGS, %g5
  255. #ifndef CONFIG_SMP
  256. cmp %o1, -1
  257. be hypersparc_flush_tlb_mm_out
  258. #endif
  259. mov 0x300, %g2
  260. sta %o1, [%g1] ASI_M_MMUREGS
  261. sta %g0, [%g2] ASI_M_FLUSH_PROBE
  262. hypersparc_flush_tlb_mm_out:
  263. retl
  264. sta %g5, [%g1] ASI_M_MMUREGS
  265. hypersparc_flush_tlb_range:
  266. ld [%o0 + VMA_VM_MM], %o0
  267. mov SRMMU_CTX_REG, %g1
  268. ld [%o0 + AOFF_mm_context], %o3
  269. lda [%g1] ASI_M_MMUREGS, %g5
  270. #ifndef CONFIG_SMP
  271. cmp %o3, -1
  272. be hypersparc_flush_tlb_range_out
  273. #endif
  274. sethi %hi(~((1 << SRMMU_PGDIR_SHIFT) - 1)), %o4
  275. sta %o3, [%g1] ASI_M_MMUREGS
  276. and %o1, %o4, %o1
  277. add %o1, 0x200, %o1
  278. sta %g0, [%o1] ASI_M_FLUSH_PROBE
  279. 1:
  280. sub %o1, %o4, %o1
  281. cmp %o1, %o2
  282. blu,a 1b
  283. sta %g0, [%o1] ASI_M_FLUSH_PROBE
  284. hypersparc_flush_tlb_range_out:
  285. retl
  286. sta %g5, [%g1] ASI_M_MMUREGS
  287. hypersparc_flush_tlb_page:
  288. ld [%o0 + VMA_VM_MM], %o0
  289. mov SRMMU_CTX_REG, %g1
  290. ld [%o0 + AOFF_mm_context], %o3
  291. andn %o1, (PAGE_SIZE - 1), %o1
  292. #ifndef CONFIG_SMP
  293. cmp %o3, -1
  294. be hypersparc_flush_tlb_page_out
  295. #endif
  296. lda [%g1] ASI_M_MMUREGS, %g5
  297. sta %o3, [%g1] ASI_M_MMUREGS
  298. sta %g0, [%o1] ASI_M_FLUSH_PROBE
  299. hypersparc_flush_tlb_page_out:
  300. retl
  301. sta %g5, [%g1] ASI_M_MMUREGS
  302. __INIT
  303. /* High speed page clear/copy. */
  304. hypersparc_bzero_1page:
  305. /* NOTE: This routine has to be shorter than 40insns --jj */
  306. clr %g1
  307. mov 32, %g2
  308. mov 64, %g3
  309. mov 96, %g4
  310. mov 128, %g5
  311. mov 160, %g7
  312. mov 192, %o2
  313. mov 224, %o3
  314. mov 16, %o1
  315. 1:
  316. stda %g0, [%o0 + %g0] ASI_M_BFILL
  317. stda %g0, [%o0 + %g2] ASI_M_BFILL
  318. stda %g0, [%o0 + %g3] ASI_M_BFILL
  319. stda %g0, [%o0 + %g4] ASI_M_BFILL
  320. stda %g0, [%o0 + %g5] ASI_M_BFILL
  321. stda %g0, [%o0 + %g7] ASI_M_BFILL
  322. stda %g0, [%o0 + %o2] ASI_M_BFILL
  323. stda %g0, [%o0 + %o3] ASI_M_BFILL
  324. subcc %o1, 1, %o1
  325. bne 1b
  326. add %o0, 256, %o0
  327. retl
  328. nop
  329. hypersparc_copy_1page:
  330. /* NOTE: This routine has to be shorter than 70insns --jj */
  331. sub %o1, %o0, %o2 ! difference
  332. mov 16, %g1
  333. 1:
  334. sta %o0, [%o0 + %o2] ASI_M_BCOPY
  335. add %o0, 32, %o0
  336. sta %o0, [%o0 + %o2] ASI_M_BCOPY
  337. add %o0, 32, %o0
  338. sta %o0, [%o0 + %o2] ASI_M_BCOPY
  339. add %o0, 32, %o0
  340. sta %o0, [%o0 + %o2] ASI_M_BCOPY
  341. add %o0, 32, %o0
  342. sta %o0, [%o0 + %o2] ASI_M_BCOPY
  343. add %o0, 32, %o0
  344. sta %o0, [%o0 + %o2] ASI_M_BCOPY
  345. add %o0, 32, %o0
  346. sta %o0, [%o0 + %o2] ASI_M_BCOPY
  347. add %o0, 32, %o0
  348. sta %o0, [%o0 + %o2] ASI_M_BCOPY
  349. subcc %g1, 1, %g1
  350. bne 1b
  351. add %o0, 32, %o0
  352. retl
  353. nop
  354. .globl hypersparc_setup_blockops
  355. hypersparc_setup_blockops:
  356. sethi %hi(bzero_1page), %o0
  357. or %o0, %lo(bzero_1page), %o0
  358. sethi %hi(hypersparc_bzero_1page), %o1
  359. or %o1, %lo(hypersparc_bzero_1page), %o1
  360. sethi %hi(hypersparc_copy_1page), %o2
  361. or %o2, %lo(hypersparc_copy_1page), %o2
  362. ld [%o1], %o4
  363. 1:
  364. add %o1, 4, %o1
  365. st %o4, [%o0]
  366. add %o0, 4, %o0
  367. cmp %o1, %o2
  368. bne 1b
  369. ld [%o1], %o4
  370. sethi %hi(__copy_1page), %o0
  371. or %o0, %lo(__copy_1page), %o0
  372. sethi %hi(hypersparc_setup_blockops), %o2
  373. or %o2, %lo(hypersparc_setup_blockops), %o2
  374. ld [%o1], %o4
  375. 1:
  376. add %o1, 4, %o1
  377. st %o4, [%o0]
  378. add %o0, 4, %o0
  379. cmp %o1, %o2
  380. bne 1b
  381. ld [%o1], %o4
  382. sta %g0, [%g0] ASI_M_FLUSH_IWHOLE
  383. retl
  384. nop