This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new 62c358946d risc-v/bl808: Flush MMU Cache after updating SATP
62c358946d is described below
commit 62c358946dd7eebcdf38fe38edd30e079791dd02
Author: Lee Lup Yuen <[email protected]>
AuthorDate: Sun Jan 21 21:43:15 2024 +0800
risc-v/bl808: Flush MMU Cache after updating SATP
Ox64 BL808 crashes with a Page Fault when we run `getprime` then `hello`.
This is caused by the T-Head C906 MMU incorrectly accessing the MMU Page Tables
of the Previous Process (`getprime`) while starting the New Process (`hello`).
To fix the problem, this PR flushes the MMU Cache whenever we point the MMU
SATP Register to the New Page Tables. We execute 2 RISC-V Instructions that are
specific to T-Head C906:
- DCACHE.IALL: Invalidate all Page Table Entries in the D-Cache
- SYNC.S: Ensure that all Cache Operations are completed
This is derived from the T-Head Errata for Linux Kernel. More details here:
https://lupyuen.github.io/articles/mmu#appendix-flush-the-mmu-cache-for-t-head-c906
Modified Files:
- `arch/risc-v/src/common/riscv_mmu.h`: If needed, `mmu_write_satp()` calls
`mmu_flush_cache()` (weak function) to flush the MMU Cache. (Like for T-Head
C906)
- `arch/risc-v/src/bl808/bl808_mm_init.c`: Flush the MMU Cache for T-Head
C906. Extend `mmuflags` from 32-bit to 64-bit to be consistent with
`mmu_ln_setentry()`.
- `boards/risc-v/bl808/ox64/configs/nsh/defconfig`: Enable `ostest` in the
Build Config. Update `CONFIG_BOARD_LOOPSPERMSEC` according to `calib_udelay`.
---
arch/risc-v/src/bl808/bl808_mm_init.c | 37 +++++++++++++++++++++-----
arch/risc-v/src/common/riscv_mmu.h | 21 +++++++++++++++
boards/risc-v/bl808/ox64/configs/nsh/defconfig | 3 ++-
3 files changed, 54 insertions(+), 7 deletions(-)
diff --git a/arch/risc-v/src/bl808/bl808_mm_init.c
b/arch/risc-v/src/bl808/bl808_mm_init.c
index 2a0ee3d29b..0d17982a8e 100644
--- a/arch/risc-v/src/bl808/bl808_mm_init.c
+++ b/arch/risc-v/src/bl808/bl808_mm_init.c
@@ -74,8 +74,8 @@
#define SLAB_COUNT (sizeof(m_l3_pgtable) / RV_MMU_PAGE_SIZE)
#define KMM_PAGE_SIZE RV_MMU_L3_PAGE_SIZE
-#define KMM_PBASE PGT_L3_PBASE
-#define KMM_PBASE_IDX 3
+#define KMM_PBASE PGT_L3_PBASE
+#define KMM_PBASE_IDX 3
#define KMM_SPBASE PGT_L2_PBASE
#define KMM_SPBASE_IDX 2
@@ -171,7 +171,7 @@ static uintptr_t slab_alloc(void)
****************************************************************************/
static void map_region(uintptr_t paddr, uintptr_t vaddr, size_t size,
- uint32_t mmuflags)
+ uint64_t mmuflags)
{
uintptr_t endaddr;
uintptr_t pbase;
@@ -235,8 +235,7 @@ void bl808_kernel_mappings(void)
/* Begin mapping memory to MMU; note that at this point the MMU is not yet
* active, so the page table virtual addresses are actually physical
- * addresses and so forth. M-mode does not perform translations anyhow, so
- * this mapping is quite simple to do
+ * addresses and so forth.
*/
/* Map I/O region, use enough large page tables for the IO region. */
@@ -291,8 +290,34 @@ void bl808_mm_init(void)
bl808_kernel_mappings();
- /* Enable MMU (note: system is still in M-mode) */
+ /* Enable MMU */
binfo("mmu_enable: satp=%" PRIuPTR "\n", g_kernel_pgt_pbase);
mmu_enable(g_kernel_pgt_pbase, 0);
}
+
+/****************************************************************************
+ * Name: mmu_flush_cache
+ *
+ * Description:
+ * Flush the MMU Cache for T-Head C906. Called by mmu_write_satp() after
+ * updating the MMU SATP Register, when swapping MMU Page Tables.
+ * This operation executes RISC-V Instructions that are specific to
+ * T-Head C906.
+ *
+ ****************************************************************************/
+
+void weak_function mmu_flush_cache(void)
+{
+ __asm__ __volatile__
+ (
+
+ /* DCACHE.IALL: Invalidate all Page Table Entries in the D-Cache */
+
+ ".long 0x0020000b\n"
+
+ /* SYNC.S: Ensure that all Cache Operations are completed */
+
+ ".long 0x0190000b\n"
+ );
+}
diff --git a/arch/risc-v/src/common/riscv_mmu.h
b/arch/risc-v/src/common/riscv_mmu.h
index 0e6e1b2b38..23ce40b525 100644
--- a/arch/risc-v/src/common/riscv_mmu.h
+++ b/arch/risc-v/src/common/riscv_mmu.h
@@ -21,6 +21,10 @@
#ifndef ___ARCH_RISC_V_SRC_COMMON_RISCV_MMU_H_
#define ___ARCH_RISC_V_SRC_COMMON_RISCV_MMU_H_
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
/* RV32/64 page size */
#define RV_MMU_PAGE_SHIFT (12)
@@ -150,6 +154,16 @@
extern uintptr_t g_kernel_pgt_pbase;
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+void weak_function mmu_flush_cache(void);
+
+/****************************************************************************
+ * Inline Functions
+ ****************************************************************************/
+
/****************************************************************************
* Name: mmu_satp_reg
*
@@ -197,6 +211,13 @@ static inline void mmu_write_satp(uintptr_t reg)
: "rK" (reg)
: "memory"
);
+
+ /* Flush the MMU Cache if needed (T-Head C906) */
+
+ if (mmu_flush_cache != NULL)
+ {
+ mmu_flush_cache();
+ }
}
/****************************************************************************
diff --git a/boards/risc-v/bl808/ox64/configs/nsh/defconfig
b/boards/risc-v/bl808/ox64/configs/nsh/defconfig
index 32aaa1ea5d..7cdd365ef2 100644
--- a/boards/risc-v/bl808/ox64/configs/nsh/defconfig
+++ b/boards/risc-v/bl808/ox64/configs/nsh/defconfig
@@ -34,7 +34,7 @@ CONFIG_ARCH_USE_S_MODE=y
CONFIG_BL808_UART3=y
CONFIG_BOARDCTL_ROMDISK=y
CONFIG_BOARD_LATE_INITIALIZE=y
-CONFIG_BOARD_LOOPSPERMSEC=116524
+CONFIG_BOARD_LOOPSPERMSEC=1120
CONFIG_BUILD_KERNEL=y
CONFIG_DEBUG_ASSERTIONS=y
CONFIG_DEBUG_ASSERTIONS_EXPRESSION=y
@@ -79,6 +79,7 @@ CONFIG_SYMTAB_ORDEREDBYNAME=y
CONFIG_SYSTEM_NSH=y
CONFIG_SYSTEM_NSH_PROGNAME="init"
CONFIG_TESTING_GETPRIME=y
+CONFIG_TESTING_OSTEST=y
CONFIG_UART3_BAUD=2000000
CONFIG_UART3_SERIAL_CONSOLE=y
CONFIG_USEC_PER_TICK=1000