NMSIS-Core  Version 1.2.0
NMSIS-Core support for Nuclei processor-based devices
PMP Functions

Functions that related to the RISCV Phyiscal Memory Protection. More...

Data Structures

struct  PMP_CONFIG
 

Functions

__STATIC_INLINE rv_csr_t __get_PMPCFGx (uint32_t csr_idx)
 Get PMPCFGx Register by csr index. More...
 
__STATIC_INLINE void __set_PMPCFGx (uint32_t csr_idx, rv_csr_t pmpcfg)
 Set PMPCFGx by csr index. More...
 
__STATIC_INLINE uint8_t __get_PMPxCFG (uint32_t entry_idx)
 Get 8bit PMPxCFG Register by PMP entry index. More...
 
__STATIC_INLINE void __set_PMPxCFG (uint32_t entry_idx, uint8_t pmpxcfg)
 Set 8bit PMPxCFG by pmp entry index. More...
 
__STATIC_INLINE rv_csr_t __get_PMPADDRx (uint32_t csr_idx)
 Get PMPADDRx Register by CSR index. More...
 
__STATIC_INLINE void __set_PMPADDRx (uint32_t csr_idx, rv_csr_t pmpaddr)
 Set PMPADDRx by CSR index. More...
 
__STATIC_INLINE void __set_PMPENTRYx (uint32_t entry_idx, const pmp_config *pmp_cfg)
 Set PMP entry by entry idx. More...
 
__STATIC_INLINE int __get_PMPENTRYx (unsigned int entry_idx, pmp_config *pmp_cfg)
 Get PMP entry by entry idx. More...
 

Detailed Description

Functions that related to the RISCV Phyiscal Memory Protection.

Optional physical memory protection (PMP) unit provides per-hart machine-mode control registers to allow physical memory access privileges (read, write, execute) to be specified for each physical memory region.

The PMP can supports region access control settings as small as four bytes.

Function Documentation

◆ __get_PMPADDRx()

__STATIC_INLINE rv_csr_t __get_PMPADDRx ( uint32_t  csr_idx)

Get PMPADDRx Register by CSR index.

Return the content of the PMPADDRx Register.

Parameters
[in]csr_idxPMP region CSR index(0-15)
Returns
PMPADDRx Register value

Definition at line 206 of file core_feature_pmp.h.

207 {
208  switch (csr_idx) {
209  case 0: return __RV_CSR_READ(CSR_PMPADDR0);
210  case 1: return __RV_CSR_READ(CSR_PMPADDR1);
211  case 2: return __RV_CSR_READ(CSR_PMPADDR2);
212  case 3: return __RV_CSR_READ(CSR_PMPADDR3);
213  case 4: return __RV_CSR_READ(CSR_PMPADDR4);
214  case 5: return __RV_CSR_READ(CSR_PMPADDR5);
215  case 6: return __RV_CSR_READ(CSR_PMPADDR6);
216  case 7: return __RV_CSR_READ(CSR_PMPADDR7);
217  case 8: return __RV_CSR_READ(CSR_PMPADDR8);
218  case 9: return __RV_CSR_READ(CSR_PMPADDR9);
219  case 10: return __RV_CSR_READ(CSR_PMPADDR10);
220  case 11: return __RV_CSR_READ(CSR_PMPADDR11);
221  case 12: return __RV_CSR_READ(CSR_PMPADDR12);
222  case 13: return __RV_CSR_READ(CSR_PMPADDR13);
223  case 14: return __RV_CSR_READ(CSR_PMPADDR14);
224  case 15: return __RV_CSR_READ(CSR_PMPADDR15);
225  default: return 0;
226  }
227 }

