Skip to content

Commit

Permalink
riscv: pmp: actually activate stack overflow protection during boot
Browse files Browse the repository at this point in the history
Before this, stack protection would be effective only after switching to
the first thread.

Even before the first thread is created, the kernel init code uses the
IRQ stack to set things up. Let's make sure this is safeguarded as well.

This also fixes the incompatibility between CONFIG_RISCV_PMP and
CONFIG_RISCV_ALWAYS_SWITCH_THROUGH_ECALL, the later needing an exception
call to switch to the first thread and exception code assuming stack
guard is already set up in the PMP.

Signed-off-by: Nicolas Pitre <[email protected]>
  • Loading branch information
Nicolas Pitre authored and nashif committed Jul 11, 2024
1 parent 0207c7f commit 8d485d4
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 4 deletions.
1 change: 0 additions & 1 deletion arch/riscv/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ config RISCV_GP
config RISCV_ALWAYS_SWITCH_THROUGH_ECALL
bool "Do not use mret outside a trap handler context"
depends on MULTITHREADING
depends on !RISCV_PMP
help
Use mret instruction only when in a trap handler.
This is for RISC-V implementations that require every mret to be
Expand Down
25 changes: 22 additions & 3 deletions arch/riscv/core/pmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -348,8 +348,8 @@ static unsigned int global_pmp_end_index;
*/
void z_riscv_pmp_init(void)
{
unsigned long pmp_addr[4];
unsigned long pmp_cfg[1];
unsigned long pmp_addr[5];
unsigned long pmp_cfg[2];
unsigned int index = 0;

/* The read-only area is always there for every mode */
Expand Down Expand Up @@ -379,9 +379,27 @@ void z_riscv_pmp_init(void)
(uintptr_t)z_interrupt_stacks[_current_cpu->id],
Z_RISCV_STACK_GUARD_SIZE,
pmp_addr, pmp_cfg, ARRAY_SIZE(pmp_addr));
#endif

/*
* This early, the kernel init code uses the IRQ stack and we want to
* safeguard it as soon as possible. But we need a temporary default
* "catch all" PMP entry for MPRV to work. Later on, this entry will
* be set for each thread by z_riscv_pmp_stackguard_prepare().
*/
set_pmp_mprv_catchall(&index, pmp_addr, pmp_cfg, ARRAY_SIZE(pmp_addr));

/* Write those entries to PMP regs. */
write_pmp_entries(0, index, true, pmp_addr, pmp_cfg, ARRAY_SIZE(pmp_addr));

/* Activate our non-locked PMP entries for m-mode */
csr_set(mstatus, MSTATUS_MPRV);

/* And forget about that last entry as we won't need it later */
index--;
#else
/* Write those entries to PMP regs. */
write_pmp_entries(0, index, true, pmp_addr, pmp_cfg, ARRAY_SIZE(pmp_addr));
#endif

#ifdef CONFIG_SMP
#ifdef CONFIG_PMP_STACK_GUARD
Expand All @@ -401,6 +419,7 @@ void z_riscv_pmp_init(void)
}
#endif

__ASSERT(index <= PMPCFG_STRIDE, "provision for one global word only");
global_pmp_cfg[0] = pmp_cfg[0];
global_pmp_last_addr = pmp_addr[index - 1];
global_pmp_end_index = index;
Expand Down

0 comments on commit 8d485d4

Please sign in to comment.