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;
+}
diff --git a/deployments/attestation/env/commonsp/attestation_sp.c b/deployments/attestation/env/commonsp/attestation_sp.c
index 53b8f8e..d82c217 100644
--- a/deployments/attestation/env/commonsp/attestation_sp.c
+++ b/deployments/attestation/env/commonsp/attestation_sp.c
@@ -179,6 +179,22 @@
 	(void)interrupt_id;
 }
 
+ffa_result ffa_vm_created_handler(uint16_t vm_id, uint64_t handle)
+{
+	(void)vm_id;
+	(void)handle;
+
+	return FFA_OK;
+}
+
+ffa_result ffa_vm_destroyed_handler(uint16_t vm_id, uint64_t handle)
+{
+	(void)vm_id;
+	(void)handle;
+
+	return FFA_OK;
+}
+
 static bool sp_init(uint16_t *own_id)
 {
 	sp_result sp_res = SP_RESULT_INTERNAL_ERROR;
diff --git a/deployments/block-storage/env/commonsp/block_storage_sp.c b/deployments/block-storage/env/commonsp/block_storage_sp.c
index 8b0c1fd..9c2ab03 100644
--- a/deployments/block-storage/env/commonsp/block_storage_sp.c
+++ b/deployments/block-storage/env/commonsp/block_storage_sp.c
@@ -111,6 +111,22 @@
 	(void)interrupt_id;
 }
 
+ffa_result ffa_vm_created_handler(uint16_t vm_id, uint64_t handle)
+{
+	(void)vm_id;
+	(void)handle;
+
+	return FFA_OK;
+}
+
+ffa_result ffa_vm_destroyed_handler(uint16_t vm_id, uint64_t handle)
+{
+	(void)vm_id;
+	(void)handle;
+
+	return FFA_OK;
+}
+
 static bool sp_init(uint16_t *own_id)
 {
 	sp_result sp_res = SP_RESULT_INTERNAL_ERROR;
diff --git a/deployments/crypto/env/commonsp/crypto_sp.c b/deployments/crypto/env/commonsp/crypto_sp.c
index 7c84147..68c6f9d 100644
--- a/deployments/crypto/env/commonsp/crypto_sp.c
+++ b/deployments/crypto/env/commonsp/crypto_sp.c
@@ -137,6 +137,22 @@
 	(void)interrupt_id;
 }
 
+ffa_result ffa_vm_created_handler(uint16_t vm_id, uint64_t handle)
+{
+	(void)vm_id;
+	(void)handle;
+
+	return FFA_OK;
+}
+
+ffa_result ffa_vm_destroyed_handler(uint16_t vm_id, uint64_t handle)
+{
+	(void)vm_id;
+	(void)handle;
+
+	return FFA_OK;
+}
+
 static bool sp_init(uint16_t *own_id)
 {
 	sp_result sp_res = SP_RESULT_INTERNAL_ERROR;
diff --git a/deployments/env-test/env/commonsp/env_test_sp.c b/deployments/env-test/env/commonsp/env_test_sp.c
index daaf50a..5635a72 100644
--- a/deployments/env-test/env/commonsp/env_test_sp.c
+++ b/deployments/env-test/env/commonsp/env_test_sp.c
@@ -102,6 +102,22 @@
 	(void)interrupt_id;
 }
 
+ffa_result ffa_vm_created_handler(uint16_t vm_id, uint64_t handle)
+{
+	(void)vm_id;
+	(void)handle;
+
+	return FFA_OK;
+}
+
+ffa_result ffa_vm_destroyed_handler(uint16_t vm_id, uint64_t handle)
+{
+	(void)vm_id;
+	(void)handle;
+
+	return FFA_OK;
+}
+
 static bool sp_init(uint16_t *own_id)
 {
 	sp_result sp_res = SP_RESULT_INTERNAL_ERROR;
diff --git a/deployments/fwu/env/commonsp/fwu_sp.c b/deployments/fwu/env/commonsp/fwu_sp.c
index e3e0544..c9bf4b1 100644
--- a/deployments/fwu/env/commonsp/fwu_sp.c
+++ b/deployments/fwu/env/commonsp/fwu_sp.c
@@ -152,6 +152,22 @@
 	(void)interrupt_id;
 }
 
