On Thu, 2026-08-20 at 21:03 -0700, Richard Henderson wrote: > Alignment faults generally have precedence over page faults, > therefore we need to test for that before probing pages. > > Signed-off-by: Richard Henderson <[email protected]>
Reviewed-by: Alistair Francis <[email protected]> Alistair > --- > target/riscv/tcg/vector_helper.c | 62 +++++++++++++++++++++++++----- > -- > 1 file changed, 50 insertions(+), 12 deletions(-) > > diff --git a/target/riscv/tcg/vector_helper.c > b/target/riscv/tcg/vector_helper.c > index 63a51f2b48..18840336cb 100644 > --- a/target/riscv/tcg/vector_helper.c > +++ b/target/riscv/tcg/vector_helper.c > @@ -31,6 +31,9 @@ > #include "tcg/tcg-gvec-desc.h" > #include "internals.h" > #include "vector_internals.h" > +#ifdef CONFIG_USER_ONLY > +#include "user/cpu_loop.h" > +#endif > #include <math.h> > > static target_ulong vtype_reserved(CPURISCVState *env, target_ulong > vtype) > @@ -433,16 +436,7 @@ vext_page_ldst_us(CPURISCVState *env, void *vd, > target_ulong addr, > probe_pages(env, addr, size, ra, access_type, mmu_index, &host, > &flags, > true); > > - bool misaligned = addr & (esz - 1); > - > - /* > - * Allow the host fast-pash when: > - * 1. Page permission/pmp/watchpoint are checked and we have a > contigous > - * host mapping. > - * 2. Zicclsm is enabled or load/store is not a misaligned > access. > - * Otherwise, we will fall back to the slow TLB-path. > - */ > - if (flags == 0 && (riscv_cpu_cfg(env)->ext_zicclsm || > !misaligned)) { > + if (flags == 0) { > if (nf == 1) { > vext_continuous_ldst_host(env, ldst_host, vd, evl, env- > >vstart, > host, esz, is_load); > @@ -462,6 +456,20 @@ vext_page_ldst_us(CPURISCVState *env, void *vd, > target_ulong addr, > } > } > > +static void vext_test_alignment(CPURISCVState *env, vaddr addr, > uint32_t esz, > + MMUAccessType access_type, int > mmu_index, > + uintptr_t ra) > +{ > + if (!riscv_cpu_cfg(env)->ext_zicclsm && (addr & (esz - 1)) != 0) > { > +#ifdef CONFIG_USER_ONLY > + cpu_loop_exit_sigbus(env_cpu(env), addr, access_type, ra); > +#else > + riscv_cpu_do_unaligned_access(env_cpu(env), addr, > access_type, > + mmu_index, ra); > +#endif > + } > +} > + > static inline QEMU_ALWAYS_INLINE void > vext_ldst_us(void *vd, target_ulong base, CPURISCVState *env, > uint32_t desc, > vext_ldst_elem_fn_tlb *ldst_tlb, > @@ -474,16 +482,21 @@ vext_ldst_us(void *vd, target_ulong base, > CPURISCVState *env, uint32_t desc, > uint32_t esz = 1 << log2_esz; > uint32_t msize = nf * esz; > int mmu_index = riscv_env_mmu_index(env, false); > + MMUAccessType access_type = is_load ? MMU_DATA_LOAD : > MMU_DATA_STORE; > > VSTART_CHECK_EARLY_EXIT(env, evl); > > + addr = base + env->vstart * msize; > + > + /* Recognize alignment fault before memory protection fault. */ > + vext_test_alignment(env, addr, esz, access_type, mmu_index, ra); > + > #if defined(CONFIG_USER_ONLY) > /* > * For data sizes <= 6 bytes we get better performance > * by simply calling ldst_tlb. > */ > if (nf == 1 && (evl << log2_esz) <= 6) { > - addr = base + (env->vstart << log2_esz); > for (uint32_t i = env->vstart; i < evl; > env->vstart = ++i, addr += esz) { > ldst_tlb(env, adjust_addr(env, addr), i, vd, ra); > @@ -495,7 +508,6 @@ vext_ldst_us(void *vd, target_ulong base, > CPURISCVState *env, uint32_t desc, > #endif > > /* Calculate the page range of first page */ > - addr = base + ((env->vstart * nf) << log2_esz); > page_split = -(addr | TARGET_PAGE_MASK); > /* Get number of elements */ > elems = page_split / msize; > @@ -725,7 +737,27 @@ vext_ldff(void *vd, void *v0, target_ulong base, > CPURISCVState *env, > > VSTART_CHECK_EARLY_EXIT(env, env->vl); > > + /* Search for the first active element. */ > + if (!vm) { > + for (i = env->vstart; i < env->vl; ++i) { > + if (vext_elem_mask(v0, i)) { > + break; > + } > + if (vma) { > + vext_set_nf_elems_1s(vd, i, nf, esz, max_elems); > + } > + } > + if (i == env->vl) { > + goto tail; > + } > + env->vstart = i; > + } > + > addr = base + ((env->vstart * nf) << log2_esz); > + > + /* Recognize alignment fault before memory protection fault. */ > + vext_test_alignment(env, addr, esz, MMU_DATA_LOAD, mmu_index, > ra); > + > page_split = -(addr | TARGET_PAGE_MASK); > /* Get number of elements */ > elems = page_split / msize; > @@ -823,6 +855,7 @@ ProbeSuccess: > } > } > > + tail: > env->vstart = 0; > vext_set_tail_elems_1s(env->vl, vd, desc, nf, esz, max_elems); > } > @@ -866,9 +899,14 @@ vext_ldst_whole(void *vd, target_ulong base, > CPURISCVState *env, uint32_t desc, > uint32_t evl = nf * max_elems; > uint32_t esz = 1 << log2_esz; > int mmu_index = riscv_env_mmu_index(env, false); > + MMUAccessType access_type = is_load ? MMU_DATA_LOAD : > MMU_DATA_STORE; > > /* Calculate the page range of first page */ > addr = base + (env->vstart << log2_esz); > + > + /* Recognize alignment fault before memory protection fault. */ > + vext_test_alignment(env, addr, esz, access_type, mmu_index, ra); > + > page_split = -(addr | TARGET_PAGE_MASK); > /* Get number of elements */ > elems = page_split / esz;
