target/arm: factor MDCR_EL2 common handling

This adds a common helper to compute the effective value of MDCR_EL2.
That is the actual value if EL2 is enabled in the current security
context, or 0 elsewise.

Signed-off-by: Rémi Denis-Courmont <remi.denis.courmont@huawei.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20210112104511.36576-5-remi.denis.courmont@huawei.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Rémi Denis-Courmont 2021-01-12 12:44:57 +02:00 committed by Peter Maydell
parent e04a5752cb
commit 59dd089cf9

View file

@ -539,6 +539,11 @@ static CPAccessResult access_trap_aa32s_el1(CPUARMState *env,
return CP_ACCESS_TRAP_UNCATEGORIZED; return CP_ACCESS_TRAP_UNCATEGORIZED;
} }
static uint64_t arm_mdcr_el2_eff(CPUARMState *env)
{
return arm_is_el2_enabled(env) ? env->cp15.mdcr_el2 : 0;
}
/* Check for traps to "powerdown debug" registers, which are controlled /* Check for traps to "powerdown debug" registers, which are controlled
* by MDCR.TDOSA * by MDCR.TDOSA
*/ */
@ -546,11 +551,11 @@ static CPAccessResult access_tdosa(CPUARMState *env, const ARMCPRegInfo *ri,
bool isread) bool isread)
{ {
int el = arm_current_el(env); int el = arm_current_el(env);
bool mdcr_el2_tdosa = (env->cp15.mdcr_el2 & MDCR_TDOSA) || uint64_t mdcr_el2 = arm_mdcr_el2_eff(env);
(env->cp15.mdcr_el2 & MDCR_TDE) || bool mdcr_el2_tdosa = (mdcr_el2 & MDCR_TDOSA) || (mdcr_el2 & MDCR_TDE) ||
(arm_hcr_el2_eff(env) & HCR_TGE); (arm_hcr_el2_eff(env) & HCR_TGE);
if (el < 2 && mdcr_el2_tdosa && !arm_is_secure_below_el3(env)) { if (el < 2 && mdcr_el2_tdosa) {
return CP_ACCESS_TRAP_EL2; return CP_ACCESS_TRAP_EL2;
} }
if (el < 3 && (env->cp15.mdcr_el3 & MDCR_TDOSA)) { if (el < 3 && (env->cp15.mdcr_el3 & MDCR_TDOSA)) {
@ -566,11 +571,11 @@ static CPAccessResult access_tdra(CPUARMState *env, const ARMCPRegInfo *ri,
bool isread) bool isread)
{ {
int el = arm_current_el(env); int el = arm_current_el(env);
bool mdcr_el2_tdra = (env->cp15.mdcr_el2 & MDCR_TDRA) || uint64_t mdcr_el2 = arm_mdcr_el2_eff(env);
(env->cp15.mdcr_el2 & MDCR_TDE) || bool mdcr_el2_tdra = (mdcr_el2 & MDCR_TDRA) || (mdcr_el2 & MDCR_TDE) ||
(arm_hcr_el2_eff(env) & HCR_TGE); (arm_hcr_el2_eff(env) & HCR_TGE);
if (el < 2 && mdcr_el2_tdra && !arm_is_secure_below_el3(env)) { if (el < 2 && mdcr_el2_tdra) {
return CP_ACCESS_TRAP_EL2; return CP_ACCESS_TRAP_EL2;
} }
if (el < 3 && (env->cp15.mdcr_el3 & MDCR_TDA)) { if (el < 3 && (env->cp15.mdcr_el3 & MDCR_TDA)) {
@ -586,11 +591,11 @@ static CPAccessResult access_tda(CPUARMState *env, const ARMCPRegInfo *ri,
bool isread) bool isread)
{ {
int el = arm_current_el(env); int el = arm_current_el(env);
bool mdcr_el2_tda = (env->cp15.mdcr_el2 & MDCR_TDA) || uint64_t mdcr_el2 = arm_mdcr_el2_eff(env);
(env->cp15.mdcr_el2 & MDCR_TDE) || bool mdcr_el2_tda = (mdcr_el2 & MDCR_TDA) || (mdcr_el2 & MDCR_TDE) ||
(arm_hcr_el2_eff(env) & HCR_TGE); (arm_hcr_el2_eff(env) & HCR_TGE);
if (el < 2 && mdcr_el2_tda && !arm_is_secure_below_el3(env)) { if (el < 2 && mdcr_el2_tda) {
return CP_ACCESS_TRAP_EL2; return CP_ACCESS_TRAP_EL2;
} }
if (el < 3 && (env->cp15.mdcr_el3 & MDCR_TDA)) { if (el < 3 && (env->cp15.mdcr_el3 & MDCR_TDA)) {
@ -606,9 +611,9 @@ static CPAccessResult access_tpm(CPUARMState *env, const ARMCPRegInfo *ri,
bool isread) bool isread)
{ {
int el = arm_current_el(env); int el = arm_current_el(env);
uint64_t mdcr_el2 = arm_mdcr_el2_eff(env);
if (el < 2 && (env->cp15.mdcr_el2 & MDCR_TPM) if (el < 2 && (mdcr_el2 & MDCR_TPM)) {
&& !arm_is_secure_below_el3(env)) {
return CP_ACCESS_TRAP_EL2; return CP_ACCESS_TRAP_EL2;
} }
if (el < 3 && (env->cp15.mdcr_el3 & MDCR_TPM)) { if (el < 3 && (env->cp15.mdcr_el3 & MDCR_TPM)) {
@ -1348,12 +1353,12 @@ static CPAccessResult pmreg_access(CPUARMState *env, const ARMCPRegInfo *ri,
* trapping to EL2 or EL3 for other accesses. * trapping to EL2 or EL3 for other accesses.
*/ */
int el = arm_current_el(env); int el = arm_current_el(env);
uint64_t mdcr_el2 = arm_mdcr_el2_eff(env);
if (el == 0 && !(env->cp15.c9_pmuserenr & 1)) { if (el == 0 && !(env->cp15.c9_pmuserenr & 1)) {
return CP_ACCESS_TRAP; return CP_ACCESS_TRAP;
} }
if (el < 2 && (env->cp15.mdcr_el2 & MDCR_TPM) if (el < 2 && (mdcr_el2 & MDCR_TPM)) {
&& !arm_is_secure_below_el3(env)) {
return CP_ACCESS_TRAP_EL2; return CP_ACCESS_TRAP_EL2;
} }
if (el < 3 && (env->cp15.mdcr_el3 & MDCR_TPM)) { if (el < 3 && (env->cp15.mdcr_el3 & MDCR_TPM)) {
@ -1432,7 +1437,8 @@ static bool pmu_counter_enabled(CPUARMState *env, uint8_t counter)
bool enabled, prohibited, filtered; bool enabled, prohibited, filtered;
bool secure = arm_is_secure(env); bool secure = arm_is_secure(env);
int el = arm_current_el(env); int el = arm_current_el(env);
uint8_t hpmn = env->cp15.mdcr_el2 & MDCR_HPMN; uint64_t mdcr_el2 = arm_mdcr_el2_eff(env);
uint8_t hpmn = mdcr_el2 & MDCR_HPMN;
if (!arm_feature(env, ARM_FEATURE_PMU)) { if (!arm_feature(env, ARM_FEATURE_PMU)) {
return false; return false;
@ -1442,13 +1448,13 @@ static bool pmu_counter_enabled(CPUARMState *env, uint8_t counter)
(counter < hpmn || counter == 31)) { (counter < hpmn || counter == 31)) {
e = env->cp15.c9_pmcr & PMCRE; e = env->cp15.c9_pmcr & PMCRE;
} else { } else {
e = env->cp15.mdcr_el2 & MDCR_HPME; e = mdcr_el2 & MDCR_HPME;
} }
enabled = e && (env->cp15.c9_pmcnten & (1 << counter)); enabled = e && (env->cp15.c9_pmcnten & (1 << counter));
if (!secure) { if (!secure) {
if (el == 2 && (counter < hpmn || counter == 31)) { if (el == 2 && (counter < hpmn || counter == 31)) {
prohibited = env->cp15.mdcr_el2 & MDCR_HPMD; prohibited = mdcr_el2 & MDCR_HPMD;
} else { } else {
prohibited = false; prohibited = false;
} }