target/arm: Update {fp,sve}_exception_el for VHE

When TGE+E2H are both set, CPACR_EL1 is ignored.

Tested-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20200206105448.4726-34-richard.henderson@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Richard Henderson 2020-02-07 14:04:26 +00:00 committed by Peter Maydell
parent d1b31428fd
commit c2ddb7cf96

View File

@ -5791,7 +5791,9 @@ static const ARMCPRegInfo debug_lpae_cp_reginfo[] = {
int sve_exception_el(CPUARMState *env, int el)
{
#ifndef CONFIG_USER_ONLY
if (el <= 1) {
uint64_t hcr_el2 = arm_hcr_el2_eff(env);
if (el <= 1 && (hcr_el2 & (HCR_E2H | HCR_TGE)) != (HCR_E2H | HCR_TGE)) {
bool disabled = false;
/* The CPACR.ZEN controls traps to EL1:
@ -5806,8 +5808,7 @@ int sve_exception_el(CPUARMState *env, int el)
}
if (disabled) {
/* route_to_el2 */
return (arm_feature(env, ARM_FEATURE_EL2)
&& (arm_hcr_el2_eff(env) & HCR_TGE) ? 2 : 1);
return hcr_el2 & HCR_TGE ? 2 : 1;
}
/* Check CPACR.FPEN. */
@ -11691,8 +11692,6 @@ uint32_t HELPER(crc32c)(uint32_t acc, uint32_t val, uint32_t bytes)
int fp_exception_el(CPUARMState *env, int cur_el)
{
#ifndef CONFIG_USER_ONLY
int fpen;
/* CPACR and the CPTR registers don't exist before v6, so FP is
* always accessible
*/
@ -11720,30 +11719,34 @@ int fp_exception_el(CPUARMState *env, int cur_el)
* 0, 2 : trap EL0 and EL1/PL1 accesses
* 1 : trap only EL0 accesses
* 3 : trap no accesses
* This register is ignored if E2H+TGE are both set.
*/
fpen = extract32(env->cp15.cpacr_el1, 20, 2);
switch (fpen) {
case 0:
case 2:
if (cur_el == 0 || cur_el == 1) {
/* Trap to PL1, which might be EL1 or EL3 */
if (arm_is_secure(env) && !arm_el_is_aa64(env, 3)) {
if ((arm_hcr_el2_eff(env) & (HCR_E2H | HCR_TGE)) != (HCR_E2H | HCR_TGE)) {
int fpen = extract32(env->cp15.cpacr_el1, 20, 2);
switch (fpen) {
case 0:
case 2:
if (cur_el == 0 || cur_el == 1) {
/* Trap to PL1, which might be EL1 or EL3 */
if (arm_is_secure(env) && !arm_el_is_aa64(env, 3)) {
return 3;
}
return 1;
}
if (cur_el == 3 && !is_a64(env)) {
/* Secure PL1 running at EL3 */
return 3;
}
return 1;
break;
case 1:
if (cur_el == 0) {
return 1;
}
break;
case 3:
break;
}
if (cur_el == 3 && !is_a64(env)) {
/* Secure PL1 running at EL3 */
return 3;
}
break;
case 1:
if (cur_el == 0) {
return 1;
}
break;
case 3:
break;
}
/*