NMSIS-Core  Version 1.4.0
NMSIS-Core support for Nuclei processor-based devices
sPMP or sMPU Functions

Functions that related to the RISCV supervisor-mode Phyiscal Memory Protection. More...

Data Structures

struct  spmp_config
 

Macros

#define __get_SMPUCFGx   __get_sPMPCFGx
 
#define __set_SMPUCFGx   __set_sPMPCFGx
 
#define __get_SMPUxCFG   __get_sPMPxCFG
 
#define __set_SMPUxCFG   __set_sPMPxCFG
 
#define __get_SMPUADDRx   __get_sPMPADDRx
 
#define __set_SMPUADDRx   __set_sPMPADDRx
 
#define __set_SMPUENTRYx   __set_sPMPENTRYx
 
#define __get_SMPUENTRYx   __get_sPMPENTRYx
 

Typedefs

typedef spmp_config smpu_config
 sPMP has upgraded to S-mode Memory Protection Unit, renamed as SMPU, but still share the apis with sPMP's More...
 

Functions

__STATIC_INLINE rv_csr_t __get_sPMPCFGx (uint32_t csr_idx)
 Get sPMPCFGx Register by csr index. More...
 
__STATIC_INLINE void __set_sPMPCFGx (uint32_t csr_idx, rv_csr_t spmpcfg)
 Set sPMPCFGx by csr index. More...
 
__STATIC_INLINE uint8_t __get_sPMPxCFG (uint32_t entry_idx)
 Get 8bit sPMPxCFG Register by sPMP entry index. More...
 
__STATIC_INLINE void __set_sPMPxCFG (uint32_t entry_idx, uint8_t spmpxcfg)
 Set 8bit sPMPxCFG by spmp entry index. More...
 
__STATIC_INLINE rv_csr_t __get_sPMPADDRx (uint32_t csr_idx)
 Get sPMPADDRx Register by CSR index. More...
 
__STATIC_INLINE void __set_sPMPADDRx (uint32_t csr_idx, rv_csr_t spmpaddr)
 Set sPMPADDRx by CSR index. More...
 
__STATIC_INLINE void __set_sPMPENTRYx (uint32_t entry_idx, const spmp_config *spmp_cfg)
 Set sPMP entry by entry idx. More...
 
__STATIC_INLINE int __get_sPMPENTRYx (unsigned int entry_idx, spmp_config *spmp_cfg)
 Get sPMP entry by entry idx. More...
 
__STATIC_INLINE void __set_SMPUSWITCHx (uint64_t val)
 Set SMPU each entry's on/off status. More...
 
__STATIC_INLINE uint64_t __get_SMPUSWITCHx (void)
 Get SMPU each entry's on/off status. More...
 

Detailed Description

Functions that related to the RISCV supervisor-mode Phyiscal Memory Protection.

Optional superviosr physical memory protection (sPMP) unit provides per-hart supervisor-mode control registers to allow physical memory access privileges (read, write, execute) to be specified for each physical memory region. The sPMP values are checked after the physical address to be accessed pass PMP checks described in the RISC-V privileged spec.

Like PMP, the sPMP can supports region access control settings as small as four bytes.

Macro Definition Documentation

◆ __get_SMPUADDRx

#define __get_SMPUADDRx   __get_sPMPADDRx

Definition at line 393 of file core_feature_spmp.h.

◆ __get_SMPUCFGx

#define __get_SMPUCFGx   __get_sPMPCFGx

Definition at line 389 of file core_feature_spmp.h.

◆ __get_SMPUENTRYx

#define __get_SMPUENTRYx   __get_sPMPENTRYx

Definition at line 396 of file core_feature_spmp.h.

◆ __get_SMPUxCFG

#define __get_SMPUxCFG   __get_sPMPxCFG

Definition at line 391 of file core_feature_spmp.h.

◆ __set_SMPUADDRx

#define __set_SMPUADDRx   __set_sPMPADDRx

Definition at line 394 of file core_feature_spmp.h.

◆ __set_SMPUCFGx

#define __set_SMPUCFGx   __set_sPMPCFGx

Definition at line 390 of file core_feature_spmp.h.

◆ __set_SMPUENTRYx

#define __set_SMPUENTRYx   __set_sPMPENTRYx

Definition at line 395 of file core_feature_spmp.h.

◆ __set_SMPUxCFG

#define __set_SMPUxCFG   __set_sPMPxCFG

Definition at line 392 of file core_feature_spmp.h.

Typedef Documentation

