The priv spec defines, for RV64, that the upper 10 bits of pmpaddr0-pmpaddr63 are WARL and are supposed to be cleared.
After this patch, using the bug reproducer in [1], writing ffffffffffffffff in pmpaddr0 and reading it back now results in 003fffffffffffff. Here's the 'diff -cp' dump before and after this change: *************** IN: *** 5272,5278 **** pmpcfg10 0000000000000000 pmpcfg12 0000000000000000 pmpcfg14 0000000000000000 ! pmpaddr0 ffffffffffffffff pmpaddr1 0000000000000000 pmpaddr2 0000000000000000 pmpaddr3 0000000000000000 --- 5545,5551 ---- pmpcfg10 0000000000000000 pmpcfg12 0000000000000000 pmpcfg14 0000000000000000 ! pmpaddr0 003fffffffffffff pmpaddr1 0000000000000000 pmpaddr2 0000000000000000 pmpaddr3 0000000000000000 [1] https://gitlab.com/qemu-project/qemu/-/work_items/3362 Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3362 Signed-off-by: Daniel Henrique Barboza <[email protected]> --- target/riscv/csr.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index e1cd4a299c..476a620035 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -5362,6 +5362,23 @@ static RISCVException read_pmpaddr(CPURISCVState *env, int csrno, target_ulong *val) { *val = pmpaddr_csr_read(env, csrno - CSR_PMPADDR0); + + /* + * For RV64, bits 54-63 of the address registers + * PMPAADDR(0-63) is a WARL zero field (priv spec, + * section "Physical Memory Protection CSRs"). + * + * We'll have to add an annoying TARGET_RISCV64 gate + * here to avoid complaints about masking bits 0-53 + * of a potential 32 bit target_ulong '*var'. + */ +#ifdef TARGET_RISCV64 + if (env->misa_mxl == MXL_RV64 + && csrno >= CSR_PMPADDR0 && csrno <= CSR_PMPADDR63) { + target_ulong read_mask = MAKE_64BIT_MASK(0, 54); + *val &= read_mask; + } +#endif return RISCV_EXCP_NONE; } -- 2.43.0
