CBIE encoding 10 is reserved when Zicbom is implemented, while
encoding 11 has defined behavior. Canonicalize only encoding 10 in the
menvcfg, senvcfg, and henvcfg write paths so the reserved value is not
retained and the defined encoding remains unchanged.

Tested: RV64 menvcfg, senvcfg, and henvcfg CBIE 10 and CBIE 11
write/readback test cases.
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4416

Signed-off-by: wangyang <[email protected]>
---
 target/riscv/tcg/csr.c | 29 +++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)

diff --git a/target/riscv/tcg/csr.c b/target/riscv/tcg/csr.c
index bd4b6dc114..cf59f9ae54 100644
--- a/target/riscv/tcg/csr.c
+++ b/target/riscv/tcg/csr.c
@@ -3260,6 +3260,16 @@ static RISCVException write_menvcfg(CPURISCVState *env, 
int csrno,
             stce_changed = true;
         }
     }
+
+    /*
+     * CBIE is a WARL field: encoding 10 is reserved.  A software write of
+     * this encoding must canonicalize to a supported value instead of being
+     * retained in the readback.
+     */
+    if (cfg->ext_zicbom && get_field(val, MENVCFG_CBIE) == 2) {
+        val &= ~MENVCFG_CBIE;
+    }
+
     env->menvcfg = (env->menvcfg & ~mask) | (val & mask);
 
     if (stce_changed) {
@@ -3354,6 +3364,16 @@ static RISCVException write_senvcfg(CPURISCVState *env, 
int csrno,
         mask |= SENVCFG_UKTE;
     }
 
+    /*
+     * CBIE is a WARL field: encoding 10 is reserved.  A software write of
+     * this encoding must canonicalize to a supported value instead of being
+     * retained in the readback.
+     */
+    if (env_archcpu(env)->cfg.ext_zicbom &&
+        get_field(val, SENVCFG_CBIE) == 2) {
+        val &= ~SENVCFG_CBIE;
+    }
+
     env->senvcfg = (env->senvcfg & ~mask) | (val & mask);
     return RISCV_EXCP_NONE;
 }
@@ -3422,6 +3442,15 @@ static RISCVException write_henvcfg(CPURISCVState *env, 
int csrno,
         }
     }
 
+    /*
+     * CBIE is a WARL field: encoding 10 is reserved.  A software write of
+     * this encoding must canonicalize to a supported value instead of being
+     * retained in the readback.
+     */
+    if (cfg->ext_zicbom && get_field(val, HENVCFG_CBIE) == 2) {
+        val &= ~HENVCFG_CBIE;
+    }
+
     if (riscv_cpu_mxl(env) == MXL_RV32) {
         /*
          * RV32 stores STCE/ADUE/PBMTE/DTE in henvcfgh, so a low-half henvcfg
-- 
2.55.0.windows.2


Reply via email to