◆ smpu_config

sPMP has upgraded to S-mode Memory Protection Unit, renamed as SMPU, but still share the apis with sPMP's

Definition at line 388 of file core_feature_spmp.h.

Function Documentation

◆ __get_SMPUSWITCHx()

__STATIC_INLINE uint64_t __get_SMPUSWITCHx ( void  )

Get SMPU each entry's on/off status.

Get the value of the SMPUSWITCHx Register.

Remarks
  • Each bit of this register holds on/off status of the corresponding SMPU entry respectively.
  • An SMPU entry is activated only when both corresponding bits in smpuswitch and A field of smpuicfg are set. (i.e., smpuswitch[i] & smpu[i]cfg.A).

Definition at line 427 of file core_feature_spmp.h.

428 {
429 #if __RISCV_XLEN == 32
430  uint32_t lo, hi = 0;
433  return (uint64_t)((((uint64_t)hi) << 32) | lo);
434 #elif __RISCV_XLEN == 64
435  return (uint64_t)__RV_CSR_READ(CSR_SMPUSWITCH0);
436 #else
437  // TODO Add RV128 Handling
438 #endif
439 }
#define __RV_CSR_READ(csr)
CSR operation Macro for csrr instruction.
#define CSR_SMPUSWITCH1
#define CSR_SMPUSWITCH0

References __RV_CSR_READ, CSR_SMPUSWITCH0, and CSR_SMPUSWITCH1.

◆ __get_sPMPADDRx()

__STATIC_INLINE rv_csr_t __get_sPMPADDRx ( uint32_t  csr_idx)

Get sPMPADDRx Register by CSR index.

Return the content of the sPMPADDRx Register.

Parameters
[in]csr_idxsPMP region CSR index(0-15)
Returns
sPMPADDRx Register value

Definition at line 212 of file core_feature_spmp.h.

213 {
214  switch (csr_idx) {
215  case 0: return __RV_CSR_READ(CSR_SPMPADDR0);
216  case 1: return __RV_CSR_READ(CSR_SPMPADDR1);
217  case 2: return __RV_CSR_READ(CSR_SPMPADDR2);
218  case 3: return __RV_CSR_READ(CSR_SPMPADDR3);
219  case 4: return __RV_CSR_READ(CSR_SPMPADDR4);
220  case 5: return __RV_CSR_READ(CSR_SPMPADDR5);
221  case 6: return __RV_CSR_READ(CSR_SPMPADDR6);
222  case 7: return __RV_CSR_READ(CSR_SPMPADDR7);
223  case 8: return __RV_CSR_READ(CSR_SPMPADDR8);
224  case 9: return __RV_CSR_READ(CSR_SPMPADDR9);
225  case 10: return __RV_CSR_READ(CSR_SPMPADDR10);
226  case 11: return __RV_CSR_READ(CSR_SPMPADDR11);
227  case 12: return __RV_CSR_READ(CSR_SPMPADDR12);
228  case 13: return __RV_CSR_READ(CSR_SPMPADDR13);
229  case 14: return __RV_CSR_READ(CSR_SPMPADDR14);
230  case 15: return __RV_CSR_READ(CSR_SPMPADDR15);
231  default: return 0;
232  }
233 }
#define CSR_SPMPADDR10
#define CSR_SPMPADDR9
#define CSR_SPMPADDR0
#define CSR_SPMPADDR11
#define CSR_SPMPADDR14
#define CSR_SPMPADDR12
#define CSR_SPMPADDR1
#define CSR_SPMPADDR8
#define CSR_SPMPADDR2
#define CSR_SPMPADDR7
#define CSR_SPMPADDR6
#define CSR_SPMPADDR13
#define CSR_SPMPADDR3
#define CSR_SPMPADDR15
#define CSR_SPMPADDR5
#define CSR_SPMPADDR4

References __RV_CSR_READ, CSR_SPMPADDR0, CSR_SPMPADDR1, CSR_SPMPADDR10, CSR_SPMPADDR11, CSR_SPMPADDR12, CSR_SPMPADDR13, CSR_SPMPADDR14, CSR_SPMPADDR15, CSR_SPMPADDR2, CSR_SPMPADDR3, CSR_SPMPADDR4, CSR_SPMPADDR5, CSR_SPMPADDR6, CSR_SPMPADDR7, CSR_SPMPADDR8, and CSR_SPMPADDR9.

Referenced by __get_sPMPENTRYx().

◆ __get_sPMPCFGx()

