fix(notifications): flag that Must Be Zero
According to FF-A v1.1 EAC0 specification the bits [31:4] of the 'flags'
argument to the FFA_NOTIFICATION_GET ABI Must Be Zero.
Change-Id: I6381d9572eb8d7f7af700833c26ced59493a36b0
Signed-off-by: J-Alves <joao.alves@arm.com>
diff --git a/src/api.c b/src/api.c
index 55e7b81..e560f8b 100644
--- a/src/api.c
+++ b/src/api.c
@@ -3082,13 +3082,27 @@
ffa_notifications_bitmap_t vm_notifications = 0;
struct vm_locked receiver_locked;
struct ffa_value ret;
+ const uint32_t flags_mbz = ~(FFA_NOTIFICATION_FLAG_BITMAP_HYP |
+ FFA_NOTIFICATION_FLAG_BITMAP_SPM |
+ FFA_NOTIFICATION_FLAG_BITMAP_SP |
+ FFA_NOTIFICATION_FLAG_BITMAP_VM);
+
+ /* The FF-A v1.1 EAC0 specification states bits [31:4] Must Be Zero. */
+ if ((flags & flags_mbz) != 0U) {
+ dlog_verbose(
+ "Invalid flags bit(s) set in notifications get. [31:4] "
+ "MBZ(%x)\n",
+ flags);
+ return ffa_error(FFA_INVALID_PARAMETERS);
+ }
/*
- * Following check should capture wrong uses of the interface, depending
- * on whether Hafnium is SPMC or hypervisor.
- * On the rest of the function it is assumed this condition is met.
+ * Following check should capture wrong uses of the interface,
+ * depending on whether Hafnium is SPMC or hypervisor. On the
+ * rest of the function it is assumed this condition is met.
*/
- if (!plat_ffa_is_notification_get_valid(current, receiver_vm_id)) {
+ if (!plat_ffa_is_notification_get_valid(current, receiver_vm_id,
+ flags)) {
dlog_verbose("Invalid use of notifications get interface.\n");
return ffa_error(FFA_INVALID_PARAMETERS);
}
diff --git a/src/arch/aarch64/plat/ffa/absent.c b/src/arch/aarch64/plat/ffa/absent.c
index 8c0c27b..b7ce7df 100644
--- a/src/arch/aarch64/plat/ffa/absent.c
+++ b/src/arch/aarch64/plat/ffa/absent.c
@@ -170,8 +170,9 @@
}
bool plat_ffa_is_notification_get_valid(struct vcpu *current,
- ffa_vm_id_t receiver_id)
+ ffa_vm_id_t receiver_id, uint32_t flags)
{
+ (void)flags;
(void)current;
(void)receiver_id;
return false;
diff --git a/src/arch/aarch64/plat/ffa/hypervisor.c b/src/arch/aarch64/plat/ffa/hypervisor.c
index 6799535..7a7ec5e 100644
--- a/src/arch/aarch64/plat/ffa/hypervisor.c
+++ b/src/arch/aarch64/plat/ffa/hypervisor.c
@@ -365,10 +365,12 @@
}
bool plat_ffa_is_notification_get_valid(struct vcpu *current,
- ffa_vm_id_t receiver_id)
+ ffa_vm_id_t receiver_id, uint32_t flags)
{
ffa_vm_id_t current_vm_id = current->vm->id;
+ (void)flags;
+
/* If Hafnium is hypervisor, receiver needs to be current vm. */
return (current_vm_id == receiver_id);
}
diff --git a/src/arch/aarch64/plat/ffa/spmc.c b/src/arch/aarch64/plat/ffa/spmc.c
index a40f2d7..942cc0a 100644
--- a/src/arch/aarch64/plat/ffa/spmc.c
+++ b/src/arch/aarch64/plat/ffa/spmc.c
@@ -363,18 +363,29 @@
}
bool plat_ffa_is_notification_get_valid(struct vcpu *current,
- ffa_vm_id_t receiver_id)
+ ffa_vm_id_t receiver_id, uint32_t flags)
{
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));
+ bool caller_and_receiver_valid =
+ (current_vm_id == receiver_id) ||
+ (current_vm_id == HF_HYPERVISOR_VM_ID &&
+ !vm_id_is_current_world(receiver_id));
+
+ /*
+ * Flags field is not valid if NWd endpoint requests notifications from
+ * VMs or Hypervisor. Those are managed by the hypervisor if present.
+ */
+ bool flags_valid =
+ !(plat_ffa_is_vm_id(receiver_id) &&
+ ((flags & FFA_NOTIFICATION_FLAG_BITMAP_VM) != 0U ||
+ (flags & FFA_NOTIFICATION_FLAG_BITMAP_HYP) != 0U));
+
+ return caller_and_receiver_valid && flags_valid;
}
void plat_ffa_notification_info_get_forward( // NOLINTNEXTLINE
diff --git a/src/arch/fake/hypervisor/ffa.c b/src/arch/fake/hypervisor/ffa.c
index efd270b..f4bbd36 100644
--- a/src/arch/fake/hypervisor/ffa.c
+++ b/src/arch/fake/hypervisor/ffa.c
@@ -171,8 +171,9 @@
}
bool plat_ffa_is_notification_get_valid(struct vcpu *current,
- ffa_vm_id_t receiver_id)
+ ffa_vm_id_t receiver_id, uint32_t flags)
{
+ (void)flags;
(void)current;
(void)receiver_id;
return false;