From 3cabc92427ba6a013e0e531bea9cf07935068152 Mon Sep 17 00:00:00 2001 From: Inochi Amaoto Date: Mon, 15 Apr 2024 19:12:20 +0800 Subject: [PATCH] arch/risc-v: add risc-v SSTC extension support SSTC extension allows nuttx to implement S-mode timer directly, which is useful for starting at S-mode. Signed-off-by: Inochi Amaoto --- arch/risc-v/Kconfig | 5 ++ arch/risc-v/include/csr.h | 74 +++++++++++++++++++++++++++ arch/risc-v/include/mode.h | 2 + arch/risc-v/src/common/riscv_mtimer.c | 17 ++++++ 4 files changed, 98 insertions(+) diff --git a/arch/risc-v/Kconfig b/arch/risc-v/Kconfig index 14f539e072..428768b320 100644 --- a/arch/risc-v/Kconfig +++ b/arch/risc-v/Kconfig @@ -520,6 +520,11 @@ config ARCH_USE_S_MODE and/or U-mode (in case of separate kernel-/userspaces). This provides an option to run the kernel in S-mode, if the target supports it. +config ARCH_RV_EXT_SSTC + bool "Enable RISC-V SSTC extension support" + default n + depends on ARCH_USE_S_MODE + choice prompt "Toolchain Selection" default RISCV_TOOLCHAIN_GNU_RV64 diff --git a/arch/risc-v/include/csr.h b/arch/risc-v/include/csr.h index 4cbf24fd8d..01506883c0 100644 --- a/arch/risc-v/include/csr.h +++ b/arch/risc-v/include/csr.h @@ -135,10 +135,19 @@ #define CSR_STVAL 0x143 #define CSR_SIP 0x144 +/* Supervisor Environment Configuration Registers */ + +#define CSR_SENVCFG 0x10a + /* Supervisor Protection and Translation Registers */ #define CSR_SATP 0x180 +/* Supervisor Time Registers */ + +#define CSR_STIMECMP 0x14d +#define CSR_STIMECMPH 0x15d + /* Machine Information Registers */ #define CSR_MVENDORID 0xf11 @@ -164,6 +173,11 @@ #define CSR_MTVAL 0x343 #define CSR_MIP 0x344 +/* Machine Environment Configuration Registers */ + +#define CSR_MENVCFG 0x30a +#define CSR_MENVCFGH 0x31a + /* Machine Protection and Translation */ #define CSR_PMPCFG0 0x3a0 @@ -354,6 +368,23 @@ #define MSTATUS_WPRI (UINT64_C(0x1ffffff) << 38 | UINT64_C(0x1ff) << 23 | 0x15) #endif +/* In menvcfg register */ +#define MENVCFG_FIOM (0x1 << 0) +#define MENVCFG_CBIE (0x3 << 4) +#define MENVCFG_CBIE_ILL (0x0 << 4) +#define MENVCFG_CBIE_FLUSH (0x1 << 4) +#define MENVCFG_CBIE_INV (0x3 << 4) +#define MENVCFG_CBCFE (0x1 << 6) +#define MENVCFG_CBZE (0x1 << 7) + +#ifdef CONFIG_ARCH_RV32 +#define MENVCFG_PBMTE (0x1 << 30) +#define MENVCFG_STCE (0x1 << 31) +#else +#define MENVCFG_PBMTE (UINT64_C(0x1) << 62) +#define MENVCFG_STCE (UINT64_C(0x1) << 63) +#endif + /* In mie (machine interrupt enable) register */ #define MIE_SSIE (0x1 << 1) /* Supervisor Software Interrupt Enable */ @@ -405,6 +436,15 @@ #define SIP_STIP MIP_STIP #define SIP_SEIP MIP_SEIP +/* In senvcfg register */ +#define SENVCFG_FIOM MENVCFG_FIOM +#define SENVCFG_CBIE MENVCFG_CBIE +#define SENVCFG_CBIE_ILL MENVCFG_CBIE_ILL +#define SENVCFG_CBIE_FLUSH MENVCFG_CBIE_FLUSH +#define SENVCFG_CBIE_INV MENVCFG_CBIE_INV +#define SENVCFG_CBCFE MENVCFG_CBCFE +#define SENVCFG_CBZE MENVCFG_CBZE + /* In pmpcfg (PMP configuration) register */ #define PMPCFG_R (1 << 0) /* readable ? */ @@ -418,6 +458,40 @@ #define PMPCFG_A_MASK (3 << 3) /* address-matching mode mask */ #define PMPCFG_L (1 << 7) /* locked ? */ +/* In mcounteren/scounteren register */ +#define COUNTEREN_CY (0x1 << 0) +#define COUNTEREN_TM (0x1 << 1) +#define COUNTEREN_IR (0x1 << 2) +#define COUNTEREN_HPM3 (0x1 << 3) +#define COUNTEREN_HPM4 (0x1 << 4) +#define COUNTEREN_HPM5 (0x1 << 5) +#define COUNTEREN_HPM6 (0x1 << 6) +#define COUNTEREN_HPM7 (0x1 << 7) +#define COUNTEREN_HPM8 (0x1 << 8) +#define COUNTEREN_HPM9 (0x1 << 9) +#define COUNTEREN_HPM10 (0x1 << 10) +#define COUNTEREN_HPM11 (0x1 << 11) +#define COUNTEREN_HPM12 (0x1 << 12) +#define COUNTEREN_HPM13 (0x1 << 13) +#define COUNTEREN_HPM14 (0x1 << 14) +#define COUNTEREN_HPM15 (0x1 << 15) +#define COUNTEREN_HPM16 (0x1 << 16) +#define COUNTEREN_HPM17 (0x1 << 17) +#define COUNTEREN_HPM18 (0x1 << 18) +#define COUNTEREN_HPM19 (0x1 << 19) +#define COUNTEREN_HPM20 (0x1 << 20) +#define COUNTEREN_HPM21 (0x1 << 21) +#define COUNTEREN_HPM22 (0x1 << 22) +#define COUNTEREN_HPM23 (0x1 << 23) +#define COUNTEREN_HPM24 (0x1 << 24) +#define COUNTEREN_HPM25 (0x1 << 25) +#define COUNTEREN_HPM26 (0x1 << 26) +#define COUNTEREN_HPM27 (0x1 << 27) +#define COUNTEREN_HPM28 (0x1 << 28) +#define COUNTEREN_HPM29 (0x1 << 29) +#define COUNTEREN_HPM30 (0x1 << 30) +#define COUNTEREN_HPM31 (0x1 << 31) + /**************************************************************************** * Public Types ****************************************************************************/ diff --git a/arch/risc-v/include/mode.h b/arch/risc-v/include/mode.h index e16c93bc95..27bff35806 100644 --- a/arch/risc-v/include/mode.h +++ b/arch/risc-v/include/mode.h @@ -44,6 +44,7 @@ # define CSR_CAUSE CSR_SCAUSE /* Interrupt cause register */ # define CSR_TVAL CSR_STVAL /* Trap value register */ # define CSR_TVEC CSR_STVEC /* Trap vector base addr register */ +# define CSR_ENVCFG CSR_SENVCFG /* Env configuration register */ /* In status register */ @@ -86,6 +87,7 @@ # define CSR_CAUSE CSR_MCAUSE /* Interrupt cause register */ # define CSR_TVAL CSR_MTVAL /* Trap value register */ # define CSR_TVEC CSR_MTVEC /* Trap vector base addr register */ +# define CSR_ENVCFG CSR_MENVCFG /* Env configuration register */ /* In status register */ diff --git a/arch/risc-v/src/common/riscv_mtimer.c b/arch/risc-v/src/common/riscv_mtimer.c index c350a45977..bd17bafe59 100644 --- a/arch/risc-v/src/common/riscv_mtimer.c +++ b/arch/risc-v/src/common/riscv_mtimer.c @@ -127,6 +127,19 @@ static void riscv_mtimer_set_mtimecmp(struct riscv_mtimer_lowerhalf_s *priv, __MB(); } #else + +#ifdef CONFIG_ARCH_RV_EXT_SSTC +static inline void riscv_write_stime(uint64_t value) +{ +#ifdef CONFIG_ARCH_RV64 + WRITE_CSR(CSR_STIMECMP, value); +#else + WRITE_CSR(CSR_STIMECMP, (uint32_t)value); + WRITE_CSR(CSR_STIMECMPH, (uint32_t)(value >> 32)); +#endif +} +#endif + static uint64_t riscv_mtimer_get_mtime(struct riscv_mtimer_lowerhalf_s *priv) { UNUSED(priv); @@ -137,7 +150,11 @@ static void riscv_mtimer_set_mtimecmp(struct riscv_mtimer_lowerhalf_s *priv, uint64_t value) { UNUSED(priv); +#ifndef CONFIG_ARCH_RV_EXT_SSTC riscv_sbi_set_timer(value); +#else + riscv_write_stime(value); +#endif } #endif