Definition of PMP
The full name of PMP is Physical Memory Protection. It is a lightweight and low-overhead memory protection mechanism in the RISC-V architecture, primarily used in embedded systems or real-time operating systems (RTOS) that do not have a Memory Management Unit (MMU).
The core purpose is to provide access control to physical memory regions (such as read, write, execute) for lower privilege modes (mainly Supervisor mode (S-mode) and User mode (U-mode)) under Machine mode (M-mode), thereby preventing erroneous operations by user programs or the operating system kernel from corrupting critical memory areas (such as firmware, peripheral registers, kernel data, etc.), enhancing the security and reliability of the system. For example, an erroneous pointer may overwrite the operating system kernel or other critical task code and data, and malicious code can freely access and modify any memory location, including peripheral registers.
PMP provides basic memory protection and permission isolation for such environments, serving as the foundation for privilege separation and Trusted Execution Environments (TEE). It allows M-mode firmware (such as bootloaders or security monitors) to delineate “secure zones” for S-mode and U-mode software.
-
Protecting critical areas: Preventing lower privilege modes (such as User mode U-mode or Supervisor mode S-mode) from accidentally or maliciously accessing M-mode private data, firmware code, device registers, etc.
-
Isolating environments: In embedded systems or simple operating systems, dividing physical memory regions for different tasks or processes and setting access permissions (read, write, execute).
-
Enhancing security: Serving as a fundamental security barrier to prevent privilege escalation attacks.
Implementation of PMP
PMP is implemented through a set of special Control and Status Registers (CSR). These registers define several (usually 8 or 16) protection rules.
-
Address Registers (pmpaddr0 – pmpaddrN): Define the boundaries of protected memory regions.
-
Configuration Registers (pmpcfg0 – pmpcfgN): Define the access permissions and matching patterns for that memory region.
When lower privilege (S or U-mode) software attempts to access a memory address, the hardware traverses all enabled PMP entries in priority order (usually from pmp0 to pmpN). If the address falls within a region defined by an entry, access is determined based on that entry’s permissions. If the address does not fall within any region, access is typically denied (unless there is a default rule).
Configuration Register (pmpcfgX)
Each pmpcfg register is typically 8 bits wide and manages a PMP entry (for example, pmpcfg2 manages pmpaddr2). Each entry’s configuration consists of three key fields:
-
R (Read): Allows load operations (read).
-
W (Write): Allows store operations (write).
-
X (Execute): Allows instruction fetch (execute).
The permission combinations are arbitrarily set. For example, R-W means readable and writable but not executable (similar to a data segment), while R-X means readable and executable but not writable (similar to a code segment).
The LOCK bit is a special bit:
-
L (Lock): When this bit is set, the corresponding PMP entry is locked. Once locked, this entry cannot be modified (including its address and configuration) unless through a system reset. Additionally, under locked conditions, accesses from M-mode will also adhere to this rule. This is used to protect extremely critical areas, preventing even M-mode code from accidentally modifying or accessing them.
Address Register (pmpaddrX) and Address Matching Modes
The address register defines the boundaries of the region, with its specific meaning determined by the A field in pmpcfg. The A field has three main modes:
-
OFF (A=0): This entry is disabled and provides no protection.
-
TOR (Top of Range, A=1): This is the most intuitive mode. The current entry’s pmpaddrX register defines the end address of the region, while the previous entry’s pmpaddrX-1 defines the start address.
That is: Region range = [pmpaddrX-1, pmpaddrX)
Note: For the first entry (pmpaddr0), there is no previous entry, and its start address is considered 0.
-
NAPOT (Naturally Aligned Power-of-Two, A=3): This is the most commonly used and efficient mode. A single pmpaddrX register can define a naturally aligned, power-of-two-sized contiguous region.
The principle: The number of consecutive ‘1’s in the least significant bits of the pmpaddr register value determines the size of the region.
For example:
pmpaddr = 0x0000FFFF → The lowest 16 bits are 1 → Region size = 2^16 = 64 KB.
If the address is 0x80000000, the region is [0x80000000, 0x8000FFFF].
For example:
pmpaddr = 0xAAAAAFFF → The lowest 12 bits are 1 (0xFFF) → Region size = 4 KB (2^12).
Mode matching rules: Specify which privilege modes (M, S, U) this entry applies to.
PMP Check Process and Priority
Traversal order: Check from the lowest index PMP entry (such as pmp0) to the highest index entry (such as pmp15).
First match: Once the target address falls within a region of an entry, the check immediately stops, and that entry’s permission rules are applied. The first matching entry has the highest priority.
Default behavior: If the address does not match any PMP rules:
In M-mode: Access is always allowed.
In S-mode or U-mode: Access is typically denied and triggers an exception (for example, a store access triggers a Store/AMO page fault exception).
Error Trigger Conditions (When does a PMP Error occur?):
-
The current CPU privilege mode (M, S, U) attempts to access a physical address.
-
The address falls within the address range covered by a configured and enabled PMP entry.
-
The permissions (R/W/X) configured for that entry do not allow the current attempted operation.
For example: A U-mode program attempts to write to a PMP entry marked as R-X (read-only, executable) memory region, which will trigger a write operation’s PMP violation.
Error Handling:
-
Trigger a precise exception (Precise Exception), usually an Instruction Access Fault, Load Access Fault, or Store Access Fault.
-
The exception cause code (mcause or scause register) will clearly indicate that it was caused by a PMP violation.
-
The exception handler (usually in M-mode) can diagnose the problem (view mtval/stval
Registers obtain the violating address), and decide how to handle it (terminate the process, log the error, etc.).
Limitations of PMP
-
Limited number: Typically only 8 or 16 entries, unable to manage complex memory mappings like page tables.
-
Granularity: The NAPOT mode requires regions to be naturally aligned, which may waste entries for many small and non-contiguous regions.
-
No address translation: PMP is for protection, not translation. It operates on physical addresses and cannot provide virtual memory space.
-
Performance: Although faster than software checks, linearly searching all entries is still slower than the MMU’s TLB.
-