__STATIC_INLINE rv_csr_t __get_sPMPCFGx ( uint32_t  csr_idx)

Get sPMPCFGx Register by csr index.

Return the content of the sPMPCFGx Register.

Parameters
[in]csr_idxsPMPCFG CSR index(0-3)
Returns
sPMPCFGx Register value
Remarks
  • For RV64, only csr_idx = 0 and csr_idx = 2 is allowed. spmpcfg0 and spmpcfg2 hold the configurations for the 16 sPMP entries, spmpcfg1 and spmpcfg3 are illegal
  • For RV32, spmpcfg0–spmpcfg3, hold the configurations spmp0cfg–spmp15cfg for the 16 sPMP entries

Definition at line 95 of file core_feature_spmp.h.

96 {
97  switch (csr_idx) {
98  case 0: return __RV_CSR_READ(CSR_SPMPCFG0);
99  case 1: return __RV_CSR_READ(CSR_SPMPCFG1);
100  case 2: return __RV_CSR_READ(CSR_SPMPCFG2);
101  case 3: return __RV_CSR_READ(CSR_SPMPCFG3);
102  default: return 0;
103  }
104 }
#define CSR_SPMPCFG3
#define CSR_SPMPCFG0
#define CSR_SPMPCFG2
#define CSR_SPMPCFG1

References __RV_CSR_READ, CSR_SPMPCFG0, CSR_SPMPCFG1, CSR_SPMPCFG2, and CSR_SPMPCFG3.

Referenced by __get_sPMPENTRYx(), __get_sPMPxCFG(), __set_sPMPENTRYx(), and __set_sPMPxCFG().

◆ __get_sPMPENTRYx()

__STATIC_INLINE int __get_sPMPENTRYx ( unsigned int  entry_idx,
spmp_config spmp_cfg 
)

Get sPMP entry by entry idx.

Write the given value to the sPMPxCFG Register and sPMPADDRx.

Parameters
[in]entry_idxsPMP entry index(0-15)
[out]spmp_cfgstructure of L, U, X, W, R, A field of sPMP configuration register, memory region base address and size of memory region as power of 2
Returns
-1 failure, else 0 success
Remarks
  • If the size of memory region is 2^12(4KB) range, spmp_cfg->order makes 12, and the like.
  • TOR of A field in PMP configuration register is not considered here.

Definition at line 336 of file core_feature_spmp.h.

337 {
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;
342  /* check parameters */
343  if (entry_idx >= __SPMP_ENTRY_NUM || !spmp_cfg) return -1;
344 
345  /* calculate sPMP register and offset */
346 #if __RISCV_XLEN == 32
347  csr_cfg_num = 4;
348  cfg_csr_idx = entry_idx >> 2;
349 #elif __RISCV_XLEN == 64
350  csr_cfg_num = 8;
351  cfg_csr_idx = (entry_idx >> 2) & ~1;
352 #else
353 // TODO Add RV128 Handling
354  return -1;
355 #endif
356 
357  cfg_shift = (entry_idx & (csr_cfg_num - 1)) << 3;
358  addr_csr_idx = entry_idx;
359 
360  /* decode sPMP config */
361  cfgmask = (0xFFUL << cfg_shift);
362  spmpcfg = (__get_sPMPCFGx(cfg_csr_idx) & cfgmask);
363  prot = spmpcfg >> cfg_shift;
364 
365  /* decode sPMP address */
366  spmpaddr = __get_sPMPADDRx(addr_csr_idx);
367  if (SPMP_A_NAPOT == (prot & SPMP_A)) {
368  t1 = __CTZ(~spmpaddr);
369  addr = (spmpaddr & ~((1UL << t1) - 1)) << SPMP_SHIFT;
370  len = (t1 + SPMP_SHIFT + 1);
371  } else {
372  addr = spmpaddr << SPMP_SHIFT;
373  len = SPMP_SHIFT;
374  }
375 
376  /* return details */
377  spmp_cfg->protection = prot;
378  spmp_cfg->base_addr = addr;
379  spmp_cfg->order = len;
380 
381  return 0;
382 }
__STATIC_FORCEINLINE unsigned long __CTZ(unsigned long data)
Count tailing zero.
#define SPMP_A
#define SPMP_A_NAPOT
#define SPMP_SHIFT
__STATIC_INLINE rv_csr_t __get_sPMPADDRx(uint32_t csr_idx)
Get sPMPADDRx Register by CSR index.
__STATIC_INLINE rv_csr_t __get_sPMPCFGx(uint32_t csr_idx)
Get sPMPCFGx Register by csr 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 ...

