diff --git a/target-arm/cpu-qom.h b/target-arm/cpu-qom.h index 072aa9baa7..3cbc4a0061 100644 --- a/target-arm/cpu-qom.h +++ b/target-arm/cpu-qom.h @@ -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 diff --git a/target-arm/cpu.c b/target-arm/cpu.c index a6e3e37e6e..a04d5c3897 100644 --- a/target-arm/cpu.c +++ b/target-arm/cpu.c @@ -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); diff --git a/target-arm/helper.c b/target-arm/helper.c index fbf20b619e..1cb881226a 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -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); } }