feat(sme): update sme/mortlach tests

FEAT_SME is an optional architectural extension from v9.2.
Previously due to the lack of support in toolchain, testing
SME instructions were overlooked and minimal tests were added.

This patch addresses them, with additional tests to test
the SME instructions. In order to avoid toolchain requirements
we manually encode the instructions for accessing ZA array.

Signed-off-by: Jayanth Dodderi Chidanand <jayanthdodderi.chidanand@arm.com>
Change-Id: Ia9edd2711d548757b96495498bf9d47b9db68a09
diff --git a/lib/extensions/sme/aarch64/sme.c b/lib/extensions/sme/aarch64/sme.c
index 28ddcd6..632b2a7 100644
--- a/lib/extensions/sme/aarch64/sme.c
+++ b/lib/extensions/sme/aarch64/sme.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2021-2023, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -8,57 +8,22 @@
 #include <stdio.h>
 
 #include <arch.h>
+#include <arch_features.h>
 #include <arch_helpers.h>
+#include <debug.h>
 #include <lib/extensions/sme.h>
 
-#ifdef __aarch64__
-
 /*
- * feat_sme_supported
- *   Check if SME is supported on this platform.
- * Return
- *   true if SME supported, false if not.
+ * Function : sme_enable
+ * Enable SME for nonsecure use at EL2 for TFTF cases.
  */
-bool feat_sme_supported(void)
-{
-	uint64_t features;
-
-	features = read_id_aa64pfr1_el1() >> ID_AA64PFR1_EL1_SME_SHIFT;
-	return (features & ID_AA64PFR1_EL1_SME_MASK) != 0U;
-}
-
-/*
- * feat_sme_fa64_supported
- *  Check if FEAT_SME_FA64 is supported.
- * Return
- *  True if supported, false if not.
- */
-bool feat_sme_fa64_supported(void)
-{
-	uint64_t features;
-
-	features = read_id_aa64smfr0_el1();
-	return (features & ID_AA64SMFR0_EL1_FA64_BIT) != 0U;
-}
-
-/*
- * sme_enable
- *   Enable SME for nonsecure use at EL2 for TFTF cases.
- * Return
- *   0 if successful.
- */
-int sme_enable(void)
+void sme_enable(void)
 {
 	u_register_t reg;
 
-	/* Make sure SME is supported. */
-	if (!feat_sme_supported()) {
-		return -1;
-	}
-
 	/*
-	 * Make sure SME accesses don't cause traps by setting appropriate fields
-	 * in CPTR_EL2.
+	 * Make sure SME accesses don't cause traps by setting appropriate
+	 * fields in CPTR_EL2.
 	 */
 	reg = read_cptr_el2();
 	if ((read_hcr_el2() & HCR_E2H_BIT) == 0U) {
@@ -70,48 +35,78 @@
 	}
 	write_cptr_el2(reg);
 
-	return 0;
+	isb();
+
 }
 
 /*
- * sme_smstart
- *   This function enables streaming mode and optinally enables ZA array access
- *   at the same time.
+ * Function: sme_smstart
+ * This function enables streaming mode and ZA array storage access
+ * independently or together based on the type of instruction variant.
+ *
  * Parameters
- *   enable_za: If set, ZA access is enabled.  If cleared, ZA bit is untouched.
+ * smstart_type: If SMSTART, streaming mode and ZA access is enabled.
+ *               If SMSTART_SM, streaming mode enabled.
+ *               If SMSTART_ZA enables SME ZA storage and, ZT0 storage access.
  */
