FF-A: map whole system memory to Hypervisor VM

The "Hypervisor VM" is an abstract representation of the NWd
(Hypervisor or OS kernel if no EL2 present) from the perspective
of the SPMC. vCPUs for such VM (or SP) are never scheduled.
Therefore the corresponding page tables are never rooted into
any physical PE. For any FF-A call from NWd to SWd, the SPMC
is resumed from ffa_handler_loop. At this stage the "current"
vCPU passed to the ffa_handler is one of the "Hypervisor VM"
of FF-A id 0. This serves different purposes (non-exhaustively):
tracking NWd to SWd mem share operations, mapping of Hypervisor
RX/TX buffers, partition info get forwarded from NWd to SWd.
There is the same concept of "TEE VM" from the perspective of
the Hypervisor in NWd. The "Hypervisor VM" is the similar concept
extended to the SWd.

Change-Id: I2d2e77c41825ef1a59a320e75d6b647c43966135
Signed-off-by: Olivier Deprez <olivier.deprez@arm.com>
diff --git a/src/BUILD.gn b/src/BUILD.gn
index 1c32ecf..5ae41fd 100644
--- a/src/BUILD.gn
+++ b/src/BUILD.gn
@@ -33,7 +33,7 @@
   deps = [
     ":src_testable",
     "//project/${project}/${plat_name}",
-    "//src/arch/${plat_arch}/hypervisor:tee",
+    "//src/arch/${plat_arch}/hypervisor:other_world",
     plat_boot_flow,
     plat_console,
     plat_iommu,
@@ -66,7 +66,7 @@
     ":vm",
     "//src/arch/${plat_arch}:arch",
     "//src/arch/${plat_arch}/hypervisor",
-    "//src/arch/${plat_arch}/hypervisor:tee",
+    "//src/arch/${plat_arch}/hypervisor:other_world",
     "//vmlib",
     plat_boot_flow,
     plat_console,
diff --git a/src/api.c b/src/api.c
index c33d9eb..bdf60d3 100644
--- a/src/api.c
+++ b/src/api.c
@@ -10,7 +10,7 @@
 
 #include "hf/arch/cpu.h"
 #include "hf/arch/mm.h"
-#include "hf/arch/tee.h"
+#include "hf/arch/other_world.h"
 #include "hf/arch/timer.h"
 
 #include "hf/check.h"
@@ -1023,7 +1023,7 @@
 	if (to.vm->id == HF_TEE_VM_ID) {
 		struct ffa_value call = ffa_msg_recv_return(to.vm);
 
-		ret = arch_tee_call(call);
+		ret = arch_other_world_call(call);
 		/*
 		 * After the call to the TEE completes it must have finished
 		 * reading its RX buffer, so it is ready for another message.
diff --git a/src/arch/aarch64/hypervisor/BUILD.gn b/src/arch/aarch64/hypervisor/BUILD.gn
index 3a5f3d5..0f9c15e 100644
--- a/src/arch/aarch64/hypervisor/BUILD.gn
+++ b/src/arch/aarch64/hypervisor/BUILD.gn
@@ -14,10 +14,10 @@
   path = "hf/arch/offsets.h"
 }
 
-source_set("tee") {
+source_set("other_world") {
   public_configs = [ "//src/arch/aarch64:config" ]
   sources = [
-    "tee.c",
+    "other_world.c",
   ]
   deps = [
     "//src:vm",
diff --git a/src/arch/aarch64/hypervisor/handler.c b/src/arch/aarch64/hypervisor/handler.c
index 2dd7793..624899e 100644
--- a/src/arch/aarch64/hypervisor/handler.c
+++ b/src/arch/aarch64/hypervisor/handler.c
@@ -11,8 +11,8 @@
 #include "hf/arch/barriers.h"
 #include "hf/arch/init.h"
 #include "hf/arch/mmu.h"
+#include "hf/arch/other_world.h"
 #include "hf/arch/plat/smc.h"
-#include "hf/arch/tee.h"
 
 #include "hf/api.h"
 #include "hf/check.h"
diff --git a/src/arch/aarch64/hypervisor/other_world.c b/src/arch/aarch64/hypervisor/other_world.c
new file mode 100644
index 0000000..39b5752
--- /dev/null
+++ b/src/arch/aarch64/hypervisor/other_world.c
@@ -0,0 +1,113 @@
+/*
+ * 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/arch/other_world.h"
+
+#include "hf/arch/mmu.h"
+
+#include "hf/check.h"
+#include "hf/dlog.h"
+#include "hf/ffa.h"
+#include "hf/panic.h"
+#include "hf/vm.h"
+
+#include "smc.h"
+
+#if SECURE_WORLD == 0
+
+alignas(PAGE_SIZE) static uint8_t other_world_send_buffer[HF_MAILBOX_SIZE];
+alignas(PAGE_SIZE) static uint8_t other_world_recv_buffer[HF_MAILBOX_SIZE];
+
+#endif
+
+void arch_other_world_init(void)
+{
+#if SECURE_WORLD == 0
+
+	struct vm *other_world_vm = vm_find(HF_OTHER_WORLD_ID);
+	struct ffa_value ret;
+	uint32_t func;
+
+	CHECK(other_world_vm != NULL);
+
+	/* Setup TEE VM RX/TX buffers */
+	other_world_vm->mailbox.send = &other_world_send_buffer;
+	other_world_vm->mailbox.recv = &other_world_recv_buffer;
+
+	/*
+	 * Note that send and recv are swapped around, as the send buffer from
+	 * Hafnium's perspective is the recv buffer from the EL3 dispatcher's
+	 * perspective and vice-versa.
+	 */
+	dlog_verbose("Setting up buffers for TEE.\n");
+	ret = arch_other_world_call((struct ffa_value){
+		.func = FFA_RXTX_MAP_64,
+		.arg1 = pa_addr(
+			pa_from_va(va_from_ptr(other_world_vm->mailbox.recv))),
+		.arg2 = pa_addr(
+			pa_from_va(va_from_ptr(other_world_vm->mailbox.send))),
+		.arg3 = HF_MAILBOX_SIZE / FFA_PAGE_SIZE});
+	func = ret.func & ~SMCCC_CONVENTION_MASK;
+	if (ret.func == SMCCC_ERROR_UNKNOWN) {
+		dlog_error(
+			"Unknown function setting up TEE message buffers. "
+			"Memory sharing with TEE will not work.\n");
+		return;
+	}
+	if (func == FFA_ERROR_32) {
+		panic("Error %d setting up TEE message buffers.", ret.arg2);
+	} else if (func != FFA_SUCCESS_32) {
+		panic("Unexpected function %#x returned setting up TEE message "
+		      "buffers.",
+		      ret.func);
+	}
+	dlog_verbose("TEE finished setting up buffers.\n");
+#endif
+}
+
+bool arch_other_world_vm_init(struct vm *other_world_vm, struct mpool *ppool)
+{
+#if SECURE_WORLD == 0
+
+	(void)other_world_vm;
+	(void)ppool;
+
+	return true;
+
+#else
+
+	struct vm_locked other_world_vm_locked;
+	bool ret = false;
+
+	/* Map 1TB address range to "Other world VM" Stage-2 */
+	other_world_vm_locked = vm_lock(other_world_vm);
+
+	if (!vm_identity_map(other_world_vm_locked, pa_init(0),
+			     pa_init(UINT64_C(1024) * 1024 * 1024 * 1024),
+			     MM_MODE_R | MM_MODE_W | MM_MODE_X | MM_MODE_NS,
+			     ppool, NULL)) {
+		dlog_error(
+			"Unable to initialise address space for "
+			"Hypervisor VM.\n");
+		goto out;
+	}
+
+	ret = true;
+
+out:
+	vm_unlock(&other_world_vm_locked);
+
+	return ret;
+
+#endif
+}
+
+struct ffa_value arch_other_world_call(struct ffa_value args)
+{
+	return smc_ffa_call(args);
+}
diff --git a/src/arch/aarch64/hypervisor/tee.c b/src/arch/aarch64/hypervisor/tee.c
deleted file mode 100644
index 5637230..0000000
--- a/src/arch/aarch64/hypervisor/tee.c
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * 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/arch/tee.h"
-
-#include "hf/check.h"
-#include "hf/dlog.h"
-#include "hf/ffa.h"
-#include "hf/panic.h"
-#include "hf/vm.h"
-
-#include "smc.h"
-
-#if SECURE_WORLD == 0
-
-alignas(PAGE_SIZE) static uint8_t tee_send_buffer[HF_MAILBOX_SIZE];
-alignas(PAGE_SIZE) static uint8_t tee_recv_buffer[HF_MAILBOX_SIZE];
-
-#endif
-
-void arch_tee_init(void)
-{
-#if SECURE_WORLD == 0
-
-	struct vm *tee_vm = vm_find(HF_OTHER_WORLD_ID);
-	struct ffa_value ret;
-	uint32_t func;
-
-	CHECK(tee_vm != NULL);
-
-	/* Setup TEE VM RX/TX buffers */
-	tee_vm->mailbox.send = &tee_send_buffer;
-	tee_vm->mailbox.recv = &tee_recv_buffer;
-
-	/*
-	 * Note that send and recv are swapped around, as the send buffer from
-	 * Hafnium's perspective is the recv buffer from the EL3 dispatcher's
-	 * perspective and vice-versa.
-	 */
-	dlog_verbose("Setting up buffers for TEE.\n");
-	ret = arch_tee_call((struct ffa_value){
-		.func = FFA_RXTX_MAP_64,
-		.arg1 = pa_addr(pa_from_va(va_from_ptr(tee_vm->mailbox.recv))),
-		.arg2 = pa_addr(pa_from_va(va_from_ptr(tee_vm->mailbox.send))),
-		.arg3 = HF_MAILBOX_SIZE / FFA_PAGE_SIZE});
-	func = ret.func & ~SMCCC_CONVENTION_MASK;
-	if (ret.func == SMCCC_ERROR_UNKNOWN) {
-		dlog_error(
-			"Unknown function setting up TEE message buffers. "
-			"Memory sharing with TEE will not work.\n");
-		return;
-	}
-	if (func == FFA_ERROR_32) {
-		panic("Error %d setting up TEE message buffers.", ret.arg2);
-	} else if (func != FFA_SUCCESS_32) {
-		panic("Unexpected function %#x returned setting up TEE message "
-		      "buffers.",
-		      ret.func);
-	}
-	dlog_verbose("TEE finished setting up buffers.\n");
-#endif
-}
-
-struct ffa_value arch_tee_call(struct ffa_value args)
-{
-	return smc_ffa_call(args);
-}
diff --git a/src/arch/fake/hypervisor/BUILD.gn b/src/arch/fake/hypervisor/BUILD.gn
index f542206..159e303 100644
--- a/src/arch/fake/hypervisor/BUILD.gn
+++ b/src/arch/fake/hypervisor/BUILD.gn
@@ -13,8 +13,8 @@
   ]
 }
 
