diff mbox series

[07/22] target/arm: Introduce ARMSecuritySpace

Message ID 20230124000027.3565716-8-richard.henderson@linaro.org
State Superseded
Headers show
Series target/arm: Implement FEAT_RME | expand

Commit Message

Richard Henderson Jan. 24, 2023, midnight UTC
Introduce both the enumeration and functions to retrieve
the current state, and state outside of EL3.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/cpu.h    | 87 +++++++++++++++++++++++++++++++++++----------
 target/arm/helper.c | 46 ++++++++++++++++++++++++
 2 files changed, 115 insertions(+), 18 deletions(-)

Comments

Peter Maydell Feb. 7, 2023, 3 p.m. UTC | #1
On Tue, 24 Jan 2023 at 00:01, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> Introduce both the enumeration and functions to retrieve
> the current state, and state outside of EL3.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  target/arm/cpu.h    | 87 +++++++++++++++++++++++++++++++++++----------
>  target/arm/helper.c | 46 ++++++++++++++++++++++++
>  2 files changed, 115 insertions(+), 18 deletions(-)

> +/* 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;
> +}


> +/**
> + * 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_is_el3_or_mon(env)) {
> -        return true;
> -    }
> -    return arm_is_secure_below_el3(env);
> +    ARMSecuritySpace ss = arm_security_space(env);
> +    return ss == ARMSS_Secure || ss == ARMSS_Root;

maybe
  return arm_space_is_secure(arm_security_space(env));

?

>  }
>
>  /*
> @@ -2457,11 +2498,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;
> diff --git a/target/arm/helper.c b/target/arm/helper.c
> index 7bd15e9d17..bf78a1d74e 100644
> --- a/target/arm/helper.c
> +++ b/target/arm/helper.c
> @@ -12280,3 +12280,49 @@ 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_EL3)) {

The old code had a comment
-        /* If EL3 is not supported then the secure state is implementation
-         * defined, in which case QEMU defaults to non-secure.
which should probably go here I guess.

(Though it's not quite so true for R-profile, where you
don't get to make the impdef choice: v8R-32 is always
NS, and v8R-64 always S. If we ever have to implement
the latter this will probably cause some mild pain.)


Otherwise
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM
Richard Henderson Feb. 8, 2023, 10 p.m. UTC | #2
On 2/7/23 05:00, Peter Maydell wrote:
>>   static inline bool arm_is_secure(CPUARMState *env)
>>   {
>> -    if (arm_is_el3_or_mon(env)) {
>> -        return true;
>> -    }
>> -    return arm_is_secure_below_el3(env);
>> +    ARMSecuritySpace ss = arm_security_space(env);
>> +    return ss == ARMSS_Secure || ss == ARMSS_Root;
> 
> maybe
>    return arm_space_is_secure(arm_security_space(env));

Quite right; arm_space_is_secure was something I added later, and failed to propagate 
completely.

>> +#ifndef CONFIG_USER_ONLY
>> +ARMSecuritySpace arm_security_space(CPUARMState *env)
>> +{
>> +    if (!arm_feature(env, ARM_FEATURE_EL3)) {
> 
> The old code had a comment
> -        /* If EL3 is not supported then the secure state is implementation
> -         * defined, in which case QEMU defaults to non-secure.
> which should probably go here I guess.

Ok.


r~
diff mbox series

Patch

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 26bdd6e465..cfc62d60b0 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -2397,23 +2397,53 @@  static inline int arm_feature(CPUARMState *env, int feature)
 
 void arm_cpu_finalize_features(ARMCPU *cpu, Error **errp);
 
+/*
+ * 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)
-/* 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.
+/**
+ * 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 those levels.
  */
 static inline bool arm_is_secure_below_el3(CPUARMState *env)
 {
-    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 */
@@ -2432,13 +2462,24 @@  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_is_el3_or_mon(env)) {
-        return true;
-    }
-    return arm_is_secure_below_el3(env);
+    ARMSecuritySpace ss = arm_security_space(env);
+    return ss == ARMSS_Secure || ss == ARMSS_Root;
 }
 
 /*
@@ -2457,11 +2498,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;
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 7bd15e9d17..bf78a1d74e 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -12280,3 +12280,49 @@  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_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)
+{
+    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 */