feat(notifications): information get interface

Handled FFA_NOTIFICATION_INFO_GET interface, to be used by a VM
(receiver's scheduler), Hypervisor or OS kernel.
Returns a list of IDs including Endpoints and vCPUs IDs that have
pending notifications. Provides support for multiple calls to the
FFA_NOTIFICATION_INFO_GET, in case there still are notifications whose
information needs to be retrieved after a call.

Change-Id: I4e73f18ee3301da4829313ffae247b6d0d262622
Signed-off-by: J-Alves <joao.alves@arm.com>
diff --git a/inc/hf/api.h b/inc/hf/api.h
index 59755a4..46bd8f9 100644
--- a/inc/hf/api.h
+++ b/inc/hf/api.h
@@ -114,3 +114,5 @@
 struct ffa_value api_ffa_notification_get(ffa_vm_id_t receiver_vm_id,
 					  uint16_t vcpu_id, uint32_t flags,
 					  struct vcpu *current);
+
+struct ffa_value api_ffa_notification_info_get(struct vcpu *current);
diff --git a/inc/hf/arch/plat/ffa.h b/inc/hf/arch/plat/ffa.h
index bffc84d..2baf272 100644
--- a/inc/hf/arch/plat/ffa.h
+++ b/inc/hf/arch/plat/ffa.h
@@ -105,3 +105,10 @@
  */
 bool plat_ffa_run_forward(ffa_vm_id_t vm_id, ffa_vcpu_index_t vcpu_idx,
 			  struct ffa_value *ret);
+
+bool plat_ffa_notification_info_get_call(struct ffa_value *ret);
+
+bool plat_ffa_vm_notifications_info_get(uint16_t *ids, uint32_t *ids_count,
+					uint32_t *lists_sizes,
+					uint32_t *lists_count,
+					const uint32_t ids_count_max);
diff --git a/inc/hf/vm.h b/inc/hf/vm.h
index c9bbebc..928de40 100644
--- a/inc/hf/vm.h
+++ b/inc/hf/vm.h
@@ -123,6 +123,40 @@
 	struct notifications_state global;
 };
 
+/**
+ * The following enum relates to a state machine to guide the insertion of
+ * IDs in the respective list as a result of a FFA_NOTIFICATION_INFO_GET call.
+ * As per the FF-A v1.1 specification, the return of the interface
+ * FFA_NOTIFICATION_INFO_GET, is a list of 16-bit values, regarding the VM ID
+ * and VCPU IDs of those with pending notifications.
+ * The overall list, is composed of "sub-lists", that starts with the VM ID, and
+ * can follow with up to 3 more VCPU IDs. A VM can have multiple 'sub-lists'.
+ * The states are traversed on a per VM basis, and should help with filling the
+ * list of IDs.
+ *
+ * INIT is the initial state. The following state transitions are possible:
+ * * INIT => INSERTING: no list has been created for the VM prior. There are
+ * notifications pending and VM ID should be inserted first. If it regards to
+ * a per VCPU notification the VCPU ID should follow. Only VCPU IDs should be
+ * inserted from this point, until reaching "sub-list" size limit.
+ * * INIT => FULL: There is no space in the ID list to insert IDs.
+ * * INSERTING => STARTING_NEW: list has been created. Adding only VCPU IDs,
+ * however "sub-list" limit has been reached. If there are more pending per VCPU
+ * notifications pending for the VM, a new list should be created starting with
+ * VM ID.
+ * * INSERTING => FULL: There is no space in the ID list to insert IDs.
+ * * STARTING_NEW => INSERTING: Started a new 'sub-list' for the given VM, for
+ * the remaining pending per VCPU notifications, only the VCPU ID should be
+ * inserted.
+ * * STARTING_NEW => FULL: There is no space in the ID list to insert IDs.
+ */
+enum notifications_info_get_state {
+	INIT,
+	INSERTING,
+	STARTING_NEW,
+	FULL,
+};
+
 struct smc_whitelist {
 	uint32_t smcs[MAX_SMCS];
 	uint16_t smc_count;
@@ -253,3 +287,12 @@
 ffa_notifications_bitmap_t vm_notifications_get_pending_and_clear(
 	struct vm_locked vm_locked, bool is_from_vm,
 	ffa_vcpu_index_t cur_vcpu_id);
+void vm_notifications_info_get_pending(
+	struct vm_locked vm_locked, bool is_from_vm, uint16_t *ids,
+	uint32_t *ids_count, uint32_t *lists_sizes, uint32_t *lists_count,
+	const uint32_t ids_max_count,
+	enum notifications_info_get_state *info_get_state);
+bool vm_notifications_info_get(struct vm_locked vm_locked, uint16_t *ids,
+			       uint32_t *ids_count, uint32_t *lists_sizes,
+			       uint32_t *lists_count,
+			       const uint32_t ids_max_count);