Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1326 lines
44 KiB

4 years ago
  1. #if defined(R4000)
  2. // TITLE("Cache Flush")
  3. //++
  4. //
  5. // Copyright (c) 1991 Microsoft Corporation
  6. //
  7. // Module Name:
  8. //
  9. // j4cache.s
  10. //
  11. // Abstract:
  12. //
  13. // This module implements the code necessary for cache operations on
  14. // a MIPS R4000.
  15. //
  16. // Author:
  17. //
  18. // David N. Cutler (davec) 19-Dec-1991
  19. //
  20. // Environment:
  21. //
  22. // Kernel mode only.
  23. //
  24. // Revision History:
  25. //
  26. //--
  27. #include "halmips.h"
  28. //
  29. // Define cache operations constants.
  30. //
  31. #define COLOR_BITS (7 << PAGE_SHIFT) // color bit (R4000 - 8kb cache)
  32. #define COLOR_MASK (0x7fff) // color mask (R4000 - 8kb cache)
  33. #define FLUSH_BASE 0xfffe0000 // flush base address
  34. #define PROTECTION_BITS ((1 << ENTRYLO_V) | (1 << ENTRYLO_D)) //
  35. SBTTL("Change Color Page")
  36. //++
  37. //
  38. // VOID
  39. // HalChangeColorPage (
  40. // IN PVOID NewColor,
  41. // IN PVOID OldColor,
  42. // IN ULONG PageFrame
  43. // )
  44. //
  45. // Routine Description:
  46. //
  47. // This function changes the color of a page if the old and new colors
  48. // do not match.
  49. //
  50. // The algorithm used to change colors for a page is as follows:
  51. //
  52. // 1. Purge (hit/invalidate) the page from the instruction cache
  53. // using the old color.
  54. //
  55. // 2. Purge (hit/invalidate) the page from the data cache using
  56. // the old color.
  57. //
  58. // Arguments:
  59. //
  60. // NewColor (a0) - Supplies the page aligned virtual address of the
  61. // new color of the page to change.
  62. //
  63. // OldColor (a1) - Supplies the page aligned virtual address of the
  64. // old color of the page to change.
  65. //
  66. // PageFrame (a2) - Supplies the page frame number of the page that
  67. // is changed.
  68. //
  69. // Return Value:
  70. //
  71. // None.
  72. //
  73. //--
  74. .struct 0
  75. .space 3 * 4 // fill
  76. CpRa: .space 4 // saved return address
  77. CpFrameLength: // length of stack frame
  78. CpA0: .space 4 // (a0)
  79. CpA1: .space 4 // (a1)
  80. CpA2: .space 4 // (a2)
  81. CpA3: .space 4 // (a3)
  82. NESTED_ENTRY(HalChangeColorPage, CpFrameLength, zero)
  83. subu sp,sp,CpFrameLength // allocate stack frame
  84. sw ra,CpRa(sp) // save return address
  85. PROLOGUE_END
  86. and a0,a0,COLOR_BITS // isolate new color bits
  87. and a1,a1,COLOR_BITS // isolate old color bits
  88. beq a0,a1,10f // if eq, colors match
  89. sw a1,CpA1(sp) // save old color bits
  90. sw a2,CpA2(sp) // save page frame
  91. //
  92. // Purge the instruction cache using the old page color.
  93. //
  94. move a0,a1 // set color value
  95. move a1,a2 // set page frame number
  96. li a2,PAGE_SIZE // set length of purge
  97. jal HalPurgeIcachePage // purge instruction cache page
  98. //
  99. // Flush the data cache using the old page color.
  100. //
  101. lw a0,CpA1(sp) // get old color bits
  102. lw a1,CpA2(sp) // get page frame number
  103. li a2,PAGE_SIZE // set length of purge
  104. jal HalFlushDcachePage // purge data cache page
  105. 10: lw ra,CpRa(sp) // get return address
  106. addu sp,sp,CpFrameLength // deallocate stack frame
  107. j ra // return
  108. .end HalChangeColorPage
  109. SBTTL("Flush Data Cache Page")
  110. //++
  111. //
  112. // VOID
  113. // HalFlushDcachePage (
  114. // IN PVOID Color,
  115. // IN ULONG PageFrame,
  116. // IN ULONG Length
  117. // )
  118. //
  119. // Routine Description:
  120. //
  121. // This function flushes (hit/writeback/invalidate) up to a page of data
  122. // from the data cache.
  123. //
  124. // Arguments:
  125. //
  126. // Color (a0) - Supplies the starting virtual address and color of the
  127. // data that is flushed.
  128. //
  129. // PageFrame (a1) - Supplies the page frame number of the page that
  130. // is flushed.
  131. //
  132. // Length (a2) - Supplies the length of the region in the page that is
  133. // flushed.
  134. //
  135. // Return Value:
  136. //
  137. // None.
  138. //
  139. //--
  140. LEAF_ENTRY(HalFlushDcachePage)
  141. #if DBG
  142. lw t0,KeDcacheFlushCount // get address of dcache flush count
  143. lw t1,0(t0) // increment the count of flushes
  144. addu t1,t1,1 //
  145. sw t1,0(t0) // store result
  146. #endif
  147. .set noreorder
  148. .set noat
  149. lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
  150. and a0,a0,COLOR_MASK // isolate color and offset bits
  151. li t0,FLUSH_BASE // get base flush address
  152. or t0,t0,a0 // compute color virtual address
  153. sll t1,a1,ENTRYLO_PFN // shift page frame into position
  154. or t1,t1,PROTECTION_BITS // merge protection bits
  155. or t1,t1,v0 // merge cache policy
  156. and a0,a0,0x1000 // isolate TB entry index
  157. beql zero,a0,10f // if eq, first entry
  158. move t2,zero // set second page table entry
  159. move t2,t1 // set second page table entry
  160. move t1,zero // set first page table entry
  161. 10: mfc0 t3,wired // get TB entry index
  162. lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
  163. lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
  164. bnel zero,v0,15f // if ne, second level cache present
  165. move t4,v0 // set flush block size
  166. .set at
  167. .set reorder
  168. //
  169. // Flush a page from the data cache.
  170. //
  171. 15: DISABLE_INTERRUPTS(t5) // disable interrupts
  172. .set noreorder
  173. .set noat
  174. mfc0 t6,entryhi // get current PID and VPN2
  175. srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
  176. sll t7,t7,ENTRYHI_VPN2 //
  177. and t6,t6,0xff << ENTRYHI_PID // isolate current PID
  178. or t7,t7,t6 // merge PID with VPN2 of virtual address
  179. mtc0 t7,entryhi // set VPN2 and PID for probe
  180. mtc0 t1,entrylo0 // set first PTE value
  181. mtc0 t2,entrylo1 // set second PTE value
  182. mtc0 t3,index // set TB index value
  183. nop // fill
  184. tlbwi // write TB entry - 3 cycle hazzard
  185. subu t6,t4,1 // compute block size minus one
  186. and t7,t0,t6 // compute offset in block
  187. addu a2,a2,t6 // round up to next block
  188. addu a2,a2,t7 //
  189. nor t6,t6,zero // complement block size minus one
  190. and a2,a2,t6 // truncate length to even number
  191. beq zero,a2,30f // if eq, no blocks to flush
  192. and t8,t0,t6 // compute starting virtual address
  193. addu t9,t8,a2 // compute ending virtual address
  194. bne zero,v0,40f // if ne, second level cache present
  195. subu t9,t9,t4 // compute ending loop address
  196. //
  197. // Flush the primary data cache only.
  198. //
  199. 20: cache HIT_WRITEBACK_INVALIDATE_D,0(t8) // invalidate cache block
  200. bne t8,t9,20b // if ne, more blocks to invalidate
  201. addu t8,t8,t4 // compute next block address
  202. .set at
  203. .set reorder
  204. 30: ENABLE_INTERRUPTS(t5) // enable interrupts
  205. j ra // return
  206. //
  207. // Flush the primary and secondary data caches.
  208. //
  209. .set noreorder
  210. .set noat
  211. 40: cache HIT_WRITEBACK_INVALIDATE_SD,0(t8) // invalidate cache block
  212. bne t8,t9,40b // if ne, more blocks to invalidate
  213. addu t8,t8,t4 // compute next block address
  214. .set at
  215. .set reorder
  216. ENABLE_INTERRUPTS(t5) // enable interrupts
  217. j ra // return
  218. .end HalFlushDcachePage
  219. SBTTL("Purge Data Cache Page")
  220. //++
  221. //
  222. // VOID
  223. // HalPurgeDcachePage (
  224. // IN PVOID Color,
  225. // IN ULONG PageFrame,
  226. // IN ULONG Length
  227. // )
  228. //
  229. // Routine Description:
  230. //
  231. // This function purges (hit/invalidate) up to a page of data from the
  232. // data cache.
  233. //
  234. // Arguments:
  235. //
  236. // Color (a0) - Supplies the starting virtual address and color of the
  237. // data that is purged.
  238. //
  239. // PageFrame (a1) - Supplies the page frame number of the page that
  240. // is purged.
  241. //
  242. // Length (a2) - Supplies the length of the region in the page that is
  243. // purged.
  244. //
  245. // Return Value:
  246. //
  247. // None.
  248. //
  249. //--
  250. LEAF_ENTRY(HalPurgeDcachePage)
  251. #if DBG
  252. lw t0,KeDcacheFlushCount // get address of dcache flush count
  253. lw t1,0(t0) // increment the count of flushes
  254. addu t1,t1,1 //
  255. sw t1,0(t0) // store result
  256. #endif
  257. .set noreorder
  258. .set noat
  259. lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
  260. and a0,a0,COLOR_MASK // isolate color bits
  261. li t0,FLUSH_BASE // get base flush address
  262. or t0,t0,a0 // compute color virtual address
  263. sll t1,a1,ENTRYLO_PFN // shift page frame into position
  264. or t1,t1,PROTECTION_BITS // merge protection bits
  265. or t1,t1,v0 // merge cache policy
  266. and a0,a0,0x1000 // isolate TB entry index
  267. beql zero,a0,10f // if eq, first entry
  268. move t2,zero // set second page table entry
  269. move t2,t1 // set second page table entry
  270. move t1,zero // set first page table entry
  271. 10: mfc0 t3,wired // get TB entry index
  272. lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
  273. lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
  274. bnel zero,v0,15f // if ne, second level cache present
  275. move t4,v0 // set purge block size
  276. .set at
  277. .set reorder
  278. //
  279. // Purge data from the data cache.
  280. //
  281. 15: DISABLE_INTERRUPTS(t5) // disable interrupts
  282. .set noreorder
  283. .set noat
  284. mfc0 t6,entryhi // get current PID and VPN2
  285. srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
  286. sll t7,t7,ENTRYHI_VPN2 //
  287. and t6,t6,0xff << ENTRYHI_PID // isolate current PID
  288. or t7,t7,t6 // merge PID with VPN2 of virtual address
  289. mtc0 t7,entryhi // set VPN2 and PID for probe
  290. mtc0 t1,entrylo0 // set first PTE value
  291. mtc0 t2,entrylo1 // set second PTE value
  292. mtc0 t3,index // set TB index value
  293. nop // fill
  294. tlbwi // write TB entry - 3 cycle hazzard
  295. subu t6,t4,1 // compute block size minus one
  296. and t7,t0,t6 // compute offset in block
  297. addu a2,a2,t6 // round up to next block
  298. addu a2,a2,t7 //
  299. nor t6,t6,zero // complement block size minus one
  300. and a2,a2,t6 // truncate length to even number
  301. beq zero,a2,30f // if eq, no blocks to purge
  302. and t8,t0,t6 // compute starting virtual address
  303. addu t9,t8,a2 // compute ending virtual address
  304. bne zero,v0,40f // if ne, second level cache present
  305. subu t9,t9,t4 // compute ending loop address
  306. //
  307. // Purge the primary data cache only.
  308. //
  309. 20: cache HIT_INVALIDATE_D,0(t8) // invalidate cache block
  310. bne t8,t9,20b // if ne, more blocks to invalidate
  311. addu t8,t8,t4 // compute next block address
  312. .set at
  313. .set reorder
  314. 30: ENABLE_INTERRUPTS(t5) // enable interrupts
  315. j ra // return
  316. //
  317. // Purge the primary and secondary data caches.
  318. //
  319. .set noreorder
  320. .set noat
  321. 40: cache HIT_INVALIDATE_SD,0(t8) // invalidate cache block
  322. bne t8,t9,40b // if ne, more blocks to invalidate
  323. addu t8,t8,t4 // compute next block address
  324. .set at
  325. .set reorder
  326. ENABLE_INTERRUPTS(t5) // enable interrupts
  327. j ra // return
  328. .end HalPurgeDcachePage
  329. SBTTL("Purge Instruction Cache Page")
  330. //++
  331. //
  332. // VOID
  333. // HalPurgeIcachePage (
  334. // IN PVOID Color,
  335. // IN ULONG PageFrame,
  336. // IN ULONG Length
  337. // )
  338. //
  339. // Routine Description:
  340. //
  341. // This function purges (hit/invalidate) up to a page fo data from the
  342. // instruction cache.
  343. //
  344. // Arguments:
  345. //
  346. // Color (a0) - Supplies the starting virtual address and color of the
  347. // data that is purged.
  348. //
  349. // PageFrame (a1) - Supplies the page frame number of the page that
  350. // is purged.
  351. //
  352. // Length (a2) - Supplies the length of the region in the page that is
  353. // purged.
  354. //
  355. // Return Value:
  356. //
  357. // None.
  358. //
  359. //--
  360. LEAF_ENTRY(HalPurgeIcachePage)
  361. #if DBG
  362. lw t0,KeIcacheFlushCount // get address of icache flush count
  363. lw t1,0(t0) // increment the count of flushes
  364. addu t1,t1,1 //
  365. sw t1,0(t0) // store result
  366. #endif
  367. .set noreorder
  368. .set noat
  369. lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
  370. and a0,a0,COLOR_MASK // isolate color bits
  371. li t0,FLUSH_BASE // get base flush address
  372. or t0,t0,a0 // compute color virtual address
  373. sll t1,a1,ENTRYLO_PFN // shift page frame into position
  374. or t1,t1,PROTECTION_BITS // merge protection bits
  375. or t1,t1,v0 // merge cache policy
  376. and a0,a0,0x1000 // isolate TB entry index
  377. beql zero,a0,10f // if eq, first entry
  378. move t2,zero // set second page table entry
  379. move t2,t1 // set second page table entry
  380. move t1,zero // set first page table entry
  381. 10: mfc0 t3,wired // get TB entry index
  382. lw v0,KiPcr + PcSecondLevelIcacheFillSize(zero) // get 2nd fill size
  383. lw t4,KiPcr + PcFirstLevelIcacheFillSize(zero) // get 1st fill size
  384. bnel zero,v0,15f // if ne, second level cache present
  385. move t4,v0 // set purge block size
  386. .set at
  387. .set reorder
  388. //
  389. // Purge data from the instruction cache.
  390. //
  391. 15: DISABLE_INTERRUPTS(t5) // disable interrupts
  392. .set noreorder
  393. .set noat
  394. mfc0 t6,entryhi // get current PID and VPN2
  395. srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
  396. sll t7,t7,ENTRYHI_VPN2 //
  397. and t6,t6,0xff << ENTRYHI_PID // isolate current PID
  398. or t7,t7,t6 // merge PID with VPN2 of virtual address
  399. mtc0 t7,entryhi // set VPN2 and PID for probe
  400. mtc0 t1,entrylo0 // set first PTE value
  401. mtc0 t2,entrylo1 // set second PTE value
  402. mtc0 t3,index // set TB index value
  403. nop // fill
  404. tlbwi // write TB entry - 3 cycle hazzard
  405. subu t6,t4,1 // compute block size minus one
  406. and t7,t0,t6 // compute offset in block
  407. addu a2,a2,t6 // round up to next block
  408. addu a2,a2,t7 //
  409. nor t6,t6,zero // complement block size minus one
  410. and a2,a2,t6 // truncate length to even number
  411. beq zero,a2,30f // if eq, no blocks to purge
  412. and t8,t0,t6 // compute starting virtual address
  413. addu t9,t8,a2 // compute ending virtual address
  414. bne zero,v0,40f // if ne, second level cache present
  415. subu t9,t9,t4 // compute ending loop address
  416. //
  417. // Purge the primary instruction cache only.
  418. //
  419. 20: cache HIT_INVALIDATE_I,0(t8) // invalidate cache block
  420. bne t8,t9,20b // if ne, more blocks to invalidate
  421. addu t8,t8,t4 // compute next block address
  422. .set at
  423. .set reorder
  424. 30: ENABLE_INTERRUPTS(t5) // enable interrupts
  425. j ra // return
  426. //
  427. // Purge the primary and secondary instruction caches.
  428. //
  429. .set noreorder
  430. .set noat
  431. 40: cache HIT_INVALIDATE_SI,0(t8) // invalidate cache block
  432. bne t8,t9,40b // if ne, more blocks to invalidate
  433. addu t8,t8,t4 // compute next block address
  434. .set at
  435. .set reorder
  436. ENABLE_INTERRUPTS(t5) // enable interrupts
  437. j ra // return
  438. .end HalPurgeIcachePage
  439. SBTTL("Sweep Data Cache")
  440. //++
  441. //
  442. // VOID
  443. // HalSweepDcache (
  444. // VOID
  445. // )
  446. //
  447. // Routine Description:
  448. //
  449. // This function sweeps (index/writeback/invalidate) the entire data cache.
  450. //
  451. // Arguments:
  452. //
  453. // None.
  454. //
  455. // Return Value:
  456. //
  457. // None.
  458. //
  459. //--
  460. LEAF_ENTRY(HalSweepDcache)
  461. #if DBG
  462. lw t0,KeDcacheFlushCount // get address of dcache flush count
  463. lw t1,0(t0) // increment the count of flushes
  464. addu t1,t1,1 //
  465. sw t1,0(t0) // store result
  466. #endif
  467. DISABLE_INTERRUPTS(t5) // disable interrupts
  468. lw t0,KiPcr + PcFirstLevelDcacheSize(zero) // get data cache size
  469. lw t1,KiPcr + PcFirstLevelDcacheFillSize(zero) // get block size
  470. li a0,KSEG0_BASE // set starting index value
  471. addu a1,a0,t0 // compute ending cache address
  472. subu a1,a1,t1 // compute ending block address
  473. //
  474. // Sweep the primary data cache.
  475. //
  476. .set noreorder
  477. .set noat
  478. 10: cache INDEX_WRITEBACK_INVALIDATE_D,0(a0) // writeback/invalidate on index
  479. cache INDEX_WRITEBACK_INVALIDATE_D,0x2000(a0) // writeback/invalidate on index ORION
  480. bne a0,a1,10b // if ne, more to invalidate
  481. addu a0,a0,t1 // compute address of next block
  482. .set at
  483. .set reorder
  484. lw t0,KiPcr + PcSecondLevelDcacheSize(zero) // get data cache size
  485. lw t1,KiPcr + PcSecondLevelDcacheFillSize(zero) // get block size
  486. beq zero,t1,30f // if eq, no second level cache
  487. li a0,KSEG0_BASE // set starting index value
  488. addu a1,a0,t0 // compute ending cache address
  489. subu a1,a1,t1 // compute ending block address
  490. //
  491. // Sweep the secondary data cache.
  492. //
  493. .set noreorder
  494. .set noat
  495. 20: cache INDEX_WRITEBACK_INVALIDATE_SD,0(a0) // writeback/invalidate on index
  496. bne a0,a1,20b // if ne, more to invalidate
  497. addu a0,a0,t1 // compute address of next block
  498. .set at
  499. .set reorder
  500. 30:
  501. ENABLE_INTERRUPTS(t5) // enable interrupts
  502. j ra // return
  503. .end HalSweepDcache
  504. SBTTL("Sweep Data Cache Range")
  505. //++
  506. //
  507. // VOID
  508. // HalSweepDcacheRange (
  509. // IN PVOID BaseAddress,
  510. // IN ULONG Length
  511. // )
  512. //
  513. // Routine Description:
  514. //
  515. // This function sweeps (index/writeback/invalidate) the specified range
  516. // of virtual addresses from the primary data cache.
  517. //
  518. // Arguments:
  519. //
  520. // BaseAddress (a0) - Supplies the base address of the range that is swept
  521. // from the data cache.
  522. //
  523. // Length (a1) - Supplies the length of the range that is swept from the
  524. // data cache.
  525. //
  526. // Return Value:
  527. //
  528. // None.
  529. //
  530. //--
  531. LEAF_ENTRY(HalSweepDcacheRange)
  532. #if DBG
  533. lw t0,KeDcacheFlushCount // get address of dcache flush count
  534. lw t1,0(t0) // increment the count of flushes
  535. addu t1,t1,1 //
  536. sw t1,0(t0) // store result conditionally
  537. #endif
  538. DISABLE_INTERRUPTS(t5) // disable interrupts
  539. and a0,a0,COLOR_MASK // isolate color and offset bits
  540. or a0,a0,KSEG0_BASE // convert to physical address
  541. lw t0,KiPcr + PcFirstLevelDcacheFillSize(zero) // get block size
  542. addu a1,a0,a1 // compute ending cache address
  543. subu a1,a1,t0 // compute ending block address
  544. //
  545. // Sweep the primary data cache.
  546. //
  547. .set noreorder
  548. .set noat
  549. 10: cache INDEX_WRITEBACK_INVALIDATE_D,0(a0) // writeback/invalidate on index
  550. cache INDEX_WRITEBACK_INVALIDATE_D,0x2000(a0) // writeback/invalidate on index ORION
  551. bne a0,a1,10b // if ne, more to invalidate
  552. addu a0,a0,t0 // compute address of next block
  553. .set at
  554. .set reorder
  555. ENABLE_INTERRUPTS(t5) // enable interrupts
  556. j ra // return
  557. .end HalSweepDcacheRange
  558. SBTTL("Sweep Instruction Cache")
  559. //++
  560. //
  561. // VOID
  562. // HalSweepIcache (
  563. // VOID
  564. // )
  565. //
  566. // Routine Description:
  567. //
  568. // This function sweeps (index/invalidate) the entire instruction cache.
  569. //
  570. // Arguments:
  571. //
  572. // None.
  573. //
  574. // Return Value:
  575. //
  576. // None.
  577. //
  578. //--
  579. LEAF_ENTRY(HalSweepIcache)
  580. #if DBG
  581. lw t0,KeIcacheFlushCount // get address of icache flush count
  582. lw t1,0(t0) // increment the count of flushes
  583. addu t1,t1,1 //
  584. sw t1,0(t0) // store result
  585. #endif
  586. DISABLE_INTERRUPTS(t5) // disable interrupts
  587. lw t0,KiPcr + PcSecondLevelIcacheSize(zero) // get instruction cache size
  588. lw t1,KiPcr + PcSecondLevelIcacheFillSize(zero) // get fill size
  589. beq zero,t1,20f // if eq, no second level cache
  590. li a0,KSEG0_BASE // set starting index value
  591. addu a1,a0,t0 // compute ending cache address
  592. subu a1,a1,t1 // compute ending block address
  593. //
  594. // Sweep the secondary instruction cache.
  595. //
  596. .set noreorder
  597. .set noat
  598. 10: cache INDEX_INVALIDATE_SI,0(a0) // invalidate cache line
  599. bne a0,a1,10b // if ne, more to invalidate
  600. addu a0,a0,t1 // compute address of next block
  601. .set at
  602. .set reorder
  603. 20: lw t0,KiPcr + PcFirstLevelIcacheSize(zero) // get instruction cache size
  604. lw t1,KiPcr + PcFirstLevelIcacheFillSize(zero) // get fill size
  605. li a0,KSEG0_BASE // set starting index value
  606. addu a1,a0,t0 // compute ending cache address
  607. subu a1,a1,t1 // compute ending block address
  608. //
  609. // Sweep the primary instruction cache.
  610. //
  611. .set noreorder
  612. .set noat
  613. 30: cache INDEX_INVALIDATE_I,0(a0) // invalidate cache line
  614. cache INDEX_INVALIDATE_I,0x2000(a0) // invalidate cache line ORION
  615. bne a0,a1,30b // if ne, more to invalidate
  616. addu a0,a0,t1 // compute address of next block
  617. .set at
  618. .set reorder
  619. ENABLE_INTERRUPTS(t5) // enable interrupts
  620. j ra // return
  621. .end HalSweepIcache
  622. SBTTL("Sweep Instruction Cache Range")
  623. //++
  624. //
  625. // VOID
  626. // HalSweepIcacheRange (
  627. // IN PVOID BaseAddress,
  628. // IN ULONG Length
  629. // )
  630. //
  631. // Routine Description:
  632. //
  633. // This function sweeps (index/invalidate) the specified range of addresses
  634. // from the instruction cache.
  635. //
  636. // Arguments:
  637. //
  638. // BaseAddress (a0) - Supplies the base address of the range that is swept
  639. // from the instruction cache.
  640. //
  641. // Length (a1) - Supplies the length of the range that is swept from the
  642. // instruction cache.
  643. //
  644. // Return Value:
  645. //
  646. // None.
  647. //
  648. //--
  649. LEAF_ENTRY(HalSweepIcacheRange)
  650. #if DBG
  651. lw t0,KeIcacheFlushCount // get address of icache flush count
  652. lw t1,0(t0) // increment the count of flushes
  653. addu t1,t1,1 //
  654. sw t1,0(t0) // store result
  655. #endif
  656. DISABLE_INTERRUPTS(t5) // disable interrupts
  657. and a0,a0,COLOR_MASK // isolate color and offset bits
  658. or a0,a0,KSEG0_BASE // convert to physical address
  659. lw t0,KiPcr + PcFirstLevelIcacheFillSize(zero) // get fill size
  660. addu a1,a0,a1 // compute ending cache address
  661. subu a1,a1,t0 // compute ending block address
  662. //
  663. // Sweep the primary instruction cache.
  664. //
  665. .set noreorder
  666. .set noat
  667. 10: cache INDEX_INVALIDATE_I,0(a0) // invalidate cache line
  668. cache INDEX_INVALIDATE_I,0x2000(a0) // invalidate cache line ORION
  669. bne a0,a1,10b // if ne, more to invalidate
  670. addu a0,a0,t0 // compute address of next block
  671. .set at
  672. .set reorder
  673. ENABLE_INTERRUPTS(t5) // enable interrupts
  674. j ra // return
  675. .end HalSweepIcacheRange
  676. SBTTL("Zero Page")
  677. //++
  678. //
  679. // VOID
  680. // HalZeroPage (
  681. // IN PVOID NewColor,
  682. // IN PVOID OldColor,
  683. // IN ULONG PageFrame
  684. // )
  685. //
  686. // Routine Description:
  687. //
  688. // This function zeros a page of memory.
  689. //
  690. // The algorithm used to zero a page is as follows:
  691. //
  692. // 1. Purge (hit/invalidate) the page from the instruction cache
  693. // using the old color iff the old color is not the same as
  694. // the new color.
  695. //
  696. // 2. Purge (hit/invalidate) the page from the data cache using
  697. // the old color iff the old color is not the same as the new
  698. // color.
  699. //
  700. // 3. Create (create/dirty/exclusive) the page in the data cache
  701. // using the new color.
  702. //
  703. // 4. Write zeros to the page using the new color.
  704. //
  705. // Arguments:
  706. //
  707. // NewColor (a0) - Supplies the page aligned virtual address of the
  708. // new color of the page that is zeroed.
  709. //
  710. // OldColor (a1) - Supplies the page aligned virtual address of the
  711. // old color of the page that is zeroed.
  712. //
  713. // PageFrame (a2) - Supplies the page frame number of the page that
  714. // is zeroed.
  715. //
  716. // Return Value:
  717. //
  718. // None.
  719. //
  720. //--
  721. .struct 0
  722. .space 3 * 4 // fill
  723. ZpRa: .space 4 // saved return address
  724. ZpFrameLength: // length of stack frame
  725. ZpA0: .space 4 // (a0)
  726. ZpA1: .space 4 // (a1)
  727. ZpA2: .space 4 // (a2)
  728. ZpA3: .space 4 // (a3)
  729. NESTED_ENTRY(HalZeroPage, ZpFrameLength, zero)
  730. subu sp,sp,ZpFrameLength // allocate stack frame
  731. sw ra,ZpRa(sp) // save return address
  732. PROLOGUE_END
  733. and a0,a0,COLOR_BITS // isolate new color bits
  734. and a1,a1,COLOR_BITS // isolate old color bits
  735. sw a0,ZpA0(sp) // save new color bits
  736. sw a1,ZpA1(sp) // save old color bits
  737. sw a2,ZpA2(sp) // save page frame
  738. //
  739. // Purge the instruction cache using the old page color iff the old page
  740. // color is not equal to the new page color.
  741. //
  742. beq a0,a1,10f // if eq, colors match
  743. move a0,a1 // set old color value
  744. move a1,a2 // set page frame number
  745. li a2,PAGE_SIZE // set length of purge
  746. jal HalPurgeIcachePage // purge instruction cache page
  747. //
  748. // Purge the data cache using the old page color iff the old page color is
  749. // not equal to the new page color.
  750. //
  751. lw a0,ZpA1(sp) // get old color value
  752. lw a1,ZpA2(sp) // get page frame number
  753. li a2,PAGE_SIZE // set length of purge
  754. jal HalPurgeDcachePage // purge data cache page
  755. //
  756. // Create dirty exclusive cache blocks and zero the data.
  757. //
  758. 10: lw a3,ZpA0(sp) // get new color bits
  759. lw a1,ZpA2(sp) // get page frame number
  760. .set noreorder
  761. .set noat
  762. lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache polciy
  763. li t0,FLUSH_BASE // get base flush address
  764. or t0,t0,a3 // compute new color virtual address
  765. sll t1,a1,ENTRYLO_PFN // shift page frame into position
  766. or t1,t1,PROTECTION_BITS // merge protection bits
  767. or t1,t1,v0 // merge cache policy
  768. and a3,a3,0x1000 // isolate TB entry index
  769. beql zero,a3,20f // if eq, first entry
  770. move t2,zero // set second page table entry
  771. move t2,t1 // set second page table entry
  772. move t1,zero // set first page table entry
  773. 20: mfc0 t3,wired // get TB entry index
  774. lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
  775. lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
  776. .set at
  777. .set reorder
  778. DISABLE_INTERRUPTS(t5) // disable interrupts
  779. .set noreorder
  780. .set noat
  781. mfc0 t6,entryhi // get current PID and VPN2
  782. srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
  783. sll t7,t7,ENTRYHI_VPN2 //
  784. and t6,t6,0xff << ENTRYHI_PID // isolate current PID
  785. or t7,t7,t6 // merge PID with VPN2 of virtual address
  786. mtc0 t7,entryhi // set VPN2 and PID for probe
  787. mtc0 t1,entrylo0 // set first PTE value
  788. mtc0 t2,entrylo1 // set second PTE value
  789. mtc0 t3,index // set TB index value
  790. nop // fill
  791. tlbwi // write TB entry - 3 cycle hazzard
  792. addu t9,t0,PAGE_SIZE // compute ending address of block
  793. dmtc1 zero,f0 // set write pattern
  794. bne zero,v0,50f // if ne, second level cache present
  795. and t8,t4,0x10 // test if 16-byte cache block
  796. //
  797. // Zero page in primary data cache only.
  798. //
  799. 30: cache CREATE_DIRTY_EXCLUSIVE_D,0(t0) // create cache block
  800. addu t0,t0,t4 // compute next block address
  801. bne zero,t8,40f // if ne, 16-byte cache line
  802. sdc1 f0,-16(t0) //
  803. sdc1 f0,-24(t0) // zero 16 bytes
  804. sdc1 f0,-32(t0) //
  805. 40: bne t0,t9,30b // if ne, more blocks to zero
  806. sdc1 f0,-8(t0) // zero 16 bytes
  807. .set at
  808. .set reorder
  809. ENABLE_INTERRUPTS(t5) // enable interrupts
  810. lw ra,ZpRa(sp) // get return address
  811. addu sp,sp,ZpFrameLength // deallocate stack frame
  812. j ra // return
  813. //
  814. // Zero page in primary and secondary data caches.
  815. //
  816. .set noreorder
  817. .set noat
  818. 50: cache CREATE_DIRTY_EXCLUSIVE_SD,0(t0) // create secondary cache block
  819. addu v1,v0,t0 // compute ending primary block address
  820. 60: addu t0,t0,t4 // compute next block address
  821. bne zero,t8,70f // if ne, 16-byte primary cache line
  822. sdc1 f0,-16(t0) //
  823. sdc1 f0,-24(t0) // zero 16 bytes
  824. sdc1 f0,-32(t0) //
  825. 70: bne t0,v1,60b // if ne, more primary blocks to zero
  826. sdc1 f0,-8(t0) // zero 16 bytes
  827. bne t0,t9,50b // if ne, more secondary blocks to zero
  828. nop // fill
  829. .set at
  830. .set reorder
  831. ENABLE_INTERRUPTS(t5) // enable interrupts
  832. lw ra,ZpRa(sp) // get return address
  833. addu sp,sp,ZpFrameLength // deallocate stack frame
  834. j ra // return
  835. .end HalZeroPage
  836. SBTTL("Copy Page To Dma Cache")
  837. //++
  838. //
  839. // VOID
  840. // HalCopyPageToDmaCache (
  841. // IN PVOID Color,
  842. // IN ULONG PageFrame,
  843. // IN ULONG Length
  844. // IN ULONG Destination,
  845. // )
  846. //
  847. // Routine Description:
  848. //
  849. // This function flushes (hit/writeback/invalidate) up to a page of data
  850. // from the data cache.
  851. //
  852. // Arguments:
  853. //
  854. // Color (a0) - Supplies the starting virtual address and color of the
  855. // data that is flushed.
  856. //
  857. // PageFrame (a1) - Supplies the page frame number of the page that
  858. // is flushed.
  859. //
  860. // Length (a2) - Supplies the length of the copy.
  861. //
  862. // Destination(a3) - Supplies the destination of the copy.
  863. //
  864. //
  865. // Return Value:
  866. //
  867. // None.
  868. //
  869. //--
  870. LEAF_ENTRY(HalCopyPageToDmaCache)
  871. #if DBG
  872. lw t0,KeDcacheFlushCount // get address of dcache flush count
  873. lw t1,0(t0) // increment the count of flushes
  874. addu t1,t1,1 //
  875. sw t1,0(t0) // store result
  876. #endif
  877. .set noreorder
  878. .set noat
  879. lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
  880. and a0,a0,COLOR_MASK // isolate color and offset bits
  881. li t0,FLUSH_BASE // get base flush address
  882. or t0,t0,a0 // compute color virtual address
  883. sll t1,a1,ENTRYLO_PFN // shift page frame into position
  884. or t1,t1,PROTECTION_BITS // merge protection bits
  885. or t1,t1,v0 // merge cache policy
  886. and a0,a0,0x1000 // isolate TB entry index
  887. beql zero,a0,10f // if eq, first entry
  888. move t2,zero // set second page table entry
  889. move t2,t1 // set second page table entry
  890. move t1,zero // set first page table entry
  891. 10:
  892. mfc0 t3,wired // get contents of wired register
  893. nop // fill
  894. addu t5,t3,1 // allocate TB entry
  895. mtc0 t5,wired //
  896. lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
  897. lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
  898. bnel zero,v0,15f // if ne, second level cache present
  899. move t4,v0 // set flush block size
  900. .set at
  901. .set reorder
  902. //
  903. // Flush a page from the data cache.
  904. //
  905. 15: DISABLE_INTERRUPTS(t5) // disable interrupts
  906. .set noreorder
  907. .set noat
  908. mfc0 t6,entryhi // get current PID and VPN2
  909. srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
  910. sll t7,t7,ENTRYHI_VPN2 //
  911. and t6,t6,0xff << ENTRYHI_PID // isolate current PID
  912. or t7,t7,t6 // merge PID with VPN2 of virtual address
  913. mtc0 t7,entryhi // set VPN2 and PID for probe
  914. mtc0 t1,entrylo0 // set first PTE value
  915. mtc0 t2,entrylo1 // set second PTE value
  916. mtc0 t3,index // set TB index value
  917. nop // fill
  918. tlbwi // write TB entry - 3 cycle hazzard
  919. subu t6,t4,1 // compute block size minus one
  920. and t7,t0,t6 // compute offset in block
  921. addu a2,a2,t6 // round up to next block
  922. addu a2,a2,t7 //
  923. nor t6,t6,zero // complement block size minus one
  924. and a2,a2,t6 // truncate length to even number
  925. beq zero,a2,30f // if eq, no blocks to flush
  926. and t8,t0,t6 // compute starting virtual address
  927. addu t9,t8,a2 // compute ending virtual address
  928. subu t9,t9,t4 // compute ending loop address
  929. and a3,a3,t6 // compute starting virtual address for destination
  930. //
  931. // Copy page from memory to DMA cache.
  932. //
  933. 20:
  934. ldc1 f0,0x0(t8)
  935. ldc1 f2,0x8(t8)
  936. ldc1 f4,0x10(t8)
  937. ldc1 f6,0x18(t8)
  938. sdc1 f0,0x0(a3)
  939. sdc1 f2,0x8(a3)
  940. sdc1 f4,0x10(a3)
  941. sdc1 f6,0x18(a3)
  942. addu a3,a3,t4
  943. bne t8,t9,20b
  944. addu t8,t8,t4
  945. mtc0 t3,wired //
  946. .set at
  947. .set reorder
  948. 30: ENABLE_INTERRUPTS(t5) // enable interrupts
  949. j ra // return
  950. .end HalCopyPageToDmaCache
  951. SBTTL("Copy Page From Dma Cache")
  952. //++
  953. //
  954. // VOID
  955. // HalCopyPageFromDmaCache (
  956. // IN PVOID Color,
  957. // IN ULONG PageFrame,
  958. // IN ULONG Length
  959. // IN ULONG Destination,
  960. // )
  961. //
  962. // Routine Description:
  963. //
  964. // This function flushes (hit/writeback/invalidate) up to a page of data
  965. // from the data cache.
  966. //
  967. // Arguments:
  968. //
  969. // Color (a0) - Supplies the starting virtual address and color of the
  970. // data that is flushed.
  971. //
  972. // PageFrame (a1) - Supplies the page frame number of the page that
  973. // is flushed.
  974. //
  975. // Length (a2) - Supplies the length of the copy.
  976. //
  977. // Destination(a3) - Supplies the destination of the copy.
  978. //
  979. //
  980. // Return Value:
  981. //
  982. // None.
  983. //
  984. //--
  985. LEAF_ENTRY(HalCopyPageFromDmaCache)
  986. #if DBG
  987. lw t0,KeDcacheFlushCount // get address of dcache flush count
  988. lw t1,0(t0) // increment the count of flushes
  989. addu t1,t1,1 //
  990. sw t1,0(t0) // store result
  991. #endif
  992. .set noreorder
  993. .set noat
  994. lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
  995. and a0,a0,COLOR_MASK // isolate color and offset bits
  996. li t0,FLUSH_BASE // get base flush address
  997. or t0,t0,a0 // compute color virtual address
  998. sll t1,a1,ENTRYLO_PFN // shift page frame into position
  999. or t1,t1,PROTECTION_BITS // merge protection bits
  1000. or t1,t1,v0 // merge cache policy
  1001. and a0,a0,0x1000 // isolate TB entry index
  1002. beql zero,a0,10f // if eq, first entry
  1003. move t2,zero // set second page table entry
  1004. move t2,t1 // set second page table entry
  1005. move t1,zero // set first page table entry
  1006. 10:
  1007. mfc0 t3,wired // get contents of wired register
  1008. nop // fill
  1009. addu t5,t3,1 // allocate TB entry
  1010. mtc0 t5,wired //
  1011. lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
  1012. lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
  1013. bnel zero,v0,15f // if ne, second level cache present
  1014. move t4,v0 // set flush block size
  1015. .set at
  1016. .set reorder
  1017. //
  1018. // Flush a page from the data cache.
  1019. //
  1020. 15: DISABLE_INTERRUPTS(t5) // disable interrupts
  1021. .set noreorder
  1022. .set noat
  1023. mfc0 t6,entryhi // get current PID and VPN2
  1024. srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
  1025. sll t7,t7,ENTRYHI_VPN2 //
  1026. and t6,t6,0xff << ENTRYHI_PID // isolate current PID
  1027. or t7,t7,t6 // merge PID with VPN2 of virtual address
  1028. mtc0 t7,entryhi // set VPN2 and PID for probe
  1029. mtc0 t1,entrylo0 // set first PTE value
  1030. mtc0 t2,entrylo1 // set second PTE value
  1031. mtc0 t3,index // set TB index value
  1032. nop // fill
  1033. tlbwi // write TB entry - 3 cycle hazzard
  1034. subu t6,t4,1 // compute block size minus one
  1035. and t7,t0,t6 // compute offset in block
  1036. addu a2,a2,t6 // round up to next block
  1037. addu a2,a2,t7 //
  1038. nor t6,t6,zero // complement block size minus one
  1039. and a2,a2,t6 // truncate length to even number
  1040. beq zero,a2,30f // if eq, no blocks to flush
  1041. and t8,t0,t6 // compute starting virtual address
  1042. addu t9,t8,a2 // compute ending virtual address
  1043. subu t9,t9,t4 // compute ending loop address
  1044. and a3,a3,t6 // compute starting virtual address for destination
  1045. //
  1046. // Copy page from DMA cache to memory.
  1047. //
  1048. 20:
  1049. ldc1 f0,0x0(a3)
  1050. ldc1 f2,0x8(a3)
  1051. ldc1 f4,0x10(a3)
  1052. ldc1 f6,0x18(a3)
  1053. sdc1 f0,0x0(t8)
  1054. sdc1 f2,0x8(t8)
  1055. sdc1 f4,0x10(t8)
  1056. sdc1 f6,0x18(t8)
  1057. addu a3,a3,t4
  1058. bne t8,t9,20b
  1059. addu t8,t8,t4
  1060. mtc0 t3,wired //
  1061. .set at
  1062. .set reorder
  1063. 30: ENABLE_INTERRUPTS(t5) // enable interrupts
  1064. j ra // return
  1065. .end HalCopyPageFromDmaCache
  1066. SBTTL("Reset ISA Bus")
  1067. //++
  1068. //
  1069. // VOID
  1070. // HalpResetIsaBus (
  1071. // IN ULONG DelayCount
  1072. // )
  1073. //
  1074. // Routine Description:
  1075. //
  1076. // This function resets all add in cards in the ISA/VESA bus.
  1077. //
  1078. // Arguments:
  1079. //
  1080. // DelayCount(a0) - Supplies the number of 2 processor cycle iterations to delay
  1081. // from the time at ISA Reset is asserted till ISA Reset is deasserted.
  1082. // DelayCount is choosen so that a 200 MHz ORION will stall for at least
  1083. // 1 ms.
  1084. //
  1085. // Return Value:
  1086. //
  1087. // None.
  1088. //
  1089. //--
  1090. LEAF_ENTRY(HalpResetIsaBus)
  1091. DISABLE_INTERRUPTS(t5) // disable interrupts to prevent external processor
  1092. // transactions during reset.
  1093. lw t1,HalpEisaControlBase // Get virtual address of ISA/VESA I/O Space
  1094. li t0,0x20
  1095. sb t0,0x22(t1) // Select OPTI register 0x20
  1096. li t0,0x02
  1097. sb t0,0x24(t1) // Write 0x02 to OPTI register 0x20 : Enable ISA reset
  1098. j 10f // Jump to a cache line aligned segment of code
  1099. .set noreorder
  1100. .set noat
  1101. //
  1102. // These next 8 instructions(32 byte line) will be loaded on a potential cache refill here.
  1103. // This guarantees that the ISA/VESA reset and delay loop will be be in the primary Icache.
  1104. // This is necessary to prevent any external processor transactions during the reset sequence.
  1105. //
  1106. .align 5 // align code on a cache line boundry
  1107. 10:
  1108. li t0,0xfe
  1109. sb t0,0x64(t1) // Reset ISA Bus
  1110. sync // Flush write buffer -> Forces ISA reset NOW.
  1111. or t0,zero,zero // Delay so LogiCore chip set can complete reset
  1112. 20:
  1113. bne t0,a0,20b
  1114. addiu t0,t0,0x01
  1115. //
  1116. // Instruction alignment to cache lines does not matter after this point.
  1117. //
  1118. .set reorder
  1119. .set at
  1120. li t0,0x00 // Send a value to a post card to gurantee the
  1121. sb t0,0x80(t1) // generation of a HADS on the ISA/VESA bus.
  1122. sync // This will deassert ISA reset.
  1123. ENABLE_INTERRUPTS(t5) // enable interrupts
  1124. j ra
  1125. .end HalpResetIsaBus
  1126. #endif