References __RV_CSR_READ, CSR_PMPADDR0, CSR_PMPADDR1, CSR_PMPADDR10, CSR_PMPADDR11, CSR_PMPADDR12, CSR_PMPADDR13, CSR_PMPADDR14, CSR_PMPADDR15, CSR_PMPADDR2, CSR_PMPADDR3, CSR_PMPADDR4, CSR_PMPADDR5, CSR_PMPADDR6, CSR_PMPADDR7, CSR_PMPADDR8, and CSR_PMPADDR9.

Referenced by __get_PMPENTRYx().

◆ __get_PMPCFGx()

__STATIC_INLINE rv_csr_t __get_PMPCFGx ( uint32_t  csr_idx)

Get PMPCFGx Register by csr index.

Return the content of the PMPCFGx Register.

Parameters
[in]csr_idxPMPCFG CSR index(0-3)
Returns
PMPCFGx Register value
Remarks
  • For RV64, only csr_idx = 0 and csr_idx = 2 is allowed. pmpcfg0 and pmpcfg2 hold the configurations for the 16 PMP entries, pmpcfg1 and pmpcfg3 are illegal
  • For RV32, pmpcfg0–pmpcfg3, hold the configurations pmp0cfg–pmp15cfg for the 16 PMP entries

Definition at line 89 of file core_feature_pmp.h.

90 {
91  switch (csr_idx) {
92  case 0: return __RV_CSR_READ(CSR_PMPCFG0);
93  case 1: return __RV_CSR_READ(CSR_PMPCFG1);
94  case 2: return __RV_CSR_READ(CSR_PMPCFG2);
95  case 3: return __RV_CSR_READ(CSR_PMPCFG3);
96  default: return 0;
97  }
98 }

References __RV_CSR_READ, CSR_PMPCFG0, CSR_PMPCFG1, CSR_PMPCFG2, and CSR_PMPCFG3.

Referenced by __get_PMPENTRYx(), __get_PMPxCFG(), __set_PMPENTRYx(), and __set_PMPxCFG().

◆ __get_PMPENTRYx()

__STATIC_INLINE int __get_PMPENTRYx ( unsigned int  entry_idx,
pmp_config *  pmp_cfg 
)

Get PMP entry by entry idx.

Write the given value to the PMPxCFG Register and PMPADDRx.

Parameters
[in]entry_idxPMP entry index(0-15)
[out]pmp_cfgstructure of L, X, W, R, A field of PMP 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, pmp_cfg->order makes 12, and the like.
  • TOR of A field in PMP configuration register is not considered here.

Definition at line 330 of file core_feature_pmp.h.

331 {
332  unsigned int cfg_shift, cfg_csr_idx, addr_csr_idx = 0;
333  unsigned long cfgmask, pmpcfg, prot = 0;
334  unsigned long t1, addr, pmpaddr, len = 0;
335  uint8_t csr_cfg_num = 0;
336  /* check parameters */
337  if (entry_idx >= __PMP_ENTRY_NUM || !pmp_cfg) return -1;
338 
339  /* calculate PMP register and offset */
340 #if __RISCV_XLEN == 32
341  csr_cfg_num = 4;
342  cfg_csr_idx = entry_idx >> 2;
343 #elif __RISCV_XLEN == 64
344  csr_cfg_num = 8;
345  cfg_csr_idx = (entry_idx>> 2) & ~1;
346 #else
347 // TODO Add RV128 Handling
348  return -1;
349 #endif
350 
351  cfg_shift = (entry_idx & (csr_cfg_num - 1)) << 3;
352  addr_csr_idx = entry_idx;
353 
354  /* decode PMP config */
355  cfgmask = (0xFFUL << cfg_shift);
356  pmpcfg = (__get_PMPCFGx(cfg_csr_idx) & cfgmask);
357  prot = pmpcfg >> cfg_shift;
358 
359  /* decode PMP address */
360  pmpaddr = __get_PMPADDRx(addr_csr_idx);
361  if (PMP_A_NAPOT == (prot & PMP_A)) {
362  t1 = __CTZ(~pmpaddr);
363  addr = (pmpaddr & ~((1UL << t1) - 1)) << PMP_SHIFT;
364  len = (t1 + PMP_SHIFT + 1);
365  } else {
366  addr = pmpaddr << PMP_SHIFT;
367  len = PMP_SHIFT;
368  }
369 
370  /* return details */
371  pmp_cfg->protection = prot;
372  pmp_cfg->base_addr = addr;
373  pmp_cfg->order = len;
374 
375  return 0;
376 }

