Introduce test for SVE support

When SVE extension is enabled, test that it correctly performs simple
operations.

Generating SVE instructions requires O3 compilation optimization. Since
the build structure does not allow compilation flag modification for
specific files, the function testing SVE support has been pre-compiled
and added as an assembly file.

Change-Id: Id9ba7d9e1de9bcbae3065cad2dd3e1dbe87ef03a
Signed-off-by: Ambroise Vincent <ambroise.vincent@arm.com>
diff --git a/include/lib/aarch32/arch_features.h b/include/lib/aarch32/arch_features.h
index ddf0968..b953db7 100644
--- a/include/lib/aarch32/arch_features.h
+++ b/include/lib/aarch32/arch_features.h
@@ -17,6 +17,12 @@
 		ID_PFR1_GENTIMER_MASK) != 0U;
 }
 
+static inline bool is_armv8_2_sve_present(void)
+{
+	/* SVE is not usable in aarch32 */
+	return false;
+}
+
 static inline bool is_armv8_2_ttcnp_present(void)
 {
 	return ((read_id_mmfr4() >> ID_MMFR4_CNP_SHIFT) &
diff --git a/include/lib/aarch64/arch.h b/include/lib/aarch64/arch.h
index c4ec4ff..fea256b 100644
--- a/include/lib/aarch64/arch.h
+++ b/include/lib/aarch64/arch.h
@@ -364,12 +364,12 @@
 #define CPTR_EL3_RESET_VAL	U(0x0)
 
 /* CPTR_EL2 definitions */
-#define CPTR_EL2_RES1		((U(1) << 13) | (U(1) << 12) | (U(0x3ff)))
-#define CPTR_EL2_TCPAC_BIT	(U(1) << 31)
-#define CPTR_EL2_TAM_BIT	(U(1) << 30)
-#define CPTR_EL2_TTA_BIT	(U(1) << 20)
-#define CPTR_EL2_TFP_BIT	(U(1) << 10)
-#define CPTR_EL2_TZ_BIT		(U(1) << 8)
+#define CPTR_EL2_RES1		((ULL(3) << 12) | (ULL(1) << 9) | (ULL(0xff)))
+#define CPTR_EL2_TCPAC_BIT	(ULL(1) << 31)
+#define CPTR_EL2_TAM_BIT	(ULL(1) << 30)
+#define CPTR_EL2_TTA_BIT	(ULL(1) << 20)
+#define CPTR_EL2_TFP_BIT	(ULL(1) << 10)
+#define CPTR_EL2_TZ_BIT		(ULL(1) << 8)
 #define CPTR_EL2_RESET_VAL	CPTR_EL2_RES1
 
 /* CPSR/SPSR definitions */
diff --git a/include/lib/aarch64/arch_features.h b/include/lib/aarch64/arch_features.h
index 6af1d03..c5cdc3e 100644
--- a/include/lib/aarch64/arch_features.h
+++ b/include/lib/aarch64/arch_features.h
@@ -17,6 +17,12 @@
 	return true;
 }
 
+static inline bool is_armv8_2_sve_present(void)
+{
+	return ((read_id_aa64pfr0_el1() >> ID_AA64PFR0_SVE_SHIFT) &
+		ID_AA64PFR0_SVE_MASK) == 1U;
+}
+
 static inline bool is_armv8_2_ttcnp_present(void)
 {
 	return ((read_id_aa64mmfr2_el1() >> ID_AA64MMFR2_EL1_CNP_SHIFT) &
diff --git a/tftf/framework/aarch64/arch.c b/tftf/framework/aarch64/arch.c
index 0cdfd65..c3f57b8 100644
--- a/tftf/framework/aarch64/arch.c
+++ b/tftf/framework/aarch64/arch.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -17,6 +17,13 @@
 		 * interrupt masks.
 		 */
 		write_hcr_el2(HCR_TGE_BIT);
+
+		/*
+		 * Disable trap of SVE instructions to EL2.
+		 * The fields of the CPTR_EL2 register reset to an
+		 * architecturally UNKNOWN value.
+		 */
+		write_cptr_el2(CPTR_EL2_RES1);
 		isb();
 	}
 }
diff --git a/tftf/tests/extensions/sve/sve_operations.S b/tftf/tests/extensions/sve/sve_operations.S
new file mode 100644
index 0000000..9440b13
--- /dev/null
+++ b/tftf/tests/extensions/sve/sve_operations.S
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <asm_macros.S>
+
+#include "./test_sve.h"
+
+#ifdef AARCH64
+#if __GNUC__ > 8 || (__GNUC__ == 8 && __GNUC_MINOR__ > 0)
+
+/*
+ * Based on example code from the Arm Compiler Scalable Vector Extension User
+ * Guide[1].
+ * [1] https://developer.arm.com/docs/100891/latest/getting-started-with-the-sve-compiler/compiling-c-and-c-code-for-sve-enabled-targets
+ */
+
+	.arch armv8.2-a+crc+fp16+sve
+	.global	sve_subtract_arrays
+func sve_subtract_arrays
+	mov	x4, SVE_ARRAYSIZE
+	mov	x5, x4
+	mov	x3, 0
+	whilelo	p0.s, xzr, x4
+.loop:
+	ld1w	z0.s, p0/z, [x1, x3, lsl 2]
+	ld1w	z1.s, p0/z, [x2, x3, lsl 2]
+	sub	z0.s, z0.s, z1.s
+	st1w	z0.s, p0, [x0, x3, lsl 2]
+	incw	x3
+	whilelo	p0.s, x3, x5
+	bne	.loop
+	ret
+endfunc sve_subtract_arrays
+
+#endif /* __GNUC__ > 8 || (__GNUC__ == 8 && __GNUC_MINOR__ > 0) */
+#endif /* AARCH64 */
diff --git a/tftf/tests/extensions/sve/test_sve.c b/tftf/tests/extensions/sve/test_sve.c
new file mode 100644
index 0000000..235e2b8
--- /dev/null
+++ b/tftf/tests/extensions/sve/test_sve.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_features.h>
+#include <arch_helpers.h>
+#include <debug.h>
+#include <stdlib.h>
+#include <tftf_lib.h>
+
+#include "./test_sve.h"
+
+#if __GNUC__ > 8 || (__GNUC__ == 8 && __GNUC_MINOR__ > 0)
+
+extern void sve_subtract_arrays(int *difference, const int *sve_op_1,
+				const int *sve_op_2);
+
+static int sve_difference[SVE_ARRAYSIZE];
+static int sve_op_1[SVE_ARRAYSIZE];
+static int sve_op_2[SVE_ARRAYSIZE];
+
+/*
+ * @Test_Aim@ Test SVE support when the extension is enabled.
+ *
+ * Execute some SVE instructions. These should not be trapped to EL3, as TF-A is
+ * responsible for enabling SVE for Non-secure world.
+ *
+ * If they are trapped, we won't recover from that and the test session will
+ * effectively be aborted.
+ */
+test_result_t test_sve_support(void)
+{
+	/* Check if SVE is implemented and usable */
+	if (is_armv8_2_sve_present() == false) {
+		tftf_testcase_printf("SVE support absent\n");
+		return TEST_RESULT_SKIPPED;
+	}
+
+	for (int i = 0; i < SVE_ARRAYSIZE; i++) {
+		/* Generate a random number between 200 and 299 */
+		sve_op_1[i] = (rand() % 100) + 200;
+		/* Generate a random number between 0 and 99 */
+		sve_op_2[i] = rand() % 100;
+	}
+
+	/* Perform SVE operations */
+	sve_subtract_arrays(sve_difference, sve_op_1, sve_op_2);
+
+	return TEST_RESULT_SUCCESS;
+}
+
+#else
+
+test_result_t test_sve_support(void)
+{
+	tftf_testcase_printf("Unsupported compiler\n");
+	return TEST_RESULT_SKIPPED;
+}
+
+#endif /* __GNUC__ > 8 || (__GNUC__ == 8 && __GNUC_MINOR__ > 0) */
diff --git a/tftf/tests/extensions/sve/test_sve.h b/tftf/tests/extensions/sve/test_sve.h
new file mode 100644
index 0000000..96eb422
--- /dev/null
+++ b/tftf/tests/extensions/sve/test_sve.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef TEST_SVE_H
+#define TEST_SVE_H
+
+#define SVE_ARRAYSIZE 1024
+
+#endif /* TEST_SVE_H */
diff --git a/tftf/tests/tests-cpu-extensions.mk b/tftf/tests/tests-cpu-extensions.mk
index 6734b0a..38271dc 100644
--- a/tftf/tests/tests-cpu-extensions.mk
+++ b/tftf/tests/tests-cpu-extensions.mk
@@ -1,11 +1,13 @@
 #
-# Copyright (c) 2018, Arm Limited. All rights reserved.
+# Copyright (c) 2018-2019, Arm Limited. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
 
 TESTS_SOURCES	+=	$(addprefix tftf/tests/,			\
 	extensions/amu/test_amu.c					\
+	extensions/sve/sve_operations.S					\
+	extensions/sve/test_sve.c					\
 	runtime_services/arm_arch_svc/smccc_arch_workaround_1.c		\
 	runtime_services/arm_arch_svc/smccc_arch_workaround_2.c		\
 )
diff --git a/tftf/tests/tests-cpu-extensions.xml b/tftf/tests/tests-cpu-extensions.xml
index 17f37fd..666d5a0 100644
--- a/tftf/tests/tests-cpu-extensions.xml
+++ b/tftf/tests/tests-cpu-extensions.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 
 <!--
-  Copyright (c) 2018, Arm Limited. All rights reserved.
+  Copyright (c) 2018-2019, Arm Limited. All rights reserved.
 
   SPDX-License-Identifier: BSD-3-Clause
 -->
@@ -11,6 +11,7 @@
   <testsuite name="CPU extensions" description="Various CPU extensions tests">
     <testcase name="AMUv1 non-zero counters" function="test_amu_nonzero_ctr" />
     <testcase name="AMUv1 suspend/resume" function="test_amu_suspend_resume" />
+    <testcase name="SVE support" function="test_sve_support" />
   </testsuite>
 
   <testsuite name="ARM_ARCH_SVC" description="Arm Architecture Service tests">