FF-A: map normal world rx/tx buffers to the SPMC
The SPMC can receive an FF-A RXTX map request to register
the NWd Hypervisor or OS kernel rx/tx buffers. In the SPMC
this request comes from the physical FF-A interface.
The buffers are mapped non-secure in the SPMC S-EL2 Stage-1
translation regime.
Change-Id: I65947f081b55e125edfd81e5e540a09dc8f915d9
Signed-off-by: Olivier Deprez <olivier.deprez@arm.com>
diff --git a/src/BUILD.gn b/src/BUILD.gn
index f8d0008..1c32ecf 100644
--- a/src/BUILD.gn
+++ b/src/BUILD.gn
@@ -64,6 +64,7 @@
":panic",
":std",
":vm",
+ "//src/arch/${plat_arch}:arch",
"//src/arch/${plat_arch}/hypervisor",
"//src/arch/${plat_arch}/hypervisor:tee",
"//vmlib",
diff --git a/src/api.c b/src/api.c
index b55ae09..c33d9eb 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/mm.h"
#include "hf/arch/tee.h"
#include "hf/arch/timer.h"
@@ -759,6 +760,7 @@
struct vm_locked vm_locked,
paddr_t pa_send_begin, paddr_t pa_send_end,
paddr_t pa_recv_begin, paddr_t pa_recv_end,
+ uint32_t extra_attributes,
struct mpool *local_page_pool)
{
bool ret;
@@ -766,7 +768,7 @@
/* Map the send page as read-only in the hypervisor address space. */
vm_locked.vm->mailbox.send =
mm_identity_map(mm_stage1_locked, pa_send_begin, pa_send_end,
- MM_MODE_R, local_page_pool);
+ MM_MODE_R | extra_attributes, local_page_pool);
if (!vm_locked.vm->mailbox.send) {
/* TODO: partial defrag of failed range. */
/* Recover any memory consumed in failed mapping. */
@@ -780,7 +782,7 @@
*/
vm_locked.vm->mailbox.recv =
mm_identity_map(mm_stage1_locked, pa_recv_begin, pa_recv_end,
- MM_MODE_W, local_page_pool);
+ MM_MODE_W | extra_attributes, local_page_pool);
if (!vm_locked.vm->mailbox.recv) {
/* TODO: partial defrag of failed range. */
/* Recover any memory consumed in failed mapping. */
@@ -833,6 +835,7 @@
paddr_t pa_recv_end;
uint32_t orig_send_mode;
uint32_t orig_recv_mode;
+ uint32_t extra_attributes;
/* We only allow these to be setup once. */
if (vm_locked.vm->mailbox.send || vm_locked.vm->mailbox.recv) {
@@ -904,9 +907,12 @@
goto fail_undo_send;
}
+ /* Get extra send/recv pages mapping attributes for the given VM ID. */
+ extra_attributes = arch_mm_extra_attributes_from_vm(vm_locked.vm->id);
+
if (!api_vm_configure_stage1(mm_stage1_locked, vm_locked, pa_send_begin,
pa_send_end, pa_recv_begin, pa_recv_end,
- local_page_pool)) {
+ extra_attributes, local_page_pool)) {
goto fail_undo_send_and_recv;
}
diff --git a/src/arch/aarch64/hypervisor/tee.c b/src/arch/aarch64/hypervisor/tee.c
index f642a0c..5637230 100644
--- a/src/arch/aarch64/hypervisor/tee.c
+++ b/src/arch/aarch64/hypervisor/tee.c
@@ -16,13 +16,27 @@
#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)
{
- struct vm *tee_vm = vm_find(HF_TEE_VM_ID);
+#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
@@ -49,6 +63,7 @@
ret.func);
}
dlog_verbose("TEE finished setting up buffers.\n");
+#endif
}
struct ffa_value arch_tee_call(struct ffa_value args)
diff --git a/src/arch/aarch64/mm.c b/src/arch/aarch64/mm.c
index 5bfced3..0abe43e 100644
--- a/src/arch/aarch64/mm.c
+++ b/src/arch/aarch64/mm.c
@@ -695,3 +695,11 @@
return true;
}
+
+/**
+ * Return the arch specific mm mode for send/recv pages of given VM ID.
+ */
+uint32_t arch_mm_extra_attributes_from_vm(ffa_vm_id_t id)
+{
+ return (id == HF_HYPERVISOR_VM_ID) ? MM_MODE_NS : 0;
+}
diff --git a/src/arch/fake/BUILD.gn b/src/arch/fake/BUILD.gn
index cbdecaa..382227e 100644
--- a/src/arch/fake/BUILD.gn
+++ b/src/arch/fake/BUILD.gn
@@ -7,7 +7,7 @@
config("arch_config") {
}
-source_set("fake") {
+source_set("arch") {
sources = [
"mm.c",
"timer.c",
diff --git a/src/arch/fake/hypervisor/BUILD.gn b/src/arch/fake/hypervisor/BUILD.gn
index 8d41d5e..f542206 100644
--- a/src/arch/fake/hypervisor/BUILD.gn
+++ b/src/arch/fake/hypervisor/BUILD.gn
@@ -9,7 +9,7 @@
"cpu.c",
]
deps = [
- "//src/arch/fake",
+ "//src/arch/fake:arch",
]
}
diff --git a/src/arch/fake/mm.c b/src/arch/fake/mm.c
index f71dd81..96407ac 100644
--- a/src/arch/fake/mm.c
+++ b/src/arch/fake/mm.c
@@ -160,3 +160,10 @@
(void)table;
return true;
}
+
+uint32_t arch_mm_extra_attributes_from_vm(ffa_vm_id_t id)
+{
+ (void)id;
+
+ return 0;
+}
diff --git a/src/load.c b/src/load.c
index 97e4b34..871c94f 100644
--- a/src/load.c
+++ b/src/load.c
@@ -29,9 +29,6 @@
#include "vmapi/hf/call.h"
#include "vmapi/hf/ffa.h"
-alignas(PAGE_SIZE) static uint8_t tee_send_buffer[HF_MAILBOX_SIZE];
-alignas(PAGE_SIZE) static uint8_t tee_recv_buffer[HF_MAILBOX_SIZE];
-
/**
* Copies data to an unmapped location by mapping it for write, copying the
* data, then unmapping it.
@@ -662,7 +659,7 @@
struct boot_params_update *update, struct mpool *ppool)
{
struct vm *primary;
- struct vm *tee;
+ struct vm *other_world_vm;
struct mem_range mem_ranges_available[MAX_MEM_RANGES];
struct vm_locked primary_vm_locked;
size_t i;
@@ -675,13 +672,19 @@
}
/*
- * Initialise the dummy VM which represents TrustZone, and set up its
- * RX/TX buffers.
+ * Initialise the dummy VM which represents the opposite world:
+ * -TrustZone (or the SPMC) when running the Hypervisor
+ * -the Hypervisor when running TZ/SPMC
*/
- tee = vm_init(HF_TEE_VM_ID, 0, ppool);
- CHECK(tee != NULL);
- tee->mailbox.send = &tee_send_buffer;
- tee->mailbox.recv = &tee_recv_buffer;
+ other_world_vm = vm_init(HF_OTHER_WORLD_ID, MAX_CPUS, ppool);
+ CHECK(other_world_vm != NULL);
+
+ for (i = 0; i < MAX_CPUS; i++) {
+ struct vcpu *vcpu = vm_get_vcpu(other_world_vm, i);
+ struct cpu *cpu = cpu_find_index(i);
+
+ vcpu->cpu = cpu;
+ }
static_assert(
sizeof(mem_ranges_available) == sizeof(params->mem_ranges),
diff --git a/src/vm.c b/src/vm.c
index a021d77..2ad3516 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -19,7 +19,7 @@
#include "vmapi/hf/call.h"
static struct vm vms[MAX_VMS];
-static struct vm tee_vm;
+static struct vm other_world;
static ffa_vm_count_t vm_count;
struct vm *vm_init(ffa_vm_id_t id, ffa_vcpu_count_t vcpu_count,
@@ -28,8 +28,8 @@
uint32_t i;
struct vm *vm;
- if (id == HF_TEE_VM_ID) {
- vm = &tee_vm;
+ if (id == HF_OTHER_WORLD_ID) {
+ vm = &other_world;
} else {
uint16_t vm_index = id - HF_VM_ID_OFFSET;
@@ -97,15 +97,15 @@
{
uint16_t index;
- /* Check that this is not a reserved ID. */
- if (id < HF_VM_ID_OFFSET) {
+ if (id == HF_OTHER_WORLD_ID) {
+ if (other_world.id == HF_OTHER_WORLD_ID) {
+ return &other_world;
+ }
return NULL;
}
- if (id == HF_TEE_VM_ID) {
- if (tee_vm.id == HF_TEE_VM_ID) {
- return &tee_vm;
- }
+ /* Check that this is not a reserved ID. */
+ if (id < HF_VM_ID_OFFSET) {
return NULL;
}