aboutsummaryrefslogtreecommitdiff
path: root/target/arm/helper.c
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2020-06-25 20:31:06 -0700
committerPeter Maydell <peter.maydell@linaro.org>2020-06-26 14:31:12 +0100
commit81ae05fa2d21ac1a0054935b74342aa38a5ecef7 (patch)
treeff3b26bce99f0594f02d987155432a402e16143d /target/arm/helper.c
parent4b779cebb3e5ab30b945181f1ba3932f5f8a1cb5 (diff)
target/arm: Add MTE bits to tb_flags
Cache the composite ATA setting. Cache when MTE is fully enabled, i.e. access to tags are enabled and tag checks affect the PE. Do this for both the normal context and the UNPRIV context. Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20200626033144.790098-9-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target/arm/helper.c')
-rw-r--r--target/arm/helper.c40
1 files changed, 40 insertions, 0 deletions
diff --git a/target/arm/helper.c b/target/arm/helper.c
index b4842ea23e..2c6ec244af 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -10655,6 +10655,16 @@ static int aa64_va_parameter_tbid(uint64_t tcr, ARMMMUIdx mmu_idx)
}
}
+static int aa64_va_parameter_tcma(uint64_t tcr, ARMMMUIdx mmu_idx)
+{
+ if (regime_has_2_ranges(mmu_idx)) {
+ return extract64(tcr, 57, 2);
+ } else {
+ /* Replicate the single TCMA bit so we always have 2 bits. */
+ return extract32(tcr, 30, 1) * 3;
+ }
+}
+
ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
ARMMMUIdx mmu_idx, bool data)
{
@@ -12679,6 +12689,36 @@ static uint32_t rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
}
}
+ if (cpu_isar_feature(aa64_mte, env_archcpu(env))) {
+ /*
+ * Set MTE_ACTIVE if any access may be Checked, and leave clear
+ * if all accesses must be Unchecked:
+ * 1) If no TBI, then there are no tags in the address to check,
+ * 2) If Tag Check Override, then all accesses are Unchecked,
+ * 3) If Tag Check Fail == 0, then Checked access have no effect,
+ * 4) If no Allocation Tag Access, then all accesses are Unchecked.
+ */
+ if (allocation_tag_access_enabled(env, el, sctlr)) {
+ flags = FIELD_DP32(flags, TBFLAG_A64, ATA, 1);
+ if (tbid
+ && !(env->pstate & PSTATE_TCO)
+ && (sctlr & (el == 0 ? SCTLR_TCF0 : SCTLR_TCF))) {
+ flags = FIELD_DP32(flags, TBFLAG_A64, MTE_ACTIVE, 1);
+ }
+ }
+ /* And again for unprivileged accesses, if required. */
+ if (FIELD_EX32(flags, TBFLAG_A64, UNPRIV)
+ && tbid
+ && !(env->pstate & PSTATE_TCO)
+ && (sctlr & SCTLR_TCF0)
+ && allocation_tag_access_enabled(env, 0, sctlr)) {
+ flags = FIELD_DP32(flags, TBFLAG_A64, MTE0_ACTIVE, 1);
+ }
+ /* Cache TCMA as well as TBI. */
+ flags = FIELD_DP32(flags, TBFLAG_A64, TCMA,
+ aa64_va_parameter_tcma(tcr, mmu_idx));
+ }
+
return rebuild_hflags_common(env, fp_el, mmu_idx, flags);
}