riscv: pmp: enable stackguard without multithreading

Without multithreading only two stacks present: ISR and main.
As any stack they also could overflow, so it make sense to add stack
guard for them also.

Remove stack guard dependency on multithreading and mark
`Z_RISCV_STACK_GUARD_SIZE` bytes at the beginning of stack as read-only
region with PMP entry.

Signed-off-by: Volodymyr Fialko <vfialko@marvell.com>
This commit is contained in:
Volodymyr Fialko 2024-10-23 14:07:24 +02:00 committed by Anas Nashif
commit 9eee2eaee6
4 changed files with 32 additions and 4 deletions

View file

@ -337,7 +337,6 @@ endif #RISCV_PMP
config PMP_STACK_GUARD
def_bool y
depends on MULTITHREADING
depends on HW_STACK_PROTECTION
config PMP_STACK_GUARD_MIN_SIZE

View file

@ -172,11 +172,21 @@ static bool bad_stack_pointer(struct arch_esf *esf)
}
#endif /* CONFIG_USERSPACE */
#if CONFIG_MULTITHREADING
if (sp >= _current->stack_info.start - K_KERNEL_STACK_RESERVED &&
sp < _current->stack_info.start - K_KERNEL_STACK_RESERVED
+ Z_RISCV_STACK_GUARD_SIZE) {
return true;
}
#else
uintptr_t isr_stack = (uintptr_t)z_interrupt_stacks;
uintptr_t main_stack = (uintptr_t)z_main_stack;
if ((sp >= isr_stack && sp < isr_stack + Z_RISCV_STACK_GUARD_SIZE) ||
(sp >= main_stack && sp < main_stack + Z_RISCV_STACK_GUARD_SIZE)) {
return true;
}
#endif /* CONFIG_MULTITHREADING */
#endif /* CONFIG_PMP_STACK_GUARD */
#ifdef CONFIG_USERSPACE

View file

@ -348,8 +348,8 @@ static unsigned int global_pmp_end_index;
*/
void z_riscv_pmp_init(void)
{
unsigned long pmp_addr[5];
unsigned long pmp_cfg[2];
unsigned long pmp_addr[CONFIG_PMP_SLOTS];
unsigned long pmp_cfg[CONFIG_PMP_SLOTS / PMPCFG_STRIDE];
unsigned int index = 0;
/* The read-only area is always there for every mode */
@ -370,6 +370,7 @@ void z_riscv_pmp_init(void)
#endif
#ifdef CONFIG_PMP_STACK_GUARD
#ifdef CONFIG_MULTITHREADING
/*
* Set the stack guard for this CPU's IRQ stack by making the bottom
* addresses inaccessible. This will never change so we do it here
@ -396,6 +397,21 @@ void z_riscv_pmp_init(void)
/* And forget about that last entry as we won't need it later */
index--;
#else
/* Without multithreading setup stack guards for IRQ and main stacks */
set_pmp_entry(&index, PMP_NONE | PMP_L,
(uintptr_t)z_interrupt_stacks,
Z_RISCV_STACK_GUARD_SIZE,
pmp_addr, pmp_cfg, ARRAY_SIZE(pmp_addr));
set_pmp_entry(&index, PMP_NONE | PMP_L,
(uintptr_t)z_main_stack,
Z_RISCV_STACK_GUARD_SIZE,
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));
#endif /* CONFIG_MULTITHREADING */
#else
/* Write those entries to PMP regs. */
write_pmp_entries(0, index, true, pmp_addr, pmp_cfg, ARRAY_SIZE(pmp_addr));
@ -419,7 +435,6 @@ 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;
@ -454,6 +469,7 @@ static inline unsigned int z_riscv_pmp_thread_init(unsigned long *pmp_addr,
#ifdef CONFIG_PMP_STACK_GUARD
#ifdef CONFIG_MULTITHREADING
/**
* @brief Prepare the PMP stackguard content for given thread.
*
@ -511,6 +527,8 @@ void z_riscv_pmp_stackguard_enable(struct k_thread *thread)
csr_set(mstatus, MSTATUS_MPRV);
}
#endif /* CONFIG_MULTITHREADING */
/**
* @brief Remove PMP stackguard content to actual PMP registers
*/

View file

@ -152,6 +152,7 @@ extern struct k_thread z_idle_threads[CONFIG_MP_MAX_NUM_CPUS];
#endif /* CONFIG_MULTITHREADING */
K_KERNEL_PINNED_STACK_ARRAY_DECLARE(z_interrupt_stacks, CONFIG_MP_MAX_NUM_CPUS,
CONFIG_ISR_STACK_SIZE);
K_THREAD_STACK_DECLARE(z_main_stack, CONFIG_MAIN_STACK_SIZE);
#ifdef CONFIG_GEN_PRIV_STACKS
extern uint8_t *z_priv_stack_find(k_thread_stack_t *stack);