Просмотр исходного кода

!362 修复D1刷cache无效的bug
Merge pull request !362 from 胡自成/smart-d1

bernard 4 лет назад
Родитель
Сommit
f8cbd784da
3 измененных файлов с 108 добавлено и 26 удалено
  1. 83 22
      libcpu/risc-v/t-head/c906/cache.c
  2. 23 0
      libcpu/risc-v/t-head/c906/cache.h
  3. 2 4
      libcpu/risc-v/t-head/c906/mmu.c

+ 83 - 22
libcpu/risc-v/t-head/c906/cache.c

@@ -6,6 +6,7 @@
  * Change Logs:
  * Date           Author       Notes
  * 2021-01-29     lizhirui     first version
+ * 2021-11-05     JasonHu      add c906 cache inst
  */
 
 #include <rthw.h>
@@ -13,36 +14,99 @@
 #include <board.h>
 #include <riscv.h>
 
-rt_inline rt_uint32_t rt_cpu_icache_line_size()
+#define L1_CACHE_BYTES (64)
+
+static void dcache_wb_range(unsigned long start, unsigned long end)
 {
-    return 0;
+    unsigned long i = start & ~(L1_CACHE_BYTES - 1);
+
+    for (; i < end; i += L1_CACHE_BYTES)
+    {
+        /* asm volatile("dcache.cva %0\n"::"r"(i):"memory"); */
+        /*
+         * compiler always use a5 = i.
+         * a6 not used, so we use a6 here.
+         */
+        asm volatile("mv a6, %0\n"::"r"(i):"memory");   /* a6 = a5(i) */
+        asm volatile(".long 0x0257800b");               /* dcache.cva a6 */
+    }
+    asm volatile(".long 0x01b0000b");   /* sync.is */
 }
 
-rt_inline rt_uint32_t rt_cpu_dcache_line_size()
+static void dcache_inv_range(unsigned long start, unsigned long end)
 {
-    return 0;
+    unsigned long i = start & ~(L1_CACHE_BYTES - 1);
+
+    for (; i < end; i += L1_CACHE_BYTES)
+    {
+        /* asm volatile("dcache.iva %0\n"::"r"(i):"memory"); */
+        asm volatile("mv a6, %0\n"::"r"(i):"memory");   /* a6 = a5(i) */
+        asm volatile(".long 0x0268000b");               /* dcache.iva a6 */
+    }
+    asm volatile(".long 0x01b0000b");
+}
+
+static void dcache_wbinv_range(unsigned long start, unsigned long end)
+{
+    unsigned long i = start & ~(L1_CACHE_BYTES - 1);
+
+    for (; i < end; i += L1_CACHE_BYTES)
+    {
+        /* asm volatile("dcache.civa %0\n"::"r"(i):"memory"); */
+        asm volatile("mv a6, %0\n"::"r"(i):"memory");   /* a6 = a5(i) */
+        asm volatile(".long 0x0278000b");               /* dcache.civa a6 */
+    }
+    asm volatile(".long 0x01b0000b");
+}
+
+static void icache_inv_range(unsigned long start, unsigned long end)
+{
+    unsigned long i = start & ~(L1_CACHE_BYTES - 1);
+
+    for (; i < end; i += L1_CACHE_BYTES)
+    {
+        /* asm volatile("icache.iva %0\n"::"r"(i):"memory"); */
+        asm volatile("mv a6, %0\n"::"r"(i):"memory");   /* a6 = a5(i) */
+        asm volatile(".long 0x0308000b");               /* icache.iva a6 */
+    }
+    asm volatile(".long 0x01b0000b");
+}
+
+rt_inline rt_uint32_t rt_cpu_icache_line_size(void)
+{
+    return L1_CACHE_BYTES;
+}
+
+rt_inline rt_uint32_t rt_cpu_dcache_line_size(void)
+{
+    return L1_CACHE_BYTES;
 }
 
 void rt_hw_cpu_icache_invalidate(void *addr,int size)
 {
-    asm volatile("fence");
+    icache_inv_range((unsigned long)addr, (unsigned long)((unsigned char *)addr + size));
 }
 
 void rt_hw_cpu_dcache_invalidate(void *addr,int size)
 {
-    asm volatile("fence");
+    dcache_inv_range((unsigned long)addr, (unsigned long)((unsigned char *)addr + size));
 }
 
 void rt_hw_cpu_dcache_clean(void *addr,int size)
 {
-    asm volatile("fence");
+    dcache_wb_range((unsigned long)addr, (unsigned long)((unsigned char *)addr + size));
+}
+
+void rt_hw_cpu_dcache_clean_flush(void *addr,int size)
+{
+    dcache_wbinv_range((unsigned long)addr, (unsigned long)((unsigned char *)addr + size));
 }
 
 void rt_hw_cpu_icache_ops(int ops,void *addr,int size)
 {
     if(ops == RT_HW_CACHE_INVALIDATE)
     {
-        rt_hw_cpu_icache_invalidate(addr,size);
+        rt_hw_cpu_icache_invalidate(addr, size);
     }
 }
 
