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.

1038 lines
34 KiB

4 years ago
  1. // TITLE("Cache Flush")
  2. //++
  3. //
  4. // Copyright (c) 1991 Microsoft Corporation
  5. //
  6. // Module Name:
  7. //
  8. // j4cache.s
  9. //
  10. // Abstract:
  11. //
  12. // This module implements the code necessary for cache operations on
  13. // a MIPS R4000.
  14. //
  15. // Author:
  16. //
  17. // David N. Cutler (davec) 19-Dec-1991
  18. //
  19. // Environment:
  20. //
  21. // Kernel mode only.
  22. //
  23. // Revision History:
  24. //
  25. //--
  26. #include "halmips.h"
  27. //
  28. // Define cache operations constants.
  29. //
  30. #define COLOR_BITS (7 << PAGE_SHIFT) // color bit (R4000 - 8kb cache)
  31. #define COLOR_MASK (0x7fff) // color mask (R4000 - 8kb cache)
  32. #define FLUSH_BASE 0xfffe0000 // flush base address
  33. #define PROTECTION_BITS ((1 << ENTRYLO_V) | (1 << ENTRYLO_D)) //
  34. SBTTL("Change Color Page")
  35. //++
  36. //
  37. // VOID
  38. // HalChangeColorPage (
  39. // IN PVOID NewColor,
  40. // IN PVOID OldColor,
  41. // IN ULONG PageFrame
  42. // )
  43. //
  44. // Routine Description:
  45. //
  46. // This function changes the color of a page if the old and new colors
  47. // do not match.
  48. //
  49. // The algorithm used to change colors for a page is as follows:
  50. //
  51. // 1. Purge (hit/invalidate) the page from the instruction cache
  52. // using the old color.
  53. //
  54. // 2. Purge (hit/invalidate) the page from the data cache using
  55. // the old color.
  56. //
  57. // Arguments:
  58. //
  59. // NewColor (a0) - Supplies the page aligned virtual address of the
  60. // new color of the page to change.
  61. //
  62. // OldColor (a1) - Supplies the page aligned virtual address of the
  63. // old color of the page to change.
  64. //
  65. // PageFrame (a2) - Supplies the page frame number of the page that
  66. // is changed.
  67. //
  68. // Return Value:
  69. //
  70. // None.
  71. //
  72. //--
  73. .struct 0
  74. .space 3 * 4 // fill
  75. CpRa: .space 4 // saved return address
  76. CpFrameLength: // length of stack frame
  77. CpA0: .space 4 // (a0)
  78. CpA1: .space 4 // (a1)
  79. CpA2: .space 4 // (a2)
  80. CpA3: .space 4 // (a3)
  81. NESTED_ENTRY(HalChangeColorPage, CpFrameLength, zero)
  82. subu sp,sp,CpFrameLength // allocate stack frame
  83. sw ra,CpRa(sp) // save return address
  84. PROLOGUE_END
  85. and a0,a0,COLOR_BITS // isolate new color bits
  86. and a1,a1,COLOR_BITS // isolate old color bits
  87. beq a0,a1,10f // if eq, colors match
  88. sw a1,CpA1(sp) // save old color bits
  89. sw a2,CpA2(sp) // save page frame
  90. //
  91. // Purge the instruction cache using the old page color.
  92. //
  93. move a0,a1 // set color value
  94. move a1,a2 // set page frame number
  95. li a2,PAGE_SIZE // set length of purge
  96. jal HalPurgeIcachePage // purge instruction cache page
  97. //
  98. // Flush the data cache using the old page color.
  99. //
  100. lw a0,CpA1(sp) // get old color bits
  101. lw a1,CpA2(sp) // get page frame number
  102. li a2,PAGE_SIZE // set length of purge
  103. jal HalFlushDcachePage // purge data cache page
  104. 10: lw ra,CpRa(sp) // get return address
  105. addu sp,sp,CpFrameLength // deallocate stack frame
  106. j ra // return
  107. .end HalChangeColorPage
  108. SBTTL("Flush Data Cache Page")
  109. //++
  110. //
  111. // VOID
  112. // HalFlushDcachePage (
  113. // IN PVOID Color,
  114. // IN ULONG PageFrame,
  115. // IN ULONG Length
  116. // )
  117. //
  118. // Routine Description:
  119. //
  120. // This function flushes (hit/writeback/invalidate) up to a page of data
  121. // from the data cache.
  122. //
  123. // Arguments:
  124. //
  125. // Color (a0) - Supplies the starting virtual address and color of the
  126. // data that is flushed.
  127. //
  128. // PageFrame (a1) - Supplies the page frame number of the page that
  129. // is flushed.
  130. //
  131. // Length (a2) - Supplies the length of the region in the page that is
  132. // flushed.
  133. //
  134. // Return Value:
  135. //
  136. // None.
  137. //
  138. //--
  139. LEAF_ENTRY(HalFlushDcachePage)
  140. #if DBG
  141. lw t0,KeDcacheFlushCount // get address of dcache flush count
  142. lw t1,0(t0) // increment the count of flushes
  143. addu t1,t1,1 //
  144. sw t1,0(t0) // store result
  145. #endif
  146. .set noreorder
  147. .set noat
  148. lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
  149. and a0,a0,COLOR_MASK // isolate color and offset bits
  150. li t0,FLUSH_BASE // get base flush address
  151. or t0,t0,a0 // compute color virtual address
  152. sll t1,a1,ENTRYLO_PFN // shift page frame into position
  153. or t1,t1,PROTECTION_BITS // merge protection bits
  154. or t1,t1,v0 // merge cache policy
  155. and a0,a0,0x1000 // isolate TB entry index
  156. beql zero,a0,10f // if eq, first entry
  157. move t2,zero // set second page table entry
  158. move t2,t1 // set second page table entry
  159. move t1,zero // set first page table entry
  160. 10: mfc0 t3,wired // get TB entry index
  161. lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
  162. lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
  163. bnel zero,v0,15f // if ne, second level cache present
  164. move t4,v0 // set flush block size
  165. .set at
  166. .set reorder
  167. //
  168. // Flush a page from the data cache.
  169. //
  170. 15: DISABLE_INTERRUPTS(t5) // disable interrupts
  171. .set noreorder
  172. .set noat
  173. mfc0 t6,entryhi // get current PID and VPN2
  174. srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
  175. sll t7,t7,ENTRYHI_VPN2 //
  176. and t6,t6,0xff << ENTRYHI_PID // isolate current PID
  177. or t7,t7,t6 // merge PID with VPN2 of virtual address
  178. mtc0 t7,entryhi // set VPN2 and PID for probe
  179. mtc0 t1,entrylo0 // set first PTE value
  180. mtc0 t2,entrylo1 // set second PTE value
  181. mtc0 t3,index // set TB index value
  182. nop // fill
  183. tlbwi // write TB entry - 3 cycle hazzard
  184. subu t6,t4,1 // compute block size minus one
  185. and t7,t0,t6 // compute offset in block
  186. addu a2,a2,t6 // round up to next block
  187. addu a2,a2,t7 //
  188. nor t6,t6,zero // complement block size minus one
  189. and a2,a2,t6 // truncate length to even number
  190. beq zero,a2,30f // if eq, no blocks to flush
  191. and t8,t0,t6 // compute starting virtual address
  192. addu t9,t8,a2 // compute ending virtual address
  193. bne zero,v0,40f // if ne, second level cache present
  194. subu t9,t9,t4 // compute ending loop address
  195. //
  196. // Flush the primary data cache only.
  197. //
  198. 20: cache HIT_WRITEBACK_INVALIDATE_D,0(t8) // invalidate cache block
  199. bne t8,t9,20b // if ne, more blocks to invalidate
  200. addu t8,t8,t4 // compute next block address
  201. .set at
  202. .set reorder
  203. 30: ENABLE_INTERRUPTS(t5) // enable interrupts
  204. j ra // return
  205. //
  206. // Flush the primary and secondary data caches.
  207. //
  208. .set noreorder
  209. .set noat
  210. 40: cache HIT_WRITEBACK_INVALIDATE_SD,0(t8) // invalidate cache block
  211. bne t8,t9,40b // if ne, more blocks to invalidate
  212. addu t8,t8,t4 // compute next block address
  213. .set at
  214. .set reorder
  215. ENABLE_INTERRUPTS(t5) // enable interrupts
  216. j ra // return
  217. .end HalFlushDcachePage
  218. SBTTL("Purge Data Cache Page")
  219. //++
  220. //
  221. // VOID
  222. // HalPurgeDcachePage (
  223. // IN PVOID Color,
  224. // IN ULONG PageFrame,
  225. // IN ULONG Length
  226. // )
  227. //
  228. // Routine Description:
  229. //
  230. // This function purges (hit/invalidate) up to a page of data from the
  231. // data cache.
  232. //
  233. // Arguments:
  234. //
  235. // Color (a0) - Supplies the starting virtual address and color of the
  236. // data that is purged.
  237. //
  238. // PageFrame (a1) - Supplies the page frame number of the page that
  239. // is purged.
  240. //
  241. // Length (a2) - Supplies the length of the region in the page that is
  242. // purged.
  243. //
  244. // Return Value:
  245. //
  246. // None.
  247. //
  248. //--
  249. LEAF_ENTRY(HalPurgeDcachePage)
  250. #if DBG
  251. lw t0,KeDcacheFlushCount // get address of dcache flush count
  252. lw t1,0(t0) // increment the count of flushes
  253. addu t1,t1,1 //
  254. sw t1,0(t0) // store result
  255. #endif
  256. .set noreorder
  257. .set noat
  258. lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
  259. and a0,a0,COLOR_MASK // isolate color bits
  260. li t0,FLUSH_BASE // get base flush address
  261. or t0,t0,a0 // compute color virtual address
  262. sll t1,a1,ENTRYLO_PFN // shift page frame into position
  263. or t1,t1,PROTECTION_BITS // merge protection bits
  264. or t1,t1,v0 // merge cache policy
  265. and a0,a0,0x1000 // isolate TB entry index
  266. beql zero,a0,10f // if eq, first entry
  267. move t2,zero // set second page table entry
  268. move t2,t1 // set second page table entry
  269. move t1,zero // set first page table entry
  270. 10: mfc0 t3,wired // get TB entry index
  271. lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
  272. lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
  273. bnel zero,v0,15f // if ne, second level cache present
  274. move t4,v0 // set purge block size
  275. .set at
  276. .set reorder
  277. //
  278. // Purge data from the data cache.
  279. //
  280. 15: DISABLE_INTERRUPTS(t5) // disable interrupts
  281. .set noreorder
  282. .set noat
  283. mfc0 t6,entryhi // get current PID and VPN2
  284. srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
  285. sll t7,t7,ENTRYHI_VPN2 //
  286. and t6,t6,0xff << ENTRYHI_PID // isolate current PID
  287. or t7,t7,t6 // merge PID with VPN2 of virtual address
  288. mtc0 t7,entryhi // set VPN2 and PID for probe
  289. mtc0 t1,entrylo0 // set first PTE value
  290. mtc0 t2,entrylo1 // set second PTE value
  291. mtc0 t3,index // set TB index value
  292. nop // fill
  293. tlbwi // write TB entry - 3 cycle hazzard
  294. subu t6,t4,1 // compute block size minus one
  295. and t7,t0,t6 // compute offset in block
  296. addu a2,a2,t6 // round up to next block
  297. addu a2,a2,t7 //
  298. nor t6,t6,zero // complement block size minus one
  299. and a2,a2,t6 // truncate length to even number
  300. beq zero,a2,30f // if eq, no blocks to purge
  301. and t8,t0,t6 // compute starting virtual address
  302. addu t9,t8,a2 // compute ending virtual address
  303. bne zero,v0,40f // if ne, second level cache present
  304. subu t9,t9,t4 // compute ending loop address
  305. //
  306. // Purge the primary data cache only.
  307. //
  308. 20: cache HIT_INVALIDATE_D,0(t8) // invalidate cache block
  309. bne t8,t9,20b // if ne, more blocks to invalidate
  310. addu t8,t8,t4 // compute next block address
  311. .set at
  312. .set reorder
  313. 30: ENABLE_INTERRUPTS(t5) // enable interrupts
  314. j ra // return
  315. //
  316. // Purge the primary and secondary data caches.
  317. //
  318. .set noreorder
  319. .set noat
  320. 40: cache HIT_INVALIDATE_SD,0(t8) // invalidate cache block
  321. bne t8,t9,40b // if ne, more blocks to invalidate
  322. addu t8,t8,t4 // compute next block address
  323. .set at
  324. .set reorder
  325. ENABLE_INTERRUPTS(t5) // enable interrupts
  326. j ra // return
  327. .end HalPurgeDcachePage
  328. SBTTL("Purge Instruction Cache Page")
  329. //++
  330. //
  331. // VOID
  332. // HalPurgeIcachePage (
  333. // IN PVOID Color,
  334. // IN ULONG PageFrame,
  335. // IN ULONG Length
  336. // )
  337. //
  338. // Routine Description:
  339. //
  340. // This function purges (hit/invalidate) up to a page fo data from the
  341. // instruction cache.
  342. //
  343. // Arguments:
  344. //
  345. // Color (a0) - Supplies the starting virtual address and color of the
  346. // data that is purged.
  347. //
  348. // PageFrame (a1) - Supplies the page frame number of the page that
  349. // is purged.
  350. //
  351. // Length (a2) - Supplies the length of the region in the page that is
  352. // purged.
  353. //
  354. // Return Value:
  355. //
  356. // None.
  357. //
  358. //--
  359. LEAF_ENTRY(HalPurgeIcachePage)
  360. #if DBG
  361. lw t0,KeIcacheFlushCount // get address of icache flush count
  362. lw t1,0(t0) // increment the count of flushes
  363. addu t1,t1,1 //
  364. sw t1,0(t0) // store result
  365. #endif
  366. .set noreorder
  367. .set noat
  368. lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
  369. and a0,a0,COLOR_MASK // isolate color bits
  370. li t0,FLUSH_BASE // get base flush address
  371. or t0,t0,a0 // compute color virtual address
  372. sll t1,a1,ENTRYLO_PFN // shift page frame into position
  373. or t1,t1,PROTECTION_BITS // merge protection bits
  374. or t1,t1,v0 // merge cache policy
  375. and a0,a0,0x1000 // isolate TB entry index
  376. beql zero,a0,10f // if eq, first entry
  377. move t2,zero // set second page table entry
  378. move t2,t1 // set second page table entry
  379. move t1,zero // set first page table entry
  380. 10: mfc0 t3,wired // get TB entry index
  381. lw v0,KiPcr + PcSecondLevelIcacheFillSize(zero) // get 2nd fill size
  382. lw t4,KiPcr + PcFirstLevelIcacheFillSize(zero) // get 1st fill size
  383. bnel zero,v0,15f // if ne, second level cache present
  384. move t4,v0 // set purge block size
  385. .set at
  386. .set reorder
  387. //
  388. // Purge data from the instruction cache.
  389. //
  390. 15: DISABLE_INTERRUPTS(t5) // disable interrupts
  391. .set noreorder
  392. .set noat
  393. mfc0 t6,entryhi // get current PID and VPN2
  394. srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
  395. sll t7,t7,ENTRYHI_VPN2 //
  396. and t6,t6,0xff << ENTRYHI_PID // isolate current PID
  397. or t7,t7,t6 // merge PID with VPN2 of virtual address
  398. mtc0 t7,entryhi // set VPN2 and PID for probe
  399. mtc0 t1,entrylo0 // set first PTE value
  400. mtc0 t2,entrylo1 // set second PTE value
  401. mtc0 t3,index // set TB index value
  402. nop // fill
  403. tlbwi // write TB entry - 3 cycle hazzard
  404. subu t6,t4,1 // compute block size minus one
  405. and t7,t0,t6 // compute offset in block
  406. addu a2,a2,t6 // round up to next block
  407. addu a2,a2,t7 //
  408. nor t6,t6,zero // complement block size minus one
  409. and a2,a2,t6 // truncate length to even number
  410. beq zero,a2,30f // if eq, no blocks to purge
  411. and t8,t0,t6 // compute starting virtual address
  412. addu t9,t8,a2 // compute ending virtual address
  413. bne zero,v0,40f // if ne, second level cache present
  414. subu t9,t9,t4 // compute ending loop address
  415. //
  416. // Purge the primary instruction cache only.
  417. //
  418. 20: cache HIT_INVALIDATE_I,0(t8) // invalidate cache block
  419. bne t8,t9,20b // if ne, more blocks to invalidate
  420. addu t8,t8,t4 // compute next block address
  421. .set at
  422. .set reorder
  423. 30: ENABLE_INTERRUPTS(t5) // enable interrupts
  424. j ra // return
  425. //
  426. // Purge the primary and secondary instruction caches.
  427. //
  428. .set noreorder
  429. .set noat
  430. 40: cache HIT_INVALIDATE_SI,0(t8) // invalidate cache block
  431. bne t8,t9,40b // if ne, more blocks to invalidate
  432. addu t8,t8,t4 // compute next block address
  433. .set at
  434. .set reorder
  435. ENABLE_INTERRUPTS(t5) // enable interrupts
  436. j ra // return
  437. .end HalPurgeIcachePage
  438. SBTTL("Sweep Data Cache")
  439. //++
  440. //
  441. // VOID
  442. // HalSweepDcache (
  443. // VOID
  444. // )
  445. //
  446. // Routine Description:
  447. //
  448. // This function sweeps (index/writeback/invalidate) the entire data cache.
  449. //
  450. // Arguments:
  451. //
  452. // None.
  453. //
  454. // Return Value:
  455. //
  456. // None.
  457. //
  458. //--
  459. LEAF_ENTRY(HalSweepDcache)
  460. #if DBG
  461. lw t0,KeDcacheFlushCount // get address of dcache flush count
  462. lw t1,0(t0) // increment the count of flushes
  463. addu t1,t1,1 //
  464. sw t1,0(t0) // store result
  465. #endif
  466. lw t0,KiPcr + PcFirstLevelDcacheSize(zero) // get data cache size
  467. lw t1,KiPcr + PcFirstLevelDcacheFillSize(zero) // get block size
  468. li a0,KSEG0_BASE // set starting index value
  469. addu a1,a0,t0 // compute ending cache address
  470. subu a1,a1,t1 // compute ending block address
  471. //
  472. // Sweep the primary data cache.
  473. //
  474. .set noreorder
  475. .set noat
  476. 10: cache INDEX_WRITEBACK_INVALIDATE_D,0(a0) // writeback/invalidate on index
  477. #if defined(_MIPS_R4600)
  478. nop // fill
  479. cache INDEX_WRITEBACK_INVALIDATE_D,8192(a0) // writeback/invalidate on index
  480. #endif
  481. bne a0,a1,10b // if ne, more to invalidate
  482. addu a0,a0,t1 // compute address of next block
  483. .set at
  484. .set reorder
  485. lw t0,KiPcr + PcSecondLevelDcacheSize(zero) // get data cache size
  486. lw t1,KiPcr + PcSecondLevelDcacheFillSize(zero) // get block size
  487. beq zero,t1,30f // if eq, no second level cache
  488. li a0,KSEG0_BASE // set starting index value
  489. addu a1,a0,t0 // compute ending cache address
  490. subu a1,a1,t1 // compute ending block address
  491. //
  492. // Sweep the secondary data cache.
  493. //
  494. .set noreorder
  495. .set noat
  496. 20: cache INDEX_WRITEBACK_INVALIDATE_SD,0(a0) // writeback/invalidate on index
  497. bne a0,a1,20b // if ne, more to invalidate
  498. addu a0,a0,t1 // compute address of next block
  499. .set at
  500. .set reorder
  501. 30: j ra // return
  502. .end HalSweepDcache
  503. SBTTL("Sweep Data Cache Range")
  504. //++
  505. //
  506. // VOID
  507. // HalSweepDcacheRange (
  508. // IN PVOID BaseAddress,
  509. // IN ULONG Length
  510. // )
  511. //
  512. // Routine Description:
  513. //
  514. // This function sweeps (index/writeback/invalidate) the specified range
  515. // of virtual addresses from the primary data cache.
  516. //
  517. // Arguments:
  518. //
  519. // BaseAddress (a0) - Supplies the base address of the range that is swept
  520. // from the data cache.
  521. //
  522. // Length (a1) - Supplies the length of the range that is swept from the
  523. // data cache.
  524. //
  525. // Return Value:
  526. //
  527. // None.
  528. //
  529. //--
  530. LEAF_ENTRY(HalSweepDcacheRange)
  531. #if DBG
  532. lw t0,KeDcacheFlushCount // get address of dcache flush count
  533. lw t1,0(t0) // increment the count of flushes
  534. addu t1,t1,1 //
  535. sw t1,0(t0) // store result conditionally
  536. #endif
  537. and a0,a0,COLOR_MASK // isolate color and offset bits
  538. or a0,a0,KSEG0_BASE // convert to physical address
  539. lw t0,KiPcr + PcFirstLevelDcacheFillSize(zero) // get block size
  540. addu a1,a0,a1 // compute ending cache address
  541. subu a1,a1,t0 // compute ending block address
  542. //
  543. // Sweep the primary data cache.
  544. //
  545. .set noreorder
  546. .set noat
  547. 10: cache INDEX_WRITEBACK_INVALIDATE_D,0(a0) // writeback/invalidate on index
  548. #if defined(_MIPS_R4600)
  549. nop // fill
  550. cache INDEX_WRITEBACK_INVALIDATE_D,8192(a0) // writeback/invalidate on index
  551. #endif
  552. bne a0,a1,10b // if ne, more to invalidate
  553. addu a0,a0,t0 // compute address of next block
  554. .set at
  555. .set reorder
  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. lw t0,KiPcr + PcSecondLevelIcacheSize(zero) // get instruction cache size
  587. lw t1,KiPcr + PcSecondLevelIcacheFillSize(zero) // get fill size
  588. beq zero,t1,20f // if eq, no second level cache
  589. li a0,KSEG0_BASE // set starting index value
  590. addu a1,a0,t0 // compute ending cache address
  591. subu a1,a1,t1 // compute ending block address
  592. //
  593. // Sweep the secondary instruction cache.
  594. //
  595. .set noreorder
  596. .set noat
  597. 10: cache INDEX_INVALIDATE_SI,0(a0) // invalidate cache line
  598. bne a0,a1,10b // if ne, more to invalidate
  599. addu a0,a0,t1 // compute address of next block
  600. .set at
  601. .set reorder
  602. 20: lw t0,KiPcr + PcFirstLevelIcacheSize(zero) // get instruction cache size
  603. lw t1,KiPcr + PcFirstLevelIcacheFillSize(zero) // get fill size
  604. li a0,KSEG0_BASE // set starting index value
  605. addu a1,a0,t0 // compute ending cache address
  606. subu a1,a1,t1 // compute ending block address
  607. //
  608. // Sweep the primary instruction cache.
  609. //
  610. #if defined(_MIPS_R4600)
  611. DISABLE_INTERRUPTS(t0) // disable interrupts
  612. #endif
  613. .set noreorder
  614. .set noat
  615. 30: cache INDEX_INVALIDATE_I,0(a0) // invalidate cache line
  616. #if defined(_MIPS_R4600)
  617. nop // fill
  618. cache INDEX_INVALIDATE_I,8192(a0) // writeback/invalidate on index
  619. #endif
  620. bne a0,a1,30b // if ne, more to invalidate
  621. addu a0,a0,t1 // compute address of next block
  622. .set at
  623. .set reorder
  624. #if defined(_MIPS_R4600)
  625. ENABLE_INTERRUPTS(t0) // enable interrupts
  626. #endif
  627. j ra // return
  628. .end HalSweepIcache
  629. SBTTL("Sweep Instruction Cache Range")
  630. //++
  631. //
  632. // VOID
  633. // HalSweepIcacheRange (
  634. // IN PVOID BaseAddress,
  635. // IN ULONG Length
  636. // )
  637. //
  638. // Routine Description:
  639. //
  640. // This function sweeps (index/invalidate) the specified range of addresses
  641. // from the instruction cache.
  642. //
  643. // Arguments:
  644. //
  645. // BaseAddress (a0) - Supplies the base address of the range that is swept
  646. // from the instruction cache.
  647. //
  648. // Length (a1) - Supplies the length of the range that is swept from the
  649. // instruction cache.
  650. //
  651. // Return Value:
  652. //
  653. // None.
  654. //
  655. //--
  656. LEAF_ENTRY(HalSweepIcacheRange)
  657. #if DBG
  658. lw t0,KeIcacheFlushCount // get address of icache flush count
  659. lw t1,0(t0) // increment the count of flushes
  660. addu t1,t1,1 //
  661. sw t1,0(t0) // store result
  662. #endif
  663. and a0,a0,COLOR_MASK // isolate color and offset bits
  664. or a0,a0,KSEG0_BASE // convert to physical address
  665. lw t0,KiPcr + PcFirstLevelIcacheFillSize(zero) // get fill size
  666. addu a1,a0,a1 // compute ending cache address
  667. subu a1,a1,t0 // compute ending block address
  668. //
  669. // Sweep the primary instruction cache.
  670. //
  671. #if defined(_MIPS_R4600)
  672. DISABLE_INTERRUPTS(t1) // disable interrupts
  673. #endif
  674. .set noreorder
  675. .set noat
  676. 10: cache INDEX_INVALIDATE_I,0(a0) // invalidate cache line
  677. #if defined(_MIPS_R4600)
  678. nop // fill
  679. cache INDEX_INVALIDATE_I,8192(a0) // writeback/invalidate on index
  680. #endif
  681. bne a0,a1,10b // if ne, more to invalidate
  682. addu a0,a0,t0 // compute address of next block
  683. .set at
  684. .set reorder
  685. #if defined(_MIPS_R4600)
  686. ENABLE_INTERRUPTS(t1) // enable interrupts
  687. #endif
  688. j ra // return
  689. .end HalSweepIcacheRange
  690. SBTTL("Zero Page")
  691. //++
  692. //
  693. // VOID
  694. // HalZeroPage (
  695. // IN PVOID NewColor,
  696. // IN PVOID OldColor,
  697. // IN ULONG PageFrame
  698. // )
  699. //
  700. // Routine Description:
  701. //
  702. // This function zeros a page of memory.
  703. //
  704. // The algorithm used to zero a page is as follows:
  705. //
  706. // 1. Purge (hit/invalidate) the page from the instruction cache
  707. // using the old color iff the old color is not the same as
  708. // the new color.
  709. //
  710. // 2. Purge (hit/invalidate) the page from the data cache using
  711. // the old color iff the old color is not the same as the new
  712. // color.
  713. //
  714. // 3. Create (create/dirty/exclusive) the page in the data cache
  715. // using the new color.
  716. //
  717. // 4. Write zeros to the page using the new color.
  718. //
  719. // Arguments:
  720. //
  721. // NewColor (a0) - Supplies the page aligned virtual address of the
  722. // new color of the page that is zeroed.
  723. //
  724. // OldColor (a1) - Supplies the page aligned virtual address of the
  725. // old color of the page that is zeroed.
  726. //
  727. // PageFrame (a2) - Supplies the page frame number of the page that
  728. // is zeroed.
  729. //
  730. // Return Value:
  731. //
  732. // None.
  733. //
  734. //--
  735. .struct 0
  736. .space 3 * 4 // fill
  737. ZpRa: .space 4 // saved return address
  738. ZpFrameLength: // length of stack frame
  739. ZpA0: .space 4 // (a0)
  740. ZpA1: .space 4 // (a1)
  741. ZpA2: .space 4 // (a2)
  742. ZpA3: .space 4 // (a3)
  743. NESTED_ENTRY(HalZeroPage, ZpFrameLength, zero)
  744. subu sp,sp,ZpFrameLength // allocate stack frame
  745. sw ra,ZpRa(sp) // save return address
  746. PROLOGUE_END
  747. and a0,a0,COLOR_BITS // isolate new color bits
  748. and a1,a1,COLOR_BITS // isolate old color bits
  749. sw a0,ZpA0(sp) // save new color bits
  750. sw a2,ZpA2(sp) // save page frame
  751. //
  752. // If the old page color is not equal to the new page color, then change
  753. // the color of the page.
  754. //
  755. beq a0,a1,10f // if eq, colors match
  756. jal KeChangeColorPage // chagne page color
  757. //
  758. // Create dirty exclusive cache blocks and zero the data.
  759. //
  760. 10: lw a3,ZpA0(sp) // get new color bits
  761. lw a1,ZpA2(sp) // get page frame number
  762. .set noreorder
  763. .set noat
  764. lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache polciy
  765. li t0,FLUSH_BASE // get base flush address
  766. or t0,t0,a3 // compute new color virtual address
  767. sll t1,a1,ENTRYLO_PFN // shift page frame into position
  768. or t1,t1,PROTECTION_BITS // merge protection bits
  769. or t1,t1,v0 // merge cache policy
  770. and a3,a3,0x1000 // isolate TB entry index
  771. beql zero,a3,20f // if eq, first entry
  772. move t2,zero // set second page table entry
  773. move t2,t1 // set second page table entry
  774. move t1,zero // set first page table entry
  775. 20: mfc0 t3,wired // get TB entry index
  776. lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
  777. lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
  778. .set at
  779. .set reorder
  780. DISABLE_INTERRUPTS(t5) // disable interrupts
  781. .set noreorder
  782. .set noat
  783. mfc0 t6,entryhi // get current PID and VPN2
  784. srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
  785. sll t7,t7,ENTRYHI_VPN2 //
  786. and t6,t6,0xff << ENTRYHI_PID // isolate current PID
  787. or t7,t7,t6 // merge PID with VPN2 of virtual address
  788. mtc0 t7,entryhi // set VPN2 and PID for probe
  789. mtc0 t1,entrylo0 // set first PTE value
  790. mtc0 t2,entrylo1 // set second PTE value
  791. mtc0 t3,index // set TB index value
  792. nop // fill
  793. tlbwi // write TB entry - 3 cycle hazzard
  794. addu t9,t0,PAGE_SIZE // compute ending address of block
  795. dmtc1 zero,f0 // set write pattern
  796. bne zero,v0,50f // if ne, second level cache present
  797. and t8,t4,0x10 // test if 16-byte cache block
  798. //
  799. // Zero page in primary data cache only.
  800. //
  801. #if defined(_DUO_)
  802. 30: sdc1 f0,0(t0) // zero 64-byte block
  803. sdc1 f0,8(t0) //
  804. sdc1 f0,16(t0) //
  805. sdc1 f0,24(t0) //
  806. sdc1 f0,32(t0) //
  807. sdc1 f0,40(t0) //
  808. sdc1 f0,48(t0) //
  809. addu t0,t0,64 // advance to next 64-byte block
  810. bne t0,t9,30b // if ne, more to zero
  811. sdc1 f0,-8(t0) //
  812. #else
  813. 30: cache CREATE_DIRTY_EXCLUSIVE_D,0(t0) // create cache block
  814. addu t0,t0,t4 // compute next block address
  815. bne zero,t8,40f // if ne, 16-byte cache line
  816. sdc1 f0,-16(t0) //
  817. sdc1 f0,-24(t0) // zero 16 bytes
  818. sdc1 f0,-32(t0) //
  819. 40: bne t0,t9,30b // if ne, more blocks to zero
  820. sdc1 f0,-8(t0) // zero 16 bytes
  821. #endif
  822. .set at
  823. .set reorder
  824. ENABLE_INTERRUPTS(t5) // enable interrupts
  825. lw ra,ZpRa(sp) // get return address
  826. addu sp,sp,ZpFrameLength // deallocate stack frame
  827. j ra // return
  828. //
  829. // Zero page in primary and secondary data caches.
  830. //
  831. .set noreorder
  832. .set noat
  833. #if defined(_DUO_)
  834. 50: sdc1 f0,0(t0) // zero 64-byte block
  835. sdc1 f0,8(t0) //
  836. sdc1 f0,16(t0) //
  837. sdc1 f0,24(t0) //
  838. sdc1 f0,32(t0) //
  839. sdc1 f0,40(t0) //
  840. sdc1 f0,48(t0) //
  841. addu t0,t0,64 // advance to next 64-byte block
  842. bne t0,t9,50b // if ne, more to zero
  843. sdc1 f0,-8(t0) //
  844. #else
  845. 50: cache CREATE_DIRTY_EXCLUSIVE_SD,0(t0) // create secondary cache block
  846. addu v1,v0,t0 // compute ending primary block address
  847. 60: addu t0,t0,t4 // compute next block address
  848. bne zero,t8,70f // if ne, 16-byte primary cache line
  849. sdc1 f0,-16(t0) //
  850. sdc1 f0,-24(t0) // zero 16 bytes
  851. sdc1 f0,-32(t0) //
  852. 70: bne t0,v1,60b // if ne, more primary blocks to zero
  853. sdc1 f0,-8(t0) // zero 16 bytes
  854. bne t0,t9,50b // if ne, more secondary blocks to zero
  855. nop // fill
  856. #endif
  857. .set at
  858. .set reorder
  859. ENABLE_INTERRUPTS(t5) // enable interrupts
  860. lw ra,ZpRa(sp) // get return address
  861. addu sp,sp,ZpFrameLength // deallocate stack frame
  862. j ra // return
  863. .end HalZeroPage