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

Reply via email to