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)
{