feat(notifications): forward notification set to SPMC
Hypervisor forwards FFA_NOTIFICATION_SET to the SPMC, if receiver is an
SP.
Change-Id: I22ae458ee5906aaa728433f9d06a02dac66801d4
Signed-off-by: J-Alves <joao.alves@arm.com>
diff --git a/src/api.c b/src/api.c
index 27189e9..d3df341 100644
--- a/src/api.c
+++ b/src/api.c
@@ -2699,6 +2699,11 @@
return ffa_error(FFA_INVALID_PARAMETERS);
}
+ if (plat_ffa_notification_set_forward(sender_vm_id, receiver_vm_id,
+ flags, notifications, &ret)) {
+ return ret;
+ }
+
/*
* This check assumes receiver is the current VM, and has been enforced
* by 'plat_ffa_is_notification_set_valid'.
@@ -2710,11 +2715,6 @@
return ffa_error(FFA_INVALID_PARAMETERS);
}
- /*
- * TODO: Forward Hypervisor's call to SWd if setting SP's notifications
- * from VMs.
- */
-
if (!vm_are_notifications_enabled(receiver_locked)) {
dlog_verbose("Receiver's notifications not enabled.\n");
ret = ffa_error(FFA_DENIED);
diff --git a/src/arch/aarch64/plat/ffa/absent.c b/src/arch/aarch64/plat/ffa/absent.c
index 950a409..44d5a70 100644
--- a/src/arch/aarch64/plat/ffa/absent.c
+++ b/src/arch/aarch64/plat/ffa/absent.c
@@ -156,6 +156,21 @@
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,
+ ffa_notifications_bitmap_t bitmap,
+ struct ffa_value *ret)
+{
+ (void)sender_vm_id;
+ (void)receiver_vm_id;
+ (void)flags;
+ (void)bitmap;
+ (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 90f9a3f..38e2217 100644
--- a/src/arch/aarch64/plat/ffa/hypervisor.c
+++ b/src/arch/aarch64/plat/ffa/hypervisor.c
@@ -271,6 +271,34 @@
return sender_id == current_vm_id && sender_id != receiver_id;
}
+bool plat_ffa_notification_set_forward(ffa_vm_id_t sender_vm_id,
+ ffa_vm_id_t receiver_vm_id,
+ uint32_t flags,
+ ffa_notifications_bitmap_t bitmap,
+ struct ffa_value *ret)
+{
+ /* Forward only if receiver is an SP. */
+ if (vm_id_is_current_world(receiver_vm_id)) {
+ return false;
+ }
+
+ dlog_verbose("Forwarding notification set to SPMC.\n");
+
+ *ret = arch_other_world_call((struct ffa_value){
+ .func = FFA_NOTIFICATION_SET_32,
+ .arg1 = (sender_vm_id << 16) | receiver_vm_id,
+ .arg2 = flags,
+ .arg3 = (uint32_t)(bitmap),
+ .arg4 = (uint32_t)(bitmap >> 32),
+ });
+
+ if (ret->func == FFA_ERROR_32) {
+ dlog_verbose("Failed to set notifications from SPMC.\n");
+ }
+
+ return true;
+}
+
bool plat_ffa_is_notification_get_valid(struct vcpu *current,
ffa_vm_id_t receiver_id)
{
diff --git a/src/arch/aarch64/plat/ffa/spmc.c b/src/arch/aarch64/plat/ffa/spmc.c
index 31b04cc..6eae955 100644
--- a/src/arch/aarch64/plat/ffa/spmc.c
+++ b/src/arch/aarch64/plat/ffa/spmc.c
@@ -231,6 +231,21 @@
vm_id_is_current_world(receiver_id)));
}
+bool plat_ffa_notification_set_forward(ffa_vm_id_t sender_vm_id,
+ ffa_vm_id_t receiver_vm_id,
+ uint32_t flags,
+ ffa_notifications_bitmap_t bitmap,
+ struct ffa_value *ret)
+{
+ (void)sender_vm_id;
+ (void)receiver_vm_id;
+ (void)flags;
+ (void)bitmap;
+ (void)ret;
+
+ return false;
+}
+
bool plat_ffa_is_notification_get_valid(struct vcpu *current,
ffa_vm_id_t receiver_id)
{
diff --git a/src/arch/fake/hypervisor/ffa.c b/src/arch/fake/hypervisor/ffa.c
index 78c384b..5dbdc34 100644
--- a/src/arch/fake/hypervisor/ffa.c
+++ b/src/arch/fake/hypervisor/ffa.c
@@ -159,6 +159,21 @@
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,
+ ffa_notifications_bitmap_t bitmap,
+ struct ffa_value *ret)
+{
+ (void)sender_vm_id;
+ (void)receiver_vm_id;
+ (void)flags;
+ (void)bitmap;
+ (void)ret;
+
+ return false;
+}
+
struct ffa_value plat_ffa_notifications_bitmap_create(
ffa_vm_id_t vm_id, ffa_vcpu_count_t vcpu_count)
{