feat(FF-A): implement FFA_SPM_ID_GET interface

If FFA_SPM_ID_GET is invoked at the secure virtual FF-A instance
(a secure partition) return the SPMC id. The SPMC id is queried by
the SPMC to the SPMD by calling FFA_ID_GET or by the Hypervisor to
the SPMD by calling FFA_SPM_ID_GET. Introduce plat_ffa module to
allow for the SPMC and hypervisor specific code.

Signed-off-by: Daniel Boulby <daniel.boulby@arm.com>
Change-Id: I892fa034ac00a1c0ada7ac13e9384a8c5ccfc507
diff --git a/inc/hf/api.h b/inc/hf/api.h
index 8af07ee..2714735 100644
--- a/inc/hf/api.h
+++ b/inc/hf/api.h
@@ -56,6 +56,7 @@
 struct ffa_value api_ffa_partition_info_get(struct vcpu *current,
 					    const struct ffa_uuid *uuid);
 struct ffa_value api_ffa_id_get(const struct vcpu *current);
+struct ffa_value api_ffa_spm_id_get(void);
 struct ffa_value api_ffa_features(uint32_t function_id);
 struct ffa_value api_ffa_run(ffa_vm_id_t vm_id, ffa_vcpu_index_t vcpu_idx,
 			     const struct vcpu *current, struct vcpu **next);
diff --git a/inc/hf/arch/ffa.h b/inc/hf/arch/ffa.h
new file mode 100644
index 0000000..1a6ae22
--- /dev/null
+++ b/inc/hf/arch/ffa.h
@@ -0,0 +1,14 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include "hf/ffa.h"
+
+/** Returns the SPMC ID. */
+ffa_vm_id_t arch_ffa_spmc_id_get(void);
diff --git a/inc/hf/arch/plat/ffa.h b/inc/hf/arch/plat/ffa.h
new file mode 100644
index 0000000..19c8e45
--- /dev/null
+++ b/inc/hf/arch/plat/ffa.h
@@ -0,0 +1,14 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include "hf/ffa.h"
+
+/** Returns the SPMC ID. */
+struct ffa_value plat_ffa_spmc_id_get(void);
diff --git a/inc/vmapi/hf/ffa.h b/inc/vmapi/hf/ffa.h
index 17c3ab6..25b1bf9 100644
--- a/inc/vmapi/hf/ffa.h
+++ b/inc/vmapi/hf/ffa.h
@@ -63,6 +63,7 @@
 #define FFA_MEM_FRAG_TX_32           0x8400007B
 #define FFA_SECONDARY_EP_REGISTER_32 0x84000084
 #define FFA_SECONDARY_EP_REGISTER_64 0xC4000084
+#define FFA_SPM_ID_GET_32	     0x84000085
 
 /* FF-A error codes. */
 #define FFA_NOT_SUPPORTED      INT32_C(-1)
diff --git a/project/reference b/project/reference
index 16fc50e..0029f48 160000
--- a/project/reference
+++ b/project/reference
@@ -1 +1 @@
-Subproject commit 16fc50ea3fd7f2e53905c6a3628621fa6ade4c21
+Subproject commit 0029f4812915ee7bb3d3fbf1df3105a1547b1422
diff --git a/src/api.c b/src/api.c
index 38475a7..01c91b5 100644
--- a/src/api.c
+++ b/src/api.c
@@ -9,6 +9,7 @@
 #include "hf/api.h"
 
 #include "hf/arch/cpu.h"
+#include "hf/arch/ffa.h"
 #include "hf/arch/ffa_memory_handle.h"
 #include "hf/arch/mm.h"
 #include "hf/arch/other_world.h"
