feat: consume spmc manifest ns memory nodes
The SPMC manifest provisions for NS memory ranges. The SPMC is aware
about the platform specific NS memory that a normal world client is able
to share/lend/donate. Similarly, it provides information about which NS
memory regions a SP is allowed to map in its SP manifest.
Signed-off-by: Olivier Deprez <olivier.deprez@arm.com>
Signed-off-by: J-Alves <joao.alves@arm.com>
Change-Id: I3f1545f79ce36e544387c707c7e024fef67f0286
diff --git a/inc/hf/arch/other_world.h b/inc/hf/arch/other_world.h
index 1d34f56..af401d1 100644
--- a/inc/hf/arch/other_world.h
+++ b/inc/hf/arch/other_world.h
@@ -8,8 +8,11 @@
#pragma once
+#include "hf/boot_params.h"
#include "hf/ffa.h"
#include "hf/vm.h"
-bool arch_other_world_vm_init(struct vm *other_world_vm, struct mpool *ppool);
+bool arch_other_world_vm_init(struct vm *other_world_vm,
+ const struct boot_params *params,
+ struct mpool *ppool);
struct ffa_value arch_other_world_call(struct ffa_value args);
diff --git a/inc/hf/boot_params.h b/inc/hf/boot_params.h
index 667f7bde..c828d07 100644
--- a/inc/hf/boot_params.h
+++ b/inc/hf/boot_params.h
@@ -29,6 +29,8 @@
size_t cpu_count;
struct mem_range mem_ranges[MAX_MEM_RANGES];
size_t mem_ranges_count;
+ struct mem_range ns_mem_ranges[MAX_MEM_RANGES];
+ size_t ns_mem_ranges_count;
struct mem_range device_mem_ranges[MAX_DEVICE_MEM_RANGES];
size_t device_mem_ranges_count;
paddr_t initrd_begin;
diff --git a/src/arch/aarch64/hypervisor/other_world.c b/src/arch/aarch64/hypervisor/other_world.c
index 652b645..a58aa76 100644
--- a/src/arch/aarch64/hypervisor/other_world.c
+++ b/src/arch/aarch64/hypervisor/other_world.c
@@ -17,28 +17,51 @@
#include "smc.h"
-bool arch_other_world_vm_init(struct vm *other_world_vm, struct mpool *ppool)
+bool arch_other_world_vm_init(struct vm *other_world_vm,
+ const struct boot_params *params,
+ struct mpool *ppool)
{
+ const char *err_msg =
+ "Unable to initialise address space for Other world VM.\n";
struct vm_locked other_world_vm_locked;
bool ret = false;
+ uint32_t i;
- /* 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;
- }
-
/* Enabling all communication methods for the other world. */
other_world_vm->messaging_method =
FFA_PARTITION_DIRECT_REQ_RECV | FFA_PARTITION_DIRECT_REQ_SEND;
+ /*
+ * If no NS memory ranges provided, map the full 1TB system address
+ * space to the other world VM.
+ */
+ if (params->ns_mem_ranges_count == 0) {
+ dlog_warning("Missing NS memory ranges, default to 1TB.\n");
+ 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("%s", err_msg);
+ goto out;
+ }
+ }
+
+ /* Map NS mem ranges to "Other world VM" Stage-2 PTs. */
+ for (i = 0; i < params->ns_mem_ranges_count; i++) {
+ if (!vm_identity_map(
+ other_world_vm_locked,
+ params->ns_mem_ranges[i].begin,
+ params->ns_mem_ranges[i].end,
+ MM_MODE_R | MM_MODE_W | MM_MODE_X | MM_MODE_NS,
+ ppool, NULL)) {
+ dlog_error("%s", err_msg);
+ goto out;
+ }
+ }
+
ret = true;
out:
diff --git a/src/boot_flow/common.c b/src/boot_flow/common.c
index 20b5deb..3e93c33 100644
--- a/src/boot_flow/common.c
+++ b/src/boot_flow/common.c
@@ -17,6 +17,7 @@
bool boot_flow_get_params(struct boot_params *p, const struct fdt *fdt)
{
struct string memory = STRING_INIT("memory");
+ struct string ns_memory = STRING_INIT("ns-memory");
struct string device_memory = STRING_INIT("device-memory");
p->mem_ranges_count = 0;
@@ -29,7 +30,9 @@
&p->mem_ranges_count, MAX_MEM_RANGES) &&
fdt_find_memory_ranges(fdt, &device_memory, p->device_mem_ranges,
&p->device_mem_ranges_count,
- MAX_DEVICE_MEM_RANGES);
+ MAX_DEVICE_MEM_RANGES) &&
+ fdt_find_memory_ranges(fdt, &ns_memory, p->ns_mem_ranges,
+ &p->ns_mem_ranges_count, MAX_MEM_RANGES);
}
/**
diff --git a/src/load.c b/src/load.c
index df18403..4ed3c0c 100644
--- a/src/load.c
+++ b/src/load.c
@@ -929,7 +929,8 @@
return true;
}
-static bool init_other_world_vm(struct mpool *ppool)
+static bool init_other_world_vm(const struct boot_params *params,
+ struct mpool *ppool)
{
struct vm *other_world_vm;
size_t i;
@@ -949,7 +950,7 @@
vcpu->cpu = cpu;
}
- return arch_other_world_vm_init(other_world_vm, ppool);
+ return arch_other_world_vm_init(other_world_vm, params, ppool);
}
/*
@@ -979,7 +980,7 @@
}
}
- if (!init_other_world_vm(ppool)) {
+ if (!init_other_world_vm(params, ppool)) {
return false;
}