feat(notifications): notifications set and get

Handle FF-A calls FFA_NOTIFICATION_SET and FFA_NOTIFICATION_GET.
The former is used for a sender to signal a notification to the
receiver; the latter is for the receiver to get whichever notifications
there are pending.

Change-Id: I7e9db94201d0d78ceecd599cd350eeb37a8cb1f8
Signed-off-by: J-Alves <joao.alves@arm.com>
diff --git a/src/arch/aarch64/hypervisor/handler.c b/src/arch/aarch64/hypervisor/handler.c
index 9bcce55..9104028 100644
--- a/src/arch/aarch64/hypervisor/handler.c
+++ b/src/arch/aarch64/hypervisor/handler.c
@@ -615,6 +615,17 @@
 			ffa_notifications_bitmap(args->arg3, args->arg4), false,
 			current);
 		return true;
+	case FFA_NOTIFICATION_SET_32:
+		*args = api_ffa_notification_set(
+			ffa_sender(*args), ffa_receiver(*args), args->arg2,
+			ffa_notifications_bitmap(args->arg3, args->arg4),
+			current);
+		return true;
+	case FFA_NOTIFICATION_GET_32:
+		*args = api_ffa_notification_get(
+			ffa_notifications_get_receiver(*args),
+			ffa_notifications_get_vcpu(*args), args->arg2, current);
+		return true;
 	}
 
 	return false;
diff --git a/src/arch/aarch64/plat/ffa/absent.c b/src/arch/aarch64/plat/ffa/absent.c
index 1bfa115..0902bca 100644
--- a/src/arch/aarch64/plat/ffa/absent.c
+++ b/src/arch/aarch64/plat/ffa/absent.c
@@ -111,6 +111,24 @@
 	return false;
 }
 
+bool plat_ffa_is_notification_set_valid(struct vcpu *current,
+					ffa_vm_id_t sender_id,
+					ffa_vm_id_t receiver_id)
+{
+	(void)current;
+	(void)sender_id;
+	(void)receiver_id;
+	return false;
+}
+
+bool plat_ffa_is_notification_get_valid(struct vcpu *current,
+					ffa_vm_id_t receiver_id)
+{
+	(void)current;
+	(void)receiver_id;
+	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 14a057e..4f35c9f 100644
--- a/src/arch/aarch64/plat/ffa/hypervisor.c
+++ b/src/arch/aarch64/plat/ffa/hypervisor.c
@@ -240,6 +240,25 @@
 	return sender_id != receiver_id && current_vm_id == receiver_id;
 }
 
+bool plat_ffa_is_notification_set_valid(struct vcpu *current,
+					ffa_vm_id_t sender_id,
+					ffa_vm_id_t receiver_id)
+{
+	ffa_vm_id_t current_vm_id = current->vm->id;
+
+	/* If Hafnium is hypervisor, sender needs to be current vm. */
+	return sender_id == current_vm_id && sender_id != receiver_id;
+}
+
+bool plat_ffa_is_notification_get_valid(struct vcpu *current,
+					ffa_vm_id_t receiver_id)
+{
+	ffa_vm_id_t current_vm_id = current->vm->id;
+
+	/* If Hafnium is hypervisor, receiver needs to be current vm. */
+	return (current_vm_id == receiver_id);
+}
+
 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/spmc.c b/src/arch/aarch64/plat/ffa/spmc.c
index 531af10..5645f39 100644
--- a/src/arch/aarch64/plat/ffa/spmc.c
+++ b/src/arch/aarch64/plat/ffa/spmc.c
@@ -197,6 +197,40 @@
 		 vm_id_is_current_world(sender_id)));
 }
 
+bool plat_ffa_is_notification_set_valid(struct vcpu *current,
+					ffa_vm_id_t sender_id,
+					ffa_vm_id_t receiver_id)
+{
+	ffa_vm_id_t current_vm_id = current->vm->id;
+
+	/*
+	 * SPMC:
+	 * - If set call from SP, sender's ID must be the same as current.
+	 * - If set call from NWd, current VM ID must be same as Hypervisor ID,
+	 * and receiver must be an SP.
+	 */
+	return sender_id != receiver_id &&
+	       (sender_id == current_vm_id ||
+		(current_vm_id == HF_HYPERVISOR_VM_ID &&
+		 !vm_id_is_current_world(sender_id) &&
+		 vm_id_is_current_world(receiver_id)));
+}
+
+bool plat_ffa_is_notification_get_valid(struct vcpu *current,
+					ffa_vm_id_t receiver_id)
+{
+	ffa_vm_id_t current_vm_id = current->vm->id;
+
+	/*
+	 * SPMC:
+	 * - An SP can ask for its notifications, or the hypervisor can get
+	 *  notifications target to a VM.
+	 */
+	return (current_vm_id == receiver_id) ||
+	       (current_vm_id == HF_HYPERVISOR_VM_ID &&
+		!vm_id_is_current_world(receiver_id));
+}
+
 ffa_memory_handle_t plat_ffa_memory_handle_make(uint64_t index)
 {
 	return (index & ~FFA_MEMORY_HANDLE_ALLOCATOR_MASK) |
diff --git a/src/arch/fake/hypervisor/ffa.c b/src/arch/fake/hypervisor/ffa.c
index c423748..00a0005 100644
--- a/src/arch/fake/hypervisor/ffa.c
+++ b/src/arch/fake/hypervisor/ffa.c
@@ -114,6 +114,24 @@
 	return false;
 }
 
+bool plat_ffa_is_notification_set_valid(struct vcpu *current,
+					ffa_vm_id_t sender_id,
+					ffa_vm_id_t receiver_id)
+{
+	(void)current;
+	(void)sender_id;
+	(void)receiver_id;
+	return false;
+}
+
+bool plat_ffa_is_notification_get_valid(struct vcpu *current,
+					ffa_vm_id_t receiver_id)
+{
+	(void)current;
+	(void)receiver_id;
+	return false;
+}
+
 struct ffa_value plat_ffa_notifications_bitmap_create(
 	ffa_vm_id_t vm_id, ffa_vcpu_count_t vcpu_count)
 {