feat(notifications): forward notification set to SPMC

Hypervisor forwards FFA_NOTIFICATION_SET to the SPMC, if receiver is an
SP.

Change-Id: I22ae458ee5906aaa728433f9d06a02dac66801d4
Signed-off-by: J-Alves <joao.alves@arm.com>
diff --git a/src/api.c b/src/api.c
index 27189e9..d3df341 100644
--- a/src/api.c
+++ b/src/api.c
@@ -2699,6 +2699,11 @@
 		return ffa_error(FFA_INVALID_PARAMETERS);
 	}
 
+	if (plat_ffa_notification_set_forward(sender_vm_id, receiver_vm_id,
+					      flags, notifications, &ret)) {
+		return ret;
+	}
+
 	/*
 	 * This check assumes receiver is the current VM, and has been enforced
 	 * by 'plat_ffa_is_notification_set_valid'.
@@ -2710,11 +2715,6 @@
 		return ffa_error(FFA_INVALID_PARAMETERS);
 	}
 
-	/*
-	 * TODO: Forward Hypervisor's call to SWd if setting SP's notifications
-	 * from VMs.
-	 */
-
 	if (!vm_are_notifications_enabled(receiver_locked)) {
 		dlog_verbose("Receiver's notifications not enabled.\n");
 		ret = ffa_error(FFA_DENIED);
diff --git a/src/arch/aarch64/plat/ffa/absent.c b/src/arch/aarch64/plat/ffa/absent.c
index 950a409..44d5a70 100644
--- a/src/arch/aarch64/plat/ffa/absent.c
+++ b/src/arch/aarch64/plat/ffa/absent.c
@@ -156,6 +156,21 @@
 	return false;
 }
 
+bool plat_ffa_notification_set_forward(ffa_vm_id_t sender_vm_id,
+				       ffa_vm_id_t receiver_vm_id,
+				       uint32_t flags,
+				       ffa_notifications_bitmap_t bitmap,
+				       struct ffa_value *ret)
+{
+	(void)sender_vm_id;
+	(void)receiver_vm_id;
+	(void)flags;
+	(void)bitmap;
+	(void)ret;
+
+	return false;
+}
+
 struct ffa_value plat_ffa_notifications_bitmap_create(
 	ffa_vm_id_t vm_id, ffa_vcpu_count_t vcpu_count)
 {
diff --git a/src/arch/aarch64/plat/ffa/hypervisor.c b/src/arch/aarch64/plat/ffa/hypervisor.c
index 90f9a3f..38e2217 100644
--- a/src/arch/aarch64/plat/ffa/hypervisor.c
+++ b/src/arch/aarch64/plat/ffa/hypervisor.c
@@ -271,6 +271,34 @@
 	return sender_id == current_vm_id && sender_id != receiver_id;
 }
 
+bool plat_ffa_notification_set_forward(ffa_vm_id_t sender_vm_id,
+				       ffa_vm_id_t receiver_vm_id,
+				       uint32_t flags,
+				       ffa_notifications_bitmap_t bitmap,
+				       struct ffa_value *ret)
+{
+	/* Forward only if receiver is an SP. */
+	if (vm_id_is_current_world(receiver_vm_id)) {
+		return false;
+	}
+
+	dlog_verbose("Forwarding notification set to SPMC.\n");
+
+	*ret = arch_other_world_call((struct ffa_value){
+		.func = FFA_NOTIFICATION_SET_32,
+		.arg1 = (sender_vm_id << 16) | receiver_vm_id,
+		.arg2 = flags,
+		.arg3 = (uint32_t)(bitmap),
+		.arg4 = (uint32_t)(bitmap >> 32),
+	});
+
+	if (ret->func == FFA_ERROR_32) {
+		dlog_verbose("Failed to set notifications from SPMC.\n");
+	}
+
+	return true;
+}
+
 bool plat_ffa_is_notification_get_valid(struct vcpu *current,
 					ffa_vm_id_t receiver_id)
 {
diff --git a/src/arch/aarch64/plat/ffa/spmc.c b/src/arch/aarch64/plat/ffa/spmc.c
index 31b04cc..6eae955 100644
--- a/src/arch/aarch64/plat/ffa/spmc.c
+++ b/src/arch/aarch64/plat/ffa/spmc.c
@@ -231,6 +231,21 @@
 		 vm_id_is_current_world(receiver_id)));
 }
 
+bool plat_ffa_notification_set_forward(ffa_vm_id_t sender_vm_id,
+				       ffa_vm_id_t receiver_vm_id,
+				       uint32_t flags,
+				       ffa_notifications_bitmap_t bitmap,
+				       struct ffa_value *ret)
+{
+	(void)sender_vm_id;
+	(void)receiver_vm_id;
+	(void)flags;
+	(void)bitmap;
+	(void)ret;
+
+	return false;
+}
+
 bool plat_ffa_is_notification_get_valid(struct vcpu *current,
 					ffa_vm_id_t receiver_id)
 {
diff --git a/src/arch/fake/hypervisor/ffa.c b/src/arch/fake/hypervisor/ffa.c
index 78c384b..5dbdc34 100644
--- a/src/arch/fake/hypervisor/ffa.c
+++ b/src/arch/fake/hypervisor/ffa.c
@@ -159,6 +159,21 @@
 	return false;
 }
 
+bool plat_ffa_notification_set_forward(ffa_vm_id_t sender_vm_id,
+				       ffa_vm_id_t receiver_vm_id,
+				       uint32_t flags,
+				       ffa_notifications_bitmap_t bitmap,
+				       struct ffa_value *ret)
+{
+	(void)sender_vm_id;
+	(void)receiver_vm_id;
+	(void)flags;
+	(void)bitmap;
+	(void)ret;
+
+	return false;
+}
+
 struct ffa_value plat_ffa_notifications_bitmap_create(
 	ffa_vm_id_t vm_id, ffa_vcpu_count_t vcpu_count)
 {