misc.S 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496
  1. /*
  2. * arch/xtensa/mm/misc.S
  3. *
  4. * Miscellaneous assembly functions.
  5. *
  6. * This file is subject to the terms and conditions of the GNU General Public
  7. * License. See the file "COPYING" in the main directory of this archive
  8. * for more details.
  9. *
  10. * Copyright (C) 2001 - 2007 Tensilica Inc.
  11. *
  12. * Chris Zankel <chris@zankel.net>
  13. */
  14. #include <linux/linkage.h>
  15. #include <asm/page.h>
  16. #include <asm/pgtable.h>
  17. #include <asm/asmmacro.h>
  18. #include <asm/cacheasm.h>
  19. #include <asm/tlbflush.h>
  20. /*
  21. * clear_page and clear_user_page are the same for non-cache-aliased configs.
  22. *
  23. * clear_page (unsigned long page)
  24. * a2
  25. */
  26. ENTRY(clear_page)
  27. entry a1, 16
  28. movi a3, 0
  29. __loopi a2, a7, PAGE_SIZE, 32
  30. s32i a3, a2, 0
  31. s32i a3, a2, 4
  32. s32i a3, a2, 8
  33. s32i a3, a2, 12
  34. s32i a3, a2, 16
  35. s32i a3, a2, 20
  36. s32i a3, a2, 24
  37. s32i a3, a2, 28
  38. __endla a2, a7, 32
  39. retw
  40. ENDPROC(clear_page)
  41. /*
  42. * copy_page and copy_user_page are the same for non-cache-aliased configs.
  43. *
  44. * copy_page (void *to, void *from)
  45. * a2 a3
  46. */
  47. ENTRY(copy_page)
  48. entry a1, 16
  49. __loopi a2, a4, PAGE_SIZE, 32
  50. l32i a8, a3, 0
  51. l32i a9, a3, 4
  52. s32i a8, a2, 0
  53. s32i a9, a2, 4
  54. l32i a8, a3, 8
  55. l32i a9, a3, 12
  56. s32i a8, a2, 8
  57. s32i a9, a2, 12
  58. l32i a8, a3, 16
  59. l32i a9, a3, 20
  60. s32i a8, a2, 16
  61. s32i a9, a2, 20
  62. l32i a8, a3, 24
  63. l32i a9, a3, 28
  64. s32i a8, a2, 24
  65. s32i a9, a2, 28
  66. addi a2, a2, 32
  67. addi a3, a3, 32
  68. __endl a2, a4
  69. retw
  70. ENDPROC(copy_page)
  71. #ifdef CONFIG_MMU
  72. /*
  73. * If we have to deal with cache aliasing, we use temporary memory mappings
  74. * to ensure that the source and destination pages have the same color as
  75. * the virtual address. We use way 0 and 1 for temporary mappings in such cases.
  76. *
  77. * The temporary DTLB entries shouldn't be flushed by interrupts, but are
  78. * flushed by preemptive task switches. Special code in the
  79. * fast_second_level_miss handler re-established the temporary mapping.
  80. * It requires that the PPNs for the destination and source addresses are
  81. * in a6, and a7, respectively.
  82. */
  83. /* TLB miss exceptions are treated special in the following region */
  84. ENTRY(__tlbtemp_mapping_start)
  85. #if (DCACHE_WAY_SIZE > PAGE_SIZE)
  86. /*
  87. * clear_user_page (void *addr, unsigned long vaddr, struct page *page)
  88. * a2 a3 a4
  89. */
  90. ENTRY(clear_user_page)
  91. entry a1, 32
  92. /* Mark page dirty and determine alias. */
  93. movi a7, (1 << PG_ARCH_1)
  94. l32i a5, a4, PAGE_FLAGS
  95. xor a6, a2, a3
  96. extui a3, a3, PAGE_SHIFT, DCACHE_ALIAS_ORDER
  97. extui a6, a6, PAGE_SHIFT, DCACHE_ALIAS_ORDER
  98. or a5, a5, a7
  99. slli a3, a3, PAGE_SHIFT
  100. s32i a5, a4, PAGE_FLAGS
  101. /* Skip setting up a temporary DTLB if not aliased. */
  102. beqz a6, 1f
  103. /* Invalidate kernel page. */
  104. mov a10, a2
  105. call8 __invalidate_dcache_page
  106. /* Setup a temporary DTLB with the color of the VPN */
  107. movi a4, -PAGE_OFFSET + (PAGE_KERNEL | _PAGE_HW_WRITE)
  108. movi a5, TLBTEMP_BASE_1 # virt
  109. add a6, a2, a4 # ppn
  110. add a2, a5, a3 # add 'color'
  111. wdtlb a6, a2
  112. dsync
  113. 1: movi a3, 0
  114. __loopi a2, a7, PAGE_SIZE, 32
  115. s32i a3, a2, 0
  116. s32i a3, a2, 4
  117. s32i a3, a2, 8
  118. s32i a3, a2, 12
  119. s32i a3, a2, 16
  120. s32i a3, a2, 20
  121. s32i a3, a2, 24
  122. s32i a3, a2, 28
  123. __endla a2, a7, 32
  124. bnez a6, 1f
  125. retw
  126. /* We need to invalidate the temporary idtlb entry, if any. */
  127. 1: addi a2, a2, -PAGE_SIZE
  128. idtlb a2
  129. dsync
  130. retw
  131. ENDPROC(clear_user_page)
  132. /*
  133. * copy_page_user (void *to, void *from, unsigned long vaddr, struct page *page)
  134. * a2 a3 a4 a5
  135. */
  136. ENTRY(copy_user_page)
  137. entry a1, 32
  138. /* Mark page dirty and determine alias for destination. */
  139. movi a8, (1 << PG_ARCH_1)
  140. l32i a9, a5, PAGE_FLAGS
  141. xor a6, a2, a4
  142. xor a7, a3, a4
  143. extui a4, a4, PAGE_SHIFT, DCACHE_ALIAS_ORDER
  144. extui a6, a6, PAGE_SHIFT, DCACHE_ALIAS_ORDER
  145. extui a7, a7, PAGE_SHIFT, DCACHE_ALIAS_ORDER
  146. or a9, a9, a8
  147. slli a4, a4, PAGE_SHIFT
  148. s32i a9, a5, PAGE_FLAGS
  149. movi a5, -PAGE_OFFSET + (PAGE_KERNEL | _PAGE_HW_WRITE)
  150. beqz a6, 1f
  151. /* Invalidate dcache */
  152. mov a10, a2
  153. call8 __invalidate_dcache_page
  154. /* Setup a temporary DTLB with a matching color. */
  155. movi a8, TLBTEMP_BASE_1 # base
  156. add a6, a2, a5 # ppn
  157. add a2, a8, a4 # add 'color'
  158. wdtlb a6, a2
  159. dsync
  160. /* Skip setting up a temporary DTLB for destination if not aliased. */
  161. 1: beqz a7, 1f
  162. /* Setup a temporary DTLB with a matching color. */
  163. movi a8, TLBTEMP_BASE_2 # base
  164. add a7, a3, a5 # ppn
  165. add a3, a8, a4
  166. addi a8, a3, 1 # way1
  167. wdtlb a7, a8
  168. dsync
  169. 1: __loopi a2, a4, PAGE_SIZE, 32
  170. l32i a8, a3, 0
  171. l32i a9, a3, 4
  172. s32i a8, a2, 0
  173. s32i a9, a2, 4
  174. l32i a8, a3, 8
  175. l32i a9, a3, 12
  176. s32i a8, a2, 8
  177. s32i a9, a2, 12
  178. l32i a8, a3, 16
  179. l32i a9, a3, 20
  180. s32i a8, a2, 16
  181. s32i a9, a2, 20
  182. l32i a8, a3, 24
  183. l32i a9, a3, 28
  184. s32i a8, a2, 24
  185. s32i a9, a2, 28
  186. addi a2, a2, 32
  187. addi a3, a3, 32
  188. __endl a2, a4
  189. /* We need to invalidate any temporary mapping! */
  190. bnez a6, 1f
  191. bnez a7, 2f
  192. retw
  193. 1: addi a2, a2, -PAGE_SIZE
  194. idtlb a2
  195. dsync
  196. bnez a7, 2f
  197. retw
  198. 2: addi a3, a3, -PAGE_SIZE+1
  199. idtlb a3
  200. dsync
  201. retw
  202. ENDPROC(copy_user_page)
  203. #endif
  204. #if (DCACHE_WAY_SIZE > PAGE_SIZE)
  205. /*
  206. * void __flush_invalidate_dcache_page_alias (addr, phys)
  207. * a2 a3
  208. */
  209. ENTRY(__flush_invalidate_dcache_page_alias)
  210. entry sp, 16
  211. movi a7, 0 # required for exception handler
  212. addi a6, a3, (PAGE_KERNEL | _PAGE_HW_WRITE)
  213. mov a4, a2
  214. wdtlb a6, a2
  215. dsync
  216. ___flush_invalidate_dcache_page a2 a3
  217. idtlb a4
  218. dsync
  219. retw
  220. ENDPROC(__flush_invalidate_dcache_page_alias)
  221. #endif
  222. ENTRY(__tlbtemp_mapping_itlb)
  223. #if (ICACHE_WAY_SIZE > PAGE_SIZE)
  224. ENTRY(__invalidate_icache_page_alias)
  225. entry sp, 16
  226. addi a6, a3, (PAGE_KERNEL_EXEC | _PAGE_HW_WRITE)
  227. mov a4, a2
  228. witlb a6, a2
  229. isync
  230. ___invalidate_icache_page a2 a3
  231. iitlb a4
  232. isync
  233. retw
  234. ENDPROC(__invalidate_icache_page_alias)
  235. #endif
  236. /* End of special treatment in tlb miss exception */
  237. ENTRY(__tlbtemp_mapping_end)
  238. #endif /* CONFIG_MMU
  239. /*
  240. * void __invalidate_icache_page(ulong start)
  241. */
  242. ENTRY(__invalidate_icache_page)
  243. entry sp, 16
  244. ___invalidate_icache_page a2 a3
  245. isync
  246. retw
  247. ENDPROC(__invalidate_icache_page)
  248. /*
  249. * void __invalidate_dcache_page(ulong start)
  250. */
  251. ENTRY(__invalidate_dcache_page)
  252. entry sp, 16
  253. ___invalidate_dcache_page a2 a3
  254. dsync
  255. retw
  256. ENDPROC(__invalidate_dcache_page)
  257. /*
  258. * void __flush_invalidate_dcache_page(ulong start)
  259. */
  260. ENTRY(__flush_invalidate_dcache_page)
  261. entry sp, 16
  262. ___flush_invalidate_dcache_page a2 a3
  263. dsync
  264. retw
  265. ENDPROC(__flush_invalidate_dcache_page)
  266. /*
  267. * void __flush_dcache_page(ulong start)
  268. */
  269. ENTRY(__flush_dcache_page)
  270. entry sp, 16
  271. ___flush_dcache_page a2 a3
  272. dsync
  273. retw
  274. ENDPROC(__flush_dcache_page)
  275. /*
  276. * void __invalidate_icache_range(ulong start, ulong size)
  277. */
  278. ENTRY(__invalidate_icache_range)
  279. entry sp, 16
  280. ___invalidate_icache_range a2 a3 a4
  281. isync
  282. retw
  283. ENDPROC(__invalidate_icache_range)
  284. /*
  285. * void __flush_invalidate_dcache_range(ulong start, ulong size)
  286. */
  287. ENTRY(__flush_invalidate_dcache_range)
  288. entry sp, 16
  289. ___flush_invalidate_dcache_range a2 a3 a4
  290. dsync
  291. retw
  292. ENDPROC(__flush_invalidate_dcache_range)
  293. /*
  294. * void _flush_dcache_range(ulong start, ulong size)
  295. */
  296. ENTRY(__flush_dcache_range)
  297. entry sp, 16
  298. ___flush_dcache_range a2 a3 a4
  299. dsync
  300. retw
  301. ENDPROC(__flush_dcache_range)
  302. /*
  303. * void _invalidate_dcache_range(ulong start, ulong size)
  304. */
  305. ENTRY(__invalidate_dcache_range)
  306. entry sp, 16
  307. ___invalidate_dcache_range a2 a3 a4
  308. retw
  309. ENDPROC(__invalidate_dcache_range)
  310. /*
  311. * void _invalidate_icache_all(void)
  312. */
  313. ENTRY(__invalidate_icache_all)
  314. entry sp, 16
  315. ___invalidate_icache_all a2 a3
  316. isync
  317. retw
  318. ENDPROC(__invalidate_icache_all)
  319. /*
  320. * void _flush_invalidate_dcache_all(void)
  321. */
  322. ENTRY(__flush_invalidate_dcache_all)
  323. entry sp, 16
  324. ___flush_invalidate_dcache_all a2 a3
  325. dsync
  326. retw
  327. ENDPROC(__flush_invalidate_dcache_all)
  328. /*
  329. * void _invalidate_dcache_all(void)
  330. */
  331. ENTRY(__invalidate_dcache_all)
  332. entry sp, 16
  333. ___invalidate_dcache_all a2 a3
  334. dsync
  335. retw
  336. ENDPROC(__invalidate_dcache_all)