target/riscv/csr.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-)
write_mstatus() already handles the reserved UXL value by writing a
legal value instead.
Apply the same handling when writing vsstatus so that reserved UXL
values follow the same WARL behavior.
Factor the common logic into a local helper riscv_write_uxl() and use
it for both mstatus and vsstatus.
Suggested-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
Fixes: f310df58bd2 ("target/riscv: Enable uxl field write")
Signed-off-by: SeungJu Cheon <suunj1331@gmail.com>
---
target/riscv/csr.c | 27 +++++++++++++++++----------
1 file changed, 17 insertions(+), 10 deletions(-)
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index dd9726fcf4..12f1ce5180 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -2012,6 +2012,20 @@ static target_ulong legalize_mpp(CPURISCVState *env, target_ulong old_mpp,
return val;
}
+static uint64_t riscv_write_uxl(CPURISCVState *env, uint64_t val,
+ uint64_t field)
+{
+ RISCVMXL xl = riscv_cpu_mxl(env);
+ uint64_t uxl = get_field(val, field);
+
+ if (uxl == MXL_RV128) {
+ uxl = xl == MXL_RV128 ? MXL_RV64 : xl;
+ val = set_field(val, field, uxl);
+ }
+
+ return val;
+}
+
static RISCVException write_mstatus(CPURISCVState *env, int csrno,
target_ulong val, uintptr_t ra)
{
@@ -2058,17 +2072,8 @@ 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);
- }
+ val = riscv_write_uxl(env, val, MSTATUS64_UXL);
}
}
@@ -5226,6 +5231,8 @@ static RISCVException write_vsstatus(CPURISCVState *env, int csrno,
uint64_t mask = (target_ulong)-1;
if ((val & VSSTATUS64_UXL) == 0) {
mask &= ~VSSTATUS64_UXL;
+ } else {
+ val = riscv_write_uxl(env, val, VSSTATUS64_UXL);
}
if ((env->henvcfg & HENVCFG_DTE)) {
if ((val & SSTATUS_SDT) != 0) {
--
2.52.0
On Thu, Jun 25, 2026 at 6:17 PM SeungJu Cheon <suunj1331@gmail.com> wrote:
>
> write_mstatus() already handles the reserved UXL value by writing a
> legal value instead.
>
> Apply the same handling when writing vsstatus so that reserved UXL
> values follow the same WARL behavior.
>
> Factor the common logic into a local helper riscv_write_uxl() and use
> it for both mstatus and vsstatus.
>
> Suggested-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
> Fixes: f310df58bd2 ("target/riscv: Enable uxl field write")
> Signed-off-by: SeungJu Cheon <suunj1331@gmail.com>
Thanks!
Applied to riscv-to-apply.next
Alistair
> ---
> target/riscv/csr.c | 27 +++++++++++++++++----------
> 1 file changed, 17 insertions(+), 10 deletions(-)
>
> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> index dd9726fcf4..12f1ce5180 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -2012,6 +2012,20 @@ static target_ulong legalize_mpp(CPURISCVState *env, target_ulong old_mpp,
> return val;
> }
>
> +static uint64_t riscv_write_uxl(CPURISCVState *env, uint64_t val,
> + uint64_t field)
> +{
> + RISCVMXL xl = riscv_cpu_mxl(env);
> + uint64_t uxl = get_field(val, field);
> +
> + if (uxl == MXL_RV128) {
> + uxl = xl == MXL_RV128 ? MXL_RV64 : xl;
> + val = set_field(val, field, uxl);
> + }
> +
> + return val;
> +}
> +
> static RISCVException write_mstatus(CPURISCVState *env, int csrno,
> target_ulong val, uintptr_t ra)
> {
> @@ -2058,17 +2072,8 @@ 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);
> - }
> + val = riscv_write_uxl(env, val, MSTATUS64_UXL);
> }
> }
>
> @@ -5226,6 +5231,8 @@ static RISCVException write_vsstatus(CPURISCVState *env, int csrno,
> uint64_t mask = (target_ulong)-1;
> if ((val & VSSTATUS64_UXL) == 0) {
> mask &= ~VSSTATUS64_UXL;
> + } else {
> + val = riscv_write_uxl(env, val, VSSTATUS64_UXL);
> }
> if ((env->henvcfg & HENVCFG_DTE)) {
> if ((val & SSTATUS_SDT) != 0) {
> --
> 2.52.0
>
>
On 6/25/2026 5:15 AM, SeungJu Cheon wrote:
> write_mstatus() already handles the reserved UXL value by writing a
> legal value instead.
>
> Apply the same handling when writing vsstatus so that reserved UXL
> values follow the same WARL behavior.
>
> Factor the common logic into a local helper riscv_write_uxl() and use
> it for both mstatus and vsstatus.
>
> Suggested-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
> Fixes: f310df58bd2 ("target/riscv: Enable uxl field write")
> Signed-off-by: SeungJu Cheon <suunj1331@gmail.com>
> ---
Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
> target/riscv/csr.c | 27 +++++++++++++++++----------
> 1 file changed, 17 insertions(+), 10 deletions(-)
>
> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> index dd9726fcf4..12f1ce5180 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -2012,6 +2012,20 @@ static target_ulong legalize_mpp(CPURISCVState *env, target_ulong old_mpp,
> return val;
> }
>
> +static uint64_t riscv_write_uxl(CPURISCVState *env, uint64_t val,
> + uint64_t field)
> +{
> + RISCVMXL xl = riscv_cpu_mxl(env);
> + uint64_t uxl = get_field(val, field);
> +
> + if (uxl == MXL_RV128) {
> + uxl = xl == MXL_RV128 ? MXL_RV64 : xl;
> + val = set_field(val, field, uxl);
> + }
> +
> + return val;
> +}
> +
> static RISCVException write_mstatus(CPURISCVState *env, int csrno,
> target_ulong val, uintptr_t ra)
> {
> @@ -2058,17 +2072,8 @@ 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);
> - }
> + val = riscv_write_uxl(env, val, MSTATUS64_UXL);
> }
> }
>
> @@ -5226,6 +5231,8 @@ static RISCVException write_vsstatus(CPURISCVState *env, int csrno,
> uint64_t mask = (target_ulong)-1;
> if ((val & VSSTATUS64_UXL) == 0) {
> mask &= ~VSSTATUS64_UXL;
> + } else {
> + val = riscv_write_uxl(env, val, VSSTATUS64_UXL);
> }
> if ((env->henvcfg & HENVCFG_DTE)) {
> if ((val & SSTATUS_SDT) != 0) {
© 2016 - 2026 Red Hat, Inc.