feat(notifications): notifications pending interrupt
This patch injects a notification pending interrupt (NPI) into the
vCPU of a receiver with pending notification:
- If notification is global the NPI is injected at context switch from
NWd to the receiver SP, at the vCPU that the scheduler gave CPU cycles
to the receiver.
- If the notification is per-vCPU the notification is injected at the
handling of FFA_NOTIFICATION_SET, into the core that is specified in
arguments of the call. It should be handled when the SP and the
respective vCPU is next executed by the scheduler.
Change-Id: Ic1232581b3861313e11c488be5091bf803a70f6a
Signed-off-by: J-Alves <joao.alves@arm.com>
diff --git a/src/vm.c b/src/vm.c
index e4bb2e1..47d4650 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -427,6 +427,13 @@
return mm_vm_get_mode(&vm_locked.vm->ptable, begin, end, mode);
}
+static struct notifications *vm_get_notifications(struct vm_locked vm_locked,
+ bool is_from_vm)
+{
+ return is_from_vm ? &vm_locked.vm->notifications.from_vm
+ : &vm_locked.vm->notifications.from_sp;
+}
+
/*
* Initializes the notifications structure.
*/
@@ -447,8 +454,7 @@
CHECK(vm_locked.vm != NULL);
- to_check = from_vm ? &vm_locked.vm->notifications.from_vm
- : &vm_locked.vm->notifications.from_sp;
+ to_check = vm_get_notifications(vm_locked, from_vm);
/* Check if there are pending per vcpu notifications */
for (uint32_t i = 0U; i < MAX_CPUS; i++) {
@@ -461,6 +467,33 @@
return (to_check->global.pending & notifications) != 0U;
}
+/**
+ * Checks if there are pending global notifications, either from SPs or from
+ * VMs.
+ */
+bool vm_are_global_notifications_pending(struct vm_locked vm_locked)
+{
+ return vm_get_notifications(vm_locked, true)->global.pending != 0ULL ||
+ vm_get_notifications(vm_locked, false)->global.pending != 0ULL;
+}
+
+/**
+ * Checks if there are pending per-vCPU notifications, in a specific vCPU either
+ * from SPs or from VMs.
+ */
+bool vm_are_per_vcpu_notifications_pending(struct vm_locked vm_locked,
+ ffa_vcpu_index_t vcpu_id)
+{
+ CHECK(vcpu_id < MAX_CPUS);
+
+ return vm_get_notifications(vm_locked, true)
+ ->per_vcpu[vcpu_id]
+ .pending != 0ULL ||
+ vm_get_notifications(vm_locked, false)
+ ->per_vcpu[vcpu_id]
+ .pending != 0ULL;
+}
+
bool vm_are_notifications_enabled(struct vm_locked vm_locked)
{
return vm_locked.vm->notifications.enabled == true;
@@ -472,13 +505,6 @@
return (notifications & FFA_NOTIFICATION_MASK(i)) != 0U;
}
-static struct notifications *vm_get_notifications(struct vm_locked vm_locked,
- bool is_from_vm)
-{
- return is_from_vm ? &vm_locked.vm->notifications.from_vm
- : &vm_locked.vm->notifications.from_sp;
-}
-
static void vm_notifications_global_state_count_update(
ffa_notifications_bitmap_t bitmap, uint32_t *counter, int inc)
{