References __CTZ(), __get_PMPADDRx(), __get_PMPCFGx(), PMP_A, PMP_A_NAPOT, and PMP_SHIFT.

◆ __get_PMPxCFG()

__STATIC_INLINE uint8_t __get_PMPxCFG ( uint32_t  entry_idx)

Get 8bit PMPxCFG Register by PMP entry index.

Return the content of the PMPxCFG Register.

Parameters
[in]entry_idxPMP region index(0-15)
Returns
PMPxCFG Register value

Definition at line 129 of file core_feature_pmp.h.

130 {
131  rv_csr_t pmpcfgx = 0;
132  uint8_t csr_cfg_num = 0;
133  uint16_t csr_idx = 0;
134  uint16_t cfg_shift = 0;
135 
136  if (entry_idx >= __PMP_ENTRY_NUM) return 0;
137 
138 #if __RISCV_XLEN == 32
139  csr_cfg_num = 4;
140  csr_idx = entry_idx >> 2;
141 #elif __RISCV_XLEN == 64
142  csr_cfg_num = 8;
143  /* For RV64, pmpcfg0 and pmpcfg2 each hold 8 PMP entries, align by 2 */
144  csr_idx = (entry_idx >> 2) & ~1;
145 #else
146  // TODO Add RV128 Handling
147  return 0;
148 #endif
149  pmpcfgx = __get_PMPCFGx(csr_idx);
150  /*
151  * first get specific pmpxcfg's order in one CSR composed of csr_cfg_num pmpxcfgs,
152  * then get pmpxcfg's bit position in one CSR by left shift 3(each pmpxcfg size is one byte)
153  */
154  cfg_shift = (entry_idx & (csr_cfg_num - 1)) << 3;
155 
156  /* read specific pmpxcfg register value */
157  return (uint8_t)(__RV_EXTRACT_FIELD(pmpcfgx, 0xFF << cfg_shift));
158 }

References __get_PMPCFGx().

◆ __set_PMPADDRx()

__STATIC_INLINE void __set_PMPADDRx ( uint32_t  csr_idx,
rv_csr_t  pmpaddr 
)

Set PMPADDRx by CSR index.

Write the given value to the PMPADDRx Register.

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

Definition at line 235 of file core_feature_pmp.h.

236 {
237  switch (csr_idx) {
238  case 0: __RV_CSR_WRITE(CSR_PMPADDR0, pmpaddr); break;
239  case 1: __RV_CSR_WRITE(CSR_PMPADDR1, pmpaddr); break;
240  case 2: __RV_CSR_WRITE(CSR_PMPADDR2, pmpaddr); break;
241  case 3: __RV_CSR_WRITE(CSR_PMPADDR3, pmpaddr); break;
242  case 4: __RV_CSR_WRITE(CSR_PMPADDR4, pmpaddr); break;
243  case 5: __RV_CSR_WRITE(CSR_PMPADDR5, pmpaddr); break;
244  case 6: __RV_CSR_WRITE(CSR_PMPADDR6, pmpaddr); break;
245  case 7: __RV_CSR_WRITE(CSR_PMPADDR7, pmpaddr); break;
246  case 8: __RV_CSR_WRITE(CSR_PMPADDR8, pmpaddr); break;
247  case 9: __RV_CSR_WRITE(CSR_PMPADDR9, pmpaddr); break;
248  case 10: __RV_CSR_WRITE(CSR_PMPADDR10, pmpaddr); break;
249  case 11: __RV_CSR_WRITE(CSR_PMPADDR11, pmpaddr); break;
250  case 12: __RV_CSR_WRITE(CSR_PMPADDR12, pmpaddr); break;
251  case 13: __RV_CSR_WRITE(CSR_PMPADDR13, pmpaddr); break;
252  case 14: __RV_CSR_WRITE(CSR_PMPADDR14, pmpaddr); break;
253  case 15: __RV_CSR_WRITE(CSR_PMPADDR15, pmpaddr); break;
254  default: return;
255  }
256 }

