diff --git a/services/std_svc/spm/sp_setup.c b/services/std_svc/spm/sp_setup.c deleted file mode 100644 index aca779f..0000000 --- a/services/std_svc/spm/sp_setup.c +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "spm_private.h" -#include "spm_shim_private.h" - -/* Setup context of the Secure Partition */ -void spm_sp_setup(sp_context_t *sp_ctx) -{ - cpu_context_t *ctx = &(sp_ctx->cpu_ctx); - - /* - * Initialize CPU context - * ---------------------- - */ - - entry_point_info_t ep_info = {0}; - - SET_PARAM_HEAD(&ep_info, PARAM_EP, VERSION_1, SECURE | EP_ST_ENABLE); - - /* Setup entrypoint and SPSR */ - ep_info.pc = sp_ctx->rd.attribute.entrypoint; - ep_info.spsr = SPSR_64(MODE_EL0, MODE_SP_EL0, DISABLE_ALL_EXCEPTIONS); - - /* - * X0: Unused (MBZ). - * X1: Unused (MBZ). - * X2: cookie value (Implementation Defined) - * X3: cookie value (Implementation Defined) - * X4 to X7 = 0 - */ - ep_info.args.arg0 = 0; - ep_info.args.arg1 = 0; - ep_info.args.arg2 = PLAT_SPM_COOKIE_0; - ep_info.args.arg3 = PLAT_SPM_COOKIE_1; - - cm_setup_context(ctx, &ep_info); - - /* - * Setup translation tables - * ------------------------ - */ - - sp_map_memory_regions(sp_ctx); - - /* - * MMU-related registers - * --------------------- - */ - xlat_ctx_t *xlat_ctx = sp_ctx->xlat_ctx_handle; - - uint64_t mmu_cfg_params[MMU_CFG_PARAM_MAX]; - - setup_mmu_cfg((uint64_t *)&mmu_cfg_params, 0, xlat_ctx->base_table, - xlat_ctx->pa_max_address, xlat_ctx->va_max_address, - EL1_EL0_REGIME); - - write_ctx_reg(get_sysregs_ctx(ctx), CTX_MAIR_EL1, - mmu_cfg_params[MMU_CFG_MAIR]); - - write_ctx_reg(get_sysregs_ctx(ctx), CTX_TCR_EL1, - mmu_cfg_params[MMU_CFG_TCR]); - - write_ctx_reg(get_sysregs_ctx(ctx), CTX_TTBR0_EL1, - mmu_cfg_params[MMU_CFG_TTBR0]); - - /* Setup SCTLR_EL1 */ - u_register_t sctlr_el1 = read_ctx_reg(get_sysregs_ctx(ctx), CTX_SCTLR_EL1); - - sctlr_el1 |= - /*SCTLR_EL1_RES1 |*/ - /* Don't trap DC CVAU, DC CIVAC, DC CVAC, DC CVAP, or IC IVAU */ - SCTLR_UCI_BIT | - /* RW regions at xlat regime EL1&0 are forced to be XN. */ - SCTLR_WXN_BIT | - /* Don't trap to EL1 execution of WFI or WFE at EL0. */ - SCTLR_NTWI_BIT | SCTLR_NTWE_BIT | - /* Don't trap to EL1 accesses to CTR_EL0 from EL0. */ - SCTLR_UCT_BIT | - /* Don't trap to EL1 execution of DZ ZVA at EL0. */ - SCTLR_DZE_BIT | - /* Enable SP Alignment check for EL0 */ - SCTLR_SA0_BIT | - /* Allow cacheable data and instr. accesses to normal memory. */ - SCTLR_C_BIT | SCTLR_I_BIT | - /* Alignment fault checking enabled when at EL1 and EL0. */ - SCTLR_A_BIT | - /* Enable MMU. */ - SCTLR_M_BIT - ; - - sctlr_el1 &= ~( - /* Explicit data accesses at EL0 are little-endian. */ - SCTLR_E0E_BIT | - /* Accesses to DAIF from EL0 are trapped to EL1. */ - SCTLR_UMA_BIT - ); - - write_ctx_reg(get_sysregs_ctx(ctx), CTX_SCTLR_EL1, sctlr_el1); - - /* - * Setup other system registers - * ---------------------------- - */ - - /* Shim Exception Vector Base Address */ - write_ctx_reg(get_sysregs_ctx(ctx), CTX_VBAR_EL1, - SPM_SHIM_EXCEPTIONS_PTR); - - /* - * FPEN: Allow the Secure Partition to access FP/SIMD registers. - * Note that SPM will not do any saving/restoring of these registers on - * behalf of the SP. This falls under the SP's responsibility. - * TTA: Enable access to trace registers. - * ZEN (v8.2): Trap SVE instructions and access to SVE registers. - */ - write_ctx_reg(get_sysregs_ctx(ctx), CTX_CPACR_EL1, - CPACR_EL1_FPEN(CPACR_EL1_FP_TRAP_NONE)); - - /* - * Prepare shared buffers - * ---------------------- - */ - - /* Initialize SPRT queues */ - sprt_initialize_queues((void *)sp_ctx->spm_sp_buffer_base, - sp_ctx->spm_sp_buffer_size); -} diff --git a/services/std_svc/spm/sp_xlat.c b/services/std_svc/spm/sp_xlat.c deleted file mode 100644 index bbe392d..0000000 --- a/services/std_svc/spm/sp_xlat.c +++ /dev/null @@ -1,312 +0,0 @@ -/* - * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "spm_private.h" -#include "spm_shim_private.h" - -/******************************************************************************* - * Instantiation of translation table context - ******************************************************************************/ - -/* Place translation tables by default along with the ones used by BL31. */ -#ifndef PLAT_SP_IMAGE_XLAT_SECTION_NAME -#define PLAT_SP_IMAGE_XLAT_SECTION_NAME "xlat_table" -#endif - -/* - * Allocate elements of the translation contexts for the Secure Partitions. - */ - -/* Allocate an array of mmap_region per partition. */ -static struct mmap_region sp_mmap_regions[PLAT_SP_IMAGE_MMAP_REGIONS + 1] - [PLAT_SPM_MAX_PARTITIONS]; -static OBJECT_POOL(sp_mmap_regions_pool, sp_mmap_regions, - sizeof(mmap_region_t) * (PLAT_SP_IMAGE_MMAP_REGIONS + 1), - PLAT_SPM_MAX_PARTITIONS); - -/* Allocate individual translation tables. */ -static uint64_t sp_xlat_tables[XLAT_TABLE_ENTRIES] - [(PLAT_SP_IMAGE_MAX_XLAT_TABLES + 1) * PLAT_SPM_MAX_PARTITIONS] - __aligned(XLAT_TABLE_SIZE) __section(PLAT_SP_IMAGE_XLAT_SECTION_NAME); -static OBJECT_POOL(sp_xlat_tables_pool, sp_xlat_tables, - XLAT_TABLE_ENTRIES * sizeof(uint64_t), - (PLAT_SP_IMAGE_MAX_XLAT_TABLES + 1) * PLAT_SPM_MAX_PARTITIONS); - -/* Allocate base translation tables. */ -static uint64_t sp_xlat_base_tables - [GET_NUM_BASE_LEVEL_ENTRIES(PLAT_VIRT_ADDR_SPACE_SIZE)] - [PLAT_SPM_MAX_PARTITIONS] - __aligned(GET_NUM_BASE_LEVEL_ENTRIES(PLAT_VIRT_ADDR_SPACE_SIZE) - * sizeof(uint64_t)) - __section(PLAT_SP_IMAGE_XLAT_SECTION_NAME); -static OBJECT_POOL(sp_xlat_base_tables_pool, sp_xlat_base_tables, - GET_NUM_BASE_LEVEL_ENTRIES(PLAT_VIRT_ADDR_SPACE_SIZE) * sizeof(uint64_t), - PLAT_SPM_MAX_PARTITIONS); - -/* Allocate arrays. */ -static int sp_xlat_mapped_regions[PLAT_SP_IMAGE_MAX_XLAT_TABLES] - [PLAT_SPM_MAX_PARTITIONS]; -static OBJECT_POOL(sp_xlat_mapped_regions_pool, sp_xlat_mapped_regions, - sizeof(int) * PLAT_SP_IMAGE_MAX_XLAT_TABLES, PLAT_SPM_MAX_PARTITIONS); - -/* Allocate individual contexts. */ -static xlat_ctx_t sp_xlat_ctx[PLAT_SPM_MAX_PARTITIONS]; -static OBJECT_POOL(sp_xlat_ctx_pool, sp_xlat_ctx, sizeof(xlat_ctx_t), - PLAT_SPM_MAX_PARTITIONS); - -/* Get handle of Secure Partition translation context */ -xlat_ctx_t *spm_sp_xlat_context_alloc(void) -{ - xlat_ctx_t *ctx = pool_alloc(&sp_xlat_ctx_pool); - - struct mmap_region *mmap = pool_alloc(&sp_mmap_regions_pool); - - uint64_t *base_table = pool_alloc(&sp_xlat_base_tables_pool); - uint64_t **tables = pool_alloc_n(&sp_xlat_tables_pool, - PLAT_SP_IMAGE_MAX_XLAT_TABLES); - - 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, - PLAT_SP_IMAGE_MMAP_REGIONS, tables, - PLAT_SP_IMAGE_MAX_XLAT_TABLES, base_table, - EL1_EL0_REGIME, mapped_regions); - - return ctx; -}; - -/******************************************************************************* - * Functions to allocate memory for regions. - ******************************************************************************/ - -/* - * The region with base PLAT_SPM_HEAP_BASE and size PLAT_SPM_HEAP_SIZE is - * reserved for SPM to use as heap to allocate memory regions of Secure - * Partitions. This is only done at boot. - */ -static OBJECT_POOL(spm_heap_mem, (void *)PLAT_SPM_HEAP_BASE, 1U, - PLAT_SPM_HEAP_SIZE); - -static uintptr_t spm_alloc_heap(size_t size) -{ - return (uintptr_t)pool_alloc_n(&spm_heap_mem, size); -} - -/******************************************************************************* - * Functions to map memory regions described in the resource description. - ******************************************************************************/ -static unsigned int rdmem_attr_to_mmap_attr(uint32_t attr) -{ - unsigned int index = attr & RD_MEM_MASK; - - const unsigned int mmap_attr_arr[8] = { - MT_DEVICE | MT_RW | MT_SECURE, /* RD_MEM_DEVICE */ - MT_CODE | MT_SECURE, /* RD_MEM_NORMAL_CODE */ - MT_MEMORY | MT_RW | MT_SECURE, /* RD_MEM_NORMAL_DATA */ - MT_MEMORY | MT_RW | MT_SECURE, /* RD_MEM_NORMAL_BSS */ - MT_RO_DATA | MT_SECURE, /* RD_MEM_NORMAL_RODATA */ - MT_MEMORY | MT_RW | MT_SECURE, /* RD_MEM_NORMAL_SPM_SP_SHARED_MEM */ - MT_MEMORY | MT_RW | MT_SECURE, /* RD_MEM_NORMAL_CLIENT_SHARED_MEM */ - MT_MEMORY | MT_RW | MT_SECURE /* RD_MEM_NORMAL_MISCELLANEOUS */ - }; - - if (index >= ARRAY_SIZE(mmap_attr_arr)) { - ERROR("Unsupported RD memory attributes 0x%x\n", attr); - panic(); - } - - return mmap_attr_arr[index]; -} - -/* - * The data provided in the resource description structure is not directly - * compatible with a mmap_region structure. This function handles the conversion - * and maps it. - */ -static void map_rdmem(sp_context_t *sp_ctx, struct sp_rd_sect_mem_region *rdmem) -{ - int rc; - mmap_region_t mmap; - - /* Location of the SP image */ - uintptr_t sp_size = sp_ctx->image_size; - uintptr_t sp_base_va = sp_ctx->rd.attribute.load_address; - unsigned long long sp_base_pa = sp_ctx->image_base; - - /* Location of the memory region to map */ - size_t rd_size = rdmem->size; - uintptr_t rd_base_va = rdmem->base; - unsigned long long rd_base_pa; - - unsigned int memtype = rdmem->attr & RD_MEM_MASK; - - VERBOSE("Adding memory region '%s'\n", rdmem->name); - - mmap.granularity = REGION_DEFAULT_GRANULARITY; - - /* Check if the RD region is inside of the SP image or not */ - int is_outside = (rd_base_va + rd_size <= sp_base_va) || - (sp_base_va + sp_size <= rd_base_va); - - /* Set to 1 if it is needed to zero this region */ - int zero_region = 0; - - switch (memtype) { - case RD_MEM_DEVICE: - /* Device regions are mapped 1:1 */ - rd_base_pa = rd_base_va; - break; - - case RD_MEM_NORMAL_CODE: - case RD_MEM_NORMAL_RODATA: - { - if (is_outside == 1) { - ERROR("Code and rodata sections must be fully contained in the image."); - panic(); - } - - /* Get offset into the image */ - rd_base_pa = sp_base_pa + rd_base_va - sp_base_va; - break; - } - case RD_MEM_NORMAL_DATA: - { - if (is_outside == 1) { - ERROR("Data sections must be fully contained in the image."); - panic(); - } - - rd_base_pa = spm_alloc_heap(rd_size); - - /* Get offset into the image */ - void *img_pa = (void *)(sp_base_pa + rd_base_va - sp_base_va); - - VERBOSE(" Copying data from %p to 0x%llx\n", img_pa, rd_base_pa); - - /* Map destination */ - rc = mmap_add_dynamic_region(rd_base_pa, rd_base_pa, - rd_size, MT_MEMORY | MT_RW | MT_SECURE); - if (rc != 0) { - ERROR("Unable to map data region at EL3: %d\n", rc); - panic(); - } - - /* Copy original data to destination */ - memcpy((void *)rd_base_pa, img_pa, rd_size); - - /* Unmap destination region */ - rc = mmap_remove_dynamic_region(rd_base_pa, rd_size); - if (rc != 0) { - ERROR("Unable to remove data region at EL3: %d\n", rc); - panic(); - } - - break; - } - case RD_MEM_NORMAL_MISCELLANEOUS: - /* Allow SPM to change the attributes of the region. */ - mmap.granularity = PAGE_SIZE; - rd_base_pa = spm_alloc_heap(rd_size); - zero_region = 1; - break; - - case RD_MEM_NORMAL_SPM_SP_SHARED_MEM: - if ((sp_ctx->spm_sp_buffer_base != 0) || - (sp_ctx->spm_sp_buffer_size != 0)) { - ERROR("A partition must have only one SPM<->SP buffer.\n"); - panic(); - } - rd_base_pa = spm_alloc_heap(rd_size); - zero_region = 1; - /* Save location of this buffer, it is needed by SPM */ - sp_ctx->spm_sp_buffer_base = rd_base_pa; - sp_ctx->spm_sp_buffer_size = rd_size; - break; - - case RD_MEM_NORMAL_CLIENT_SHARED_MEM: - /* Fallthrough */ - case RD_MEM_NORMAL_BSS: - rd_base_pa = spm_alloc_heap(rd_size); - zero_region = 1; - break; - - default: - panic(); - } - - mmap.base_pa = rd_base_pa; - mmap.base_va = rd_base_va; - mmap.size = rd_size; - - /* Only S-EL0 mappings supported for now */ - mmap.attr = rdmem_attr_to_mmap_attr(rdmem->attr) | MT_USER; - - VERBOSE(" VA: 0x%lx PA: 0x%llx (0x%lx, attr: 0x%x)\n", - mmap.base_va, mmap.base_pa, mmap.size, mmap.attr); - - /* Map region in the context of the Secure Partition */ - mmap_add_region_ctx(sp_ctx->xlat_ctx_handle, &mmap); - - if (zero_region == 1) { - VERBOSE(" Zeroing region...\n"); - - rc = mmap_add_dynamic_region(mmap.base_pa, mmap.base_pa, - mmap.size, MT_MEMORY | MT_RW | MT_SECURE); - if (rc != 0) { - ERROR("Unable to map memory at EL3 to zero: %d\n", - rc); - panic(); - } - - zeromem((void *)mmap.base_pa, mmap.size); - - /* - * Unmap destination region unless it is the SPM<->SP buffer, - * which must be used by SPM. - */ - if (memtype != RD_MEM_NORMAL_SPM_SP_SHARED_MEM) { - rc = mmap_remove_dynamic_region(rd_base_pa, rd_size); - if (rc != 0) { - ERROR("Unable to remove region at EL3: %d\n", rc); - panic(); - } - } - } -} - -void sp_map_memory_regions(sp_context_t *sp_ctx) -{ - /* This region contains the exception vectors used at S-EL1. */ - const mmap_region_t sel1_exception_vectors = - MAP_REGION_FLAT(SPM_SHIM_EXCEPTIONS_START, - SPM_SHIM_EXCEPTIONS_SIZE, - MT_CODE | MT_SECURE | MT_PRIVILEGED); - - mmap_add_region_ctx(sp_ctx->xlat_ctx_handle, - &sel1_exception_vectors); - - struct sp_rd_sect_mem_region *rdmem; - - for (rdmem = sp_ctx->rd.mem_region; rdmem != NULL; rdmem = rdmem->next) { - map_rdmem(sp_ctx, rdmem); - } - - init_xlat_tables_ctx(sp_ctx->xlat_ctx_handle); -} diff --git a/services/std_svc/spm/spm.mk b/services/std_svc/spm/spm.mk index b52292d..4ba9feb 100644 --- a/services/std_svc/spm/spm.mk +++ b/services/std_svc/spm/spm.mk @@ -16,11 +16,11 @@ SPM_SOURCES := $(addprefix services/std_svc/spm/, \ ${ARCH}/spm_helpers.S \ ${ARCH}/spm_shim_exceptions.S \ - sp_setup.c \ - sp_xlat.c \ spci.c \ spm_buffers.c \ spm_main.c \ + spm_setup.c \ + spm_xlat.c \ sprt.c) \ ${SPRT_LIB_SOURCES} diff --git a/services/std_svc/spm/spm_setup.c b/services/std_svc/spm/spm_setup.c new file mode 100644 index 0000000..aca779f --- /dev/null +++ b/services/std_svc/spm/spm_setup.c @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "spm_private.h" +#include "spm_shim_private.h" + +/* Setup context of the Secure Partition */ +void spm_sp_setup(sp_context_t *sp_ctx) +{ + cpu_context_t *ctx = &(sp_ctx->cpu_ctx); + + /* + * Initialize CPU context + * ---------------------- + */ + + entry_point_info_t ep_info = {0}; + + SET_PARAM_HEAD(&ep_info, PARAM_EP, VERSION_1, SECURE | EP_ST_ENABLE); + + /* Setup entrypoint and SPSR */ + ep_info.pc = sp_ctx->rd.attribute.entrypoint; + ep_info.spsr = SPSR_64(MODE_EL0, MODE_SP_EL0, DISABLE_ALL_EXCEPTIONS); + + /* + * X0: Unused (MBZ). + * X1: Unused (MBZ). + * X2: cookie value (Implementation Defined) + * X3: cookie value (Implementation Defined) + * X4 to X7 = 0 + */ + ep_info.args.arg0 = 0; + ep_info.args.arg1 = 0; + ep_info.args.arg2 = PLAT_SPM_COOKIE_0; + ep_info.args.arg3 = PLAT_SPM_COOKIE_1; + + cm_setup_context(ctx, &ep_info); + + /* + * Setup translation tables + * ------------------------ + */ + + sp_map_memory_regions(sp_ctx); + + /* + * MMU-related registers + * --------------------- + */ + xlat_ctx_t *xlat_ctx = sp_ctx->xlat_ctx_handle; + + uint64_t mmu_cfg_params[MMU_CFG_PARAM_MAX]; + + setup_mmu_cfg((uint64_t *)&mmu_cfg_params, 0, xlat_ctx->base_table, + xlat_ctx->pa_max_address, xlat_ctx->va_max_address, + EL1_EL0_REGIME); + + write_ctx_reg(get_sysregs_ctx(ctx), CTX_MAIR_EL1, + mmu_cfg_params[MMU_CFG_MAIR]); + + write_ctx_reg(get_sysregs_ctx(ctx), CTX_TCR_EL1, + mmu_cfg_params[MMU_CFG_TCR]); + + write_ctx_reg(get_sysregs_ctx(ctx), CTX_TTBR0_EL1, + mmu_cfg_params[MMU_CFG_TTBR0]); + + /* Setup SCTLR_EL1 */ + u_register_t sctlr_el1 = read_ctx_reg(get_sysregs_ctx(ctx), CTX_SCTLR_EL1); + + sctlr_el1 |= + /*SCTLR_EL1_RES1 |*/ + /* Don't trap DC CVAU, DC CIVAC, DC CVAC, DC CVAP, or IC IVAU */ + SCTLR_UCI_BIT | + /* RW regions at xlat regime EL1&0 are forced to be XN. */ + SCTLR_WXN_BIT | + /* Don't trap to EL1 execution of WFI or WFE at EL0. */ + SCTLR_NTWI_BIT | SCTLR_NTWE_BIT | + /* Don't trap to EL1 accesses to CTR_EL0 from EL0. */ + SCTLR_UCT_BIT | + /* Don't trap to EL1 execution of DZ ZVA at EL0. */ + SCTLR_DZE_BIT | + /* Enable SP Alignment check for EL0 */ + SCTLR_SA0_BIT | + /* Allow cacheable data and instr. accesses to normal memory. */ + SCTLR_C_BIT | SCTLR_I_BIT | + /* Alignment fault checking enabled when at EL1 and EL0. */ + SCTLR_A_BIT | + /* Enable MMU. */ + SCTLR_M_BIT + ; + + sctlr_el1 &= ~( + /* Explicit data accesses at EL0 are little-endian. */ + SCTLR_E0E_BIT | + /* Accesses to DAIF from EL0 are trapped to EL1. */ + SCTLR_UMA_BIT + ); + + write_ctx_reg(get_sysregs_ctx(ctx), CTX_SCTLR_EL1, sctlr_el1); + + /* + * Setup other system registers + * ---------------------------- + */ + + /* Shim Exception Vector Base Address */ + write_ctx_reg(get_sysregs_ctx(ctx), CTX_VBAR_EL1, + SPM_SHIM_EXCEPTIONS_PTR); + + /* + * FPEN: Allow the Secure Partition to access FP/SIMD registers. + * Note that SPM will not do any saving/restoring of these registers on + * behalf of the SP. This falls under the SP's responsibility. + * TTA: Enable access to trace registers. + * ZEN (v8.2): Trap SVE instructions and access to SVE registers. + */ + write_ctx_reg(get_sysregs_ctx(ctx), CTX_CPACR_EL1, + CPACR_EL1_FPEN(CPACR_EL1_FP_TRAP_NONE)); + + /* + * Prepare shared buffers + * ---------------------- + */ + + /* Initialize SPRT queues */ + sprt_initialize_queues((void *)sp_ctx->spm_sp_buffer_base, + sp_ctx->spm_sp_buffer_size); +} diff --git a/services/std_svc/spm/spm_xlat.c b/services/std_svc/spm/spm_xlat.c new file mode 100644 index 0000000..bbe392d --- /dev/null +++ b/services/std_svc/spm/spm_xlat.c @@ -0,0 +1,312 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "spm_private.h" +#include "spm_shim_private.h" + +/******************************************************************************* + * Instantiation of translation table context + ******************************************************************************/ + +/* Place translation tables by default along with the ones used by BL31. */ +#ifndef PLAT_SP_IMAGE_XLAT_SECTION_NAME +#define PLAT_SP_IMAGE_XLAT_SECTION_NAME "xlat_table" +#endif + +/* + * Allocate elements of the translation contexts for the Secure Partitions. + */ + +/* Allocate an array of mmap_region per partition. */ +static struct mmap_region sp_mmap_regions[PLAT_SP_IMAGE_MMAP_REGIONS + 1] + [PLAT_SPM_MAX_PARTITIONS]; +static OBJECT_POOL(sp_mmap_regions_pool, sp_mmap_regions, + sizeof(mmap_region_t) * (PLAT_SP_IMAGE_MMAP_REGIONS + 1), + PLAT_SPM_MAX_PARTITIONS); + +/* Allocate individual translation tables. */ +static uint64_t sp_xlat_tables[XLAT_TABLE_ENTRIES] + [(PLAT_SP_IMAGE_MAX_XLAT_TABLES + 1) * PLAT_SPM_MAX_PARTITIONS] + __aligned(XLAT_TABLE_SIZE) __section(PLAT_SP_IMAGE_XLAT_SECTION_NAME); +static OBJECT_POOL(sp_xlat_tables_pool, sp_xlat_tables, + XLAT_TABLE_ENTRIES * sizeof(uint64_t), + (PLAT_SP_IMAGE_MAX_XLAT_TABLES + 1) * PLAT_SPM_MAX_PARTITIONS); + +/* Allocate base translation tables. */ +static uint64_t sp_xlat_base_tables + [GET_NUM_BASE_LEVEL_ENTRIES(PLAT_VIRT_ADDR_SPACE_SIZE)] + [PLAT_SPM_MAX_PARTITIONS] + __aligned(GET_NUM_BASE_LEVEL_ENTRIES(PLAT_VIRT_ADDR_SPACE_SIZE) + * sizeof(uint64_t)) + __section(PLAT_SP_IMAGE_XLAT_SECTION_NAME); +static OBJECT_POOL(sp_xlat_base_tables_pool, sp_xlat_base_tables, + GET_NUM_BASE_LEVEL_ENTRIES(PLAT_VIRT_ADDR_SPACE_SIZE) * sizeof(uint64_t), + PLAT_SPM_MAX_PARTITIONS); + +/* Allocate arrays. */ +static int sp_xlat_mapped_regions[PLAT_SP_IMAGE_MAX_XLAT_TABLES] + [PLAT_SPM_MAX_PARTITIONS]; +static OBJECT_POOL(sp_xlat_mapped_regions_pool, sp_xlat_mapped_regions, + sizeof(int) * PLAT_SP_IMAGE_MAX_XLAT_TABLES, PLAT_SPM_MAX_PARTITIONS); + +/* Allocate individual contexts. */ +static xlat_ctx_t sp_xlat_ctx[PLAT_SPM_MAX_PARTITIONS]; +static OBJECT_POOL(sp_xlat_ctx_pool, sp_xlat_ctx, sizeof(xlat_ctx_t), + PLAT_SPM_MAX_PARTITIONS); + +/* Get handle of Secure Partition translation context */ +xlat_ctx_t *spm_sp_xlat_context_alloc(void) +{ + xlat_ctx_t *ctx = pool_alloc(&sp_xlat_ctx_pool); + + struct mmap_region *mmap = pool_alloc(&sp_mmap_regions_pool); + + uint64_t *base_table = pool_alloc(&sp_xlat_base_tables_pool); + uint64_t **tables = pool_alloc_n(&sp_xlat_tables_pool, + PLAT_SP_IMAGE_MAX_XLAT_TABLES); + + 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, + PLAT_SP_IMAGE_MMAP_REGIONS, tables, + PLAT_SP_IMAGE_MAX_XLAT_TABLES, base_table, + EL1_EL0_REGIME, mapped_regions); + + return ctx; +}; + +/******************************************************************************* + * Functions to allocate memory for regions. + ******************************************************************************/ + +/* + * The region with base PLAT_SPM_HEAP_BASE and size PLAT_SPM_HEAP_SIZE is + * reserved for SPM to use as heap to allocate memory regions of Secure + * Partitions. This is only done at boot. + */ +static OBJECT_POOL(spm_heap_mem, (void *)PLAT_SPM_HEAP_BASE, 1U, + PLAT_SPM_HEAP_SIZE); + +static uintptr_t spm_alloc_heap(size_t size) +{ + return (uintptr_t)pool_alloc_n(&spm_heap_mem, size); +} + +/******************************************************************************* + * Functions to map memory regions described in the resource description. + ******************************************************************************/ +static unsigned int rdmem_attr_to_mmap_attr(uint32_t attr) +{ + unsigned int index = attr & RD_MEM_MASK; + + const unsigned int mmap_attr_arr[8] = { + MT_DEVICE | MT_RW | MT_SECURE, /* RD_MEM_DEVICE */ + MT_CODE | MT_SECURE, /* RD_MEM_NORMAL_CODE */ + MT_MEMORY | MT_RW | MT_SECURE, /* RD_MEM_NORMAL_DATA */ + MT_MEMORY | MT_RW | MT_SECURE, /* RD_MEM_NORMAL_BSS */ + MT_RO_DATA | MT_SECURE, /* RD_MEM_NORMAL_RODATA */ + MT_MEMORY | MT_RW | MT_SECURE, /* RD_MEM_NORMAL_SPM_SP_SHARED_MEM */ + MT_MEMORY | MT_RW | MT_SECURE, /* RD_MEM_NORMAL_CLIENT_SHARED_MEM */ + MT_MEMORY | MT_RW | MT_SECURE /* RD_MEM_NORMAL_MISCELLANEOUS */ + }; + + if (index >= ARRAY_SIZE(mmap_attr_arr)) { + ERROR("Unsupported RD memory attributes 0x%x\n", attr); + panic(); + } + + return mmap_attr_arr[index]; +} + +/* + * The data provided in the resource description structure is not directly + * compatible with a mmap_region structure. This function handles the conversion + * and maps it. + */ +static void map_rdmem(sp_context_t *sp_ctx, struct sp_rd_sect_mem_region *rdmem) +{ + int rc; + mmap_region_t mmap; + + /* Location of the SP image */ + uintptr_t sp_size = sp_ctx->image_size; + uintptr_t sp_base_va = sp_ctx->rd.attribute.load_address; + unsigned long long sp_base_pa = sp_ctx->image_base; + + /* Location of the memory region to map */ + size_t rd_size = rdmem->size; + uintptr_t rd_base_va = rdmem->base; + unsigned long long rd_base_pa; + + unsigned int memtype = rdmem->attr & RD_MEM_MASK; + + VERBOSE("Adding memory region '%s'\n", rdmem->name); + + mmap.granularity = REGION_DEFAULT_GRANULARITY; + + /* Check if the RD region is inside of the SP image or not */ + int is_outside = (rd_base_va + rd_size <= sp_base_va) || + (sp_base_va + sp_size <= rd_base_va); + + /* Set to 1 if it is needed to zero this region */ + int zero_region = 0; + + switch (memtype) { + case RD_MEM_DEVICE: + /* Device regions are mapped 1:1 */ + rd_base_pa = rd_base_va; + break; + + case RD_MEM_NORMAL_CODE: + case RD_MEM_NORMAL_RODATA: + { + if (is_outside == 1) { + ERROR("Code and rodata sections must be fully contained in the image."); + panic(); + } + + /* Get offset into the image */ + rd_base_pa = sp_base_pa + rd_base_va - sp_base_va; + break; + } + case RD_MEM_NORMAL_DATA: + { + if (is_outside == 1) { + ERROR("Data sections must be fully contained in the image."); + panic(); + } + + rd_base_pa = spm_alloc_heap(rd_size); + + /* Get offset into the image */ + void *img_pa = (void *)(sp_base_pa + rd_base_va - sp_base_va); + + VERBOSE(" Copying data from %p to 0x%llx\n", img_pa, rd_base_pa); + + /* Map destination */ + rc = mmap_add_dynamic_region(rd_base_pa, rd_base_pa, + rd_size, MT_MEMORY | MT_RW | MT_SECURE); + if (rc != 0) { + ERROR("Unable to map data region at EL3: %d\n", rc); + panic(); + } + + /* Copy original data to destination */ + memcpy((void *)rd_base_pa, img_pa, rd_size); + + /* Unmap destination region */ + rc = mmap_remove_dynamic_region(rd_base_pa, rd_size); + if (rc != 0) { + ERROR("Unable to remove data region at EL3: %d\n", rc); + panic(); + } + + break; + } + case RD_MEM_NORMAL_MISCELLANEOUS: + /* Allow SPM to change the attributes of the region. */ + mmap.granularity = PAGE_SIZE; + rd_base_pa = spm_alloc_heap(rd_size); + zero_region = 1; + break; + + case RD_MEM_NORMAL_SPM_SP_SHARED_MEM: + if ((sp_ctx->spm_sp_buffer_base != 0) || + (sp_ctx->spm_sp_buffer_size != 0)) { + ERROR("A partition must have only one SPM<->SP buffer.\n"); + panic(); + } + rd_base_pa = spm_alloc_heap(rd_size); + zero_region = 1; + /* Save location of this buffer, it is needed by SPM */ + sp_ctx->spm_sp_buffer_base = rd_base_pa; + sp_ctx->spm_sp_buffer_size = rd_size; + break; + + case RD_MEM_NORMAL_CLIENT_SHARED_MEM: + /* Fallthrough */ + case RD_MEM_NORMAL_BSS: + rd_base_pa = spm_alloc_heap(rd_size); + zero_region = 1; + break; + + default: + panic(); + } + + mmap.base_pa = rd_base_pa; + mmap.base_va = rd_base_va; + mmap.size = rd_size; + + /* Only S-EL0 mappings supported for now */ + mmap.attr = rdmem_attr_to_mmap_attr(rdmem->attr) | MT_USER; + + VERBOSE(" VA: 0x%lx PA: 0x%llx (0x%lx, attr: 0x%x)\n", + mmap.base_va, mmap.base_pa, mmap.size, mmap.attr); + + /* Map region in the context of the Secure Partition */ + mmap_add_region_ctx(sp_ctx->xlat_ctx_handle, &mmap); + + if (zero_region == 1) { + VERBOSE(" Zeroing region...\n"); + + rc = mmap_add_dynamic_region(mmap.base_pa, mmap.base_pa, + mmap.size, MT_MEMORY | MT_RW | MT_SECURE); + if (rc != 0) { + ERROR("Unable to map memory at EL3 to zero: %d\n", + rc); + panic(); + } + + zeromem((void *)mmap.base_pa, mmap.size); + + /* + * Unmap destination region unless it is the SPM<->SP buffer, + * which must be used by SPM. + */ + if (memtype != RD_MEM_NORMAL_SPM_SP_SHARED_MEM) { + rc = mmap_remove_dynamic_region(rd_base_pa, rd_size); + if (rc != 0) { + ERROR("Unable to remove region at EL3: %d\n", rc); + panic(); + } + } + } +} + +void sp_map_memory_regions(sp_context_t *sp_ctx) +{ + /* This region contains the exception vectors used at S-EL1. */ + const mmap_region_t sel1_exception_vectors = + MAP_REGION_FLAT(SPM_SHIM_EXCEPTIONS_START, + SPM_SHIM_EXCEPTIONS_SIZE, + MT_CODE | MT_SECURE | MT_PRIVILEGED); + + mmap_add_region_ctx(sp_ctx->xlat_ctx_handle, + &sel1_exception_vectors); + + struct sp_rd_sect_mem_region *rdmem; + + for (rdmem = sp_ctx->rd.mem_region; rdmem != NULL; rdmem = rdmem->next) { + map_rdmem(sp_ctx, rdmem); + } + + init_xlat_tables_ctx(sp_ctx->xlat_ctx_handle); +} diff --git a/services/std_svc/spm_deprecated/sp_setup.c b/services/std_svc/spm_deprecated/sp_setup.c deleted file mode 100644 index 0d61306..0000000 --- a/services/std_svc/spm_deprecated/sp_setup.c +++ /dev/null @@ -1,247 +0,0 @@ -/* - * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "spm_private.h" -#include "spm_shim_private.h" - -/* Setup context of the Secure Partition */ -void spm_sp_setup(sp_context_t *sp_ctx) -{ - cpu_context_t *ctx = &(sp_ctx->cpu_ctx); - - /* - * Initialize CPU context - * ---------------------- - */ - - entry_point_info_t ep_info = {0}; - - SET_PARAM_HEAD(&ep_info, PARAM_EP, VERSION_1, SECURE | EP_ST_ENABLE); - - /* Setup entrypoint and SPSR */ - ep_info.pc = BL32_BASE; - ep_info.spsr = SPSR_64(MODE_EL0, MODE_SP_EL0, DISABLE_ALL_EXCEPTIONS); - - /* - * X0: Virtual address of a buffer shared between EL3 and Secure EL0. - * The buffer will be mapped in the Secure EL1 translation regime - * with Normal IS WBWA attributes and RO data and Execute Never - * instruction access permissions. - * - * X1: Size of the buffer in bytes - * - * X2: cookie value (Implementation Defined) - * - * X3: cookie value (Implementation Defined) - * - * X4 to X7 = 0 - */ - ep_info.args.arg0 = PLAT_SPM_BUF_BASE; - ep_info.args.arg1 = PLAT_SPM_BUF_SIZE; - ep_info.args.arg2 = PLAT_SPM_COOKIE_0; - ep_info.args.arg3 = PLAT_SPM_COOKIE_1; - - cm_setup_context(ctx, &ep_info); - - /* - * SP_EL0: A non-zero value will indicate to the SP that the SPM has - * initialized the stack pointer for the current CPU through - * implementation defined means. The value will be 0 otherwise. - */ - write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_SP_EL0, - PLAT_SP_IMAGE_STACK_BASE + PLAT_SP_IMAGE_STACK_PCPU_SIZE); - - /* - * Setup translation tables - * ------------------------ - */ - -#if ENABLE_ASSERTIONS - - /* Get max granularity supported by the platform. */ - unsigned int max_granule = xlat_arch_get_max_supported_granule_size(); - - VERBOSE("Max translation granule size supported: %u KiB\n", - max_granule / 1024U); - - unsigned int max_granule_mask = max_granule - 1U; - - /* Base must be aligned to the max granularity */ - assert((ARM_SP_IMAGE_NS_BUF_BASE & max_granule_mask) == 0); - - /* Size must be a multiple of the max granularity */ - assert((ARM_SP_IMAGE_NS_BUF_SIZE & max_granule_mask) == 0); - -#endif /* ENABLE_ASSERTIONS */ - - /* This region contains the exception vectors used at S-EL1. */ - const mmap_region_t sel1_exception_vectors = - MAP_REGION_FLAT(SPM_SHIM_EXCEPTIONS_START, - SPM_SHIM_EXCEPTIONS_SIZE, - MT_CODE | MT_SECURE | MT_PRIVILEGED); - mmap_add_region_ctx(sp_ctx->xlat_ctx_handle, - &sel1_exception_vectors); - - mmap_add_ctx(sp_ctx->xlat_ctx_handle, - plat_get_secure_partition_mmap(NULL)); - - init_xlat_tables_ctx(sp_ctx->xlat_ctx_handle); - - /* - * MMU-related registers - * --------------------- - */ - xlat_ctx_t *xlat_ctx = sp_ctx->xlat_ctx_handle; - - uint64_t mmu_cfg_params[MMU_CFG_PARAM_MAX]; - - setup_mmu_cfg((uint64_t *)&mmu_cfg_params, 0, xlat_ctx->base_table, - xlat_ctx->pa_max_address, xlat_ctx->va_max_address, - EL1_EL0_REGIME); - - write_ctx_reg(get_sysregs_ctx(ctx), CTX_MAIR_EL1, - mmu_cfg_params[MMU_CFG_MAIR]); - - write_ctx_reg(get_sysregs_ctx(ctx), CTX_TCR_EL1, - mmu_cfg_params[MMU_CFG_TCR]); - - write_ctx_reg(get_sysregs_ctx(ctx), CTX_TTBR0_EL1, - mmu_cfg_params[MMU_CFG_TTBR0]); - - /* Setup SCTLR_EL1 */ - u_register_t sctlr_el1 = read_ctx_reg(get_sysregs_ctx(ctx), CTX_SCTLR_EL1); - - sctlr_el1 |= - /*SCTLR_EL1_RES1 |*/ - /* Don't trap DC CVAU, DC CIVAC, DC CVAC, DC CVAP, or IC IVAU */ - SCTLR_UCI_BIT | - /* RW regions at xlat regime EL1&0 are forced to be XN. */ - SCTLR_WXN_BIT | - /* Don't trap to EL1 execution of WFI or WFE at EL0. */ - SCTLR_NTWI_BIT | SCTLR_NTWE_BIT | - /* Don't trap to EL1 accesses to CTR_EL0 from EL0. */ - SCTLR_UCT_BIT | - /* Don't trap to EL1 execution of DZ ZVA at EL0. */ - SCTLR_DZE_BIT | - /* Enable SP Alignment check for EL0 */ - SCTLR_SA0_BIT | - /* Allow cacheable data and instr. accesses to normal memory. */ - SCTLR_C_BIT | SCTLR_I_BIT | - /* Alignment fault checking enabled when at EL1 and EL0. */ - SCTLR_A_BIT | - /* Enable MMU. */ - SCTLR_M_BIT - ; - - sctlr_el1 &= ~( - /* Explicit data accesses at EL0 are little-endian. */ - SCTLR_E0E_BIT | - /* Accesses to DAIF from EL0 are trapped to EL1. */ - SCTLR_UMA_BIT - ); - - write_ctx_reg(get_sysregs_ctx(ctx), CTX_SCTLR_EL1, sctlr_el1); - - /* - * Setup other system registers - * ---------------------------- - */ - - /* Shim Exception Vector Base Address */ - write_ctx_reg(get_sysregs_ctx(ctx), CTX_VBAR_EL1, - SPM_SHIM_EXCEPTIONS_PTR); - - /* - * FPEN: Allow the Secure Partition to access FP/SIMD registers. - * Note that SPM will not do any saving/restoring of these registers on - * behalf of the SP. This falls under the SP's responsibility. - * TTA: Enable access to trace registers. - * ZEN (v8.2): Trap SVE instructions and access to SVE registers. - */ - write_ctx_reg(get_sysregs_ctx(ctx), CTX_CPACR_EL1, - CPACR_EL1_FPEN(CPACR_EL1_FP_TRAP_NONE)); - - /* - * Prepare information in buffer shared between EL3 and S-EL0 - * ---------------------------------------------------------- - */ - - void *shared_buf_ptr = (void *) PLAT_SPM_BUF_BASE; - - /* Copy the boot information into the shared buffer with the SP. */ - assert((uintptr_t)shared_buf_ptr + sizeof(secure_partition_boot_info_t) - <= (PLAT_SPM_BUF_BASE + PLAT_SPM_BUF_SIZE)); - - assert(PLAT_SPM_BUF_BASE <= (UINTPTR_MAX - PLAT_SPM_BUF_SIZE + 1)); - - const secure_partition_boot_info_t *sp_boot_info = - plat_get_secure_partition_boot_info(NULL); - - assert(sp_boot_info != NULL); - - memcpy((void *) shared_buf_ptr, (const void *) sp_boot_info, - sizeof(secure_partition_boot_info_t)); - - /* Pointer to the MP information from the platform port. */ - secure_partition_mp_info_t *sp_mp_info = - ((secure_partition_boot_info_t *) shared_buf_ptr)->mp_info; - - assert(sp_mp_info != NULL); - - /* - * Point the shared buffer MP information pointer to where the info will - * be populated, just after the boot info. - */ - ((secure_partition_boot_info_t *) shared_buf_ptr)->mp_info = - (secure_partition_mp_info_t *) ((uintptr_t)shared_buf_ptr - + sizeof(secure_partition_boot_info_t)); - - /* - * Update the shared buffer pointer to where the MP information for the - * payload will be populated - */ - shared_buf_ptr = ((secure_partition_boot_info_t *) shared_buf_ptr)->mp_info; - - /* - * Copy the cpu information into the shared buffer area after the boot - * information. - */ - assert(sp_boot_info->num_cpus <= PLATFORM_CORE_COUNT); - - assert((uintptr_t)shared_buf_ptr - <= (PLAT_SPM_BUF_BASE + PLAT_SPM_BUF_SIZE - - (sp_boot_info->num_cpus * sizeof(*sp_mp_info)))); - - memcpy(shared_buf_ptr, (const void *) sp_mp_info, - sp_boot_info->num_cpus * sizeof(*sp_mp_info)); - - /* - * Calculate the linear indices of cores in boot information for the - * secure partition and flag the primary CPU - */ - sp_mp_info = (secure_partition_mp_info_t *) shared_buf_ptr; - - for (unsigned int index = 0; index < sp_boot_info->num_cpus; index++) { - u_register_t mpidr = sp_mp_info[index].mpidr; - - sp_mp_info[index].linear_id = plat_core_pos_by_mpidr(mpidr); - if (plat_my_core_pos() == sp_mp_info[index].linear_id) - sp_mp_info[index].flags |= MP_INFO_FLAG_PRIMARY_CPU; - } -} diff --git a/services/std_svc/spm_deprecated/sp_xlat.c b/services/std_svc/spm_deprecated/sp_xlat.c deleted file mode 100644 index 3527138..0000000 --- a/services/std_svc/spm_deprecated/sp_xlat.c +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "spm_private.h" -#include "spm_shim_private.h" - -/* Place translation tables by default along with the ones used by BL31. */ -#ifndef PLAT_SP_IMAGE_XLAT_SECTION_NAME -#define PLAT_SP_IMAGE_XLAT_SECTION_NAME "xlat_table" -#endif - -/* Allocate and initialise the translation context for the secure partitions. */ -REGISTER_XLAT_CONTEXT2(sp, - PLAT_SP_IMAGE_MMAP_REGIONS, - PLAT_SP_IMAGE_MAX_XLAT_TABLES, - PLAT_VIRT_ADDR_SPACE_SIZE, PLAT_PHY_ADDR_SPACE_SIZE, - EL1_EL0_REGIME, PLAT_SP_IMAGE_XLAT_SECTION_NAME); - -/* Lock used for SP_MEMORY_ATTRIBUTES_GET and SP_MEMORY_ATTRIBUTES_SET */ -static spinlock_t mem_attr_smc_lock; - -/* Get handle of Secure Partition translation context */ -xlat_ctx_t *spm_get_sp_xlat_context(void) -{ - return &sp_xlat_ctx; -}; - -/* - * Attributes are encoded using a different format in the SMC interface than in - * the Trusted Firmware, where the mmap_attr_t enum type is used. This function - * converts an attributes value from the SMC format to the mmap_attr_t format by - * setting MT_RW/MT_RO, MT_USER/MT_PRIVILEGED and MT_EXECUTE/MT_EXECUTE_NEVER. - * The other fields are left as 0 because they are ignored by the function - * xlat_change_mem_attributes_ctx(). - */ -static unsigned int smc_attr_to_mmap_attr(unsigned int attributes) -{ - unsigned int tf_attr = 0U; - - unsigned int access = (attributes & SP_MEMORY_ATTRIBUTES_ACCESS_MASK) - >> SP_MEMORY_ATTRIBUTES_ACCESS_SHIFT; - - if (access == SP_MEMORY_ATTRIBUTES_ACCESS_RW) { - tf_attr |= MT_RW | MT_USER; - } else if (access == SP_MEMORY_ATTRIBUTES_ACCESS_RO) { - tf_attr |= MT_RO | MT_USER; - } else { - /* Other values are reserved. */ - assert(access == SP_MEMORY_ATTRIBUTES_ACCESS_NOACCESS); - /* The only requirement is that there's no access from EL0 */ - tf_attr |= MT_RO | MT_PRIVILEGED; - } - - if ((attributes & SP_MEMORY_ATTRIBUTES_NON_EXEC) == 0) { - tf_attr |= MT_EXECUTE; - } else { - tf_attr |= MT_EXECUTE_NEVER; - } - - return tf_attr; -} - -/* - * This function converts attributes from the Trusted Firmware format into the - * SMC interface format. - */ -static unsigned int smc_mmap_to_smc_attr(unsigned int attr) -{ - unsigned int smc_attr = 0U; - - unsigned int data_access; - - if ((attr & MT_USER) == 0) { - /* No access from EL0. */ - data_access = SP_MEMORY_ATTRIBUTES_ACCESS_NOACCESS; - } else { - if ((attr & MT_RW) != 0) { - assert(MT_TYPE(attr) != MT_DEVICE); - data_access = SP_MEMORY_ATTRIBUTES_ACCESS_RW; - } else { - data_access = SP_MEMORY_ATTRIBUTES_ACCESS_RO; - } - } - - smc_attr |= (data_access & SP_MEMORY_ATTRIBUTES_ACCESS_MASK) - << SP_MEMORY_ATTRIBUTES_ACCESS_SHIFT; - - if ((attr & MT_EXECUTE_NEVER) != 0U) { - smc_attr |= SP_MEMORY_ATTRIBUTES_NON_EXEC; - } - - return smc_attr; -} - -int32_t spm_memory_attributes_get_smc_handler(sp_context_t *sp_ctx, - uintptr_t base_va) -{ - uint32_t attributes; - - spin_lock(&mem_attr_smc_lock); - - int rc = xlat_get_mem_attributes_ctx(sp_ctx->xlat_ctx_handle, - base_va, &attributes); - - spin_unlock(&mem_attr_smc_lock); - - /* Convert error codes of xlat_get_mem_attributes_ctx() into SPM. */ - assert((rc == 0) || (rc == -EINVAL)); - - if (rc == 0) { - return (int32_t) smc_mmap_to_smc_attr(attributes); - } else { - return SPM_INVALID_PARAMETER; - } -} - -int spm_memory_attributes_set_smc_handler(sp_context_t *sp_ctx, - u_register_t page_address, - u_register_t pages_count, - u_register_t smc_attributes) -{ - uintptr_t base_va = (uintptr_t) page_address; - size_t size = (size_t) (pages_count * PAGE_SIZE); - uint32_t attributes = (uint32_t) smc_attributes; - - INFO(" Start address : 0x%lx\n", base_va); - INFO(" Number of pages: %i (%zi bytes)\n", (int) pages_count, size); - INFO(" Attributes : 0x%x\n", attributes); - - spin_lock(&mem_attr_smc_lock); - - int ret = xlat_change_mem_attributes_ctx(sp_ctx->xlat_ctx_handle, - base_va, size, - smc_attr_to_mmap_attr(attributes)); - - spin_unlock(&mem_attr_smc_lock); - - /* Convert error codes of xlat_change_mem_attributes_ctx() into SPM. */ - assert((ret == 0) || (ret == -EINVAL)); - - return (ret == 0) ? SPM_SUCCESS : SPM_INVALID_PARAMETER; -} diff --git a/services/std_svc/spm_deprecated/spm.mk b/services/std_svc/spm_deprecated/spm.mk index fedcaed..ed36812 100644 --- a/services/std_svc/spm_deprecated/spm.mk +++ b/services/std_svc/spm_deprecated/spm.mk @@ -15,8 +15,8 @@ ${ARCH}/spm_helpers.S \ ${ARCH}/spm_shim_exceptions.S \ spm_main.c \ - sp_setup.c \ - sp_xlat.c) + spm_setup.c \ + spm_xlat.c) # Let the top-level Makefile know that we intend to include a BL32 image diff --git a/services/std_svc/spm_deprecated/spm_setup.c b/services/std_svc/spm_deprecated/spm_setup.c new file mode 100644 index 0000000..0d61306 --- /dev/null +++ b/services/std_svc/spm_deprecated/spm_setup.c @@ -0,0 +1,247 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "spm_private.h" +#include "spm_shim_private.h" + +/* Setup context of the Secure Partition */ +void spm_sp_setup(sp_context_t *sp_ctx) +{ + cpu_context_t *ctx = &(sp_ctx->cpu_ctx); + + /* + * Initialize CPU context + * ---------------------- + */ + + entry_point_info_t ep_info = {0}; + + SET_PARAM_HEAD(&ep_info, PARAM_EP, VERSION_1, SECURE | EP_ST_ENABLE); + + /* Setup entrypoint and SPSR */ + ep_info.pc = BL32_BASE; + ep_info.spsr = SPSR_64(MODE_EL0, MODE_SP_EL0, DISABLE_ALL_EXCEPTIONS); + + /* + * X0: Virtual address of a buffer shared between EL3 and Secure EL0. + * The buffer will be mapped in the Secure EL1 translation regime + * with Normal IS WBWA attributes and RO data and Execute Never + * instruction access permissions. + * + * X1: Size of the buffer in bytes + * + * X2: cookie value (Implementation Defined) + * + * X3: cookie value (Implementation Defined) + * + * X4 to X7 = 0 + */ + ep_info.args.arg0 = PLAT_SPM_BUF_BASE; + ep_info.args.arg1 = PLAT_SPM_BUF_SIZE; + ep_info.args.arg2 = PLAT_SPM_COOKIE_0; + ep_info.args.arg3 = PLAT_SPM_COOKIE_1; + + cm_setup_context(ctx, &ep_info); + + /* + * SP_EL0: A non-zero value will indicate to the SP that the SPM has + * initialized the stack pointer for the current CPU through + * implementation defined means. The value will be 0 otherwise. + */ + write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_SP_EL0, + PLAT_SP_IMAGE_STACK_BASE + PLAT_SP_IMAGE_STACK_PCPU_SIZE); + + /* + * Setup translation tables + * ------------------------ + */ + +#if ENABLE_ASSERTIONS + + /* Get max granularity supported by the platform. */ + unsigned int max_granule = xlat_arch_get_max_supported_granule_size(); + + VERBOSE("Max translation granule size supported: %u KiB\n", + max_granule / 1024U); + + unsigned int max_granule_mask = max_granule - 1U; + + /* Base must be aligned to the max granularity */ + assert((ARM_SP_IMAGE_NS_BUF_BASE & max_granule_mask) == 0); + + /* Size must be a multiple of the max granularity */ + assert((ARM_SP_IMAGE_NS_BUF_SIZE & max_granule_mask) == 0); + +#endif /* ENABLE_ASSERTIONS */ + + /* This region contains the exception vectors used at S-EL1. */ + const mmap_region_t sel1_exception_vectors = + MAP_REGION_FLAT(SPM_SHIM_EXCEPTIONS_START, + SPM_SHIM_EXCEPTIONS_SIZE, + MT_CODE | MT_SECURE | MT_PRIVILEGED); + mmap_add_region_ctx(sp_ctx->xlat_ctx_handle, + &sel1_exception_vectors); + + mmap_add_ctx(sp_ctx->xlat_ctx_handle, + plat_get_secure_partition_mmap(NULL)); + + init_xlat_tables_ctx(sp_ctx->xlat_ctx_handle); + + /* + * MMU-related registers + * --------------------- + */ + xlat_ctx_t *xlat_ctx = sp_ctx->xlat_ctx_handle; + + uint64_t mmu_cfg_params[MMU_CFG_PARAM_MAX]; + + setup_mmu_cfg((uint64_t *)&mmu_cfg_params, 0, xlat_ctx->base_table, + xlat_ctx->pa_max_address, xlat_ctx->va_max_address, + EL1_EL0_REGIME); + + write_ctx_reg(get_sysregs_ctx(ctx), CTX_MAIR_EL1, + mmu_cfg_params[MMU_CFG_MAIR]); + + write_ctx_reg(get_sysregs_ctx(ctx), CTX_TCR_EL1, + mmu_cfg_params[MMU_CFG_TCR]); + + write_ctx_reg(get_sysregs_ctx(ctx), CTX_TTBR0_EL1, + mmu_cfg_params[MMU_CFG_TTBR0]); + + /* Setup SCTLR_EL1 */ + u_register_t sctlr_el1 = read_ctx_reg(get_sysregs_ctx(ctx), CTX_SCTLR_EL1); + + sctlr_el1 |= + /*SCTLR_EL1_RES1 |*/ + /* Don't trap DC CVAU, DC CIVAC, DC CVAC, DC CVAP, or IC IVAU */ + SCTLR_UCI_BIT | + /* RW regions at xlat regime EL1&0 are forced to be XN. */ + SCTLR_WXN_BIT | + /* Don't trap to EL1 execution of WFI or WFE at EL0. */ + SCTLR_NTWI_BIT | SCTLR_NTWE_BIT | + /* Don't trap to EL1 accesses to CTR_EL0 from EL0. */ + SCTLR_UCT_BIT | + /* Don't trap to EL1 execution of DZ ZVA at EL0. */ + SCTLR_DZE_BIT | + /* Enable SP Alignment check for EL0 */ + SCTLR_SA0_BIT | + /* Allow cacheable data and instr. accesses to normal memory. */ + SCTLR_C_BIT | SCTLR_I_BIT | + /* Alignment fault checking enabled when at EL1 and EL0. */ + SCTLR_A_BIT | + /* Enable MMU. */ + SCTLR_M_BIT + ; + + sctlr_el1 &= ~( + /* Explicit data accesses at EL0 are little-endian. */ + SCTLR_E0E_BIT | + /* Accesses to DAIF from EL0 are trapped to EL1. */ + SCTLR_UMA_BIT + ); + + write_ctx_reg(get_sysregs_ctx(ctx), CTX_SCTLR_EL1, sctlr_el1); + + /* + * Setup other system registers + * ---------------------------- + */ + + /* Shim Exception Vector Base Address */ + write_ctx_reg(get_sysregs_ctx(ctx), CTX_VBAR_EL1, + SPM_SHIM_EXCEPTIONS_PTR); + + /* + * FPEN: Allow the Secure Partition to access FP/SIMD registers. + * Note that SPM will not do any saving/restoring of these registers on + * behalf of the SP. This falls under the SP's responsibility. + * TTA: Enable access to trace registers. + * ZEN (v8.2): Trap SVE instructions and access to SVE registers. + */ + write_ctx_reg(get_sysregs_ctx(ctx), CTX_CPACR_EL1, + CPACR_EL1_FPEN(CPACR_EL1_FP_TRAP_NONE)); + + /* + * Prepare information in buffer shared between EL3 and S-EL0 + * ---------------------------------------------------------- + */ + + void *shared_buf_ptr = (void *) PLAT_SPM_BUF_BASE; + + /* Copy the boot information into the shared buffer with the SP. */ + assert((uintptr_t)shared_buf_ptr + sizeof(secure_partition_boot_info_t) + <= (PLAT_SPM_BUF_BASE + PLAT_SPM_BUF_SIZE)); + + assert(PLAT_SPM_BUF_BASE <= (UINTPTR_MAX - PLAT_SPM_BUF_SIZE + 1)); + + const secure_partition_boot_info_t *sp_boot_info = + plat_get_secure_partition_boot_info(NULL); + + assert(sp_boot_info != NULL); + + memcpy((void *) shared_buf_ptr, (const void *) sp_boot_info, + sizeof(secure_partition_boot_info_t)); + + /* Pointer to the MP information from the platform port. */ + secure_partition_mp_info_t *sp_mp_info = + ((secure_partition_boot_info_t *) shared_buf_ptr)->mp_info; + + assert(sp_mp_info != NULL); + + /* + * Point the shared buffer MP information pointer to where the info will + * be populated, just after the boot info. + */ + ((secure_partition_boot_info_t *) shared_buf_ptr)->mp_info = + (secure_partition_mp_info_t *) ((uintptr_t)shared_buf_ptr + + sizeof(secure_partition_boot_info_t)); + + /* + * Update the shared buffer pointer to where the MP information for the + * payload will be populated + */ + shared_buf_ptr = ((secure_partition_boot_info_t *) shared_buf_ptr)->mp_info; + + /* + * Copy the cpu information into the shared buffer area after the boot + * information. + */ + assert(sp_boot_info->num_cpus <= PLATFORM_CORE_COUNT); + + assert((uintptr_t)shared_buf_ptr + <= (PLAT_SPM_BUF_BASE + PLAT_SPM_BUF_SIZE - + (sp_boot_info->num_cpus * sizeof(*sp_mp_info)))); + + memcpy(shared_buf_ptr, (const void *) sp_mp_info, + sp_boot_info->num_cpus * sizeof(*sp_mp_info)); + + /* + * Calculate the linear indices of cores in boot information for the + * secure partition and flag the primary CPU + */ + sp_mp_info = (secure_partition_mp_info_t *) shared_buf_ptr; + + for (unsigned int index = 0; index < sp_boot_info->num_cpus; index++) { + u_register_t mpidr = sp_mp_info[index].mpidr; + + sp_mp_info[index].linear_id = plat_core_pos_by_mpidr(mpidr); + if (plat_my_core_pos() == sp_mp_info[index].linear_id) + sp_mp_info[index].flags |= MP_INFO_FLAG_PRIMARY_CPU; + } +} diff --git a/services/std_svc/spm_deprecated/spm_xlat.c b/services/std_svc/spm_deprecated/spm_xlat.c new file mode 100644 index 0000000..3527138 --- /dev/null +++ b/services/std_svc/spm_deprecated/spm_xlat.c @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "spm_private.h" +#include "spm_shim_private.h" + +/* Place translation tables by default along with the ones used by BL31. */ +#ifndef PLAT_SP_IMAGE_XLAT_SECTION_NAME +#define PLAT_SP_IMAGE_XLAT_SECTION_NAME "xlat_table" +#endif + +/* Allocate and initialise the translation context for the secure partitions. */ +REGISTER_XLAT_CONTEXT2(sp, + PLAT_SP_IMAGE_MMAP_REGIONS, + PLAT_SP_IMAGE_MAX_XLAT_TABLES, + PLAT_VIRT_ADDR_SPACE_SIZE, PLAT_PHY_ADDR_SPACE_SIZE, + EL1_EL0_REGIME, PLAT_SP_IMAGE_XLAT_SECTION_NAME); + +/* Lock used for SP_MEMORY_ATTRIBUTES_GET and SP_MEMORY_ATTRIBUTES_SET */ +static spinlock_t mem_attr_smc_lock; + +/* Get handle of Secure Partition translation context */ +xlat_ctx_t *spm_get_sp_xlat_context(void) +{ + return &sp_xlat_ctx; +}; + +/* + * Attributes are encoded using a different format in the SMC interface than in + * the Trusted Firmware, where the mmap_attr_t enum type is used. This function + * converts an attributes value from the SMC format to the mmap_attr_t format by + * setting MT_RW/MT_RO, MT_USER/MT_PRIVILEGED and MT_EXECUTE/MT_EXECUTE_NEVER. + * The other fields are left as 0 because they are ignored by the function + * xlat_change_mem_attributes_ctx(). + */ +static unsigned int smc_attr_to_mmap_attr(unsigned int attributes) +{ + unsigned int tf_attr = 0U; + + unsigned int access = (attributes & SP_MEMORY_ATTRIBUTES_ACCESS_MASK) + >> SP_MEMORY_ATTRIBUTES_ACCESS_SHIFT; + + if (access == SP_MEMORY_ATTRIBUTES_ACCESS_RW) { + tf_attr |= MT_RW | MT_USER; + } else if (access == SP_MEMORY_ATTRIBUTES_ACCESS_RO) { + tf_attr |= MT_RO | MT_USER; + } else { + /* Other values are reserved. */ + assert(access == SP_MEMORY_ATTRIBUTES_ACCESS_NOACCESS); + /* The only requirement is that there's no access from EL0 */ + tf_attr |= MT_RO | MT_PRIVILEGED; + } + + if ((attributes & SP_MEMORY_ATTRIBUTES_NON_EXEC) == 0) { + tf_attr |= MT_EXECUTE; + } else { + tf_attr |= MT_EXECUTE_NEVER; + } + + return tf_attr; +} + +/* + * This function converts attributes from the Trusted Firmware format into the + * SMC interface format. + */ +static unsigned int smc_mmap_to_smc_attr(unsigned int attr) +{ + unsigned int smc_attr = 0U; + + unsigned int data_access; + + if ((attr & MT_USER) == 0) { + /* No access from EL0. */ + data_access = SP_MEMORY_ATTRIBUTES_ACCESS_NOACCESS; + } else { + if ((attr & MT_RW) != 0) { + assert(MT_TYPE(attr) != MT_DEVICE); + data_access = SP_MEMORY_ATTRIBUTES_ACCESS_RW; + } else { + data_access = SP_MEMORY_ATTRIBUTES_ACCESS_RO; + } + } + + smc_attr |= (data_access & SP_MEMORY_ATTRIBUTES_ACCESS_MASK) + << SP_MEMORY_ATTRIBUTES_ACCESS_SHIFT; + + if ((attr & MT_EXECUTE_NEVER) != 0U) { + smc_attr |= SP_MEMORY_ATTRIBUTES_NON_EXEC; + } + + return smc_attr; +} + +int32_t spm_memory_attributes_get_smc_handler(sp_context_t *sp_ctx, + uintptr_t base_va) +{ + uint32_t attributes; + + spin_lock(&mem_attr_smc_lock); + + int rc = xlat_get_mem_attributes_ctx(sp_ctx->xlat_ctx_handle, + base_va, &attributes); + + spin_unlock(&mem_attr_smc_lock); + + /* Convert error codes of xlat_get_mem_attributes_ctx() into SPM. */ + assert((rc == 0) || (rc == -EINVAL)); + + if (rc == 0) { + return (int32_t) smc_mmap_to_smc_attr(attributes); + } else { + return SPM_INVALID_PARAMETER; + } +} + +int spm_memory_attributes_set_smc_handler(sp_context_t *sp_ctx, + u_register_t page_address, + u_register_t pages_count, + u_register_t smc_attributes) +{ + uintptr_t base_va = (uintptr_t) page_address; + size_t size = (size_t) (pages_count * PAGE_SIZE); + uint32_t attributes = (uint32_t) smc_attributes; + + INFO(" Start address : 0x%lx\n", base_va); + INFO(" Number of pages: %i (%zi bytes)\n", (int) pages_count, size); + INFO(" Attributes : 0x%x\n", attributes); + + spin_lock(&mem_attr_smc_lock); + + int ret = xlat_change_mem_attributes_ctx(sp_ctx->xlat_ctx_handle, + base_va, size, + smc_attr_to_mmap_attr(attributes)); + + spin_unlock(&mem_attr_smc_lock); + + /* Convert error codes of xlat_change_mem_attributes_ctx() into SPM. */ + assert((ret == 0) || (ret == -EINVAL)); + + return (ret == 0) ? SPM_SUCCESS : SPM_INVALID_PARAMETER; +}