NMSIS-Core  Version 1.3.1
NMSIS-Core support for Nuclei processor-based devices
sPMP Functions

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

Data Structures

struct  SPMP_CONFIG
 

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...
 

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.

Function Documentation

◆ __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 }

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 }

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 }

References __CTZ(), __get_sPMPADDRx(), __get_sPMPCFGx(), 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 }

References __get_sPMPCFGx().

◆ __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 }

References __get_sPMPCFGx(), __RISCV_XLEN, __set_sPMPADDRx(), __set_sPMPCFGx(), 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().

CSR_SPMPADDR12
#define CSR_SPMPADDR12
Definition: riscv_encoding.h:900
CSR_SPMPADDR9
#define CSR_SPMPADDR9
Definition: riscv_encoding.h:897
SPMP_A
#define SPMP_A
Definition: riscv_encoding.h:422
SPMP_A_NA4
#define SPMP_A_NA4
Definition: riscv_encoding.h:424
__CTZ
__STATIC_FORCEINLINE unsigned long __CTZ(unsigned long data)
Count tailing zero.
Definition: core_compatiable.h:255
CSR_SPMPADDR4
#define CSR_SPMPADDR4
Definition: riscv_encoding.h:892
__RV_CSR_WRITE
#define __RV_CSR_WRITE(csr, val)
CSR operation Macro for csrw instruction.
Definition: core_feature_base.h:532
CSR_SPMPADDR10
#define CSR_SPMPADDR10
Definition: riscv_encoding.h:898
__set_sPMPADDRx
__STATIC_INLINE void __set_sPMPADDRx(uint32_t csr_idx, rv_csr_t spmpaddr)
Set sPMPADDRx by CSR index.
Definition: core_feature_spmp.h:241
__set_sPMPCFGx
__STATIC_INLINE void __set_sPMPCFGx(uint32_t csr_idx, rv_csr_t spmpcfg)
Set sPMPCFGx by csr index.
Definition: core_feature_spmp.h:118
CSR_SPMPADDR0
#define CSR_SPMPADDR0
Definition: riscv_encoding.h:888
CSR_SPMPCFG3
#define CSR_SPMPCFG3
Definition: riscv_encoding.h:887
SPMP_SHIFT
#define SPMP_SHIFT
Definition: riscv_encoding.h:429
__get_sPMPCFGx
__STATIC_INLINE rv_csr_t __get_sPMPCFGx(uint32_t csr_idx)
Get sPMPCFGx Register by csr index.
Definition: core_feature_spmp.h:95
CSR_SPMPADDR15
#define CSR_SPMPADDR15
Definition: riscv_encoding.h:903
__get_sPMPADDRx
__STATIC_INLINE rv_csr_t __get_sPMPADDRx(uint32_t csr_idx)
Get sPMPADDRx Register by CSR index.
Definition: core_feature_spmp.h:212
__RV_CSR_READ
#define __RV_CSR_READ(csr)
CSR operation Macro for csrr instruction.
Definition: core_feature_base.h:514
CSR_SPMPADDR2
#define CSR_SPMPADDR2
Definition: riscv_encoding.h:890
CSR_SPMPADDR8
#define CSR_SPMPADDR8
Definition: riscv_encoding.h:896
CSR_SPMPADDR14
#define CSR_SPMPADDR14
Definition: riscv_encoding.h:902
CSR_SPMPADDR6
#define CSR_SPMPADDR6
Definition: riscv_encoding.h:894
CSR_SPMPADDR7
#define CSR_SPMPADDR7
Definition: riscv_encoding.h:895
CSR_SPMPCFG0
#define CSR_SPMPCFG0
Definition: riscv_encoding.h:884
CSR_SPMPADDR3
#define CSR_SPMPADDR3
Definition: riscv_encoding.h:891
CSR_SPMPCFG1
#define CSR_SPMPCFG1
Definition: riscv_encoding.h:885
CSR_SPMPCFG2
#define CSR_SPMPCFG2
Definition: riscv_encoding.h:886
__RISCV_XLEN
#define __RISCV_XLEN
Refer to the width of an integer register in bits(either 32 or 64)
Definition: core_feature_base.h:48
CSR_SPMPADDR1
#define CSR_SPMPADDR1
Definition: riscv_encoding.h:889
CSR_SPMPADDR13
#define CSR_SPMPADDR13
Definition: riscv_encoding.h:901
rv_csr_t
unsigned long rv_csr_t
Type of Control and Status Register(CSR), depends on the XLEN defined in RISC-V.
Definition: core_feature_base.h:55
CSR_SPMPADDR5
#define CSR_SPMPADDR5
Definition: riscv_encoding.h:893
SPMP_A_NAPOT
#define SPMP_A_NAPOT
Definition: riscv_encoding.h:425
CSR_SPMPADDR11
#define CSR_SPMPADDR11
Definition: riscv_encoding.h:899