Fixes a bug in that with SCTLR.A set, we should raise any alignment fault before raising any MTE check fault.
Signed-off-by: Richard Henderson <richard.hender...@linaro.org> --- target/arm/internals.h | 3 ++- target/arm/mte_helper.c | 18 ++++++++++++++++++ target/arm/translate-a64.c | 2 ++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/target/arm/internals.h b/target/arm/internals.h index e1e018da46..fa264e368c 100644 --- a/target/arm/internals.h +++ b/target/arm/internals.h @@ -1222,7 +1222,8 @@ FIELD(MTEDESC, MIDX, 0, 4) FIELD(MTEDESC, TBI, 4, 2) FIELD(MTEDESC, TCMA, 6, 2) FIELD(MTEDESC, WRITE, 8, 1) -FIELD(MTEDESC, SIZEM1, 9, SIMD_DATA_BITS - 9) /* size - 1 */ +FIELD(MTEDESC, ALIGN, 9, 3) +FIELD(MTEDESC, SIZEM1, 12, SIMD_DATA_BITS - 12) /* size - 1 */ bool mte_probe(CPUARMState *env, uint32_t desc, uint64_t ptr); uint64_t mte_check(CPUARMState *env, uint32_t desc, uint64_t ptr, uintptr_t ra); diff --git a/target/arm/mte_helper.c b/target/arm/mte_helper.c index 98bcf59c22..e50bb4ea13 100644 --- a/target/arm/mte_helper.c +++ b/target/arm/mte_helper.c @@ -784,6 +784,24 @@ uint64_t mte_check(CPUARMState *env, uint32_t desc, uint64_t ptr, uintptr_t ra) uint64_t HELPER(mte_check)(CPUARMState *env, uint32_t desc, uint64_t ptr) { + /* + * In the Arm ARM pseudocode, the alignment check happens at the top + * of Mem[], while the MTE check happens later in AArch64.MemSingle[]. + * Thus the alignment check has priority. + * When the mte check is disabled, tcg performs the alignment check + * during the code generated for the memory access. + */ + unsigned align = FIELD_EX32(desc, MTEDESC, ALIGN); + if (unlikely(align)) { + align = (1u << align) - 1; + if (unlikely(ptr & align)) { + int idx = FIELD_EX32(desc, MTEDESC, MIDX); + bool w = FIELD_EX32(desc, MTEDESC, WRITE); + MMUAccessType type = w ? MMU_DATA_STORE : MMU_DATA_LOAD; + arm_cpu_do_unaligned_access(env_cpu(env), ptr, type, idx, GETPC()); + } + } + return mte_check(env, desc, ptr, GETPC()); } diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c index 1117a1cc41..caeb91efa5 100644 --- a/target/arm/translate-a64.c +++ b/target/arm/translate-a64.c @@ -267,6 +267,7 @@ static TCGv_i64 gen_mte_check1_mmuidx(DisasContext *s, TCGv_i64 addr, desc = FIELD_DP32(desc, MTEDESC, TBI, s->tbid); desc = FIELD_DP32(desc, MTEDESC, TCMA, s->tcma); desc = FIELD_DP32(desc, MTEDESC, WRITE, is_write); + desc = FIELD_DP32(desc, MTEDESC, ALIGN, get_alignment_bits(memop)); desc = FIELD_DP32(desc, MTEDESC, SIZEM1, memop_size(memop) - 1); ret = new_tmp_a64(s); @@ -298,6 +299,7 @@ TCGv_i64 gen_mte_checkN(DisasContext *s, TCGv_i64 addr, bool is_write, desc = FIELD_DP32(desc, MTEDESC, TBI, s->tbid); desc = FIELD_DP32(desc, MTEDESC, TCMA, s->tcma); desc = FIELD_DP32(desc, MTEDESC, WRITE, is_write); + desc = FIELD_DP32(desc, MTEDESC, ALIGN, get_alignment_bits(single_mop)); desc = FIELD_DP32(desc, MTEDESC, SIZEM1, total_size - 1); ret = new_tmp_a64(s); -- 2.34.1