ldst_whole_trans() takes an inline TCG path that performs 8-byte host accesses and increments vstart by 8 >> log2_esz after each access. When one of those accesses faults across a page boundary, vstart is left at the host-chunk boundary instead of the faulting element index, and with small VLEN (e.g. VLEN=32) the 8-byte access can also spill into the neighbouring register. The existing element-sized helper path (vext_ldst_whole) reports precise vstart and keeps register boundaries, so always use it.
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4150 Signed-off-by: wangyang <[email protected]> --- target/riscv/tcg/insn_trans/trans_rvv.c.inc | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/target/riscv/tcg/insn_trans/trans_rvv.c.inc b/target/riscv/tcg/insn_trans/trans_rvv.c.inc index 23262b1d036..9b9a751e58e 100644 --- a/target/riscv/tcg/insn_trans/trans_rvv.c.inc +++ b/target/riscv/tcg/insn_trans/trans_rvv.c.inc @@ -1192,7 +1192,13 @@ static bool ldst_whole_trans(uint32_t vd, uint32_t rs1, uint32_t nf, * - vstart is not 0. */ - bool use_helper_fn = !s->vstart_eq_zero; + /* + * The inline path groups bytes into host-sized accesses. A fault in + * the middle of such an access cannot be represented by the resulting + * element-index vstart, so use the element-sized helper path whenever + * precise restart state can be observed. + */ + bool use_helper_fn = true; if (!use_helper_fn) { uint32_t size = s->cfg_ptr->vlenb * nf; -- 2.43.0
