This feature causes tag checks to compare logical address tags against
their canonical form rather than against allocation tags. Described in
the ARM ARM section "Logical Address Tagging".
Signed-off-by: Gabriel Brookman <brookmangabriel@gmail.com>
---
target/arm/internals.h | 29 +++++++++++++++++++++++++++++
target/arm/tcg/mte_helper.c | 20 ++++++++++++++++++++
2 files changed, 49 insertions(+)
diff --git a/target/arm/internals.h b/target/arm/internals.h
index 9cd4bf74ef..31d37b80fb 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -1633,6 +1633,35 @@ static inline bool tcma_check(uint32_t desc, int bit55, int ptr_tag)
return tcma && match;
}
+/* Return whether or not the second nibble of a VA matches bit 55. */
+static inline bool tag_is_canonical(int ptr_tag, int bit55)
+{
+ return ((ptr_tag + bit55) & 0xf) == 0;
+}
+
+/* Return true if mtx bits mean that the access is canonically checked. */
+static inline bool mtx_check(CPUARMState *env, bool bit55)
+{
+ int mmu_idx;
+ uint64_t tcr, mtx_bit;
+
+ /* If mte4 is not implemented, then mtx is by definition not enabled */
+ if (!cpu_isar_feature(aa64_mte4, env_archcpu(env))) {
+ return false;
+ }
+
+ mmu_idx = arm_mmu_idx_el(env, arm_current_el(env));
+ tcr = regime_tcr(env, mmu_idx);
+
+ /*
+ * In two-range regimes, mtx is governed by bit 60 or 61 of TCR, and in
+ * one-range regimes, bit 33 is used.
+ */
+ mtx_bit = regime_has_2_ranges(mmu_idx) ? 60 + bit55 : 33;
+
+ return extract64(tcr, mtx_bit, 1);
+}
+
/*
* For TBI, ideally, we would do nothing. Proper behaviour on fault is
* for the tag to be present in the FAR_ELx register. But for user-only
diff --git a/target/arm/tcg/mte_helper.c b/target/arm/tcg/mte_helper.c
index f0880991b6..6827d030dd 100644
--- a/target/arm/tcg/mte_helper.c
+++ b/target/arm/tcg/mte_helper.c
@@ -825,6 +825,14 @@ static int mte_probe_int(CPUARMState *env, uint32_t desc, uint64_t ptr,
return 1;
}
+ /*
+ * If mtx is enabled, then the access is MemTag_CanonicallyTagged,
+ * otherwise it is MemTag_AllocationTagged. See AArch64.CheckTag.
+ */
+ if (mtx_check(env, bit55)) {
+ return tag_is_canonical(ptr_tag, bit55);
+ }
+
mmu_idx = FIELD_EX32(desc, MTEDESC, MIDX);
type = FIELD_EX32(desc, MTEDESC, WRITE) ? MMU_DATA_STORE : MMU_DATA_LOAD;
sizem1 = FIELD_EX32(desc, MTEDESC, SIZEM1);
@@ -961,6 +969,18 @@ uint64_t HELPER(mte_check_zva)(CPUARMState *env, uint32_t desc, uint64_t ptr)
goto done;
}
+ /*
+ * If mtx is enabled, then the access is MemTag_CanonicallyTagged,
+ * otherwise it is MemTag_AllocationTagged. See AArch64.CheckTag.
+ */
+ if (mtx_check(env, bit55)) {
+ if (tag_is_canonical(ptr_tag, bit55)) {
+ goto done;
+ }
+ mte_check_fail(env, desc, ptr, ra);
+ }
+
+
/*
* In arm_cpu_realizefn, we asserted that dcz > LOG2_TAG_GRANULE+1,
* i.e. 32 bytes, which is an unreasonably small dcz anyway, to make
--
2.52.0