Skip to content

Commit 12426b6

Browse files
committed
arch: riscv: Add function to clear all unlocked PMP entries
Introduce the new function `riscv_pmp_clear_all()` to securely reset the Physical Memory Protection (PMP) configuration. This function iterates through all configured PMP slots. For each entry, it checks if the Lock (L) bit is set. If the entry is not locked, it clears the Address Matching Mode (A) bits, effectively setting the region type to OFF (Null Region), disabling the entry. The function ensures it operates in Machine mode with MSTATUS.MPRV = 0 before modifying any PMP Control and Status Registers (CSRs). This provides a mechanism to clear all non-locked PMP regions, returning them to a default disabled state. The function is exposed in the pmp.h header file. Signed-off-by: Firas Sammoura <[email protected]>
1 parent f762d7f commit 12426b6

File tree

2 files changed

+57
-7
lines changed

2 files changed

+57
-7
lines changed

arch/riscv/core/pmp.c

Lines changed: 46 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -345,20 +345,59 @@ static unsigned long global_pmp_last_addr;
345345
/* End of global PMP entry range */
346346
static unsigned int global_pmp_end_index;
347347

348-
/**
349-
* @Brief Initialize the PMP with global entries on each CPU
350-
*/
351-
void z_riscv_pmp_init(void)
348+
void riscv_pmp_clear_all(void)
352349
{
353350
/*
354351
* Ensure we are in M-mode and that memory accesses use M-mode privileges
355-
* (MPRV=0) before configuring PMP registers. This prevents memory accesses
356-
* during PMP setup from being restricted by a lingering MPP state.
357-
* We also set MPP to M-mode to establish a predictable prior privilege level.
352+
* (MPRV=0). We also set MPP to M-mode to establish a predictable prior privilege level.
358353
*/
359354
csr_clear(mstatus, MSTATUS_MPRV);
360355
csr_set(mstatus, MSTATUS_MPP);
361356

357+
unsigned long pmp_cfg[CONFIG_PMP_SLOTS / PMPCFG_STRIDE];
358+
359+
#ifdef CONFIG_64BIT
360+
pmp_cfg[0] = csr_read(pmpcfg0);
361+
#if CONFIG_PMP_SLOTS > 8
362+
pmp_cfg[1] = csr_read(pmpcfg2);
363+
#endif
364+
#else
365+
pmp_cfg[0] = csr_read(pmpcfg0);
366+
pmp_cfg[1] = csr_read(pmpcfg1);
367+
#if CONFIG_PMP_SLOTS > 8
368+
pmp_cfg[2] = csr_read(pmpcfg2);
369+
pmp_cfg[3] = csr_read(pmpcfg3);
370+
#endif
371+
#endif
372+
373+
uint8_t *pmp_n_cfg = (uint8_t *)pmp_cfg;
374+
375+
for (index = 0; index < CONFIG_PMP_SLOTS; ++index) {
376+
if ((pmp_n_cfg[index] & PMP_L) == 0) {
377+
pmp_n_cfg[index] &= ~PMP_A;
378+
}
379+
}
380+
381+
#ifdef CONFIG_64BIT
382+
csr_write(pmpcfg0, pmp_cfg[0]);
383+
#if CONFIG_PMP_SLOTS > 8
384+
csr_write(pmpcfg2, pmp_cfg[1]);
385+
#endif
386+
#else
387+
csr_write(pmpcfg0, pmp_cfg[0]);
388+
csr_write(pmpcfg1, pmp_cfg[1]);
389+
#if CONFIG_PMP_SLOTS > 8
390+
csr_write(pmpcfg2, pmp_cfg[2]);
391+
csr_write(pmpcfg3, pmp_cfg[3]);
392+
#endif
393+
#endif
394+
}
395+
396+
/**
397+
* @Brief Initialize the PMP with global entries on each CPU
398+
*/
399+
void z_riscv_pmp_init(void)
400+
{
362401
unsigned long pmp_addr[CONFIG_PMP_SLOTS];
363402
unsigned long pmp_cfg[CONFIG_PMP_SLOTS / PMPCFG_STRIDE];
364403
unsigned int index = 0;

arch/riscv/include/pmp.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,15 @@ void z_riscv_pmp_usermode_init(struct k_thread *thread);
1515
void z_riscv_pmp_usermode_prepare(struct k_thread *thread);
1616
void z_riscv_pmp_usermode_enable(struct k_thread *thread);
1717

18+
/**
19+
* @brief Resets all unlocked PMP entries to OFF mode (Null Region).
20+
*
21+
* This function is used to securely clear the PMP configuration. It first
22+
* ensures the execution context is M-mode by setting MSTATUS_MPRV=0 and
23+
* MSTATUS_MPP=M-mode. It then reads all pmpcfgX CSRs, iterates through
24+
* the configuration bytes, and clears the Address Matching Mode bits (PMP_A)
25+
* for any entry that is not locked (PMP_L is clear), effectively disabling the region.
26+
*/
27+
void riscv_pmp_clear_all(void);
28+
1829
#endif /* PMP_H_ */

0 commit comments

Comments
 (0)