feat(notifications): get notifications from SPs
Handling the call FFA_NOTIFICATION_GET to retrieve pending notifications
from SPs:
- SPMC retrieves the pending notifications from the partition's bitmap
field;
- Hypervisor forwards the call to SPMC, analyzes the returned value
and populates its return to the VM.
Hypervisor case useful to test notifications full signaling flow from
NWd.
Change-Id: Icda45d0bca025a023c75ec2ceecf15d06c2456a0
Signed-off-by: J-Alves <joao.alves@arm.com>
diff --git a/src/api.c b/src/api.c
index 37a6ca9..27189e9 100644
--- a/src/api.c
+++ b/src/api.c
@@ -2809,12 +2809,12 @@
}
if ((flags & FFA_NOTIFICATION_FLAG_BITMAP_SP) != 0U) {
- /*
- * TODO: For hypervisor, forward call to SPMC to get VM's
- * notifications from SPs.
- */
- sp_notifications = vm_notifications_get_pending_and_clear(
- receiver_locked, false, vcpu_id);
+ if (!plat_ffa_notifications_get_from_sp(
+ receiver_locked, vcpu_id, &sp_notifications,
+ &ret)) {
+ dlog_verbose("Failed to get notifications from sps.");
+ goto out;
+ }
}
if ((flags & FFA_NOTIFICATION_FLAG_BITMAP_VM) != 0U) {
diff --git a/src/arch/aarch64/plat/ffa/absent.c b/src/arch/aarch64/plat/ffa/absent.c
index 6a27d69..950a409 100644
--- a/src/arch/aarch64/plat/ffa/absent.c
+++ b/src/arch/aarch64/plat/ffa/absent.c
@@ -144,6 +144,18 @@
return false;
}
+bool plat_ffa_notifications_get_from_sp(
+ struct vm_locked receiver_locked, ffa_vcpu_index_t vcpu_id,
+ const ffa_notifications_bitmap_t *from_sp, struct ffa_value *ret)
+{
+ (void)receiver_locked;
+ (void)vcpu_id;
+ (void)from_sp;
+ (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 350763b..90f9a3f 100644
--- a/src/arch/aarch64/plat/ffa/hypervisor.c
+++ b/src/arch/aarch64/plat/ffa/hypervisor.c
@@ -324,6 +324,30 @@
return vm_id_is_current_world(vm_id);
}
+bool plat_ffa_notifications_get_from_sp(struct vm_locked receiver_locked,
+ ffa_vcpu_index_t vcpu_id,
+ ffa_notifications_bitmap_t *from_sp,
+ struct ffa_value *ret)
+{
+ CHECK(from_sp != NULL && ret != NULL);
+
+ ffa_vm_id_t receiver_id = receiver_locked.vm->id;
+
+ *ret = arch_other_world_call((struct ffa_value){
+ .func = FFA_NOTIFICATION_GET_32,
+ .arg1 = (receiver_id << 16) | (vcpu_id),
+ .arg2 = FFA_NOTIFICATION_FLAG_BITMAP_SP,
+ });
+
+ if (ret->func == FFA_ERROR_32) {
+ return false;
+ }
+
+ *from_sp = ffa_notification_get_from_sp(*ret);
+
+ return true;
+}
+
bool plat_ffa_vm_notifications_info_get(const uint16_t *ids,
const uint32_t *ids_count,
const uint32_t *lists_sizes,
diff --git a/src/arch/aarch64/plat/ffa/spmc.c b/src/arch/aarch64/plat/ffa/spmc.c
index 817600c..31b04cc 100644
--- a/src/arch/aarch64/plat/ffa/spmc.c
+++ b/src/arch/aarch64/plat/ffa/spmc.c
@@ -471,6 +471,19 @@
return !vm_id_is_current_world(vm_id);
}
+bool plat_ffa_notifications_get_from_sp(struct vm_locked receiver_locked,
+ ffa_vcpu_index_t vcpu_id,
+ ffa_notifications_bitmap_t *from_sp,
+ struct ffa_value *ret)
+{
+ (void)ret;
+
+ *from_sp = vm_notifications_get_pending_and_clear(receiver_locked,
+ false, vcpu_id);
+
+ return true;
+}
+
bool plat_ffa_vm_notifications_info_get(uint16_t *ids, uint32_t *ids_count,
uint32_t *lists_sizes,
uint32_t *lists_count,
diff --git a/src/arch/fake/hypervisor/ffa.c b/src/arch/fake/hypervisor/ffa.c
index 4dd3fcd..78c384b 100644
--- a/src/arch/fake/hypervisor/ffa.c
+++ b/src/arch/fake/hypervisor/ffa.c
@@ -147,6 +147,18 @@
return false;
}
+bool plat_ffa_notifications_get_from_sp(
+ struct vm_locked receiver_locked, ffa_vcpu_index_t vcpu_id,
+ const ffa_notifications_bitmap_t *from_sp, struct ffa_value *ret)
+{
+ (void)receiver_locked;
+ (void)vcpu_id;
+ (void)from_sp;
+ (void)ret;
+
+ return false;
+}
+
struct ffa_value plat_ffa_notifications_bitmap_create(
ffa_vm_id_t vm_id, ffa_vcpu_count_t vcpu_count)
{