diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c index 1c23187d1a..c4afee77d7 100644 --- a/target/arm/cpu64.c +++ b/target/arm/cpu64.c @@ -679,9 +679,10 @@ static void aarch64_max_initfn(Object *obj) t = FIELD_DP64(t, ID_AA64PFR1, BT, 1); t = FIELD_DP64(t, ID_AA64PFR1, SSBS, 2); /* - * Begin with full support for MTE. This will be downgraded to MTE=0 - * during realize if the board provides no tag memory, much like - * we do for EL2 with the virtualization=on property. + * Begin with full support for MTE (FEAT_MTE3). This will be + * downgraded to MTE=0 (no MTE) during realize if the board + * provides no tag memory, much like we do for EL2 with the + * virtualization=on property. */ t = FIELD_DP64(t, ID_AA64PFR1, MTE, 2); cpu->isar.id_aa64pfr1 = t; diff --git a/target/arm/mte_helper.c b/target/arm/mte_helper.c index 9e615cc513..e93603bc02 100644 --- a/target/arm/mte_helper.c +++ b/target/arm/mte_helper.c @@ -561,12 +561,23 @@ static void mte_check_fail(CPUARMState *env, uint32_t desc, tcf = extract64(sctlr, 40, 2); } + is_write = FIELD_EX32(desc, MTEDESC, WRITE); + switch (tcf) { + default: /* case 3 */ + /* + * Tag check fail causes asynchronous flag set for stores, + * or a synchronous exception for loads. + */ + if (is_write) { + goto fail_async; + } + /* fall through */ + case 1: /* Tag check fail causes a synchronous exception. */ env->exception.vaddress = dirty_ptr; - is_write = FIELD_EX32(desc, MTEDESC, WRITE); syn = syn_data_abort_no_iss(arm_current_el(env) != 0, 0, 0, 0, 0, is_write, 0x11); raise_exception_ra(env, EXCP_DATA_ABORT, syn, @@ -582,6 +593,7 @@ static void mte_check_fail(CPUARMState *env, uint32_t desc, g_assert_not_reached(); case 2: + fail_async: /* Tag check fail causes asynchronous flag set. */ if (regime_has_2_ranges(arm_mmu_idx)) { select = extract64(dirty_ptr, 55, 1); @@ -600,14 +612,6 @@ static void mte_check_fail(CPUARMState *env, uint32_t desc, qemu_cpu_kick(env_cpu(env)); #endif break; - - default: - /* Case 3: Reserved. */ - qemu_log_mask(LOG_GUEST_ERROR, - "Tag check failure with SCTLR_EL%d.TCF%s " - "set to reserved value %d\n", - reg_el, el ? "" : "0", tcf); - break; } }