Skip to content

Commit 325cdce

Browse files
committed
arch/riscv: Allow overriding ROM region for PMP setup
The Physical Memory Protection (PMP) setup for the ROM region currently relies on the fixed linker symbols `__rom_region_start` and `__rom_region_size`. In environments where the firmware is loaded by a bootloader (example a two-stage boot, or jumping from a RO-image to a RW-image), the actual physical address of the executable code might change. This is especially critical when the PMP must protect the entire persistent ROM area, regardless of which stage of the firmware is executing. This commit addresses this by: 1. Introducing `CONFIG_ROM_REGION_START` and `CONFIG_ROM_REGION_SIZE` Kconfig options, guarded by `RISCV_PMP`. These default to the standard linker symbols but allow manual override via hexadecimal strings. 2. Adding a compile-time `ADDRESS_RESOLVER` macro in `pmp.c` to parse the Kconfig string, correctly handling the conversion of either the default linker symbol or a user-provided hexadecimal address into a numerical value. 3. Updating `z_riscv_pmp_init()` to use the resolved Kconfig values, ensuring that the PMP always protects the correct, full ROM area as defined by the user or the linker. Signed-off-by: Firas Sammoura <[email protected]>
1 parent b8576db commit 325cdce

File tree

2 files changed

+37
-4
lines changed

2 files changed

+37
-4
lines changed

arch/riscv/Kconfig

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,30 @@ config PMP_STACK_GUARD_MIN_SIZE
432432
wiggle room to accommodate the eventual overflow exception
433433
stack usage.
434434

435+
config ROM_REGION_START
436+
string "Start address or linker symbol of the ROM region"
437+
depends on RISCV_PMP
438+
default "__rom_region_start"
439+
help
440+
The linker symbol or hexadecimal address that defines the start of the
441+
ROM region.
442+
This configuration is used to calculate the physical memory
443+
protection (PMP) region entry. The value is resolved at compile time.
444+
To override the linker's default, set this to a hexadecimal string,
445+
such as "0x80000000".
446+
447+
config ROM_REGION_SIZE
448+
string "Size or linker symbol of the ROM region"
449+
depends on RISCV_PMP
450+
default "__rom_region_size"
451+
help
452+
The linker symbol or hexadecimal size that defines the overall byte
453+
length of the ROM region.
454+
This configuration is used to calculate the physical memory
455+
protection (PMP) region size. The value is resolved at compile time.
456+
To manually override the linker's default size, set this to a
457+
hexadecimal string, such as "0x100000".
458+
435459
# Implement the null pointer detection using the Physical Memory Protection
436460
# (PMP) Unit.
437461
config NULL_POINTER_EXCEPTION_DETECTION_PMP

arch/riscv/core/pmp.c

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
#include <zephyr/arch/arch_interface.h>
3333
#include <zephyr/arch/riscv/csr.h>
3434

35+
#include <stdlib.h>
36+
3537
#define LOG_LEVEL CONFIG_MPU_LOG_LEVEL
3638
#include <zephyr/logging/log.h>
3739
LOG_MODULE_REGISTER(mpu);
@@ -56,6 +58,14 @@ LOG_MODULE_REGISTER(mpu);
5658

5759
#define PMP_NONE 0
5860

61+
#define ADDRESS_RESOLVER(config_value) \
62+
(strcmp(config_value, "__rom_region_start") == 0) ? (uintptr_t)__rom_region_start \
63+
: (strcmp(config_value, "__rom_region_size") == 0) \
64+
? (uintptr_t)__rom_region_size \
65+
: ((config_value[0] == '0' && (config_value[1] == 'x' || config_value[1] == 'X')) \
66+
? (uintptr_t)strtoul(config_value, NULL, 16) \
67+
: 0)
68+
5969
static void print_pmp_entries(unsigned int pmp_start, unsigned int pmp_end,
6070
unsigned long *pmp_addr, unsigned long *pmp_cfg,
6171
const char *banner)
@@ -355,10 +365,9 @@ void z_riscv_pmp_init(void)
355365
unsigned int index = 0;
356366

357367
/* The read-only area is always there for every mode */
358-
set_pmp_entry(&index, PMP_R | PMP_X | PMP_L,
359-
(uintptr_t)__rom_region_start,
360-
(size_t)__rom_region_size,
361-
pmp_addr, pmp_cfg, ARRAY_SIZE(pmp_addr));
368+
set_pmp_entry(&index, PMP_R | PMP_X | PMP_L, ADDRESS_RESOLVER(CONFIG_ROM_REGION_START),
369+
ADDRESS_RESOLVER(CONFIG_ROM_REGION_SIZE), pmp_addr, pmp_cfg,
370+
ARRAY_SIZE(pmp_addr));
362371

363372
#ifdef CONFIG_NULL_POINTER_EXCEPTION_DETECTION_PMP
364373
/*

0 commit comments

Comments
 (0)