target/arm: Support CP_ACCESS_TRAP_EL1 as a CPAccessResult
In the CPAccessResult enum, the CP_ACCESS_TRAP* values indicate the equivalent of the pseudocode AArch64.SystemAccessTrap(..., 0x18), causing a trap to a specified exception level with a syndrome value giving information about the failing instructions. In the pseudocode, such traps are always taken to a specified target EL. We support that for target EL of 2 or 3 via CP_ACCESS_TRAP_EL2 and CP_ACCESS_TRAP_EL3, but the only way to take the access trap to EL1 currently is to use CP_ACCESS_TRAP, which takes the trap to the "usual target EL" (EL1 if in EL0, otherwise to the current EL). Add CP_ACCESS_TRAP_EL1 so that access functions can follow the pseudocode more closely. (Note that for the common case in the pseudocode of "trap to EL2 if HCR_EL2.TGE is set, otherwise trap to EL1", we handle this in raise_exception(), so access functions don't need to special case it and can use CP_ACCESS_TRAP_EL1.) Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20250130182309.717346-10-peter.maydell@linaro.org
This commit is contained in:
parent
ff8b906a00
commit
273d0e84cc
@ -331,6 +331,7 @@ typedef enum CPAccessResult {
|
|||||||
* 0xc or 0x18).
|
* 0xc or 0x18).
|
||||||
*/
|
*/
|
||||||
CP_ACCESS_TRAP = (1 << 2),
|
CP_ACCESS_TRAP = (1 << 2),
|
||||||
|
CP_ACCESS_TRAP_EL1 = CP_ACCESS_TRAP | 1,
|
||||||
CP_ACCESS_TRAP_EL2 = CP_ACCESS_TRAP | 2,
|
CP_ACCESS_TRAP_EL2 = CP_ACCESS_TRAP | 2,
|
||||||
CP_ACCESS_TRAP_EL3 = CP_ACCESS_TRAP | 3,
|
CP_ACCESS_TRAP_EL3 = CP_ACCESS_TRAP | 3,
|
||||||
|
|
||||||
|
@ -781,7 +781,7 @@ const void *HELPER(access_check_cp_reg)(CPUARMState *env, uint32_t key,
|
|||||||
* the other trap takes priority. So we take the "check HSTR_EL2" path
|
* the other trap takes priority. So we take the "check HSTR_EL2" path
|
||||||
* for all of those cases.)
|
* for all of those cases.)
|
||||||
*/
|
*/
|
||||||
if (res != CP_ACCESS_OK && ((res & CP_ACCESS_EL_MASK) == 0) &&
|
if (res != CP_ACCESS_OK && ((res & CP_ACCESS_EL_MASK) < 2) &&
|
||||||
arm_current_el(env) == 0) {
|
arm_current_el(env) == 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
@ -887,6 +887,9 @@ const void *HELPER(access_check_cp_reg)(CPUARMState *env, uint32_t key,
|
|||||||
case 0:
|
case 0:
|
||||||
target_el = exception_target_el(env);
|
target_el = exception_target_el(env);
|
||||||
break;
|
break;
|
||||||
|
case 1:
|
||||||
|
assert(arm_current_el(env) < 2);
|
||||||
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
assert(arm_current_el(env) != 3);
|
assert(arm_current_el(env) != 3);
|
||||||
assert(arm_is_el2_enabled(env));
|
assert(arm_is_el2_enabled(env));
|
||||||
@ -895,7 +898,6 @@ const void *HELPER(access_check_cp_reg)(CPUARMState *env, uint32_t key,
|
|||||||
assert(arm_feature(env, ARM_FEATURE_EL3));
|
assert(arm_feature(env, ARM_FEATURE_EL3));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* No "direct" traps to EL1 */
|
|
||||||
g_assert_not_reached();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user