References __CTZ(), __get_sPMPADDRx(), __get_sPMPCFGx(), spmp_config::base_addr, spmp_config::order, spmp_config::protection, SPMP_A, SPMP_A_NAPOT, and SPMP_SHIFT.

◆ __get_sPMPxCFG()

__STATIC_INLINE uint8_t __get_sPMPxCFG ( uint32_t  entry_idx)

Get 8bit sPMPxCFG Register by sPMP entry index.

Return the content of the sPMPxCFG Register.

Parameters
[in]entry_idxsPMP region index(0-15)
Returns
sPMPxCFG Register value

Definition at line 135 of file core_feature_spmp.h.

136 {
137  rv_csr_t spmpcfgx = 0;
138  uint8_t csr_cfg_num = 0;
139  uint16_t csr_idx = 0;
140  uint16_t cfg_shift = 0;
141 
142  if (entry_idx >= __SPMP_ENTRY_NUM) return 0;
143 
144 #if __RISCV_XLEN == 32
145  csr_cfg_num = 4;
146  csr_idx = entry_idx >> 2;
147 #elif __RISCV_XLEN == 64
148  csr_cfg_num = 8;
149  /* For RV64, spmpcfg0 and spmpcfg2 each hold 8 sPMP entries, align by 2 */
150  csr_idx = (entry_idx >> 2) & ~1;
151 #else
152  // TODO Add RV128 Handling
153  return 0;
154 #endif
155  spmpcfgx = __get_sPMPCFGx(csr_idx);
156  /*
157  * first get specific spmpxcfg's order in one CSR composed of csr_cfg_num spmpxcfgs,
158  * then get spmpxcfg's bit position in one CSR by left shift 3(each spmpxcfg size is one byte)
159  */
160  cfg_shift = (entry_idx & (csr_cfg_num - 1)) << 3;
161 
162  /* read specific spmpxcfg register value */
163  return (uint8_t)(__RV_EXTRACT_FIELD(spmpcfgx, 0xFF << cfg_shift));
164 }
unsigned long rv_csr_t
Type of Control and Status Register(CSR), depends on the XLEN defined in RISC-V.

References __get_sPMPCFGx().

◆ __set_SMPUSWITCHx()

__STATIC_INLINE void __set_SMPUSWITCHx ( uint64_t  val)

Set SMPU each entry's on/off status.

Write the given value to the SMPUSWITCHx Register.

Parameters
[in]valactivate each entry(max to 64) or not
Remarks
  • Each bit of this register holds on/off status of the corresponding SMPU entry respectively.
  • An SMPU entry is activated only when both corresponding bits in smpuswitch and A field of smpuicfg are set. (i.e., smpuswitch[i] & smpu[i]cfg.A).

Definition at line 407 of file core_feature_spmp.h.

408 {
409 #if __RISCV_XLEN == 32
410  __RV_CSR_WRITE(CSR_SMPUSWITCH0, (uint32_t)val);
411  __RV_CSR_WRITE(CSR_SMPUSWITCH1, (uint32_t)(val >> 32));
412 #elif __RISCV_XLEN == 64
414 #else
415  // TODO Add RV128 Handling
416 #endif
417 }
#define __RV_CSR_WRITE(csr, val)
CSR operation Macro for csrw instruction.

References __RV_CSR_WRITE, CSR_SMPUSWITCH0, and CSR_SMPUSWITCH1.

◆ __set_sPMPADDRx()

__STATIC_INLINE void __set_sPMPADDRx ( uint32_t  csr_idx,
rv_csr_t  spmpaddr 
)

Set sPMPADDRx by CSR index.

Write the given value to the sPMPADDRx Register.

Parameters
[in]csr_idxsPMP region CSR index(0-15)
[in]spmpaddrsPMPADDRx Register value to set

Definition at line 241 of file core_feature_spmp.h.

