@@ -105,6 +105,8 @@ typedef struct ARMCPU {
/* CPU has memory protection unit */
bool has_mpu;
+ /* PMSAv7 MPU number of supported regions */
+ uint32_t pmsav7_dregion;
/* PSCI conduit used to invoke PSCI methods
* 0 - disabled, 1 - smc, 2 - hvc
@@ -457,6 +457,9 @@ static Property arm_cpu_has_el3_property =
static Property arm_cpu_has_mpu_property =
DEFINE_PROP_BOOL("has-mpu", ARMCPU, has_mpu, true);
+static Property arm_cpu_pmsav7_dregion_property =
+ DEFINE_PROP_UINT32("pmsav7-dregion", ARMCPU, pmsav7_dregion, 16);
+
static void arm_cpu_post_init(Object *obj)
{
ARMCPU *cpu = ARM_CPU(obj);
@@ -488,6 +491,11 @@ static void arm_cpu_post_init(Object *obj)
if (arm_feature(&cpu->env, ARM_FEATURE_MPU)) {
qdev_property_add_static(DEVICE(obj), &arm_cpu_has_mpu_property,
&error_abort);
+ if (arm_feature(&cpu->env, ARM_FEATURE_V7)) {
+ qdev_property_add_static(DEVICE(obj),
+ &arm_cpu_pmsav7_dregion_property,
+ &error_abort);
+ }
}
}
@@ -580,6 +588,16 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
unset_feature(env, ARM_FEATURE_MPU);
}
+ if (arm_feature(env, ARM_FEATURE_MPU) &&
+ arm_feature(env, ARM_FEATURE_V7)) {
+ uint32_t nr = cpu->pmsav7_dregion;
+
+ if (nr > 0xff) {
+ error_setg(errp, "PMSAv7 MPU #regions invalid %" PRIu32 "\n", nr);
+ return;
+ }
+ }
+
register_cp_regs_for_features(cpu);
arm_cpu_register_gdb_regs_for_features(cpu);
@@ -3457,6 +3457,13 @@ void register_cp_regs_for_features(ARMCPU *cpu)
.cp = 15, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 3,
.access = PL1_R, .type = ARM_CP_CONST, .resetvalue = 0,
};
+ /* MPUIR is specific to PMSA V6+ */
+ ARMCPRegInfo id_mpuir_reginfo = {
+ .name = "MPUIR",
+ .cp = 15, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 4,
+ .access = PL1_R, .type = ARM_CP_CONST,
+ .resetvalue = cpu->pmsav7_dregion << 8
+ };
ARMCPRegInfo crn0_wi_reginfo = {
.name = "CRN0_WI", .cp = 15, .crn = 0, .crm = CP_ANY,
.opc1 = CP_ANY, .opc2 = CP_ANY, .access = PL1_W,
@@ -3479,6 +3486,7 @@ void register_cp_regs_for_features(ARMCPU *cpu)
r->access = PL1_RW;
}
id_tlbtr_reginfo.access = PL1_RW;
+ id_tlbtr_reginfo.access = PL1_RW;
}
if (arm_feature(env, ARM_FEATURE_V8)) {
define_arm_cp_regs(cpu, id_v8_midr_cp_reginfo);
@@ -3488,6 +3496,8 @@ void register_cp_regs_for_features(ARMCPU *cpu)
define_arm_cp_regs(cpu, id_cp_reginfo);
if (!arm_feature(env, ARM_FEATURE_MPU)) {
define_one_arm_cp_reg(cpu, &id_tlbtr_reginfo);
+ } else if (arm_feature(env, ARM_FEATURE_V7)) {
+ define_one_arm_cp_reg(cpu, &id_mpuir_reginfo);
}
}