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
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~
© 2016 - 2025 Red Hat, Inc.