refactor: implementation of HF_MAILBOX_*_GET interfaces

The interfaces HF_MAILBOX_WRITABLE_GET and HF_MAILBOX_WAITER_GET
are to accompany the FF-A v1.0 indirect message implementation.

This functionality is not used in the context of the SPMC,
hence factoring it out of common source files to SPMC
and hypervisor. This is now place in an hypervisor-specific
file.

Change-Id: I81332c286ad8a48fbe9a2425023d94ed7520fee8
Signed-off-by: J-Alves <joao.alves@arm.com>
diff --git a/inc/hf/arch/plat/ffa.h b/inc/hf/arch/plat/ffa.h
index b3a8669..7221dcd 100644
--- a/inc/hf/arch/plat/ffa.h
+++ b/inc/hf/arch/plat/ffa.h
@@ -376,3 +376,8 @@
 struct ffa_value plat_ffa_msg_recv(bool block,
 				   struct vcpu_locked current_locked,
 				   struct vcpu **next);
+
+int64_t plat_ffa_mailbox_writable_get(const struct vcpu *current);
+
+int64_t plat_ffa_mailbox_waiter_get(ffa_vm_id_t vm_id,
+				    const struct vcpu *current);
diff --git a/src/api.c b/src/api.c
index 8e5ef90..9494ffe 100644
--- a/src/api.c
+++ b/src/api.c
@@ -936,29 +936,6 @@
 	vcpu->regs_available = true;
 	sl_unlock(&vcpu->lock);
 }
