On Sat, 18 Jul 2026 at 00:26, Richard Henderson
<[email protected]> wrote:
>
> Raise alignment fault when DC_ZVA targets Device memory, as required
> by the architecture. With MTE, an alignment exception is not always
> correctly ordered vs a tag check fail exception -- to be fixed in
> followup patches.
>
> Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3005
> Signed-off-by: Richard Henderson <[email protected]>
>
> +void HELPER(dc_zva)(CPUARMState *env, uint64_t addr)
> +{
> + uintptr_t ra = GETPC();
> + size_t len = (size_t)4 << get_dczid_bs(env_archcpu(env));
> + int mmu_idx = arm_env_mmu_index(env);
> + MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED;
I feel like some static analyzer or compiler is going to complain
that this assignment is pointless in the !CONFIG_USER_ONLY case.
Maybe better to set attrs = MEMTXATTRS_UNSPECIFIED inside the
#ifdef CONFIG_USER_ONLY block ?
> + int flags;
> + void *mem;
> +
> + /* DC_ZVA requires that we supply the original pointer for traps. */
> +#ifdef CONFIG_USER_ONLY
> + flags = probe_access_flags(env, addr, 0, MMU_DATA_STORE, mmu_idx,
> + false, &mem, ra);
> +#else
> + CPUTLBEntryFull *full;
> + flags = probe_access_full(env, addr, 0, MMU_DATA_STORE, mmu_idx,
> + false, &mem, &full, ra);
Is 0 really the right size to pass in here? Looking at
probe_access_full(), if you pass in a 0 size then it will
call notdirty_write() with a dirtysize parameter of 1,
which will then not invalidate or set the VGA/migration
dirty bits on the full range of memory we're about to clear.
This would be OK if we then went through the slowpath and
did a set of byte accesses, but probe_access_full() will
clear TLB_NOTDIRTY from the flags it returns to us if it
called notdirty_write(), so we will take the fastpath if
that was the only flag set.
Maybe probe_access_full(), probe_access_full_mmu() and
probe_access_flags() should not call notdirty_write() and
clear TLB_NOTDIRTY from the flags they return if the passed
in size is 0 ?
The notdirty_write() API also wants the base address of the
DC ZVA block (since that's where we will be writing from),
not the address from the guest.
(We may be getting away with some of this because of various
functions rounding up/down to full page addresses, but none
of these functions seem to document that, so we shouldn't
rely on it.)
> + attrs = full->attrs;
> +#endif
> +
> + flags = do_dcxva_traps(env, addr, len, mmu_idx, flags, attrs, ra);
> +
> + /* After traps, treat as aligned blocks. */
> + addr = addr & -len;
> + mem = (void *)((uintptr_t)mem & -len);
> +
> + do_dczva_0(env, addr, len, mem, mmu_idx, flags, ra);
> +}
> +
> /*
> * Perform an MTE checked access for DC_ZVA.
> */
> --
-- PMM