Skip to content

Conversation

fsammoura1980
Copy link
Contributor

@fsammoura1980 fsammoura1980 commented Sep 18, 2025

This patch series enhances the flexibility and control of the RISC-V Physical Memory Protection (PMP) unit in Zephyr, moving towards device-tree driven configuration with runtime adjustability.

The first commit, "riscv: pmp: Add custom entries from device tree," introduces CONFIG_CUSTOM_PMP_ENTRY. This allows PMP regions to be defined within the Device Tree using the zephyr,memattr property, rather than being hardcoded. During boot, the system configures PMP entries based on these Device Tree nodes, enabling hardware-specific protection for critical memory areas like rollback segments. This commit also includes necessary adjustments to the Machine Status Register (mstatus) handling for privilege levels when this new feature is active without the PMP stack guard.

The second commit, "arch/riscv: Add API to control write permission for custom PMP entry," builds upon the first by providing a runtime mechanism to manage these Device Tree-configured PMP regions. The new riscv_pmp_set_write_permission() API allows dynamic enabling or disabling of the write permission ('W' bit) for a specific region, identified by its index from the Device Tree scan. This enables use cases such as temporarily allowing writes to a protected region during a secure update process.

Together, these changes provide a more robust and adaptable PMP management framework for RISC-V targets, allowing static configuration via hardware description and dynamic control at runtime.

@fkokosinski
Copy link
Member

Hi, thanks for the PR!

I see that we're limiting the user to just one custom protected memory region. Is this due to limitations imposed by Kconfig? Could we use devicetree for defining those regions instead? That would allow the user to specify more than one protected memory region.

@fsammoura1980
Copy link
Contributor Author

Hi, thanks for the PR!

I see that we're limiting the user to just one custom protected memory region. Is this due to limitations imposed by Kconfig? Could we use devicetree for defining those regions instead? That would allow the user to specify more than one protected memory region.

I am just defining only a new one because this is something that our application requires. users of the entry can get the config values from the device tree. Do you have any specific suggestion of how to generalize extracting things from a device tree early in the abstraction phase?

@fkokosinski
Copy link
Member

Do you have any specific suggestion of how to generalize extracting things from a device tree early in the abstraction phase?

We could start using zephyr,memory-attr for declaring PMP regions. IIRC the Zephyr ARM port uses them for MPU regions.

Introduce CONFIG_CUSTOM_PMP_ENTRY to enable configuring custom Physical
Memory Protection (PMP) regions directly from the Device Tree.

When this option is enabled, the PMP initialization process in
z_riscv_pmp_init() will scan the Device Tree for memory regions
tagged with the 'zephyr,memattr' property. For each such region
found, a corresponding PMP entry is programmed with the base address,
size, and permissions (R/W/X) specified in the Device Tree node.
This is facilitated by the mem_attr API.

This change allows for more flexible and hardware-specific memory
protection schemes, ideal for safeguarding critical areas like
firmware rollback segments or sensitive configuration data early in
the boot process.

Additionally, this patch introduces z_riscv_custom_pmp_entry_enable()
to manage the Machine Status Register (mstatus) MPRV bit when custom
PMP entries are used without the PMP stack guard. This function is
called during context switch to ensure correct privilege levels for
memory access.

Signed-off-by: Firas Sammoura <[email protected]>
Introduce the `riscv_pmp_set_write_permission()` API to dynamically
control the write access to memory regions protected by the RISC-V
Physical Memory Protection (PMP) unit.

This function enables or disables the Write (W) bit in the PMP
configuration register (pmpcfg) for a specific region. The region
is identified by an index (`region_idx`) referencing the list of
memory regions defined in the Device Tree with the "zephyr,memattr"
property.

This API is particularly useful for security-sensitive applications,
such as protecting critical flash sections like firmware rollback
data from accidental or unauthorized writes, while allowing writes
only during specific, controlled operations.

The current implementation supports systems with up to 8 PMP slots
(CONFIG_PMP_SLOTS <= 8) due to the method used to access pmpcfg
registers.

Signed-off-by: Firas Sammoura <[email protected]>
@fsammoura1980
Copy link
Contributor Author

Do you have any specific suggestion of how to generalize extracting things from a device tree early in the abstraction phase?

We could start using zephyr,memory-attr for declaring PMP regions. IIRC the Zephyr ARM port uses them for MPU regions.

ok, I implemented it using zephyr,memattr approach.

Copy link

sonarqubecloud bot commented Oct 6, 2025

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: RISCV RISCV Architecture (32-bit & 64-bit)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants