This feature disables generation of the mte check helper on loads when
STORE_ONLY tag checking mode is enabled.
Signed-off-by: Gabriel Brookman <brookmangabriel@gmail.com>
---
target/arm/cpu.h | 2 ++
target/arm/tcg/hflags.c | 14 ++++++++++++++
target/arm/tcg/translate-a64.c | 8 ++++++--
target/arm/tcg/translate.h | 2 ++
4 files changed, 24 insertions(+), 2 deletions(-)
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 393bfc0dc9..4087484faf 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -2496,6 +2496,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 5c9b9bec3b..c4696af5d8 100644
--- a/target/arm/tcg/hflags.c
+++ b/target/arm/tcg/hflags.c
@@ -425,6 +425,16 @@ 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 (cpu_isar_feature(aa64_mte4, env_archcpu(env)) &&
+ ((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. */
@@ -434,6 +444,10 @@ 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 (cpu_isar_feature(aa64_mte4, env_archcpu(env)) &&
+ (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 cde22a5cca..8b39d5357a 100644
--- a/target/arm/tcg/translate-a64.c
+++ b/target/arm/tcg/translate-a64.c
@@ -298,7 +298,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;
@@ -330,7 +331,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;
@@ -10693,6 +10695,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 b62104b4ae..206aadcb17 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.52.0