📄 cachesb1alib.s
字号:
.end cacheSb1ICInvalidateLines/********************************************************************************* sb1CacheExcVec - Special cache error handler for SB1** RETURNS: N/A** not a user callable routine*/ .ent sb1CacheExcVecFUNC_LABEL(sb1CacheExcVec) /* * This is a very bad place to be. Our cache error * detection has triggered. If we have write-back data * in the cache, we may not be able to recover. As a * first-order desperate measure, turn off KSEG0 cacheing. */ .set noat /* look for signature of spurious CErr */ mfc0 k1, C0_ECC lui k0, 0x4000 bne k0, k1,real_cerr .word 0x401bd801 /* mfc0 k1,C0_CACHERR,1 */ lui k0, 0xffe0 and k1, k0,k1 lui k0, 0x0200 bne k0, k1,real_cerr /* clear/unlock the registers */ mtc0 zero, C0_ECC .word 0x4080d801 /* mtc0 zero,C0_CACHERR,1 */ eretreal_cerr: b real_cerr .end sb1CacheExcVec /******************************************************************************** sb1L2CacheInit - Initialize the L2 Cache tags to be "invalid"** void sb1L2CacheInit (void) * * Registers used:* t0,t1,t2*/ .globl sb1L2CacheInit .ent sb1L2CacheInitFUNC_LABEL(sb1L2CacheInit) /* Save the old status register, and set the KX bit. */ mfc0 t2,C0_SR or t1,t2,SR_KX mtc0 t1,C0_SR HAZARD_CP_WRITE /* Start the index at the base of the cache management area, but leave the address bit for "Valid" zero. Note that the management tags are at 00_D000_0000, which cannot be expressed with the PHYS_TO_K1 macro, so well need to use a 64-bit address to get to it. */ dli t0,PHYS_TO_XKSEG_UNCACHED(A_L2C_MGMT_TAG_BASE) /* Loop through each entry and each way */ li t1,L2C_ENTRIES_PER_WAY*L2C_NUM_WAYS /* Write a zero to the cache management register at each address. */ .align 41: sd zero,(t0) sd zero,1*L2CACHE_LINESIZE(t0) sd zero,2*L2CACHE_LINESIZE(t0) sd zero,3*L2CACHE_LINESIZE(t0) daddiu t0,t0,(4*L2CACHE_LINESIZE) subu t1,t1,4 bne t1,zero,1b /* Restore old KX bit setting */ mtc0 t2,C0_SR HAZARD_CP_WRITE j ra .end sb1L2CacheInit/******************************************************************************** sb1L2CacheDisable - Convert the entire L2 Cache into static memory, ** void sb1L2CacheDisable (void) * * Registers used:* t0,t1*/ .globl sb1L2CacheDisable .ent sb1L2CacheDisableFUNC_LABEL(sb1L2CacheDisable) /* Configure the L2 cache as SRAM (all ways disabled except one) Do a memory reference at the "way_disable" address to switch it off. Warning: do NOT try to configure all of the ways off - you must leave at least one way active! This code leaves way #3 active and gives ways 0..2 to the program. */ li t0,PHYS_TO_K1(A_L2_MAKEDISABLE(0x07)) ld t0,(t0) /* Use the result of the load to stall the pipe here. Ref sec 5.4.2 XXX is this necessary for global enable/disable operations? */ addu t0,t0,t0 /* Re-write all the tags */ b sb1L2CacheInit .end sb1L2CacheDisable/******************************************************************************** sb1L2CacheEnable - Convert the L2 Cache into a functioning cache memory** void sb1L2CacheEnable (void) * * Registers used:* t0,t1*/ .globl sb1L2CacheEnable .ent sb1L2CacheEnableFUNC_LABEL(sb1L2CacheEnable) /* Configure the L2 cache as Cache (all ways enabled) Do a memory reference at the "way_disable" address to switch it on. */ li t0,PHYS_TO_K1(A_L2_MAKEDISABLE(0x0)) ld t0,(t0) /* Use the result of the load to stall the pipe here. Ref sec 5.4.2 XXX is this necessary for global enable/disable operations? */ addu t0,t0,t0 /* Re-write all the tags */ b sb1L2CacheInit .end sb1L2CacheEnable/******************************************************************************** sb1L2CacheFlush - force all dirty lines to be written back to memory** int sb1L2CacheFlush (void) * * Registers used:* t0,t1,t2,t3,t4,t5,t6,t7,a0** RETURNS: number of lines flushed*/ .globl sb1L2CacheFlush .ent sb1L2CacheFlushFUNC_LABEL(sb1L2CacheFlush) /* Save the old status register, and set the KX bit. */ mfc0 a0,C0_SR or t1,a0,SR_KX mtc0 t1,C0_SR HAZARD_CP_WRITE /* Set the BERR bits in both memory controllers. We re going to do cacheable reads where there is no memory. */ li t0,PHYS_TO_K1(A_MC_REGISTER(0,R_MC_CONFIG)) ld t6,0(t0) dli t1,(M_MC_BERR_DISABLE | M_MC_ECC_DISABLE) or t1,t1,t6 sd t1,0(t0) li t0,PHYS_TO_K1(A_MC_REGISTER(1,R_MC_CONFIG)) ld t7,0(t0) dli t1,(M_MC_BERR_DISABLE | M_MC_ECC_DISABLE) or t1,t1,t7 sd t1,0(t0) /* Start the index at the base of the cache management area. Note that the management tags are at 00_D000_0000, which cannot be expressed with the PHYS_TO_K1 macro, so well need to use a 64-bit address to get to it. */ dli t0,PHYS_TO_XKSEG_UNCACHED(A_L2C_MGMT_TAG_BASE) li t2,PHYS_TO_K1(A_L2_READ_ADDRESS) /* Loop through each entry and each way */ li t1,L2C_ENTRIES_PER_WAY*L2C_NUM_WAYS move v0,zero /* Do a read at the cache management address to set the A_L2_READ_TAG register. */1: ld t3,0(t0) /*this sets the register.*/ daddi t3,t3,0 /*Do an ALU op to ensure ordering*/ ld t4,0(t2) /*Get the tag*/ li t5,M_L2C_TAG_DIRTY and t5,t4,t5 /*Test the dirty bit*/ beq t5,zero,2f /*don t flush this line*/ /* The way that we re looking at now will be the victim, so all we need to do is a cacheable read at any address that does *not* match this tag. To do this, we re going to OR in some bits into the physical address to put it way outside the memory area. Then do a cacheable read. The current way will be replaced with the garbage data. We ll pick PA 30_0000_0000 in the middle of the 520GB memory expansion area for this purpose. */ add v0,1 /*count this line (debug)*/ dli t5,(M_L2C_TAG_TAG|M_L2C_TAG_INDEX) and t4,t4,t5 /*Have a physical address*/ dli t5,PHYS_TO_XKSEG_CACHED(0x3000000000) or t4,t4,t5 ld t4,0(t4) /*Do a read.*/ daddi t4,t4,1 /*Use it in an ALU op.*/2: daddiu t0,t0,L2CACHE_LINESIZE subu t1,t1,1 bne t1,zero,1b /* Now, reinit the entire cache. Of course, we could just reinit the lines we flushed, but this routine is mucking the entire cache anyway, so it doesn t matter. */ dli t0,PHYS_TO_XKSEG_UNCACHED(A_L2C_MGMT_TAG_BASE) li t1,L2C_ENTRIES_PER_WAY*L2C_NUM_WAYS /* Write a zero to the cache management register at each address. */1: sd zero,0(t0) sd zero,1*L2CACHE_LINESIZE(t0) sd zero,2*L2CACHE_LINESIZE(t0) sd zero,3*L2CACHE_LINESIZE(t0) daddiu t0,t0,(4*L2CACHE_LINESIZE) subu t1,t1,4 bne t1,zero,1b /* Restore the old MC register values */ li t0,PHYS_TO_K1(A_MC_REGISTER(0,R_MC_CONFIG)) sd t6,0(t0) li t0,PHYS_TO_K1(A_MC_REGISTER(1,R_MC_CONFIG)) sd t7,0(t0) /* Restore old KX bit setting */ mtc0 a0,C0_SR HAZARD_CP_WRITE j ra /*return to caller*/ .end sb1L2CacheFlush
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -