On Wed, 2026-10-21 at 22:02 -0600, Sebastian Alba Vives wrote: > v2 cleared the whole pmp_state with a memset. Alistair pointed out > that > the priv spec only requires the A and L fields to be reset, so v3 > splits > the change: 1/2 stays within what the spec mandates, and 2/2 handles > the > derived state QEMU keeps alongside the architectural registers. > > 1/2 is the v1 fix. It bounds the loop by the number of implemented > regions rather than pmp_get_num_rules(), so entries past the last > active > rule are no longer skipped. > > 2/2 clears pmp_state.addr[] and pmp_state.num_rules. Those are not > architectural, so the spec does not speak to them, but they are > recomputed on the pmpaddr and pmpcfg write paths only and never at > reset. > > The second one is observable from a guest. A bare-metal M-mode > program > configures PMP entry 0 as NA4 over [0x80100000, 0x80100003], resets > through sifive_test, and on the second boot performs an 8-byte load > at > 0x80100000, which starts inside the old range and ends outside it: > > tree pmpcfg0 after reset 8-byte load at 0x80100000 > 1/2 only 0x00000001 load access fault > 1/2 + 2/2 0x00000001 succeeds > > The architectural state is identical in both runs. The difference is > that with 1/2 alone num_rules is still 1 and addr[0] still holds the > old > bounds, so pmp_hart_has_privs() skips the no-rules short cut and > reaches > the partially-inside check. That check calls pmp_is_in_range(), which > compares against addr[].sa and addr[].ea only, and returns before the > A > field is ever tested. > > v2: > https://lore.kernel.org/qemu-devel/[email protected]/ > v1: > https://lore.kernel.org/qemu-devel/[email protected]/
Thanks! Applied to riscv-to-apply.next Alistair > > Sebastian Alba Vives (2): > target/riscv: pmp: clear A and L on every implemented PMP entry at > reset > target/riscv: pmp: reset the derived PMP bounds and rule count > > target/riscv/tcg/pmp.c | 10 +++++++++- > 1 file changed, 9 insertions(+), 1 deletion(-)
