tftf(rme): intermittently switch to Realm while doing NS SVE ops

Interleave NS SVE operations with Realm SVE operations and check whether
SVE vectors are not affected.

This test also configures SVE op array and SVE vector length with random
value in NS and Realm for test each iteration.

Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Change-Id: I7a9ba4bd0d298f187baa3048ec622eb97ec3d99f
diff --git a/realm/include/realm_tests.h b/realm/include/realm_tests.h
index c1c780b..13a063a 100644
--- a/realm/include/realm_tests.h
+++ b/realm/include/realm_tests.h
@@ -15,6 +15,7 @@
 bool test_realm_sve_rdvl(void);
 bool test_realm_sve_read_id_registers(void);
 bool test_realm_sve_probe_vl(void);
+bool test_realm_sve_ops(void);
 
 #endif /* REALM_TESTS_H */
 
diff --git a/realm/realm.mk b/realm/realm.mk
index e12f3e1..047dff8 100644
--- a/realm/realm.mk
+++ b/realm/realm.mk
@@ -43,7 +43,8 @@
 	lib/locks/${ARCH}/spinlock.S					\
 	lib/delay/delay.c						\
 	lib/extensions/fpu/fpu.c					\
-	lib/extensions/sve/aarch64/sve.c
+	lib/extensions/sve/aarch64/sve.c				\
+	lib/extensions/sve/aarch64/sve_helpers.S
 
 # TODO: Remove dependency on TFTF files.
 REALM_SOURCES	+=							\
diff --git a/realm/realm_payload_main.c b/realm/realm_payload_main.c
index f19dd3e..b13e0a1 100644
--- a/realm/realm_payload_main.c
+++ b/realm/realm_payload_main.c
@@ -102,6 +102,9 @@
 		case REALM_SVE_PROBE_VL:
 			test_succeed = test_realm_sve_probe_vl();
 			break;
+		case REALM_SVE_OPS:
+			test_succeed = test_realm_sve_ops();
+			break;
 		default:
 			realm_printf("%s() invalid cmd %u\n", __func__, cmd);
 			break;
diff --git a/realm/realm_sve.c b/realm/realm_sve.c
index 349b8d7..ed6c7c7 100644
--- a/realm/realm_sve.c
+++ b/realm/realm_sve.c
@@ -8,11 +8,18 @@
 #include <arch_helpers.h>
 #include <assert.h>
 #include <debug.h>
+#include <stdlib.h>
 #include <lib/extensions/sve.h>
 
 #include <host_realm_sve.h>
 #include <host_shared_data.h>
 
+#define RL_SVE_OP_ARRAYSIZE		512U
+#define SVE_TEST_ITERATIONS		4U
+
+static int rl_sve_op_1[RL_SVE_OP_ARRAYSIZE];
+static int rl_sve_op_2[RL_SVE_OP_ARRAYSIZE];
+
 /* Returns the maximum supported VL. This test is called only by sve Realm */
 bool test_realm_sve_rdvl(void)
 {
@@ -69,3 +76,36 @@
 
 	return true;
 }
+
+bool test_realm_sve_ops(void)
+{
+	int val, i;
+
+	assert(is_armv8_2_sve_present());
+
+	/* get at random value to do sve_subtract */
+	val = rand();
+	for (i = 0; i < RL_SVE_OP_ARRAYSIZE; i++) {
+		rl_sve_op_1[i] = val - i;
+		rl_sve_op_2[i] = 1;
+	}
+
+	for (i = 0; i < SVE_TEST_ITERATIONS; i++) {
+		/* Config Realm with random SVE length */
+		sve_config_vq(SVE_GET_RANDOM_VQ);
+
+		/* Perform SVE operations, without world switch */
+		sve_subtract_arrays(rl_sve_op_1, rl_sve_op_1, rl_sve_op_2,
+				    RL_SVE_OP_ARRAYSIZE);
+	}
+
+	/* Check result of SVE operations. */
+	for (i = 0; i < RL_SVE_OP_ARRAYSIZE; i++) {
+		if (rl_sve_op_1[i] != (val - i - SVE_TEST_ITERATIONS)) {
+			realm_printf("Realm: SVE ops failed\n");
+			return false;
+		}
+	}
+
+	return true;
+}