-
-/**
- * Retrieves the next waiter and removes it from the wait list if the VM's
- * mailbox is in a writable state.
- */
-static struct wait_entry *api_fetch_waiter(struct vm_locked locked_vm)
-{
-	struct wait_entry *entry;
-	struct vm *vm = locked_vm.vm;
-
-	if (vm->mailbox.state != MAILBOX_STATE_EMPTY ||
-	    vm->mailbox.recv == NULL || list_empty(&vm->mailbox.waiter_list)) {
-		/* The mailbox is not writable or there are no waiters. */
-		return NULL;
-	}
-
-	/* Remove waiter from the wait list. */
-	entry = CONTAINER_OF(vm->mailbox.waiter_list.next, struct wait_entry,
-			     wait_links);
-	list_remove(&entry->wait_links);
-	return entry;
-}
-
 /**
  * Assuming that the arguments have already been checked by the caller, injects
  * a virtual interrupt of the given ID into the given target vCPU. This doesn't
@@ -2070,85 +2047,6 @@
 }
 
 /**
- * Retrieves the next VM whose mailbox became writable. For a VM to be notified
- * by this function, the caller must have called api_mailbox_send before with
- * the notify argument set to true, and this call must have failed because the
- * mailbox was not available.
- *
- * It should be called repeatedly to retrieve a list of VMs.
- *
- * Returns -1 if no VM became writable, or the id of the VM whose mailbox
- * became writable.
- */
-int64_t api_mailbox_writable_get(const struct vcpu *current)
-{
-	struct vm *vm = current->vm;
-	struct wait_entry *entry;
-	int64_t ret;
-
-	sl_lock(&vm->lock);
-	if (list_empty(&vm->mailbox.ready_list)) {
-		ret = -1;
-		goto exit;
-	}
-
-	entry = CONTAINER_OF(vm->mailbox.ready_list.next, struct wait_entry,
-			     ready_links);
-	list_remove(&entry->ready_links);
-	ret = vm_id_for_wait_entry(vm, entry);
-
-exit:
-	sl_unlock(&vm->lock);
-	return ret;
-}
-
-/**
- * Retrieves the next VM waiting to be notified that the mailbox of the
- * specified VM became writable. Only primary VMs are allowed to call this.
- *
- * Returns -1 on failure or if there are no waiters; the VM id of the next
- * waiter otherwise.
- */
-int64_t api_mailbox_waiter_get(ffa_vm_id_t vm_id, const struct vcpu *current)
-{
-	struct vm *vm;
-	struct vm_locked locked;
-	struct wait_entry *entry;
-	struct vm *waiting_vm;
-
-	/* Only primary VMs are allowed to call this function. */
-	if (current->vm->id != HF_PRIMARY_VM_ID) {
-		return -1;
-	}
-
-	vm = vm_find(vm_id);
-	if (vm == NULL) {
-		return -1;
-	}
-
-	/* Check if there are outstanding notifications from given VM. */
-	locked = vm_lock(vm);
-	entry = api_fetch_waiter(locked);
-	vm_unlock(&locked);
-
-	if (entry == NULL) {
-		return -1;
-	}
-
-	/* Enqueue notification to waiting VM. */
-	waiting_vm = entry->waiting_vm;
-
-	sl_lock(&waiting_vm->lock);
-	if (list_empty(&entry->ready_links)) {
-		list_append(&waiting_vm->mailbox.ready_list,
-			    &entry->ready_links);
-	}
-	sl_unlock(&waiting_vm->lock);
-
-	return waiting_vm->id;
-}
-
-/**
  * Releases the caller's mailbox so that a new message can be received. The
  * caller must have copied out all data they wish to preserve as new messages
  * will overwrite the old and will arrive asynchronously.
diff --git a/src/arch/aarch64/hypervisor/handler.c b/src/arch/aarch64/hypervisor/handler.c
index 83c59c1..31ccc83 100644
--- a/src/arch/aarch64/hypervisor/handler.c
+++ b/src/arch/aarch64/hypervisor/handler.c
@@ -591,6 +591,7 @@
 	case FFA_MSG_WAIT_32:
 		*args = api_ffa_msg_wait(current, next, args);
 		return true;
+#if SECURE_WORLD == 0
 	case FFA_MSG_POLL_32: {
 		struct vcpu_locked current_locked;
 
@@ -599,6 +600,7 @@
 		vcpu_unlock(&current_locked);
 		return true;
 	}
+#endif
 	case FFA_RUN_32:
 		*args = api_ffa_run(ffa_vm_id(*args), ffa_vcpu_index(*args),
 				    current, next);
@@ -1035,14 +1037,15 @@
 	}
 
 	switch (args.func) {
+#if SECURE_WORLD == 0
 	case HF_MAILBOX_WRITABLE_GET:
-		vcpu->regs.r[0] = api_mailbox_writable_get(vcpu);
+		vcpu->regs.r[0] = plat_ffa_mailbox_writable_get(vcpu);
 		break;
 
 	case HF_MAILBOX_WAITER_GET:
-		vcpu->regs.r[0] = api_mailbox_waiter_get(args.arg1, vcpu);
+		vcpu->regs.r[0] = plat_ffa_mailbox_waiter_get(args.arg1, vcpu);
 		break;
-
+#endif
 	case HF_INTERRUPT_ENABLE:
 		vcpu->regs.r[0] = api_interrupt_enable(args.arg1, args.arg2,
 						       args.arg3, vcpu);
diff --git a/src/arch/aarch64/plat/ffa/absent.c b/src/arch/aarch64/plat/ffa/absent.c
index e875f3c..dfae5cb 100644
--- a/src/arch/aarch64/plat/ffa/absent.c
+++ b/src/arch/aarch64/plat/ffa/absent.c
@@ -640,3 +640,17 @@
 {
 	return false;
 }
+
+int64_t plat_ffa_mailbox_waiter_get(ffa_vm_id_t vm_id,
+				    const struct vcpu *current)
+{
+	(void)vm_id;
+	(void)current;
+	return -1;
+}
+
+int64_t plat_ffa_mailbox_writable_get(const struct vcpu *current)
+{
+	(void)current;
+	return -1;
+}
diff --git a/src/arch/aarch64/plat/ffa/hypervisor.c b/src/arch/aarch64/plat/ffa/hypervisor.c
index 3b62b2b..878fed3 100644
--- a/src/arch/aarch64/plat/ffa/hypervisor.c
+++ b/src/arch/aarch64/plat/ffa/hypervisor.c
@@ -2310,3 +2310,106 @@
 	/* TODO: Interface not handled in hypervisor. */
 	return ffa_error(FFA_NOT_SUPPORTED);
 }
