Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions arch/riscv/core/pmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,54 @@ static unsigned long global_pmp_last_addr;
/* End of global PMP entry range */
static unsigned int global_pmp_end_index;

void riscv_pmp_clear_all(void)
{
/*
* Ensure we are in M-mode and that memory accesses use M-mode privileges
* (MPRV=0). We also set MPP to M-mode to establish a predictable prior privilege level.
*/
csr_clear(mstatus, MSTATUS_MPRV);
csr_set(mstatus, MSTATUS_MPP);

unsigned long pmp_cfg[CONFIG_PMP_SLOTS / PMPCFG_STRIDE];

#ifdef CONFIG_64BIT
pmp_cfg[0] = csr_read(pmpcfg0);
#if CONFIG_PMP_SLOTS > 8
pmp_cfg[1] = csr_read(pmpcfg2);
#endif
#else
pmp_cfg[0] = csr_read(pmpcfg0);
pmp_cfg[1] = csr_read(pmpcfg1);
#if CONFIG_PMP_SLOTS > 8
pmp_cfg[2] = csr_read(pmpcfg2);
pmp_cfg[3] = csr_read(pmpcfg3);
#endif
#endif

uint8_t *pmp_n_cfg = (uint8_t *)pmp_cfg;

for (int index = 0; index < CONFIG_PMP_SLOTS; ++index) {
if ((pmp_n_cfg[index] & PMP_L) == 0) {
pmp_n_cfg[index] &= ~PMP_A;
}
}

#ifdef CONFIG_64BIT
csr_write(pmpcfg0, pmp_cfg[0]);
#if CONFIG_PMP_SLOTS > 8
csr_write(pmpcfg2, pmp_cfg[1]);
#endif
#else
csr_write(pmpcfg0, pmp_cfg[0]);
csr_write(pmpcfg1, pmp_cfg[1]);
#if CONFIG_PMP_SLOTS > 8
csr_write(pmpcfg2, pmp_cfg[2]);
csr_write(pmpcfg3, pmp_cfg[3]);
#endif
#endif
}

/**
* @Brief Initialize the PMP with global entries on each CPU
*/
Expand Down
11 changes: 11 additions & 0 deletions arch/riscv/include/pmp.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,15 @@ void z_riscv_pmp_usermode_init(struct k_thread *thread);
void z_riscv_pmp_usermode_prepare(struct k_thread *thread);
void z_riscv_pmp_usermode_enable(struct k_thread *thread);

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

#endif /* PMP_H_ */