Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
rth7680 authored and pm215 committed Jun 23, 2023
1 parent ef1febe commit 5d28ac0
Show file tree
Hide file tree
Showing 2 changed files with 127 additions and 22 deletions.
89 changes: 67 additions & 22 deletions target/arm/cpu.h
Expand Up @@ -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 */
Expand All @@ -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));
}

/*
Expand All @@ -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;
Expand Down
60 changes: 60 additions & 0 deletions target/arm/helper.c
Expand Up @@ -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 */

0 comments on commit 5d28ac0

Please sign in to comment.