References __RV_CSR_WRITE, CSR_PMPADDR0, CSR_PMPADDR1, CSR_PMPADDR10, CSR_PMPADDR11, CSR_PMPADDR12, CSR_PMPADDR13, CSR_PMPADDR14, CSR_PMPADDR15, CSR_PMPADDR2, CSR_PMPADDR3, CSR_PMPADDR4, CSR_PMPADDR5, CSR_PMPADDR6, CSR_PMPADDR7, CSR_PMPADDR8, and CSR_PMPADDR9.

Referenced by __set_PMPENTRYx().

◆ __set_PMPCFGx()

__STATIC_INLINE void __set_PMPCFGx ( uint32_t  csr_idx,
rv_csr_t  pmpcfg 
)

Set PMPCFGx by csr index.

Write the given value to the PMPCFGx Register.

Parameters
[in]csr_idxPMPCFG CSR index(0-3)
[in]pmpcfgPMPCFGx Register value to set
Remarks
  • For RV64, only csr_idx = 0 and csr_idx = 2 is allowed. pmpcfg0 and pmpcfg2 hold the configurations for the 16 PMP entries, pmpcfg1 and pmpcfg3 are illegal
  • For RV32, pmpcfg0–pmpcfg3, hold the configurations pmp0cfg–pmp15cfg for the 16 PMP entries

Definition at line 112 of file core_feature_pmp.h.

113 {
114  switch (csr_idx) {
115  case 0: __RV_CSR_WRITE(CSR_PMPCFG0, pmpcfg); break;
116  case 1: __RV_CSR_WRITE(CSR_PMPCFG1, pmpcfg); break;
117  case 2: __RV_CSR_WRITE(CSR_PMPCFG2, pmpcfg); break;
118  case 3: __RV_CSR_WRITE(CSR_PMPCFG3, pmpcfg); break;
119  default: return;
120  }
121 }

References __RV_CSR_WRITE, CSR_PMPCFG0, CSR_PMPCFG1, CSR_PMPCFG2, and CSR_PMPCFG3.

Referenced by __set_PMPENTRYx(), and __set_PMPxCFG().

◆ __set_PMPENTRYx()

__STATIC_INLINE void __set_PMPENTRYx ( uint32_t  entry_idx,
const pmp_config *  pmp_cfg 
)

Set PMP entry by entry idx.

Write the given value to the PMPxCFG Register and PMPADDRx.

Parameters
[in]entry_idxPMP entry index(0-15)
[in]pmp_cfgstructure of L, X, W, R field of PMP 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, pmp_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 PMP configuration register is not considered here.

Definition at line 269 of file core_feature_pmp.h.

