feat(spmd): pass SMCCCv1.3 SVE hint to lower EL

A normal world caller can emit an SMC with the SVE hint bit set such
that the callee can perform an optimization by omitting to save/restore
the SVE context. Update the SPMD to pass this information to the SPMC
when set by the caller in the SMC flags parameter.
For now, restrict this behavior to the SPMC living at S-EL2.

Signed-off-by: Olivier Deprez <olivier.deprez@arm.com>
Change-Id: Icf46eb8a391dd3ddd2ee6aff8581a2f1c8a1c274
diff --git a/services/std_svc/spm/el3_spmc/spmc_main.c b/services/std_svc/spm/el3_spmc/spmc_main.c
index 9cfcd87..247e2c8 100644
--- a/services/std_svc/spm/el3_spmc/spmc_main.c
+++ b/services/std_svc/spm/el3_spmc/spmc_main.c
@@ -234,7 +234,7 @@
 	/* If we originated in the normal world then switch contexts. */
 	else if (!secure_origin && ffa_is_secure_world_id(dst_id)) {
 		return spmd_smc_switch_state(smc_fid, secure_origin, x1, x2,
-					     x3, x4, handle);
+					     x3, x4, handle, flags);
 	} else {
 		/* Unknown State. */
 		panic();
@@ -2490,9 +2490,11 @@
 	/*
 	 * Forward the interrupt to the S-EL1 SP. The interrupt ID is not
 	 * populated as the SP can determine this by itself.
+	 * The flags field is forced to 0 mainly to pass the SVE hint bit
+	 * cleared for consumption by the lower EL.
 	 */
 	return spmd_smc_switch_state(FFA_INTERRUPT, false,
 				     FFA_PARAM_MBZ, FFA_PARAM_MBZ,
 				     FFA_PARAM_MBZ, FFA_PARAM_MBZ,
-				     handle);
+				     handle, 0ULL);
 }
diff --git a/services/std_svc/spmd/spmd_main.c b/services/std_svc/spmd/spmd_main.c
index 5d19868..49d7058 100644
--- a/services/std_svc/spmd/spmd_main.c
+++ b/services/std_svc/spmd/spmd_main.c
@@ -667,11 +667,22 @@
 			       uint64_t x2,
 			       uint64_t x3,
 			       uint64_t x4,
-			       void *handle)
+			       void *handle,
+			       uint64_t flags)
 {
 	unsigned int secure_state_in = (secure_origin) ? SECURE : NON_SECURE;
 	unsigned int secure_state_out = (!secure_origin) ? SECURE : NON_SECURE;
 
+#if SPMD_SPM_AT_SEL2
+	if ((secure_state_out == SECURE) && (is_sve_hint_set(flags) == true)) {
+		/*
+		 * Set the SVE hint bit in x0 and pass to the lower secure EL,
+		 * if it was set by the caller.
+		 */
+		smc_fid |= (FUNCID_SVE_HINT_MASK << FUNCID_SVE_HINT_SHIFT);
+	}
+#endif
+
 	/* Save incoming security state */
 #if SPMD_SPM_AT_SEL2
 	if (secure_state_in == NON_SECURE) {
@@ -746,8 +757,9 @@
 		return spmc_smc_handler(smc_fid, secure_origin, x1, x2, x3, x4,
 					cookie, handle, flags);
 	}
+
 	return spmd_smc_switch_state(smc_fid, secure_origin, x1, x2, x3, x4,
-				     handle);
+				     handle, flags);
 
 }