test(ff-a): signaling per-vCPU notifications (SP to VM)
To consolidate test from previous patch [1], validate signaling of
per-vCPU notifications from SP to NWd.
[1] I86ba840b4c1d35cce95e2bc197293511db6783a1
Signed-off-by: J-Alves <joao.alves@arm.com>
Change-Id: I1899badcb2b0ea0ce1fa84e249dc53c6fb73a0e5
diff --git a/include/runtime_services/ffa_helpers.h b/include/runtime_services/ffa_helpers.h
index eddd55a..b25b6a1 100644
--- a/include/runtime_services/ffa_helpers.h
+++ b/include/runtime_services/ffa_helpers.h
@@ -70,6 +70,9 @@
#define FFA_NOTIFICATIONS_FLAG_PER_VCPU UINT32_C(0x1 << 0)
+/** Flag to delay Schedule Receiver Interrupt. */
+#define FFA_NOTIFICATIONS_FLAG_DELAY_SRI UINT32_C(0x1 << 1)
+
#define FFA_NOTIFICATIONS_FLAGS_VCPU_ID(id) UINT32_C((id & 0xFFFF) << 16)
#define FFA_NOTIFICATIONS_FLAG_BITMAP_SP UINT32_C(0x1 << 0)
diff --git a/tftf/tests/runtime_services/secure_service/test_ffa_notifications.c b/tftf/tests/runtime_services/secure_service/test_ffa_notifications.c
index 25b1e0a..2245895 100644
--- a/tftf/tests/runtime_services/secure_service/test_ffa_notifications.c
+++ b/tftf/tests/runtime_services/secure_service/test_ffa_notifications.c
@@ -976,3 +976,131 @@
{
return base_test_per_vcpu_notifications(SP_ID(1), SP_ID(2));
}
+
+static test_result_t notification_get_per_vcpu_on_handler(void)
+{
+ unsigned int mpid = read_mpidr_el1() & MPID_MASK;
+ unsigned int core_pos = platform_get_core_pos(mpid);
+ smc_ret_values ret;
+ test_result_t result = TEST_RESULT_SUCCESS;
+
+ VERBOSE("Getting per-vCPU notifications from %x, core: %u.\n",
+ per_vcpu_receiver, core_pos);
+
+ ret = ffa_run(per_vcpu_sender, core_pos);
+
+ if (ffa_func_id(ret) != FFA_MSG_WAIT) {
+ ERROR("Failed to run SP%x on core %u\n",
+ per_vcpu_sender, core_pos);
+ result = TEST_RESULT_FAIL;
+ goto out;
+ }
+
+ if (!notification_get_and_validate(per_vcpu_receiver,
+ FFA_NOTIFICATION(core_pos), 0,
+ core_pos,
+ FFA_NOTIFICATIONS_FLAG_BITMAP_SP)) {
+ result = TEST_RESULT_FAIL;
+ goto out;
+ }
+
+out:
+ /* Tell the lead CPU that the calling CPU has completed the test. */
+ tftf_send_event(&per_vcpu_finished[core_pos]);
+
+ return result;
+}
+
+/**
+ * Test whole flow from binding, to getting notifications' info, and getting
+ * pending notifications, namely signaling of notifications from SP to a VM.
+ * Each vCPU will receive a notification whose ID is the same as the core
+ * position.
+ */
+test_result_t test_ffa_notifications_sp_signals_vm_per_vcpu(void)
+{
+ /* Making a VM the receiver, and an SP the sender */
+ per_vcpu_receiver = 1;
+ per_vcpu_sender = SP_ID(2);
+
+ /**
+ * Manually set variables to validate what should be the return of to
+ * FFA_NOTIFICATION_INFO_GET.
+ */
+ uint16_t exp_ids[FFA_NOTIFICATIONS_INFO_GET_MAX_IDS] = {
+ per_vcpu_receiver, 0, 1, 2,
+ per_vcpu_receiver, 3, 4, 5,
+ per_vcpu_receiver, 6, 7, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ };
+ uint32_t exp_lists_count = 3;
+ uint32_t exp_lists_sizes[FFA_NOTIFICATIONS_INFO_GET_MAX_IDS] = {
+ 3, 3, 2, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ };
+
+ const bool exp_more_notif_pending = false;
+ test_result_t result = TEST_RESULT_SUCCESS;
+ uint64_t notifications_to_unbind = 0;
+ smc_ret_values ret;
+
+ CHECK_SPMC_TESTING_SETUP(1, 1, expected_sp_uuids);
+
+ /* Create bitmap for receiver. */
+ if (!notifications_bitmap_create(per_vcpu_receiver,
+ PLATFORM_CORE_COUNT)) {
+ return TEST_RESULT_FAIL;
+ }
+
+ /* Bind notifications, and request Cactus SP to set them. */
+ for (uint32_t i = 0U; i < PLATFORM_CORE_COUNT; i++) {
+ notifications_to_unbind |= FFA_NOTIFICATION(i);
+
+ uint32_t flags = FFA_NOTIFICATIONS_FLAG_DELAY_SRI |
+ FFA_NOTIFICATIONS_FLAG_PER_VCPU |
+ FFA_NOTIFICATIONS_FLAGS_VCPU_ID((uint16_t)i);
+
+ if (!notification_bind_and_set(per_vcpu_sender,
+ per_vcpu_receiver,
+ FFA_NOTIFICATION(i),
+ flags)) {
+ return TEST_RESULT_FAIL;
+ };
+ }
+
+ /* Call FFA_NOTIFICATION_INFO_GET and validate return. */
+ if (!notifications_info_get(exp_ids, exp_lists_count, exp_lists_sizes,
+ FFA_NOTIFICATIONS_INFO_GET_MAX_IDS,
+ exp_more_notif_pending)) {
+ ERROR("Info Get Failed....\n");
+ return TEST_RESULT_FAIL;
+ }
+
+ /*
+ * Get notifications in core 0, as it is not iterated at the CPU ON
+ * handler.
+ */
+ if (!notification_get_and_validate(per_vcpu_receiver,
+ FFA_NOTIFICATION(0), 0, 0,
+ FFA_NOTIFICATIONS_FLAG_BITMAP_SP)) {
+ result = TEST_RESULT_FAIL;
+ }
+
+ /* Bring up all the cores, and get notifications in each one of them. */
+ if (spm_run_multi_core_test(
+ (uintptr_t)notification_get_per_vcpu_on_handler,
+ per_vcpu_finished) != TEST_RESULT_SUCCESS) {
+ ERROR("Failed to get per-vCPU notifications\n");
+ result = TEST_RESULT_FAIL;
+ }
+
+ /* As a clean-up, unbind notifications. */
+ ret = ffa_notification_unbind(per_vcpu_sender, per_vcpu_receiver,
+ notifications_to_unbind);
+ if (is_ffa_call_error(ret)) {
+ result = TEST_RESULT_FAIL;
+ }
+
+ return result;
+}
diff --git a/tftf/tests/tests-spm.xml b/tftf/tests/tests-spm.xml
index 1a0134d..5752b8e 100644
--- a/tftf/tests/tests-spm.xml
+++ b/tftf/tests/tests-spm.xml
@@ -134,6 +134,8 @@
function="test_ffa_notifications_vm_signals_sp_per_vcpu" />
<testcase name="Notifications SP signals SP per-vCPU"
function="test_ffa_notifications_sp_signals_sp_per_vcpu" />
+ <testcase name="Notifications SP signals VM per-vCPU"
+ function="test_ffa_notifications_sp_signals_vm_per_vcpu" />
</testsuite>
</testsuites>