270 {
271  unsigned int cfg_shift, cfg_csr_idx, addr_csr_idx = 0;
272  unsigned long cfgmask, addrmask = 0;
273  unsigned long pmpcfg, pmpaddr = 0;
274  uint8_t protection, csr_cfg_num = 0;
275  /* check parameters */
276  if (entry_idx >= __PMP_ENTRY_NUM || pmp_cfg->order > __RISCV_XLEN || pmp_cfg->order < PMP_SHIFT) return;
277 
278  /* calculate PMP register and offset */
279 #if __RISCV_XLEN == 32
280  csr_cfg_num = 4;
281  cfg_csr_idx = (entry_idx >> 2);
282 #elif __RISCV_XLEN == 64
283  csr_cfg_num = 8;
284  cfg_csr_idx = ((entry_idx >> 2)) & ~1;
285 #else
286  // TODO Add RV128 Handling
287  return;
288 #endif
289  /*
290  * first get specific pmpxcfg's order in one CSR composed of csr_cfg_num pmpxcfgs,
291  * then get pmpxcfg's bit position in one CSR by left shift 3, each pmpxcfg size is one byte
292  */
293  cfg_shift = (entry_idx & (csr_cfg_num - 1)) << 3;
294  addr_csr_idx = entry_idx;
295 
296  /* encode PMP config */
297  protection = pmp_cfg->protection;
298  protection |= (PMP_SHIFT == pmp_cfg->order) ? PMP_A_NA4 : PMP_A_NAPOT;
299  cfgmask = ~(0xFFUL << cfg_shift);
300  pmpcfg = (__get_PMPCFGx(cfg_csr_idx) & cfgmask);
301  pmpcfg |= ((protection << cfg_shift) & ~cfgmask);
302 
303  /* encode PMP address */
304  if (PMP_SHIFT == pmp_cfg->order) { /* NA4 */
305  pmpaddr = (pmp_cfg->base_addr >> PMP_SHIFT);
306  } else { /* NAPOT */
307  addrmask = (1UL << (pmp_cfg->order - PMP_SHIFT)) - 1;
308  pmpaddr = ((pmp_cfg->base_addr >> PMP_SHIFT) & ~addrmask);
309  pmpaddr |= (addrmask >> 1);
310  }
311  /*
312  * write csrs, update the address first, in case the entry is locked that
313  * we won't be able to modify it after we set the config csr.
314  */
315  __set_PMPADDRx(addr_csr_idx, pmpaddr);
316  __set_PMPCFGx(cfg_csr_idx, pmpcfg);
317 }

References __get_PMPCFGx(), __RISCV_XLEN, __set_PMPADDRx(), __set_PMPCFGx(), PMP_A_NA4, PMP_A_NAPOT, and PMP_SHIFT.

◆ __set_PMPxCFG()

__STATIC_INLINE void __set_PMPxCFG ( uint32_t  entry_idx,
uint8_t  pmpxcfg 
)

Set 8bit PMPxCFG by pmp entry index.

Set the given pmpxcfg value to the PMPxCFG Register.

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

Definition at line 169 of file core_feature_pmp.h.

170 {
171  rv_csr_t pmpcfgx = 0;
172  uint8_t csr_cfg_num = 0;
173  uint16_t csr_idx = 0;
174  uint16_t cfg_shift = 0;
175  if (entry_idx >= __PMP_ENTRY_NUM) return;
176 
177 #if __RISCV_XLEN == 32
178  csr_cfg_num = 4;
179  csr_idx = entry_idx >> 2;
180 #elif __RISCV_XLEN == 64
181  csr_cfg_num = 8;
182  /* For RV64, pmpcfg0 and pmpcfg2 each hold 8 PMP entries, align by 2 */
183  csr_idx = (entry_idx >> 2) & ~1;
184 #else
185  // TODO Add RV128 Handling
186  return;
187 #endif
188  /* read specific pmpcfgx register value */
189  pmpcfgx = __get_PMPCFGx(csr_idx);
190  /*
191  * first get specific pmpxcfg's order in one CSR composed of csr_cfg_num pmpxcfgs,
192  * then get pmpxcfg's bit position in one CSR by left shift 3(each pmpxcfg size is one byte)
193  */
194  cfg_shift = (entry_idx & (csr_cfg_num - 1)) << 3;
195 
196  pmpcfgx = __RV_INSERT_FIELD(pmpcfgx, 0xFFUL << cfg_shift, pmpxcfg);
197  __set_PMPCFGx(csr_idx, pmpcfgx);
198 }

