Add special dummy VM for TrustZone.
Bug: 132429380
Change-Id: If6d7ecf674d2c3c1e8c26fd8c68fa89f362f3a10
diff --git a/inc/hf/vm.h b/inc/hf/vm.h
index e421a3d..0d7735e 100644
--- a/inc/hf/vm.h
+++ b/inc/hf/vm.h
@@ -142,8 +142,10 @@
struct vm_locked vm2;
};
-bool vm_init(spci_vcpu_count_t vcpu_count, struct mpool *ppool,
- struct vm **new_vm);
+struct vm *vm_init(spci_vm_id_t id, spci_vcpu_count_t vcpu_count,
+ struct mpool *ppool);
+bool vm_init_next(spci_vcpu_count_t vcpu_count, struct mpool *ppool,
+ struct vm **new_vm);
spci_vm_count_t vm_get_count(void);
struct vm *vm_find(spci_vm_id_t id);
struct vm_locked vm_lock(struct vm *vm);
diff --git a/inc/vmapi/hf/types.h b/inc/vmapi/hf/types.h
index 1f0d5d4..dc9f7a1 100644
--- a/inc/vmapi/hf/types.h
+++ b/inc/vmapi/hf/types.h
@@ -50,6 +50,12 @@
#define HF_PRIMARY_VM_INDEX 0
#define HF_PRIMARY_VM_ID (HF_VM_ID_OFFSET + HF_PRIMARY_VM_INDEX)
+/**
+ * The special VM ID reserved for the OS running in the trusted execution
+ * environment, e.g. secure EL1 on AArch64.
+ */
+#define HF_TEE_VM_ID 0x8000
+
/** Sleep value for an indefinite period of time. */
#define HF_SLEEP_INDEFINITE 0xffffffffffffffff
diff --git a/src/load.c b/src/load.c
index a8bb759..e2a272e 100644
--- a/src/load.c
+++ b/src/load.c
@@ -34,6 +34,9 @@
#include "vmapi/hf/call.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.
@@ -134,7 +137,7 @@
return false;
}
- if (!vm_init(MAX_CPUS, ppool, &vm)) {
+ if (!vm_init_next(MAX_CPUS, ppool, &vm)) {
dlog("Unable to initialise primary vm\n");
return false;
}
@@ -214,7 +217,7 @@
return false;
}
- if (!vm_init(manifest_vm->secondary.vcpu_count, ppool, &vm)) {
+ if (!vm_init_next(manifest_vm->secondary.vcpu_count, ppool, &vm)) {
dlog("Unable to initialise VM.\n");
return false;
}
@@ -333,6 +336,7 @@
struct boot_params_update *update, struct mpool *ppool)
{
struct vm *primary;
+ struct vm *tee;
struct mem_range mem_ranges_available[MAX_MEM_RANGES];
struct vm_locked primary_vm_locked;
size_t i;
@@ -344,6 +348,15 @@
return false;
}
+ /*
+ * Initialise the dummy VM which represents TrustZone, and set up its
+ * RX/TX buffers.
+ */
+ tee = vm_init(HF_TEE_VM_ID, 0, ppool);
+ CHECK(tee != NULL);
+ tee->mailbox.send = &tee_send_buffer;
+ tee->mailbox.recv = &tee_recv_buffer;
+
static_assert(
sizeof(mem_ranges_available) == sizeof(params->mem_ranges),
"mem_range arrays must be the same size for memcpy.");
diff --git a/src/manifest.c b/src/manifest.c
index c3b5566..d574e55 100644
--- a/src/manifest.c
+++ b/src/manifest.c
@@ -33,6 +33,8 @@
#define VM_NAME_BUF_SIZE (2 + 5 + 1) /* "vm" + number + null terminator */
static_assert(MAX_VMS <= 99999, "Insufficient VM_NAME_BUF_SIZE");
+static_assert(HF_TEE_VM_ID > MAX_VMS,
+ "TrustZone VM ID clashes with normal VM range.");
/**
* Generates a string with the two letters "vm" followed by an integer.
diff --git a/src/vm.c b/src/vm.c
index 0f36e21..7237dfb 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -27,19 +27,24 @@
#include "vmapi/hf/call.h"
static struct vm vms[MAX_VMS];
+static struct vm tee_vm;
static spci_vm_count_t vm_count;
-bool vm_init(spci_vcpu_count_t vcpu_count, struct mpool *ppool,
- struct vm **new_vm)
+struct vm *vm_init(spci_vm_id_t id, spci_vcpu_count_t vcpu_count,
+ struct mpool *ppool)
{
uint32_t i;
struct vm *vm;
- if (vm_count >= MAX_VMS) {
- return false;
- }
+ if (id == HF_TEE_VM_ID) {
+ vm = &tee_vm;
+ } else {
+ uint16_t vm_index = id - HF_VM_ID_OFFSET;
- vm = &vms[vm_count];
+ CHECK(id >= HF_VM_ID_OFFSET);
+ CHECK(vm_index < ARRAY_SIZE(vms));
+ vm = &vms[vm_index];
+ }
memset_s(vm, sizeof(*vm), 0, sizeof(*vm));
@@ -47,14 +52,13 @@
list_init(&vm->mailbox.ready_list);
sl_init(&vm->lock);
- /* Generate IDs based on an offset, as low IDs e.g., 0, are reserved */
- vm->id = vm_count + HF_VM_ID_OFFSET;
+ vm->id = id;
vm->vcpu_count = vcpu_count;
vm->mailbox.state = MAILBOX_STATE_EMPTY;
atomic_init(&vm->aborting, false);
if (!mm_vm_init(&vm->ptable, ppool)) {
- return false;
+ return NULL;
}
/* Initialise waiter entries. */
@@ -69,8 +73,22 @@
vcpu_init(vm_get_vcpu(vm, i), vm);
}
+ return vm;
+}
+
+bool vm_init_next(spci_vcpu_count_t vcpu_count, struct mpool *ppool,
+ struct vm **new_vm)
+{
+ if (vm_count >= MAX_VMS) {
+ return false;
+ }
+
+ /* Generate IDs based on an offset, as low IDs e.g., 0, are reserved */
+ *new_vm = vm_init(vm_count + HF_VM_ID_OFFSET, vcpu_count, ppool);
+ if (*new_vm == NULL) {
+ return false;
+ }
++vm_count;
- *new_vm = vm;
return true;
}
@@ -89,6 +107,13 @@
return NULL;
}
+ if (id == HF_TEE_VM_ID) {
+ if (tee_vm.id == HF_TEE_VM_ID) {
+ return &tee_vm;
+ }
+ return NULL;
+ }
+
index = id - HF_VM_ID_OFFSET;
/* Ensure the VM is initialized. */
diff --git a/src/vm_test.cc b/src/vm_test.cc
index fb33ec4..7bec31a 100644
--- a/src/vm_test.cc
+++ b/src/vm_test.cc
@@ -67,7 +67,7 @@
struct_vm *vm;
struct vm_locked vm_locked;
- vm_init(1, &ppool, &vm);
+ EXPECT_TRUE(vm_init_next(1, &ppool, &vm));
vm_locked = vm_lock(vm);
ASSERT_TRUE(mm_vm_init(&vm->ptable, &ppool));
EXPECT_TRUE(vm_unmap_hypervisor(vm_locked, &ppool));