@@ -436,6 +437,24 @@
 }
 
 /**
+ * Returns the ID of the SPMC.
+ */
+struct ffa_value api_ffa_spm_id_get(void)
+{
+	struct ffa_value ret = ffa_error(FFA_NOT_SUPPORTED);
+
+	if (MAKE_FFA_VERSION(1, 1) <= FFA_VERSION_COMPILED) {
+		/*
+		 * Return the SPMC ID that was fetched during FF-A
+		 * initialization.
+		 */
+		ret = (struct ffa_value){.func = FFA_SUCCESS_32,
+					 .arg2 = arch_ffa_spmc_id_get()};
+	}
+	return ret;
+}
+
+/**
  * This function is called by the architecture-specific context switching
  * function to indicate that register state for the given vCPU has been saved
  * and can therefore be used by other pCPUs.
@@ -1692,6 +1711,11 @@
 	case FFA_MSG_SEND_DIRECT_REQ_64:
 	case FFA_MSG_SEND_DIRECT_REQ_32:
 		return (struct ffa_value){.func = FFA_SUCCESS_32};
+	/* FF-A v1.1 features. */
+	case FFA_SPM_ID_GET_32:
+		if (MAKE_FFA_VERSION(1, 1) <= FFA_VERSION_COMPILED) {
+			return (struct ffa_value){.func = FFA_SUCCESS_32};
+		}
 	default:
 		return ffa_error(FFA_NOT_SUPPORTED);
 	}
diff --git a/src/arch/aarch64/args.gni b/src/arch/aarch64/args.gni
index e51f164..f42d228 100644
--- a/src/arch/aarch64/args.gni
+++ b/src/arch/aarch64/args.gni
@@ -5,6 +5,9 @@
 # https://opensource.org/licenses/BSD-3-Clause.
 
 declare_args() {
+  # FF-A hooks to be used for the platform, specified as build target.
+  plat_ffa = "//src/arch/aarch64/plat/ffa:absent"
+
   # PSCI hooks to be used for the platform, specified as build target.
   plat_psci = "//src/arch/aarch64/plat/psci:hypervisor"
 
diff --git a/src/arch/aarch64/hypervisor/BUILD.gn b/src/arch/aarch64/hypervisor/BUILD.gn
index 3648cba..4473cd2 100644
--- a/src/arch/aarch64/hypervisor/BUILD.gn
+++ b/src/arch/aarch64/hypervisor/BUILD.gn
@@ -41,6 +41,7 @@
     "cpu.c",
     "debug_el1.c",
     "feature_id.c",
+    "ffa.c",
     "handler.c",
     "perfmon.c",
     "psci_handler.c",
@@ -52,6 +53,7 @@
     "//src/arch/aarch64:arch",
     "//src/arch/aarch64:entry",
     "//src/arch/aarch64:smc",
+    plat_ffa,
     plat_interrupts,
     plat_prng,
     plat_psci,
diff --git a/src/arch/aarch64/hypervisor/ffa.c b/src/arch/aarch64/hypervisor/ffa.c
new file mode 100644
index 0000000..33786cc
--- /dev/null
+++ b/src/arch/aarch64/hypervisor/ffa.c
@@ -0,0 +1,31 @@
+/*
+ * 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/plat/ffa.h"
+
+#include "hf/ffa.h"
+#include "hf/panic.h"
+#include "hf/vm_ids.h"
+
+/**
+ * Returns the SPMC ID returned from the SPMD.
+ */
+ffa_vm_id_t arch_ffa_spmc_id_get(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) {
+		panic("Failed to get SPMC ID\n");
+	}
+
+	return HF_SPMC_VM_ID;
+}
diff --git a/src/arch/aarch64/hypervisor/handler.c b/src/arch/aarch64/hypervisor/handler.c
index cd98722..fc82b1b 100644
--- a/src/arch/aarch64/hypervisor/handler.c
+++ b/src/arch/aarch64/hypervisor/handler.c
@@ -473,6 +473,9 @@
 	case FFA_ID_GET_32:
 		*args = api_ffa_id_get(current);
 		return true;
