[POSSIBLE BUG] PMP access does not trigger illegal read when not present
Is there an existing CVA6 bug for this?
- [x] I have searched the existing bug issues
Bug Description
PMP reads and writes are allowed even when no PMP entry is present (NrPMPEntries = 0). Is this intended ?
RISC-V Specification
Unprivileged ISA: 20250508 | Privileged Architecture: 20250508 | SAIL Model: 20250709
As we can see in the sail specification, before accessing any CSR, a check is performed to see if the targeted CSR exists and is writable / readable / ... and else it raise an illegal instruction exception :
function doCSR(csr : csreg, rs1_val : xlenbits, rd : regidx, op : csrop, is_CSR_Write: bool) -> ExecutionResult = {
if not(check_CSR(csr, cur_privilege, is_CSR_Write))
then Illegal_Instruction()
else { ... }
}
function check_CSR(csr : csreg, p : Privilege, isWrite : bool) -> bool =
is_CSR_defined(csr)
& check_CSR_priv(csr, p)
& check_CSR_access(csr, isWrite)
& ...
Then specifically for the PMP registers, the sail specification defines if this check will be successful or not depending on the number of PMP Entries of the chosen configuration.
function clause is_CSR_defined(0x3B) @ idx : bits(4) = sys_pmp_count > unsigned(0b00 @ idx)
function clause is_CSR_defined(0x3C) @ idx : bits(4) = sys_pmp_count > unsigned(0b01 @ idx)
function clause is_CSR_defined(0x3D) @ idx : bits(4) = sys_pmp_count > unsigned(0b10 @ idx)
function clause is_CSR_defined(0x3E) @ idx : bits(4) = sys_pmp_count > unsigned(0b11 @ idx)
Example scenario
In the CV32A60X configuration, with NrPMPEntries = 0, the first instruction that is decoded at t_id (t##2) is csrrw x0, pmp_addr43, x0. It goes through the pipeline and is successfully commited at t_wb11 (t##5).
branch: cv32a60x | targeted configuration: cv32a60x | targeted design: cva6_pipeline.sv
Product: Questa OneSpin Solutions App: Questa Processor App Tool's version: 2025.1
Thanks for the report. I was under the impression that PMP CSRs were WARL (Write Any Read Legal). AFAIK, this is also how it was implemented, meaning that writes will succeed but not actually affect the underlying values. In the example above: you can write any value but will continue to read zeros from the CSR. I am not sure if this is the intended behavior (by the spec) or an illegal instruction exception...
According to last sentence of first paragraph of section 3.7.1 Physical Memory Protection CSRs (The RISC-V Instruction Set Manual Volume II: Privileged Architecture https://github.com/riscv/riscv-isa-manual/releases/tag/riscv-isa-release-584390d-2025-05-12): "All PMP CSR fields are WARL and may be read-only zero."
The current behaviour of CV32A60X (allowing any value to be written and reading always 0) is compliant with RISC-V specification.
I would suggest to close this issue.
PMP reads and writes are allowed even when no PMP entry is present (NrPMPEntries = 0). Is this intended ?
Section 2.1 of the unprivileged spec says, Attempts to access a non-existent CSR raise an illegal instruction exception.
As @ASintzoff says, section 3.7.1 says, All PMP CSR fields are WARL and may be read-only zero. If pmpcfg is 0 then address mapping is disabled.
So the question is, if PMP is not supported in the CV32A60X, should accesses to PMP CSRs return an illegal exception or follow the WARL access rules? I agree with André that the current behavior of the CV32A60X is compliant with the spec.
Having said that, the CV32A60X User Manual is clear that PMP is not implemented, but does not explain what happens when software attempts to access these CSRs. So I would recommend that the CSR chapter of the CV32A60X Design Manual be updated to clearly state this access behavior.