diff mbox series

[PULL,13/19] target/arm: Add ARM_CP_ADD_TLBI_NXS type flag for NXS insns

Message ID 20241217171937.3899947-14-peter.maydell@linaro.org
State Accepted
Commit a2508d0e29b69525f39733c5726e1412e5663eb0
Headers show
Series [PULL,01/19] target/arm: remove redundant code | expand

Commit Message

Peter Maydell Dec. 17, 2024, 5:19 p.m. UTC
All of the TLBI insns with an NXS variant put that variant at the
same encoding but with a CRn field that is one greater than for the
original TLBI insn.  To avoid having to define every TLBI insn
effectively twice, once in the normal way and once in a set of cpreg
arrays that are only registered when FEAT_XS is present, we define a
new ARM_CP_ADD_TLB_NXS type flag for cpregs.  When this flag is set
in a cpreg struct and FEAT_XS is present,
define_one_arm_cp_reg_with_opaque() will automatically add a second
cpreg to the hash table for the TLBI NXS insn with:
 * the crn+1 encoding
 * an FGT field that indicates that it should honour HCR_EL2.FGTnXS
 * a name with the "NXS" suffix

(If there are future TLBI NXS insns that don't use this same
encoding convention, it is also possible to define them manually.)

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20241211144440.2700268-3-peter.maydell@linaro.org
---
 target/arm/cpregs.h |  8 ++++++++
 target/arm/helper.c | 25 +++++++++++++++++++++++++
 2 files changed, 33 insertions(+)
diff mbox series

Patch

diff --git a/target/arm/cpregs.h b/target/arm/cpregs.h
index 87704762ef9..1759d9defbe 100644
--- a/target/arm/cpregs.h
+++ b/target/arm/cpregs.h
@@ -126,6 +126,14 @@  enum {
      * equivalent EL1 register when FEAT_NV2 is enabled.
      */
     ARM_CP_NV2_REDIRECT          = 1 << 20,
+    /*
+     * Flag: this is a TLBI insn which (when FEAT_XS is present) also has
+     * an NXS variant at the same encoding except that crn is 1 greater,
+     * so when registering this cpreg automatically also register one
+     * for the TLBI NXS variant. (For QEMU the NXS variant behaves
+     * identically to the normal one, other than FGT trapping handling.)
+     */
+    ARM_CP_ADD_TLBI_NXS          = 1 << 21,
 };
 
 /*
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 8e62769ec0d..c2a70f8c053 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -9146,6 +9146,31 @@  void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
                     if (r->state != state && r->state != ARM_CP_STATE_BOTH) {
                         continue;
                     }
+                    if ((r->type & ARM_CP_ADD_TLBI_NXS) &&
+                        cpu_isar_feature(aa64_xs, cpu)) {
+                        /*
+                         * This is a TLBI insn which has an NXS variant. The
+                         * NXS variant is at the same encoding except that
+                         * crn is +1, and has the same behaviour except for
+                         * fine-grained trapping. Add the NXS insn here and
+                         * then fall through to add the normal register.
+                         * add_cpreg_to_hashtable() copies the cpreg struct
+                         * and name that it is passed, so it's OK to use
+                         * a local struct here.
+                         */
+                        ARMCPRegInfo nxs_ri = *r;
+                        g_autofree char *name = g_strdup_printf("%sNXS", r->name);
+
+                        assert(state == ARM_CP_STATE_AA64);
+                        assert(nxs_ri.crn < 0xf);
+                        nxs_ri.crn++;
+                        if (nxs_ri.fgt) {
+                            nxs_ri.fgt |= R_FGT_NXS_MASK;
+                        }
+                        add_cpreg_to_hashtable(cpu, &nxs_ri, opaque, state,
+                                               ARM_CP_SECSTATE_NS,
+                                               crm, opc1, opc2, name);
+                    }
                     if (state == ARM_CP_STATE_AA32) {
                         /*
                          * Under AArch32 CP registers can be common