Merge changes from topic "tftf_refactor"
* changes:
refactor(neoverse_rd): introduce flash and ros macros
refactor(neoverse_rd): introduce timer and watchdog macros
refactor(neoverse_rd): define naming convention for CSS macros
refactor(neoverse_rd): remove deprecated header files
refactor(neoverse_rd): refactor header files for second gen platforms
refactor(neoverse_rd): refactor header files for first gen platforms
diff --git a/include/common/test_helpers.h b/include/common/test_helpers.h
index 3caca39..d6a7ade 100644
--- a/include/common/test_helpers.h
+++ b/include/common/test_helpers.h
@@ -420,4 +420,9 @@
/* Generate 64-bit random number */
unsigned long long rand64(void);
+/* TRBE Errata */
+#define CORTEX_A520_MIDR U(0x410FD800)
+#define CORTEX_X4_MIDR U(0x410FD821)
+#define RXPX_RANGE(x, y, z) (((x >= y) && (x <= z)) ? true : false)
+bool is_trbe_errata_affected_core(void);
#endif /* __TEST_HELPERS_H__ */
diff --git a/include/lib/aarch32/arch.h b/include/lib/aarch32/arch.h
index 6f41db9..cfbce56 100644
--- a/include/lib/aarch32/arch.h
+++ b/include/lib/aarch32/arch.h
@@ -23,6 +23,16 @@
#define MIDR_VAR_MASK U(0xf0)
#define MIDR_REV_MASK U(0xf)
+/******************************************************************************
+ * MIDR macros
+ *****************************************************************************/
+/* Extract the partnumber */
+#define EXTRACT_PARTNUM(x) ((x >> MIDR_PN_SHIFT) & MIDR_PN_MASK)
+/* Extract revision and variant info */
+
+#define EXTRACT_REV_VAR(x) (x & MIDR_REV_MASK) | ((x >> (MIDR_VAR_SHIFT - MIDR_REV_BITS)) \
+ & MIDR_VAR_MASK)
+
/*******************************************************************************
* MPIDR macros
******************************************************************************/
diff --git a/include/lib/aarch64/arch.h b/include/lib/aarch64/arch.h
index c45358e..d29f5a6 100644
--- a/include/lib/aarch64/arch.h
+++ b/include/lib/aarch64/arch.h
@@ -23,6 +23,16 @@
#define MIDR_PN_MASK U(0xfff)
#define MIDR_PN_SHIFT U(0x4)
+/******************************************************************************
+ * MIDR macros
+ *****************************************************************************/
+/* Extract the partnumber */
+#define EXTRACT_PARTNUM(x) ((x >> MIDR_PN_SHIFT) & MIDR_PN_MASK)
+/* Extract revision and variant info */
+
+#define EXTRACT_REV_VAR(x) (x & MIDR_REV_MASK) | ((x >> (MIDR_VAR_SHIFT - MIDR_REV_BITS)) \
+ & MIDR_VAR_MASK)
+
/*******************************************************************************
* MPIDR macros
******************************************************************************/
diff --git a/include/lib/aarch64/arch_features.h b/include/lib/aarch64/arch_features.h
index a2ed5be..f5dd294 100644
--- a/include/lib/aarch64/arch_features.h
+++ b/include/lib/aarch64/arch_features.h
@@ -251,6 +251,11 @@
ID_AA64DFR0_PMS_MASK);
}
+static inline bool is_feat_spe_supported(void)
+{
+ return spe_get_version() >= ID_AA64DFR0_SPE;
+}
+
static inline bool get_feat_pmuv3_supported(void)
{
return (((read_id_aa64dfr0_el1() >> ID_AA64DFR0_PMUVER_SHIFT) &
diff --git a/include/runtime_services/cactus_test_cmds.h b/include/runtime_services/cactus_test_cmds.h
index 0630753..282cfbe 100644
--- a/include/runtime_services/cactus_test_cmds.h
+++ b/include/runtime_services/cactus_test_cmds.h
@@ -201,10 +201,12 @@
static inline struct ffa_value cactus_mem_send_cmd(
ffa_id_t source, ffa_id_t dest, uint32_t mem_func,
ffa_memory_handle_t handle, ffa_memory_region_flags_t retrieve_flags,
- uint16_t word_to_write, bool expect_exception)
+ uint16_t word_to_write, bool expect_exception, bool is_normal_memory)
{
uint64_t _expect_exception = expect_exception ? (1ULL << 32) : 0;
- uint64_t packed = (uint64_t)word_to_write | _expect_exception;
+ uint64_t _is_normal_memory = is_normal_memory ? (1ULL << 33) : 0;
+ uint64_t packed = (uint64_t)word_to_write | _expect_exception |
+ _is_normal_memory;
return cactus_send_cmd(source, dest, CACTUS_MEM_SEND_CMD, mem_func,
handle, retrieve_flags, packed);
@@ -229,7 +231,12 @@
static inline bool cactus_mem_send_expect_exception(struct ffa_value ret)
{
- return (bool)(ret.arg7 >> 32);
+ return (bool)((ret.arg7 >> 32) & 0x1);
+}
+
+static inline bool cactus_mem_send_is_normal_memory(struct ffa_value ret)
+{
+ return (bool)((ret.arg7 >> 33) & 0x1);
}
/**
diff --git a/include/runtime_services/spm_common.h b/include/runtime_services/spm_common.h
index 6c01751..3fe154a 100644
--- a/include/runtime_services/spm_common.h
+++ b/include/runtime_services/spm_common.h
@@ -113,7 +113,8 @@
bool memory_retrieve(struct mailbox_buffers *mb,
struct ffa_memory_region **retrieved, uint64_t handle,
ffa_id_t sender, struct ffa_memory_access receivers[],
- uint32_t receiver_count, ffa_memory_region_flags_t flags);
+ uint32_t receiver_count, ffa_memory_region_flags_t flags,
+ bool is_normal_memory);
bool hypervisor_retrieve_request(struct mailbox_buffers *mb, uint64_t handle,
void *out, uint32_t out_size);
diff --git a/spm/cactus/cactus_main.c b/spm/cactus/cactus_main.c
index 1d5cd97..28afbfb 100644
--- a/spm/cactus/cactus_main.c
+++ b/spm/cactus/cactus_main.c
@@ -111,9 +111,9 @@
}
static const mmap_region_t cactus_mmap[] __attribute__((used)) = {
- /* PLAT_ARM_DEVICE0 area includes UART2 necessary to console */
- MAP_REGION_FLAT(PLAT_ARM_DEVICE0_BASE, PLAT_ARM_DEVICE0_SIZE,
+ MAP_REGION_FLAT(PLAT_CACTUS_DEVICE_BASE, PLAT_CACTUS_DEVICE_SIZE,
MT_DEVICE | MT_RW),
+
/* scratch memory allocated to be used for running SMMU tests */
MAP_REGION_FLAT(PLAT_CACTUS_MEMCPY_BASE, PLAT_CACTUS_MEMCPY_RANGE,
MT_MEMORY | MT_RW),
@@ -328,7 +328,7 @@
register_maintenance_interrupt_handlers();
/* Invoking self tests */
- ffa_tests(&mb);
+ ffa_tests(&mb, true);
cpu_feature_tests();
msg_loop:
diff --git a/spm/cactus/cactus_tests/cactus_test_memory_sharing.c b/spm/cactus/cactus_tests/cactus_test_memory_sharing.c
index 811c79f..570c648 100644
--- a/spm/cactus/cactus_tests/cactus_test_memory_sharing.c
+++ b/spm/cactus/cactus_tests/cactus_test_memory_sharing.c
@@ -114,6 +114,8 @@
cactus_mem_send_get_retrv_flags(*args);
uint32_t words_to_write = cactus_mem_send_words_to_write(*args);
bool expect_exception = cactus_mem_send_expect_exception(*args);
+ bool is_normal_memory = cactus_mem_send_is_normal_memory(*args);
+
struct ffa_memory_access receiver = ffa_memory_access_init(
vm_id, FFA_DATA_ACCESS_RW,
@@ -123,7 +125,7 @@
0, NULL);
EXPECT(memory_retrieve(mb, &m, handle, source, &receiver, 1,
- retrv_flags),
+ retrv_flags, is_normal_memory),
true);
composite = ffa_memory_region_get_composite(m, 0);
@@ -337,7 +339,7 @@
}
ffa_ret = cactus_mem_send_cmd(vm_id, receiver_id, mem_func, handle,
- 0, 10, false);
+ 0, 10, false, true);
if (!is_ffa_direct_response(ffa_ret)) {
return cactus_error_resp(vm_id, source, CACTUS_ERROR_FFA_CALL);
diff --git a/spm/cactus/plat/arm/fvp/include/sp_platform_def.h b/spm/cactus/plat/arm/fvp/include/sp_platform_def.h
index bb57ce8..390294f 100644
--- a/spm/cactus/plat/arm/fvp/include/sp_platform_def.h
+++ b/spm/cactus/plat/arm/fvp/include/sp_platform_def.h
@@ -18,8 +18,13 @@
#define PLAT_SP_RX_BASE ULL(0x7300000)
#define PLAT_SP_CORE_COUNT U(8)
-#define PLAT_ARM_DEVICE0_BASE DEVICE0_BASE
-#define PLAT_ARM_DEVICE0_SIZE DEVICE0_SIZE
+/*
+ * Map the device memory starting from UART2
+ * so UART0 can be lent by tftf in the device memory sharing tests.
+ */
+#define PLAT_CACTUS_DEVICE_BASE PL011_UART2_BASE
+#define PLAT_CACTUS_DEVICE_SIZE DEVICE0_SIZE - \
+ (PLAT_CACTUS_DEVICE_BASE - DEVICE0_BASE)
/* Scratch memory used for SMMUv3 driver testing purposes in Cactus SP */
#define PLAT_CACTUS_MEMCPY_BASE ULL(0x7400000)
diff --git a/spm/cactus/plat/arm/tc/include/sp_platform_def.h b/spm/cactus/plat/arm/tc/include/sp_platform_def.h
index b3a3514..7211dd0 100644
--- a/spm/cactus/plat/arm/tc/include/sp_platform_def.h
+++ b/spm/cactus/plat/arm/tc/include/sp_platform_def.h
@@ -18,8 +18,8 @@
#define PLAT_SP_RX_BASE ULL(0xfe300000)
#define PLAT_SP_CORE_COUNT U(8)
-#define PLAT_ARM_DEVICE0_BASE TC_DEVICE0_BASE
-#define PLAT_ARM_DEVICE0_SIZE TC_DEVICE0_SIZE
+#define PLAT_CACTUS_DEVICE_BASE TC_DEVICE0_BASE
+#define PLAT_CACTUS_DEVICE_SIZE TC_DEVICE0_SIZE
/* Scratch memory used for SMMUv3 driver testing purposes in Cactus SP */
/* SMMUv3 tests are disabled for TC platform */
diff --git a/spm/cactus_mm/cactus_mm_service_loop.c b/spm/cactus_mm/cactus_mm_service_loop.c
index dbec190..4226767 100644
--- a/spm/cactus_mm/cactus_mm_service_loop.c
+++ b/spm/cactus_mm/cactus_mm_service_loop.c
@@ -90,10 +90,13 @@
uint32_t ctx_size = svc_values.arg2;
uint64_t cookie = svc_values.arg3;
- NOTICE("Cactus: Received MM_COMMUNICATE_AARCH64 call\n");
- NOTICE("Cactus: Context address: 0x%llx\n", ctx_addr);
- NOTICE("Cactus: Context size : %u\n", ctx_size);
- NOTICE("Cactus: Cookie : 0x%llx\n", cookie);
+ (void) cookie;
+ (void) ctx_size;
+
+ VERBOSE("Cactus: Received MM_COMMUNICATE_AARCH64 call\n");
+ VERBOSE("Cactus: Context address: 0x%llx\n", ctx_addr);
+ VERBOSE("Cactus: Context size : %u\n", ctx_size);
+ VERBOSE("Cactus: Cookie : 0x%llx\n", cookie);
if (ctx_addr == 0) {
ERROR("Context address is invalid\n");
@@ -102,7 +105,7 @@
}
secure_partition_request_info_t *sps = (void *)(uintptr_t) ctx_addr;
- NOTICE("Received fast secure service request with ID #%u\n",
+ INFO("Received fast secure service request with ID #%u\n",
sps->id);
event_status_code = cactus_handle_fast_request(64, sps);
break;
@@ -114,10 +117,13 @@
uint32_t ctx_size = svc_values.arg2;
uint32_t cookie = svc_values.arg3;
- NOTICE("Cactus: Received MM_COMMUNICATE_AARCH32 call\n");
- NOTICE("Cactus: Context address: 0x%x\n", ctx_addr);
- NOTICE("Cactus: Context size : %u\n", ctx_size);
- NOTICE("Cactus: Cookie : 0x%x\n", cookie);
+ (void) cookie;
+ (void) ctx_size;
+
+ VERBOSE("Cactus: Received MM_COMMUNICATE_AARCH32 call\n");
+ VERBOSE("Cactus: Context address: 0x%x\n", ctx_addr);
+ VERBOSE("Cactus: Context size : %u\n", ctx_size);
+ VERBOSE("Cactus: Cookie : 0x%x\n", cookie);
if (ctx_addr == 0) {
ERROR("Context address is invalid\n");
@@ -126,8 +132,8 @@
}
secure_partition_request_info_t *sps = (void *)(uintptr_t) ctx_addr;
- NOTICE("Received fast secure service request with ID #%u\n",
- sps->id);
+ INFO("Received fast secure service request with ID #%u\n",
+ sps->id);
event_status_code = cactus_handle_fast_request(32, sps);
break;
}
diff --git a/spm/cactus_mm/cactus_mm_tests_memory_attributes.c b/spm/cactus_mm/cactus_mm_tests_memory_attributes.c
index 0a7af5f..d0ca6d3 100644
--- a/spm/cactus_mm/cactus_mm_tests_memory_attributes.c
+++ b/spm/cactus_mm/cactus_mm_tests_memory_attributes.c
@@ -44,10 +44,10 @@
int pages_count,
uint32_t memory_access_controls)
{
- INFO("Requesting memory attributes change\n");
- INFO(" Start address : %p\n", (void *) base_address);
- INFO(" Number of pages: %i\n", pages_count);
- INFO(" Attributes : 0x%x\n", memory_access_controls);
+ VERBOSE("Requesting memory attributes change\n");
+ VERBOSE(" Start address : %p\n", (void *) base_address);
+ VERBOSE(" Number of pages: %i\n", pages_count);
+ VERBOSE(" Attributes : 0x%x\n", memory_access_controls);
svc_args svc_values = { SP_MEMORY_ATTRIBUTES_SET_AARCH64,
base_address,
@@ -62,8 +62,8 @@
*/
static int32_t request_get_mem_attr(uintptr_t base_address)
{
- INFO("Requesting memory attributes\n");
- INFO(" Base address : %p\n", (void *) base_address);
+ VERBOSE("Requesting memory attributes\n");
+ VERBOSE(" Base address : %p\n", (void *) base_address);
svc_args svc_values = { SP_MEMORY_ATTRIBUTES_GET_AARCH64,
base_address };
@@ -105,8 +105,9 @@
new_attr = mem_access_perm(SP_MEMORY_ATTRIBUTES_NON_EXEC, SP_MEMORY_ATTRIBUTES_ACCESS_RW);
ret = request_mem_attr_changes(addr, pages_count, new_attr);
+
EXPECT(ret, SPM_SUCCESS);
- printf("Successfully changed memory attributes\n");
+ VERBOSE("Successfully changed memory attributes\n");
/* The attributes should be the ones we have just written. */
ret = request_get_mem_attr(addr);
@@ -118,12 +119,13 @@
++data) {
*data = 42;
}
- printf("Successfully wrote to the memory\n");
+ VERBOSE("Successfully wrote to the memory\n");
/* Let's revert back to the original attributes for the next test */
ret = request_mem_attr_changes(addr, pages_count, old_attr);
+
EXPECT(ret, SPM_SUCCESS);
- printf("Successfully restored the old attributes\n");
+ VERBOSE("Successfully restored the old attributes\n");
/* The attributes should be the original ones again. */
ret = request_get_mem_attr(addr);
diff --git a/spm/common/sp_tests/sp_test_ffa.c b/spm/common/sp_tests/sp_test_ffa.c
index ba63a0e..6e7fe1a 100644
--- a/spm/common/sp_tests/sp_test_ffa.c
+++ b/spm/common/sp_tests/sp_test_ffa.c
@@ -78,13 +78,13 @@
/*
* Test FFA_FEATURES interface.
*/
-static void ffa_features_test(void)
+static void ffa_features_test(bool el1_partition)
{
const struct ffa_features_test *func_id_targets;
/* Get common features between tftf and cactus. */
unsigned int test_target_size =
get_ffa_feature_test_target(&func_id_targets);
- const struct ffa_features_test feature_id_targets[] = {
+ struct ffa_features_test feature_id_targets[3] = {
{"FFA_FEATURE_MEI", FFA_FEATURE_MEI, FFA_SUCCESS_SMC32, 0,
FFA_VERSION_1_1},
{"FFA_FEATURE_SRI", FFA_FEATURE_SRI, FFA_ERROR, 0,
@@ -97,6 +97,12 @@
ffa_features_test_targets(func_id_targets, test_target_size);
/* Features are expected to be different to tftf. */
+
+ /* EL0 partitions don't support NPI. */
+ if (!el1_partition) {
+ feature_id_targets[2].expected_ret = FFA_ERROR;
+ }
+
ffa_features_test_targets(feature_id_targets,
ARRAY_SIZE(feature_id_targets));
}
@@ -234,13 +240,13 @@
}
}
-void ffa_tests(struct mailbox_buffers *mb)
+void ffa_tests(struct mailbox_buffers *mb, bool el1_partition)
{
const char *test_ffa_str = "FF-A setup and discovery";
announce_test_section_start(test_ffa_str);
- ffa_features_test();
+ ffa_features_test(el1_partition);
ffa_version_test();
ffa_spm_id_get_test();
ffa_partition_info_get_test(mb);
diff --git a/spm/common/sp_tests/sp_tests.h b/spm/common/sp_tests/sp_tests.h
index 007c2ca..f56d7e8 100644
--- a/spm/common/sp_tests/sp_tests.h
+++ b/spm/common/sp_tests/sp_tests.h
@@ -13,7 +13,7 @@
* Self test functions
*/
-void ffa_tests(struct mailbox_buffers *mb);
+void ffa_tests(struct mailbox_buffers *mb, bool el1_partition);
void cpu_feature_tests(void);
#endif /* CACTUS_TESTS_H */
diff --git a/spm/ivy/app/ivy_main.c b/spm/ivy/app/ivy_main.c
index 861ef30..53dbf73 100644
--- a/spm/ivy/app/ivy_main.c
+++ b/spm/ivy/app/ivy_main.c
@@ -47,7 +47,7 @@
panic();
}
- ffa_tests(&mb);
+ ffa_tests(&mb, false);
ret = ffa_msg_wait();
diff --git a/tftf/tests/common/test_helpers.c b/tftf/tests/common/test_helpers.c
index 6a0b08b..adcac3d 100644
--- a/tftf/tests/common/test_helpers.c
+++ b/tftf/tests/common/test_helpers.c
@@ -160,3 +160,22 @@
{
return ((unsigned long long)rand() << 32) | rand();
}
+
+/* Check if TRBE erratums 2938996 and 2726228 applies */
+bool is_trbe_errata_affected_core(void)
+{
+ long midr_val = read_midr();
+ long rev_var = EXTRACT_REV_VAR(midr_val);
+
+ if(EXTRACT_PARTNUM(midr_val) == EXTRACT_PARTNUM(CORTEX_A520_MIDR)) {
+ if(RXPX_RANGE(rev_var, 0, 1)) {
+ return true;
+ }
+ } else if (EXTRACT_PARTNUM(midr_val) == EXTRACT_PARTNUM(CORTEX_X4_MIDR)) {
+ if(RXPX_RANGE(rev_var, 0, 1)) {
+ return true;
+ }
+ }
+
+ return false;
+}
diff --git a/tftf/tests/extensions/trbe/test_trbe.c b/tftf/tests/extensions/trbe/test_trbe.c
index 8ef9576..4de48dc 100644
--- a/tftf/tests/extensions/trbe/test_trbe.c
+++ b/tftf/tests/extensions/trbe/test_trbe.c
@@ -21,6 +21,12 @@
#ifdef __aarch64__
SKIP_TEST_IF_TRBE_NOT_SUPPORTED();
+
+ /* If TRBE errata applies, EL3 disables the feature, SKIP the test */
+ if (is_trbe_errata_affected_core()) {
+ return TEST_RESULT_SKIPPED;
+ }
+
read_trblimitr_el1();
read_trbptr_el1();
read_trbbaser_el1();
diff --git a/tftf/tests/misc_tests/test_asymmetric_features.c b/tftf/tests/misc_tests/test_asymmetric_features.c
new file mode 100644
index 0000000..25b2421
--- /dev/null
+++ b/tftf/tests/misc_tests/test_asymmetric_features.c
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <arch.h>
+#include <arch_helpers.h>
+#include <arm_arch_svc.h>
+#include <events.h>
+#include <plat_topology.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <power_management.h>
+#include <psci.h>
+#include <smccc.h>
+#include <sync.h>
+#include <test_helpers.h>
+#include <tftf_lib.h>
+
+static event_t cpu_has_entered_test[PLATFORM_CORE_COUNT];
+
+static volatile bool undef_injection_triggered;
+
+static unsigned int test_result;
+
+static bool undef_injection_handler(void)
+{
+ uint64_t esr_el2 = read_esr_el2();
+ if (EC_BITS(esr_el2) == EC_UNKNOWN) {
+ undef_injection_triggered = true;
+ return true;
+ }
+
+ return false;
+}
+
+static test_result_t test_trbe(void)
+{
+ unsigned int mpid = read_mpidr_el1() & MPID_MASK;
+ unsigned int core_pos = platform_get_core_pos(mpid);
+ bool check_if_affected = is_trbe_errata_affected_core();
+
+ read_trblimitr_el1();
+
+ if (undef_injection_triggered == true && check_if_affected == true) {
+ test_result = TEST_RESULT_SUCCESS;
+ undef_injection_triggered = false;
+ tftf_testcase_printf("Undef injection triggered for core = %d "
+ "when accessing TRB_LIMTR\n", core_pos);
+ } else if (undef_injection_triggered == false && check_if_affected == false) {
+ test_result = TEST_RESULT_SUCCESS;
+ tftf_testcase_printf("TRB_LIMITR register accessible for core "
+ "= %d\n", core_pos);
+ } else {
+ test_result = TEST_RESULT_FAIL;
+ }
+
+ return test_result;
+}
+
+static test_result_t test_spe(void)
+{
+ unsigned int mpid = read_mpidr_el1() & MPID_MASK;
+ unsigned int core_pos = platform_get_core_pos(mpid);
+
+ read_pmscr_el1();
+
+ if (undef_injection_triggered == true && !is_feat_spe_supported()) {
+ test_result = TEST_RESULT_SUCCESS;
+ undef_injection_triggered = false;
+ tftf_testcase_printf("Undef injection triggered for core = %d "
+ "when accessing PMSCR_EL1\n", core_pos);
+ } else if (undef_injection_triggered == false &&
+ is_feat_spe_supported()) {
+ test_result = TEST_RESULT_SUCCESS;
+ tftf_testcase_printf("PMSCR_EL1 register accessible for core = "
+ "%d\n", core_pos);
+ } else {
+ test_result = TEST_RESULT_FAIL;
+ }
+
+ return test_result;
+}
+
+/*
+ * Non-lead cpu function that checks if trblimitr_el1 is accessible,
+ * on affected cores this causes a undef injection and passes.In cores that
+ * are not affected test just passes. It fails in other cases.
+ */
+static test_result_t non_lead_cpu_fn(void)
+{
+ unsigned int mpid = read_mpidr_el1() & MPID_MASK;
+ unsigned int core_pos = platform_get_core_pos(mpid);
+ test_result_t result;
+
+ test_result = TEST_RESULT_SUCCESS;
+
+ /* Signal to the lead CPU that the calling CPU has entered the test */
+ tftf_send_event(&cpu_has_entered_test[core_pos]);
+
+ result = test_trbe();
+ if (result != TEST_RESULT_SUCCESS) {
+ tftf_testcase_printf("test_trbe_enabled failed with result "
+ "%d\n", result);
+ test_result = result;
+ }
+
+ result = test_spe();
+ if (result != TEST_RESULT_SUCCESS) {
+ tftf_testcase_printf("test_spe_support failed with result %d\n",
+ result);
+ test_result = result;
+ }
+
+ /* Ensure that EL3 still functional */
+ smc_args args;
+ smc_ret_values smc_ret;
+ memset(&args, 0, sizeof(args));
+ args.fid = SMCCC_VERSION;
+ smc_ret = tftf_smc(&args);
+
+ tftf_testcase_printf("SMCCC Version = %d.%d\n",
+ (int)((smc_ret.ret0 >> SMCCC_VERSION_MAJOR_SHIFT) & SMCCC_VERSION_MAJOR_MASK),
+ (int)((smc_ret.ret0 >> SMCCC_VERSION_MINOR_SHIFT) & SMCCC_VERSION_MINOR_MASK));
+
+ return test_result;
+}
+
+/* This function kicks off non-lead cpus and the non-lead cpu function
+ * checks if errata is applied or not using the test.
+ */
+test_result_t test_asymmetric_features(void)
+{
+ unsigned int lead_mpid;
+ unsigned int cpu_mpid, cpu_node;
+ unsigned int core_pos;
+ int psci_ret;
+
+ test_result_t result;
+
+ test_result = TEST_RESULT_SUCCESS;
+
+ undef_injection_triggered = false;
+
+ register_custom_sync_exception_handler(undef_injection_handler);
+
+ lead_mpid = read_mpidr_el1() & MPID_MASK;
+
+ /* Testing TRBE and SPE feature in Lead core */
+ result = test_trbe();
+ if (result != TEST_RESULT_SUCCESS) {
+ tftf_testcase_printf("test_trbe_enabled failed with result "
+ "%d\n", result);
+ test_result = result;
+ }
+
+ result = test_spe();
+ if (result != TEST_RESULT_SUCCESS) {
+ tftf_testcase_printf("test_spe_support failed with result %d\n",
+ result);
+ test_result = result;
+ }
+
+ SKIP_TEST_IF_LESS_THAN_N_CPUS(2);
+
+ /* Power on all CPUs */
+ for_each_cpu(cpu_node) {
+ cpu_mpid = tftf_get_mpidr_from_node(cpu_node);
+ /* Skip lead CPU as it is already powered on */
+ if (cpu_mpid == lead_mpid)
+ continue;
+
+ psci_ret = tftf_cpu_on(cpu_mpid, (uintptr_t) non_lead_cpu_fn, 0);
+ if (psci_ret != PSCI_E_SUCCESS) {
+ tftf_testcase_printf(
+ "Failed to power on CPU 0x%x (%d)\n",
+ cpu_mpid, psci_ret);
+ return TEST_RESULT_SKIPPED;
+ }
+ }
+
+ /* Wait for non-lead CPUs to enter the test */
+ for_each_cpu(cpu_node) {
+ cpu_mpid = tftf_get_mpidr_from_node(cpu_node);
+ /* Skip lead CPU */
+ if (cpu_mpid == lead_mpid)
+ continue;
+
+ core_pos = platform_get_core_pos(cpu_mpid);
+ tftf_wait_for_event(&cpu_has_entered_test[core_pos]);
+ if (test_result == TEST_RESULT_FAIL)
+ break;
+ }
+
+ unregister_custom_sync_exception_handler();
+
+ return test_result;
+}
diff --git a/tftf/tests/runtime_services/secure_service/spm_common.c b/tftf/tests/runtime_services/secure_service/spm_common.c
index 53f4981..06e76db 100644
--- a/tftf/tests/runtime_services/secure_service/spm_common.c
+++ b/tftf/tests/runtime_services/secure_service/spm_common.c
@@ -270,12 +270,17 @@
bool memory_retrieve(struct mailbox_buffers *mb,
struct ffa_memory_region **retrieved, uint64_t handle,
ffa_id_t sender, struct ffa_memory_access receivers[],
- uint32_t receiver_count, ffa_memory_region_flags_t flags)
+ uint32_t receiver_count, ffa_memory_region_flags_t flags,
+ bool is_normal_memory)
{
struct ffa_value ret;
uint32_t fragment_size;
uint32_t total_size;
uint32_t descriptor_size;
+ enum ffa_memory_type memory_type = is_normal_memory ?
+ FFA_MEMORY_NORMAL_MEM : FFA_MEMORY_DEVICE_MEM;
+ enum ffa_memory_cacheability memory_cacheability = is_normal_memory ?
+ FFA_MEMORY_CACHE_WRITE_BACK : FFA_MEMORY_DEV_NGNRNE;
if (retrieved == NULL || mb == NULL) {
ERROR("Invalid parameters!\n");
@@ -284,8 +289,7 @@
descriptor_size = ffa_memory_retrieve_request_init(
mb->send, handle, sender, receivers, receiver_count, 0, flags,
- FFA_MEMORY_NORMAL_MEM, FFA_MEMORY_CACHE_WRITE_BACK,
- FFA_MEMORY_INNER_SHAREABLE);
+ memory_type, memory_cacheability, FFA_MEMORY_INNER_SHAREABLE);
ret = ffa_mem_retrieve_req(descriptor_size, descriptor_size);
diff --git a/tftf/tests/runtime_services/secure_service/test_ffa_exceptions.c b/tftf/tests/runtime_services/secure_service/test_ffa_exceptions.c
index cda7d22..552d2f9 100644
--- a/tftf/tests/runtime_services/secure_service/test_ffa_exceptions.c
+++ b/tftf/tests/runtime_services/secure_service/test_ffa_exceptions.c
@@ -90,7 +90,7 @@
* Tell SP to expect an exception.
*/
ret = cactus_mem_send_cmd(SENDER, RECEIVER, FFA_MEM_SHARE_SMC64,
- handle, 0, 1, true);
+ handle, 0, 1, true, true);
/* Undelegate the shared page. */
retmm = host_rmi_granule_undelegate((u_register_t)&share_page);
diff --git a/tftf/tests/runtime_services/secure_service/test_ffa_memory_sharing.c b/tftf/tests/runtime_services/secure_service/test_ffa_memory_sharing.c
index 3f7e270..ad4040a 100644
--- a/tftf/tests/runtime_services/secure_service/test_ffa_memory_sharing.c
+++ b/tftf/tests/runtime_services/secure_service/test_ffa_memory_sharing.c
@@ -177,7 +177,7 @@
*/
static test_result_t test_memory_send_sp(uint32_t mem_func, ffa_id_t borrower,
struct ffa_memory_region_constituent *constituents,
- size_t constituents_count)
+ size_t constituents_count, bool is_normal_memory)
{
struct ffa_value ret;
ffa_memory_handle_t handle;
@@ -186,10 +186,13 @@
unsigned int rme_supported = get_armv9_2_feat_rme_support();
const bool check_gpc_fault =
mem_func != FFA_MEM_SHARE_SMC64 &&
- rme_supported != 0U;
+ rme_supported != 0U && is_normal_memory;
- /* Arbitrarily write 5 words after using memory. */
- const uint32_t nr_words_to_write = 5;
+ /*
+ * For normal memory arbitrarilty write 5 words after using memory.
+ * For device just write 1 so we only write in the data register of the device.
+ */
+ const uint32_t nr_words_to_write = is_normal_memory ? 5 : 1;
struct ffa_memory_access receiver =
ffa_memory_access_init_permissions_from_mem_func(borrower,
@@ -232,7 +235,7 @@
ptr = (uint32_t *)constituents[0].address;
ret = cactus_mem_send_cmd(SENDER, borrower, mem_func, handle, 0,
- nr_words_to_write, false);
+ nr_words_to_write, false, is_normal_memory);
if (!is_ffa_direct_response(ret) ||
cactus_get_response(ret) != CACTUS_SUCCESS) {
@@ -295,7 +298,7 @@
sizeof(struct ffa_memory_region_constituent);
return test_memory_send_sp(FFA_MEM_SHARE_SMC64, RECEIVER, constituents,
- constituents_count);
+ constituents_count, true);
}
test_result_t test_mem_lend_sp(void)
@@ -309,7 +312,7 @@
sizeof(struct ffa_memory_region_constituent);
return test_memory_send_sp(FFA_MEM_LEND_SMC64, RECEIVER, constituents,
- constituents_count);
+ constituents_count, true);
}
test_result_t test_mem_donate_sp(void)
@@ -320,7 +323,7 @@
const uint32_t constituents_count = sizeof(constituents) /
sizeof(struct ffa_memory_region_constituent);
return test_memory_send_sp(FFA_MEM_DONATE_SMC64, RECEIVER, constituents,
- constituents_count);
+ constituents_count, true);
}
test_result_t test_consecutive_donate(void)
@@ -335,7 +338,7 @@
test_result_t ret = test_memory_send_sp(FFA_MEM_DONATE_SMC64, SP_ID(1),
constituents,
- constituents_count);
+ constituents_count, true);
if (ret != TEST_RESULT_SUCCESS) {
ERROR("Failed at first attempting of sharing.\n");
@@ -362,6 +365,28 @@
}
/*
+ * Lend device memory to the Secure Partition.
+ */
+test_result_t test_ffa_mem_lend_device_memory_sp(void)
+{
+#if PLAT_fvp || PLAT_tc
+ struct ffa_memory_region_constituent constituents[] = {
+ {(void *)PLAT_ARM_UART_BASE, 1, 0},
+ };
+
+ const uint32_t constituents_count = sizeof(constituents) /
+ sizeof(struct ffa_memory_region_constituent);
+
+ return test_memory_send_sp(FFA_MEM_LEND_SMC64, RECEIVER, constituents,
+ constituents_count, false);
+#else
+ return TEST_RESULT_SKIPPED;
+#endif
+
+}
+
+
+/*
* Test requests a memory send operation between cactus SPs.
* Cactus SP should reply to TFTF on whether the test succeeded or not.
*/
@@ -527,7 +552,7 @@
ret = cactus_mem_send_cmd(SENDER, RECEIVER, FFA_MEM_LEND_SMC64, handle,
FFA_MEMORY_REGION_FLAG_CLEAR,
- nr_words_to_write, false);
+ nr_words_to_write, false, true);
if (!is_ffa_direct_response(ret)) {
return TEST_RESULT_FAIL;
@@ -1322,7 +1347,8 @@
return TEST_RESULT_FAIL;
}
- if (!memory_retrieve(&mb, &m, handle, 0, receivers, ARRAY_SIZE(receivers), 0)) {
+ if (!memory_retrieve(&mb, &m, handle, 0, receivers, ARRAY_SIZE(receivers),
+ 0, true)) {
ERROR("Failed to retrieve the memory.\n");
return TEST_RESULT_FAIL;
}
@@ -1503,7 +1529,8 @@
return TEST_RESULT_FAIL;
}
- if (!memory_retrieve(&mb, &m, handle, 0, receivers, ARRAY_SIZE(receivers), 0)) {
+ if (!memory_retrieve(&mb, &m, handle, 0, receivers, ARRAY_SIZE(receivers),
+ 0, true)) {
ERROR("Failed to retrieve the memory.\n");
return TEST_RESULT_FAIL;
}
diff --git a/tftf/tests/tests-asymmetric-features.mk b/tftf/tests/tests-asymmetric-features.mk
new file mode 100644
index 0000000..86bb276
--- /dev/null
+++ b/tftf/tests/tests-asymmetric-features.mk
@@ -0,0 +1,7 @@
+#
+# Copyright (c) 2024, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+TESTS_SOURCES += tftf/tests/misc_tests/test_asymmetric_features.c
diff --git a/tftf/tests/tests-asymmetric-features.xml b/tftf/tests/tests-asymmetric-features.xml
new file mode 100644
index 0000000..413ef2c
--- /dev/null
+++ b/tftf/tests/tests-asymmetric-features.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ Copyright (c) 2024, Arm Limited. All rights reserved.
+
+ SPDX-License-Identifier: BSD-3-Clause
+-->
+
+<testsuites>
+ <testsuite name="Asymmetric Features" description="Asymmetric features support">
+ <testcase name="Asymmetric Features"
+ function="test_asymmetric_features" />
+ </testsuite>
+</testsuites>
diff --git a/tftf/tests/tests-memory-access.xml b/tftf/tests/tests-memory-access.xml
index 49965a0..200c5dd 100644
--- a/tftf/tests/tests-memory-access.xml
+++ b/tftf/tests/tests-memory-access.xml
@@ -18,6 +18,8 @@
function="test_mem_share_sp" />
<testcase name="Donate Memory to Secure World"
function="test_mem_donate_sp"/>
+ <testcase name="Lend Device Memory to Secure World"
+ function="test_ffa_mem_lend_device_memory_sp" />
<testcase name="Request Share Memory SP-to-SP"
function="test_req_mem_share_sp_to_sp" />
<testcase name="Request Lend Memory SP-to-SP"