aarch64: create an SPMC boot flow

Create an SPMC boot flow and skip initialization of a primary VM
in the secure world (SPMC). The PVM initialization remains in the
normal world (Hypervisor). Secure Partitions share same properties
as secondary VMs in the NWd.

Change-Id: Ic9d0c407ae1413eaecd4427b02bcb15d02374e02
Signed-off-by: Olivier Deprez <olivier.deprez@arm.com>
diff --git a/src/arch/aarch64/hypervisor/cpu.c b/src/arch/aarch64/hypervisor/cpu.c
index 0f6710e0..a59b055 100644
--- a/src/arch/aarch64/hypervisor/cpu.c
+++ b/src/arch/aarch64/hypervisor/cpu.c
@@ -65,11 +65,7 @@
 {
 	ffa_vm_id_t vm_id = vcpu->vm->id;
 	bool is_primary = vm_id == HF_PRIMARY_VM_ID;
-#if SECURE_WORLD == 0
 	cpu_id_t vcpu_id = is_primary ? vcpu->cpu->id : vcpu_index(vcpu);
-#else
-	cpu_id_t vcpu_id = vcpu_index(vcpu);
-#endif
 
 	paddr_t table = vcpu->vm->ptable.root;
 	struct arch_regs *r = &vcpu->regs;
diff --git a/src/boot_flow/BUILD.gn b/src/boot_flow/BUILD.gn
index 884c22d..5f44f11 100644
--- a/src/boot_flow/BUILD.gn
+++ b/src/boot_flow/BUILD.gn
@@ -40,3 +40,13 @@
     "//src/arch/${plat_arch}/boot_flow:linux",
   ]
 }
+
+source_set("spmc") {
+  sources = [
+    "spmc.c",
+  ]
+  deps = [
+    ":common",
+    "//src/arch/${plat_arch}/boot_flow:linux",
+  ]
+}
diff --git a/src/boot_flow/spmc.c b/src/boot_flow/spmc.c
new file mode 100644
index 0000000..3f29eca
--- /dev/null
+++ b/src/boot_flow/spmc.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2020 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/plat/boot_flow.h"
+#include "hf/std.h"
+
+/* Set by arch-specific boot-time hook. */
+uintreg_t plat_boot_flow_fdt_addr;
+
+/**
+ * Returns the physical address of SPMC manifest FDT blob. This was passed to
+ * SPMC cold boot entry by the SPMD.
+ */
+paddr_t plat_boot_flow_get_fdt_addr(void)
+{
+	return pa_init((uintpaddr_t)plat_boot_flow_fdt_addr);
+}
+
+/**
+ * The value returned by this function is not meaningful in context of the SPMC
+ * as there is no primary VM.
+ */
+uintreg_t plat_boot_flow_get_kernel_arg(void)
+{
+	return 0;
+}
+
+/**
+ * The value returned by this function is not meaningful in context of the SPMC
+ * as there is no initrd.
+ */
+bool plat_boot_flow_get_initrd_range(const struct fdt *fdt, paddr_t *begin,
+				     paddr_t *end)
+{
+	(void)fdt;
+	(void)begin;
+	(void)end;
+
+	return true;
+}
+
+/**
+ * This wrapper is unused in context of the SPMC.
+ */
+bool plat_boot_flow_update(struct mm_stage1_locked stage1_locked,
+			   const struct manifest *manifest,
+			   struct boot_params_update *update,
+			   struct memiter *cpio, struct mpool *ppool)
+{
+	(void)stage1_locked;
+	(void)manifest;
+	(void)update;
+	(void)cpio;
+	(void)ppool;
+
+	return true;
+}
diff --git a/src/manifest.c b/src/manifest.c
index ab61b12..0425f68 100644
--- a/src/manifest.c
+++ b/src/manifest.c
@@ -810,7 +810,7 @@
 		}
 	}
 
-	if (!found_primary_vm) {
+	if (!found_primary_vm && vm_id_is_current_world(HF_PRIMARY_VM_ID)) {
 		return MANIFEST_ERROR_NO_PRIMARY_VM;
 	}