From 62c358946dd7eebcdf38fe38edd30e079791dd02 Mon Sep 17 00:00:00 2001 From: Lee Lup Yuen Date: Sun, 21 Jan 2024 21:43:15 +0800 Subject: [PATCH] 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 +++++++++++ .../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 2a0ee3d29b2..0d17982a8e3 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 0e6e1b2b389..23ce40b5258 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 32aaa1ea5db..7cdd365ef2b 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