242 {
243  switch (csr_idx) {
244  case 0: __RV_CSR_WRITE(CSR_SPMPADDR0, spmpaddr); break;
245  case 1: __RV_CSR_WRITE(CSR_SPMPADDR1, spmpaddr); break;
246  case 2: __RV_CSR_WRITE(CSR_SPMPADDR2, spmpaddr); break;
247  case 3: __RV_CSR_WRITE(CSR_SPMPADDR3, spmpaddr); break;
248  case 4: __RV_CSR_WRITE(CSR_SPMPADDR4, spmpaddr); break;
249  case 5: __RV_CSR_WRITE(CSR_SPMPADDR5, spmpaddr); break;
250  case 6: __RV_CSR_WRITE(CSR_SPMPADDR6, spmpaddr); break;
251  case 7: __RV_CSR_WRITE(CSR_SPMPADDR7, spmpaddr); break;
252  case 8: __RV_CSR_WRITE(CSR_SPMPADDR8, spmpaddr); break;
253  case 9: __RV_CSR_WRITE(CSR_SPMPADDR9, spmpaddr); break;
254  case 10: __RV_CSR_WRITE(CSR_SPMPADDR10, spmpaddr); break;
255  case 11: __RV_CSR_WRITE(CSR_SPMPADDR11, spmpaddr); break;
256  case 12: __RV_CSR_WRITE(CSR_SPMPADDR12, spmpaddr); break;
257  case 13: __RV_CSR_WRITE(CSR_SPMPADDR13, spmpaddr); break;
258  case 14: __RV_CSR_WRITE(CSR_SPMPADDR14, spmpaddr); break;
259  case 15: __RV_CSR_WRITE(CSR_SPMPADDR15, spmpaddr); break;
260  default: return;
261  }
262 }

References __RV_CSR_WRITE, CSR_SPMPADDR0, CSR_SPMPADDR1, CSR_SPMPADDR10, CSR_SPMPADDR11, CSR_SPMPADDR12, CSR_SPMPADDR13, CSR_SPMPADDR14, CSR_SPMPADDR15, CSR_SPMPADDR2, CSR_SPMPADDR3, CSR_SPMPADDR4, CSR_SPMPADDR5, CSR_SPMPADDR6, CSR_SPMPADDR7, CSR_SPMPADDR8, and CSR_SPMPADDR9.

Referenced by __set_sPMPENTRYx().

◆ __set_sPMPCFGx()

__STATIC_INLINE void __set_sPMPCFGx ( uint32_t  csr_idx,
rv_csr_t  spmpcfg 
)

Set sPMPCFGx by csr index.

Write the given value to the sPMPCFGx Register.

Parameters
[in]csr_idxsPMPCFG CSR index(0-3)
[in]spmpcfgsPMPCFGx Register value to set
Remarks
  • For RV64, only csr_idx = 0 and csr_idx = 2 is allowed. spmpcfg0 and spmpcfg2 hold the configurations for the 16 sPMP entries, spmpcfg1 and spmpcfg3 are illegal
  • For RV32, spmpcfg0–spmpcfg3, hold the configurations spmp0cfg–spmp15cfg for the 16 sPMP entries

Definition at line 118 of file core_feature_spmp.h.

119 {
120  switch (csr_idx) {
121  case 0: __RV_CSR_WRITE(CSR_SPMPCFG0, spmpcfg); break;
122  case 1: __RV_CSR_WRITE(CSR_SPMPCFG1, spmpcfg); break;
123  case 2: __RV_CSR_WRITE(CSR_SPMPCFG2, spmpcfg); break;
124  case 3: __RV_CSR_WRITE(CSR_SPMPCFG3, spmpcfg); break;
125  default: return;
126  }
127 }

References __RV_CSR_WRITE, CSR_SPMPCFG0, CSR_SPMPCFG1, CSR_SPMPCFG2, and CSR_SPMPCFG3.

Referenced by __set_sPMPENTRYx(), and __set_sPMPxCFG().

◆ __set_sPMPENTRYx()

__STATIC_INLINE void __set_sPMPENTRYx ( uint32_t  entry_idx,
const spmp_config spmp_cfg 
)

Set sPMP entry by entry idx.

Write the given value to the sPMPxCFG Register and sPMPADDRx.

Parameters
[in]entry_idxsPMP entry index(0-15)
[in]spmp_cfgstructure of L,U,X,W,R field of sPMP configuration register, memory region base address and size of memory region as power of 2
Remarks
  • If the size of memory region is 2^12(4KB) range, spmp_cfg->order makes 12, and the like.
  • Suppose the size of memory region is 2^X bytes range, if X >=3, the NA4 mode is not selectable, NAPOT is selected.
  • TOR of A field in sPMP configuration register is not considered here.

Definition at line 275 of file core_feature_spmp.h.

