plat(ff-a): forward FFA_PARTITION_INFO_GET to SPMC
When a VM calls FFA_PARTITION_INFO_GET the Hypervisor looks up for the
passed UUID in the current list of VMs. If the UUID is unknown or NULL
then it forwards it to the SPMC to look up for the same UUID amongst
secure partitions.
Change-Id: I6ef9bf01da90ef18983e7bd8cb2ffbc90aa07ddc
Signed-off-by: Olivier Deprez <olivier.deprez@arm.com>
diff --git a/src/arch/aarch64/plat/ffa/absent.c b/src/arch/aarch64/plat/ffa/absent.c
index df0ccb2..7750cac 100644
--- a/src/arch/aarch64/plat/ffa/absent.c
+++ b/src/arch/aarch64/plat/ffa/absent.c
@@ -296,3 +296,12 @@
(void)next;
(void)current;
}
+
+bool plat_ffa_partition_info_get_forward(const struct ffa_uuid *uuid,
+ const ffa_vm_count_t *ret_count)
+{
+ (void)uuid;
+ (void)ret_count;
+
+ return false;
+}
diff --git a/src/arch/aarch64/plat/ffa/hypervisor.c b/src/arch/aarch64/plat/ffa/hypervisor.c
index 2cdc3cc..b5a2307 100644
--- a/src/arch/aarch64/plat/ffa/hypervisor.c
+++ b/src/arch/aarch64/plat/ffa/hypervisor.c
@@ -555,3 +555,61 @@
(void)next;
(void)current;
}
+
+/*
+ * Forward helper for FFA_PARTITION_INFO_GET.
+ * Emits FFA_PARTITION_INFO_GET from Hypervisor to SPMC if allowed.
+ */
+void plat_ffa_partition_info_get_forward(const struct ffa_uuid *uuid,
+ struct ffa_partition_info *partitions,
+ ffa_vm_count_t *ret_count)
+{
+ const struct vm *tee = vm_find(HF_TEE_VM_ID);
+ struct ffa_partition_info *tee_partitions;
+ ffa_vm_count_t tee_partitions_count;
+ ffa_vm_count_t vm_count = *ret_count;
+ struct ffa_value ret;
+
+ CHECK(tee != NULL);
+ CHECK(vm_count < MAX_VMS);
+
+ /*
+ * Allow forwarding from the Hypervisor if TEE or SPMC exists and
+ * declared as such in the Hypervisor manifest.
+ */
+ if (!ffa_tee_enabled) {
+ return;
+ }
+
+ ret = arch_other_world_call(
+ (struct ffa_value){.func = FFA_PARTITION_INFO_GET_32,
+ .arg1 = uuid->uuid[0],
+ .arg2 = uuid->uuid[1],
+ .arg3 = uuid->uuid[2],
+ .arg4 = uuid->uuid[3]});
+ if (ffa_func_id(ret) != FFA_SUCCESS_32) {
+ dlog_verbose(
+ "Failed forwarding FFA_PARTITION_INFO_GET to "
+ "the SPMC.\n");
+ return;
+ }
+
+ tee_partitions_count = ffa_partition_info_get_count(ret);
+ if (tee_partitions_count == 0 || tee_partitions_count > MAX_VMS) {
+ dlog_verbose("Invalid number of SPs returned by the SPMC.\n");
+ return;
+ }
+
+ tee_partitions = (struct ffa_partition_info *)tee->mailbox.send;
+ for (ffa_vm_count_t index = 0; index < tee_partitions_count; index++) {
+ partitions[vm_count] = tee_partitions[index];
+ ++vm_count;
+ }
+
+ /* Release the RX buffer. */
+ ret = arch_other_world_call(
+ (struct ffa_value){.func = FFA_RX_RELEASE_32});
+ CHECK(ret.func == FFA_SUCCESS_32);
+
+ *ret_count = vm_count;
+}
diff --git a/src/arch/aarch64/plat/ffa/spmc.c b/src/arch/aarch64/plat/ffa/spmc.c
index 128574c..f53d9c7 100644
--- a/src/arch/aarch64/plat/ffa/spmc.c
+++ b/src/arch/aarch64/plat/ffa/spmc.c
@@ -1216,3 +1216,15 @@
vm_unlock(&target_vm_locked);
}
}
+
+/** Forward helper for FFA_PARTITION_INFO_GET. */
+void plat_ffa_partition_info_get_forward( // NOLINTNEXTLINE
+ const struct ffa_uuid *uuid, // NOLINTNEXTLINE
+ struct ffa_partition_info *partitions, ffa_vm_count_t *ret_count)
+{
+ /* The SPMC does not forward FFA_PARTITION_INFO_GET. */
+
+ (void)uuid;
+ (void)partitions;
+ (void)ret_count;
+}
diff --git a/src/arch/fake/hypervisor/ffa.c b/src/arch/fake/hypervisor/ffa.c
index d9bfc8b..cadebee 100644
--- a/src/arch/fake/hypervisor/ffa.c
+++ b/src/arch/fake/hypervisor/ffa.c
@@ -283,3 +283,12 @@
(void)next;
(void)current;
}
+
+void plat_ffa_partition_info_get_forward( // NOLINTNEXTLINE
+ const struct ffa_uuid *uuid, // NOLINTNEXTLINE
+ struct ffa_partition_info *partitions, ffa_vm_count_t *ret_count)
+{
+ (void)uuid;
+ (void)partitions;
+ (void)ret_count;
+}