Hello,

On 6/24/2026 6:00 AM, SeungJu Cheon wrote:
By the priv spec the value "3" is marked as 'Reserved' for
mstatus.UXL. write_mstatus() rejects this value, but
write_vsstatus() does not, allowing the reserved value to be
written and read back unchanged.

Handle a vsstatus.UXL = 3 write by writing the current 'xl'
instead.

Fixes: f310df58bd2 ("target/riscv: Enable uxl field write")
Signed-off-by: SeungJu Cheon <[email protected]>
---
  target/riscv/csr.c | 8 ++++++++
  1 file changed, 8 insertions(+)

diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index dd9726fcf4..4c1da61824 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -5226,7 +5226,15 @@ static RISCVException write_vsstatus(CPURISCVState *env, 
int csrno,
      uint64_t mask = (target_ulong)-1;
      if ((val & VSSTATUS64_UXL) == 0) {
          mask &= ~VSSTATUS64_UXL;
+    } else {
+        uint64_t uxl = (val & VSSTATUS64_UXL) >> 32;
+        if (uxl == 3) {
+            int xl = riscv_cpu_mxl(env);
+            val = deposit64(val, 32, 2,
+                            xl == MXL_RV128 ? MXL_RV64 : xl);
+        }
      }

This is similar to what was done here:

commit ddfd33f1965804fc4a718d8d46bc150525c2f9db
Author: Daniel Henrique Barboza <[email protected]>
Date:   Thu May 14 16:45:37 2026 -0300

    target/riscv/csr.c: fix mstatus.UXL reserved value


diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 83ca354bf0..d004a4bfb4 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -2045,7 +2045,17 @@ static RISCVException write_mstatus(CPURISCVState *env, 
int csrno,

     if (xl != MXL_RV32 || env->debugger) {
         if ((val & MSTATUS64_UXL) != 0) {
+            uint64_t uxl = val & MSTATUS64_UXL >> 32;
             mask |= MSTATUS64_UXL;
+
+            /*
+             * uxl = 3 is reserved so write the current xl instead.
+             * In case xl = MXL_RV128 (3) write MXL_RV64.
+             */
+            if (uxl == 3) {
+                uxl = xl == MXL_RV128 ? MXL_RV64 : xl;
+                val = deposit64(val, 32, 2, uxl);
+            }
         }
     }


But that patch fixed just write_mstatus().

I suggest adding a local helper riscv_write_uxl (feel free to choose another 
better
name) to encapsulate this logic and then use it in both mstatus and vsstatus to
write UXL:

 val = riscv_write_uxl(val)


Thanks,
Daniel



+
      if ((env->henvcfg & HENVCFG_DTE)) {
          if ((val & SSTATUS_SDT) != 0) {
              val &= ~SSTATUS_SIE;


Reply via email to