refactor(direct message): create new dedicated test suite
Factored direct messaging related tests out of "ffa" test suite
and created a dedicated test suite for it.
Change-Id: I17b244d330ee634c4bd0c36a06160108de57953c
Signed-off-by: J-Alves <joao.alves@arm.com>
diff --git a/src/api.c b/src/api.c
index baa2d0e..abf2fae 100644
--- a/src/api.c
+++ b/src/api.c
@@ -2494,6 +2494,7 @@
if (!plat_ffa_is_direct_request_valid(current, sender_vm_id,
receiver_vm_id)) {
+ dlog_verbose("Invalid direct message request.\n");
return ffa_error(FFA_INVALID_PARAMETERS);
}
@@ -2697,6 +2698,7 @@
if (!plat_ffa_is_direct_response_valid(current, sender_vm_id,
receiver_vm_id)) {
+ dlog_verbose("Invalid direct response call.\n");
return ffa_error(FFA_INVALID_PARAMETERS);
}
diff --git a/test/vmapi/el0_partitions/services/BUILD.gn b/test/vmapi/el0_partitions/services/BUILD.gn
index 5bf8920..97622fe 100644
--- a/test/vmapi/el0_partitions/services/BUILD.gn
+++ b/test/vmapi/el0_partitions/services/BUILD.gn
@@ -21,6 +21,7 @@
"//src/arch/${plat_arch}/hftest/el0:interrupts",
"//test/hftest:hftest_secondary_el0_partition",
"//test/vmapi/common:common",
+ "//test/vmapi/primary_with_secondaries:primary_with_secondaries",
"//test/vmapi/primary_with_secondaries/services:echo",
"//test/vmapi/primary_with_secondaries/services:ffa_check",
"//test/vmapi/primary_with_secondaries/services:relay",
diff --git a/test/vmapi/primary_with_secondaries/BUILD.gn b/test/vmapi/primary_with_secondaries/BUILD.gn
index acfb173..8dec7a2 100644
--- a/test/vmapi/primary_with_secondaries/BUILD.gn
+++ b/test/vmapi/primary_with_secondaries/BUILD.gn
@@ -87,6 +87,7 @@
sources = [
"boot.c",
"debug_el1.c",
+ "dir_msg.c",
"ffa.c",
"floating_point.c",
"indirect_messaging.c",
@@ -186,6 +187,7 @@
]
sources = [
+ "dir_msg.c",
"indirect_messaging.c",
"memory_sharing.c",
]
@@ -265,6 +267,7 @@
]
sources = [
+ "dir_msg.c",
"indirect_messaging.c",
"memory_sharing.c",
]
diff --git a/test/vmapi/primary_with_secondaries/dir_msg.c b/test/vmapi/primary_with_secondaries/dir_msg.c
new file mode 100644
index 0000000..af7a7a1
--- /dev/null
+++ b/test/vmapi/primary_with_secondaries/dir_msg.c
@@ -0,0 +1,230 @@
+/*
+ * Copyright 2023 The Hafnium Authors.
+ *
+ * Use of this source code is governed by a BSD-style
+ * license that can be found in the LICENSE file or at
+ * https://opensource.org/licenses/BSD-3-Clause.
+ */
+
+#include <stdint.h>
+
+#include "hf/ffa.h"
+
+#include "vmapi/hf/call.h"
+
+#include "primary_with_secondary.h"
+#include "test/hftest.h"
+#include "test/vmapi/ffa.h"
+
+/**
+ * Send direct message, verify that sent info is echoed back.
+ */
+TEST(direct_message, ffa_send_direct_message_req_echo)
+{
+ const uint32_t msg[] = {0x00001111, 0x22223333, 0x44445555, 0x66667777,
+ 0x88889999};
+ struct mailbox_buffers mb = set_up_mailbox();
+ struct ffa_value res;
+ struct ffa_partition_info *service1_info = service1(mb.recv);
+
+ SERVICE_SELECT(service1_info->vm_id, "ffa_direct_message_resp_echo",
+ mb.send);
+ ffa_run(service1_info->vm_id, 0);
+
+ res = ffa_msg_send_direct_req(HF_PRIMARY_VM_ID, service1_info->vm_id,
+ msg[0], msg[1], msg[2], msg[3], msg[4]);
+
+ EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
+
+ EXPECT_EQ(res.arg3, msg[0]);
+ EXPECT_EQ(res.arg4, msg[1]);
+ EXPECT_EQ(res.arg5, msg[2]);
+ EXPECT_EQ(res.arg6, msg[3]);
+ EXPECT_EQ(res.arg7, msg[4]);
+}
+
+/**
+ * Initiate direct message request between test SPs.
+ * If test services are VMs, test should be skipped.
+ */
+TEST_PRECONDITION(direct_message, ffa_direct_message_services_echo,
+ service1_and_service2_are_secure)
+{
+ struct mailbox_buffers mb = set_up_mailbox();
+ struct ffa_partition_info *service1_info = service1(mb.recv);
+ struct ffa_partition_info *service2_info = service2(mb.recv);
+ ffa_vm_id_t own_id = hf_vm_get_id();
+ struct ffa_value ret;
+
+ /* Run service2 for it to wait for a request from service1. */
+ SERVICE_SELECT(service2_info->vm_id, "ffa_direct_message_resp_echo",
+ mb.send);
+ ffa_run(service2_info->vm_id, 0);
+
+ /* Service1 requests echo from service2. */
+ SERVICE_SELECT(service1_info->vm_id, "ffa_direct_message_echo_services",
+ mb.send);
+
+ /* Send to service1 the uuid of the target for its message. */
+ ret = send_indirect_message(own_id, service1_info->vm_id, mb.send,
+ &service2_info->vm_id,
+ sizeof(service2_info->vm_id), 0);
+ ASSERT_EQ(ret.func, FFA_SUCCESS_32);
+ ffa_run(service1_info->vm_id, 0);
+}
+
+/**
+ * If Hafnium is the hypervisor, and service1 is a VM:
+ * - Service verifies disallowed SMC invocations while ffa_msg_send_direct_req
+ * is being serviced.
+ * If Hafnium as SPMC is deployed and service1 is an SP:
+ * - Validate the state transitions permitted under RTM_FFA_DIR_REQ partition
+ * runtime model
+ */
+TEST(direct_message, ffa_send_direct_message_req_disallowed_smc)
+{
+ const uint32_t msg[] = {0x00001111, 0x22223333, 0x44445555, 0x66667777,
+ 0x88889999};
+ struct mailbox_buffers mb = set_up_mailbox();
+ struct ffa_value res;
+ struct ffa_partition_info *service1_info = service1(mb.recv);
+
+ SERVICE_SELECT(service1_info->vm_id,
+ "ffa_direct_msg_req_disallowed_smc", mb.send);
+ ffa_run(service1_info->vm_id, 0);
+
+ res = ffa_msg_send_direct_req(hf_vm_get_id(), service1_info->vm_id,
+ msg[0], msg[1], msg[2], msg[3], msg[4]);
+
+ EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
+}
+
+/**
+ * Send direct message to invalid destination.
+ */
+TEST(direct_message, ffa_send_direct_message_req_invalid_dst)
+{
+ const uint32_t msg[] = {0x00001111, 0x22223333, 0x44445555, 0x66667777,
+ 0x88889999};
+ struct ffa_value res;
+
+ res = ffa_msg_send_direct_req(HF_PRIMARY_VM_ID, HF_PRIMARY_VM_ID,
+ msg[0], msg[1], msg[2], msg[3], msg[4]);
+
+ EXPECT_FFA_ERROR(res, FFA_INVALID_PARAMETERS);
+}
+
+/**
+ * Verify that the primary VM can't send direct message responses.
+ */
+TEST(direct_message, ffa_send_direct_message_resp_invalid)
+{
+ struct mailbox_buffers mb = set_up_mailbox();
+ struct ffa_value res;
+ struct ffa_partition_info *service1_info = service1(mb.recv);
+
+ SERVICE_SELECT(service1_info->vm_id, "ffa_direct_message_resp_echo",
+ mb.send);
+ ffa_run(service1_info->vm_id, 0);
+
+ res = ffa_msg_send_direct_resp(HF_PRIMARY_VM_ID, service1_info->vm_id,
+ 0, 0, 0, 0, 0);
+ EXPECT_FFA_ERROR(res, FFA_INVALID_PARAMETERS);
+}
+
+/**
+ * Test has two purposes. It runs the test service via ffa_run, and validates
+ * that:
+ * - If service is an SP, it can't send a direct message request to a VM in the
+ * NWd.
+ * - If service is a secondary VM, it can't invoke a direct message request to
+ * the PVM (legacy behavior, for hafnium as an hypervisor).
+ */
+TEST(direct_message, ffa_secondary_direct_msg_req_invalid)
+{
+ struct mailbox_buffers mb = set_up_mailbox();
+ struct ffa_value res;
+ struct ffa_partition_info *service1_info = service1(mb.recv);
+
+ SERVICE_SELECT(service1_info->vm_id, "ffa_disallowed_direct_msg_req",
+ mb.send);
+ ffa_run(service1_info->vm_id, 0);
+
+ res = ffa_msg_send_direct_req(HF_PRIMARY_VM_ID, service1_info->vm_id, 0,
+ 0, 0, 0, 0);
+ EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
+}
+
+/**
+ * Run secondary VM without sending a direct message request beforehand.
+ * Secondary VM must fail sending a direct message response.
+ */
+TEST(direct_message, ffa_secondary_direct_msg_resp_invalid)
+{
+ struct mailbox_buffers mb = set_up_mailbox();
+ struct ffa_value res;
+ struct ffa_partition_info *service1_info = service1(mb.recv);
+
+ SERVICE_SELECT(service1_info->vm_id, "ffa_disallowed_direct_msg_resp",
+ mb.send);
+ ffa_run(service1_info->vm_id, 0);
+
+ res = ffa_msg_send_direct_req(HF_PRIMARY_VM_ID, service1_info->vm_id, 0,
+ 0, 0, 0, 0);
+ EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
+}
+
+/**
+ * Run secondary VM and send a direct message request. Secondary VM attempts
+ * altering the sender and receiver in its direct message responses, and must
+ * fail to do so.
+ */
+TEST(direct_message, ffa_secondary_spoofed_response)
+{
+ struct mailbox_buffers mb = set_up_mailbox();
+ struct ffa_value res;
+ struct ffa_partition_info *service1_info = service1(mb.recv);
+
+ SERVICE_SELECT(service1_info->vm_id,
+ "ffa_direct_msg_resp_invalid_sender_receiver", mb.send);
+ ffa_run(service1_info->vm_id, 0);
+
+ res = ffa_msg_send_direct_req(HF_PRIMARY_VM_ID, service1_info->vm_id, 0,
+ 0, 0, 0, 0);
+ EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
+}
+
+/*
+ * Validate that the creation of a cyclic dependency via direct_messaging
+ * is not possible.
+ * The test only makes sense in the scope of validating the SPMC, as the
+ * hypervisor limits the direct message requests to be only invoked from
+ * the primary VM. Thus, using precondition that checks both involved test
+ * services are SPs.
+ */
+TEST_PRECONDITION(direct_message, fail_if_cyclic_dependency,
+ service1_and_service2_are_secure)
+{
+ struct mailbox_buffers mb = set_up_mailbox();
+ struct ffa_partition_info *service1_info = service1(mb.recv);
+ struct ffa_partition_info *service2_info = service2(mb.recv);
+ ffa_vm_id_t own_id = hf_vm_get_id();
+ struct ffa_value ret;
+
+ /* Run service2 for it to wait for a request from service1. */
+ SERVICE_SELECT(service2_info->vm_id, "ffa_direct_message_cycle_denied",
+ mb.send);
+ ffa_run(service2_info->vm_id, 0);
+
+ /* Service1 requests echo from service2. */
+ SERVICE_SELECT(service1_info->vm_id, "ffa_direct_message_echo_services",
+ mb.send);
+
+ /* Send to service1 the uuid of the target for its message. */
+ ret = send_indirect_message(own_id, service1_info->vm_id, mb.send,
+ &service2_info->vm_id,
+ sizeof(service2_info->vm_id), 0);
+
+ ASSERT_EQ(ret.func, FFA_SUCCESS_32);
+ EXPECT_EQ(ffa_run(service1_info->vm_id, 0).func, FFA_YIELD_32);
+}
diff --git a/test/vmapi/primary_with_secondaries/ffa.c b/test/vmapi/primary_with_secondaries/ffa.c
index cfea431..95068f9 100644
--- a/test/vmapi/primary_with_secondaries/ffa.c
+++ b/test/vmapi/primary_with_secondaries/ffa.c
@@ -212,136 +212,6 @@
EXPECT_EQ(run_res.arg2, FFA_SLEEP_INDEFINITE);
}
-/**
- * Send direct message, verify that sent info is echoed back.
- */
-TEST(ffa, ffa_send_direct_message_req_echo)
-{
- const uint32_t msg[] = {0x00001111, 0x22223333, 0x44445555, 0x66667777,
- 0x88889999};
- struct mailbox_buffers mb = set_up_mailbox();
- struct ffa_value res;
-
- SERVICE_SELECT(SERVICE_VM1, "ffa_direct_message_resp_echo", mb.send);
- ffa_run(SERVICE_VM1, 0);
-
- res = ffa_msg_send_direct_req(HF_PRIMARY_VM_ID, SERVICE_VM1, msg[0],
- msg[1], msg[2], msg[3], msg[4]);
-
- EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
-
- EXPECT_EQ(res.arg3, msg[0]);
- EXPECT_EQ(res.arg4, msg[1]);
- EXPECT_EQ(res.arg5, msg[2]);
- EXPECT_EQ(res.arg6, msg[3]);
- EXPECT_EQ(res.arg7, msg[4]);
-}
-
-/**
- * Send direct message, secondary verifies disallowed SMC invocations while
- * ffa_msg_send_direct_req is being serviced.
- */
-TEST(ffa, ffa_send_direct_message_req_disallowed_smc)
-{
- const uint32_t msg[] = {0x00001111, 0x22223333, 0x44445555, 0x66667777,
- 0x88889999};
- struct mailbox_buffers mb = set_up_mailbox();
- struct ffa_value res;
-
- SERVICE_SELECT(SERVICE_VM1, "ffa_direct_msg_req_disallowed_smc",
- mb.send);
- ffa_run(SERVICE_VM1, 0);
-
- res = ffa_msg_send_direct_req(HF_PRIMARY_VM_ID, SERVICE_VM1, msg[0],
- msg[1], msg[2], msg[3], msg[4]);
-
- EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
-}
-
-/**
- * Send direct message to invalid destination.
- */
-TEST(ffa, ffa_send_direct_message_req_invalid_dst)
-{
- const uint32_t msg[] = {0x00001111, 0x22223333, 0x44445555, 0x66667777,
- 0x88889999};
- struct ffa_value res;
-
- res = ffa_msg_send_direct_req(HF_PRIMARY_VM_ID, HF_PRIMARY_VM_ID,
- msg[0], msg[1], msg[2], msg[3], msg[4]);
-
- EXPECT_FFA_ERROR(res, FFA_INVALID_PARAMETERS);
-}
-
-/**
- * Verify that the primary VM can't send direct message responses.
- */
-TEST(ffa, ffa_send_direct_message_resp_invalid)
-{
- struct ffa_value res;
- struct mailbox_buffers mb = set_up_mailbox();
-
- SERVICE_SELECT(SERVICE_VM1, "ffa_direct_message_resp_echo", mb.send);
- ffa_run(SERVICE_VM1, 0);
-
- res = ffa_msg_send_direct_resp(HF_PRIMARY_VM_ID, SERVICE_VM1, 0, 0, 0,
- 0, 0);
- EXPECT_FFA_ERROR(res, FFA_INVALID_PARAMETERS);
-}
-
-/**
- * Run secondary VM through ffa_run and check it cannot invoke
- * a direct message request.
- */
-TEST(ffa, ffa_secondary_direct_msg_req_invalid)
-{
- struct mailbox_buffers mb = set_up_mailbox();
- struct ffa_value res;
-
- SERVICE_SELECT(SERVICE_VM1, "ffa_disallowed_direct_msg_req", mb.send);
- ffa_run(SERVICE_VM1, 0);
-
- res = ffa_msg_send_direct_req(HF_PRIMARY_VM_ID, SERVICE_VM1, 0, 0, 0, 0,
- 0);
- EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
-}
-
-/**
- * Run secondary VM without sending a direct message request beforehand.
- * Secondary VM must fail sending a direct message response.
- */
-TEST(ffa, ffa_secondary_direct_msg_resp_invalid)
-{
- struct mailbox_buffers mb = set_up_mailbox();
- struct ffa_value res;
-
- SERVICE_SELECT(SERVICE_VM1, "ffa_disallowed_direct_msg_resp", mb.send);
- ffa_run(SERVICE_VM1, 0);
-
- res = ffa_msg_send_direct_req(HF_PRIMARY_VM_ID, SERVICE_VM1, 0, 0, 0, 0,
- 0);
- EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
-}
-
-/**
- * Run secondary VM and send a direct message request. Secondary VM attempts
- * altering the sender and receiver in its direct message responses, and must
- * fail to do so.
- */
-TEST(ffa, ffa_secondary_spoofed_response)
-{
- struct mailbox_buffers mb = set_up_mailbox();
- struct ffa_value res;
-
- SERVICE_SELECT(SERVICE_VM1,
- "ffa_direct_msg_resp_invalid_sender_receiver", mb.send);
- ffa_run(SERVICE_VM1, 0);
-
- res = ffa_msg_send_direct_req(HF_PRIMARY_VM_ID, SERVICE_VM1, 0, 0, 0, 0,
- 0);
- EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
-}
-
/*
* The secondary vCPU is waiting for a direct request, but the primary instead
* calls `FFA_RUN`. This should return immediately to the primary without the
diff --git a/test/vmapi/primary_with_secondaries/inc/primary_with_secondary.h b/test/vmapi/primary_with_secondaries/inc/primary_with_secondary.h
index 8a3c737..5e154f3 100644
--- a/test/vmapi/primary_with_secondaries/inc/primary_with_secondary.h
+++ b/test/vmapi/primary_with_secondaries/inc/primary_with_secondary.h
@@ -54,6 +54,7 @@
/* Precondition functions for this test setup. */
bool service1_is_vm(void);
+bool service1_and_service2_are_secure(void);
bool hypervisor_only(void);
#define SERVICE_VM1 (HF_VM_ID_OFFSET + 1)
diff --git a/test/vmapi/primary_with_secondaries/primary_with_secondaries.c b/test/vmapi/primary_with_secondaries/primary_with_secondaries.c
index ae28c38..1771fc1 100644
--- a/test/vmapi/primary_with_secondaries/primary_with_secondaries.c
+++ b/test/vmapi/primary_with_secondaries/primary_with_secondaries.c
@@ -31,6 +31,16 @@
return mb;
}
+bool service1_and_service2_are_secure(void)
+{
+ struct mailbox_buffers mb = get_precondition_mailbox();
+ struct ffa_partition_info *service1_info = service1(mb.recv);
+ struct ffa_partition_info *service2_info = service2(mb.recv);
+
+ return !IS_VM_ID(service1_info->vm_id) &&
+ !IS_VM_ID(service2_info->vm_id);
+}
+
/*
* The following is a precondition function, for the current system set-up.
* This is currently being used to skip memory sharing tests, when
@@ -40,6 +50,7 @@
{
struct mailbox_buffers mb = get_precondition_mailbox();
struct ffa_partition_info *service1_info = service1(mb.recv);
+
return IS_VM_ID(service1_info->vm_id);
}
diff --git a/test/vmapi/primary_with_secondaries/services/BUILD.gn b/test/vmapi/primary_with_secondaries/services/BUILD.gn
index b8a5334..67d63db 100644
--- a/test/vmapi/primary_with_secondaries/services/BUILD.gn
+++ b/test/vmapi/primary_with_secondaries/services/BUILD.gn
@@ -164,7 +164,10 @@
]
deps = [ "//test/vmapi/common" ]
- sources = [ "ffa_check.c" ]
+ sources = [
+ "dir_msg.c",
+ "ffa_check.c",
+ ]
}
# Group services together into VMs.
@@ -199,6 +202,7 @@
deps = [
":echo",
+ ":ffa_check",
":interruptible",
":memory",
":relay",
@@ -214,6 +218,7 @@
deps = [
":echo",
+ ":ffa_check",
":smp",
"//test/hftest:hftest_secondary_vm",
"//test/vmapi/primary_with_secondaries:primary_with_secondaries",
diff --git a/test/vmapi/primary_with_secondaries/services/dir_msg.c b/test/vmapi/primary_with_secondaries/services/dir_msg.c
new file mode 100644
index 0000000..e6b0d0f
--- /dev/null
+++ b/test/vmapi/primary_with_secondaries/services/dir_msg.c
@@ -0,0 +1,182 @@
+/*
+ * Copyright 2023 The Hafnium Authors.
+ *
+ * Use of this source code is governed by a BSD-style
+ * license that can be found in the LICENSE file or at
+ * https://opensource.org/licenses/BSD-3-Clause.
+ */
+
+#include "hf/ffa.h"
+
+#include "vmapi/hf/call.h"
+
+#include "primary_with_secondary.h"
+#include "test/hftest.h"
+#include "test/vmapi/ffa.h"
+
+TEST_SERVICE(ffa_direct_message_resp_echo)
+{
+ struct ffa_value args = ffa_msg_wait();
+
+ EXPECT_EQ(args.func, FFA_MSG_SEND_DIRECT_REQ_32);
+
+ ffa_msg_send_direct_resp(ffa_receiver(args), ffa_sender(args),
+ args.arg3, args.arg4, args.arg5, args.arg6,
+ args.arg7);
+}
+
+TEST_SERVICE(ffa_direct_message_echo_services)
+{
+ const uint32_t msg[] = {0x00001111, 0x22223333, 0x44445555, 0x66667777,
+ 0x88889999};
+ void *recv_buf = SERVICE_RECV_BUFFER();
+ struct ffa_value res;
+ ffa_vm_id_t target_id;
+
+ /* Retrieve FF-A ID of the target endpoint. */
+ receive_indirect_message((void *)&target_id, sizeof(target_id),
+ recv_buf, NULL);
+
+ HFTEST_LOG("Echo test with: %x", target_id);
+
+ res = ffa_msg_send_direct_req(hf_vm_get_id(), target_id, msg[0], msg[1],
+ msg[2], msg[3], msg[4]);
+
+ EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
+
+ EXPECT_EQ(res.arg3, msg[0]);
+ EXPECT_EQ(res.arg4, msg[1]);
+ EXPECT_EQ(res.arg5, msg[2]);
+ EXPECT_EQ(res.arg6, msg[3]);
+ EXPECT_EQ(res.arg7, msg[4]);
+
+ ffa_yield();
+}
+
+TEST_SERVICE(ffa_direct_msg_req_disallowed_smc)
+{
+ struct ffa_value args = ffa_msg_wait();
+ struct ffa_value ret;
+ void *recv_buf = SERVICE_RECV_BUFFER();
+ struct ffa_partition_info *service1_info = service1(recv_buf);
+
+ EXPECT_EQ(args.func, FFA_MSG_SEND_DIRECT_REQ_32);
+
+ ret = ffa_yield();
+ EXPECT_FFA_ERROR(ret, FFA_DENIED);
+
+ ret = ffa_msg_wait();
+ EXPECT_FFA_ERROR(ret, FFA_DENIED);
+
+ ret = ffa_msg_send_direct_req(service1_info->vm_id, ffa_sender(args), 0,
+ 0, 0, 0, 0);
+ EXPECT_FFA_ERROR(ret, FFA_INVALID_PARAMETERS);
+
+ ffa_msg_send_direct_resp(ffa_receiver(args), ffa_sender(args),
+ args.arg3, args.arg4, args.arg5, args.arg6,
+ args.arg7);
+}
+
+/**
+ * Verify that services can't send direct message requests
+ * when invoked by FFA_RUN.
+ */
+TEST_SERVICE(ffa_disallowed_direct_msg_req)
+{
+ struct ffa_value args;
+ struct ffa_value ret;
+ void *recv_buf = SERVICE_RECV_BUFFER();
+ struct ffa_partition_info *service1_info = service1(recv_buf);
+
+ ret = ffa_msg_send_direct_req(service1_info->vm_id, HF_PRIMARY_VM_ID, 0,
+ 0, 0, 0, 0);
+ EXPECT_FFA_ERROR(ret, FFA_INVALID_PARAMETERS);
+
+ ret = ffa_msg_send_direct_req(service1_info->vm_id, HF_VM_ID_BASE + 10,
+ 0, 0, 0, 0, 0);
+ EXPECT_FFA_ERROR(ret, FFA_INVALID_PARAMETERS);
+
+ args = ffa_msg_wait();
+ EXPECT_EQ(args.func, FFA_MSG_SEND_DIRECT_REQ_32);
+
+ ffa_msg_send_direct_resp(ffa_receiver(args), ffa_sender(args),
+ args.arg3, args.arg4, args.arg5, args.arg6,
+ args.arg7);
+}
+
+/**
+ * Verify a service can't send a direct message response when it hasn't
+ * first been sent a request.
+ */
+TEST_SERVICE(ffa_disallowed_direct_msg_resp)
+{
+ struct ffa_value args;
+ struct ffa_value ret;
+ void *recv_buf = SERVICE_RECV_BUFFER();
+ struct ffa_partition_info *service1_info = service1(recv_buf);
+
+ ret = ffa_msg_send_direct_resp(service1_info->vm_id, HF_PRIMARY_VM_ID,
+ 0, 0, 0, 0, 0);
+ EXPECT_FFA_ERROR(ret, FFA_DENIED);
+
+ args = ffa_msg_wait();
+ EXPECT_EQ(args.func, FFA_MSG_SEND_DIRECT_REQ_32);
+
+ ffa_msg_send_direct_resp(ffa_receiver(args), ffa_sender(args),
+ args.arg3, args.arg4, args.arg5, args.arg6,
+ args.arg7);
+}
+
+/**
+ * Verify a service can't send a response to a different VM than the one
+ * that sent the request.
+ * Verify a service cannot send a response with a sender ID different from
+ * its own service ID.
+ */
+TEST_SERVICE(ffa_direct_msg_resp_invalid_sender_receiver)
+{
+ struct ffa_value res;
+ void *recv_buf = SERVICE_RECV_BUFFER();
+ struct ffa_partition_info *service2_info = service2(recv_buf);
+ ffa_vm_id_t invalid_receiver;
+ struct ffa_value args = ffa_msg_wait();
+ ffa_vm_id_t own_id = hf_vm_get_id();
+ EXPECT_EQ(args.func, FFA_MSG_SEND_DIRECT_REQ_32);
+
+ ffa_vm_id_t sender = ffa_sender(args);
+ ASSERT_EQ(own_id, ffa_receiver(args));
+
+ /* Other receiver ID. */
+ invalid_receiver = IS_VM_ID(own_id) ? service2_info->vm_id : own_id;
+ res = ffa_msg_send_direct_resp(own_id, invalid_receiver, 0, 0, 0, 0, 0);
+ EXPECT_FFA_ERROR(res, FFA_INVALID_PARAMETERS);
+
+ /* Spoof sender ID. */
+ res = ffa_msg_send_direct_resp(service2_info->vm_id, sender, 0, 0, 0, 0,
+ 0);
+ EXPECT_FFA_ERROR(res, FFA_INVALID_PARAMETERS);
+
+ ffa_msg_send_direct_resp(own_id, sender, 0, 0, 0, 0, 0);
+}
+
+TEST_SERVICE(ffa_direct_message_cycle_denied)
+{
+ struct ffa_value res;
+ struct ffa_value args = ffa_msg_wait();
+ ffa_vm_id_t sender;
+ ffa_vm_id_t receiver;
+ ffa_vm_id_t own_id = hf_vm_get_id();
+
+ ASSERT_EQ(args.func, FFA_MSG_SEND_DIRECT_REQ_32);
+ receiver = ffa_receiver(args);
+ sender = ffa_sender(args);
+
+ EXPECT_EQ(receiver, hf_vm_get_id());
+
+ res = ffa_msg_send_direct_req(own_id, sender, 1, 2, 3, 4, 5);
+ EXPECT_FFA_ERROR(res, FFA_DENIED);
+
+ ffa_msg_send_direct_resp(ffa_receiver(args), ffa_sender(args),
+ args.arg3, args.arg4, args.arg5, args.arg6,
+ args.arg7);
+}
diff --git a/test/vmapi/primary_with_secondaries/services/ffa_check.c b/test/vmapi/primary_with_secondaries/services/ffa_check.c
index c56cb6b..e8353f4 100644
--- a/test/vmapi/primary_with_secondaries/services/ffa_check.c
+++ b/test/vmapi/primary_with_secondaries/services/ffa_check.c
@@ -66,117 +66,20 @@
ffa_yield();
}
-TEST_SERVICE(ffa_direct_message_resp_echo)
-{
- struct ffa_value args = ffa_msg_wait();
-
- EXPECT_EQ(args.func, FFA_MSG_SEND_DIRECT_REQ_32);
-
- ffa_msg_send_direct_resp(ffa_receiver(args), ffa_sender(args),
- args.arg3, args.arg4, args.arg5, args.arg6,
- args.arg7);
-}
-
-TEST_SERVICE(ffa_direct_msg_req_disallowed_smc)
-{
- struct ffa_value args = ffa_msg_wait();
- struct ffa_value ret;
-
- EXPECT_EQ(args.func, FFA_MSG_SEND_DIRECT_REQ_32);
-
- ret = ffa_yield();
- EXPECT_FFA_ERROR(ret, FFA_DENIED);
-
- ret = ffa_msg_send(ffa_receiver(args), ffa_sender(args), 0, 0);
- EXPECT_FFA_ERROR(ret, FFA_DENIED);
-
- ret = ffa_msg_wait();
- EXPECT_FFA_ERROR(ret, FFA_DENIED);
-
- ret = ffa_msg_send_direct_req(SERVICE_VM1, SERVICE_VM2, 0, 0, 0, 0, 0);
- EXPECT_FFA_ERROR(ret, FFA_INVALID_PARAMETERS);
-
- ret = ffa_msg_poll();
- EXPECT_FFA_ERROR(ret, FFA_DENIED);
-
- ffa_msg_send_direct_resp(ffa_receiver(args), ffa_sender(args),
- args.arg3, args.arg4, args.arg5, args.arg6,
- args.arg7);
-}
-
/**
- * Verify that secondary VMs can't send direct message requests
- * when invoked by FFA_RUN.
+ * Service for indirect message error checking.
+ * The VM unmap its RX/TX and waits for a message.
*/
-TEST_SERVICE(ffa_disallowed_direct_msg_req)
+TEST_SERVICE(ffa_indirect_msg_error)
{
- struct ffa_value args;
- struct ffa_value ret;
+ EXPECT_EQ(ffa_rxtx_unmap().func, FFA_SUCCESS_32);
- ret = ffa_msg_send_direct_req(SERVICE_VM1, HF_PRIMARY_VM_ID, 0, 0, 0, 0,
- 0);
- EXPECT_FFA_ERROR(ret, FFA_INVALID_PARAMETERS);
-
- ret = ffa_msg_send_direct_req(SERVICE_VM1, SERVICE_VM2, 0, 0, 0, 0, 0);
- EXPECT_FFA_ERROR(ret, FFA_INVALID_PARAMETERS);
-
- args = ffa_msg_wait();
- EXPECT_EQ(args.func, FFA_MSG_SEND_DIRECT_REQ_32);
-
- ffa_msg_send_direct_resp(ffa_receiver(args), ffa_sender(args),
- args.arg3, args.arg4, args.arg5, args.arg6,
- args.arg7);
+ ffa_msg_wait();
}
/**
- * Verify a secondary VM can't send a direct message response when it hasn't
- * first been sent a request.
- */
-TEST_SERVICE(ffa_disallowed_direct_msg_resp)
-{
- struct ffa_value args;
- struct ffa_value ret;
-
- ret = ffa_msg_send_direct_resp(SERVICE_VM1, HF_PRIMARY_VM_ID, 0, 0, 0,
- 0, 0);
- EXPECT_FFA_ERROR(ret, FFA_DENIED);
-
- args = ffa_msg_wait();
- EXPECT_EQ(args.func, FFA_MSG_SEND_DIRECT_REQ_32);
-
- ffa_msg_send_direct_resp(ffa_receiver(args), ffa_sender(args),
- args.arg3, args.arg4, args.arg5, args.arg6,
- args.arg7);
-}
-
-/**
- * Verify a secondary VM can't send a response to a different VM than the one
- * that sent the request.
- * Verify a secondary VM cannot send a response with a sender ID different from
- * its own secondary VM ID.
- */
-TEST_SERVICE(ffa_direct_msg_resp_invalid_sender_receiver)
-{
- struct ffa_value args = ffa_msg_wait();
- struct ffa_value res;
-
- EXPECT_EQ(args.func, FFA_MSG_SEND_DIRECT_REQ_32);
-
- ffa_vm_id_t sender = ffa_sender(args);
- ffa_vm_id_t receiver = ffa_receiver(args);
-
- res = ffa_msg_send_direct_resp(receiver, SERVICE_VM2, 0, 0, 0, 0, 0);
- EXPECT_FFA_ERROR(res, FFA_INVALID_PARAMETERS);
-
- res = ffa_msg_send_direct_resp(SERVICE_VM2, sender, 0, 0, 0, 0, 0);
- EXPECT_FFA_ERROR(res, FFA_INVALID_PARAMETERS);
-
- ffa_msg_send_direct_resp(receiver, sender, 0, 0, 0, 0, 0);
-}
-
-/**
- * Secondary VM waits for a direct message request but primary VM
- * calls ffa_run instead. Verify the secondary VM does not run.
+ * Service waits for a direct message request but primary VM
+ * calls ffa_run instead. Verify the service does not run.
*/
TEST_SERVICE(ffa_direct_msg_run)
{
@@ -193,14 +96,3 @@
ffa_msg_send_direct_resp(ffa_receiver(res), ffa_sender(res), 4, 0, 0, 0,
0);
}
-
-/**
- * Service for indirect message error checking.
- * The VM unmap its RX/TX and waits for a message.
- */
-TEST_SERVICE(ffa_indirect_msg_error)
-{
- EXPECT_EQ(ffa_rxtx_unmap().func, FFA_SUCCESS_32);
-
- ffa_msg_wait();
-}