target/arm: Reorg CPAccessResult and access_check_cp_reg
Rearrange the values of the enumerators of CPAccessResult so that we may directly extract the target el. For the two special cases in access_check_cp_reg, use CPAccessResult. Reviewed-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: 20220501055028.646596-3-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
parent
cf7c6d1004
commit
330477eae9
|
@ -167,26 +167,32 @@ static inline bool cptype_valid(int cptype)
|
||||||
typedef enum CPAccessResult {
|
typedef enum CPAccessResult {
|
||||||
/* Access is permitted */
|
/* Access is permitted */
|
||||||
CP_ACCESS_OK = 0,
|
CP_ACCESS_OK = 0,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Combined with one of the following, the low 2 bits indicate the
|
||||||
|
* target exception level. If 0, the exception is taken to the usual
|
||||||
|
* target EL (EL1 or PL1 if in EL0, otherwise to the current EL).
|
||||||
|
*/
|
||||||
|
CP_ACCESS_EL_MASK = 3,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Access fails due to a configurable trap or enable which would
|
* Access fails due to a configurable trap or enable which would
|
||||||
* result in a categorized exception syndrome giving information about
|
* result in a categorized exception syndrome giving information about
|
||||||
* the failing instruction (ie syndrome category 0x3, 0x4, 0x5, 0x6,
|
* the failing instruction (ie syndrome category 0x3, 0x4, 0x5, 0x6,
|
||||||
* 0xc or 0x18). The exception is taken to the usual target EL (EL1 or
|
* 0xc or 0x18).
|
||||||
* PL1 if in EL0, otherwise to the current EL).
|
|
||||||
*/
|
*/
|
||||||
CP_ACCESS_TRAP = 1,
|
CP_ACCESS_TRAP = (1 << 2),
|
||||||
|
CP_ACCESS_TRAP_EL2 = CP_ACCESS_TRAP | 2,
|
||||||
|
CP_ACCESS_TRAP_EL3 = CP_ACCESS_TRAP | 3,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Access fails and results in an exception syndrome 0x0 ("uncategorized").
|
* Access fails and results in an exception syndrome 0x0 ("uncategorized").
|
||||||
* Note that this is not a catch-all case -- the set of cases which may
|
* Note that this is not a catch-all case -- the set of cases which may
|
||||||
* result in this failure is specifically defined by the architecture.
|
* result in this failure is specifically defined by the architecture.
|
||||||
*/
|
*/
|
||||||
CP_ACCESS_TRAP_UNCATEGORIZED = 2,
|
CP_ACCESS_TRAP_UNCATEGORIZED = (2 << 2),
|
||||||
/* As CP_ACCESS_TRAP, but for traps directly to EL2 or EL3 */
|
CP_ACCESS_TRAP_UNCATEGORIZED_EL2 = CP_ACCESS_TRAP_UNCATEGORIZED | 2,
|
||||||
CP_ACCESS_TRAP_EL2 = 3,
|
CP_ACCESS_TRAP_UNCATEGORIZED_EL3 = CP_ACCESS_TRAP_UNCATEGORIZED | 3,
|
||||||
CP_ACCESS_TRAP_EL3 = 4,
|
|
||||||
/* As CP_ACCESS_UNCATEGORIZED, but for traps directly to EL2 or EL3 */
|
|
||||||
CP_ACCESS_TRAP_UNCATEGORIZED_EL2 = 5,
|
|
||||||
CP_ACCESS_TRAP_UNCATEGORIZED_EL3 = 6,
|
|
||||||
} CPAccessResult;
|
} CPAccessResult;
|
||||||
|
|
||||||
typedef struct ARMCPRegInfo ARMCPRegInfo;
|
typedef struct ARMCPRegInfo ARMCPRegInfo;
|
||||||
|
|
|
@ -632,11 +632,13 @@ void HELPER(access_check_cp_reg)(CPUARMState *env, void *rip, uint32_t syndrome,
|
||||||
uint32_t isread)
|
uint32_t isread)
|
||||||
{
|
{
|
||||||
const ARMCPRegInfo *ri = rip;
|
const ARMCPRegInfo *ri = rip;
|
||||||
|
CPAccessResult res = CP_ACCESS_OK;
|
||||||
int target_el;
|
int target_el;
|
||||||
|
|
||||||
if (arm_feature(env, ARM_FEATURE_XSCALE) && ri->cp < 14
|
if (arm_feature(env, ARM_FEATURE_XSCALE) && ri->cp < 14
|
||||||
&& extract32(env->cp15.c15_cpar, ri->cp, 1) == 0) {
|
&& extract32(env->cp15.c15_cpar, ri->cp, 1) == 0) {
|
||||||
raise_exception(env, EXCP_UDEF, syndrome, exception_target_el(env));
|
res = CP_ACCESS_TRAP;
|
||||||
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -655,48 +657,46 @@ void HELPER(access_check_cp_reg)(CPUARMState *env, void *rip, uint32_t syndrome,
|
||||||
mask &= ~((1 << 4) | (1 << 14));
|
mask &= ~((1 << 4) | (1 << 14));
|
||||||
|
|
||||||
if (env->cp15.hstr_el2 & mask) {
|
if (env->cp15.hstr_el2 & mask) {
|
||||||
target_el = 2;
|
res = CP_ACCESS_TRAP_EL2;
|
||||||
goto exept;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ri->accessfn) {
|
if (ri->accessfn) {
|
||||||
|
res = ri->accessfn(env, ri, isread);
|
||||||
|
}
|
||||||
|
if (likely(res == CP_ACCESS_OK)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (ri->accessfn(env, ri, isread)) {
|
fail:
|
||||||
case CP_ACCESS_OK:
|
switch (res & ~CP_ACCESS_EL_MASK) {
|
||||||
return;
|
|
||||||
case CP_ACCESS_TRAP:
|
case CP_ACCESS_TRAP:
|
||||||
target_el = exception_target_el(env);
|
|
||||||
break;
|
|
||||||
case CP_ACCESS_TRAP_EL2:
|
|
||||||
/* Requesting a trap to EL2 when we're in EL3 is
|
|
||||||
* a bug in the access function.
|
|
||||||
*/
|
|
||||||
assert(arm_current_el(env) != 3);
|
|
||||||
target_el = 2;
|
|
||||||
break;
|
|
||||||
case CP_ACCESS_TRAP_EL3:
|
|
||||||
target_el = 3;
|
|
||||||
break;
|
break;
|
||||||
case CP_ACCESS_TRAP_UNCATEGORIZED:
|
case CP_ACCESS_TRAP_UNCATEGORIZED:
|
||||||
target_el = exception_target_el(env);
|
|
||||||
syndrome = syn_uncategorized();
|
|
||||||
break;
|
|
||||||
case CP_ACCESS_TRAP_UNCATEGORIZED_EL2:
|
|
||||||
target_el = 2;
|
|
||||||
syndrome = syn_uncategorized();
|
|
||||||
break;
|
|
||||||
case CP_ACCESS_TRAP_UNCATEGORIZED_EL3:
|
|
||||||
target_el = 3;
|
|
||||||
syndrome = syn_uncategorized();
|
syndrome = syn_uncategorized();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
g_assert_not_reached();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
|
|
||||||
exept:
|
target_el = res & CP_ACCESS_EL_MASK;
|
||||||
|
switch (target_el) {
|
||||||
|
case 0:
|
||||||
|
target_el = exception_target_el(env);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
assert(arm_current_el(env) != 3);
|
||||||
|
assert(arm_is_el2_enabled(env));
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
assert(arm_feature(env, ARM_FEATURE_EL3));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* No "direct" traps to EL1 */
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
|
||||||
raise_exception(env, EXCP_UDEF, syndrome, target_el);
|
raise_exception(env, EXCP_UDEF, syndrome, target_el);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue