@samitouri / QOSamiQemu / commits / 0e8ad6a846

target/riscv: rvv: Fix page probe issues in vext_ldff

Commit 17288e38bebf ("optimize the memory probing for vector fault-only-first loads") introduced an optimization that moved from per-element probing to a fast-path broad probe. Unfortunately it introduced following bugs in cross-page handling: - Wrong condition for second page probing: checked "env->vl > elems" instead of "env->vl > elems + env->vstart", failing to account for the vstart offset. - Incorrect second page address calculation: used "addr + (elems << log2_esz)" instead of "addr + page_split". For segment loads (nf > 1), this would probe the wrong address,not at the page boundary. - Wrong second page probe size: used "elems * msize" (the first page size) instead of calculating the remaining size as "(env->vl - env->vstart) * msize - page_split". This would probe too little memory and could miss faults. This commit fixes these bugs by leveraging the probe_pages helper which automatically handles cross-page memory accesses correctly. Fixes: 17288e38bebf ("optimize the memory probing for vector fault-only-first loads.") Signed-off-by: Max Chou <max.chou@sifive.com> Acked-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260318013805.1920377-3-max.chou@sifive.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>

Max Chou committed Mar 18, 2026 at 09:38 UTC 0e8ad6a8460fe070ecdde4625e4ed6d791550e3d
1 file changed +4 -12
target/riscv/vector_helper.c
+4 -12
@@ -658,9 +658,9 @@ vext_ldff(void *vd, void *v0, target_ulong base, CPURISCVState *env,
658 uint32_t esz = 1 << log2_esz;
659 uint32_t msize = nf * esz;
660 uint32_t vma = vext_vma(desc);
661 - target_ulong addr, addr_probe, addr_i, offset, remain, page_split, elems;
661 + target_ulong addr, addr_i, offset, remain, page_split, elems;
662 int mmu_index = riscv_env_mmu_index(env, false);
663 - int flags, probe_flags;
663 + int flags;
664 void *host;
665
666 VSTART_CHECK_EARLY_EXIT(env, env->vl);
@@ -674,16 +674,8 @@ vext_ldff(void *vd, void *v0, target_ulong base, CPURISCVState *env,
674 }
675
676 /* Check page permission/pmp/watchpoint/etc. */
677 - probe_pages(env, addr, elems * msize, ra, MMU_DATA_LOAD, mmu_index, &host,
678 - &flags, true);
679 -
680 - /* If we are crossing a page check also the second page. */
681 - if (env->vl > elems) {
682 - addr_probe = addr + (elems << log2_esz);
683 - probe_pages(env, addr_probe, elems * msize, ra, MMU_DATA_LOAD,
684 - mmu_index, &host, &probe_flags, true);
685 - flags |= probe_flags;
686 - }
677 + probe_pages(env, addr, (env->vl - env->vstart) * msize, ra, MMU_DATA_LOAD,
678 + mmu_index, &host, &flags, true);
679
680 if (flags & ~TLB_WATCHPOINT) {
681 /* probe every access */