cpu_isar_feature(aa64_s2pie, cpu)) {
valid_mask |= SCR_PIEN;
}
+ if (cpu_isar_feature(aa64_mec, cpu)) {
+ valid_mask |= SCR_MECEN;
+ }
} else {
valid_mask &= ~(SCR_RW | SCR_ST);
if (cpu_isar_feature(aa32_ras, cpu)) {
.resetfn = arm_cp_reset_ignore },
};
+static CPAccessResult mecid_access(CPUARMState *env,
+ const ARMCPRegInfo *ri, bool isread)
+{
+ int el = arm_current_el(env);
+
+ if (el == 2) {
+ if (arm_security_space(env) != ARMSS_Realm) {
+ return CP_ACCESS_UNDEFINED;
+ }
+
+ if (!(env->cp15.scr_el3 & SCR_MECEN)) {
+ return CP_ACCESS_TRAP_EL3;
+ }
+ }
+
+ return CP_ACCESS_OK;
+}
+
+static void mecid_write(CPUARMState *env, const ARMCPRegInfo *ri,
+ uint64_t value)
+{
+ value = extract64(value, 0, MECID_WIDTH);
+ raw_write(env, ri, value);
+}
+
+static CPAccessResult cipae_access(CPUARMState *env, const ARMCPRegInfo *ri,
+ bool isread)
+{
+ switch (arm_security_space(env)) {
+ case ARMSS_Root: /* EL3 */
+ case ARMSS_Realm: /* Realm EL2 */
+ return CP_ACCESS_OK;
+ default:
+ return CP_ACCESS_UNDEFINED;
+ }
+}
+
+static const ARMCPRegInfo mec_reginfo[] = {
+ { .name = "MECIDR_EL2", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 4, .opc2 = 7, .crn = 10, .crm = 8,
+ .access = PL2_R, .type = ARM_CP_CONST | ARM_CP_NV_NO_TRAP,
+ .resetvalue = MECID_WIDTH - 1 },
+ { .name = "MECID_P0_EL2", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 4, .opc2 = 0, .crn = 10, .crm = 8,
+ .access = PL2_RW, .type = ARM_CP_NV_NO_TRAP,
+ .accessfn = mecid_access, .writefn = mecid_write,
+ .fieldoffset = offsetof(CPUARMState, cp15.mecid_p0_el2) },
+ { .name = "MECID_A0_EL2", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 4, .opc2 = 1, .crn = 10, .crm = 8,
+ .access = PL2_RW, .type = ARM_CP_NV_NO_TRAP,
+ .accessfn = mecid_access, .writefn = mecid_write,
+ .fieldoffset = offsetof(CPUARMState, cp15.mecid_a0_el2) },
+ { .name = "MECID_P1_EL2", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 4, .opc2 = 2, .crn = 10, .crm = 8,
+ .access = PL2_RW, .type = ARM_CP_NV_NO_TRAP,
+ .accessfn = mecid_access, .writefn = mecid_write,
+ .fieldoffset = offsetof(CPUARMState, cp15.mecid_p1_el2) },
+ { .name = "MECID_A1_EL2", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 4, .opc2 = 3, .crn = 10, .crm = 8,
+ .access = PL2_RW, .type = ARM_CP_NV_NO_TRAP,
+ .accessfn = mecid_access, .writefn = mecid_write,
+ .fieldoffset = offsetof(CPUARMState, cp15.mecid_a1_el2) },
+ { .name = "MECID_RL_A_EL3", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 6, .opc2 = 1, .crn = 10, .crm = 10,
+ .access = PL3_RW, .accessfn = mecid_access,
+ .writefn = mecid_write,
+ .fieldoffset = offsetof(CPUARMState, cp15.mecid_rl_a_el3) },
+ { .name = "VMECID_P_EL2", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 4, .opc2 = 0, .crn = 10, .crm = 9,
+ .access = PL2_RW, .type = ARM_CP_NV_NO_TRAP,
+ .accessfn = mecid_access, .writefn = mecid_write,
+ .fieldoffset = offsetof(CPUARMState, cp15.vmecid_p_el2) },
+ { .name = "VMECID_A_EL2", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 4, .opc2 = 1, .crn = 10, .crm = 9,
+ .access = PL2_RW, .type = ARM_CP_NV_NO_TRAP,
+ .accessfn = mecid_access, .writefn = mecid_write,
+ .fieldoffset = offsetof(CPUARMState, cp15.vmecid_a_el2) },
+ { .name = "DC_CIPAE", .state = ARM_CP_STATE_AA64,
+ .opc0 = 1, .opc1 = 4, .crn = 7, .crm = 14, .opc2 = 0,
+ .access = PL2_W, .type = ARM_CP_NOP | ARM_CP_NV_NO_TRAP,
+ .accessfn = cipae_access },
+};
+
+static const ARMCPRegInfo mec_mte_reginfo[] = {
+ { .name = "DC_CIGDPAE", .state = ARM_CP_STATE_AA64,
+ .opc0 = 1, .opc1 = 4, .crn = 7, .crm = 14, .opc2 = 7,
+ .access = PL2_W, .type = ARM_CP_NOP | ARM_CP_NV_NO_TRAP,
+ .accessfn = cipae_access },
+};
+
#ifndef CONFIG_USER_ONLY
/*
* We don't know until after realize whether there's a GICv3
{
uint64_t valid_mask = 0;
+ if (cpu_isar_feature(aa64_mec, env_archcpu(env))) {
+ valid_mask |= SCTLR2_EMEC;
+ }
value &= valid_mask;
raw_write(env, ri, value);
}
{
uint64_t valid_mask = 0;
+ if (cpu_isar_feature(aa64_mec, env_archcpu(env))) {
+ valid_mask |= SCTLR2_EMEC;
+ }
value &= valid_mask;
raw_write(env, ri, value);
}
if (cpu_isar_feature(aa64_s1pie, cpu)) {
valid_mask |= TCR2_PIE;
}
+ if (cpu_isar_feature(aa64_mec, env_archcpu(env))) {
+ valid_mask |= TCR2_AMEC0 | TCR2_AMEC1;
+ }
value &= valid_mask;
raw_write(env, ri, value);
}
if (cpu_isar_feature(aa64_s2pie, cpu)) {
define_arm_cp_regs(cpu, s2pie_reginfo);
}
+ 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);
+ }
+ }
if (cpu_isar_feature(any_predinv, cpu)) {
define_arm_cp_regs(cpu, predinv_reginfo);