target/arm: Introduce ARMSecuritySpace

Introduce both the enumeration and functions to retrieve
the current state, and state outside of EL3.

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20230620124418.805717-6-richard.henderson@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Richard Henderson 2023-06-23 11:15:44 +01:00 committed by Peter Maydell
parent ef1febe758
commit 5d28ac0cf7
2 changed files with 127 additions and 22 deletions

View File

@ -2414,25 +2414,53 @@ static inline int arm_feature(CPUARMState *env, int feature)
void arm_cpu_finalize_features(ARMCPU *cpu, Error **errp);
#if !defined(CONFIG_USER_ONLY)
/*
* ARM v9 security states.
* The ordering of the enumeration corresponds to the low 2 bits
* of the GPI value, and (except for Root) the concat of NSE:NS.
*/
typedef enum ARMSecuritySpace {
ARMSS_Secure = 0,
ARMSS_NonSecure = 1,
ARMSS_Root = 2,
ARMSS_Realm = 3,
} ARMSecuritySpace;
/* Return true if @space is secure, in the pre-v9 sense. */
static inline bool arm_space_is_secure(ARMSecuritySpace space)
{
return space == ARMSS_Secure || space == ARMSS_Root;
}
/* Return the ARMSecuritySpace for @secure, assuming !RME or EL[0-2]. */
static inline ARMSecuritySpace arm_secure_to_space(bool secure)
{
return secure ? ARMSS_Secure : ARMSS_NonSecure;
}
#if !defined(CONFIG_USER_ONLY)
/**
* arm_security_space_below_el3:
* @env: cpu context
*
* Return the security space of exception levels below EL3, following
* an exception return to those levels. Unlike arm_security_space,
* this doesn't care about the current EL.
*/
ARMSecuritySpace arm_security_space_below_el3(CPUARMState *env);
/**
* arm_is_secure_below_el3:
* @env: cpu context
*
* Return true if exception levels below EL3 are in secure state,
* or would be following an exception return to that level.
* Unlike arm_is_secure() (which is always a question about the
* _current_ state of the CPU) this doesn't care about the current
* EL or mode.
* or would be following an exception return to those levels.
*/
static inline bool arm_is_secure_below_el3(CPUARMState *env)
{
assert(!arm_feature(env, ARM_FEATURE_M));
if (arm_feature(env, ARM_FEATURE_EL3)) {
return !(env->cp15.scr_el3 & SCR_NS);
} else {
/* If EL3 is not supported then the secure state is implementation
* defined, in which case QEMU defaults to non-secure.
*/
return false;
}
ARMSecuritySpace ss = arm_security_space_below_el3(env);
return ss == ARMSS_Secure;
}
/* Return true if the CPU is AArch64 EL3 or AArch32 Mon */
@ -2452,16 +2480,23 @@ static inline bool arm_is_el3_or_mon(CPUARMState *env)
return false;
}
/* Return true if the processor is in secure state */
/**
* arm_security_space:
* @env: cpu context
*
* Return the current security space of the cpu.
*/
ARMSecuritySpace arm_security_space(CPUARMState *env);
/**
* arm_is_secure:
* @env: cpu context
*
* Return true if the processor is in secure state.
*/
static inline bool arm_is_secure(CPUARMState *env)
{
if (arm_feature(env, ARM_FEATURE_M)) {
return env->v7m.secure;
}
if (arm_is_el3_or_mon(env)) {
return true;
}
return arm_is_secure_below_el3(env);
return arm_space_is_secure(arm_security_space(env));
}
/*
@ -2480,11 +2515,21 @@ static inline bool arm_is_el2_enabled(CPUARMState *env)
}
#else
static inline ARMSecuritySpace arm_security_space_below_el3(CPUARMState *env)
{
return ARMSS_NonSecure;
}
static inline bool arm_is_secure_below_el3(CPUARMState *env)
{
return false;
}
static inline ARMSecuritySpace arm_security_space(CPUARMState *env)
{
return ARMSS_NonSecure;
}
static inline bool arm_is_secure(CPUARMState *env)
{
return false;

View File

@ -12136,3 +12136,63 @@ void aarch64_sve_change_el(CPUARMState *env, int old_el,
}
}
#endif
#ifndef CONFIG_USER_ONLY
ARMSecuritySpace arm_security_space(CPUARMState *env)
{
if (arm_feature(env, ARM_FEATURE_M)) {
return arm_secure_to_space(env->v7m.secure);
}
/*
* If EL3 is not supported then the secure state is implementation
* defined, in which case QEMU defaults to non-secure.
*/
if (!arm_feature(env, ARM_FEATURE_EL3)) {
return ARMSS_NonSecure;
}
/* Check for AArch64 EL3 or AArch32 Mon. */
if (is_a64(env)) {
if (extract32(env->pstate, 2, 2) == 3) {
if (cpu_isar_feature(aa64_rme, env_archcpu(env))) {
return ARMSS_Root;
} else {
return ARMSS_Secure;
}
}
} else {
if ((env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_MON) {
return ARMSS_Secure;
}
}
return arm_security_space_below_el3(env);
}
ARMSecuritySpace arm_security_space_below_el3(CPUARMState *env)
{
assert(!arm_feature(env, ARM_FEATURE_M));
/*
* If EL3 is not supported then the secure state is implementation
* defined, in which case QEMU defaults to non-secure.
*/
if (!arm_feature(env, ARM_FEATURE_EL3)) {
return ARMSS_NonSecure;
}
/*
* Note NSE cannot be set without RME, and NSE & !NS is Reserved.
* Ignoring NSE when !NS retains consistency without having to
* modify other predicates.
*/
if (!(env->cp15.scr_el3 & SCR_NS)) {
return ARMSS_Secure;
} else if (env->cp15.scr_el3 & SCR_NSE) {
return ARMSS_Realm;
} else {
return ARMSS_NonSecure;
}
}
#endif /* !CONFIG_USER_ONLY */