-source_set("tee") {
+source_set("other_world") {
   sources = [
-    "tee.c",
+    "other_world.c",
   ]
 }
diff --git a/src/arch/fake/hypervisor/tee.c b/src/arch/fake/hypervisor/other_world.c
similarity index 80%
rename from src/arch/fake/hypervisor/tee.c
rename to src/arch/fake/hypervisor/other_world.c
index 3b5aa21..57df952 100644
--- a/src/arch/fake/hypervisor/tee.c
+++ b/src/arch/fake/hypervisor/other_world.c
@@ -6,13 +6,13 @@
  * https://opensource.org/licenses/BSD-3-Clause.
  */
 
-#include "hf/arch/tee.h"
+#include "hf/arch/other_world.h"
 
 #include "hf/dlog.h"
 #include "hf/ffa.h"
 #include "hf/ffa_internal.h"
 
-struct ffa_value arch_tee_call(struct ffa_value args)
+struct ffa_value arch_other_world_call(struct ffa_value args)
 {
 	dlog_error("Attempted to call TEE function %#x\n", args.func);
 	return ffa_error(FFA_NOT_SUPPORTED);
diff --git a/src/ffa_memory.c b/src/ffa_memory.c
index 699b63b..53130f2 100644
--- a/src/ffa_memory.c
+++ b/src/ffa_memory.c
@@ -8,7 +8,7 @@
 
 #include "hf/ffa_memory.h"
 
-#include "hf/arch/tee.h"
+#include "hf/arch/other_world.h"
 
 #include "hf/api.h"
 #include "hf/check.h"
@@ -1137,10 +1137,11 @@
 	if (clear) {
 		tee_flags |= FFA_MEMORY_REGION_FLAG_CLEAR;
 	}
-	ret = arch_tee_call((struct ffa_value){.func = FFA_MEM_RECLAIM_32,
-					       .arg1 = (uint32_t)handle,
-					       .arg2 = (uint32_t)(handle >> 32),
-					       .arg3 = tee_flags});
+	ret = arch_other_world_call(
+		(struct ffa_value){.func = FFA_MEM_RECLAIM_32,
+				   .arg1 = (uint32_t)handle,
+				   .arg2 = (uint32_t)(handle >> 32),
+				   .arg3 = tee_flags});
 
 	if (ret.func != FFA_SUCCESS_32) {
 		dlog_verbose(
@@ -1459,9 +1460,10 @@
 	tee_locked.vm->mailbox.recv_sender = sender_vm_id;
 	tee_locked.vm->mailbox.recv_func = share_func;
 	tee_locked.vm->mailbox.state = MAILBOX_STATE_RECEIVED;
-	ret = arch_tee_call((struct ffa_value){.func = share_func,
-					       .arg1 = memory_share_length,
-					       .arg2 = fragment_length});
+	ret = arch_other_world_call(
+		(struct ffa_value){.func = share_func,
+				   .arg1 = memory_share_length,
+				   .arg2 = fragment_length});
 	/*
 	 * After the call to the TEE completes it must have finished reading its
 	 * RX buffer, so it is ready for another message.
@@ -1546,7 +1548,7 @@
 	tee_locked.vm->mailbox.recv_sender = sender_vm_id;
 	tee_locked.vm->mailbox.recv_func = FFA_MEM_FRAG_TX_32;
 	tee_locked.vm->mailbox.state = MAILBOX_STATE_RECEIVED;
-	ret = arch_tee_call(
+	ret = arch_other_world_call(
 		(struct ffa_value){.func = FFA_MEM_FRAG_TX_32,
 				   .arg1 = (uint32_t)handle,
 				   .arg2 = (uint32_t)(handle >> 32),
@@ -1990,7 +1992,7 @@
 		} else {
 			/* Abort sending to TEE. */
 			struct ffa_value tee_ret =
-				arch_tee_call((struct ffa_value){
+				arch_other_world_call((struct ffa_value){
 					.func = FFA_MEM_RECLAIM_32,
 					.arg1 = (uint32_t)handle,
 					.arg2 = (uint32_t)(handle >> 32)});
@@ -2659,7 +2661,7 @@
 	CHECK(from_locked.vm->id == HF_TEE_VM_ID);
 
 	/* Retrieve memory region information from the TEE. */
-	tee_ret = arch_tee_call(
+	tee_ret = arch_other_world_call(
 		(struct ffa_value){.func = FFA_MEM_RETRIEVE_REQ_32,
 				   .arg1 = request_length,
 				   .arg2 = request_length});
@@ -2695,7 +2697,7 @@
 	/* Fetch the remaining fragments into the same buffer. */
 	fragment_offset = fragment_length;
 	while (fragment_offset < length) {
-		tee_ret = arch_tee_call(
+		tee_ret = arch_other_world_call(
 			(struct ffa_value){.func = FFA_MEM_FRAG_RX_32,
 					   .arg1 = (uint32_t)handle,
 					   .arg2 = (uint32_t)(handle >> 32),
diff --git a/src/init.c b/src/init.c
index 03fc2fd..a5b48ab 100644
--- a/src/init.c
+++ b/src/init.c
@@ -11,7 +11,7 @@
 #include <stdalign.h>
 #include <stddef.h>
 
-#include "hf/arch/tee.h"
+#include "hf/arch/other_world.h"
 
 #include "hf/api.h"
 #include "hf/boot_flow.h"
@@ -169,7 +169,7 @@
 
 	if (manifest.ffa_tee_enabled) {
 		/* Set up message buffers for TEE dispatcher. */
-		arch_tee_init();
+		arch_other_world_init();
 	}
 
 	dlog_info("Hafnium initialisation completed\n");
diff --git a/src/load.c b/src/load.c
index 871c94f..f820204 100644
--- a/src/load.c
+++ b/src/load.c
@@ -10,6 +10,7 @@
 
 #include <stdbool.h>
 
+#include "hf/arch/other_world.h"
 #include "hf/arch/vm.h"
 
 #include "hf/api.h"
@@ -650,26 +651,10 @@
 	return true;
 }
 
-/*
- * Loads alls VMs from the manifest.
- */
-bool load_vms(struct mm_stage1_locked stage1_locked,
-	      const struct manifest *manifest, const struct memiter *cpio,
-	      const struct boot_params *params,
-	      struct boot_params_update *update, struct mpool *ppool)
+static bool init_other_world_vm(struct mpool *ppool)
 {
-	struct vm *primary;
 	struct vm *other_world_vm;
-	struct mem_range mem_ranges_available[MAX_MEM_RANGES];
-	struct vm_locked primary_vm_locked;
 	size_t i;
-	bool success = true;
-
-	if (!load_primary(stage1_locked, &manifest->vm[HF_PRIMARY_VM_INDEX],
-			  cpio, params, ppool)) {
-		dlog_error("Unable to load primary VM.\n");
-		return false;
-	}
 
 	/*
 	 * Initialise the dummy VM which represents the opposite world:
@@ -686,6 +671,33 @@
 		vcpu->cpu = cpu;
 	}
 
+	return arch_other_world_vm_init(other_world_vm, ppool);
+}
+
+/*
+ * Loads alls VMs from the manifest.
+ */
+bool load_vms(struct mm_stage1_locked stage1_locked,
+	      const struct manifest *manifest, const struct memiter *cpio,
+	      const struct boot_params *params,
+	      struct boot_params_update *update, struct mpool *ppool)
+{
+	struct vm *primary;
+	struct mem_range mem_ranges_available[MAX_MEM_RANGES];
+	struct vm_locked primary_vm_locked;
+	size_t i;
+	bool success = true;
+
+	if (!load_primary(stage1_locked, &manifest->vm[HF_PRIMARY_VM_INDEX],
+			  cpio, params, ppool)) {
+		dlog_error("Unable to load primary VM.\n");
+		return false;
+	}
+
+	if (!init_other_world_vm(ppool)) {
+		return false;
+	}
+
 	static_assert(
 		sizeof(mem_ranges_available) == sizeof(params->mem_ranges),
 		"mem_range arrays must be the same size for memcpy.");