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/tftf/tests/extensions/sme/test_sme.c b/tftf/tests/extensions/sme/test_sme.c
index 9652b45..58690ea 100644
--- a/tftf/tests/extensions/sme/test_sme.c
+++ b/tftf/tests/extensions/sme/test_sme.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2021-2023, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -14,6 +14,53 @@
#include <test_helpers.h>
#include <tftf_lib.h>
+#ifdef __aarch64__
+
+/* Global buffers*/
+static uint64_t ZA_In_vector[8] = {0xaaff, 0xbbff, 0xccff, 0xddff, 0xeeff,
+ 0xffff, 0xff00, 0xff00};
+static uint64_t ZA_Out_vector[8] = {0};
+
+
+/**
+ * sme_zero_ZA
+ * ZER0 : Zero a list of upto eight 64bit element ZA tiles.
+ * ZERO {<mask>} , where mask=ff, to clear all the 8, 64 bit elements.
+ */
+static void sme_zero_ZA(void)
+{
+ /**
+ * Due to the lack of support from the toolchain, instruction
+ * opcodes are used here.
+ * Manual Encoding Instruction, to Zero all the tiles of ZA array.
+ *
+ * TODO: Further, once the toolchain adds support for SME features
+ * this could be replaced with the actual instruction ZERO { <mask>}.
+ */
+ asm volatile(".inst 0xc008000f" : : : );
+}
+
+/**
+ * This function compares two buffers/vector elements
+ * Inputs: uint64_t *ZA_In_vector, ZA_Out_vector
+ * @return true : If both are equal
+ * @return false : If both are not equal
+ */
+static bool sme_cmp_vector(const uint64_t *ZA_In_vector, const uint64_t *ZA_Out_vector)
+{
+ bool ret = true;
+
+ for (int i = 0; i < (MAX_VL_B/8); i++) {
+ if (ZA_In_vector[i] != ZA_Out_vector[i]) {
+ ret = false;
+ }
+ }
+
+ return ret;
+}
+
+#endif /* __aarch64__ */
+
test_result_t test_sme_support(void)
{
/* SME is an AArch64-only feature.*/
@@ -24,19 +71,13 @@
unsigned int current_vector_len;
unsigned int requested_vector_len;
unsigned int len_max;
+ unsigned int __unused svl_max = 0U;
/* Skip the test if SME is not supported. */
- if (!feat_sme_supported()) {
- INFO("SME not supported, skipping.\n");
- return TEST_RESULT_SKIPPED;
- }
+ SKIP_TEST_IF_SME_NOT_SUPPORTED();
/* Enable SME for use at NS EL2. */
- if (sme_enable() != 0) {
- ERROR("Could not enable SME.\n");
- return TEST_RESULT_FAIL;
- }
- isb();
+ sme_enable();
/* Make sure TPIDR2_EL0 is accessible. */
write_tpidr2_el0(0);
@@ -50,21 +91,12 @@
return TEST_RESULT_FAIL;
}
- /* Make sure we can start and stop streaming mode. */
- VERBOSE("Entering Streaming SVE mode.\n");
- sme_smstart(false);
- read_smcr_el2();
- sme_smstop(false);
- sme_smstart(true);
- read_smcr_el2();
- sme_smstop(true);
-
/*
* Iterate through values for LEN to detect supported vector lengths.
- * SME instructions aren't supported by GCC yet so for now this is all
- * we'll do.
*/
- sme_smstart(false);
+
+ /* Entering Streaming SVE mode */
+ sme_smstart(SMSTART_SM);
/* Write SMCR_EL2 with the LEN max to find implemented width. */
write_smcr_el2(SME_SMCR_LEN_MAX);
@@ -87,15 +119,48 @@
* match, we've found the largest supported value for SMLEN.
*/
if (current_vector_len == requested_vector_len) {
+ svl_max = current_vector_len;
VERBOSE("SUPPORTED: %u bits (LEN=%u)\n", requested_vector_len, i);
} else {
- VERBOSE("NOT SUPPORTED: %u bits (LEN=%u)\n", requested_vector_len, i);
+ VERBOSE("NOT SUPPORTED: %u bits (LEN=%u)\n", requested_vector_len, i);
}
}
- sme_smstop(false);
+
+ INFO("Largest Supported Streaming Vector Length(SVL): %u bits \n", svl_max);
+
+ /* Exiting Streaming SVE mode */
+ sme_smstop(SMSTOP_SM);
+
+ /**
+ * Perform/Execute SME Instructions.
+ * SME Data processing instructions LDR, STR, and ZERO instructions that
+ * access the SME ZA storage are legal only if ZA is enabled.
+ */
+
+ /* Enable SME ZA Array Storage */
+ sme_smstart(SMSTART_ZA);
+
+ /* LDR : Load vector to ZA Array */
+ sme_vector_to_ZA(ZA_In_vector);
+
+ /* STR : Store Vector from ZA Array. */
+ sme_ZA_to_vector(ZA_Out_vector);
+
+ /* Compare both vectors to ensure load and store instructions have
+ * executed precisely.
+ */
+ if (!sme_cmp_vector(ZA_In_vector, ZA_Out_vector)) {
+ return TEST_RESULT_FAIL;
+ }
+
+ /* Zero or clear the entire ZA Array Storage/Tile */
+ sme_zero_ZA();
+
+ /* Disable the SME ZA array storage. */
+ sme_smstop(SMSTOP_ZA);
/* If FEAT_SME_FA64 then attempt to execute an illegal instruction. */
- if (feat_sme_fa64_supported()) {
+ if (is_feat_sme_fa64_supported()) {
VERBOSE("FA64 supported, trying illegal instruction.\n");
sme_try_illegal_instruction();
}