refactor(cm): introduce a real manage_extensions_nonsecure()

manage_extensions_nonsecure() is problematic because it updates both
context and in-place registers (unlike its secure/realm counterparts).
The in-place register updates make it particularly tricky, as those
never change for the lifetime of TF-A. However, they are only set when
exiting to NS world. As such, all of TF-A's execution before that
operates under a different context. This is inconsistent and could cause
problems.

This patch Introduce a real manage_extensions_nonsecure() which only
operates on the context structure. It also introduces a
cm_manage_extensions_el3() which only operates on register in-place that
are not context switched. It is called in BL31's entrypoints so that all
of TF-A executes with the same environment once all features have been
converted.

Signed-off-by: Boyan Karatotev <boyan.karatotev@arm.com>
Change-Id: Ic579f86c41026d2054863ef44893e0ba4c591da9
diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c
index 3760b8f..44177fa 100644
--- a/lib/el3_runtime/aarch64/context_mgmt.c
+++ b/lib/el3_runtime/aarch64/context_mgmt.c
@@ -37,6 +37,7 @@
 CASSERT(((TWED_DELAY & ~SCR_TWEDEL_MASK) == 0U), assert_twed_delay_value_check);
 #endif /* ENABLE_FEAT_TWED */
 
+static void manage_extensions_nonsecure(cpu_context_t *ctx);
 static void manage_extensions_secure(cpu_context_t *ctx);
 
 static void setup_el1_context(cpu_context_t *ctx, const struct entry_point_info *ep)
@@ -288,6 +289,8 @@
 			HCRX_EL2_INIT_VAL);
 	}
 #endif /* CTX_INCLUDE_EL2_REGS */
+
+	manage_extensions_nonsecure(ctx);
 }
 
 /*******************************************************************************
@@ -504,9 +507,11 @@
 /*******************************************************************************
  * Enable architecture extensions on first entry to Non-secure world.
  * When EL2 is implemented but unused `el2_unused` is non-zero, otherwise
- * it is zero.
+ * it is zero. This function updates some registers in-place and its contents
+ * are being prepared to be moved to cm_manage_extensions_el3 and
+ * cm_manage_extensions_nonsecure.
  ******************************************************************************/
-static void manage_extensions_nonsecure(bool el2_unused, cpu_context_t *ctx)
+static void manage_extensions_nonsecure_mixed(bool el2_unused, cpu_context_t *ctx)
 {
 #if IMAGE_BL31
 	if (is_feat_spe_supported()) {
@@ -549,6 +554,36 @@
 }
 
 /*******************************************************************************
+ * Enable architecture extensions for EL3 execution. This function only updates
+ * registers in-place which are expected to either never change or be
+ * overwritten by el3_exit.
+ ******************************************************************************/
+#if IMAGE_BL31
+void cm_manage_extensions_el3(void)
+{
+}
+#endif /* IMAGE_BL31 */
+
+/*******************************************************************************
+ * Enable architecture extensions on first entry to Non-secure world.
+ ******************************************************************************/
+static void manage_extensions_nonsecure(cpu_context_t *ctx)
+{
+#if IMAGE_BL31
+#endif /* IMAGE_BL31 */
+}
+
+/*******************************************************************************
+ * Enable architecture extensions in-place at EL2 on first entry to Non-secure
+ * world when EL2 is empty and unused.
+ ******************************************************************************/
+static void manage_extensions_nonsecure_el2_unused(void)
+{
+#if IMAGE_BL31
+#endif /* IMAGE_BL31 */
+}
+
+/*******************************************************************************
  * Enable architecture extensions on first entry to Secure world.
  ******************************************************************************/
 static void manage_extensions_secure(cpu_context_t *ctx)
@@ -845,8 +880,10 @@
 			 */
 			write_cnthp_ctl_el2(CNTHP_CTL_RESET_VAL &
 						~(CNTHP_CTL_ENABLE_BIT));
+
+			manage_extensions_nonsecure_el2_unused();
 		}
-		manage_extensions_nonsecure(el2_unused, ctx);
+		manage_extensions_nonsecure_mixed(el2_unused, ctx);
 	}
 
 	cm_el1_sysregs_context_restore(security_state);
@@ -1167,7 +1204,7 @@
 	 * direct register updates. Therefore, do this here
 	 * instead of when setting up context.
 	 */
-	manage_extensions_nonsecure(0, ctx);
+	manage_extensions_nonsecure_mixed(0, ctx);
 
 	/*
 	 * Set the NS bit to be able to access the ICC_SRE_EL2
diff --git a/lib/psci/psci_common.c b/lib/psci/psci_common.c
index bfc09cc..8aa0cce 100644
--- a/lib/psci/psci_common.c
+++ b/lib/psci/psci_common.c
@@ -985,6 +985,9 @@
 	unsigned int parent_nodes[PLAT_MAX_PWR_LVL] = {0};
 	psci_power_state_t state_info = { {PSCI_LOCAL_STATE_RUN} };
 
+	/* Init registers that never change for the lifetime of TF-A */
+	cm_manage_extensions_el3();
+
 	/*
 	 * Verify that we have been explicitly turned ON or resumed from
 	 * suspend.