On 14/5/26 14:33, Daniel Henrique Barboza wrote:
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'.

deposit64() shouldn't generate complains.

      *val = deposit64(*val, 54, 10, 0x000);

Anyhow,

Reviewed-by: Philippe Mathieu-Daudé <[email protected]>

+     */
+#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;
  }


Reply via email to