+	case FFA_SPM_ID_GET_32:
+		*args = api_ffa_spm_id_get();
+		return true;
 	case FFA_FEATURES_32:
 		*args = api_ffa_features(args->arg1);
 		return true;
diff --git a/src/arch/aarch64/plat/ffa/BUILD.gn b/src/arch/aarch64/plat/ffa/BUILD.gn
new file mode 100644
index 0000000..8b278fd
--- /dev/null
+++ b/src/arch/aarch64/plat/ffa/BUILD.gn
@@ -0,0 +1,27 @@
+# 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.
+
+import("//build/toolchain/platform.gni")
+
+source_set("absent") {
+  sources = [
+    "absent.c",
+  ]
+}
+
+source_set("hypervisor") {
+  public_configs = [ "//src/arch/${plat_arch}:config" ]
+  sources = [
+    "hypervisor.c",
+  ]
+}
+
+source_set("spmc") {
+  public_configs = [ "//src/arch/${plat_arch}:config" ]
+  sources = [
+    "spmc.c",
+  ]
+}
diff --git a/src/arch/aarch64/plat/ffa/absent.c b/src/arch/aarch64/plat/ffa/absent.c
new file mode 100644
index 0000000..141e97e
--- /dev/null
+++ b/src/arch/aarch64/plat/ffa/absent.c
@@ -0,0 +1,15 @@
+/*
+ * 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/ffa.h"
+
+struct ffa_value plat_ffa_spmc_id_get(void)
+{
+	return (struct ffa_value){.func = FFA_ERROR_32,
+				  .arg2 = FFA_NOT_SUPPORTED};
+}
diff --git a/src/arch/aarch64/plat/ffa/hypervisor.c b/src/arch/aarch64/plat/ffa/hypervisor.c
new file mode 100644
index 0000000..9bdf0ab
--- /dev/null
+++ b/src/arch/aarch64/plat/ffa/hypervisor.c
@@ -0,0 +1,17 @@
+/*
+ * 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/ffa.h"
+
+#include "smc.h"
+
+struct ffa_value plat_ffa_spmc_id_get(void)
+{
+	/* Fetch the SPMC ID from the SPMD using FFA_SPM_ID_GET. */
+	return smc_ffa_call((struct ffa_value){.func = FFA_SPM_ID_GET_32});
+}
diff --git a/src/arch/aarch64/plat/ffa/spmc.c b/src/arch/aarch64/plat/ffa/spmc.c
new file mode 100644
index 0000000..8cd65c4
--- /dev/null
+++ b/src/arch/aarch64/plat/ffa/spmc.c
@@ -0,0 +1,20 @@
+/*
+ * 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/ffa.h"
+
+#include "smc.h"
+
+struct ffa_value plat_ffa_spmc_id_get(void)
+{
+	/*
+	 * Since we are running in the SPMC use FFA_ID_GET to fetch our
+	 * ID from the SPMD.
+	 */
+	return smc_ffa_call((struct ffa_value){.func = FFA_ID_GET_32});
+}
diff --git a/src/arch/fake/hypervisor/BUILD.gn b/src/arch/fake/hypervisor/BUILD.gn
index 8f28802..4c6f2c2 100644
--- a/src/arch/fake/hypervisor/BUILD.gn
+++ b/src/arch/fake/hypervisor/BUILD.gn
@@ -7,6 +7,7 @@
 source_set("hypervisor") {
   sources = [
     "cpu.c",
+    "ffa.c",
     "vm.c",
   ]
   deps = [
diff --git a/src/arch/fake/hypervisor/ffa.c b/src/arch/fake/hypervisor/ffa.c
new file mode 100644
index 0000000..08183e8
--- /dev/null
+++ b/src/arch/fake/hypervisor/ffa.c
@@ -0,0 +1,16 @@
+/*
+ * 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/ffa.h"
+
+#include "hf/vm_ids.h"
+
+ffa_vm_id_t arch_ffa_spmc_id_get(void)
+{
+	return HF_SPMC_VM_ID;
+}