target/riscv/csr.c: fix read of pmpaddr(0-63) CSRs
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 Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260514123342.2139464-1-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Daniel Henrique Barboza committed
May 14, 2026 at 09:33 UTC
53cc9747ed7c9b95ba084d614976dd48c9a57a97
1 file changed
+17
target/riscv/csr.c
+17
@@ -5365,6 +5365,23 @@ static RISCVException read_pmpaddr(CPURISCVState *env, int csrno,
5365
target_ulong *val)
5366
{
5367
*val = pmpaddr_csr_read(env, csrno - CSR_PMPADDR0);
5368
+
5369
+ /*
5370
+ * For RV64, bits 54-63 of the address registers
5371
+ * PMPAADDR(0-63) is a WARL zero field (priv spec,
5372
+ * section "Physical Memory Protection CSRs").
5373
+ *
5374
+ * We'll have to add an annoying TARGET_RISCV64 gate
5375
+ * here to avoid complaints about masking bits 0-53
5376
+ * of a potential 32 bit target_ulong '*var'.
5377
+ */
5378
+#ifdef TARGET_RISCV64
5379
+ if (env->misa_mxl == MXL_RV64
5380
+ && csrno >= CSR_PMPADDR0 && csrno <= CSR_PMPADDR63) {
5381
+ target_ulong read_mask = MAKE_64BIT_MASK(0, 54);
5382
+ *val &= read_mask;
5383
+ }
5384
+#endif
5385
return RISCV_EXCP_NONE;
5386
}
5387