-void sme_smstart(bool enable_za)
+void sme_smstart(smestart_instruction_type_t smstart_type)
 {
-	u_register_t svcr = SVCR_SM_BIT;
+	u_register_t svcr = 0ULL;
 
-	if (enable_za) {
-		svcr |= SVCR_ZA_BIT;
+	switch (smstart_type) {
+	case SMSTART:
+		svcr = (SVCR_SM_BIT | SVCR_ZA_BIT);
+		break;
+
+	case SMSTART_SM:
+		svcr = SVCR_SM_BIT;
+		break;
+
+	case SMSTART_ZA:
+		svcr = SVCR_ZA_BIT;
+		break;
+
+	default:
+		ERROR("Illegal SMSTART Instruction Variant\n");
+		break;
 	}
-
 	write_svcr(read_svcr() | svcr);
+
+	isb();
 }
 
 /*
  * sme_smstop
- *   This function disables streaming mode OR disables ZA array access but not
- *   both.  It might seem strange but this is the functionality of the SMSTOP
- *   assembly instruction.
+ * This function exits streaming mode and disables ZA array storage access
+ * independently or together based on the type of instruction variant.
+ *
  * Parameters
- *   disable_za: If set, ZA access is disabled but streaming mode is not
- *               affected.  If clear, streaming mode is exited and ZA bit is
- *               left alone.
+ * smstop_type: If SMSTOP, exits streaming mode and ZA access is disabled
+ *              If SMSTOP_SM, exits streaming mode.
+ *              If SMSTOP_ZA disables SME ZA storage and, ZT0 storage access.
  */
-void sme_smstop(bool disable_za)
+void sme_smstop(smestop_instruction_type_t smstop_type)
 {
-	u_register_t svcr;
+	u_register_t svcr = 0ULL;
 
-	if (disable_za) {
-		svcr = ~SVCR_ZA_BIT;
-	} else {
+	switch (smstop_type) {
+	case SMSTOP:
+		svcr = (~SVCR_SM_BIT) & (~SVCR_ZA_BIT);
+		break;
+
+	case SMSTOP_SM:
 		svcr = ~SVCR_SM_BIT;
+		break;
+
+	case SMSTOP_ZA:
+		svcr = ~SVCR_ZA_BIT;
+		break;
+
+	default:
+		ERROR("Illegal SMSTOP Instruction Variant\n");
+		break;
 	}
-
 	write_svcr(read_svcr() & svcr);
-}
 
-#endif /* __aarch64__ */
+	isb();
+}
diff --git a/lib/extensions/sme/aarch64/sme_helpers.S b/lib/extensions/sme/aarch64/sme_helpers.S
index 6261c90..c440f09 100644
--- a/lib/extensions/sme/aarch64/sme_helpers.S
+++ b/lib/extensions/sme/aarch64/sme_helpers.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2021-2023, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -8,11 +8,52 @@
 #include <asm_macros.S>
 #include <assert_macros.S>
 
-#ifdef __aarch64__
-
 	.arch	armv8-a+sve
 	.globl	sme_rdvl_1
 	.globl	sme_try_illegal_instruction
+	.globl  sme_vector_to_ZA
+	.globl  sme_ZA_to_vector
+
+
+/*
+ * TODO: Due to the limitation with toolchain, SME intrinsics, still not being
+ * supported, instructions are manually encoded using the opcodes.
+ * Further, when the toolchain supports the requirements, these macros could
+ * be refactored.
+ */
+
+
+/*
+ * LDR (Loads a vector (an array of elements ) to ZA array ):
+ * LDR ZA[\nw, #\offset], [X\nxbase, #\offset, MUL VL]
+ *
+ * Arguments/Opcode bit field:
+ * nw     : the vector select register W12-W15
+ * nxbase : 64-bit name of the general-purpose base register.
+ * offset : vector select  and optional memory offset. Default to 0.
+ */
+.macro _ldr_za nw, nxbase, offset=0
+	.inst	0xe1000000			\
+		| (((\nw) & 3) << 13)		\
+		| ((\nxbase) << 5)		\
+		| ((\offset) & 0xf)
+.endm
+
+/*
+ * STR ( It stores an array of elements from ZA array to a vector ).
+ * STR ZA[\nw, #\offset], [X\nxbase, #\offset, MUL VL]
+ *
+ * Arguments/Opcode bit field:
+ * nw     : the vector select register W12-W15
+ * nxbase : 64-bit name of the general-purpose base register.
+ * offset : vector select  and optional memory offset. Default to 0.
+ */
+.macro _str_za nw, nxbase, offset=0
+	.inst	0xe1200000			\
+		| (((\nw) & 3) << 13)		\
+		| ((\nxbase) << 5)		\
+		| ((\offset) & 0xf)
+.endm
 
 /*
  * uint64_t sme_rdvl_1(void);
@@ -36,4 +77,25 @@
 	ret
 endfunc sme_try_illegal_instruction
 
-#endif /* __aarch64__ */
+
+/**
+ * void sme_vector_to_ZA(uint64_t *input_vec)
+ *
+ * This function loads an vector of elements to an ZA Array storage
+ */
+func sme_vector_to_ZA
+	mov	w12, wzr
+	_ldr_za	12, 0		// ZA.H[W12] loaded from [X0 / input_vector]
+	ret
+endfunc sme_vector_to_ZA
+
+/**
+ * void sme_ZA_to_vector(uint64_t *out_vec)
+ *
+ * This function stores elements from ZA Array storage to an ZA vector
+ */
+func sme_ZA_to_vector
+	mov	w12, wzr
+	_str_za	12, 0		// ZA.H[W12] stored to [X0 / out_vector]
+	ret
+endfunc sme_ZA_to_vector