feat(FF-A): create ffa_init to prefetch the SPMC ID

Prefetch the SPMC ID to prevent unnecessary SMC calls. Also group
SPMC initialization code into an arch specific initialization file.

Signed-off-by: Daniel Boulby <daniel.boulby@arm.com>
Change-Id: I0be0be95a8eea9d39eaf8b5ddc3600bcc7d66ebe
diff --git a/src/arch/aarch64/hypervisor/BUILD.gn b/src/arch/aarch64/hypervisor/BUILD.gn
index 4473cd2..4a366fa 100644
--- a/src/arch/aarch64/hypervisor/BUILD.gn
+++ b/src/arch/aarch64/hypervisor/BUILD.gn
@@ -38,6 +38,7 @@
   ]
 
   sources += [
+    "arch_init.c",
     "cpu.c",
     "debug_el1.c",
     "feature_id.c",
diff --git a/src/arch/aarch64/hypervisor/arch_init.c b/src/arch/aarch64/hypervisor/arch_init.c
new file mode 100644
index 0000000..bcadd60
--- /dev/null
+++ b/src/arch/aarch64/hypervisor/arch_init.c
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2021 The Hafnium Authors.
+ *
+ * Use of this source code is governed by a BSD-style
+ * license that can be found in the LICENSE file or at
+ * https://opensource.org/licenses/BSD-3-Clause.
+ */
+
+#include "hf/arch/ffa.h"
+#include "hf/arch/plat/psci.h"
+
+/**
+ * Performs arch specific boot time initialization.
+ */
+void arch_one_time_init(void)
+{
+	plat_psci_init();
+	arch_ffa_init();
+}
diff --git a/src/arch/aarch64/hypervisor/ffa.c b/src/arch/aarch64/hypervisor/ffa.c
index 33786cc..e036659 100644
--- a/src/arch/aarch64/hypervisor/ffa.c
+++ b/src/arch/aarch64/hypervisor/ffa.c
@@ -8,24 +8,41 @@
 
 #include "hf/arch/plat/ffa.h"
 
+#include "hf/check.h"
 #include "hf/ffa.h"
 #include "hf/panic.h"
 #include "hf/vm_ids.h"
 
+static ffa_vm_id_t spmc_id = HF_INVALID_VM_ID;
+
 /**
  * Returns the SPMC ID returned from the SPMD.
  */
 ffa_vm_id_t arch_ffa_spmc_id_get(void)
 {
+	return spmc_id;
+}
+
+/**
+ * Initialize the platform FF-A module in the context of running the SPMC.
+ * In particular it fetches the SPMC ID to prevent SMC calls everytime
+ * FFA_SPM_ID_GET is invoked.
+ */
+void arch_ffa_init(void)
+{
 	struct ffa_value ret = plat_ffa_spmc_id_get();
 
 	if (ret.func == FFA_SUCCESS_32) {
-		return (ffa_vm_id_t)ret.arg2;
-	}
-	if (ret.func == FFA_ERROR_32 &&
-	    ffa_error_code(ret) != FFA_NOT_SUPPORTED) {
+		spmc_id = ret.arg2;
+	} else if (ret.func == FFA_ERROR_32 &&
+		   ffa_error_code(ret) == FFA_NOT_SUPPORTED) {
+		spmc_id = HF_SPMC_VM_ID;
+	} else {
 		panic("Failed to get SPMC ID\n");
 	}
 
-	return HF_SPMC_VM_ID;
+	/*
+	 * Check that spmc_id is equal to HF_SPMC_VM_ID.
+	 */
+	CHECK(spmc_id == HF_SPMC_VM_ID);
 }
diff --git a/src/arch/aarch64/hypervisor/psci_handler.c b/src/arch/aarch64/hypervisor/psci_handler.c
index 358c827..3c78e57 100644
--- a/src/arch/aarch64/hypervisor/psci_handler.c
+++ b/src/arch/aarch64/hypervisor/psci_handler.c
@@ -24,12 +24,6 @@
 
 void cpu_entry(struct cpu *c);
 
-/* Performs arch specific boot time initialisation. */
-void arch_one_time_init(void)
-{
-	plat_psci_init();
-}
-
 /**
  * Handles PSCI requests received via HVC or SMC instructions from the primary
  * VM.