]> git.ipfire.org Git - thirdparty/qemu.git/commitdiff
target/riscv: preserve RV32 henvcfgh on henvcfg writes
authorBruno Sa <bruno.vilaca.sa@gmail.com>
Thu, 9 Apr 2026 15:53:42 +0000 (16:53 +0100)
committerAlistair Francis <alistair.francis@wdc.com>
Wed, 29 Apr 2026 01:41:00 +0000 (11:41 +1000)
On RV32, STCE/ADUE/PBMTE/DTE are implemented in henvcfgh. A write to
henvcfg should therefore only update the low 32 bits of env->henvcfg.

The current write_henvcfg() path overwrites env->henvcfg with the
low-half value and clears any bits previously written via henvcfgh.

Preserve the upper 32 bits on RV32 henvcfg writes and keep the existing
RV64 behaviour unchanged.

Signed-off-by: Bruno Sa <bruno.vilaca.sa@gmail.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Message-ID: <20260409155344.2849233-2-bruno.vilaca.sa@gmail.com>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
target/riscv/csr.c

index a75281539bd3ba1ce5d415c4d498bf99a8b0bc81..cfd076b368110c4f3917a3eb9e94449b9cf862e5 100644 (file)
@@ -3353,7 +3353,15 @@ static RISCVException write_henvcfg(CPURISCVState *env, int csrno,
         }
     }
 
-    env->henvcfg = val & mask;
+    if (riscv_cpu_mxl(env) == MXL_RV32) {
+        /*
+         * RV32 stores STCE/ADUE/PBMTE/DTE in henvcfgh, so a low-half henvcfg
+         * write must not clobber the upper 32 bits.
+         */
+        env->henvcfg = (env->henvcfg & ~0xFFFFFFFFULL) | (val & mask);
+    } else {
+        env->henvcfg = val & mask;
+    }
     if ((env->henvcfg & HENVCFG_DTE) == 0) {
         env->vsstatus &= ~MSTATUS_SDT;
     }