@@ -50,33 +114,30 @@ void rt_hw_cpu_dcache_ops(int ops,void *addr,int size)
 {
     if(ops == RT_HW_CACHE_FLUSH)
     {
-        rt_hw_cpu_dcache_clean(addr,size);
+        rt_hw_cpu_dcache_clean(addr, size);
     }
     else
     {
-        rt_hw_cpu_dcache_invalidate(addr,size);
+        rt_hw_cpu_dcache_invalidate(addr, size);
     }
 }
 
-void rt_hw_cpu_dcache_flush_all()
-{
-    asm volatile("fence");
-    //asm volatile("dcache.call");
-}
-
-void rt_hw_cpu_icache_invalidate_all()
+void rt_hw_cpu_dcache_clean_all(void)
 {
-    asm volatile("fence");
+    /* asm volatile("dcache.ciall\n":::"memory"); */
+    asm volatile(".long 0x0030000b\n":::"memory");
 }
 
-rt_base_t rt_hw_cpu_icache_status()
+void rt_hw_cpu_dcache_invalidate_all(void)
 {
-    return 0;
+    /* asm volatile("dcache.iall\n":::"memory"); */
+    asm volatile(".long 0x0020000b\n":::"memory");
 }
 
-rt_base_t rt_hw_cpu_dcache_status()
+void rt_hw_cpu_icache_invalidate_all(void)
 {
-    return 0;
+    /* asm volatile("icache.iall\n":::"memory"); */
+    asm volatile(".long 0x0100000b\n":::"memory");
 }
 
 int sys_cacheflush(void *addr, int size, int cache)

+ 23 - 0
libcpu/risc-v/t-head/c906/cache.h

@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2021-11-05     JasonHu      The first version
+ */
+
+#ifndef CACHE_H__
+#define CACHE_H__
+
+void rt_hw_cpu_dcache_clean(void *addr,int size);
+void rt_hw_cpu_icache_invalidate(void *addr,int size);
+void rt_hw_cpu_dcache_invalidate(void *addr,int size);
+
+void rt_hw_cpu_dcache_clean_flush(void *addr,int size);
+void rt_hw_cpu_dcache_clean_all(void);
+void rt_hw_cpu_dcache_invalidate_all(void);
+void rt_hw_cpu_icache_invalidate_all(void);
+
+#endif /* CACHE_H__ */

+ 2 - 4
libcpu/risc-v/t-head/c906/mmu.c

@@ -14,15 +14,13 @@
 #include "page.h"
 #include <stdlib.h>
 #include <string.h>
+#include <cache.h>
 
 #include "riscv.h"
 #include "riscv_mmu.h"
 #include "mmu.h"
 
 void *current_mmu_table = RT_NULL;
-void rt_hw_cpu_icache_invalidate_all();
-void rt_hw_cpu_dcache_flush_all();
-void rt_hw_cpu_dcache_clean(void *addr,rt_size_t size);
 
 static void rt_hw_cpu_tlb_invalidate()
 {
@@ -41,7 +39,7 @@ void switch_mmu(void *mmu_table)
     current_mmu_table = mmu_table;
     RT_ASSERT(__CHECKALIGN(mmu_table,PAGE_OFFSET_BIT));
     mmu_set_pagetable((rt_ubase_t)mmu_table);
-    rt_hw_cpu_dcache_flush_all();
+    rt_hw_cpu_dcache_clean_all();
     rt_hw_cpu_icache_invalidate_all();
 }