Skip to content

Commit 9eee2ea

Browse files
f0rget-the-sadnashif
authored andcommitted
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 <[email protected]>
1 parent 2253a26 commit 9eee2ea

File tree

4 files changed

+32
-4
lines changed

4 files changed

+32
-4
lines changed

arch/riscv/Kconfig

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,6 @@ endif #RISCV_PMP
337337

338338
config PMP_STACK_GUARD
339339
def_bool y
340-
depends on MULTITHREADING
341340
depends on HW_STACK_PROTECTION
342341

343342
config PMP_STACK_GUARD_MIN_SIZE

arch/riscv/core/fatal.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,11 +172,21 @@ static bool bad_stack_pointer(struct arch_esf *esf)
172172
}
173173
#endif /* CONFIG_USERSPACE */
174174

175+
#if CONFIG_MULTITHREADING
175176
if (sp >= _current->stack_info.start - K_KERNEL_STACK_RESERVED &&
176177
sp < _current->stack_info.start - K_KERNEL_STACK_RESERVED
177178
+ Z_RISCV_STACK_GUARD_SIZE) {
178179
return true;
179180
}
181+
#else
182+
uintptr_t isr_stack = (uintptr_t)z_interrupt_stacks;
183+
uintptr_t main_stack = (uintptr_t)z_main_stack;
184+
185+
if ((sp >= isr_stack && sp < isr_stack + Z_RISCV_STACK_GUARD_SIZE) ||
186+
(sp >= main_stack && sp < main_stack + Z_RISCV_STACK_GUARD_SIZE)) {
187+
return true;
188+
}
189+
#endif /* CONFIG_MULTITHREADING */
180190
#endif /* CONFIG_PMP_STACK_GUARD */
181191

182192
#ifdef CONFIG_USERSPACE

arch/riscv/core/pmp.c

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -348,8 +348,8 @@ static unsigned int global_pmp_end_index;
348348
*/
349349
void z_riscv_pmp_init(void)
350350
{
351-
unsigned long pmp_addr[5];
352-
unsigned long pmp_cfg[2];
351+
unsigned long pmp_addr[CONFIG_PMP_SLOTS];
352+
unsigned long pmp_cfg[CONFIG_PMP_SLOTS / PMPCFG_STRIDE];
353353
unsigned int index = 0;
354354

355355
/* The read-only area is always there for every mode */
@@ -370,6 +370,7 @@ void z_riscv_pmp_init(void)
370370
#endif
371371

372372
#ifdef CONFIG_PMP_STACK_GUARD
373+
#ifdef CONFIG_MULTITHREADING
373374
/*
374375
* Set the stack guard for this CPU's IRQ stack by making the bottom
375376
* addresses inaccessible. This will never change so we do it here
@@ -396,6 +397,21 @@ void z_riscv_pmp_init(void)
396397

397398
/* And forget about that last entry as we won't need it later */
398399
index--;
400+
#else
401+
/* Without multithreading setup stack guards for IRQ and main stacks */
402+
set_pmp_entry(&index, PMP_NONE | PMP_L,
403+
(uintptr_t)z_interrupt_stacks,
404+
Z_RISCV_STACK_GUARD_SIZE,
405+
pmp_addr, pmp_cfg, ARRAY_SIZE(pmp_addr));
406+
407+
set_pmp_entry(&index, PMP_NONE | PMP_L,
408+
(uintptr_t)z_main_stack,
409+
Z_RISCV_STACK_GUARD_SIZE,
410+
pmp_addr, pmp_cfg, ARRAY_SIZE(pmp_addr));
411+
412+
/* Write those entries to PMP regs. */
413+
write_pmp_entries(0, index, true, pmp_addr, pmp_cfg, ARRAY_SIZE(pmp_addr));
414+
#endif /* CONFIG_MULTITHREADING */
399415
#else
400416
/* Write those entries to PMP regs. */
401417
write_pmp_entries(0, index, true, pmp_addr, pmp_cfg, ARRAY_SIZE(pmp_addr));
@@ -419,7 +435,6 @@ void z_riscv_pmp_init(void)
419435
}
420436
#endif
421437

422-
__ASSERT(index <= PMPCFG_STRIDE, "provision for one global word only");
423438
global_pmp_cfg[0] = pmp_cfg[0];
424439
global_pmp_last_addr = pmp_addr[index - 1];
425440
global_pmp_end_index = index;
@@ -454,6 +469,7 @@ static inline unsigned int z_riscv_pmp_thread_init(unsigned long *pmp_addr,
454469

455470
#ifdef CONFIG_PMP_STACK_GUARD
456471

472+
#ifdef CONFIG_MULTITHREADING
457473
/**
458474
* @brief Prepare the PMP stackguard content for given thread.
459475
*
@@ -511,6 +527,8 @@ void z_riscv_pmp_stackguard_enable(struct k_thread *thread)
511527
csr_set(mstatus, MSTATUS_MPRV);
512528
}
513529

530+
#endif /* CONFIG_MULTITHREADING */
531+
514532
/**
515533
* @brief Remove PMP stackguard content to actual PMP registers
516534
*/

kernel/include/kernel_internal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ extern struct k_thread z_idle_threads[CONFIG_MP_MAX_NUM_CPUS];
152152
#endif /* CONFIG_MULTITHREADING */
153153
K_KERNEL_PINNED_STACK_ARRAY_DECLARE(z_interrupt_stacks, CONFIG_MP_MAX_NUM_CPUS,
154154
CONFIG_ISR_STACK_SIZE);
155+
K_THREAD_STACK_DECLARE(z_main_stack, CONFIG_MAIN_STACK_SIZE);
155156

156157
#ifdef CONFIG_GEN_PRIV_STACKS
157158
extern uint8_t *z_priv_stack_find(k_thread_stack_t *stack);

0 commit comments

Comments
 (0)