qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v5 16/22] target/arm: Implement data cache set allocation tag


From: Peter Maydell
Subject: Re: [PATCH v5 16/22] target/arm: Implement data cache set allocation tags
Date: Thu, 5 Dec 2019 18:17:27 +0000

On Fri, 11 Oct 2019 at 14:50, Richard Henderson
<address@hidden> wrote:
>
> This is DC GVA and DC GZVA.
>
> Signed-off-by: Richard Henderson <address@hidden>
> ---
> v2: Use allocation_tag_mem + memset.
> v3: Require pre-cleaned addresses.
> ---

> diff --git a/target/arm/mte_helper.c b/target/arm/mte_helper.c
> index f1315bae37..e8d8a6bedb 100644
> --- a/target/arm/mte_helper.c
> +++ b/target/arm/mte_helper.c
> @@ -510,3 +510,31 @@ void HELPER(stzgm)(CPUARMState *env, uint64_t ptr, 
> uint64_t val)
>          }
>      }
>  }
> +
> +void HELPER(dc_gva)(CPUARMState *env, uint64_t ptr)
> +{
> +    ARMCPU *cpu = env_archcpu(env);
> +    size_t blocklen = 4 << cpu->dcz_blocksize;
> +    int el;
> +    uint64_t sctlr;
> +    uint8_t *mem;
> +    int rtag;
> +
> +    ptr = QEMU_ALIGN_DOWN(ptr, blocklen);
> +
> +    /* Trap if accessing an invalid page.  */
> +    mem = allocation_tag_mem(env, ptr, true, GETPC());
> +
> +    /* No action if page does not support tags, or if access is disabled.  */
> +    el = arm_current_el(env);
> +    sctlr = arm_sctlr(env, el);
> +    if (!mem || !allocation_tag_access_enabled(env, el, sctlr)) {
> +        return;
> +    }
> +
> +    rtag = allocation_tag_from_addr(ptr);
> +    rtag |= rtag << 4;
> +
> +    assert(QEMU_IS_ALIGNED(blocklen, 2 * TAG_GRANULE));

Could we assert this on CPU init rather than in this helper?
That way if anybody tries to create a CPU whose dcz_blocksize
doesn't work with the TAG_GRANULE they'll realize immediately
rather than only if they happen to run a guest workload that
use DC GVA or DC GZVA.

I also had to think a bit to work out which way round this
assert is checking: it's testing that the ZVA block length
(usually 64 bytes) is a multiple of (twice the TAG_GRANULE),
which is to say a multiple of 32. Given that the blocksize
is stored as a log2 value, this can only fail for blocksizes
16, 8, 4, 2 or 1, which are all fairly unlikely.

> +    memset(mem, rtag, blocklen / (2 * TAG_GRANULE));
> +}
> diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
> index 49817b96ae..31260f97f9 100644
> --- a/target/arm/translate-a64.c
> +++ b/target/arm/translate-a64.c
> @@ -1769,6 +1769,15 @@ static void handle_sys(DisasContext *s, uint32_t insn, 
> bool isread,
>          tcg_rt = clean_data_tbi(s, cpu_reg(s, rt), false);
>          gen_helper_dc_zva(cpu_env, tcg_rt);
>          return;
> +    case ARM_CP_DC_GVA:
> +        tcg_rt = clean_data_tbi(s, cpu_reg(s, rt), false);
> +        gen_helper_dc_gva(cpu_env, tcg_rt);
> +        return;
> +    case ARM_CP_DC_GZVA:
> +        tcg_rt = clean_data_tbi(s, cpu_reg(s, rt), false);
> +        gen_helper_dc_zva(cpu_env, tcg_rt);
> +        gen_helper_dc_gva(cpu_env, tcg_rt);

I think this means that if there's a watchpoint set on the memory
partway through the block we're zeroing then we'll take the
watchpoint with some of the memory zeroed but without the
corresponding tags having been updated. But that's probably OK
(at any rate I wouldn't worry about it for now...)

> +        return;
>      default:
>          break;
>      }
> --

Otherwise
Reviewed-by: Peter Maydell <address@hidden>

thanks
-- PMM



reply via email to

[Prev in Thread] Current Thread [Next in Thread]