@samitouri / QOSamiQemu / commits / 5bd4fa5c6c

target/arm: add canonical MTE check logic

With MTX active, address tag bits are checked for canonicity if the corresponding memory regions are not allocation tagged. See AArch64_CheckTag. Signed-off-by: Gabriel Brookman <brookmangabriel@gmail.com> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260529-feat-mte4-v7-8-ccbd3c14eb3c@gmail.com Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Gabriel Brookman committed May 29, 2026 at 12:52 UTC 5bd4fa5c6c202da0e5110674c4f0354decce551f
2 files changed +32 -4
target/arm/internals.h
+6
@@ -1658,6 +1658,12 @@ static inline uint64_t address_with_allocation_tag(uint64_t ptr, int rtag)
1658 return deposit64(ptr, 56, 4, rtag);
1659 }
1660
1661 +/* Return true if mtx bits mean that the access is canonically checked. */
1662 +static inline bool mtx_check(uint32_t desc, int bit55)
1663 +{
1664 + return (desc >> (R_MTEDESC_MTX_SHIFT + bit55)) & 1;
1665 +}
1666 +
1667 /* Return true if tbi or mtx bits mean that the access is tag checked. */
1668 static inline bool tbi_or_mtx_check(uint32_t desc, int bit55)
1669 {
target/arm/tcg/mte_helper.c
+26 -4
@@ -858,6 +858,14 @@ static int mte_probe_int(CPUARMState *env, uint32_t desc, uint64_t ptr,
858 mem1 = allocation_tag_mem(env, mmu_idx, ptr, type, sizem1 + 1,
859 MMU_DATA_LOAD, ra);
860 if (!mem1) {
861 + /*
862 + * If mtx is enabled, then the access is MemTag_CanonicallyTagged,
863 + * otherwise it is Untagged. See AArch64.S1DecodeMemAttrs and
864 + * AArch64.S1DisabledOutput.
865 + */
866 + if (mtx_check(desc, bit55)) {
867 + return tag_is_canonical(ptr_tag, bit55);
868 + }
869 return 1;
870 }
871 /* Perform all of the comparisons. */
@@ -873,18 +881,24 @@ static int mte_probe_int(CPUARMState *env, uint32_t desc, uint64_t ptr,
881
882 /*
883 * Perform all of the comparisons.
876 - * Note the possible but unlikely case of the operation spanning
877 - * two pages that do not both have tagging enabled.
884 + * Note the possible but unlikely case of the operation spanning two
885 + * pages that do not both have allocation tagging enabled. This can
886 + * happen with or without mtx (canonical tagging) enabled.
887 */
888 n = c = (next_page - tag_first) / TAG_GRANULE;
889 if (mem1) {
890 n = checkN(mem1, ptr & TAG_GRANULE, ptr_tag, c);
891 + } else if (mtx_check(desc, bit55) &&
892 + !tag_is_canonical(ptr_tag, bit55)) {
893 + return 0;
894 }
895 if (n == c) {
884 - if (!mem2) {
896 + if (mem2) {
897 + n += checkN(mem2, 0, ptr_tag, tag_count - c);
898 + } else if (!mtx_check(desc, bit55) ||
899 + tag_is_canonical(ptr_tag, bit55)) {
900 return 1;
901 }
887 - n += checkN(mem2, 0, ptr_tag, tag_count - c);
902 }
903 }
904
@@ -999,6 +1013,14 @@ uint64_t HELPER(mte_check_zva)(CPUARMState *env, uint32_t desc, uint64_t ptr)
1013 mem = allocation_tag_mem(env, mmu_idx, align_ptr, MMU_DATA_STORE,
1014 dcz_bytes, MMU_DATA_LOAD, ra);
1015 if (!mem) {
1016 + /*
1017 + * If mtx is enabled, then the access is MemTag_CanonicallyTagged,
1018 + * otherwise it is Untagged. See AArch64.S1DecodeMemAttrs and
1019 + * AArch64.S1DisabledOutput.
1020 + */
1021 + if (mtx_check(desc, bit55) && !tag_is_canonical(ptr_tag, bit55)) {
1022 + mte_check_fail(env, desc, ptr, ra);
1023 + }
1024 goto done;
1025 }
1026