It is IMPLEMENTATION DEFINED whether HCR_EL2.TID3 traps on registers
within the range which are not explicitly listed.  Previously we chose
not to honor the TID3 bit.

However, with FEAT_IDTE3 it becomes mandatory to honor SCR_EL3.TID3
on these registers, so we might as well honor HCR_EL2.TID3 too.

Signed-off-by: Richard Henderson <[email protected]>
---
 target/arm/cpregs.h            |  8 ++++++++
 target/arm/tcg/helper-defs.h   |  1 +
 target/arm/tcg/op_helper.c     | 19 +++++++++++++++++++
 target/arm/tcg/translate-a64.c | 12 ++++++++++--
 target/arm/tcg/translate.c     |  8 ++++++++
 5 files changed, 46 insertions(+), 2 deletions(-)

diff --git a/target/arm/cpregs.h b/target/arm/cpregs.h
index 9f2532fe66..b1fc1f9f85 100644
--- a/target/arm/cpregs.h
+++ b/target/arm/cpregs.h
@@ -1213,6 +1213,14 @@ static inline bool arm_cpreg_in_idspace(const 
ARMCPRegInfo *ri)
                                       ri->crn, ri->crm);
 }
 
+/* The TID3 subset of idspace. */
+static inline bool
+arm_cpreg_encoding_in_tid3(uint8_t opc0, uint8_t opc1, uint8_t opc2,
+                           uint8_t crn, uint8_t crm)
+{
+    return opc0 == 3 && opc1 == 0 && crn == 0 && crm >= 2 && crm < 8;
+}
+
 #ifdef CONFIG_USER_ONLY
 static inline void define_cortex_a72_a57_a53_cp_reginfo(ARMCPU *cpu) { }
 #else
diff --git a/target/arm/tcg/helper-defs.h b/target/arm/tcg/helper-defs.h
index 0077aeb4e2..97b8678f19 100644
--- a/target/arm/tcg/helper-defs.h
+++ b/target/arm/tcg/helper-defs.h
@@ -86,6 +86,7 @@ DEF_HELPER_FLAGS_2(check_bxj_trap, TCG_CALL_NO_WG, void, env, 
i32)
 
 DEF_HELPER_4(access_check_cp_reg, cptr, env, i32, i32, i32)
 DEF_HELPER_FLAGS_2(lookup_cp_reg, TCG_CALL_NO_RWG_SE, cptr, env, i32)
+DEF_HELPER_FLAGS_2(tid3_udef_el1, TCG_CALL_NO_WG, noreturn, env, i32)
 DEF_HELPER_FLAGS_2(tidcp_el0, TCG_CALL_NO_WG, void, env, i32)
 DEF_HELPER_FLAGS_2(tidcp_el1, TCG_CALL_NO_WG, void, env, i32)
 DEF_HELPER_3(set_cp_reg, void, env, cptr, i32)
diff --git a/target/arm/tcg/op_helper.c b/target/arm/tcg/op_helper.c
index d4186b3d0a..93336daf53 100644
--- a/target/arm/tcg/op_helper.c
+++ b/target/arm/tcg/op_helper.c
@@ -1187,6 +1187,25 @@ const void *HELPER(lookup_cp_reg)(CPUARMState *env, 
uint32_t key)
     return ri;
 }
 
+/* Raise an exception for an unimplemented sysreg in TID3 space, from EL1. */
+void HELPER(tid3_udef_el1)(CPUARMState *env, uint32_t syndrome)
+{
+    int target_el = 1;
+    int excp = EXCP_UDEF;
+
+    if (arm_hcr_el2_eff(env) & HCR_TID3) {
+        target_el = 2;
+        excp = EXCP_HYP_TRAP;
+    } else if (is_a64(env)) {
+        if (!cpu_isar_feature(aa64_idst, env_archcpu(env))) {
+            syndrome = syn_uncategorized();
+        }
+    } else {
+        syndrome = syn_uncategorized();
+    }
+    raise_exception(env, excp, syndrome, target_el);
+}
+
 /*
  * Test for HCR_EL2.TIDCP at EL1.
  * Since implementation defined registers are rare, and within QEMU
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
index b45e1b28b2..7e78d62496 100644
--- a/target/arm/tcg/translate-a64.c
+++ b/target/arm/tcg/translate-a64.c
@@ -2675,9 +2675,17 @@ static void gen_sysreg_undef(DisasContext *s, bool 
isread,
      */
     uint32_t syndrome;
 
-    if (isread && dc_isar_feature(aa64_idst, s) &&
-        arm_cpreg_encoding_in_idspace(op0, op1, op2, crn, crm)) {
+    if (isread && arm_cpreg_encoding_in_idspace(op0, op1, op2, crn, crm)) {
         syndrome = syn_aa64_sysregtrap(op0, op1, op2, crn, crm, rt, isread);
+        if (s->current_el == 1 &&
+            arm_cpreg_encoding_in_tid3(op0, op1, op2, crn, crm)) {
+            gen_a64_update_pc(s, 0);
+            gen_helper_tid3_udef_el1(tcg_env, tcg_constant_i32(syndrome));
+            return;
+        }
+        if (!dc_isar_feature(aa64_idst, s)) {
+            syndrome = syn_uncategorized();
+        }
     } else {
         syndrome = syn_uncategorized();
     }
diff --git a/target/arm/tcg/translate.c b/target/arm/tcg/translate.c
index a1fc050618..3fa15f493a 100644
--- a/target/arm/tcg/translate.c
+++ b/target/arm/tcg/translate.c
@@ -1824,6 +1824,14 @@ static void do_coproc_insn(DisasContext *s, int cpnum, 
int is64,
                           isread ? "read" : "write", cpnum, opc1, crn,
                           crm, opc2, s->ns ? "non-secure" : "secure");
         }
+        if (isread
+            && s->current_el == 1
+            && cpnum == 15
+            && arm_cpreg_encoding_in_tid3(3, opc1, opc2, crn, crm)) {
+            gen_set_condexec(s);
+            gen_update_pc(s, 0);
+            gen_helper_tid3_udef_el1(tcg_env, tcg_constant_i32(syndrome));
+        }
         unallocated_encoding(s);
         return;
     }
-- 
2.43.0


Reply via email to