@samitouri / QOSamiQemu / commits / 907f99861b

target/arm: implement MTE_PERM

Introduces a new stage 2 memory attribute, NoTagAccess, that raises a stage 2 data abort on a tag check, tag read, or tag write. Signed-off-by: Gabriel Brookman <brookmangabriel@gmail.com> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260529-feat-mte4-v7-1-ccbd3c14eb3c@gmail.com Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Gabriel Brookman committed May 29, 2026 at 12:52 UTC 907f99861beb7d209695d114352c2e894c520cda
3 files changed +63 -5
target/arm/cpu-features.h
+5
@@ -1191,6 +1191,11 @@ static inline bool isar_feature_aa64_mte3(const ARMISARegisters *id)
1191 return FIELD_EX64_IDREG(id, ID_AA64PFR1, MTE) >= 3;
1192 }
1193
1194 +static inline bool isar_feature_aa64_mteperm(const ARMISARegisters *id)
1195 +{
1196 + return FIELD_EX64_IDREG(id, ID_AA64PFR2, MTEPERM) >= 1;
1197 +}
1198 +
1199 static inline bool isar_feature_aa64_sme(const ARMISARegisters *id)
1200 {
1201 return FIELD_EX64_IDREG(id, ID_AA64PFR1, SME) != 0;
target/arm/ptw.c
+22 -3
@@ -3415,7 +3415,7 @@ static ARMCacheAttrs combine_cacheattrs(uint64_t hcr,
3415 ARMCacheAttrs s1, ARMCacheAttrs s2)
3416 {
3417 ARMCacheAttrs ret;
3418 - bool tagged = false;
3418 + bool tagged = false, notagaccess = false;
3419
3420 assert(!s1.is_s2_format);
3421 ret.is_s2_format = false;
@@ -3425,6 +3425,18 @@ static ARMCacheAttrs combine_cacheattrs(uint64_t hcr,
3425 s1.attrs = 0xff;
3426 }
3427
3428 + if (hcr & HCR_FWB) {
3429 + if (s2.attrs >= 0xe) {
3430 + notagaccess = true;
3431 + s2.attrs = 0x7;
3432 + }
3433 + } else {
3434 + if (s2.attrs == 0x4) {
3435 + notagaccess = true;
3436 + s2.attrs = 0xf;
3437 + }
3438 + }
3439 +
3440 /* Combine shareability attributes (table D4-43) */
3441 if (s1.shareability == 2 || s2.shareability == 2) {
3442 /* if either are outer-shareable, the result is outer-shareable */
@@ -3456,9 +3468,16 @@ static ARMCacheAttrs combine_cacheattrs(uint64_t hcr,
3468 ret.shareability = 2;
3469 }
3470
3459 - /* TODO: CombineS1S2Desc does not consider transient, only WB, RWA. */
3471 + /*
3472 + * The attr encoding 0xe0 corresponds to Tagged NoTagAccess and is only
3473 + * valid with FEAT_MTE_PERM (otherwise RESERVED, constrained
3474 + * unpredictable)). The presence of this feature is checked in
3475 + * allocation_tag_mem_probe, where Tagged NoTagAccess has its effect. See
3476 + * J1.3.5.2 EncodePARAttrs.
3477 + * TODO: CombineS1S2Desc does not consider transient, only WB, RWA.
3478 + */
3479 if (tagged && ret.attrs == 0xff) {
3461 - ret.attrs = 0xf0;
3480 + ret.attrs = notagaccess ? 0xe0 : 0xf0;
3481 }
3482
3483 return ret;
target/arm/tcg/mte_helper.c
+36 -2
@@ -58,6 +58,27 @@ static int choose_nonexcluded_tag(int tag, int offset, uint16_t exclude)
58 return tag;
59 }
60
61 +#ifndef CONFIG_USER_ONLY
62 +/*
63 + * Constructs S2 Permission Fault as described in ARM ARM "Stage 2 Memory
64 + * Tagging Attributes".
65 + */
66 +static void mte_perm_check_fail(CPUARMState *env, uint64_t dirty_ptr,
67 + uintptr_t ra, bool is_write)
68 +{
69 + uint64_t syn;
70 +
71 + env->exception.vaddress = dirty_ptr;
72 +
73 + syn = syn_data_abort_no_iss(0, 0, 0, 0, 0, is_write, 0);
74 +
75 + syn |= BIT_ULL(41); /* TagAccess is bit 41 */
76 +
77 + raise_exception_ra(env, EXCP_DATA_ABORT, syn, 2, ra);
78 + g_assert_not_reached();
79 +}
80 +#endif
81 +
82 uint8_t *allocation_tag_mem_probe(CPUARMState *env, int ptr_mmu_idx,
83 uint64_t ptr, MMUAccessType ptr_access,
84 int ptr_size, MMUAccessType tag_access,
@@ -117,8 +138,21 @@ uint8_t *allocation_tag_mem_probe(CPUARMState *env, int ptr_mmu_idx,
138 }
139 assert(!(flags & TLB_INVALID_MASK));
140
120 - /* If the virtual page MemAttr != Tagged, access unchecked. */
121 - if (full->extra.arm.pte_attrs != 0xf0) {
141 + switch (full->extra.arm.pte_attrs) {
142 + case 0xf0: /* Tagged */
143 + break;
144 +
145 + case 0xe0: /* NoTagAccess */
146 + if (cpu_isar_feature(aa64_mteperm, env_archcpu(env))) {
147 + if (probe) {
148 + return NULL;
149 + }
150 + assert(ra);
151 + mte_perm_check_fail(env, ptr, ra, tag_access == MMU_DATA_STORE);
152 + }
153 + /* fall through */
154 +
155 + default: /* Not Tagged */
156 return NULL;
157 }
158