target/riscv/tcg/tcg-cpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
trans_rvv.c.inc checks for the RVV extension through the function
require_rvv. However, at least under CONFIG_USER_ONLY, the RVV extension
status in DisasContex->mstatus_vs is always set to DIRTY, therefore
treating RVV instructions as legal even when the extension is not
present, e.g. with -cpu=rv32,v=false.
This bug manifests rarely because vset{i}vl{i} perform extra checks that
do fail without RVV, thus raising SIGILL, and with no vtype set nearly
all other RVV instructions still pass require_rvv but fail the vill check.
Only instructions that don't depend on type (whole-register load/stores,
such as vs*r.v) would show the bug by being executed when v=false.
This patch sets mstatus_vs to DISABLED when RVV is not present (checked
with the minimalistic Zve32x), meaning require_rvv now fails as intended.
Signed-off-by: Sébastien Michelland <sebastien.michelland@inria.fr>
---
Thanks Max for your patience with this patch.
target/riscv/tcg/tcg-cpu.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
index 988b2d905f..9c2c3ac278 100644
--- a/target/riscv/tcg/tcg-cpu.c
+++ b/target/riscv/tcg/tcg-cpu.c
@@ -153,7 +153,7 @@ static TCGTBCPUState riscv_get_tb_cpu_state(CPUState *cs)
#ifdef CONFIG_USER_ONLY
fs = EXT_STATUS_DIRTY;
- vs = EXT_STATUS_DIRTY;
+ vs = cpu->cfg.ext_zve32x ? EXT_STATUS_DIRTY : EXT_STATUS_DISABLED;
#else
flags = FIELD_DP32(flags, TB_FLAGS, PRIV, env->priv);
--
2.52.0
On 2026-02-06 11:01, Sébastien Michelland wrote:
> trans_rvv.c.inc checks for the RVV extension through the function
> require_rvv. However, at least under CONFIG_USER_ONLY, the RVV extension
> status in DisasContex->mstatus_vs is always set to DIRTY, therefore
> treating RVV instructions as legal even when the extension is not
> present, e.g. with -cpu=rv32,v=false.
>
> This bug manifests rarely because vset{i}vl{i} perform extra checks that
> do fail without RVV, thus raising SIGILL, and with no vtype set nearly
> all other RVV instructions still pass require_rvv but fail the vill check.
> Only instructions that don't depend on type (whole-register load/stores,
> such as vs*r.v) would show the bug by being executed when v=false.
>
> This patch sets mstatus_vs to DISABLED when RVV is not present (checked
> with the minimalistic Zve32x), meaning require_rvv now fails as intended.
>
> Signed-off-by: Sébastien Michelland <sebastien.michelland@inria.fr>
> ---
> Thanks Max for your patience with this patch.
Reviewed-by: Max Chou <max.chou@sifive.com>
rnax
Hi Sébastien,
On Fri, Feb 06, 2026 at 11:01:23AM +0100, Sébastien Michelland wrote:
> trans_rvv.c.inc checks for the RVV extension through the function
> require_rvv. However, at least under CONFIG_USER_ONLY, the RVV extension
> status in DisasContex->mstatus_vs is always set to DIRTY, therefore
> treating RVV instructions as legal even when the extension is not
> present, e.g. with -cpu=rv32,v=false.
>
> This bug manifests rarely because vset{i}vl{i} perform extra checks that
> do fail without RVV, thus raising SIGILL, and with no vtype set nearly
> all other RVV instructions still pass require_rvv but fail the vill check.
> Only instructions that don't depend on type (whole-register load/stores,
> such as vs*r.v) would show the bug by being executed when v=false.
>
> This patch sets mstatus_vs to DISABLED when RVV is not present (checked
> with the minimalistic Zve32x), meaning require_rvv now fails as intended.
>
> Signed-off-by: Sébastien Michelland <sebastien.michelland@inria.fr>
> ---
> Thanks Max for your patience with this patch.
>
> target/riscv/tcg/tcg-cpu.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
> index 988b2d905f..9c2c3ac278 100644
> --- a/target/riscv/tcg/tcg-cpu.c
> +++ b/target/riscv/tcg/tcg-cpu.c
> @@ -153,7 +153,7 @@ static TCGTBCPUState riscv_get_tb_cpu_state(CPUState *cs)
>
> #ifdef CONFIG_USER_ONLY
> fs = EXT_STATUS_DIRTY;
> - vs = EXT_STATUS_DIRTY;
> + vs = cpu->cfg.ext_zve32x ? EXT_STATUS_DIRTY : EXT_STATUS_DISABLED;
This change looks good and perfect to me. Thanks for your contribution!
Reviewed-by: Chao Liu <chao.liu.zevorn@gmail.com>
Thanks,
Chao
> #else
> flags = FIELD_DP32(flags, TB_FLAGS, PRIV, env->priv);
>
> --
> 2.52.0
>
>
© 2016 - 2026 Red Hat, Inc.