+ffa_result ffa_vm_created_handler(uint16_t vm_id, uint64_t handle)
+{
+	(void)vm_id;
+	(void)handle;
+
+	return FFA_OK;
+}
+
+ffa_result ffa_vm_destroyed_handler(uint16_t vm_id, uint64_t handle)
+{
+	(void)vm_id;
+	(void)handle;
+
+	return FFA_OK;
+}
+
 static bool sp_init(uint16_t *own_id)
 {
 	static uint8_t tx_buffer[4096] __aligned(4096);
diff --git a/deployments/internal-trusted-storage/env/commonsp/its_sp.c b/deployments/internal-trusted-storage/env/commonsp/its_sp.c
index 7bcae85..f123be7 100644
--- a/deployments/internal-trusted-storage/env/commonsp/its_sp.c
+++ b/deployments/internal-trusted-storage/env/commonsp/its_sp.c
@@ -110,3 +110,19 @@
 {
 	(void)interrupt_id;
 }
+
+ffa_result ffa_vm_created_handler(uint16_t vm_id, uint64_t handle)
+{
+	(void)vm_id;
+	(void)handle;
+
+	return FFA_OK;
+}
+
+ffa_result ffa_vm_destroyed_handler(uint16_t vm_id, uint64_t handle)
+{
+	(void)vm_id;
+	(void)handle;
+
+	return FFA_OK;
+}
diff --git a/deployments/logging/env/commonsp/logging_sp.c b/deployments/logging/env/commonsp/logging_sp.c
index af81d2c..03bbcfb 100644
--- a/deployments/logging/env/commonsp/logging_sp.c
+++ b/deployments/logging/env/commonsp/logging_sp.c
@@ -101,6 +101,22 @@
 	(void)interrupt_id;
 }
 
+ffa_result ffa_vm_created_handler(uint16_t vm_id, uint64_t handle)
+{
+	(void)vm_id;
+	(void)handle;
+
+	return FFA_OK;
+}
+
+ffa_result ffa_vm_destroyed_handler(uint16_t vm_id, uint64_t handle)
+{
+	(void)vm_id;
+	(void)handle;
+
+	return FFA_OK;
+}
+
 static bool sp_init(uint16_t *own_id)
 {
 	sp_result sp_res = SP_RESULT_INTERNAL_ERROR;
diff --git a/deployments/protected-storage/env/commonsp/ps_sp.c b/deployments/protected-storage/env/commonsp/ps_sp.c
index c43bccb..f88477b 100644
--- a/deployments/protected-storage/env/commonsp/ps_sp.c
+++ b/deployments/protected-storage/env/commonsp/ps_sp.c
@@ -110,3 +110,19 @@
 {
 	(void)interrupt_id;
 }
+
+ffa_result ffa_vm_created_handler(uint16_t vm_id, uint64_t handle)
+{
+	(void)vm_id;
+	(void)handle;
+
+	return FFA_OK;
+}
+
+ffa_result ffa_vm_destroyed_handler(uint16_t vm_id, uint64_t handle)
+{
+	(void)vm_id;
+	(void)handle;
+
+	return FFA_OK;
+}
diff --git a/deployments/se-proxy/env/commonsp/se_proxy_sp.c b/deployments/se-proxy/env/commonsp/se_proxy_sp.c
index 155e948..c7ae99e 100644
--- a/deployments/se-proxy/env/commonsp/se_proxy_sp.c
+++ b/deployments/se-proxy/env/commonsp/se_proxy_sp.c
@@ -126,6 +126,22 @@
 	(void)interrupt_id;
 }
 
+ffa_result ffa_vm_created_handler(uint16_t vm_id, uint64_t handle)
+{
+	(void)vm_id;
+	(void)handle;
+
+	return FFA_OK;
+}
+
+ffa_result ffa_vm_destroyed_handler(uint16_t vm_id, uint64_t handle)
+{
+	(void)vm_id;
+	(void)handle;
+
+	return FFA_OK;
+}
+
 static bool sp_init(uint16_t *own_id)
 {
 	sp_result sp_res = SP_RESULT_INTERNAL_ERROR;
diff --git a/deployments/smm-gateway/env/commonsp/smm_gateway_sp.c b/deployments/smm-gateway/env/commonsp/smm_gateway_sp.c
index bb2d0c3..9edc3c7 100644
--- a/deployments/smm-gateway/env/commonsp/smm_gateway_sp.c
+++ b/deployments/smm-gateway/env/commonsp/smm_gateway_sp.c
@@ -127,6 +127,22 @@
 	(void)interrupt_id;
 }
 
+ffa_result ffa_vm_created_handler(uint16_t vm_id, uint64_t handle)
+{
+	(void)vm_id;
+	(void)handle;
+
+	return FFA_OK;
+}
+
+ffa_result ffa_vm_destroyed_handler(uint16_t vm_id, uint64_t handle)
+{
+	(void)vm_id;
+	(void)handle;
+
+	return FFA_OK;
+}
+
 static bool sp_init(uint16_t *own_id)
 {
 	sp_result sp_res = SP_RESULT_INTERNAL_ERROR;