This feature disables generation of the mte check helper on loads when STORE_ONLY tag checking mode is enabled.
Signed-off-by: Gabriel Brookman <[email protected]> Reviewed-by: Richard Henderson <[email protected]> --- target/arm/cpu.h | 2 ++ target/arm/tcg/hflags.c | 12 ++++++++++++ target/arm/tcg/translate-a64.c | 8 ++++++-- target/arm/tcg/translate.h | 2 ++ 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/target/arm/cpu.h b/target/arm/cpu.h index 0894a050b1..fce0bde168 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -2531,6 +2531,8 @@ FIELD(TBFLAG_A64, ZT0EXC_EL, 39, 2) FIELD(TBFLAG_A64, GCS_EN, 41, 1) FIELD(TBFLAG_A64, GCS_RVCEN, 42, 1) FIELD(TBFLAG_A64, GCSSTR_EL, 43, 2) +FIELD(TBFLAG_A64, MTE_STORE_ONLY, 45, 1) +FIELD(TBFLAG_A64, MTE0_STORE_ONLY, 46, 1) /* * Helpers for using the above. Note that only the A64 accessors use diff --git a/target/arm/tcg/hflags.c b/target/arm/tcg/hflags.c index 7e6f8d3647..75c55b1a6d 100644 --- a/target/arm/tcg/hflags.c +++ b/target/arm/tcg/hflags.c @@ -423,6 +423,15 @@ static CPUARMTBFlags rebuild_hflags_a64(CPUARMState *env, int el, int fp_el, */ DP_TBFLAG_A64(flags, MTE0_ACTIVE, 1); } + /* + * Repeat for MTE_STORE_ONLY + */ + if ((el == 0 ? SCTLR_TCSO0 : SCTLR_TCSO) & sctlr) { + DP_TBFLAG_A64(flags, MTE_STORE_ONLY, 1); + if (!EX_TBFLAG_A64(flags, UNPRIV)) { + DP_TBFLAG_A64(flags, MTE0_STORE_ONLY, 1); + } + } } } /* And again for unprivileged accesses, if required. */ @@ -432,6 +441,9 @@ static CPUARMTBFlags rebuild_hflags_a64(CPUARMState *env, int el, int fp_el, && (sctlr & SCTLR_TCF0) && allocation_tag_access_enabled(env, 0, sctlr)) { DP_TBFLAG_A64(flags, MTE0_ACTIVE, 1); + if (SCTLR_TCSO0 & sctlr) { + DP_TBFLAG_A64(flags, MTE0_STORE_ONLY, 1); + } } /* * For unpriv tag-setting accesses we also need ATA0. Again, in diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c index 9a27c4c6ec..ce6249649a 100644 --- a/target/arm/tcg/translate-a64.c +++ b/target/arm/tcg/translate-a64.c @@ -302,7 +302,8 @@ static TCGv_i64 gen_mte_check1_mmuidx(DisasContext *s, TCGv_i64 addr, MemOp memop, bool is_unpriv, int core_idx) { - if (tag_checked && s->mte_active[is_unpriv]) { + if (tag_checked && s->mte_active[is_unpriv] && + (is_write || !s->mte_store_only[is_unpriv])) { TCGv_i64 ret; int desc = 0; @@ -334,7 +335,8 @@ TCGv_i64 gen_mte_check1(DisasContext *s, TCGv_i64 addr, bool is_write, TCGv_i64 gen_mte_checkN(DisasContext *s, TCGv_i64 addr, bool is_write, bool tag_checked, int total_size, MemOp single_mop) { - if (tag_checked && s->mte_active[0]) { + if (tag_checked && s->mte_active[0] && + (is_write || !s->mte_store_only[0])) { TCGv_i64 ret; int desc = 0; @@ -10697,6 +10699,8 @@ static void aarch64_tr_init_disas_context(DisasContextBase *dcbase, dc->ata[1] = EX_TBFLAG_A64(tb_flags, ATA0); dc->mte_active[0] = EX_TBFLAG_A64(tb_flags, MTE_ACTIVE); dc->mte_active[1] = EX_TBFLAG_A64(tb_flags, MTE0_ACTIVE); + dc->mte_store_only[0] = EX_TBFLAG_A64(tb_flags, MTE_STORE_ONLY); + dc->mte_store_only[1] = EX_TBFLAG_A64(tb_flags, MTE0_STORE_ONLY); dc->pstate_sm = EX_TBFLAG_A64(tb_flags, PSTATE_SM); dc->pstate_za = EX_TBFLAG_A64(tb_flags, PSTATE_ZA); dc->sme_trap_nonstreaming = EX_TBFLAG_A64(tb_flags, SME_TRAP_NONSTREAMING); diff --git a/target/arm/tcg/translate.h b/target/arm/tcg/translate.h index 77fdc5f3a1..c74a4f6675 100644 --- a/target/arm/tcg/translate.h +++ b/target/arm/tcg/translate.h @@ -140,6 +140,8 @@ typedef struct DisasContext { bool ata[2]; /* True if v8.5-MTE tag checks affect the PE; index with is_unpriv. */ bool mte_active[2]; + /* True if v8.5-MTE tag checks disabled for reads; index with is_unpriv. */ + bool mte_store_only[2]; /* True with v8.5-BTI and SCTLR_ELx.BT* set. */ bool bt; /* True if any CP15 access is trapped by HSTR_EL2 */ -- 2.54.0
