target/arm: skip tag bit bounds check if MTX is on
Virtual address canonicity checks should ignore mismatch in tag bits during translation step if MTX is set. This mismatch is checked during the tag check instead, in that case. Signed-off-by: Gabriel Brookman <brookmangabriel@gmail.com> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260529-feat-mte4-v7-11-ccbd3c14eb3c@gmail.com Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Gabriel Brookman committed
May 29, 2026 at 12:52 UTC
46100e93c62e474c3f1e93a4fc0d2c723f1756d0
3 files changed
+36
-6
target/arm/helper.c
+5
-1
@@ -9795,7 +9795,7 @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
9795
{
9796
uint64_t tcr = regime_tcr(env, mmu_idx);
9797
bool epd, hpd, tsz_oob, ds, ha, hd, pie = false;
9798
- bool aie = false;
9798
+ bool mtx, aie = false;
9799
int select, tsz, tbi, max_tsz, min_tsz, ps, sh;
9800
ARMGranuleSize gran;
9801
ARMCPU *cpu = env_archcpu(env);
@@ -9832,6 +9832,7 @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
9832
ha = extract32(tcr, 21, 1) && cpu_isar_feature(aa64_hafs, cpu);
9833
hd = extract32(tcr, 22, 1) && cpu_isar_feature(aa64_hdbs, cpu);
9834
ds = extract64(tcr, 32, 1);
9835
+ mtx = extract64(tcr, 33, 1) && cpu_isar_feature(aa64_mte_mtx, cpu);
9836
} else {
9837
bool e0pd;
9838
@@ -9847,6 +9848,7 @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
9848
sh = extract32(tcr, 12, 2);
9849
hpd = extract64(tcr, 41, 1);
9850
e0pd = extract64(tcr, 55, 1);
9851
+ mtx = extract64(tcr, 60, 1) && cpu_isar_feature(aa64_mte_mtx, cpu);
9852
} else {
9853
tsz = extract32(tcr, 16, 6);
9854
gran = tg1_to_gran_size(extract32(tcr, 30, 2));
@@ -9854,6 +9856,7 @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
9856
sh = extract32(tcr, 28, 2);
9857
hpd = extract64(tcr, 42, 1);
9858
e0pd = extract64(tcr, 56, 1);
9859
+ mtx = extract64(tcr, 61, 1) && cpu_isar_feature(aa64_mte_mtx, cpu);
9860
}
9861
ps = extract64(tcr, 32, 3);
9862
ha = extract64(tcr, 39, 1) && cpu_isar_feature(aa64_hafs, cpu);
@@ -9953,6 +9956,7 @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
9956
.gran = gran,
9957
.pie = pie,
9958
.aie = aie,
9959
+ .mtx = mtx,
9960
};
9961
}
9962
target/arm/internals.h
+1
@@ -1430,6 +1430,7 @@ typedef struct ARMVAParameters {
1430
ARMGranuleSize gran : 2;
1431
bool pie : 1;
1432
bool aie : 1;
1433
+ bool mtx : 1;
1434
} ARMVAParameters;
1435
1436
/**
target/arm/ptw.c
+30
-5
@@ -1951,9 +1951,18 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
1951
* validation to do here.
1952
*/
1953
if (inputsize < addrsize) {
1954
- uint64_t top_bits = sextract64(address, inputsize,
1955
- addrsize - inputsize);
1956
- if (-top_bits != param.select) {
1954
+ /*
1955
+ * If MTX is enabled, bits 56-59 aren't checked for canonicity
1956
+ * during translation, since they will later be checked during
1957
+ * the tag check step.
1958
+ */
1959
+
1960
+ uint64_t cmp_mask = MAKE_64BIT_MASK(inputsize, addrsize - inputsize);
1961
+
1962
+ if (param.mtx) {
1963
+ cmp_mask &= ~MAKE_64BIT_MASK(56, 4);
1964
+ }
1965
+ if ((address ^ -param.select) & cmp_mask) {
1966
/* The gap between the two regions is a Translation fault */
1967
goto do_translation_fault;
1968
}
@@ -3514,15 +3523,31 @@ static bool get_phys_addr_disabled(CPUARMState *env,
3523
int pamax = arm_pamax(env_archcpu(env));
3524
uint64_t tcr = env->cp15.tcr_el[r_el];
3525
int addrtop, tbi;
3526
+ bool bit55;
3527
3528
tbi = aa64_va_parameter_tbi(tcr, mmu_idx);
3529
if (access_type == MMU_INST_FETCH) {
3530
tbi &= ~aa64_va_parameter_tbid(tcr, mmu_idx);
3531
}
3522
- tbi = (tbi >> extract64(address, 55, 1)) & 1;
3532
+ bit55 = extract64(address, 55, 1);
3533
+ tbi = (tbi >> bit55) & 1;
3534
addrtop = (tbi ? 55 : 63);
3535
3525
- if (extract64(address, pamax, addrtop - pamax + 1) != 0) {
3536
+ /*
3537
+ * With MTX enabled, bits 56-59 are not checked according to
3538
+ * AArch64.S1DisabledOutput.
3539
+ */
3540
+ uint64_t cmp_mask = MAKE_64BIT_MASK(pamax, addrtop - pamax + 1);
3541
+
3542
+ if (access_type != MMU_INST_FETCH &&
3543
+ cpu_isar_feature(aa64_mte_mtx, env_archcpu(env))) {
3544
+ int mtx = aa64_va_parameter_mtx(tcr, mmu_idx);
3545
+ if (mtx & (1 << bit55)) {
3546
+ cmp_mask &= ~MAKE_64BIT_MASK(56, 4);
3547
+ }
3548
+ }
3549
+
3550
+ if (address & cmp_mask) {
3551
fi->type = ARMFault_AddressSize;
3552
fi->level = 0;
3553
fi->stage2 = false;