On 2026-01-28 14:26, Sebastien Michelland wrote:
> 
> >> GEN_LDST_WHOLE_TRANS checks for require_rvv but it's always true, even with
> >> e.g. -cpu=rv32,v=false.
> >> --- a/target/riscv/insn_trans/trans_rvv.c.inc
> >> +++ b/target/riscv/insn_trans/trans_rvv.c.inc
> >> @@ -1235,6 +1235,7 @@ static bool ldst_whole_trans(uint32_t vd, uint32_t 
> >> rs1,
> >> uint32_t nf,
> >>   static bool trans_##NAME(DisasContext *s, arg_##NAME * a)                
> >>    \
> >>   {                                                                        
> >>    \
> >>       if (require_rvv(s) &&                                                
> >>    \
> >> +        vext_check_isa_ill(s) &&                                          
> >>   \
> >>           QEMU_IS_ALIGNED(a->rd, ARG_NF)) {                                
> >>    \
> >>           return ldst_whole_trans(a->rd, a->rs1, ARG_NF, 
> >> ctzl(sizeof(ETYPE)), \
> > >                                   gen_helper_##NAME, s, IS_LOAD);         
> > >     \
>
Hi Sebastien,

Thank you for this patch and for identifying this bug.

But I think that the proposed fix of adding vext_check_isa_ill to whole
register load/store instructions will violate the RISC-V vector specification.

There is an existing comment in trans_rvv.c.inc:

    /*
     * load and store whole register instructions ignore vtype and vl setting.
     * Thus, we don't need to check vill bit. (Section 7.9)
     */

The RISC-V unpriviledge specification (31.3.4.4. Vector Type Illegal (vill))
states that whole register load/store instructions do not depend on vtype:

    "If the vill bit is set, then any attempt to execute a vector instruction
    that depends upon vtype will raise an illegal-instruction exception.
    NOTE: vset{i}vl{i} and whole register loads and stores do not depend
    upon vtype."

- https://github.com/riscv/riscv-isa-manual

This means whole register instructions (vl*r.v, vs*r.v) should not check
the vill bit.

The Spike reference implementation confirms this interpretation. Whole
register instructions use require_vector_novtype which does not check vill,
while regular vector instructions use require_vector which does:

    // riscv/v_ext_macros.h - used by vl*r.v, vs*r.v
    #define VI_ST_WHOLE \
      require_vector_novtype(true); \
      ...

    // riscv/decode_macros.h
    #define require_vector_novtype(is_log) \
      do { \
        require_vector_vs;    // Only checks VS status
        ...
      } while (0);            // NO vill check!

    #define require_vector(alu) \
      do { \
        require_vector_vs;
        require(!P.VU.vill);  // Checks vill
        ...
      } while (0);

- https://github.com/riscv-software-src/riscv-isa-sim

With this patch, whole register load/store instructions would incorrectly
raise illegal instruction exceptions when vill=1, even though the V extension
is enabled.

I would recommend that we should fix this bug at riscv_get_tb_cpu_state by
checking the CPU configuration in CONFIG_USER_ONLY block (user mode) to
ensures require_rvv returns false when the vector is disabled.

Thanks,
rnax

Reply via email to