[PATCH v4 5/6] target/arm: Implement FEAT_MEC cache instructions

Gustavo Romero posted 6 patches 4 months, 1 week ago
Maintainers: Peter Maydell <peter.maydell@linaro.org>
There is a newer version of this series
[PATCH v4 5/6] target/arm: Implement FEAT_MEC cache instructions
Posted by Gustavo Romero 4 months, 1 week ago
This commit implements the two cache maintenance instructions introduced
by FEAT_MEC, DC CIPAE and DC CIGDPAE.

Because QEMU does not model the cache topology, all cache maintenance
instructions are implemented as NOPs, hence these new instructions are
implemented as NOPs too.

Signed-off-by: Gustavo Romero <gustavo.romero@linaro.org>
---
 target/arm/helper.c | 34 ++++++++++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)

diff --git a/target/arm/helper.c b/target/arm/helper.c
index 34e12bde90..36cf2b6415 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -4996,6 +4996,34 @@ static void ic_ivau_write(CPUARMState *env, const ARMCPRegInfo *ri,
 }
 #endif
 
+static CPAccessResult cipae_access(CPUARMState *env, const ARMCPRegInfo *ri,
+                                   bool isread)
+{
+    int el = arm_current_el(env);
+
+    if (!cpu_isar_feature(aa64_mec, env_archcpu(env))) {
+        return CP_ACCESS_UNDEFINED;
+    }
+    if (el < 3 && arm_security_space(env) != ARMSS_Realm) {
+        return CP_ACCESS_UNDEFINED;
+    }
+    return CP_ACCESS_OK;
+}
+
+static CPAccessResult cigdpae_access(CPUARMState *env, const ARMCPRegInfo *ri,
+                                     bool isread)
+{
+    CPAccessResult ret = cipae_access(env, ri, isread);
+
+    if (ret != CP_ACCESS_OK) {
+        return ret;
+    }
+    if (!cpu_isar_feature(aa64_mte, env_archcpu(env))) {
+        return CP_ACCESS_UNDEFINED;
+    }
+    return CP_ACCESS_OK;
+}
+
 static const ARMCPRegInfo v8_cp_reginfo[] = {
     /*
      * Minimal set of EL0-visible registers. This will need to be expanded
@@ -5094,6 +5122,12 @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
       .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 14, .opc2 = 2,
       .fgt = FGT_DCCISW,
       .access = PL1_W, .accessfn = access_tsw, .type = ARM_CP_NOP },
+    { .name = "DC_CIPAE", .state = ARM_CP_STATE_AA64,
+      .opc0 = 1, .opc1 = 4, .crn = 7, .crm = 14, .opc2 = 0,
+      .access = PL2_W, .accessfn = cipae_access, .type = ARM_CP_NOP },
+    { .name = "DC_CIGDPAE", .state = ARM_CP_STATE_AA64,
+      .opc0 = 1, .opc1 = 4, .crn = 7, .crm = 14, .opc2 = 7,
+      .access = PL2_W, .accessfn = cigdpae_access, .type = ARM_CP_NOP },
 #ifndef CONFIG_USER_ONLY
     /* 64 bit address translation operations */
     { .name = "AT_S1E1R", .state = ARM_CP_STATE_AA64,
-- 
2.34.1
Re: [PATCH v4 5/6] target/arm: Implement FEAT_MEC cache instructions
Posted by Richard Henderson 4 months, 1 week ago
On 7/9/25 12:03, Gustavo Romero wrote:
> This commit implements the two cache maintenance instructions introduced
> by FEAT_MEC, DC CIPAE and DC CIGDPAE.
> 
> Because QEMU does not model the cache topology, all cache maintenance
> instructions are implemented as NOPs, hence these new instructions are
> implemented as NOPs too.
> 
> Signed-off-by: Gustavo Romero <gustavo.romero@linaro.org>
> ---
>   target/arm/helper.c | 34 ++++++++++++++++++++++++++++++++++
>   1 file changed, 34 insertions(+)
> 
> diff --git a/target/arm/helper.c b/target/arm/helper.c
> index 34e12bde90..36cf2b6415 100644
> --- a/target/arm/helper.c
> +++ b/target/arm/helper.c
> @@ -4996,6 +4996,34 @@ static void ic_ivau_write(CPUARMState *env, const ARMCPRegInfo *ri,
>   }
>   #endif
>   
> +static CPAccessResult cipae_access(CPUARMState *env, const ARMCPRegInfo *ri,
> +                                   bool isread)
> +{
> +    int el = arm_current_el(env);
> +
> +    if (!cpu_isar_feature(aa64_mec, env_archcpu(env))) {
> +        return CP_ACCESS_UNDEFINED;
> +    }

Not required, because the cpreg should not be registered in this case.

> +    if (el < 3 && arm_security_space(env) != ARMSS_Realm) {
> +        return CP_ACCESS_UNDEFINED;
> +    }

Correct, but we can simplify this to

     switch (arm_security_space(env)) {
     case ARMSS_Root:  /* EL3 */
     case ARMSS_Realm: /* Realm EL2 */
         return CP_ACCESS_OK;
     default:
         return CP_ACCESS_UNDEFINED;
     }


> +static CPAccessResult cigdpae_access(CPUARMState *env, const ARMCPRegInfo *ri,
> +                                     bool isread)
> +{
> +    CPAccessResult ret = cipae_access(env, ri, isread);
> +
> +    if (ret != CP_ACCESS_OK) {
> +        return ret;
> +    }
> +    if (!cpu_isar_feature(aa64_mte, env_archcpu(env))) {
> +        return CP_ACCESS_UNDEFINED;
> +    }

Likewise not required.  Therefore the two cpregs can share the same accessfn.

> @@ -5094,6 +5122,12 @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
>         .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 14, .opc2 = 2,
>         .fgt = FGT_DCCISW,
>         .access = PL1_W, .accessfn = access_tsw, .type = ARM_CP_NOP },
> +    { .name = "DC_CIPAE", .state = ARM_CP_STATE_AA64,
> +      .opc0 = 1, .opc1 = 4, .crn = 7, .crm = 14, .opc2 = 0,
> +      .access = PL2_W, .accessfn = cipae_access, .type = ARM_CP_NOP },
> +    { .name = "DC_CIGDPAE", .state = ARM_CP_STATE_AA64,
> +      .opc0 = 1, .opc1 = 4, .crn = 7, .crm = 14, .opc2 = 7,
> +      .access = PL2_W, .accessfn = cigdpae_access, .type = ARM_CP_NOP },

You should insert the first into the same mec_reginfo[] structure that you introduced in 
patch 1.  The second must be in a separate array, like so:

     if (cpu_isar_feature(aa64_mec, cpu)) {
         define_arm_cp_regs(cpu, mec_reginfo);
         if (cpu_isar_feature(aa64_mte, cpu)) {
             define_arm_cp_regs(cpu, mec_mte_reginfo);
         }
     }


r~