276 {
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;
281  /* check parameters */
282  if (entry_idx >= __SPMP_ENTRY_NUM || spmp_cfg->order > __RISCV_XLEN || spmp_cfg->order < SPMP_SHIFT) return;
283 
284  /* calculate sPMP register and offset */
285 #if __RISCV_XLEN == 32
286  csr_cfg_num = 4;
287  cfg_csr_idx = (entry_idx >> 2);
288 #elif __RISCV_XLEN == 64
289  csr_cfg_num = 8;
290  cfg_csr_idx = ((entry_idx >> 2)) & ~1;
291 #else
292  // TODO Add RV128 Handling
293  return;
294 #endif
295  /*
296  * first get specific spmpxcfg's order in one CSR composed of csr_cfg_num spmpxcfgs,
297  * then get spmpxcfg's bit position in one CSR by left shift 3, each spmpxcfg size is one byte
298  */
299  cfg_shift = (entry_idx & (csr_cfg_num - 1)) << 3;
300  addr_csr_idx = entry_idx;
301 
302  /* encode sPMP config */
303  protection = (unsigned long)spmp_cfg->protection;
304  protection |= (SPMP_SHIFT == spmp_cfg->order) ? SPMP_A_NA4 : SPMP_A_NAPOT;
305  cfgmask = ~(0xFFUL << cfg_shift);
306  spmpcfg = (__get_sPMPCFGx(cfg_csr_idx) & cfgmask);
307  spmpcfg |= ((protection << cfg_shift) & ~cfgmask);
308 
309  /* encode sPMP address */
310  if (SPMP_SHIFT == spmp_cfg->order) { /* NA4 */
311  spmpaddr = (spmp_cfg->base_addr >> SPMP_SHIFT);
312  } else { /* NAPOT */
313  addrmask = (1UL << (spmp_cfg->order - SPMP_SHIFT)) - 1;
314  spmpaddr = ((spmp_cfg->base_addr >> SPMP_SHIFT) & ~addrmask);
315  spmpaddr |= (addrmask >> 1);
316  }
317  /*
318  * write csrs, update the address first, in case the entry is locked that
319  * we won't be able to modify it after we set the config csr.
320  */
321  __set_sPMPADDRx(addr_csr_idx, spmpaddr);
322  __set_sPMPCFGx(cfg_csr_idx, spmpcfg);
323 }
#define SPMP_A_NA4
#define __RISCV_XLEN
Refer to the width of an integer register in bits(either 32 or 64)
__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.

References __get_sPMPCFGx(), __RISCV_XLEN, __set_sPMPADDRx(), __set_sPMPCFGx(), spmp_config::base_addr, spmp_config::order, spmp_config::protection, SPMP_A_NA4, SPMP_A_NAPOT, and SPMP_SHIFT.

◆ __set_sPMPxCFG()

__STATIC_INLINE void __set_sPMPxCFG ( uint32_t  entry_idx,
uint8_t  spmpxcfg 
)

Set 8bit sPMPxCFG by spmp entry index.

Set the given spmpxcfg value to the sPMPxCFG Register.

Parameters
[in]entry_idxsPMPx region index(0-15)
[in]spmpxcfgsPMPxCFG register value to set
Remarks
  • For RV32, 4 spmpxcfgs are densely packed into one CSR in order For RV64, 8 spmpxcfgs are densely packed into one CSR in order

Definition at line 175 of file core_feature_spmp.h.

176 {
177  rv_csr_t spmpcfgx = 0;
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;
182 
183 #if __RISCV_XLEN == 32
184  csr_cfg_num = 4;
185  csr_idx = entry_idx >> 2;
186 #elif __RISCV_XLEN == 64
187  csr_cfg_num = 8;
188  /* For RV64, spmpcfg0 and spmpcfg2 each hold 8 sPMP entries, align by 2 */
189  csr_idx = (entry_idx >> 2) & ~1;
190 #else
191  // TODO Add RV128 Handling
192  return;
193 #endif
194  /* read specific spmpcfgx register value */
195  spmpcfgx = __get_sPMPCFGx(csr_idx);
196  /*
197  * first get specific spmpxcfg's order in one CSR composed of csr_cfg_num spmpxcfgs,
198  * then get spmpxcfg's bit position in one CSR by left shift 3(each spmpxcfg size is one byte)
199  */
200  cfg_shift = (entry_idx & (csr_cfg_num - 1)) << 3;
201 
202  spmpcfgx = __RV_INSERT_FIELD(spmpcfgx, 0xFFUL << cfg_shift, spmpxcfg);
203  __set_sPMPCFGx(csr_idx, spmpcfgx);
204 }

References __get_sPMPCFGx(), and __set_sPMPCFGx().