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]/ 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(-) -- 2.43.0
