Note that CreateAccDescGCS() does not enable tagchecked,
and Data Aborts from GCS instructions do not set iss.isv.
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/tcg/translate-a64.c | 42 ++++++++++++++++++++++++++++++++++
target/arm/tcg/a64.decode | 3 +++
2 files changed, 45 insertions(+)
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
index 1175d37c87..022a7c27e3 100644
--- a/target/arm/tcg/translate-a64.c
+++ b/target/arm/tcg/translate-a64.c
@@ -139,6 +139,12 @@ static int core_user_mem_index(DisasContext *s, bool unpriv)
return arm_to_core_mmu_idx(arm_user_mem_index(s, unpriv));
}
+/* For a given translation regime, return the core mmu_idx for gcs access. */
+static int core_gcs_mem_index(ARMMMUIdx armidx)
+{
+ return arm_to_core_mmu_idx(regime_to_gcs(armidx));
+}
+
static void set_btype_raw(int val)
{
tcg_gen_st_i32(tcg_constant_i32(val), tcg_env,
@@ -3951,6 +3957,42 @@ static bool trans_STLR_i(DisasContext *s, arg_ldapr_stlr_i *a)
return true;
}
+static bool trans_GCSSTR(DisasContext *s, arg_GCSSTR *a)
+{
+ ARMMMUIdx armidx;
+
+ if (!dc_isar_feature(aa64_gcs, s)) {
+ return false;
+ }
+
+ /*
+ * The pseudocode for GCSSTTR is
+ *
+ * effective_el = AArch64.IsUnprivAccessPriv() ? PSTATE.EL : EL0;
+ * if (effective_el == PSTATE.EL) CheckGCSSTREnabled();
+ *
+ * We have cached the result of IsUnprivAccessPriv in DisasContext,
+ * but since we need the result of arm_user_mem_index anyway, use
+ * the mmu_idx test as a proxy for the effective_el test.
+ */
+ armidx = arm_user_mem_index(s, a->unpriv);
+ if (armidx == s->mmu_idx && s->gcsstr_el != 0) {
+ gen_exception_insn_el(s, 0, EXCP_UDEF,
+ syn_gcs_gcsstr(a->rn, a->rt),
+ s->gcsstr_el);
+ return true;
+ }
+
+ if (a->rn == 31) {
+ gen_check_sp_alignment(s);
+ }
+ tcg_gen_qemu_st_i64(cpu_reg(s, a->rt),
+ clean_data_tbi(s, cpu_reg_sp(s, a->rn)),
+ core_gcs_mem_index(armidx),
+ finalize_memop(s, MO_64 | MO_ALIGN));
+ return true;
+}
+
static bool trans_LD_mult(DisasContext *s, arg_ldst_mult *a)
{
TCGv_i64 clean_addr, tcg_rn, tcg_ebytes;
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
index 8283a9c83d..2ae73f443a 100644
--- a/target/arm/tcg/a64.decode
+++ b/target/arm/tcg/a64.decode
@@ -571,6 +571,9 @@ LDAPR_i 10 011001 10 0 ......... 00 ..... ..... @ldapr_stlr_i sign=1 ext
LDAPR_i 00 011001 11 0 ......... 00 ..... ..... @ldapr_stlr_i sign=1 ext=1 sz=0
LDAPR_i 01 011001 11 0 ......... 00 ..... ..... @ldapr_stlr_i sign=1 ext=1 sz=1
+# GCSSTR, GCSSTTR
+GCSSTR 11011001 000 11111 000 unpriv:1 11 rn:5 rt:5
+
# Load/store multiple structures
# The 4-bit opcode in [15:12] encodes repeat count and structure elements
&ldst_mult rm rn rt sz q p rpt selem
--
2.43.0