arch/mips/mips32: fix the L1 cache maintenance functions.

Several bugs made the MIPS32 cache functions unusable:

- The range functions rounded the end address down instead of up and
  stopped before it, so the last line was never handled.  A range
  within a single line started a loop that only ended when the address
  wrapped around 4 GB, which took seconds.
- HIT_WRITEBACK_D was 0x15, which is Hit_Writeback_Inv_D.  Hit
  Writeback D is 0x19.  up_clean_dcache() now uses it and
  up_flush_dcache() uses Hit_Writeback_Inv_D.
- The *_all functions used Hit operations over a KSEG0 range the size of
  the cache, which only affects lines caching that range.  Use index
  operations instead: Index_Invalidate_I, Index_Writeback_Inv_D and, to
  discard the D-Cache, Index_Store_Tag_D with a zero tag.
- With CONFIG_MIPS32_CACHE_AUTOINFO the line size was computed with a
  right shift instead of a left shift.
- The CACHE_OP loop label was "1", the same label the callers use to
  skip the operation, and the branch delay slot was left to whatever
  instruction followed.
- up_coherent_dcache() called up_invalidate_icache_all() even when it is
  not built.

Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Daniel P. Carvalho <danieloak@gmail.com>
This commit is contained in:
Daniel P. Carvalho 2026-10-04 00:54:37 -03:00 • committed by Alan C. Assis
parent eafd01cecc
commit d4201facd8

View file

@ -45,13 +45,14 @@
/* Cache Operations ********************************************************/
#define INDEX_INVALIDATE_I 0x00
#define INDEX_INVALIDATE_D 0x01
#define INDEX_STORE_TAG_I 0x08
#define INDEX_STORE_TAG_D 0x09
#define HIT_INVALIDATE_I 0x10
#define HIT_INVALIDATE_D 0x11
#define HIT_WRITEBACK_D 0x15
#define INDEX_INVALIDATE_I 0x00
#define INDEX_WRITEBACK_INV_D 0x01
#define INDEX_STORE_TAG_I 0x08
#define INDEX_STORE_TAG_D 0x09
#define HIT_INVALIDATE_I 0x10
#define HIT_INVALIDATE_D 0x11
#define HIT_WRITEBACK_INV_D 0x15
#define HIT_WRITEBACK_D 0x19
/****************************************************************************
* Public Symbols
@ -67,15 +68,22 @@
* Name: CACHE_OP
* Description:
* Performs cache operation on an address range.
* Performs cache operation on an address range. start and end must be
* aligned to lsize; nothing is done if start is not below end. Must be
* used with noreorder. Clobbers t5.
*
****************************************************************************/
.macro CACHE_OP op, start, end, lsize
1:
sltu t5, \start, \end
beqz t5, .Lcacheop_done\@
nop
.Lcacheop_loop\@:
cache \op, 0(\start)
addu \start, \start, \lsize
bne \start, \end, 1b
bne \start, \end, .Lcacheop_loop\@
nop
.Lcacheop_done\@:
.endm
/****************************************************************************
@ -128,7 +136,7 @@ icache_linesize:
srl t1, t1, CP0_CONFIG1_IL_SHIFT
li t2, 2
srl v0, t2, t1 /* Cache line size = 2 << IL_VALUE */
sll v0, t2, t1 /* Cache line size = 2 << IL_VALUE */
#endif
1:
@ -337,7 +345,7 @@ dcache_linesize:
srl t1, t1, CP0_CONFIG1_DL_SHIFT
li t2, 2
srl v0, t2, t1 /* Cache line size = 2 << DL_VALUE */
sll v0, t2, t1 /* Cache line size = 2 << DL_VALUE */
#endif
1:
@ -643,7 +651,8 @@ up_invalidate_icache:
and t0, a0, t3
subu t1, a1, 1
addu t1, a1, t2
subu t1, t1, 1
and t1, t1, t3
/* Perform the cache operation */
@ -715,7 +724,7 @@ up_invalidate_icache_all:
/* Perform the cache operation */
CACHE_OP HIT_INVALIDATE_I, t3, t4, t1
CACHE_OP INDEX_INVALIDATE_I, t3, t4, t1
/* Ensure all pending cache operations are completed. */
@ -875,7 +884,8 @@ up_invalidate_dcache:
and t0, a0, t3
subu t1, a1, 1
addu t1, a1, t2
subu t1, t1, 1
and t1, t1, t3
/* Perform the cache operation */
@ -945,9 +955,13 @@ up_invalidate_dcache_all:
li t3, CONFIG_MIPS32_KSEG0_DBASE
addu t4, t3, t0
/* Perform the cache operation */
/* Write a zero (invalid) tag to every line, discarding its contents */
CACHE_OP HIT_INVALIDATE_D, t3, t4, t1
mtc0 zero, MIPS32_CP0_ERRCTL
mtc0 zero, MIPS32_CP0_TAGLO
ehb
CACHE_OP INDEX_STORE_TAG_D, t3, t4, t1
/* Ensure all pending cache operations are completed. */
@ -1009,7 +1023,8 @@ up_clean_dcache:
and t0, a0, t3
subu t1, a1, 1
addu t1, a1, t2
subu t1, t1, 1
and t1, t1, t3
/* Perform the cache operation */
@ -1038,7 +1053,8 @@ up_clean_dcache:
*
* Description:
* Clean the entire data cache within the specified region by flushing the
* contents of the data cache to memory.
* contents of the data cache to memory. MIPS32 has no indexed write-back
* without invalidate, so the lines are invalidated too.
*
* Input Parameters:
* None
@ -1082,7 +1098,7 @@ up_clean_dcache_all:
/* Perform the cache operation */
CACHE_OP HIT_WRITEBACK_D, t3, t4, t1
CACHE_OP INDEX_WRITEBACK_INV_D, t3, t4, t1
/* Ensure all pending cache operations are completed. */
@ -1144,12 +1160,13 @@ up_flush_dcache:
and t0, a0, t3
subu t1, a1, 1
addu t1, a1, t2
subu t1, t1, 1
and t1, t1, t3
/* Perform the cache operation */
CACHE_OP HIT_WRITEBACK_D, t0, t1, t2
CACHE_OP HIT_WRITEBACK_INV_D, t0, t1, t2
/* Ensure all pending cache operations are completed. */
@ -1216,7 +1233,7 @@ up_flush_dcache_all:
/* Perform the cache operation */
CACHE_OP HIT_WRITEBACK_D, t3, t4, t1
CACHE_OP INDEX_WRITEBACK_INV_D, t3, t4, t1
/* Ensure all pending cache operations are completed. */
@ -1277,10 +1294,12 @@ up_coherent_dcache:
jal up_flush_dcache
nop
#ifdef CONFIG_MIPS32_ICACHE
/* Invalidate the entire I-Cache */
jal up_invalidate_icache_all
nop
#endif
1:
lw ra, 0(sp)