References __get_PMPCFGx(), and __set_PMPCFGx().

CSR_PMPADDR8
#define CSR_PMPADDR8
Definition: riscv_encoding.h:611
CSR_PMPADDR4
#define CSR_PMPADDR4
Definition: riscv_encoding.h:607
PMP_A_NA4
#define PMP_A_NA4
Definition: riscv_encoding.h:393
CSR_PMPADDR10
#define CSR_PMPADDR10
Definition: riscv_encoding.h:613
__CTZ
__STATIC_FORCEINLINE unsigned long __CTZ(unsigned long data)
Count tailing zero.
Definition: core_compatiable.h:235
__RV_CSR_WRITE
#define __RV_CSR_WRITE(csr, val)
CSR operation Macro for csrw instruction.
Definition: core_feature_base.h:499
PMP_A_NAPOT
#define PMP_A_NAPOT
Definition: riscv_encoding.h:394
CSR_PMPADDR3
#define CSR_PMPADDR3
Definition: riscv_encoding.h:606
CSR_PMPADDR13
#define CSR_PMPADDR13
Definition: riscv_encoding.h:616
CSR_PMPCFG2
#define CSR_PMPCFG2
Definition: riscv_encoding.h:589
CSR_PMPADDR1
#define CSR_PMPADDR1
Definition: riscv_encoding.h:604
CSR_PMPADDR14
#define CSR_PMPADDR14
Definition: riscv_encoding.h:617
CSR_PMPADDR0
#define CSR_PMPADDR0
Definition: riscv_encoding.h:603
__get_PMPADDRx
__STATIC_INLINE rv_csr_t __get_PMPADDRx(uint32_t csr_idx)
Get PMPADDRx Register by CSR index.
Definition: core_feature_pmp.h:206
CSR_PMPCFG3
#define CSR_PMPCFG3
Definition: riscv_encoding.h:590
CSR_PMPADDR12
#define CSR_PMPADDR12
Definition: riscv_encoding.h:615
CSR_PMPADDR2
#define CSR_PMPADDR2
Definition: riscv_encoding.h:605
PMP_A
#define PMP_A
Definition: riscv_encoding.h:391
__get_PMPCFGx
__STATIC_INLINE rv_csr_t __get_PMPCFGx(uint32_t csr_idx)
Get PMPCFGx Register by csr index.
Definition: core_feature_pmp.h:89
CSR_PMPADDR5
#define CSR_PMPADDR5
Definition: riscv_encoding.h:608
__RV_CSR_READ
#define __RV_CSR_READ(csr)
CSR operation Macro for csrr instruction.
Definition: core_feature_base.h:481
PMP_SHIFT
#define PMP_SHIFT
Definition: riscv_encoding.h:397
CSR_PMPCFG1
#define CSR_PMPCFG1
Definition: riscv_encoding.h:588
CSR_PMPADDR15
#define CSR_PMPADDR15
Definition: riscv_encoding.h:618
CSR_PMPCFG0
#define CSR_PMPCFG0
Definition: riscv_encoding.h:587
CSR_PMPADDR7
#define CSR_PMPADDR7
Definition: riscv_encoding.h:610
__set_PMPADDRx
__STATIC_INLINE void __set_PMPADDRx(uint32_t csr_idx, rv_csr_t pmpaddr)
Set PMPADDRx by CSR index.
Definition: core_feature_pmp.h:235
__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_PMPADDR11
#define CSR_PMPADDR11
Definition: riscv_encoding.h:614
CSR_PMPADDR6
#define CSR_PMPADDR6
Definition: riscv_encoding.h:609
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_PMPADDR9
#define CSR_PMPADDR9
Definition: riscv_encoding.h:612
__set_PMPCFGx
__STATIC_INLINE void __set_PMPCFGx(uint32_t csr_idx, rv_csr_t pmpcfg)
Set PMPCFGx by csr index.
Definition: core_feature_pmp.h:112