ultra.S
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:16k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* $Id: ultra.S,v 1.70.2.1 2002/03/03 10:31:56 davem Exp $
  2.  * ultra.S: Don't expand these all over the place...
  3.  *
  4.  * Copyright (C) 1997, 2000 David S. Miller (davem@redhat.com)
  5.  */
  6. #include <linux/config.h>
  7. #include <asm/asi.h>
  8. #include <asm/pgtable.h>
  9. #include <asm/page.h>
  10. #include <asm/spitfire.h>
  11. #include <asm/mmu_context.h>
  12. #include <asm/pil.h>
  13. #include <asm/head.h>
  14. /* Basically, most of the Spitfire vs. Cheetah madness
  15.  * has to do with the fact that Cheetah does not support
  16.  * IMMU flushes out of the secondary context.  Someone needs
  17.  * to throw a south lake birthday party for the folks
  18.  * in Microelectronics who refused to fix this shit.
  19.  */
  20. /* This file is meant to be read efficiently by the CPU, not humans.
  21.  * Staraj sie tego nikomu nie pierdolnac...
  22.  */
  23. .text
  24. .align 32
  25. .globl __flush_tlb_page, __flush_tlb_mm, __flush_tlb_range
  26. __flush_tlb_page: /* %o0=(ctx & TAG_CONTEXT_BITS), %o1=page&PAGE_MASK, %o2=SECONDARY_CONTEXT */
  27. ldxa [%o2] ASI_DMMU, %g2
  28. cmp %g2, %o0
  29. bne,pn %icc, __spitfire_flush_tlb_page_slow
  30.  or %o1, 0x10, %g3
  31. stxa %g0, [%g3] ASI_DMMU_DEMAP
  32. stxa %g0, [%g3] ASI_IMMU_DEMAP
  33. retl
  34.  flush %g6
  35. nop
  36. nop
  37. nop
  38. nop
  39. nop
  40. nop
  41. nop
  42. nop
  43. __flush_tlb_mm: /* %o0=(ctx & TAG_CONTEXT_BITS), %o1=SECONDARY_CONTEXT */
  44. ldxa [%o1] ASI_DMMU, %g2
  45. cmp %g2, %o0
  46. bne,pn %icc, __spitfire_flush_tlb_mm_slow
  47.  mov 0x50, %g3
  48. stxa %g0, [%g3] ASI_DMMU_DEMAP
  49. stxa %g0, [%g3] ASI_IMMU_DEMAP
  50. retl
  51.  flush %g6
  52. nop
  53. nop
  54. nop
  55. nop
  56. nop
  57. nop
  58. nop
  59. nop
  60. __flush_tlb_range: /* %o0=(ctx&TAG_CONTEXT_BITS), %o1=start&PAGE_MASK, %o2=SECONDARY_CONTEXT,
  61.     * %o3=end&PAGE_MASK, %o4=PAGE_SIZE, %o5=(end - start)
  62.     */
  63. #define TLB_MAGIC 207 /* Students, do you know how I calculated this?  -DaveM */
  64. cmp %o5, %o4
  65. bleu,pt %xcc, __flush_tlb_page
  66.  srlx %o5, PAGE_SHIFT, %g5
  67. cmp %g5, TLB_MAGIC
  68. bgeu,pn %icc, __spitfire_flush_tlb_range_constant_time
  69.  or %o1, 0x10, %g5
  70. ldxa [%o2] ASI_DMMU, %g2
  71. cmp %g2, %o0
  72. __spitfire_flush_tlb_range_page_by_page:
  73. bne,pn %icc, __spitfire_flush_tlb_range_pbp_slow
  74.  sub %o5, %o4, %o5
  75. 1: stxa %g0, [%g5 + %o5] ASI_DMMU_DEMAP
  76. stxa %g0, [%g5 + %o5] ASI_IMMU_DEMAP
  77. brnz,pt %o5, 1b
  78.  sub %o5, %o4, %o5
  79. retl
  80.  flush %g6
  81. __spitfire_flush_tlb_range_constant_time: /* %o0=ctx, %o1=start, %o3=end */
  82. rdpr %pstate, %g1
  83. wrpr %g1, PSTATE_IE, %pstate
  84. mov TLB_TAG_ACCESS, %g3
  85. mov ((SPITFIRE_HIGHEST_LOCKED_TLBENT-1) << 3), %g2
  86. /* Spitfire Errata #32 workaround. */
  87. mov 0x8, %o4
  88. stxa %g0, [%o4] ASI_DMMU
  89. flush %g6
  90. 1: ldxa [%g2] ASI_ITLB_TAG_READ, %o4
  91. and %o4, TAG_CONTEXT_BITS, %o5
  92. cmp %o5, %o0
  93. bne,pt %icc, 2f
  94.  andn %o4, TAG_CONTEXT_BITS, %o4
  95. cmp %o4, %o1
  96. blu,pt %xcc, 2f
  97.  cmp %o4, %o3
  98. blu,pn %xcc, 4f
  99. 2:  ldxa [%g2] ASI_DTLB_TAG_READ, %o4
  100. and %o4, TAG_CONTEXT_BITS, %o5
  101. cmp %o5, %o0
  102. andn %o4, TAG_CONTEXT_BITS, %o4
  103. bne,pt %icc, 3f
  104.  cmp %o4, %o1
  105. blu,pt %xcc, 3f
  106.  cmp %o4, %o3
  107. blu,pn %xcc, 5f
  108.  nop
  109. 3: brnz,pt %g2, 1b
  110.  sub %g2, (1 << 3), %g2
  111. retl
  112.  wrpr %g1, 0x0, %pstate
  113. 4: stxa %g0, [%g3] ASI_IMMU
  114. stxa %g0, [%g2] ASI_ITLB_DATA_ACCESS
  115. flush %g6
  116. /* Spitfire Errata #32 workaround. */
  117. mov 0x8, %o4
  118. stxa %g0, [%o4] ASI_DMMU
  119. flush %g6
  120. ba,pt %xcc, 2b
  121.  nop
  122. 5: stxa %g0, [%g3] ASI_DMMU
  123. stxa %g0, [%g2] ASI_DTLB_DATA_ACCESS
  124. flush %g6
  125. /* Spitfire Errata #32 workaround. */
  126. mov 0x8, %o4
  127. stxa %g0, [%o4] ASI_DMMU
  128. flush %g6
  129. ba,pt %xcc, 3b
  130.  nop
  131. __spitfire_flush_tlb_mm_slow:
  132. rdpr %pstate, %g1
  133. wrpr %g1, PSTATE_IE, %pstate
  134. stxa %o0, [%o1] ASI_DMMU
  135. stxa %g0, [%g3] ASI_DMMU_DEMAP
  136. stxa %g0, [%g3] ASI_IMMU_DEMAP
  137. flush %g6
  138. stxa %g2, [%o1] ASI_DMMU
  139. flush %g6
  140. retl
  141.  wrpr %g1, 0, %pstate
  142. __spitfire_flush_tlb_page_slow:
  143. rdpr %pstate, %g1
  144. wrpr %g1, PSTATE_IE, %pstate
  145. stxa %o0, [%o2] ASI_DMMU
  146. stxa %g0, [%g3] ASI_DMMU_DEMAP
  147. stxa %g0, [%g3] ASI_IMMU_DEMAP
  148. flush %g6
  149. stxa %g2, [%o2] ASI_DMMU
  150. flush %g6
  151. retl
  152.  wrpr %g1, 0, %pstate
  153. __spitfire_flush_tlb_range_pbp_slow:
  154. rdpr %pstate, %g1
  155. wrpr %g1, PSTATE_IE, %pstate
  156. stxa %o0, [%o2] ASI_DMMU
  157. 2: stxa %g0, [%g5 + %o5] ASI_DMMU_DEMAP
  158. stxa %g0, [%g5 + %o5] ASI_IMMU_DEMAP
  159. brnz,pt %o5, 2b
  160.  sub %o5, %o4, %o5
  161. flush %g6
  162. stxa %g2, [%o2] ASI_DMMU
  163. flush %g6
  164. retl
  165.  wrpr %g1, 0x0, %pstate
  166. /*
  167.  * The following code flushes one page_size worth.
  168.  */
  169. #if (PAGE_SHIFT == 13)
  170. #define ITAG_MASK 0xfe
  171. #elif (PAGE_SHIFT == 16)
  172. #define ITAG_MASK 0x7fe
  173. #else
  174. #error unsupported PAGE_SIZE
  175. #endif
  176. .align 32
  177. .globl __flush_icache_page
  178. __flush_icache_page: /* %o0 = phys_page */
  179. sethi %hi(1 << 13), %o2 ! IC_set bit
  180. mov 1, %g1
  181. srlx %o0, 5, %o0
  182. clr %o1 ! IC_addr
  183. sllx %g1, 36, %g1
  184. ldda [%o1] ASI_IC_TAG, %o4
  185. sub %g1, 1, %g2
  186. or %o0, %g1, %o0 ! VALID+phys-addr comparitor
  187. sllx %g2, 1, %g2
  188. andn %g2, ITAG_MASK, %g2 ! IC_tag mask
  189. nop
  190. nop
  191. nop
  192. nop
  193. nop
  194. nop
  195. 1: addx %g0, %g0, %g0
  196. ldda [%o1 + %o2] ASI_IC_TAG, %g4
  197. addx %g0, %g0, %g0
  198. and %o5, %g2, %g3
  199. cmp %g3, %o0
  200. add %o1, 0x20, %o1
  201. ldda [%o1] ASI_IC_TAG, %o4
  202. be,pn %xcc, iflush1
  203. 2:  nop
  204. and %g5, %g2, %g5
  205. cmp %g5, %o0
  206. be,pn %xcc, iflush2
  207. 3:  cmp %o1, %o2
  208. bne,pt %xcc, 1b
  209.  addx %g0, %g0, %g0
  210. nop
  211. sethi %uhi(PAGE_OFFSET), %g4
  212. retl
  213.  sllx %g4, 32, %g4
  214. iflush1:sub %o1, 0x20, %g3
  215. stxa %g0, [%g3] ASI_IC_TAG
  216. flush %g6
  217. ba,a,pt %xcc, 2b
  218. iflush2:sub %o1, 0x20, %g3
  219. stxa %g0, [%o1 + %o2] ASI_IC_TAG
  220. flush %g6
  221. ba,a,pt %xcc, 3b
  222. #if (PAGE_SHIFT == 13)
  223. #define DTAG_MASK 0x3
  224. #elif (PAGE_SHIFT == 16)
  225. #define DTAG_MASK 0x1f
  226. #elif (PAGE_SHIFT == 19)
  227. #define DTAG_MASK 0xff
  228. #elif (PAGE_SHIFT == 22)
  229. #define DTAG_MASK 0x3ff
  230. #endif
  231. .align 64
  232. .globl __flush_dcache_page
  233. __flush_dcache_page: /* %o0=kaddr, %o1=flush_icache */
  234. sub %o0, %g4, %o0
  235. clr %o4
  236. srlx %o0, 11, %o0
  237. sethi %hi(1 << 14), %o2
  238. 1: ldxa [%o4] ASI_DCACHE_TAG, %o3 ! LSU Group
  239. add %o4, (1 << 5), %o4 ! IEU0
  240. ldxa [%o4] ASI_DCACHE_TAG, %g1 ! LSU Group
  241. add %o4, (1 << 5), %o4 ! IEU0
  242. ldxa [%o4] ASI_DCACHE_TAG, %g2 ! LSU Group o3 available
  243. add %o4, (1 << 5), %o4 ! IEU0
  244. andn %o3, DTAG_MASK, %o3 ! IEU1
  245. ldxa [%o4] ASI_DCACHE_TAG, %g3 ! LSU Group
  246. add %o4, (1 << 5), %o4 ! IEU0
  247. andn %g1, DTAG_MASK, %g1 ! IEU1
  248. cmp %o0, %o3 ! IEU1 Group
  249. be,a,pn %xcc, dflush1 ! CTI
  250.  sub %o4, (4 << 5), %o4 ! IEU0 (Group)
  251. cmp %o0, %g1 ! IEU1 Group
  252. andn %g2, DTAG_MASK, %g2 ! IEU0
  253. be,a,pn %xcc, dflush2 ! CTI
  254.  sub %o4, (3 << 5), %o4 ! IEU0 (Group)
  255. cmp %o0, %g2 ! IEU1 Group
  256. andn %g3, DTAG_MASK, %g3 ! IEU0
  257. be,a,pn %xcc, dflush3 ! CTI
  258.  sub %o4, (2 << 5), %o4 ! IEU0 (Group)
  259. cmp %o0, %g3 ! IEU1 Group
  260. be,a,pn %xcc, dflush4 ! CTI
  261.  sub %o4, (1 << 5), %o4 ! IEU0
  262. 2: cmp %o4, %o2 ! IEU1 Group
  263. bne,pt %xcc, 1b ! CTI
  264.  nop ! IEU0
  265. /* The I-cache does not snoop local stores so we
  266.  * better flush that too when necessary.
  267.  */
  268. brnz,pt %o1, __flush_icache_page
  269.  sllx %o0, 11, %o0
  270. retl
  271.  nop
  272. dflush1:stxa %g0, [%o4] ASI_DCACHE_TAG
  273. add %o4, (1 << 5), %o4
  274. dflush2:stxa %g0, [%o4] ASI_DCACHE_TAG
  275. add %o4, (1 << 5), %o4
  276. dflush3:stxa %g0, [%o4] ASI_DCACHE_TAG
  277. add %o4, (1 << 5), %o4
  278. dflush4:stxa %g0, [%o4] ASI_DCACHE_TAG
  279. add %o4, (1 << 5), %o4
  280. membar #Sync
  281. ba,pt %xcc, 2b
  282.  nop
  283. .align 32
  284. __prefill_dtlb:
  285. rdpr %pstate, %g7
  286. wrpr %g7, PSTATE_IE, %pstate
  287. mov TLB_TAG_ACCESS, %g1
  288. stxa %o0, [%g1] ASI_DMMU
  289. stxa %o1, [%g0] ASI_DTLB_DATA_IN
  290. flush %g6
  291. retl
  292.  wrpr %g7, %pstate
  293. __prefill_itlb:
  294. rdpr %pstate, %g7
  295. wrpr %g7, PSTATE_IE, %pstate
  296. mov TLB_TAG_ACCESS, %g1
  297. stxa %o0, [%g1] ASI_IMMU
  298. stxa %o1, [%g0] ASI_ITLB_DATA_IN
  299. flush %g6
  300. retl
  301.  wrpr %g7, %pstate
  302. .globl __update_mmu_cache
  303. __update_mmu_cache: /* %o0=vma, %o1=address, %o2=pte */
  304. ldub [%g6 + AOFF_task_thread + AOFF_thread_fault_code], %o3
  305. srlx %o1, PAGE_SHIFT, %o1
  306. ldx [%o0 + 0x0], %o4 /* XXX vma->vm_mm */
  307. brz,pn %o3, 1f
  308.  sllx %o1, PAGE_SHIFT, %o0
  309. ldx [%o4 + AOFF_mm_context], %o5
  310. andcc %o3, FAULT_CODE_DTLB, %g0
  311. mov %o2, %o1
  312. and %o5, TAG_CONTEXT_BITS, %o5
  313. bne,pt %xcc, __prefill_dtlb
  314.  or %o0, %o5, %o0
  315. ba,a,pt %xcc, __prefill_itlb
  316. 1: retl
  317.  nop
  318. /* Cheetah specific versions, patched at boot time.  */
  319. __cheetah_flush_tlb_page: /* 14 insns */
  320. rdpr %pstate, %g5
  321. andn %g5, PSTATE_IE, %g2
  322. wrpr %g2, 0x0, %pstate
  323. wrpr %g0, 1, %tl
  324. mov PRIMARY_CONTEXT, %o2
  325. ldxa [%o2] ASI_DMMU, %g2
  326. stxa %o0, [%o2] ASI_DMMU
  327. stxa %g0, [%o1] ASI_DMMU_DEMAP
  328. stxa %g0, [%o1] ASI_IMMU_DEMAP
  329. stxa %g2, [%o2] ASI_DMMU
  330. flush %g6
  331. wrpr %g0, 0, %tl
  332. retl
  333.  wrpr %g5, 0x0, %pstate
  334. __cheetah_flush_tlb_mm: /* 15 insns */
  335. rdpr %pstate, %g5
  336. andn %g5, PSTATE_IE, %g2
  337. wrpr %g2, 0x0, %pstate
  338. wrpr %g0, 1, %tl
  339. mov PRIMARY_CONTEXT, %o2
  340. mov 0x40, %g3
  341. ldxa [%o2] ASI_DMMU, %g2
  342. stxa %o0, [%o2] ASI_DMMU
  343. stxa %g0, [%g3] ASI_DMMU_DEMAP
  344. stxa %g0, [%g3] ASI_IMMU_DEMAP
  345. stxa %g2, [%o2] ASI_DMMU
  346. flush %g6
  347. wrpr %g0, 0, %tl
  348. retl
  349.  wrpr %g5, 0x0, %pstate
  350. __cheetah_flush_tlb_range: /* 20 insns */
  351. cmp %o5, %o4
  352. blu,pt %xcc, 9f
  353.  rdpr %pstate, %g5
  354. andn %g5, PSTATE_IE, %g2
  355. wrpr %g2, 0x0, %pstate
  356. wrpr %g0, 1, %tl
  357. mov PRIMARY_CONTEXT, %o2
  358. sub %o5, %o4, %o5
  359. ldxa [%o2] ASI_DMMU, %g2
  360. stxa %o0, [%o2] ASI_DMMU
  361. 1: stxa %g0, [%o1 + %o5] ASI_DMMU_DEMAP
  362. stxa %g0, [%o1 + %o5] ASI_IMMU_DEMAP
  363. membar #Sync
  364. brnz,pt %o5, 1b
  365.  sub %o5, %o4, %o5
  366. stxa %g2, [%o2] ASI_DMMU
  367. flush %g6
  368. wrpr %g0, 0, %tl
  369. 9: retl
  370.  wrpr %g5, 0x0, %pstate
  371. flush_dcpage_cheetah: /* 9 insns */
  372. sub %o0, %g4, %o0
  373. sethi %hi(PAGE_SIZE), %o4
  374. 1: subcc %o4, (1 << 5), %o4
  375. stxa %g0, [%o0 + %o4] ASI_DCACHE_INVALIDATE
  376. membar #Sync
  377. bne,pt %icc, 1b
  378.  nop
  379. retl /* I-cache flush never needed on Cheetah, see callers. */
  380.  nop
  381. cheetah_patch_one:
  382. 1: lduw [%o1], %g1
  383. stw %g1, [%o0]
  384. flush %o0
  385. subcc %o2, 1, %o2
  386. add %o1, 4, %o1
  387. bne,pt %icc, 1b
  388.  add %o0, 4, %o0
  389. retl
  390.  nop
  391. .globl cheetah_patch_cachetlbops
  392. cheetah_patch_cachetlbops:
  393. save %sp, -128, %sp
  394. sethi %hi(__flush_tlb_page), %o0
  395. or %o0, %lo(__flush_tlb_page), %o0
  396. sethi %hi(__cheetah_flush_tlb_page), %o1
  397. or %o1, %lo(__cheetah_flush_tlb_page), %o1
  398. call cheetah_patch_one
  399.  mov 14, %o2
  400. sethi %hi(__flush_tlb_mm), %o0
  401. or %o0, %lo(__flush_tlb_mm), %o0
  402. sethi %hi(__cheetah_flush_tlb_mm), %o1
  403. or %o1, %lo(__cheetah_flush_tlb_mm), %o1
  404. call cheetah_patch_one
  405.  mov 15, %o2
  406. sethi %hi(__flush_tlb_range), %o0
  407. or %o0, %lo(__flush_tlb_range), %o0
  408. sethi %hi(__cheetah_flush_tlb_range), %o1
  409. or %o1, %lo(__cheetah_flush_tlb_range), %o1
  410. call cheetah_patch_one
  411.  mov 20, %o2
  412. sethi %hi(__flush_dcache_page), %o0
  413. or %o0, %lo(__flush_dcache_page), %o0
  414. sethi %hi(flush_dcpage_cheetah), %o1
  415. or %o1, %lo(flush_dcpage_cheetah), %o1
  416. call cheetah_patch_one
  417.  mov 9, %o2
  418. ret
  419.  restore
  420. #ifdef CONFIG_SMP
  421. /* These are all called by the slaves of a cross call, at
  422.  * trap level 1, with interrupts fully disabled.
  423.  *
  424.  * Register usage:
  425.  *   %g5 mm->context (all tlb flushes)
  426.  *   %g1 address arg 1 (tlb page and range flushes)
  427.  *   %g7 address arg 2 (tlb range flush only)
  428.  *
  429.  *   %g6 ivector table, don't touch
  430.  *   %g2 scratch 1
  431.  *   %g3 scratch 2
  432.  *   %g4 scratch 3
  433.  *
  434.  * TODO: Make xcall TLB range flushes use the tricks above... -DaveM
  435.  */
  436. .align 32
  437. .globl xcall_flush_tlb_page, xcall_flush_tlb_mm, xcall_flush_tlb_range
  438. xcall_flush_tlb_page:
  439. mov PRIMARY_CONTEXT, %g2
  440. ldxa [%g2] ASI_DMMU, %g3
  441. stxa %g5, [%g2] ASI_DMMU
  442. stxa %g0, [%g1] ASI_DMMU_DEMAP
  443. stxa %g0, [%g1] ASI_IMMU_DEMAP
  444. stxa %g3, [%g2] ASI_DMMU
  445. retry
  446. nop
  447. xcall_flush_tlb_mm:
  448. mov PRIMARY_CONTEXT, %g2
  449. mov 0x40, %g4
  450. ldxa [%g2] ASI_DMMU, %g3
  451. stxa %g5, [%g2] ASI_DMMU
  452. stxa %g0, [%g4] ASI_DMMU_DEMAP
  453. stxa %g0, [%g4] ASI_IMMU_DEMAP
  454. stxa %g3, [%g2] ASI_DMMU
  455. retry
  456. xcall_flush_tlb_range:
  457. sethi %hi(PAGE_SIZE - 1), %g2
  458. or %g2, %lo(PAGE_SIZE - 1), %g2
  459. andn %g1, %g2, %g1
  460. andn %g7, %g2, %g7
  461. sub %g7, %g1, %g3
  462. add %g2, 1, %g2
  463. srlx %g3, PAGE_SHIFT, %g4
  464. cmp %g4, 96
  465. bgu,pn %icc, xcall_flush_tlb_mm
  466.  mov PRIMARY_CONTEXT, %g4
  467. ldxa [%g4] ASI_DMMU, %g7
  468. sub %g3, %g2, %g3
  469. stxa %g5, [%g4] ASI_DMMU
  470. nop
  471. nop
  472. nop
  473. 1: stxa %g0, [%g1 + %g3] ASI_DMMU_DEMAP
  474. stxa %g0, [%g1 + %g3] ASI_IMMU_DEMAP
  475. membar #Sync
  476. brnz,pt %g3, 1b
  477.  sub %g3, %g2, %g3
  478. stxa %g7, [%g4] ASI_DMMU
  479. retry
  480. nop
  481. nop
  482. /* NOTE: This is SPECIAL!!  We do etrap/rtrap however
  483.  *       we choose to deal with the "BH's run with
  484.  *       %pil==15" problem (described in asm/pil.h)
  485.  *       by just invoking rtrap directly past where
  486.  *       BH's are checked for.
  487.  *
  488.  *       We do it like this because we do not want %pil==15
  489.  *       lockups to prevent regs being reported.
  490.  */
  491. .globl xcall_report_regs
  492. xcall_report_regs:
  493. rdpr %pstate, %g2
  494. wrpr %g2, PSTATE_IG | PSTATE_AG, %pstate
  495. rdpr %pil, %g2
  496. wrpr %g0, 15, %pil
  497. sethi %hi(109f), %g7
  498. b,pt %xcc, etrap_irq
  499. 109:  or %g7, %lo(109b), %g7
  500. call __show_regs
  501.  add %sp, STACK_BIAS + REGWIN_SZ, %o0
  502. clr %l6
  503. /* Has to be a non-v9 branch due to the large distance. */
  504. b rtrap_xcall
  505.  ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1
  506. .align 32
  507. .globl xcall_flush_dcache_page_cheetah
  508. xcall_flush_dcache_page_cheetah: /* %g1 == physical page address */
  509. sethi %hi(PAGE_SIZE), %g3
  510. 1: subcc %g3, (1 << 5), %g3
  511. stxa %g0, [%g1 + %g3] ASI_DCACHE_INVALIDATE
  512. membar #Sync
  513. bne,pt %icc, 1b
  514.  nop
  515. retry
  516. nop
  517. .globl xcall_flush_dcache_page_spitfire
  518. xcall_flush_dcache_page_spitfire: /* %g1 == physical page address
  519.      %g7 == kernel page virtual address
  520.      %g5 == (page->mapping != NULL)  */
  521. #if (L1DCACHE_SIZE > PAGE_SIZE)
  522. srlx %g1, (13 - 2), %g1 ! Form tag comparitor
  523. sethi %hi(L1DCACHE_SIZE), %g3 ! D$ size == 16K
  524. sub %g3, (1 << 5), %g3 ! D$ linesize == 32
  525. 1: ldxa [%g3] ASI_DCACHE_TAG, %g2
  526. andcc %g2, 0x3, %g0
  527. be,pn %xcc, 2f
  528.  andn %g2, 0x3, %g2
  529. cmp %g2, %g1
  530. bne,pt %xcc, 2f
  531.  nop
  532. stxa %g0, [%g3] ASI_DCACHE_TAG
  533. membar #Sync
  534. 2: cmp %g3, 0
  535. bne,pt %xcc, 1b
  536.  sub %g3, (1 << 5), %g3
  537. brz,pn %g5, 2f
  538. #endif /* L1DCACHE_SIZE > PAGE_SIZE */
  539.  sethi %hi(PAGE_SIZE), %g3
  540. 1: flush %g7
  541. subcc %g3, (1 << 5), %g3
  542. bne,pt %icc, 1b
  543.  add %g7, (1 << 5), %g7
  544. 2: retry
  545. nop
  546. nop
  547. .globl xcall_promstop
  548. xcall_promstop:
  549. rdpr %pstate, %g2
  550. wrpr %g2, PSTATE_IG | PSTATE_AG, %pstate
  551. rdpr %pil, %g2
  552. wrpr %g0, 15, %pil
  553. sethi %hi(109f), %g7
  554. b,pt %xcc, etrap_irq
  555. 109:  or %g7, %lo(109b), %g7
  556. flushw
  557. call prom_stopself
  558.  nop
  559. /* We should not return, just spin if we do... */
  560. 1: b,a,pt %xcc, 1b
  561. nop
  562. .data
  563. errata32_hwbug:
  564. .xword 0
  565. .text
  566. /* These two are not performance critical... */
  567. .globl xcall_flush_tlb_all_spitfire
  568. xcall_flush_tlb_all_spitfire:
  569. /* Spitfire Errata #32 workaround. */
  570. sethi %hi(errata32_hwbug), %g4
  571. stx %g0, [%g4 + %lo(errata32_hwbug)]
  572. clr %g2
  573. clr %g3
  574. 1: ldxa [%g3] ASI_DTLB_DATA_ACCESS, %g4
  575. and %g4, _PAGE_L, %g5
  576. brnz,pn %g5, 2f
  577.  mov TLB_TAG_ACCESS, %g7
  578. stxa %g0, [%g7] ASI_DMMU
  579. membar #Sync
  580. stxa %g0, [%g3] ASI_DTLB_DATA_ACCESS
  581. membar #Sync
  582. /* Spitfire Errata #32 workaround. */
  583. sethi %hi(errata32_hwbug), %g4
  584. stx %g0, [%g4 + %lo(errata32_hwbug)]
  585. 2: ldxa [%g3] ASI_ITLB_DATA_ACCESS, %g4
  586. and %g4, _PAGE_L, %g5
  587. brnz,pn %g5, 2f
  588.  mov TLB_TAG_ACCESS, %g7
  589. stxa %g0, [%g7] ASI_IMMU
  590. membar #Sync
  591. stxa %g0, [%g3] ASI_ITLB_DATA_ACCESS
  592. membar #Sync
  593. /* Spitfire Errata #32 workaround. */
  594. sethi %hi(errata32_hwbug), %g4
  595. stx %g0, [%g4 + %lo(errata32_hwbug)]
  596. 2: add %g2, 1, %g2
  597. cmp %g2, SPITFIRE_HIGHEST_LOCKED_TLBENT
  598. ble,pt %icc, 1b
  599.  sll %g2, 3, %g3
  600. flush %g6
  601. retry
  602. .globl xcall_flush_tlb_all_cheetah
  603. xcall_flush_tlb_all_cheetah:
  604. mov 0x80, %g2
  605. stxa %g0, [%g2] ASI_DMMU_DEMAP
  606. stxa %g0, [%g2] ASI_IMMU_DEMAP
  607. retry
  608. .globl xcall_flush_cache_all_spitfire
  609. xcall_flush_cache_all_spitfire:
  610. sethi %hi(16383), %g2
  611. or %g2, %lo(16383), %g2
  612. clr %g3
  613. 1: stxa %g0, [%g3] ASI_IC_TAG
  614. membar #Sync
  615. add %g3, 32, %g3
  616. cmp %g3, %g2
  617. bleu,pt %xcc, 1b
  618.  nop
  619. flush %g6
  620. retry
  621. /* These just get rescheduled to PIL vectors. */
  622. .globl xcall_call_function
  623. xcall_call_function:
  624. wr %g0, (1 << PIL_SMP_CALL_FUNC), %set_softint
  625. retry
  626. .globl xcall_receive_signal
  627. xcall_receive_signal:
  628. wr %g0, (1 << PIL_SMP_RECEIVE_SIGNAL), %set_softint
  629. retry
  630. .globl xcall_capture
  631. xcall_capture:
  632. wr %g0, (1 << PIL_SMP_CAPTURE), %set_softint
  633. retry
  634. #endif /* CONFIG_SMP */