summaryrefslogtreecommitdiff
path: root/services
diff options
context:
space:
mode:
authorAntonio Nino Diaz <antonio.ninodiaz@arm.com>2019-03-27 13:45:52 +0000
committerAntonio Nino Diaz <antonio.ninodiaz@arm.com>2019-04-03 10:51:31 +0100
commit75f364b3e09c16e67dfca27318bc0fec668d688f (patch)
tree565bde3d335fcf7fef1d20407a393c47d1006104 /services
parent014df18b8e6cc2e6accb8230b950d7f3263f497a (diff)
SPM: Adjust size of virtual address space per partition
Rather than using a fixed virtual address space size, read all regions in the resource description of each partition and restrict the virtual address space size to the one the partition actually needs. This also allows SPM to take advantage of the extension ARMv8.4-TTST if the virtual address space size is small enough. Change-Id: I8646aa95e659136b58b44b040364cdee631f7e82 Signed-off-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
Diffstat (limited to 'services')
-rw-r--r--services/std_svc/spm/spm_xlat.c58
1 files changed, 56 insertions, 2 deletions
diff --git a/services/std_svc/spm/spm_xlat.c b/services/std_svc/spm/spm_xlat.c
index 1619f972..5d5bc519 100644
--- a/services/std_svc/spm/spm_xlat.c
+++ b/services/std_svc/spm/spm_xlat.c
@@ -5,6 +5,7 @@
*/
#include <arch.h>
+#include <arch_features.h>
#include <arch_helpers.h>
#include <assert.h>
#include <errno.h>
@@ -64,6 +65,8 @@ static OBJECT_POOL(sp_xlat_ctx_pool, sp_xlat_ctx, sizeof(xlat_ctx_t),
/* Get handle of Secure Partition translation context */
void spm_sp_xlat_context_alloc(sp_context_t *sp_ctx)
{
+ /* Allocate xlat context elements */
+
xlat_ctx_t *ctx = pool_alloc(&sp_xlat_ctx_pool);
struct mmap_region *mmap = pool_alloc(&sp_mmap_regions_pool);
@@ -74,8 +77,59 @@ void spm_sp_xlat_context_alloc(sp_context_t *sp_ctx)
int *mapped_regions = pool_alloc(&sp_xlat_mapped_regions_pool);
- xlat_setup_dynamic_ctx(ctx, PLAT_PHY_ADDR_SPACE_SIZE - 1,
- PLAT_VIRT_ADDR_SPACE_SIZE - 1, mmap,
+ /* Calculate the size of the virtual address space needed */
+
+ uintptr_t va_size = 0U;
+ struct sp_rd_sect_mem_region *rdmem;
+
+ for (rdmem = sp_ctx->rd.mem_region; rdmem != NULL; rdmem = rdmem->next) {
+ uintptr_t end_va = (uintptr_t)rdmem->base +
+ (uintptr_t)rdmem->size;
+
+ if (end_va > va_size)
+ va_size = end_va;
+ }
+
+ if (va_size == 0U) {
+ ERROR("No regions in resource description.\n");
+ panic();
+ }
+
+ /*
+ * Get the power of two that is greater or equal to the top VA. The
+ * values of base and size in the resource description are 32-bit wide
+ * so the values will never overflow when using a uintptr_t.
+ */
+ if (!IS_POWER_OF_TWO(va_size)) {
+ va_size = 1ULL <<
+ ((sizeof(va_size) * 8) - __builtin_clzll(va_size));
+ }
+
+ if (va_size > PLAT_VIRT_ADDR_SPACE_SIZE) {
+ ERROR("Resource description requested too much virtual memory.\n");
+ panic();
+ }
+
+ uintptr_t min_va_size;
+
+ /* The following sizes are only valid for 4KB pages */
+ assert(PAGE_SIZE == (4U * 1024U));
+
+ if (is_armv8_4_ttst_present()) {
+ VERBOSE("Using ARMv8.4-TTST\n");
+ min_va_size = 1ULL << (64 - TCR_TxSZ_MAX_TTST);
+ } else {
+ min_va_size = 1ULL << (64 - TCR_TxSZ_MAX);
+ }
+
+ if (va_size < min_va_size) {
+ va_size = min_va_size;
+ }
+
+ /* Initialize xlat context */
+
+ xlat_setup_dynamic_ctx(ctx, PLAT_PHY_ADDR_SPACE_SIZE - 1ULL,
+ va_size - 1ULL, mmap,
PLAT_SP_IMAGE_MMAP_REGIONS, tables,
PLAT_SP_IMAGE_MAX_XLAT_TABLES, base_table,
EL1_EL0_REGIME, mapped_regions);