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 <[email protected]> Reviewed-by: Richard Henderson <[email protected]> --- target/arm/helper.c | 6 +++++- target/arm/internals.h | 1 + target/arm/ptw.c | 35 ++++++++++++++++++++++++++++++----- 3 files changed, 36 insertions(+), 6 deletions(-) diff --git a/target/arm/helper.c b/target/arm/helper.c index 902eac767b..768a8e977d 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -9747,7 +9747,7 @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va, { uint64_t tcr = regime_tcr(env, mmu_idx); bool epd, hpd, tsz_oob, ds, ha, hd, pie = false; - bool aie = false; + bool mtx, aie = false; int select, tsz, tbi, max_tsz, min_tsz, ps, sh; ARMGranuleSize gran; ARMCPU *cpu = env_archcpu(env); @@ -9784,6 +9784,7 @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va, ha = extract32(tcr, 21, 1) && cpu_isar_feature(aa64_hafs, cpu); hd = extract32(tcr, 22, 1) && cpu_isar_feature(aa64_hdbs, cpu); ds = extract64(tcr, 32, 1); + mtx = extract64(tcr, 33, 1) && cpu_isar_feature(aa64_mte_mtx, cpu); } else { bool e0pd; @@ -9799,6 +9800,7 @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va, sh = extract32(tcr, 12, 2); hpd = extract64(tcr, 41, 1); e0pd = extract64(tcr, 55, 1); + mtx = extract64(tcr, 60, 1) && cpu_isar_feature(aa64_mte_mtx, cpu); } else { tsz = extract32(tcr, 16, 6); gran = tg1_to_gran_size(extract32(tcr, 30, 2)); @@ -9806,6 +9808,7 @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va, sh = extract32(tcr, 28, 2); hpd = extract64(tcr, 42, 1); e0pd = extract64(tcr, 56, 1); + mtx = extract64(tcr, 61, 1) && cpu_isar_feature(aa64_mte_mtx, cpu); } ps = extract64(tcr, 32, 3); ha = extract64(tcr, 39, 1) && cpu_isar_feature(aa64_hafs, cpu); @@ -9905,6 +9908,7 @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va, .gran = gran, .pie = pie, .aie = aie, + .mtx = mtx, }; } diff --git a/target/arm/internals.h b/target/arm/internals.h index 51d7f09889..d8f68270a1 100644 --- a/target/arm/internals.h +++ b/target/arm/internals.h @@ -1420,6 +1420,7 @@ typedef struct ARMVAParameters { ARMGranuleSize gran : 2; bool pie : 1; bool aie : 1; + bool mtx : 1; } ARMVAParameters; /** diff --git a/target/arm/ptw.c b/target/arm/ptw.c index 6cb0fe5645..8b54018c98 100644 --- a/target/arm/ptw.c +++ b/target/arm/ptw.c @@ -1951,9 +1951,18 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw, * validation to do here. */ if (inputsize < addrsize) { - uint64_t top_bits = sextract64(address, inputsize, - addrsize - inputsize); - if (-top_bits != param.select) { + /* + * If MTX is enabled, bits 56-59 aren't checked for canonicity + * during translation, since they will later be checked during + * the tag check step. + */ + + uint64_t cmp_mask = MAKE_64BIT_MASK(inputsize, addrsize - inputsize); + + if (param.mtx) { + cmp_mask &= ~MAKE_64BIT_MASK(56, 4); + } + if ((address ^ -param.select) & cmp_mask) { /* The gap between the two regions is a Translation fault */ goto do_translation_fault; } @@ -3514,15 +3523,31 @@ static bool get_phys_addr_disabled(CPUARMState *env, int pamax = arm_pamax(env_archcpu(env)); uint64_t tcr = env->cp15.tcr_el[r_el]; int addrtop, tbi; + bool bit55; tbi = aa64_va_parameter_tbi(tcr, mmu_idx); if (access_type == MMU_INST_FETCH) { tbi &= ~aa64_va_parameter_tbid(tcr, mmu_idx); } - tbi = (tbi >> extract64(address, 55, 1)) & 1; + bit55 = extract64(address, 55, 1); + tbi = (tbi >> bit55) & 1; addrtop = (tbi ? 55 : 63); - if (extract64(address, pamax, addrtop - pamax + 1) != 0) { + /* + * With MTX enabled, bits 56-59 are not checked according to + * AArch64.S1DisabledOutput. + */ + uint64_t cmp_mask = MAKE_64BIT_MASK(pamax, addrtop - pamax + 1); + + if (access_type != MMU_INST_FETCH && + cpu_isar_feature(aa64_mte_mtx, env_archcpu(env))) { + int mtx = aa64_va_parameter_mtx(tcr, mmu_idx); + if (mtx & (1 << bit55)) { + cmp_mask &= ~MAKE_64BIT_MASK(56, 4); + } + } + + if (address & cmp_mask) { fi->type = ARMFault_AddressSize; fi->level = 0; fi->stage2 = false; -- 2.54.0
