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.

1098 lines
36 KiB

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