feat(notifications): information get interface
Handled FFA_NOTIFICATION_INFO_GET interface, to be used by a VM
(receiver's scheduler), Hypervisor or OS kernel.
Returns a list of IDs including Endpoints and vCPUs IDs that have
pending notifications. Provides support for multiple calls to the
FFA_NOTIFICATION_INFO_GET, in case there still are notifications whose
information needs to be retrieved after a call.
Change-Id: I4e73f18ee3301da4829313ffae247b6d0d262622
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 9104028..147c711 100644
--- a/src/arch/aarch64/hypervisor/handler.c
+++ b/src/arch/aarch64/hypervisor/handler.c
@@ -626,6 +626,9 @@
ffa_notifications_get_receiver(*args),
ffa_notifications_get_vcpu(*args), args->arg2, current);
return true;
+ case FFA_NOTIFICATION_INFO_GET_64:
+ *args = api_ffa_notification_info_get(current);
+ return true;
}
return false;
diff --git a/src/arch/aarch64/plat/ffa/absent.c b/src/arch/aarch64/plat/ffa/absent.c
index 0902bca..bb41c7b 100644
--- a/src/arch/aarch64/plat/ffa/absent.c
+++ b/src/arch/aarch64/plat/ffa/absent.c
@@ -166,3 +166,18 @@
return false;
}
+
+bool plat_ffa_vm_notifications_info_get(const uint16_t *ids,
+ const uint32_t *ids_count,
+ const uint32_t *lists_sizes,
+ const uint32_t *lists_count,
+ const uint32_t ids_count_max)
+{
+ (void)ids;
+ (void)ids_count;
+ (void)lists_sizes;
+ (void)lists_count;
+ (void)ids_count_max;
+
+ return false;
+}
diff --git a/src/arch/aarch64/plat/ffa/hypervisor.c b/src/arch/aarch64/plat/ffa/hypervisor.c
index 4f35c9f..158cd37 100644
--- a/src/arch/aarch64/plat/ffa/hypervisor.c
+++ b/src/arch/aarch64/plat/ffa/hypervisor.c
@@ -290,3 +290,18 @@
{
return vm_id_is_current_world(vm_id);
}
+
+bool plat_ffa_vm_notifications_info_get(const uint16_t *ids,
+ const uint32_t *ids_count,
+ const uint32_t *lists_sizes,
+ const uint32_t *lists_count,
+ const uint32_t ids_count_max)
+{
+ (void)ids;
+ (void)ids_count;
+ (void)lists_sizes;
+ (void)lists_count;
+ (void)ids_count_max;
+
+ return false;
+}
diff --git a/src/arch/aarch64/plat/ffa/spmc.c b/src/arch/aarch64/plat/ffa/spmc.c
index 5645f39..dded83c 100644
--- a/src/arch/aarch64/plat/ffa/spmc.c
+++ b/src/arch/aarch64/plat/ffa/spmc.c
@@ -446,3 +446,47 @@
{
return !vm_id_is_current_world(vm_id);
}
+
+bool plat_ffa_vm_notifications_info_get(uint16_t *ids, uint32_t *ids_count,
+ uint32_t *lists_sizes,
+ uint32_t *lists_count,
+ const uint32_t ids_count_max)
+{
+ enum notifications_info_get_state info_get_state = INIT;
+ struct nwd_vms_locked nwd_vms_locked = nwd_vms_lock();
+ struct vm_locked other_world_locked = vm_find_locked(HF_OTHER_WORLD_ID);
+
+ CHECK(other_world_locked.vm != NULL);
+
+ vm_notifications_info_get_pending(other_world_locked, false, ids,
+ ids_count, lists_sizes, lists_count,
+ ids_count_max, &info_get_state);
+
+ if (info_get_state == FULL) {
+ goto out;
+ }
+
+ vm_unlock(&other_world_locked);
+
+ for (unsigned int i = 0; i < nwd_vms_size; i++) {
+ info_get_state = INIT;
+
+ if (nwd_vms[i].id != HF_INVALID_VM_ID) {
+ struct vm_locked vm_locked = vm_lock(&nwd_vms[i]);
+
+ vm_notifications_info_get_pending(
+ vm_locked, false, ids, ids_count, lists_sizes,
+ lists_count, ids_count_max, &info_get_state);
+
+ if (info_get_state == FULL) {
+ goto out;
+ }
+
+ vm_unlock(&vm_locked);
+ }
+ }
+out:
+ nwd_vms_unlock(&nwd_vms_locked);
+
+ return info_get_state == FULL;
+}
diff --git a/src/arch/fake/hypervisor/ffa.c b/src/arch/fake/hypervisor/ffa.c
index 00a0005..6ea1dda 100644
--- a/src/arch/fake/hypervisor/ffa.c
+++ b/src/arch/fake/hypervisor/ffa.c
@@ -159,3 +159,18 @@
(void)vm_id;
return false;
}
+
+bool plat_ffa_vm_notifications_info_get(const uint16_t *ids,
+ const uint32_t *ids_count,
+ const uint32_t *lists_sizes,
+ const uint32_t *lists_count,
+ const uint32_t ids_count_max)
+{
+ (void)ids;
+ (void)ids_count;
+ (void)lists_sizes;
+ (void)lists_count;
+ (void)ids_count_max;
+
+ return false;
+}