feat(spm): probe SVL for SME related tests
For world switch SPM tests checking the SME context, probe the possible
SVL values in streaming SVE and run tests with each possible SVL.
Signed-off-by: Olivier Deprez <olivier.deprez@arm.com>
Change-Id: I5157fc896168f7ea2df131a86acdb1d1f1bb795e
diff --git a/include/lib/extensions/sme.h b/include/lib/extensions/sme.h
index 4a7e9b7..7175b71 100644
--- a/include/lib/extensions/sme.h
+++ b/include/lib/extensions/sme.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021-2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2021-2024, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -13,6 +13,9 @@
#define MAX_VL_B (MAX_VL / 8)
#define SME_SVQ_ARCH_MAX (MASK(SMCR_ELX_LEN) >> SMCR_ELX_LEN_SHIFT)
+/* convert SME SVL in bytes to SVQ */
+#define SME_SVL_TO_SVQ(svl_bytes) (((svl_bytes) >> 4U) - 1U)
+
/* get a random Streaming SVE VQ b/w 0 to SME_SVQ_ARCH_MAX */
#define SME_GET_RANDOM_SVQ (rand() % (SME_SVQ_ARCH_MAX + 1))
@@ -31,6 +34,7 @@
/* SME feature related prototypes. */
void sme_smstart(smestart_instruction_type_t smstart_type);
void sme_smstop(smestop_instruction_type_t smstop_type);
+uint32_t sme_probe_svl(uint8_t sme_max_svq);
/* Assembly function prototypes. */
uint64_t sme_rdsvl_1(void);
diff --git a/lib/extensions/sme/aarch64/sme.c b/lib/extensions/sme/aarch64/sme.c
index ee21578..a7337ee 100644
--- a/lib/extensions/sme/aarch64/sme.c
+++ b/lib/extensions/sme/aarch64/sme.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021-2023, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2021-2024, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -91,7 +91,7 @@
{
u_register_t smcr_el2_val;
- /* cap svq to arch supported max value */
+ /* Cap svq to arch supported max value. */
if (svq > SME_SVQ_ARCH_MAX) {
svq = SME_SVQ_ARCH_MAX;
}
@@ -145,3 +145,25 @@
{
return ((read_smcr_el2() & SMCR_ELX_FA64_BIT) != 0U);
}
+
+uint32_t sme_probe_svl(uint8_t sme_max_svq)
+{
+ uint32_t svl_bitmap = 0;
+ uint8_t svq, rdsvl_vq;
+
+ /* Cap svq to arch supported max value. */
+ if (sme_max_svq > SME_SVQ_ARCH_MAX) {
+ sme_max_svq = SME_SVQ_ARCH_MAX;
+ }
+
+ for (svq = 0; svq <= sme_max_svq; svq++) {
+ sme_config_svq(svq);
+ rdsvl_vq = SME_SVL_TO_SVQ(sme_rdsvl_1());
+ if (svl_bitmap & BIT_32(rdsvl_vq)) {
+ continue;
+ }
+ svl_bitmap |= BIT_32(rdsvl_vq);
+ }
+
+ return svl_bitmap;
+}
diff --git a/tftf/tests/runtime_services/secure_service/test_spm_simd.c b/tftf/tests/runtime_services/secure_service/test_spm_simd.c
index c15677c..baec1ac 100644
--- a/tftf/tests/runtime_services/secure_service/test_spm_simd.c
+++ b/tftf/tests/runtime_services/secure_service/test_spm_simd.c
@@ -186,7 +186,6 @@
* false - On success
* true - On failure
*/
-#ifdef __aarch64__
static bool callback_enter_cactus_sp(void)
{
struct ffa_value ret = cactus_req_simd_fill_send_cmd(SENDER, RECEIVER);
@@ -201,7 +200,6 @@
return false;
}
-#endif /* __aarch64__ */
/*
* Tests that SVE vector operations in normal world are not affected by context
@@ -254,14 +252,15 @@
}
/*
- * SME enter SPMC with SSVE enabled.
- *
- * Check Streaming SVE is preserved on a normal/secure world switch.
- *
+ * This base function probes all possible Streaming SVE vector length
+ * values and calls the function passed as parameter with each discovered
+ * value.
*/
-test_result_t test_sme_streaming_sve(void)
+static test_result_t helper_test_sme(test_result_t (*func)(uint8_t svq))
{
- struct ffa_value ret;
+ uint32_t svl_bitmap;
+ uint8_t svq;
+ test_result_t ret;
SKIP_TEST_IF_AARCH32();
@@ -270,7 +269,27 @@
CHECK_SPMC_TESTING_SETUP(1, 2, expected_sp_uuids);
-#ifdef __aarch64__
+ svl_bitmap = sme_probe_svl(SME_SVQ_ARCH_MAX);
+ svq = 0;
+ for (uint32_t bitmap = svl_bitmap; bitmap != 0U; bitmap >>= 1) {
+ if ((bitmap & 1) != 0) {
+ VERBOSE("Test SVL %u bits.\n", SVE_VQ_TO_BITS(svq));
+ ret = func(svq);
+ if (ret != TEST_RESULT_SUCCESS) {
+ return ret;
+ }
+ }
+
+ svq++;
+ }
+
+ return TEST_RESULT_SUCCESS;
+}
+
+static test_result_t do_test_sme_streaming_sve(uint8_t svq)
+{
+ struct ffa_value ret;
+
/* Enable SME FA64 if implemented. */
if (is_feat_sme_fa64_supported()) {
sme_enable_fa64();
@@ -279,8 +298,8 @@
/* Enter Streaming SVE mode. */
sme_smstart(SMSTART_SM);
- /* Configure SVQ to max. implemented SVL. */
- sme_config_svq(SME_SVQ_ARCH_MAX);
+ /* Configure SVQ. */
+ sme_config_svq((uint32_t)svq);
sve_z_regs_write_rand(&sve_vectors_input);
sve_p_regs_write_rand(&sve_predicates_input);
@@ -337,28 +356,25 @@
/* Exit Streaming SVE mode. */
sme_smstop(SMSTOP_SM);
-#endif
return TEST_RESULT_SUCCESS;
}
/*
- * SME enter SPMC with ZA enabled.
+ * SME enter SPMC with SSVE enabled.
*
- * Check ZA array enabled is preserved on a normal/secure world switch.
+ * Check Streaming SVE is preserved on a normal/secure world switch.
+ *
*/
-test_result_t test_sme_za(void)
+test_result_t test_sme_streaming_sve(void)
+{
+ return helper_test_sme(do_test_sme_streaming_sve);
+}
+
+static test_result_t do_test_sme_za(uint8_t vq)
{
struct ffa_value ret;
- SKIP_TEST_IF_AARCH32();
-
- /* Skip the test if SME is not supported. */
- SKIP_TEST_IF_SME_NOT_SUPPORTED();
-
- CHECK_SPMC_TESTING_SETUP(1, 2, expected_sp_uuids);
-
-#ifdef __aarch64__
/* Enable SME FA64 if implemented. */
if (is_feat_sme_fa64_supported()) {
sme_enable_fa64();
@@ -368,7 +384,7 @@
sme_smstart(SMSTART_ZA);
/* Configure VQ. */
- sve_config_vq(SVE_VQ_ARCH_MAX);
+ sve_config_vq(vq);
sve_z_regs_write_rand(&sve_vectors_input);
sve_p_regs_write_rand(&sve_predicates_input);
@@ -424,29 +440,29 @@
/* Disable SME ZA array storage. */
sme_smstop(SMSTOP_ZA);
-#endif
return TEST_RESULT_SUCCESS;
}
/*
- * SME enter SPMC with SSVE+ZA enabled.
+ * SME enter SPMC with ZA enabled.
*
- * Check Streaming SVE and ZA array enabled are preserved on a
- * normal/secure world switch.
+ * Check ZA array enabled is preserved on a normal/secure world switch.
*/
-test_result_t test_sme_streaming_sve_za(void)
+test_result_t test_sme_za(void)
{
- struct ffa_value ret;
-
SKIP_TEST_IF_AARCH32();
/* Skip the test if SME is not supported. */
SKIP_TEST_IF_SME_NOT_SUPPORTED();
- CHECK_SPMC_TESTING_SETUP(1, 2, expected_sp_uuids);
+ return helper_test_sve(do_test_sme_za);
+}
-#ifdef __aarch64__
+static test_result_t do_test_sme_streaming_sve_za(uint8_t svq)
+{
+ struct ffa_value ret;
+
/* Enable SME FA64 if implemented. */
if (is_feat_sme_fa64_supported()) {
sme_enable_fa64();
@@ -455,8 +471,8 @@
/* Enable SME SSVE + ZA. */
sme_smstart(SMSTART);
- /* Configure SVQ to max. implemented SVL. */
- sme_config_svq(SME_SVQ_ARCH_MAX);
+ /* Configure SVQ. */
+ sme_config_svq((uint32_t)svq);
sve_z_regs_write_rand(&sve_vectors_input);
sve_p_regs_write_rand(&sve_predicates_input);
@@ -515,7 +531,17 @@
/* Disable SSVE + ZA. */
sme_smstop(SMSTOP);
-#endif
return TEST_RESULT_SUCCESS;
}
+
+/*
+ * SME enter SPMC with SSVE+ZA enabled.
+ *
+ * Check Streaming SVE and ZA array enabled are preserved on a
+ * normal/secure world switch.
+ */
+test_result_t test_sme_streaming_sve_za(void)
+{
+ return helper_test_sme(do_test_sme_streaming_sve_za);
+}