+
+/**
+ * Retrieves the next waiter and removes it from the wait list if the VM's
+ * mailbox is in a writable state.
+ */
+static struct wait_entry *plat_ffa_fetch_waiter(struct vm_locked locked_vm)
+{
+	struct wait_entry *entry;
+	struct vm *vm = locked_vm.vm;
+
+	if (vm->mailbox.state != MAILBOX_STATE_EMPTY ||
+	    vm->mailbox.recv == NULL || list_empty(&vm->mailbox.waiter_list)) {
+		/* The mailbox is not writable or there are no waiters. */
+		return NULL;
+	}
+
+	/* Remove waiter from the wait list. */
+	entry = CONTAINER_OF(vm->mailbox.waiter_list.next, struct wait_entry,
+			     wait_links);
+	list_remove(&entry->wait_links);
+	return entry;
+}
+
+/**
+ * Retrieves the next VM whose mailbox became writable. For a VM to be notified
+ * by this function, the caller must have called api_mailbox_send before with
+ * the notify argument set to true, and this call must have failed because the
+ * mailbox was not available.
+ *
+ * It should be called repeatedly to retrieve a list of VMs.
+ *
+ * Returns -1 if no VM became writable, or the id of the VM whose mailbox
+ * became writable.
+ */
+int64_t plat_ffa_mailbox_writable_get(const struct vcpu *current)
+{
+	struct vm *vm = current->vm;
+	struct wait_entry *entry;
+	int64_t ret;
+	struct vm_locked vm_locked = vm_lock(vm);
+
+	if (list_empty(&vm->mailbox.ready_list)) {
+		ret = -1;
+		goto exit;
+	}
+
+	entry = CONTAINER_OF(vm->mailbox.ready_list.next, struct wait_entry,
+			     ready_links);
+	list_remove(&entry->ready_links);
+	ret = vm_id_for_wait_entry(vm, entry);
+
+exit:
+	vm_unlock(&vm_locked);
+	return ret;
+}
+
+/**
+ * Retrieves the next VM waiting to be notified that the mailbox of the
+ * specified VM became writable. Only primary VMs are allowed to call this.
+ *
+ * Returns -1 on failure or if there are no waiters; the VM id of the next
+ * waiter otherwise.
+ */
+int64_t plat_ffa_mailbox_waiter_get(ffa_vm_id_t vm_id,
+				    const struct vcpu *current)
+{
+	struct vm *vm;
+	struct vm_locked locked;
+	struct vm_locked waiting_locked;
+	struct wait_entry *entry;
+	struct vm *waiting_vm;
+
+	/* Only primary VMs are allowed to call this function. */
+	if (current->vm->id != HF_PRIMARY_VM_ID) {
+		return -1;
+	}
+
+	vm = vm_find(vm_id);
+	if (vm == NULL) {
+		return -1;
+	}
+
+	/* Check if there are outstanding notifications from given VM. */
+	locked = vm_lock(vm);
+	entry = plat_ffa_fetch_waiter(locked);
+	vm_unlock(&locked);
+
+	if (entry == NULL) {
+		return -1;
+	}
+
+	/* Enqueue notification to waiting VM. */
+	waiting_vm = entry->waiting_vm;
+	waiting_locked = vm_lock(waiting_vm);
+
+	if (list_empty(&entry->ready_links)) {
+		list_append(&waiting_vm->mailbox.ready_list,
+			    &entry->ready_links);
+	}
+	vm_unlock(&waiting_locked);
+
+	return waiting_vm->id;
+}
diff --git a/src/arch/aarch64/plat/ffa/spmc.c b/src/arch/aarch64/plat/ffa/spmc.c
index 4f91e79..f21a5e6 100644
--- a/src/arch/aarch64/plat/ffa/spmc.c
+++ b/src/arch/aarch64/plat/ffa/spmc.c
@@ -2763,13 +2763,18 @@
 	return ret;
 }
 
-struct ffa_value plat_ffa_msg_recv(bool block,
-				   struct vcpu_locked current_locked,
-				   struct vcpu **next)
+int64_t plat_ffa_mailbox_waiter_get(ffa_vm_id_t vm_id,
+				    const struct vcpu *current)
 {
-	(void)block;
-	(void)current_locked;
-	(void)next;
+	(void)vm_id;
+	(void)current;
 
-	return ffa_error(FFA_NOT_SUPPORTED);
+	return -1;
+}
+
+int64_t plat_ffa_mailbox_writable_get(const struct vcpu *current)
+{
+	(void)current;
+
+	return -1;
 }
diff --git a/src/arch/fake/hypervisor/ffa.c b/src/arch/fake/hypervisor/ffa.c
index 702a35c..8374862 100644
--- a/src/arch/fake/hypervisor/ffa.c
+++ b/src/arch/fake/hypervisor/ffa.c
@@ -663,15 +663,20 @@
 	return ffa_error(FFA_NOT_SUPPORTED);
 }
 
-struct ffa_value plat_ffa_msg_recv(bool block,
-				   struct vcpu_locked current_locked,
-				   struct vcpu **next)
+int64_t plat_ffa_mailbox_waiter_get(ffa_vm_id_t vm_id,
+				    const struct vcpu *current)
 {
-	(void)block;
-	(void)current_locked;
-	(void)next;
+	(void)vm_id;
+	(void)current;
 
-	return ffa_error(FFA_NOT_SUPPORTED);
+	return -1;
+}
+
+int64_t plat_ffa_mailbox_writable_get(const struct vcpu *current)
+{
+	(void)current;
+
+	return -1;
 }
 
 bool plat_ffa_partition_info_get_regs_forward_allowed(void)