This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit d4201facd8480f1dc5f2546cdc6e5b0aa9cbc12b
Author: Daniel P. Carvalho <[email protected]>
AuthorDate: Sun Oct 4 00:54:37 2026 -0300

    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 <[email protected]>
---
 arch/mips/src/mips32/mips_cache.S | 65 +++++++++++++++++++++++++--------------
 1 file changed, 42 insertions(+), 23 deletions(-)

diff --git a/arch/mips/src/mips32/mips_cache.S 
b/arch/mips/src/mips32/mips_cache.S
index 92c2c4f5f10..8654e89ea83 100644
--- a/arch/mips/src/mips32/mips_cache.S
+++ b/arch/mips/src/mips32/mips_cache.S
@@ -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 */
+
+  mtc0 zero, MIPS32_CP0_ERRCTL
+  mtc0 zero, MIPS32_CP0_TAGLO
+  ehb
 
-  CACHE_OP HIT_INVALIDATE_D, t3, t4, t1
+  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)

Reply via email to