[PATCH] target/riscv: Fix vsstatus.UXL reserved value

SeungJu Cheon posted 1 patch 1 month ago
Patches applied successfully (tree, apply log)
git fetch https://github.com/patchew-project/qemu tags/patchew/20260624090052.463075-1-suunj1331@gmail.com
Maintainers: Palmer Dabbelt <palmer@dabbelt.com>, Alistair Francis <alistair.francis@wdc.com>, Weiwei Li <liwei1518@gmail.com>, Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>, Liu Zhiwei <zhiwei_liu@linux.alibaba.com>, Chao Liu <chao.liu.zevorn@gmail.com>
target/riscv/csr.c | 8 ++++++++
1 file changed, 8 insertions(+)
[PATCH] target/riscv: Fix vsstatus.UXL reserved value
Posted by SeungJu Cheon 1 month ago
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 <suunj1331@gmail.com>
---
 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);
+        }
     }
+
     if ((env->henvcfg & HENVCFG_DTE)) {
         if ((val & SSTATUS_SDT) != 0) {
             val &= ~SSTATUS_SIE;
-- 
2.52.0
Re: [PATCH] target/riscv: Fix vsstatus.UXL reserved value
Posted by Daniel Henrique Barboza 1 month ago
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 <suunj1331@gmail.com>
> ---
>   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 <daniel.barboza@oss.qualcomm.com>
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;
Re: [PATCH] target/riscv: Fix vsstatus.UXL reserved value
Posted by SeungJu Cheon 1 month ago
Thanks for the review, Daniel.

I'll add a helper function and resend as v2.

Best regards,
SeungJu

On Wed, Jun 24, 2026 at 9:34 PM Daniel Henrique Barboza
<daniel.barboza@oss.qualcomm.com> wrote:
>
> 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 <suunj1331@gmail.com>
> > ---
> >   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 <daniel.barboza@oss.qualcomm.com>
> 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;
>