feat(notifications): get framework notifications
Get framework notifications in FFA_NOTIFICATION_GET handler. If flag
for SPM notifications is set:
- SPMC returns SPM framework notifications set for the receiver VM.
- Hypervisor forwards call to SPMC.
If flag for Hypervisor notifications is set:
- SPMC returns Hypervisor framework notifications set for the VM;
- Hypervisor retrieves Hypervisor framework notifications set in the
SPMC and merge with its own bitmap.
Change-Id: If371accc35bf2bd6e0425fadd5e1901286eaadc4
Signed-off-by: J-Alves <joao.alves@arm.com>
Signed-off-by: Federico Recanati <federico.recanati@arm.com>
diff --git a/src/api.c b/src/api.c
index 79095f9..7424b24 100644
--- a/src/api.c
+++ b/src/api.c
@@ -3233,6 +3233,18 @@
receiver_locked, true, vcpu_id);
}
+ if ((flags & FFA_NOTIFICATION_FLAG_BITMAP_HYP) != 0U ||
+ (flags & FFA_NOTIFICATION_FLAG_BITMAP_SPM) != 0U) {
+ if (!plat_ffa_notifications_get_framework_notifications(
+ receiver_locked, &framework_notifications, flags,
+ vcpu_id, &ret)) {
+ dlog_verbose(
+ "Failed to get notifications from "
+ "framework.\n");
+ goto out;
+ }
+ }
+
ret = api_ffa_notification_get_success_return(
sp_notifications, vm_notifications, framework_notifications);
diff --git a/src/arch/aarch64/plat/ffa/absent.c b/src/arch/aarch64/plat/ffa/absent.c
index acd3eda..ca8a080 100644
--- a/src/arch/aarch64/plat/ffa/absent.c
+++ b/src/arch/aarch64/plat/ffa/absent.c
@@ -205,6 +205,19 @@
return false;
}
+bool plat_ffa_notifications_get_framework_notifications(
+ struct vm_locked receiver_locked,
+ ffa_notifications_bitmap_t *from_fwk, // NOLINT
+ uint32_t flags, struct ffa_value *ret)
+{
+ (void)receiver_locked;
+ (void)from_fwk;
+ (void)flags;
+ (void)ret;
+
+ 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,
diff --git a/src/arch/aarch64/plat/ffa/hypervisor.c b/src/arch/aarch64/plat/ffa/hypervisor.c
index 995d322..cd473fd 100644
--- a/src/arch/aarch64/plat/ffa/hypervisor.c
+++ b/src/arch/aarch64/plat/ffa/hypervisor.c
@@ -502,10 +502,10 @@
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;
+ assert(from_sp != NULL && ret != NULL);
+
*ret = arch_other_world_call((struct ffa_value){
.func = FFA_NOTIFICATION_GET_32,
.arg1 = (vcpu_id << 16) | receiver_id,
@@ -521,6 +521,40 @@
return true;
}
+bool plat_ffa_notifications_get_framework_notifications(
+ struct vm_locked receiver_locked, ffa_notifications_bitmap_t *from_fwk,
+ uint32_t flags, ffa_vcpu_index_t vcpu_id, struct ffa_value *ret)
+{
+ ffa_vm_id_t receiver_id = receiver_locked.vm->id;
+ ffa_notifications_bitmap_t spm_notifications = 0;
+
+ (void)flags;
+
+ assert(from_fwk != NULL);
+ assert(ret != NULL);
+
+ /* Get SPMC notifications. */
+ if (ffa_tee_enabled) {
+ *ret = arch_other_world_call((struct ffa_value){
+ .func = FFA_NOTIFICATION_GET_32,
+ .arg1 = (vcpu_id << 16) | receiver_id,
+ .arg2 = FFA_NOTIFICATION_FLAG_BITMAP_SPM,
+ });
+
+ if (ffa_func_id(*ret) == FFA_ERROR_32) {
+ return false;
+ }
+
+ spm_notifications = ffa_notification_get_from_framework(*ret);
+ }
+
+ /* Merge notifications from SPMC and Hypervisor. */
+ *from_fwk = spm_notifications |
+ vm_notifications_framework_get_pending(receiver_locked);
+
+ return true;
+}
+
bool plat_ffa_vm_notifications_info_get( // NOLINTNEXTLINE
uint16_t *ids, uint32_t *ids_count, // NOLINTNEXTLINE
uint32_t *lists_sizes, // NOLINTNEXTLINE
diff --git a/src/arch/aarch64/plat/ffa/spmc.c b/src/arch/aarch64/plat/ffa/spmc.c
index 77bdbe7..e8bcfc8 100644
--- a/src/arch/aarch64/plat/ffa/spmc.c
+++ b/src/arch/aarch64/plat/ffa/spmc.c
@@ -660,6 +660,29 @@
return true;
}
+bool plat_ffa_notifications_get_framework_notifications(
+ struct vm_locked receiver_locked, ffa_notifications_bitmap_t *from_fwk,
+ uint32_t flags, ffa_vcpu_index_t vcpu_id, struct ffa_value *ret)
+{
+ assert(from_fwk != NULL);
+ assert(ret != NULL);
+
+ (void)vcpu_id;
+
+ if (!vm_id_is_current_world(receiver_locked.vm->id) &&
+ (flags & FFA_NOTIFICATION_FLAG_BITMAP_HYP) != 0U) {
+ dlog_error(
+ "Notification get flag from hypervisor in call to SPMC "
+ "MBZ.\n");
+ *ret = ffa_error(FFA_INVALID_PARAMETERS);
+ return false;
+ }
+
+ *from_fwk = vm_notifications_framework_get_pending(receiver_locked);
+
+ 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 2f54c71..a18b34d 100644
--- a/src/arch/fake/hypervisor/ffa.c
+++ b/src/arch/fake/hypervisor/ffa.c
@@ -207,6 +207,20 @@
return false;
}
+bool plat_ffa_notifications_get_framework_notifications(
+ struct vm_locked receiver_locked,
+ ffa_notifications_bitmap_t *from_fwk, // NOLINT
+ uint32_t flags, ffa_vcpu_index_t vcpu_id, struct ffa_value *ret)
+{
+ (void)receiver_locked;
+ (void)from_fwk;
+ (void)flags;
+ (void)vcpu_id;
+ (void)ret;
+
+ 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,