Handle VM availability messages
Add handling for the FF-A VM availability messages to libsp. Currently
this is only a skeleton implementation that calls an empty callback in
the SPs.
Signed-off-by: Balint Dobszay <balint.dobszay@arm.com>
Change-Id: I037f7a67121b7b02ceb1775baf4508abb9455fcd
diff --git a/components/messaging/ffa/libsp/ffa.c b/components/messaging/ffa/libsp/ffa.c
index 89fd8fe..76f0eda 100644
--- a/components/messaging/ffa/libsp/ffa.c
+++ b/components/messaging/ffa/libsp/ffa.c
@@ -238,6 +238,41 @@
return FFA_OK;
}
+static void handle_framework_msg(struct ffa_params *result)
+{
+ if (result->a0 == FFA_INTERRUPT) {
+ ffa_interrupt_handler(result->a2);
+ ffa_return_from_interrupt(result);
+ } else if (result->a0 == FFA_MSG_SEND_DIRECT_REQ_32 && FFA_IS_FRAMEWORK_MSG(result->a2)) {
+ ffa_result res = FFA_OK;
+ uint16_t src_id = result->a1 >> 16;
+ uint16_t dst_id = result->a1;
+ uint64_t handle = reg_pair_to_64(result->a4, result->a3);
+ uint16_t vm_id = result->a5;
+
+ switch (result->a2 & FFA_FRAMEWORK_MSG_TYPE_MASK) {
+ case FFA_FRAMEWORK_MSG_VM_CREATED:
+ res = ffa_vm_created_handler(vm_id, handle);
+ ffa_svc(FFA_MSG_SEND_DIRECT_RESP_32, ((uint32_t)dst_id << 16) | src_id,
+ FFA_MSG_FLAG_FRAMEWORK | FFA_FRAMEWORK_MSG_VM_CREATED_ACK,
+ (uint64_t)res, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
+ FFA_PARAM_MBZ, result);
+ break;
+ case FFA_FRAMEWORK_MSG_VM_DESTROYED:
+ res = ffa_vm_destroyed_handler(vm_id, handle);
+ ffa_svc(FFA_MSG_SEND_DIRECT_RESP_32, ((uint32_t)dst_id << 16) | src_id,
+ FFA_MSG_FLAG_FRAMEWORK | FFA_FRAMEWORK_MSG_VM_DESTROYED_ACK,
+ (uint64_t)res, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
+ FFA_PARAM_MBZ, result);
+ break;
+ default:
+ ffa_svc(FFA_ERROR, FFA_PARAM_MBZ, FFA_INVALID_PARAMETERS, FFA_PARAM_MBZ,
+ FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, result);
+ break;
+ }
+ }
+}
+
ffa_result ffa_msg_wait(struct ffa_direct_msg *msg)
{
struct ffa_params result = {0};
@@ -246,9 +281,10 @@
FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
&result);
- while (result.a0 == FFA_INTERRUPT) {
- ffa_interrupt_handler(result.a2);
- ffa_return_from_interrupt(&result);
+ /* FF-A framework messages are handled outside of the main partition message handler loop */
+ while ((result.a0 == FFA_INTERRUPT) ||
+ (result.a0 == FFA_MSG_SEND_DIRECT_REQ_32 && FFA_IS_FRAMEWORK_MSG(result.a2))) {
+ handle_framework_msg(&result);
}
if (result.a0 == FFA_ERROR) {
@@ -325,9 +361,10 @@
SHIFT_U32(source, FFA_MSG_SEND_DIRECT_RESP_SOURCE_ID_SHIFT) |
dest, FFA_PARAM_MBZ, a0, a1, a2, a3, a4, &result);
- while (result.a0 == FFA_INTERRUPT) {
- ffa_interrupt_handler(result.a2);
- ffa_return_from_interrupt(&result);
+ /* FF-A framework messages are handled outside of the main partition message handler loop */
+ while ((result.a0 == FFA_INTERRUPT) ||
+ (result.a0 == FFA_MSG_SEND_DIRECT_REQ_32 && FFA_IS_FRAMEWORK_MSG(result.a2))) {
+ handle_framework_msg(&result);
}
if (result.a0 == FFA_ERROR) {
diff --git a/components/messaging/ffa/libsp/include/ffa_api.h b/components/messaging/ffa/libsp/include/ffa_api.h
index 82541f7..2175d8f 100644
--- a/components/messaging/ffa/libsp/include/ffa_api.h
+++ b/components/messaging/ffa/libsp/include/ffa_api.h
@@ -412,6 +412,28 @@
*/
void ffa_interrupt_handler(uint32_t interrupt_id);
+/**
+ * @brief VM created message handler prototype. Must be implemented by
+ * another component.
+ *
+ * @param[in] vm_id ID of VM that has been created
+ * @param[in] handle Globally unique Handle to identify a memory region that
+ * contains information associated with the created VM
+ * @return The FF-A error status code
+ */
+ffa_result ffa_vm_created_handler(uint16_t vm_id, uint64_t handle);
+
+/**
+ * @brief VM destroyed message handler prototype. Must be implemented by
+ * another component.
+ *
+ * @param[in] vm_id ID of VM that has been destroyed
+ * @param[in] handle Globally unique Handle to identify a memory region that
+ * contains information associated with the destroyed VM
+ * @return The FF-A error status code
+ */
+ffa_result ffa_vm_destroyed_handler(uint16_t vm_id, uint64_t handle);
+
#ifdef __cplusplus
}
#endif
diff --git a/components/messaging/ffa/libsp/include/ffa_api_defines.h b/components/messaging/ffa/libsp/include/ffa_api_defines.h
index a007749..23389a5 100644
--- a/components/messaging/ffa/libsp/include/ffa_api_defines.h
+++ b/components/messaging/ffa/libsp/include/ffa_api_defines.h
@@ -195,6 +195,17 @@
#define FFA_MSG_SEND_DIRECT_RESP_DEST_ID_MASK GENMASK_32(15, 0)
#define FFA_MSG_SEND_DIRECT_RESP_DEST_ID_SHIFT UINT32_C(0)
+/* FF-A direct message flags */
+#define FFA_MSG_FLAG_FRAMEWORK BIT32(31)
+#define FFA_FRAMEWORK_MSG_TYPE_SHIFT UINT32_C(0)
+#define FFA_FRAMEWORK_MSG_TYPE_MASK GENMASK_32(7, 0)
+#define FFA_FRAMEWORK_MSG_PSCI UINT32_C(0x0)
+#define FFA_FRAMEWORK_MSG_VM_CREATED UINT32_C(0x4)
+#define FFA_FRAMEWORK_MSG_VM_CREATED_ACK UINT32_C(0x5)
+#define FFA_FRAMEWORK_MSG_VM_DESTROYED UINT32_C(0x6)
+#define FFA_FRAMEWORK_MSG_VM_DESTROYED_ACK UINT32_C(0x7)
+#define FFA_IS_FRAMEWORK_MSG(x) (((x) & FFA_MSG_FLAG_FRAMEWORK) != 0)
+
/* Table 5.15: Memory access permissions descriptor */
/* Memory access permissions */
diff --git a/components/messaging/ffa/libsp/test/test_ffa_api.cpp b/components/messaging/ffa/libsp/test/test_ffa_api.cpp
index 3c51e60..9660599 100644
--- a/components/messaging/ffa/libsp/test/test_ffa_api.cpp
+++ b/components/messaging/ffa/libsp/test/test_ffa_api.cpp
@@ -23,6 +23,38 @@
.withUnsignedIntParameter("id", id);
}
+void expect_ffa_vm_created_handler(uint16_t vm_id, uint64_t handle, ffa_result result)
+{
+ mock().expectOneCall("ffa_vm_created_handler")
+ .withUnsignedIntParameter("vm_id", vm_id)
+ .withUnsignedLongIntParameter("handle", handle)
+ .andReturnValue(result);
+}
+
+ffa_result ffa_vm_created_handler(uint16_t vm_id, uint64_t handle)
+{
+ return mock().actualCall("ffa_vm_created_handler")
+ .withUnsignedIntParameter("vm_id", vm_id)
+ .withUnsignedLongIntParameter("handle", handle)
+ .returnIntValue();
+}
+
+void expect_ffa_vm_destroyed_handler(uint16_t vm_id, uint64_t handle, ffa_result result)
+{
+ mock().expectOneCall("ffa_vm_destroyed_handler")
+ .withUnsignedIntParameter("vm_id", vm_id)
+ .withUnsignedLongIntParameter("handle", handle)
+ .andReturnValue(result);
+}
+
+ffa_result ffa_vm_destroyed_handler(uint16_t vm_id, uint64_t handle)
+{
+ return mock().actualCall("ffa_vm_destroyed_handler")
+ .withUnsignedIntParameter("vm_id", vm_id)
+ .withUnsignedLongIntParameter("handle", handle)
+ .returnIntValue();
+}
+
TEST_GROUP(ffa_api)
{
TEST_SETUP()
@@ -551,6 +583,157 @@
msg_equal_32(0x84000061, 0, 0, 0, 0, 0, 0, 0);
}
+TEST(ffa_api, ffa_msg_wait_vm_created_success)
+{
+ const uint16_t source_id = 0;
+ const uint16_t dest_id = 0x8001;
+ const uint16_t vm_id = 0x1234;
+ const uint64_t handle = 0x0123456789abcdefULL;
+ const uint32_t handle_hi = 0x01234567;
+ const uint32_t handle_lo = 0x89abcdef;
+ struct ffa_params vm_created_msg;
+
+ vm_created_msg.a0 = 0x8400006F;
+ vm_created_msg.a1 = ((uint32_t)source_id << 16) | dest_id;
+ vm_created_msg.a2 = FFA_MSG_FLAG_FRAMEWORK |
+ (FFA_FRAMEWORK_MSG_VM_CREATED << FFA_FRAMEWORK_MSG_TYPE_SHIFT);
+ vm_created_msg.a3 = handle_lo;
+ vm_created_msg.a4 = handle_hi;
+ vm_created_msg.a5 = vm_id;
+ expect_ffa_svc(0x8400006B, 0, 0, 0, 0, 0, 0, 0, &vm_created_msg);
+ expect_ffa_vm_created_handler(vm_id, handle, FFA_OK);
+
+ svc_result.a0 = 0x84000061;
+ expect_ffa_svc(0x84000070, ((uint32_t)dest_id) << 16 | source_id, FFA_MSG_FLAG_FRAMEWORK |
+ (FFA_FRAMEWORK_MSG_VM_CREATED_ACK << FFA_FRAMEWORK_MSG_TYPE_SHIFT), 0, 0,
+ 0, 0, 0, &svc_result);
+
+ ffa_result result = ffa_msg_wait(&msg);
+ LONGS_EQUAL(0, result);
+ msg_equal_32(0x84000061, 0, 0, 0, 0, 0, 0, 0);
+}
+
+TEST(ffa_api, ffa_msg_wait_vm_destroyed_success)
+{
+ const uint16_t source_id = 0;
+ const uint16_t dest_id = 0x8001;
+ const uint16_t vm_id = 0x1234;
+ const uint64_t handle = 0x0123456789abcdefULL;
+ const uint32_t handle_hi = 0x01234567;
+ const uint32_t handle_lo = 0x89abcdef;
+ struct ffa_params vm_destroyed_msg;
+
+ vm_destroyed_msg.a0 = 0x8400006F;
+ vm_destroyed_msg.a1 = ((uint32_t)source_id << 16) | dest_id;
+ vm_destroyed_msg.a2 = FFA_MSG_FLAG_FRAMEWORK |
+ (FFA_FRAMEWORK_MSG_VM_DESTROYED << FFA_FRAMEWORK_MSG_TYPE_SHIFT);
+ vm_destroyed_msg.a3 = handle_lo;
+ vm_destroyed_msg.a4 = handle_hi;
+ vm_destroyed_msg.a5 = vm_id;
+ expect_ffa_svc(0x8400006B, 0, 0, 0, 0, 0, 0, 0, &vm_destroyed_msg);
+ expect_ffa_vm_destroyed_handler(vm_id, handle, FFA_OK);
+
+ svc_result.a0 = 0x84000061;
+ expect_ffa_svc(0x84000070, ((uint32_t)dest_id) << 16 | source_id, FFA_MSG_FLAG_FRAMEWORK |
+ (FFA_FRAMEWORK_MSG_VM_DESTROYED_ACK << FFA_FRAMEWORK_MSG_TYPE_SHIFT), 0, 0,
+ 0, 0, 0, &svc_result);
+
+ ffa_result result = ffa_msg_wait(&msg);
+ LONGS_EQUAL(0, result);
+ msg_equal_32(0x84000061, 0, 0, 0, 0, 0, 0, 0);
+}
+
+TEST(ffa_api, ffa_msg_wait_vm_created_destroyed_success)
+{
+ const uint16_t source_id = 0;
+ const uint16_t dest_id = 0x8001;
+ const uint16_t vm_id = 0x1234;
+ const uint64_t handle = 0x0123456789abcdefULL;
+ const uint32_t handle_hi = 0x01234567;
+ const uint32_t handle_lo = 0x89abcdef;
+ struct ffa_params vm_created_msg;
+ struct ffa_params vm_destroyed_msg;
+
+ vm_created_msg.a0 = 0x8400006F;
+ vm_created_msg.a1 = ((uint32_t)source_id << 16) | dest_id;
+ vm_created_msg.a2 = FFA_MSG_FLAG_FRAMEWORK |
+ (FFA_FRAMEWORK_MSG_VM_CREATED << FFA_FRAMEWORK_MSG_TYPE_SHIFT);
+ vm_created_msg.a3 = handle_lo;
+ vm_created_msg.a4 = handle_hi;
+ vm_created_msg.a5 = vm_id;
+ expect_ffa_svc(0x8400006B, 0, 0, 0, 0, 0, 0, 0, &vm_created_msg);
+ expect_ffa_vm_created_handler(vm_id, handle, FFA_OK);
+
+ vm_destroyed_msg.a0 = 0x8400006F;
+ vm_destroyed_msg.a1 = ((uint32_t)source_id << 16) | dest_id;
+ vm_destroyed_msg.a2 = FFA_MSG_FLAG_FRAMEWORK |
+ (FFA_FRAMEWORK_MSG_VM_DESTROYED << FFA_FRAMEWORK_MSG_TYPE_SHIFT);
+ vm_destroyed_msg.a3 = handle_lo;
+ vm_destroyed_msg.a4 = handle_hi;
+ vm_destroyed_msg.a5 = vm_id;
+ expect_ffa_svc(0x84000070, ((uint32_t)dest_id) << 16 | source_id, FFA_MSG_FLAG_FRAMEWORK |
+ (FFA_FRAMEWORK_MSG_VM_CREATED_ACK << FFA_FRAMEWORK_MSG_TYPE_SHIFT), 0, 0,
+ 0, 0, 0, &vm_destroyed_msg);
+ expect_ffa_vm_destroyed_handler(vm_id, handle, FFA_OK);
+
+ svc_result.a0 = 0x84000061;
+ expect_ffa_svc(0x84000070, ((uint32_t)dest_id) << 16 | source_id, FFA_MSG_FLAG_FRAMEWORK |
+ (FFA_FRAMEWORK_MSG_VM_DESTROYED_ACK << FFA_FRAMEWORK_MSG_TYPE_SHIFT), 0, 0,
+ 0, 0, 0, &svc_result);
+ ffa_result result = ffa_msg_wait(&msg);
+ LONGS_EQUAL(0, result);
+ msg_equal_32(0x84000061, 0, 0, 0, 0, 0, 0, 0);
+}
+
+TEST(ffa_api, ffa_msg_wait_vm_created_interrupt_destroyed_success)
+{
+ const uint16_t source_id = 0;
+ const uint16_t dest_id = 0x8001;
+ const uint16_t vm_id = 0x1234;
+ const uint64_t handle = 0x0123456789abcdefULL;
+ const uint32_t handle_hi = 0x01234567;
+ const uint32_t handle_lo = 0x89abcdef;
+ const uint32_t interrupt_id = 0x12345678;
+ struct ffa_params vm_created_msg;
+ struct ffa_params vm_destroyed_msg;
+ struct ffa_params interrupt_params;
+
+ vm_created_msg.a0 = 0x8400006F;
+ vm_created_msg.a1 = ((uint32_t)source_id << 16) | dest_id;
+ vm_created_msg.a2 = FFA_MSG_FLAG_FRAMEWORK |
+ (FFA_FRAMEWORK_MSG_VM_CREATED << FFA_FRAMEWORK_MSG_TYPE_SHIFT);
+ vm_created_msg.a3 = handle_lo;
+ vm_created_msg.a4 = handle_hi;
+ vm_created_msg.a5 = vm_id;
+ expect_ffa_svc(0x8400006B, 0, 0, 0, 0, 0, 0, 0, &vm_created_msg);
+ expect_ffa_vm_created_handler(vm_id, handle, FFA_OK);
+
+ interrupt_params.a0 = 0x84000062;
+ interrupt_params.a2 = interrupt_id;
+ expect_ffa_svc(0x84000070, ((uint32_t)dest_id) << 16 | source_id, FFA_MSG_FLAG_FRAMEWORK |
+ (FFA_FRAMEWORK_MSG_VM_CREATED_ACK << FFA_FRAMEWORK_MSG_TYPE_SHIFT), 0, 0,
+ 0, 0, 0, &interrupt_params);
+ expect_ffa_interrupt_handler(interrupt_id);
+
+ vm_destroyed_msg.a0 = 0x8400006F;
+ vm_destroyed_msg.a1 = ((uint32_t)source_id << 16) | dest_id;
+ vm_destroyed_msg.a2 = FFA_MSG_FLAG_FRAMEWORK |
+ (FFA_FRAMEWORK_MSG_VM_DESTROYED << FFA_FRAMEWORK_MSG_TYPE_SHIFT);
+ vm_destroyed_msg.a3 = handle_lo;
+ vm_destroyed_msg.a4 = handle_hi;
+ vm_destroyed_msg.a5 = vm_id;
+ expect_ffa_svc(0x8400006B, 0, 0, 0, 0, 0, 0, 0, &vm_destroyed_msg);
+ expect_ffa_vm_destroyed_handler(vm_id, handle, FFA_OK);
+
+ svc_result.a0 = 0x84000061;
+ expect_ffa_svc(0x84000070, ((uint32_t)dest_id) << 16 | source_id, FFA_MSG_FLAG_FRAMEWORK |
+ (FFA_FRAMEWORK_MSG_VM_DESTROYED_ACK << FFA_FRAMEWORK_MSG_TYPE_SHIFT), 0, 0,
+ 0, 0, 0, &svc_result);
+ ffa_result result = ffa_msg_wait(&msg);
+ LONGS_EQUAL(0, result);
+ msg_equal_32(0x84000061, 0, 0, 0, 0, 0, 0, 0);
+}
+
TEST(ffa_api, ffa_msg_wait_unknown_response)
{
assert_environment_t assert_env;
@@ -1046,6 +1229,43 @@
msg_equal_32(0x84000061, 0, 0, 0, 0, 0, 0, 0);
}
+TEST(ffa_api, ffa_msg_send_direct_resp_32_vm_created_success)
+{
+ const uint16_t source_id = 0x1122;
+ const uint16_t dest_id = 0x3344;
+ const uint16_t nwd_id = 0;
+ const uint32_t arg0 = 0x01234567ULL;
+ const uint32_t arg1 = 0x12345678ULL;
+ const uint32_t arg2 = 0x23456789ULL;
+ const uint32_t arg3 = 0x3456789aULL;
+ const uint32_t arg4 = 0x456789abULL;
+ const uint16_t vm_id = 0x1234;
+ const uint64_t handle = 0x0123456789abcdefULL;
+ const uint32_t handle_hi = 0x01234567;
+ const uint32_t handle_lo = 0x89abcdef;
+ struct ffa_params vm_created_msg;
+
+ vm_created_msg.a0 = 0x8400006F;
+ vm_created_msg.a1 = ((uint32_t)nwd_id << 16) | source_id;
+ vm_created_msg.a2 = FFA_MSG_FLAG_FRAMEWORK |
+ (FFA_FRAMEWORK_MSG_VM_CREATED << FFA_FRAMEWORK_MSG_TYPE_SHIFT);
+ vm_created_msg.a3 = handle_lo;
+ vm_created_msg.a4 = handle_hi;
+ vm_created_msg.a5 = vm_id;
+ expect_ffa_svc(0x84000070, ((uint32_t)source_id << 16) | dest_id, 0,
+ arg0, arg1, arg2, arg3, arg4, &vm_created_msg);
+ expect_ffa_vm_created_handler(vm_id, handle, FFA_OK);
+
+ svc_result.a0 = 0x84000061;
+ expect_ffa_svc(0x84000070, ((uint32_t)source_id) << 16 | nwd_id, FFA_MSG_FLAG_FRAMEWORK |
+ (FFA_FRAMEWORK_MSG_VM_CREATED_ACK << FFA_FRAMEWORK_MSG_TYPE_SHIFT), 0, 0,
+ 0, 0, 0, &svc_result);
+ ffa_result result = ffa_msg_send_direct_resp_32(
+ source_id, dest_id, arg0, arg1, arg2, arg3, arg4, &msg);
+ LONGS_EQUAL(0, result);
+ msg_equal_32(0x84000061, 0, 0, 0, 0, 0, 0, 0);
+}
+
TEST(ffa_api, ffa_msg_send_direct_resp_32_unknown_response)
{
const uint16_t source_id = 0x1122;
diff --git a/components/service/spm_test/sp.c b/components/service/spm_test/sp.c
index 37aa939..fce494a 100644
--- a/components/service/spm_test/sp.c
+++ b/components/service/spm_test/sp.c
@@ -1116,3 +1116,19 @@
(void)interrupt_id;
DMSG("Got interrupt %x", interrupt_id);
}
+
+ffa_result ffa_vm_created_handler(uint16_t vm_id, uint64_t handle)
+{
+ (void)handle;
+ DMSG("VM with ID %d created", vm_id);
+
+ return FFA_OK;
+}
+
+ffa_result ffa_vm_destroyed_handler(uint16_t vm_id, uint64_t handle)
+{
+ (void)handle;
+ DMSG("VM with ID %d destroyed", vm_id);
+
+ return FFA_OK;
+}