// TITLE("Cache Flush") //++ // // Copyright (c) 1991 Microsoft Corporation // // Module Name: // // j4cache.s // // Abstract: // // This module implements the code necessary for cache operations on // a MIPS R4000. // // Author: // // David N. Cutler (davec) 19-Dec-1991 // // Environment: // // Kernel mode only. // // Revision History: // //-- #include "halmips.h" // // Define cache operations constants. // #define COLOR_BITS (7 << PAGE_SHIFT) // color bit (R4000 - 8kb cache) #define COLOR_MASK (0x7fff) // color mask (R4000 - 8kb cache) #define FLUSH_BASE 0xfffe0000 // flush base address #define PROTECTION_BITS ((1 << ENTRYLO_V) | (1 << ENTRYLO_D)) // SBTTL("Export Data From Data Cache") //++ // // VOID // HalExportDcachePage ( // IN PVOID Color, // IN ULONG PageFrame, // IN ULONG Length // ) // // Routine Description: // // This function exports (hit/writeback) up to a page of data from the // data cache. // // Arguments: // // Color (a0) - Supplies the starting virtual address and color of the // data that is exported. // // PageFrame (a1) - Supplies the page frame number of the page that // is exported. // // Length (a2) - Supplies the length of the region in the page that is // exported. // // Return Value: // // None. // //-- LEAF_ENTRY(HalExportDcachePage) .set noreorder .set noat lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy and a0,a0,COLOR_MASK // isolate color and offset bits li t0,FLUSH_BASE // get base flush address or t0,t0,a0 // compute color virtual address sll t1,a1,ENTRYLO_PFN // shift page frame into position or t1,t1,PROTECTION_BITS // merge protection bits or t1,t1,v0 // merge cache policy and a0,a0,0x1000 // isolate TB entry index beql zero,a0,10f // if eq, first entry move t2,zero // set second page table entry move t2,t1 // set second page table entry move t1,zero // set first page table entry 10: mfc0 t3,wired // get TB entry index lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size bnel zero,v0,15f // if ne, second level cache present move t4,v0 // set flush block size .set at .set reorder // // Export data from the data cache. // 15: DISABLE_INTERRUPTS(t5) // disable interrupts .set noreorder .set noat mfc0 t6,entryhi // get current PID and VPN2 srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address sll t7,t7,ENTRYHI_VPN2 // and t6,t6,0xff << ENTRYHI_PID // isolate current PID or t7,t7,t6 // merge PID with VPN2 of virtual address mtc0 t7,entryhi // set VPN2 and PID for probe mtc0 t1,entrylo0 // set first PTE value mtc0 t2,entrylo1 // set second PTE value mtc0 t3,index // set TB index value nop // fill tlbwi // write TB entry - 3 cycle hazzard subu t6,t4,1 // compute block size minus one and t7,t0,t6 // compute offset in block addu a2,a2,t6 // round up to next block addu a2,a2,t7 // nor t6,t6,zero // complement block size minus one and a2,a2,t6 // truncate length to even number beq zero,a2,30f // if eq, no blocks to export and t8,t0,t6 // compute starting virtual address addu t9,t8,a2 // compute ending virtual address bne zero,v0,40f // if ne, second level cache present subu t9,t9,t4 // compute ending loop address // // Export the primary data cache only. // 20: cache HIT_WRITEBACK_D,0(t8) // invalidate cache block bne t8,t9,20b // if ne, more blocks to invalidate addu t8,t8,t4 // compute next block address .set at .set reorder 30: ENABLE_INTERRUPTS(t5) j ra // return // // Export the primary and secondary data caches. // .set noreorder .set noat 40: cache HIT_WRITEBACK_SD,0(t8) // invalidate cache block bne t8,t9,40b // if ne, more blocks to invalidate addu t8,t8,t4 // compute next block address .set at .set reorder ENABLE_INTERRUPTS(t5) // enable interrupts j ra // return .end HalExportDcachePage SBTTL("Flush Data Cache Page") //++ // // VOID // HalFlushDcachePage ( // IN PVOID Color, // IN ULONG PageFrame, // IN ULONG Length // ) // // Routine Description: // // This function flushes (hit/writeback/invalidate) up to a page of data // from the data cache. // // Arguments: // // Color (a0) - Supplies the starting virtual address and color of the // data that is flushed. // // PageFrame (a1) - Supplies the page frame number of the page that // is flushed. // // Length (a2) - Supplies the length of the region in the page that is // flushed. // // Return Value: // // None. // //-- LEAF_ENTRY(HalFlushDcachePage) .set noreorder .set noat lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy and a0,a0,COLOR_MASK // isolate color and offset bits li t0,FLUSH_BASE // get base flush address or t0,t0,a0 // compute color virtual address sll t1,a1,ENTRYLO_PFN // shift page frame into position or t1,t1,PROTECTION_BITS // merge protection bits or t1,t1,v0 // merge cache policy and a0,a0,0x1000 // isolate TB entry index beql zero,a0,10f // if eq, first entry move t2,zero // set second page table entry move t2,t1 // set second page table entry move t1,zero // set first page table entry 10: mfc0 t3,wired // get TB entry index lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size bnel zero,v0,15f // if ne, second level cache present move t4,v0 // set flush block size .set at .set reorder // // Flush a page from the data cache. // 15: DISABLE_INTERRUPTS(t5) // disable interrupts .set noreorder .set noat mfc0 t6,entryhi // get current PID and VPN2 srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address sll t7,t7,ENTRYHI_VPN2 // and t6,t6,0xff << ENTRYHI_PID // isolate current PID or t7,t7,t6 // merge PID with VPN2 of virtual address mtc0 t7,entryhi // set VPN2 and PID for probe mtc0 t1,entrylo0 // set first PTE value mtc0 t2,entrylo1 // set second PTE value mtc0 t3,index // set TB index value nop // fill tlbwi // write TB entry - 3 cycle hazzard subu t6,t4,1 // compute block size minus one and t7,t0,t6 // compute offset in block addu a2,a2,t6 // round up to next block addu a2,a2,t7 // nor t6,t6,zero // complement block size minus one and a2,a2,t6 // truncate length to even number beq zero,a2,30f // if eq, no blocks to flush and t8,t0,t6 // compute starting virtual address addu t9,t8,a2 // compute ending virtual address bne zero,v0,40f // if ne, second level cache present subu t9,t9,t4 // compute ending loop address // // Flush the primary data cache only. // 20: cache HIT_WRITEBACK_INVALIDATE_D,0(t8) // invalidate cache block bne t8,t9,20b // if ne, more blocks to invalidate addu t8,t8,t4 // compute next block address .set at .set reorder 30: ENABLE_INTERRUPTS(t5) // enable interrupts j ra // return // // Flush the primary and secondary data caches. // .set noreorder .set noat 40: cache HIT_WRITEBACK_INVALIDATE_SD,0(t8) // invalidate cache block bne t8,t9,40b // if ne, more blocks to invalidate addu t8,t8,t4 // compute next block address .set at .set reorder ENABLE_INTERRUPTS(t5) // enable interrupts j ra // return .end HalFlushDcachePage SBTTL("Purge Data Cache Page") //++ // // VOID // HalPurgeDcachePage ( // IN PVOID Color, // IN ULONG PageFrame, // IN ULONG Length // ) // // Routine Description: // // This function purges (hit/invalidate) up to a page of data from the // data cache. // // Arguments: // // Color (a0) - Supplies the starting virtual address and color of the // data that is purged. // // PageFrame (a1) - Supplies the page frame number of the page that // is purged. // // Length (a2) - Supplies the length of the region in the page that is // purged. // // Return Value: // // None. // //-- LEAF_ENTRY(HalPurgeDcachePage) .set noreorder .set noat lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy and a0,a0,COLOR_MASK // isolate color bits li t0,FLUSH_BASE // get base flush address or t0,t0,a0 // compute color virtual address sll t1,a1,ENTRYLO_PFN // shift page frame into position or t1,t1,PROTECTION_BITS // merge protection bits or t1,t1,v0 // merge cache policy and a0,a0,0x1000 // isolate TB entry index beql zero,a0,10f // if eq, first entry move t2,zero // set second page table entry move t2,t1 // set second page table entry move t1,zero // set first page table entry 10: mfc0 t3,wired // get TB entry index lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size bnel zero,v0,15f // if ne, second level cache present move t4,v0 // set purge block size .set at .set reorder // // Purge data from the data cache. // 15: DISABLE_INTERRUPTS(t5) // disable interrupts .set noreorder .set noat mfc0 t6,entryhi // get current PID and VPN2 srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address sll t7,t7,ENTRYHI_VPN2 // and t6,t6,0xff << ENTRYHI_PID // isolate current PID or t7,t7,t6 // merge PID with VPN2 of virtual address mtc0 t7,entryhi // set VPN2 and PID for probe mtc0 t1,entrylo0 // set first PTE value mtc0 t2,entrylo1 // set second PTE value mtc0 t3,index // set TB index value nop // fill tlbwi // write TB entry - 3 cycle hazzard subu t6,t4,1 // compute block size minus one and t7,t0,t6 // compute offset in block addu a2,a2,t6 // round up to next block addu a2,a2,t7 // nor t6,t6,zero // complement block size minus one and a2,a2,t6 // truncate length to even number beq zero,a2,30f // if eq, no blocks to purge and t8,t0,t6 // compute starting virtual address addu t9,t8,a2 // compute ending virtual address bne zero,v0,40f // if ne, second level cache present subu t9,t9,t4 // compute ending loop address // // Purge the primary data cache only. // 20: cache HIT_INVALIDATE_D,0(t8) // invalidate cache block bne t8,t9,20b // if ne, more blocks to invalidate addu t8,t8,t4 // compute next block address .set at .set reorder 30: ENABLE_INTERRUPTS(t5) // enable interrupts j ra // return // // Purge the primary and secondary data caches. // .set noreorder .set noat 40: cache HIT_INVALIDATE_SD,0(t8) // invalidate cache block bne t8,t9,40b // if ne, more blocks to invalidate addu t8,t8,t4 // compute next block address .set at .set reorder ENABLE_INTERRUPTS(t5) // enable interrupts j ra // return .end HalPurgeDcachePage SBTTL("Purge Instruction Cache Page") //++ // // VOID // HalPurgeIcachePage ( // IN PVOID Color, // IN ULONG PageFrame, // IN ULONG Length // ) // // Routine Description: // // This function purges (hit/invalidate) up to a page fo data from the // instruction cache. // // Arguments: // // Color (a0) - Supplies the starting virtual address and color of the // data that is purged. // // PageFrame (a1) - Supplies the page frame number of the page that // is purged. // // Length (a2) - Supplies the length of the region in the page that is // purged. // // Return Value: // // None. // //-- LEAF_ENTRY(HalPurgeIcachePage) .set noreorder .set noat lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy and a0,a0,COLOR_MASK // isolate color bits li t0,FLUSH_BASE // get base flush address or t0,t0,a0 // compute color virtual address sll t1,a1,ENTRYLO_PFN // shift page frame into position or t1,t1,PROTECTION_BITS // merge protection bits or t1,t1,v0 // merge cache policy and a0,a0,0x1000 // isolate TB entry index beql zero,a0,10f // if eq, first entry move t2,zero // set second page table entry move t2,t1 // set second page table entry move t1,zero // set first page table entry 10: mfc0 t3,wired // get TB entry index lw v0,KiPcr + PcSecondLevelIcacheFillSize(zero) // get 2nd fill size lw t4,KiPcr + PcFirstLevelIcacheFillSize(zero) // get 1st fill size bnel zero,v0,15f // if ne, second level cache present move t4,v0 // set purge block size .set at .set reorder // // Purge data from the instruction cache. // 15: DISABLE_INTERRUPTS(t5) // disable interrupts .set noreorder .set noat mfc0 t6,entryhi // get current PID and VPN2 srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address sll t7,t7,ENTRYHI_VPN2 // and t6,t6,0xff << ENTRYHI_PID // isolate current PID or t7,t7,t6 // merge PID with VPN2 of virtual address mtc0 t7,entryhi // set VPN2 and PID for probe mtc0 t1,entrylo0 // set first PTE value mtc0 t2,entrylo1 // set second PTE value mtc0 t3,index // set TB index value nop // fill tlbwi // write TB entry - 3 cycle hazzard subu t6,t4,1 // compute block size minus one and t7,t0,t6 // compute offset in block addu a2,a2,t6 // round up to next block addu a2,a2,t7 // nor t6,t6,zero // complement block size minus one and a2,a2,t6 // truncate length to even number beq zero,a2,30f // if eq, no blocks to purge and t8,t0,t6 // compute starting virtual address addu t9,t8,a2 // compute ending virtual address bne zero,v0,40f // if ne, second level cache present subu t9,t9,t4 // compute ending loop address // // Purge the primary instruction cache only. // 20: cache HIT_INVALIDATE_I,0(t8) // invalidate cache block bne t8,t9,20b // if ne, more blocks to invalidate addu t8,t8,t4 // compute next block address .set at .set reorder 30: ENABLE_INTERRUPTS(t5) // enable interrupts j ra // return // // Purge the primary and secondary instruction caches. // .set noreorder .set noat 40: cache HIT_INVALIDATE_SI,0(t8) // invalidate cache block bne t8,t9,40b // if ne, more blocks to invalidate addu t8,t8,t4 // compute next block address .set at .set reorder ENABLE_INTERRUPTS(t5) // enable interrupts j ra // return .end HalPurgeIcachePage SBTTL("Sweep Data Cache") //++ // // VOID // HalSweepDcache ( // VOID // ) // // Routine Description: // // This function sweeps (index/writeback/invalidate) the entire data cache. // // Arguments: // // None. // // Return Value: // // None. // //-- LEAF_ENTRY(HalSweepDcache) lw t0,KiPcr + PcFirstLevelDcacheSize(zero) // get data cache size lw t1,KiPcr + PcFirstLevelDcacheFillSize(zero) // get block size li a0,KSEG0_BASE // set starting index value addu a1,a0,t0 // compute ending cache address subu a1,a1,t1 // compute ending block address // // Sweep the primary data cache. // #if defined(_DUO_) DISABLE_INTERRUPTS(t2) // disable interrupts .set noreorder .set noat 10: lw zero,0(a0) // force writeback with load nop // fill nop // fill nop // fill cache INDEX_WRITEBACK_INVALIDATE_D,0(a0) // invalidate on index bne a0,a1,10b // if ne, more to invalidate addu a0,a0,t1 // compute address of next block #else .set noreorder .set noat 10: cache INDEX_WRITEBACK_INVALIDATE_D,0(a0) // writeback/invalidate on index bne a0,a1,10b // if ne, more to invalidate addu a0,a0,t1 // compute address of next block #endif .set at .set reorder lw t0,KiPcr + PcSecondLevelDcacheSize(zero) // get data cache size lw t1,KiPcr + PcSecondLevelDcacheFillSize(zero) // get block size beq zero,t1,30f // if eq, no second level cache li a0,KSEG0_BASE // set starting index value addu a1,a0,t0 // compute ending cache address subu a1,a1,t1 // compute ending block address // // Sweep the secondary data cache. // .set noreorder .set noat 20: cache INDEX_WRITEBACK_INVALIDATE_SD,0(a0) // writeback/invalidate on index bne a0,a1,20b // if ne, more to invalidate addu a0,a0,t1 // compute address of next block .set at .set reorder #if defined(_DUO_) ENABLE_INTERRUPTS(t2) // enable interrupts #endif 30: j ra // return .end HalSweepDcache SBTTL("Sweep Instruction Cache") //++ // // VOID // HalSweepIcache ( // VOID // ) // // Routine Description: // // This function sweeps (index/invalidate) the entire instruction cache. // // Arguments: // // None. // // Return Value: // // None. // //-- LEAF_ENTRY(HalSweepIcache) lw t0,KiPcr + PcSecondLevelIcacheSize(zero) // get instruction cache size lw t1,KiPcr + PcSecondLevelIcacheFillSize(zero) // get fill size beq zero,t1,20f // if eq, no second level cache li a0,KSEG0_BASE // set starting index value addu a1,a0,t0 // compute ending cache address subu a1,a1,t1 // compute ending block address // // Sweep the secondary instruction cache. // .set noreorder .set noat 10: cache INDEX_INVALIDATE_SI,0(a0) // invalidate cache line bne a0,a1,10b // if ne, more to invalidate addu a0,a0,t1 // compute address of next block .set at .set reorder 20: lw t0,KiPcr + PcFirstLevelIcacheSize(zero) // get instruction cache size lw t1,KiPcr + PcFirstLevelIcacheFillSize(zero) // get fill size li a0,KSEG0_BASE // set starting index value addu a1,a0,t0 // compute ending cache address subu a1,a1,t1 // compute ending block address // // Sweep the primary instruction cache. // .set noreorder .set noat 30: cache INDEX_INVALIDATE_I,0(a0) // invalidate cache line bne a0,a1,30b // if ne, more to invalidate addu a0,a0,t1 // compute address of next block .set at .set reorder j ra // return .end HalSweepIcache