refactor(cm): clean up per-world context

In preparation for SMCCC_ARCH_FEATURE_AVAILABILITY, it is useful for
context to be directly related to the underlying system. Currently,
certain bits like SCR_EL3.APK are always set with the understanding that
they will only take effect if the feature is present.

However, that is problematic for SMCCC_ARCH_FEATURE_AVAILABILITY (an
SMCCC call to report which features firmware enables), as simply reading
the enable bit may contradict the ID register, like the APK bit above
for a system with no Pauth present.

This patch is to clean up these cases. Add a check for PAuth's presence
so that the APK bit remains unset if not present. Also move SPE and TRBE
enablement to only the NS context. They already only enable the features
for NS only and disable them for Secure and Realm worlds. This change
only makes these worlds' context read 0 for easy bitmasking.

There's only a single snag on SPE and TRBE. Currently, their fields have
the same values and any world asymmetry is handled by hardware. Since we
don't want to do that, the buffers' ownership will change if we just set
the fields to 0 for non-NS worlds. Doing that, however, exposes Secure
state to a potential denial of service attack - a malicious NS can
enable profiling and call an SMC. Then, the owning security state will
change and since no SPE/TRBE registers are contexted, Secure state will
start generating records. Always have NS world own the buffers to
prevent this.

Finally, get rid of manage_extensions_common() as it's just a level of
indirection to enable a single feature.

Change-Id: I487bd4c70ac3e2105583917a0e5499e0ee248ed9
Signed-off-by: Boyan Karatotev <boyan.karatotev@arm.com>
diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c
index ca5e047..f220d8a 100644
--- a/lib/el3_runtime/aarch64/context_mgmt.c
+++ b/lib/el3_runtime/aarch64/context_mgmt.c
@@ -49,7 +49,6 @@
 per_world_context_t per_world_context[CPU_DATA_CONTEXT_NUM];
 static bool has_secure_perworld_init;
 
-static void manage_extensions_common(cpu_context_t *ctx);
 static void manage_extensions_nonsecure(cpu_context_t *ctx);
 static void manage_extensions_secure(cpu_context_t *ctx);
 static void manage_extensions_secure_per_world(void);
@@ -236,8 +235,9 @@
 	 * SCR_EL3.APK: Set to one to not trap any PAuth key values at ELs other
 	 *  than EL3
 	 */
-	scr_el3 |= SCR_API_BIT | SCR_APK_BIT;
-
+	if (is_armv8_3_pauth_present()) {
+		scr_el3 |= SCR_API_BIT | SCR_APK_BIT;
+	}
 #endif /* CTX_INCLUDE_PAUTH_REGS */
 
 #if HANDLE_EA_EL3_FIRST_NS
@@ -251,7 +251,6 @@
 	 * and RAS ERX registers from EL1 and EL2(from any security state)
 	 * are trapped to EL3.
 	 * Set here to trap only for NS EL1/EL2
-	 *
 	 */
 	scr_el3 |= SCR_TERR_BIT;
 #endif
@@ -447,9 +446,9 @@
 	 * If FEAT_RNG_TRAP is enabled, all reads of the RNDR and RNDRRS
 	 * registers are trapped to EL3.
 	 */
-#if ENABLE_FEAT_RNG_TRAP
-	scr_el3 |= SCR_TRNDR_BIT;
-#endif
+	if (is_feat_rng_trap_supported()) {
+		scr_el3 |= SCR_TRNDR_BIT;
+	}
 
 #if FAULT_INJECTION_SUPPORT
 	/* Enable fault injection from lower ELs */
@@ -466,7 +465,9 @@
 	 * SCR_EL3.APK: Set to one to not trap any PAuth key values at ELs other
 	 *  than EL3
 	 */
-	scr_el3 |= SCR_API_BIT | SCR_APK_BIT;
+	if (is_armv8_3_pauth_present()) {
+		scr_el3 |= SCR_API_BIT | SCR_APK_BIT;
+	}
 #endif /* CTX_INCLUDE_PAUTH_REGS */
 
 	/*
@@ -567,11 +568,12 @@
 			& ~(MDCR_TDA_BIT | MDCR_TDOSA_BIT)) ;
 	write_ctx_reg(state, CTX_MDCR_EL3, mdcr_el3);
 
-	/*
-	 * Configure MDCR_EL3 register as applicable for each world
-	 * (NS/Secure/Realm) context.
-	 */
-	manage_extensions_common(ctx);
+#if IMAGE_BL31
+	/* Enable FEAT_TRF for Non-Secure and prohibit for Secure state. */
+	if (is_feat_trf_supported()) {
+		trf_enable(ctx);
+	}
+#endif /* IMAGE_BL31 */
 
 	/*
 	 * Store the X0-X7 value from the entrypoint into the context
@@ -781,41 +783,6 @@
 }
 
 /*******************************************************************************
- * Enable architecture extensions on first entry to Non-secure world only
- * and disable for secure world.
- *
- * NOTE: Arch features which have been provided with the capability of getting
- * enabled only for non-secure world and being disabled for secure world are
- * grouped here, as the MDCR_EL3 context value remains same across the worlds.
- ******************************************************************************/
-static void manage_extensions_common(cpu_context_t *ctx)
-{
-#if IMAGE_BL31
-	if (is_feat_spe_supported()) {
-		/*
-		 * Enable FEAT_SPE for Non-Secure and prohibit for Secure state.
-		 */
-		spe_enable(ctx);
-	}
-
-	if (is_feat_trbe_supported()) {
-		/*
-		 * Enable FEAT_TRBE for Non-Secure and prohibit for Secure and
-		 * Realm state.
-		 */
-		trbe_enable(ctx);
-	}
-
-	if (is_feat_trf_supported()) {
-		/*
-		 * Enable FEAT_TRF for Non-Secure and prohibit for Secure state.
-		 */
-		trf_enable(ctx);
-	}
-#endif /* IMAGE_BL31 */
-}
-
-/*******************************************************************************
  * Enable architecture extensions on first entry to Non-secure world.
  ******************************************************************************/
 static void manage_extensions_nonsecure(cpu_context_t *ctx)
@@ -837,6 +804,21 @@
 		debugv8p9_extended_bp_wp_enable(ctx);
 	}
 
+	/*
+	 * SPE, TRBE, and BRBE have multi-field enables that affect which world
+	 * they apply to. Despite this, it is useful to ignore these for
+	 * simplicity in determining the feature's per world enablement status.
+	 * This is only possible when context is written per-world. Relied on
+	 * by SMCCC_ARCH_FEATURE_AVAILABILITY
+	 */
+	if (is_feat_spe_supported()) {
+		spe_enable(ctx);
+	}
+
+	if (is_feat_trbe_supported()) {
+		trbe_enable(ctx);
+	}
+
 	if (is_feat_brbe_supported()) {
 		brbe_enable(ctx);
 	}
@@ -930,6 +912,20 @@
 			sme_disable(ctx);
 		}
 	}
+
+	/*
+	 * SPE and TRBE cannot be fully disabled from EL3 registers alone, only
+	 * sysreg access can. In case the EL1 controls leave them active on
+	 * context switch, we want the owning security state to be NS so Secure
+	 * can't be DOSed.
+	 */
+	if (is_feat_spe_supported()) {
+		spe_disable(ctx);
+	}
+
+	if (is_feat_trbe_supported()) {
+		trbe_disable(ctx);
+	}
 #endif /* IMAGE_BL31 */
 }