qemu-arm
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 4/5] target/arm: MTE privileged system mode assembly


From: Rémi Denis-Courmont
Subject: [PATCH 4/5] target/arm: MTE privileged system mode assembly
Date: Fri, 13 Mar 2020 16:00:22 +0200

From: Rémi Denis-Courmont <address@hidden>

This adds all remaining MTE instructions for EL1, EL2 and EL3 on a
processor with ID_AA64PFR1_EL1.MTE == 1.

Signed-off-by: Rémi Denis-Courmont <address@hidden>
---
 target/arm/cpu64.c         |  8 +++---
 target/arm/helper.c        | 19 ++++++++++++++
 target/arm/translate-a64.c | 52 +++++++++++++++++++++++++++++++++++---
 3 files changed, 71 insertions(+), 8 deletions(-)

diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index a72dfd3d98..749eb93872 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -665,13 +665,11 @@ static void aarch64_max_initfn(Object *obj)
 
         t = cpu->isar.id_aa64pfr1;
         t = FIELD_DP64(t, ID_AA64PFR1, BT, 1);
-#ifdef CONFIG_USER_ONLY
-        /* All MTE instructions and processor states are supported for user
-         * mode. This corresponds to feature field value 1 (field value 2
-         * implies MemTag memory support).
+        /* All MTE instructions and processor states are supported. This
+         * corresponds to feature field value 1 (field value 2 implies MemTag
+         * memory support).
          */
         t = FIELD_DP64(t, ID_AA64PFR1, MTE, 1);
-#endif
         cpu->isar.id_aa64pfr1 = t;
 
         t = cpu->isar.id_aa64mmfr1;
diff --git a/target/arm/helper.c b/target/arm/helper.c
index dd64fcb4ef..630dc04302 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -6906,10 +6906,29 @@ static const ARMCPRegInfo mte_reginfo[] = {
       .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 14, .opc2 = 5,
       .access = PL0_W, .type = ARM_CP_NOP,
       .accessfn = aa64_cacheop_poc_access },
+    { .name = "RGSR_EL1", .state = ARM_CP_STATE_AA64,
+      .opc0 = 3, .opc1 = 0, .crn = 1, .crm = 0, .opc2 = 5,
+      .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, rgsr_el1) },
+    { .name = "GCR_EL1", .state = ARM_CP_STATE_AA64,
+      .opc0 = 3, .opc1 = 0, .crn = 1, .crm = 0, .opc2 = 6,
+      .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, gcr_el1) },
     { .name = "TCO", .state = ARM_CP_STATE_AA64,
       .opc0 = 3, .opc1 = 3, .crn = 4, .crm = 2, .opc2 = 7,
       .access = PL0_RW, .type = ARM_CP_NO_RAW,
       .readfn = tco_read, .writefn = tco_write },
+    { .name = "TFSR_EL1", .state = ARM_CP_STATE_AA64,
+      .opc0 = 3, .opc1 = 0, .crn = 6, .crm = 5, .opc2 = 0,
+      .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, tfsr_el[1]) },
+    { .name = "TFSR_EL2", .state = ARM_CP_STATE_AA64,
+      .opc0 = 3, .opc1 = 4, .crn = 6, .crm = 5, .opc2 = 0,
+      .access = PL2_RW, .type = ARM_CP_ALIAS,
+      .fieldoffset = offsetof(CPUARMState, tfsr_el[1]) },
+    { .name = "TFSR_EL3", .state = ARM_CP_STATE_AA64,
+      .opc0 = 3, .opc1 = 6, .crn = 6, .crm = 5, .opc2 = 0,
+      .access = PL3_RW, .fieldoffset = offsetof(CPUARMState, tfsr_el[3]) },
+    { .name = "TFSRE0_EL1", .state = ARM_CP_STATE_AA64,
+      .opc0 = 3, .opc1 = 0, .crn = 6, .crm = 6, .opc2 = 1,
+      .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, tfsre0_el1) },
     REGINFO_SENTINEL
 };
 #endif
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 6d86480043..9382f53794 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -2716,6 +2716,38 @@ static void disas_ld_lit(DisasContext *s, uint32_t insn)
     tcg_temp_free_i64(clean_addr);
 }
 
+#ifndef CONFIG_USER_ONLY
+static void disas_ldst_memtag_vec(DisasContext *s, int rn, int rt,
+                                  bool is_load)
+{
+    TCGv_i64 tcg_addr;
+
+    if (rn == rt) {
+        return;
+    }
+
+    if (rn == 31) {
+        gen_check_sp_alignment(s);
+    }
+
+    /* The starting point between the specified address and the aligned
+     * address is implementation defined. We start at the aligned address.
+     */
+    tcg_addr = tcg_temp_new_i64();
+    tcg_gen_andi_i64(tcg_addr, cpu_reg_sp(s, rn),
+                     ~((16 * ARM_TAG_GRANULE) - 1));
+
+    /* In principles, memory access permissions should be checked here. */
+    if (is_load) {
+        tcg_gen_movi_i64(cpu_reg(s, rt), 0);
+    }
+
+    tcg_gen_addi_i64(cpu_reg_sp(s, rn), tcg_addr, 16 * ARM_TAG_GRANULE);
+
+    tcg_temp_free_i64(tcg_addr);
+}
+#endif
+
 /* LDG, LDGV(EL1), ST(Z)(2)G, STGV */
 static void disas_ldst_memtag(DisasContext *s, uint32_t insn)
 {
@@ -2736,9 +2768,23 @@ static void disas_ldst_memtag(DisasContext *s, uint32_t 
insn)
         return;
     }
 
-    if (op2 == 0 && opc != 1) {
-        unallocated_encoding(s);
-        return;
+    if (op2 == 0) {
+        switch (opc) {
+        case 1:
+            break;
+#ifndef CONFIG_USER_ONLY
+        case 2:
+        case 3:
+            if (s->current_el > 0 && offset == 0) {
+                disas_ldst_memtag_vec(s, rn, rt, opc & 1);
+                return;
+            }
+#endif
+            /* fall through */
+        default:
+            unallocated_encoding(s);
+            return;
+        }
     }
 
     if (rn == 31) {
-- 
2.25.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]