Skip to content

Commit 7c180f1

Browse files
committed
RISCV: PMP: Correct pmpcfg register indexing for multi-register configs
The PMP initialization and thread context switching logic was incorrectly assuming that the configuration for all global PMP entries was stored and restored from the first PMP configuration register, pmpcfg0 (i.e., pmp_cfg[0]). On RISC-V architectures, each pmpcfg register controls multiple PMP entries (e.g., 4 entries on RV32). When the number of PMP entries exceeds this, the configuration data spans across multiple pmpcfg registers (pmpcfg0, pmpcfg1, etc.). Failure to save and restore the contents of the correct pmpcfg register leads to an incorrect PMP setup, potentially compromising memory protection boundaries. This patch fixes the indexing by calculating the correct pmpcfg array index using integer division (index / PMPCFG_STRIDE), where PMPCFG_STRIDE represents the number of PMP entries per cfg register. The fixes are in: 1) z_riscv_pmp_init: When saving the configuration of the last global PMP entry, the content is now read from pmp_cfg[index / PMPCFG_STRIDE] instead of always from pmp_cfg[0]. 2) z_riscv_pmp_thread_init: When restoring the global PMP configuration for a new thread, the saved value is now written back to pmp_cfg[global_pmp_end_index / PMPCFG_STRIDE]. Signed-off-by: Firas Sammoura <[email protected]>
1 parent 6bb4cb5 commit 7c180f1

File tree

1 file changed

+4
-4
lines changed

1 file changed

+4
-4
lines changed

arch/riscv/core/pmp.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -432,12 +432,12 @@ void z_riscv_pmp_init(void)
432432
/* Make sure secondary CPUs produced the same values */
433433
if (global_pmp_end_index != 0) {
434434
__ASSERT(global_pmp_end_index == index, "");
435-
__ASSERT(global_pmp_cfg[0] == pmp_cfg[0], "");
435+
__ASSERT(global_pmp_cfg[0] == pmp_cfg[index / PMPCFG_STRIDE], "");
436436
__ASSERT(global_pmp_last_addr == pmp_addr[index - 1], "");
437437
}
438438
#endif
439439

440-
global_pmp_cfg[0] = pmp_cfg[0];
440+
global_pmp_cfg[0] = pmp_cfg[index / PMPCFG_STRIDE];
441441
global_pmp_last_addr = pmp_addr[index - 1];
442442
global_pmp_end_index = index;
443443

@@ -457,9 +457,9 @@ static inline unsigned int z_riscv_pmp_thread_init(unsigned long *pmp_addr,
457457
ARG_UNUSED(index_limit);
458458

459459
/*
460-
* Retrieve pmpcfg0 partial content from global entries.
460+
* Retrieve the pmpcfg register with partial content from global entries.
461461
*/
462-
pmp_cfg[0] = global_pmp_cfg[0];
462+
pmp_cfg[global_pmp_end_index / PMPCFG_STRIDE] = global_pmp_cfg[0];
463463

464464
/*
465465
* Retrieve the pmpaddr value matching the last global PMP slot.

0 commit comments

Comments
 (0)