18 #ifndef __CORE_FEATURE_SPMP_H__
19 #define __CORE_FEATURE_SPMP_H__
38 #include "core_feature_base.h"
39 #include "core_compatiable.h"
41 #if defined(__SPMP_PRESENT) && (__SPMP_PRESENT == 1)
58 #ifndef __SPMP_ENTRY_NUM
60 #error "__SPMP_ENTRY_NUM is not defined, please check!"
63 typedef struct SPMP_CONFIG {
138 uint8_t csr_cfg_num = 0;
139 uint16_t csr_idx = 0;
140 uint16_t cfg_shift = 0;
142 if (entry_idx >= __SPMP_ENTRY_NUM)
return 0;
144 #if __RISCV_XLEN == 32
146 csr_idx = entry_idx >> 2;
147 #elif __RISCV_XLEN == 64
150 csr_idx = (entry_idx >> 2) & ~1;
160 cfg_shift = (entry_idx & (csr_cfg_num - 1)) << 3;
163 return (uint8_t)(__RV_EXTRACT_FIELD(spmpcfgx, 0xFF << cfg_shift));
178 uint8_t csr_cfg_num = 0;
179 uint16_t csr_idx = 0;
180 uint16_t cfg_shift = 0;
181 if (entry_idx >= __SPMP_ENTRY_NUM)
return;
183 #if __RISCV_XLEN == 32
185 csr_idx = entry_idx >> 2;
186 #elif __RISCV_XLEN == 64
189 csr_idx = (entry_idx >> 2) & ~1;
200 cfg_shift = (entry_idx & (csr_cfg_num - 1)) << 3;
202 spmpcfgx = __RV_INSERT_FIELD(spmpcfgx, 0xFFUL << cfg_shift, spmpxcfg);
277 unsigned int cfg_shift, cfg_csr_idx, addr_csr_idx = 0;
278 unsigned long cfgmask, addrmask = 0;
279 unsigned long spmpcfg, spmpaddr = 0;
280 unsigned long protection, csr_cfg_num = 0;
285 #if __RISCV_XLEN == 32
287 cfg_csr_idx = (entry_idx >> 2);
288 #elif __RISCV_XLEN == 64
290 cfg_csr_idx = ((entry_idx >> 2)) & ~1;
299 cfg_shift = (entry_idx & (csr_cfg_num - 1)) << 3;
300 addr_csr_idx = entry_idx;
303 protection = (
unsigned long)spmp_cfg->
protection;
305 cfgmask = ~(0xFFUL << cfg_shift);
307 spmpcfg |= ((protection << cfg_shift) & ~cfgmask);
315 spmpaddr |= (addrmask >> 1);
338 unsigned int cfg_shift, cfg_csr_idx, addr_csr_idx = 0;
339 unsigned long cfgmask, spmpcfg, prot = 0;
340 unsigned long t1, addr, spmpaddr, len = 0;
341 uint8_t csr_cfg_num = 0;
343 if (entry_idx >= __SPMP_ENTRY_NUM || !spmp_cfg)
return -1;
346 #if __RISCV_XLEN == 32
348 cfg_csr_idx = entry_idx >> 2;
349 #elif __RISCV_XLEN == 64
351 cfg_csr_idx = (entry_idx >> 2) & ~1;
357 cfg_shift = (entry_idx & (csr_cfg_num - 1)) << 3;
358 addr_csr_idx = entry_idx;
361 cfgmask = (0xFFUL << cfg_shift);
363 prot = spmpcfg >> cfg_shift;
368 t1 =
__CTZ(~spmpaddr);
369 addr = (spmpaddr & ~((1UL << t1) - 1)) <<
SPMP_SHIFT;
379 spmp_cfg->
order = len;
384 #if defined(__SMPU_PRESENT) && (__SMPU_PRESENT == 1)
389 #define __get_SMPUCFGx __get_sPMPCFGx
390 #define __set_SMPUCFGx __set_sPMPCFGx
391 #define __get_SMPUxCFG __get_sPMPxCFG
392 #define __set_SMPUxCFG __set_sPMPxCFG
393 #define __get_SMPUADDRx __get_sPMPADDRx
394 #define __set_SMPUADDRx __set_sPMPADDRx
395 #define __set_SMPUENTRYx __set_sPMPENTRYx
396 #define __get_SMPUENTRYx __get_sPMPENTRYx
409 #if __RISCV_XLEN == 32
412 #elif __RISCV_XLEN == 64
429 #if __RISCV_XLEN == 32
433 return (uint64_t)((((uint64_t)hi) << 32) | lo);
434 #elif __RISCV_XLEN == 64
__STATIC_FORCEINLINE unsigned long __CTZ(unsigned long data)
Count tailing zero.
#define __RV_CSR_READ(csr)
CSR operation Macro for csrr instruction.
#define __RV_CSR_WRITE(csr, val)
CSR operation Macro for csrw instruction.
#define __STATIC_INLINE
Define a static function that may be inlined by the compiler.
unsigned long rv_csr_t
Type of Control and Status Register(CSR), depends on the XLEN defined in RISC-V.
#define __RISCV_XLEN
Refer to the width of an integer register in bits(either 32 or 64)
__STATIC_INLINE uint64_t __get_SMPUSWITCHx(void)
Get SMPU each entry's on/off status.
__STATIC_INLINE int __get_sPMPENTRYx(unsigned int entry_idx, spmp_config *spmp_cfg)
Get sPMP entry by entry idx.
__STATIC_INLINE void __set_sPMPADDRx(uint32_t csr_idx, rv_csr_t spmpaddr)
Set sPMPADDRx by CSR index.
__STATIC_INLINE void __set_sPMPCFGx(uint32_t csr_idx, rv_csr_t spmpcfg)
Set sPMPCFGx by csr index.
__STATIC_INLINE void __set_SMPUSWITCHx(uint64_t val)
Set SMPU each entry's on/off status.
__STATIC_INLINE rv_csr_t __get_sPMPADDRx(uint32_t csr_idx)
Get sPMPADDRx Register by CSR index.
spmp_config smpu_config
sPMP has upgraded to S-mode Memory Protection Unit, renamed as SMPU, but still share the apis with sP...
__STATIC_INLINE void __set_sPMPENTRYx(uint32_t entry_idx, const spmp_config *spmp_cfg)
Set sPMP entry by entry idx.
__STATIC_INLINE void __set_sPMPxCFG(uint32_t entry_idx, uint8_t spmpxcfg)
Set 8bit sPMPxCFG by spmp entry index.
__STATIC_INLINE rv_csr_t __get_sPMPCFGx(uint32_t csr_idx)
Get sPMPCFGx Register by csr index.
__STATIC_INLINE uint8_t __get_sPMPxCFG(uint32_t entry_idx)
Get 8bit sPMPxCFG Register by sPMP entry index.
unsigned long base_addr
Base address of memory region It must be 2^order aligned address.
unsigned int protection
Set permissions using macros SMPU_S/ SMPU_R/SMPU_W/ SMPU_X of SMPU; SPMP_L/ SPMP_U/SPMP_R/ SPMP_W/SPM...
unsigned long order
Size of memory region as power of 2, it has to be minimum 2 and maxium __RISCV_XLEN according to the ...