aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorManish Pandey <manish.pandey2@arm.com>2020-07-27 13:57:21 +0000
committerTrustedFirmware Code Review <review@review.trustedfirmware.org>2020-07-27 13:57:21 +0000
commit8a669d956699e967ca7f298d4bf74111c10dd164 (patch)
tree3ca54a71167a91304db18c5ee891ce2f831f03b6
parentd07b682769c1861bf12ef3a9177c62796c5c9d2b (diff)
parent57c6ddbfddeb0d5ebe27d62b426bb1029fe8d622 (diff)
downloadtf-a-tests-8a669d956699e967ca7f298d4bf74111c10dd164.tar.gz
Merge changes from topic "ffa_tests"
* changes: Cactus: tidying FFA_VERSION test. Cactus: FFA_PARTITION_INFO_GET test. Cactus: FFA_FEATURES test. SPM: TFTF test of FFA_FEATURES interface.
-rw-r--r--include/runtime_services/ffa_helpers.h19
-rw-r--r--spm/cactus/cactus_def.h14
-rw-r--r--spm/cactus/cactus_ffa_tests.c154
-rw-r--r--spm/cactus/cactus_main.c21
-rw-r--r--spm/cactus/cactus_tests.h4
-rw-r--r--spm/cactus/cactus_tests_misc.c41
-rw-r--r--tftf/tests/runtime_services/secure_service/ffa_helpers.c83
-rw-r--r--tftf/tests/runtime_services/secure_service/test_ffa_direct_messaging.c48
-rw-r--r--tftf/tests/runtime_services/secure_service/test_ffa_features.c79
-rw-r--r--tftf/tests/tests-spm.mk1
-rw-r--r--tftf/tests/tests-spm.xml6
11 files changed, 362 insertions, 108 deletions
diff --git a/include/runtime_services/ffa_helpers.h b/include/runtime_services/ffa_helpers.h
index d4ef803..0692aa9 100644
--- a/include/runtime_services/ffa_helpers.h
+++ b/include/runtime_services/ffa_helpers.h
@@ -28,11 +28,25 @@ typedef unsigned short ffa_vcpu_count_t;
#include <stdint.h>
+struct mailbox_buffers {
+ const void *recv;
+ void *send;
+};
+
+struct ffa_partition_info {
+ /** The ID of the VM the information is about */
+ ffa_vm_id_t id;
+ /** The number of execution contexts implemented by the partition */
+ uint16_t exec_context;
+ /** The Partition's properties, e.g. supported messaging methods */
+ uint32_t properties;
+};
+
/*
* TODO: In the future this file should be placed in a common folder, and not
* under tftf. The functions in this file are also used by SPs for SPM tests.
*/
-
+bool check_spmc_execution_level(void);
smc_ret_values ffa_msg_send_direct_req(uint32_t source_id, uint32_t dest_id, uint32_t message);
smc_ret_values ffa_msg_send_direct_req64(uint32_t source_id, uint32_t dest_id, uint64_t message);
smc_ret_values ffa_run(uint32_t dest_id, uint32_t vcpu_id);
@@ -42,6 +56,9 @@ smc_ret_values ffa_msg_wait(void);
smc_ret_values ffa_msg_send_direct_resp(ffa_vm_id_t source_id,
ffa_vm_id_t dest_id, uint32_t message);
smc_ret_values ffa_error(int32_t error_code);
+smc_ret_values ffa_features(uint32_t feature);
+smc_ret_values ffa_partition_info_get(const uint32_t uuid[4]);
+smc_ret_values ffa_rx_release(void);
#endif /* __ASSEMBLY__ */
diff --git a/spm/cactus/cactus_def.h b/spm/cactus/cactus_def.h
index a0adb23..0d3df2e 100644
--- a/spm/cactus/cactus_def.h
+++ b/spm/cactus/cactus_def.h
@@ -28,4 +28,18 @@
#define CACTUS_TX_BASE CACTUS_RX_BASE + PAGE_SIZE
#define CACTUS_RX_TX_SIZE PAGE_SIZE * 2
+/*
+ * RX/TX buffer helpers.
+ */
+#define get_sp_rx_start(sp_id) (CACTUS_RX_BASE + ((sp_id - 1) * CACTUS_RX_TX_SIZE))
+#define get_sp_rx_end(sp_id) (CACTUS_RX_BASE + ((sp_id - 1) * CACTUS_RX_TX_SIZE) + PAGE_SIZE)
+#define get_sp_tx_start(sp_id) (CACTUS_TX_BASE + ((sp_id - 1) * CACTUS_RX_TX_SIZE))
+#define get_sp_tx_end(sp_id) (CACTUS_TX_BASE + ((sp_id - 1) * CACTUS_RX_TX_SIZE) + PAGE_SIZE)
+
+/*
+ * UUID of secure partition as defined in the respective manifests.
+ */
+#define PRIMARY_UUID {0xb4b5671e, 0x4a904fe1, 0xb81ffb13, 0xdae1dacb}
+#define SECONDARY_UUID {0xd1582309, 0xf02347b9, 0x827c4464, 0xf5578fc8}
+
#endif /* CACTUS_DEF_H */
diff --git a/spm/cactus/cactus_ffa_tests.c b/spm/cactus/cactus_ffa_tests.c
index 411cc9f..25c20b0 100644
--- a/spm/cactus/cactus_ffa_tests.c
+++ b/spm/cactus/cactus_ffa_tests.c
@@ -4,8 +4,9 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
-#include <errno.h>
#include <debug.h>
+#include <errno.h>
+#include <cactus_def.h>
#include <ffa_helpers.h>
#include <sp_helpers.h>
@@ -13,20 +14,146 @@
#define FFA_MAJOR 1U
#define FFA_MINOR 0U
-void ffa_tests(void)
+static const uint32_t primary_uuid[4] = PRIMARY_UUID;
+static const uint32_t secondary_uuid[4] = SECONDARY_UUID;
+static const uint32_t null_uuid[4] = {0};
+
+struct feature_test {
+ const char *test_name;
+ unsigned int feature;
+ unsigned int expected_ret;
+};
+
+static const struct feature_test test_target[] = {
+ {"FFA_ERROR_32 check", FFA_ERROR, FFA_SUCCESS_SMC32},
+ {"FFA_SUCCESS_32 check", FFA_SUCCESS_SMC32, FFA_SUCCESS_SMC32},
+ {"FFA_INTERRUPT_32 check", FFA_INTERRUPT, FFA_SUCCESS_SMC32},
+ {"FFA_VERSION_32 check", FFA_VERSION, FFA_SUCCESS_SMC32},
+ {"FFA_FEATURES_32 check", FFA_FEATURES, FFA_SUCCESS_SMC32},
+ {"FFA_RX_RELEASE_32 check", FFA_RX_RELEASE, FFA_SUCCESS_SMC32},
+ {"FFA_RXTX_MAP_32 check", FFA_RXTX_MAP_SMC32, FFA_ERROR},
+ {"FFA_RXTX_MAP_64 check", FFA_RXTX_MAP_SMC64, FFA_SUCCESS_SMC32},
+ {"FFA_RXTX_UNMAP_32 check", FFA_RXTX_UNMAP, FFA_ERROR},
+ {"FFA_PARTITION_INFO_GET_32 check", FFA_PARTITION_INFO_GET, FFA_SUCCESS_SMC32},
+ {"FFA_ID_GET_32 check", FFA_ID_GET, FFA_SUCCESS_SMC32},
+ {"FFA_MSG_POLL_32 check", FFA_MSG_POLL, FFA_SUCCESS_SMC32},
+ {"FFA_MSG_WAIT_32 check", FFA_MSG_WAIT, FFA_SUCCESS_SMC32},
+ {"FFA_YIELD_32 check", FFA_MSG_YIELD, FFA_SUCCESS_SMC32},
+ {"FFA_RUN_32 check", FFA_MSG_RUN, FFA_SUCCESS_SMC32},
+ {"FFA_MSG_SEND_32 check", FFA_MSG_SEND, FFA_SUCCESS_SMC32},
+ {"FFA_MEM_DONATE_32 check", FFA_MEM_DONATE_SMC32, FFA_SUCCESS_SMC32},
+ {"FFA_MEM_LEND_32 check", FFA_MEM_LEND_SMC32, FFA_SUCCESS_SMC32},
+ {"FFA_MEM_SHARE_32 check", FFA_MEM_SHARE_SMC32, FFA_SUCCESS_SMC32},
+ {"FFA_MEM_RETRIEVE_REQ_32 check", FFA_MEM_RETRIEVE_REQ_SMC32, FFA_SUCCESS_SMC32},
+ {"FFA_MEM_RETRIEVE_RESP_32 check", FFA_MEM_RETRIEVE_RESP, FFA_SUCCESS_SMC32},
+ {"FFA_MEM_RELINQUISH_32 check", FFA_MEM_RELINQUISH, FFA_SUCCESS_SMC32},
+ {"FFA_MEM_RECLAIM_32 check", FFA_MEM_RECLAIM, FFA_SUCCESS_SMC32},
+ {"Check non-existent command", 0xFFFF, FFA_ERROR}
+};
+
+/*
+ * Test FFA_FEATURES interface.
+ */
+static void ffa_features_test(void)
{
- const char *test_ffa = "FFA Interfaces";
- const char *test_ffa_version = "FFA Version interface";
+ const char *test_features = "FFA Features interface";
+ smc_ret_values ffa_ret;
+ unsigned int i, test_target_size =
+ sizeof(test_target) / sizeof(struct feature_test);
- announce_test_section_start(test_ffa);
+ announce_test_section_start(test_features);
+
+ for (i = 0U; i < test_target_size; i++) {
+ announce_test_start(test_target[i].test_name);
+
+ ffa_ret = ffa_features(test_target[i].feature);
+ expect(ffa_ret.ret0, test_target[i].expected_ret);
+ if (test_target[i].expected_ret == FFA_ERROR) {
+ expect(ffa_ret.ret2, FFA_ERROR_NOT_SUPPORTED);
+ }
+
+ announce_test_end(test_target[i].test_name);
+ }
+
+ announce_test_section_end(test_features);
+}
+
+static void ffa_partition_info_helper(struct mailbox_buffers *mb, const uint32_t uuid[4],
+ const struct ffa_partition_info *expected,
+ const uint16_t expected_size)
+{
+ smc_ret_values ret = ffa_partition_info_get(uuid);
+ unsigned int i;
+ expect(ret.ret0, FFA_SUCCESS_SMC32);
+
+ struct ffa_partition_info *info = (struct ffa_partition_info *)(mb->recv);
+ for (i = 0U; i < expected_size; i++) {
+ expect(info[i].id, expected[i].id);
+ expect(info[i].exec_context, expected[i].exec_context);
+ expect(info[i].properties, expected[i].properties);
+ }
+
+ ret = ffa_rx_release();
+ expect(ret.ret0, FFA_SUCCESS_SMC32);
+}
+
+static void ffa_partition_info_wrong_test(void)
+{
+ const char *test_wrong_uuid = "Request wrong UUID";
+ uint32_t uuid[4] = {1};
+
+ announce_test_start(test_wrong_uuid);
+
+ smc_ret_values ret = ffa_partition_info_get(uuid);
+ expect(ret.ret0, FFA_ERROR);
+ expect(ret.ret2, FFA_ERROR_INVALID_PARAMETER);
+
+ announce_test_end(test_wrong_uuid);
+}
+
+static void ffa_partition_info_get_test(struct mailbox_buffers *mb)
+{
+ const char *test_partition_info = "FFA Partition info interface";
+ const char *test_primary = "Get primary partition info";
+ const char *test_secondary = "Get secondary partition info";
+ const char *test_all = "Get all partitions info";
+
+ const struct ffa_partition_info expected_info[] = {
+ {.id = SPM_VM_ID_FIRST, .exec_context = 8, .properties = 0}, /* Primary partition info */
+ {.id = 2, .exec_context = 2, .properties = 0} /* Secondary partition info */
+ };
+
+ announce_test_section_start(test_partition_info);
+
+ announce_test_start(test_secondary);
+ ffa_partition_info_helper(mb, secondary_uuid, &expected_info[1], 1);
+ announce_test_end(test_secondary);
+
+ announce_test_start(test_primary);
+ ffa_partition_info_helper(mb, primary_uuid, &expected_info[0], 1);
+ announce_test_end(test_primary);
+
+ announce_test_start(test_all);
+ ffa_partition_info_helper(mb, null_uuid, expected_info, 2);
+ announce_test_end(test_all);
+
+ ffa_partition_info_wrong_test();
+
+ announce_test_section_end(test_partition_info);
+}
+
+void ffa_version_test(void)
+{
+ const char *test_ffa_version = "FFA Version interface";
announce_test_start(test_ffa_version);
smc_ret_values ret = ffa_version(MAKE_FFA_VERSION(FFA_MAJOR, FFA_MINOR));
- uint32_t spm_version = (uint32_t)(0xFFFFFFFF & ret.ret0);
+ uint32_t spm_version = (uint32_t)ret.ret0;
- bool ffa_version_compatible = ((spm_version >> FFA_VERSION_MAJOR_SHIFT) == FFA_MAJOR &&
- (spm_version & FFA_VERSION_MINOR_MASK) >= FFA_MINOR);
+ bool ffa_version_compatible =
+ ((spm_version >> FFA_VERSION_MAJOR_SHIFT) == FFA_MAJOR &&
+ (spm_version & FFA_VERSION_MINOR_MASK) >= FFA_MINOR);
NOTICE("FFA_VERSION returned %u.%u; Compatible: %i\n",
spm_version >> FFA_VERSION_MAJOR_SHIFT,
@@ -36,6 +163,17 @@ void ffa_tests(void)
expect((int)ffa_version_compatible, (int)true);
announce_test_end(test_ffa_version);
+}
+
+void ffa_tests(struct mailbox_buffers *mb)
+{
+ const char *test_ffa = "FFA Interfaces";
+
+ announce_test_section_start(test_ffa);
+
+ ffa_features_test();
+ ffa_version_test();
+ ffa_partition_info_get_test(mb);
announce_test_section_end(test_ffa);
}
diff --git a/spm/cactus/cactus_main.c b/spm/cactus/cactus_main.c
index 49764ec..31906d5 100644
--- a/spm/cactus/cactus_main.c
+++ b/spm/cactus/cactus_main.c
@@ -102,12 +102,12 @@ static void cactus_print_memory_layout(unsigned int vm_id)
(void *)CACTUS_BSS_START, (void *)CACTUS_BSS_END);
NOTICE(" RX : %p - %p\n",
- (void *)(CACTUS_RX_BASE + ((vm_id - 1) * CACTUS_RX_TX_SIZE)),
- (void *)(CACTUS_TX_BASE + ((vm_id - 1) * CACTUS_RX_TX_SIZE)));
+ (void *)get_sp_rx_start(vm_id),
+ (void *)get_sp_rx_end(vm_id));
NOTICE(" TX : %p - %p\n",
- (void *)(CACTUS_TX_BASE + ((vm_id - 1) * CACTUS_RX_TX_SIZE)),
- (void *)(CACTUS_RX_BASE + (vm_id * CACTUS_RX_TX_SIZE)));
+ (void *)get_sp_tx_start(vm_id),
+ (void *)get_sp_tx_end(vm_id));
}
static void cactus_plat_configure_mmu(unsigned int vm_id)
@@ -129,13 +129,13 @@ static void cactus_plat_configure_mmu(unsigned int vm_id)
CACTUS_BSS_END - CACTUS_BSS_START,
MT_RW_DATA);
- mmap_add_region((CACTUS_RX_BASE + ((vm_id - 1) * CACTUS_RX_TX_SIZE)),
- (CACTUS_RX_BASE + ((vm_id - 1) * CACTUS_RX_TX_SIZE)),
+ mmap_add_region(get_sp_rx_start(vm_id),
+ get_sp_rx_start(vm_id),
(CACTUS_RX_TX_SIZE / 2),
MT_RO_DATA);
- mmap_add_region((CACTUS_TX_BASE + ((vm_id - 1) * CACTUS_RX_TX_SIZE)),
- (CACTUS_TX_BASE + ((vm_id - 1) * CACTUS_RX_TX_SIZE)),
+ mmap_add_region(get_sp_tx_start(vm_id),
+ get_sp_tx_start(vm_id),
(CACTUS_RX_TX_SIZE / 2),
MT_RW_DATA);
@@ -147,6 +147,7 @@ void __dead2 cactus_main(void)
{
assert(IS_IN_EL1() != 0);
+ struct mailbox_buffers mb;
/* Clear BSS */
memset((void *)CACTUS_BSS_START,
0, CACTUS_BSS_END - CACTUS_BSS_START);
@@ -159,6 +160,8 @@ void __dead2 cactus_main(void)
}
ffa_vm_id_t ffa_id = ffa_id_ret.ret2 & 0xffff;
+ mb.send = (void *) get_sp_tx_start(ffa_id);
+ mb.recv = (void *) get_sp_rx_start(ffa_id);
/* Configure and enable Stage-1 MMU, enable D-Cache */
cactus_plat_configure_mmu(ffa_id);
@@ -190,7 +193,7 @@ void __dead2 cactus_main(void)
cactus_print_memory_layout(ffa_id);
/* Invoking Tests */
- ffa_tests();
+ ffa_tests(&mb);
/* End up to message loop */
message_loop(ffa_id);
diff --git a/spm/cactus/cactus_tests.h b/spm/cactus/cactus_tests.h
index 23586f5..2e13a6f 100644
--- a/spm/cactus/cactus_tests.h
+++ b/spm/cactus/cactus_tests.h
@@ -7,6 +7,8 @@
#ifndef CACTUS_TESTS_H
#define CACTUS_TESTS_H
+#include <ffa_helpers.h>
+
/*
* Test functions
*/
@@ -14,7 +16,7 @@
/*
* Test to FFA interfaces.
*/
-void ffa_tests(void);
+void ffa_tests(struct mailbox_buffers *mb);
/*
* Test other things like the version number returned by SPM.
diff --git a/spm/cactus/cactus_tests_misc.c b/spm/cactus/cactus_tests_misc.c
deleted file mode 100644
index 39eb752..0000000
--- a/spm/cactus/cactus_tests_misc.c
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2018, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <assert.h>
-#include <debug.h>
-#include <errno.h>
-#include <sp_helpers.h>
-#include <spm_svc.h>
-#include <sprt_client.h>
-#include <sprt_svc.h>
-#include <stdint.h>
-
-#include "cactus.h"
-#include "cactus_tests.h"
-
-/*
- * Miscellaneous SPM tests.
- */
-void misc_tests(void)
-{
- int32_t ret;
-
- const char *test_sect_desc = "miscellaneous";
-
- announce_test_section_start(test_sect_desc);
-
- const char *test_version_sprt = "SPRT version check";
-
- announce_test_start(test_version_sprt);
- ret = sprt_version();
- INFO("Version = 0x%x (%u.%u)\n", ret,
- (ret >> SPRT_VERSION_MAJOR_SHIFT) & SPRT_VERSION_MAJOR_MASK,
- ret & SPRT_VERSION_MINOR_MASK);
- expect(ret, SPRT_VERSION_COMPILED);
- announce_test_end(test_version_sprt);
-
- announce_test_section_end(test_sect_desc);
-}
diff --git a/tftf/tests/runtime_services/secure_service/ffa_helpers.c b/tftf/tests/runtime_services/secure_service/ffa_helpers.c
index 9955c7c..c90cac8 100644
--- a/tftf/tests/runtime_services/secure_service/ffa_helpers.c
+++ b/tftf/tests/runtime_services/secure_service/ffa_helpers.c
@@ -9,6 +9,11 @@
#include <ffa_helpers.h>
#include <ffa_svc.h>
+#define OPTEE_FFA_GET_API_VERSION (0)
+#define OPTEE_FFA_GET_OS_VERSION (1)
+#define OPTEE_FFA_GET_OS_VERSION_MAJOR (3)
+#define OPTEE_FFA_GET_OS_VERSION_MINOR (8)
+
/*-----------------------------------------------------------------------------
* FFA_RUN
*
@@ -108,6 +113,49 @@ smc_ret_values ffa_msg_send_direct_req64(uint32_t source_id, uint32_t dest_id,
}
/*
+ * check_spmc_execution_level
+ *
+ * Attempt sending impdef protocol messages to OP-TEE through direct messaging.
+ * Criteria for detecting OP-TEE presence is that responses match defined
+ * version values. In the case of SPMC running at S-EL2 (and Cactus instances
+ * running at S-EL1) the response will not match the pre-defined version IDs.
+ *
+ * Returns true if SPMC is probed as being OP-TEE at S-EL1.
+ *
+ */
+bool check_spmc_execution_level(void)
+{
+ unsigned int is_optee_spmc_criteria = 0U;
+ smc_ret_values ret_values;
+
+ /*
+ * Send a first OP-TEE-defined protocol message through
+ * FFA direct message.
+ *
+ */
+ ret_values = ffa_msg_send_direct_req(HYP_ID, SP_ID(1),
+ OPTEE_FFA_GET_API_VERSION);
+ if ((ret_values.ret3 == FFA_VERSION_MAJOR) &&
+ (ret_values.ret4 == FFA_VERSION_MINOR)) {
+ is_optee_spmc_criteria++;
+ }
+
+ /*
+ * Send a second OP-TEE-defined protocol message through
+ * FFA direct message.
+ *
+ */
+ ret_values = ffa_msg_send_direct_req(HYP_ID, SP_ID(1),
+ OPTEE_FFA_GET_OS_VERSION);
+ if ((ret_values.ret3 == OPTEE_FFA_GET_OS_VERSION_MAJOR) &&
+ (ret_values.ret4 == OPTEE_FFA_GET_OS_VERSION_MINOR)) {
+ is_optee_spmc_criteria++;
+ }
+
+ return (is_optee_spmc_criteria == 2U);
+}
+
+/*
* FFA Version ABI helper.
* Version fields:
* -Bits[30:16]: Major version.
@@ -164,3 +212,38 @@ smc_ret_values ffa_error(int32_t error_code)
return tftf_smc(&args);
}
+
+/* Query the higher EL if the requested FF-A feature is implemented. */
+smc_ret_values ffa_features(uint32_t feature)
+{
+ smc_args args = {
+ .fid = FFA_FEATURES,
+ .arg1 = feature
+ };
+
+ return tftf_smc(&args);
+}
+
+/* Get information about VMs or SPs based on UUID */
+smc_ret_values ffa_partition_info_get(const uint32_t uuid[4])
+{
+ smc_args args = {
+ .fid = FFA_PARTITION_INFO_GET,
+ .arg1 = uuid[0],
+ .arg2 = uuid[1],
+ .arg3 = uuid[2],
+ .arg4 = uuid[3]
+ };
+
+ return tftf_smc(&args);
+}
+
+/* Query SPMD that the rx buffer of the partition can be released */
+smc_ret_values ffa_rx_release(void)
+{
+ smc_args args = {
+ .fid = FFA_RX_RELEASE
+ };
+
+ return tftf_smc(&args);
+}
diff --git a/tftf/tests/runtime_services/secure_service/test_ffa_direct_messaging.c b/tftf/tests/runtime_services/secure_service/test_ffa_direct_messaging.c
index c83a403..6008b78 100644
--- a/tftf/tests/runtime_services/secure_service/test_ffa_direct_messaging.c
+++ b/tftf/tests/runtime_services/secure_service/test_ffa_direct_messaging.c
@@ -16,11 +16,6 @@
#define DIRECT_MSG_TEST_PATTERN2 (0xbbbb0000)
#define DIRECT_MSG_TEST_PATTERN3 (0xcccc0000)
-#define OPTEE_FFA_GET_API_VERSION (0)
-#define OPTEE_FFA_GET_OS_VERSION (1)
-#define OPTEE_FFA_GET_OS_VERSION_MAJOR (3)
-#define OPTEE_FFA_GET_OS_VERSION_MINOR (8)
-
static test_result_t send_receive_direct_msg(unsigned int sp_id,
unsigned int test_pattern)
{
@@ -51,49 +46,6 @@ static test_result_t send_receive_direct_msg(unsigned int sp_id,
return TEST_RESULT_SUCCESS;
}
-/*
- * check_spmc_execution_level
- *
- * Attempt sending impdef protocol messages to OP-TEE through direct messaging.
- * Criteria for detecting OP-TEE presence is that responses match defined
- * version values. In the case of SPMC running at S-EL2 (and Cactus instances
- * running at S-EL1) the response will not match the pre-defined version IDs.
- *
- * Returns true if SPMC is probed as being OP-TEE at S-EL1.
- *
- */
-static bool check_spmc_execution_level(void)
-{
- unsigned int is_optee_spmc_criteria = 0;
- smc_ret_values ret_values;
-
- /*
- * Send a first OP-TEE-defined protocol message through
- * FFA direct message.
- *
- */
- ret_values = ffa_msg_send_direct_req(HYP_ID, SP_ID(1),
- OPTEE_FFA_GET_API_VERSION);
- if ((ret_values.ret3 == FFA_VERSION_MAJOR) &&
- (ret_values.ret4 == FFA_VERSION_MINOR)) {
- is_optee_spmc_criteria++;
- }
-
- /*
- * Send a second OP-TEE-defined protocol message through
- * FFA direct message.
- *
- */
- ret_values = ffa_msg_send_direct_req(HYP_ID, SP_ID(1),
- OPTEE_FFA_GET_OS_VERSION);
- if ((ret_values.ret3 == OPTEE_FFA_GET_OS_VERSION_MAJOR) &&
- (ret_values.ret4 == OPTEE_FFA_GET_OS_VERSION_MINOR)) {
- is_optee_spmc_criteria++;
- }
-
- return (is_optee_spmc_criteria == 2);
-}
-
test_result_t test_ffa_direct_messaging(void)
{
test_result_t result;
diff --git a/tftf/tests/runtime_services/secure_service/test_ffa_features.c b/tftf/tests/runtime_services/secure_service/test_ffa_features.c
new file mode 100644
index 0000000..7d67bf8
--- /dev/null
+++ b/tftf/tests/runtime_services/secure_service/test_ffa_features.c
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <ffa_helpers.h>
+#include <test_helpers.h>
+#include <tftf_lib.h>
+
+struct feature_test {
+ const char *test_name;
+ unsigned int feature;
+ u_register_t expected_ret;
+};
+
+static const struct feature_test test_target[] = {
+ {"FFA_ERROR_32 check", FFA_ERROR, FFA_SUCCESS_SMC32},
+ {"FFA_SUCCESS_32 check", FFA_SUCCESS_SMC32, FFA_SUCCESS_SMC32},
+ {"FFA_INTERRUPT_32 check", FFA_INTERRUPT, FFA_SUCCESS_SMC32},
+ {"FFA_VERSION_32 check", FFA_VERSION, FFA_SUCCESS_SMC32},
+ {"FFA_FEATURES_32 check", FFA_FEATURES, FFA_SUCCESS_SMC32},
+ {"FFA_RX_RELEASE_32 check", FFA_RX_RELEASE, FFA_SUCCESS_SMC32},
+ {"FFA_RXTX_MAP_32 check", FFA_RXTX_MAP_SMC32, FFA_ERROR},
+ {"FFA_RXTX_MAP_64 check", FFA_RXTX_MAP_SMC64, FFA_SUCCESS_SMC32},
+ {"FFA_RXTX_UNMAP_32 check", FFA_RXTX_UNMAP, FFA_ERROR},
+ {"FFA_PARTITION_INFO_GET_32 check", FFA_PARTITION_INFO_GET, FFA_SUCCESS_SMC32},
+ {"FFA_ID_GET_32 check", FFA_ID_GET, FFA_SUCCESS_SMC32},
+ {"FFA_MSG_POLL_32 check", FFA_MSG_POLL, FFA_SUCCESS_SMC32},
+ {"FFA_MSG_WAIT_32 check", FFA_MSG_WAIT, FFA_SUCCESS_SMC32},
+ {"FFA_YIELD_32 check", FFA_MSG_YIELD, FFA_SUCCESS_SMC32},
+ {"FFA_RUN_32 check", FFA_MSG_RUN, FFA_SUCCESS_SMC32},
+ {"FFA_MSG_SEND_32 check", FFA_MSG_SEND, FFA_SUCCESS_SMC32},
+ {"FFA_MEM_DONATE_32 check", FFA_MEM_DONATE_SMC32, FFA_SUCCESS_SMC32},
+ {"FFA_MEM_LEND_32 check", FFA_MEM_LEND_SMC32, FFA_SUCCESS_SMC32},
+ {"FFA_MEM_SHARE_32 check", FFA_MEM_SHARE_SMC32, FFA_SUCCESS_SMC32},
+ {"FFA_MEM_RETRIEVE_REQ_32 check", FFA_MEM_RETRIEVE_REQ_SMC32, FFA_SUCCESS_SMC32},
+ {"FFA_MEM_RETRIEVE_RESP_32 check", FFA_MEM_RETRIEVE_RESP, FFA_SUCCESS_SMC32},
+ {"FFA_MEM_RELINQUISH_32 check", FFA_MEM_RELINQUISH, FFA_SUCCESS_SMC32},
+ {"FFA_MEM_RECLAIM_32 check", FFA_MEM_RECLAIM, FFA_SUCCESS_SMC32},
+ {"Check non-existent command", 0xFFFF, FFA_ERROR}
+};
+
+test_result_t test_ffa_features(void)
+{
+ SKIP_TEST_IF_FFA_VERSION_LESS_THAN(1, 0);
+
+ /* Check if SPMC is OP-TEE at S-EL1 */
+ if (check_spmc_execution_level()) {
+ /* FFA_FEATURES is not yet supported in OP-TEE */
+ return TEST_RESULT_SUCCESS;
+ }
+
+ smc_ret_values ffa_ret;
+ unsigned int i, test_target_size =
+ sizeof(test_target) / sizeof(struct feature_test);
+
+ for (i = 0U; i < test_target_size; i++) {
+ ffa_ret = ffa_features(test_target[i].feature);
+ if (ffa_ret.ret0 != test_target[i].expected_ret) {
+ tftf_testcase_printf("%s returned %lx, expected %lx\n",
+ test_target[i].test_name,
+ ffa_ret.ret0,
+ test_target[i].expected_ret);
+ return TEST_RESULT_FAIL;
+ }
+ if ((test_target[i].expected_ret == (u_register_t)FFA_ERROR) &&
+ (ffa_ret.ret2 != (u_register_t)FFA_ERROR_NOT_SUPPORTED)) {
+ tftf_testcase_printf("%s failed for the wrong reason: "
+ "returned %lx, expected %lx\n",
+ test_target[i].test_name,
+ ffa_ret.ret2,
+ (u_register_t)FFA_ERROR_NOT_SUPPORTED);
+ return TEST_RESULT_FAIL;
+ }
+ }
+
+ return TEST_RESULT_SUCCESS;
+}
diff --git a/tftf/tests/tests-spm.mk b/tftf/tests/tests-spm.mk
index 0c54e1c..bef373f 100644
--- a/tftf/tests/tests-spm.mk
+++ b/tftf/tests/tests-spm.mk
@@ -9,4 +9,5 @@ TESTS_SOURCES += \
ffa_helpers.c \
test_ffa_direct_messaging.c \
test_ffa_version.c \
+ test_ffa_features.c \
)
diff --git a/tftf/tests/tests-spm.xml b/tftf/tests/tests-spm.xml
index 5ed2524..e2f29bf 100644
--- a/tftf/tests/tests-spm.xml
+++ b/tftf/tests/tests-spm.xml
@@ -30,4 +30,10 @@
</testsuite>
+ <testsuite name="PSA FF-A features"
+ description="Test FFA_FEATURES ABI" >
+ <testcase name="Test FFA_FEATURES"
+ function="test_ffa_features" />
+ </testsuite>
+
</testsuites>