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 {
100 #if __SPMP_ENTRY_NUM > 8
125 #if __SPMP_ENTRY_NUM > 8
142 uint8_t csr_cfg_num = 0;
143 uint16_t csr_idx = 0;
144 uint16_t cfg_shift = 0;
146 if (entry_idx >= __SPMP_ENTRY_NUM)
return 0;
148 #if __RISCV_XLEN == 32
150 csr_idx = entry_idx >> 2;
151 #elif __RISCV_XLEN == 64
154 csr_idx = (entry_idx >> 2) & ~1;
164 cfg_shift = (entry_idx & (csr_cfg_num - 1)) << 3;
167 return (uint8_t)(__RV_EXTRACT_FIELD(spmpcfgx, 0xFF << cfg_shift));
182 uint8_t csr_cfg_num = 0;
183 uint16_t csr_idx = 0;
184 uint16_t cfg_shift = 0;
185 if (entry_idx >= __SPMP_ENTRY_NUM)
return;
187 #if __RISCV_XLEN == 32
189 csr_idx = entry_idx >> 2;
190 #elif __RISCV_XLEN == 64
193 csr_idx = (entry_idx >> 2) & ~1;
204 cfg_shift = (entry_idx & (csr_cfg_num - 1)) << 3;
206 spmpcfgx = __RV_INSERT_FIELD(spmpcfgx, 0xFFUL << cfg_shift, spmpxcfg);
227 #if __SPMP_ENTRY_NUM > 8
258 #if __SPMP_ENTRY_NUM > 8
285 unsigned int cfg_shift, cfg_csr_idx, addr_csr_idx = 0;
286 unsigned long cfgmask, addrmask = 0;
287 unsigned long spmpcfg, spmpaddr = 0;
288 unsigned long protection, csr_cfg_num = 0;
293 #if __RISCV_XLEN == 32
295 cfg_csr_idx = (entry_idx >> 2);
296 #elif __RISCV_XLEN == 64
298 cfg_csr_idx = ((entry_idx >> 2)) & ~1;
307 cfg_shift = (entry_idx & (csr_cfg_num - 1)) << 3;
308 addr_csr_idx = entry_idx;
311 protection = (
unsigned long)spmp_cfg->
protection;
313 cfgmask = ~(0xFFUL << cfg_shift);
315 spmpcfg |= ((protection << cfg_shift) & ~cfgmask);
323 spmpaddr |= (addrmask >> 1);
346 unsigned int cfg_shift, cfg_csr_idx, addr_csr_idx = 0;
347 unsigned long cfgmask, spmpcfg, prot = 0;
348 unsigned long t1, addr, spmpaddr, len = 0;
349 uint8_t csr_cfg_num = 0;
351 if (entry_idx >= __SPMP_ENTRY_NUM || !spmp_cfg)
return -1;
354 #if __RISCV_XLEN == 32
356 cfg_csr_idx = entry_idx >> 2;
357 #elif __RISCV_XLEN == 64
359 cfg_csr_idx = (entry_idx >> 2) & ~1;
365 cfg_shift = (entry_idx & (csr_cfg_num - 1)) << 3;
366 addr_csr_idx = entry_idx;
369 cfgmask = (0xFFUL << cfg_shift);
371 prot = spmpcfg >> cfg_shift;
376 t1 =
__CTZ(~spmpaddr);
377 addr = (spmpaddr & ~((1UL << t1) - 1)) <<
SPMP_SHIFT;
387 spmp_cfg->
order = len;
392 #if defined(__SMPU_PRESENT) && (__SMPU_PRESENT == 1)
397 #define __get_SMPUCFGx __get_sPMPCFGx
398 #define __set_SMPUCFGx __set_sPMPCFGx
399 #define __get_SMPUxCFG __get_sPMPxCFG
400 #define __set_SMPUxCFG __set_sPMPxCFG
401 #define __get_SMPUADDRx __get_sPMPADDRx
402 #define __set_SMPUADDRx __set_sPMPADDRx
403 #define __set_SMPUENTRYx __set_sPMPENTRYx
404 #define __get_SMPUENTRYx __get_sPMPENTRYx
417 #if __RISCV_XLEN == 32
420 #elif __RISCV_XLEN == 64
437 #if __RISCV_XLEN == 32
441 return (uint64_t)((((uint64_t)hi) << 32) | lo);
442 #elif __RISCV_XLEN == 64
__STATIC_INLINE 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 ...