diff options
author | Ken Liu <Ken.Liu@arm.com> | 2021-05-22 17:41:25 +0800 |
---|---|---|
committer | Ken Liu <ken.liu@arm.com> | 2021-06-30 05:45:14 +0200 |
commit | ea45b0d4fb29351c029a13dc66b76898d41d53ce (patch) | |
tree | a4fa875f5868b88239d939f55125dc873121ad4a /secure_fw | |
parent | e5c151d0c8dd37c0b79ff928109a3b8537162d8c (diff) | |
download | trusted-firmware-m-ea45b0d4fb29351c029a13dc66b76898d41d53ce.tar.gz |
SPM: Add partition runtime region in the linker
- Add ZI region in the linker script for holding partition runtime
and service runtime data, replacing the original runtime data
arrays.
- Organize the partition and service runtime data with linked list.
- The logic for loading partitions and services is changed
accordingly.
Change-Id: I7ccfb5055cf62b7a3d185812af43084c767a98dd
Signed-off-by: Ken Liu <Ken.Liu@arm.com>
Co-authored-by: Mingyang Sun <mingyang.sun@arm.com>
Diffstat (limited to 'secure_fw')
-rw-r--r-- | secure_fw/partitions/ns_proxy_partition/load_info_ns_proxy.c | 5 | ||||
-rw-r--r-- | secure_fw/partitions/partition_load_info.template | 7 | ||||
-rw-r--r-- | secure_fw/partitions/tfm_service_list.inc.template | 49 | ||||
-rwxr-xr-x | secure_fw/spm/CMakeLists.txt | 2 | ||||
-rw-r--r-- | secure_fw/spm/cmsis_psa/spm_ipc.c | 65 | ||||
-rw-r--r-- | secure_fw/spm/cmsis_psa/spm_ipc.h | 8 | ||||
-rw-r--r-- | secure_fw/spm/cmsis_psa/static_load.c | 76 | ||||
-rw-r--r-- | secure_fw/spm/cmsis_psa/tfm_spm_db_ipc.inc.template | 50 | ||||
-rw-r--r-- | secure_fw/spm/include/load/spm_load_api.h | 27 |
9 files changed, 92 insertions, 197 deletions
diff --git a/secure_fw/partitions/ns_proxy_partition/load_info_ns_proxy.c b/secure_fw/partitions/ns_proxy_partition/load_info_ns_proxy.c index b099dc4a84..6f5fcc08f2 100644 --- a/secure_fw/partitions/ns_proxy_partition/load_info_ns_proxy.c +++ b/secure_fw/partitions/ns_proxy_partition/load_info_ns_proxy.c @@ -11,6 +11,7 @@ #include <stddef.h> #include "region.h" #include "region_defs.h" +#include "spm_ipc.h" #include "spm_partition_defs.h" #include "load/partition_defs.h" #include "load/service_defs.h" @@ -74,3 +75,7 @@ const struct partition_tfm_sp_ns_proxy_load_info_t }, #endif }; + +/* Placeholder for partition runtime space. Do not reference it. */ +static struct partition_t tfm_sp_ns_proxy_partition_runtime_item + __attribute__((used, section(".bss.part_runtime"))); diff --git a/secure_fw/partitions/partition_load_info.template b/secure_fw/partitions/partition_load_info.template index 54f9257881..908944b735 100644 --- a/secure_fw/partitions/partition_load_info.template +++ b/secure_fw/partitions/partition_load_info.template @@ -10,6 +10,7 @@ #include <stdint.h> #include <stddef.h> #include "region.h" +#include "spm_ipc.h" #include "load/irq_defs.h" #include "load/partition_defs.h" #include "load/service_defs.h" @@ -234,3 +235,9 @@ const struct partition_{{manifest.name|lower}}_load_info_t {{manifest.name|lower }, {% endif %} }; + +/* Placeholder for partition and service runtime space. Do not reference it. */ +static struct partition_t {{manifest.name|lower}}_partition_runtime_item + __attribute__((used, section(".bss.part_runtime"))); +static struct service_t {{manifest.name|lower}}_service_runtime_item[{{(manifest.name|upper + "_NSERVS")}}] + __attribute__((used, section(".bss.serv_runtime"))); diff --git a/secure_fw/partitions/tfm_service_list.inc.template b/secure_fw/partitions/tfm_service_list.inc.template deleted file mode 100644 index 26acd1605c..0000000000 --- a/secure_fw/partitions/tfm_service_list.inc.template +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2018-2021, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -{{utilities.donotedit_warning}} - -#ifndef __TFM_SERVICE_LIST_INC__ -#define __TFM_SERVICE_LIST_INC__ - -{% for partition in partitions %} -#ifdef {{partition.attr.conditional}} -#include "{{partition.header_file}}" -#endif /* {{partition.attr.conditional}} */ - -{% endfor %} - -/**************************************************************************/ -/** The service list */ -/**************************************************************************/ -struct service_t g_services[] = -{ -{% for partition in partitions %} - {% if partition.attr.tfm_partition_ipc %} - {% if partition.manifest.services %} - {% if partition.attr.conditional %} -#ifdef {{partition.attr.conditional}} - {% endif %} - /******** {{partition.manifest.name}} ********/ - {% for service in partition.manifest.services %} - {{'{'}} - .p_ldinf = NULL, - .partition = NULL, - .handle_list = {0}, - .list = {0}, - {{'}'}}, - {% endfor %} - {% if partition.attr.conditional %} -#endif /* {{partition.attr.conditional}} */ - {% endif %} - {% endif %} - - {% endif %} -{% endfor %} -}; - -#endif /* __TFM_SERVICE_LIST_INC__ */ diff --git a/secure_fw/spm/CMakeLists.txt b/secure_fw/spm/CMakeLists.txt index ff7d28d562..098c5188bc 100755 --- a/secure_fw/spm/CMakeLists.txt +++ b/secure_fw/spm/CMakeLists.txt @@ -67,6 +67,8 @@ target_sources(tfm_spm $<$<AND:$<BOOL:${TFM_PSA_API}>,$<STREQUAL:${CMAKE_SYSTEM_ARCHITECTURE},armv7-m>>:cmsis_psa/arch/tfm_arch_v6m_v7m.c> ) +target_include_directories(tfm_partitions INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/cmsis_psa) + #workaround for arch-test if (TEST_PSA_API STREQUAL IPC) target_include_directories(tfm_partitions INTERFACE ${CMAKE_BINARY_DIR}/generated/api-tests/platform/manifests) diff --git a/secure_fw/spm/cmsis_psa/spm_ipc.c b/secure_fw/spm/cmsis_psa/spm_ipc.c index 7f4bc2f851..19cfbdd119 100644 --- a/secure_fw/spm/cmsis_psa/spm_ipc.c +++ b/secure_fw/spm/cmsis_psa/spm_ipc.c @@ -36,8 +36,9 @@ #include "load/spm_load_api.h" #include "load/irq_defs.h" -extern struct spm_partition_db_t g_spm_partition_db; -static struct service_t *connection_services_listhead; +/* Partition and service runtime data list head/runtime data table */ +static struct partition_head_t partitions_listhead; +static struct service_head_t services_listhead; struct service_t *stateless_services_ref_tbl[STATIC_HANDLE_NUM_LIMIT]; /* Pools */ @@ -259,30 +260,6 @@ struct tfm_msg_body_t *tfm_spm_get_msg_by_signal(struct partition_t *partition, return msg; } -/** - * \brief Returns the index of the partition with the given partition ID. - * - * \param[in] partition_id Partition id - * - * \return the partition idx if partition_id is valid, - * \ref SPM_INVALID_PARTITION_IDX othervise - */ -static uint32_t get_partition_idx(uint32_t partition_id) -{ - uint32_t i; - - if (partition_id == INVALID_PARTITION_ID) { - return SPM_INVALID_PARTITION_IDX; - } - - for (i = 0; i < g_spm_partition_db.partition_count; ++i) { - if (g_spm_partition_db.partitions[i].p_ldinf->pid == partition_id) { - return i; - } - } - return SPM_INVALID_PARTITION_IDX; -} - #if TFM_LVL != 1 /** * \brief Change the privilege mode for partition thread mode. @@ -326,25 +303,15 @@ uint32_t tfm_spm_partition_get_privileged_mode(uint32_t partition_flags) struct service_t *tfm_spm_get_service_by_sid(uint32_t sid) { - uint32_t i = 0; - struct service_t *p_serv = connection_services_listhead; + struct service_t *p_serv; - for (i = 0; i < STATIC_HANDLE_NUM_LIMIT; i++) { - if (stateless_services_ref_tbl[i]) { - if (stateless_services_ref_tbl[i]->p_ldinf->sid == sid) { - return stateless_services_ref_tbl[i]; - } + UNI_LIST_FOR_EACH(p_serv, &services_listhead) { + if (p_serv->p_ldinf->sid == sid) { + return p_serv; } } - while (p_serv && p_serv->p_ldinf->sid != sid) { - p_serv = TO_CONTAINER(BI_LIST_NEXT_NODE(&p_serv->list), - struct service_t, list); - if (p_serv == connection_services_listhead) - return NULL; - } - - return p_serv; + return NULL; } /** @@ -358,11 +325,14 @@ struct service_t *tfm_spm_get_service_by_sid(uint32_t sid) */ static struct partition_t *tfm_spm_get_partition_by_id(int32_t partition_id) { - uint32_t idx = get_partition_idx(partition_id); + struct partition_t *p_part; - if (idx != SPM_INVALID_PARTITION_IDX) { - return &(g_spm_partition_db.partitions[idx]); + UNI_LIST_FOR_EACH(p_part, &partitions_listhead) { + if (p_part->p_ldinf->pid == partition_id) { + return p_part; + } } + return NULL; } @@ -650,8 +620,11 @@ uint32_t tfm_spm_init(void) sizeof(struct tfm_conn_handle_t), TFM_CONN_HANDLE_MAX_NUM); + UNI_LISI_INIT_HEAD(&partitions_listhead); + UNI_LISI_INIT_HEAD(&services_listhead); + while (1) { - partition = load_a_partition_assuredly(); + partition = load_a_partition_assuredly(&partitions_listhead); if (partition == NULL) { break; } @@ -659,7 +632,7 @@ uint32_t tfm_spm_init(void) p_ldinf = partition->p_ldinf; if (p_ldinf->nservices) { - load_services_assuredly(partition, &connection_services_listhead, + load_services_assuredly(partition, &services_listhead, stateless_services_ref_tbl, sizeof(stateless_services_ref_tbl)); } diff --git a/secure_fw/spm/cmsis_psa/spm_ipc.h b/secure_fw/spm/cmsis_psa/spm_ipc.h index 7d6e3420d7..ee710e115e 100644 --- a/secure_fw/spm/cmsis_psa/spm_ipc.h +++ b/secure_fw/spm/cmsis_psa/spm_ipc.h @@ -93,11 +93,7 @@ struct partition_t { uint32_t signals_allowed; uint32_t signals_waiting; uint32_t signals_asserted; -}; - -struct spm_partition_db_t { - uint32_t partition_count; - struct partition_t *partitions; + struct partition_t *next; }; /* RoT Service data */ @@ -105,7 +101,7 @@ struct service_t { const struct service_load_info_t *p_ldinf; /* Service load info */ struct partition_t *partition; /* Owner of the service */ struct bi_list_node_t handle_list; /* Service handle list */ - struct bi_list_node_t list; /* For list operation */ + struct service_t *next; /* For list operation */ }; /* RoT connection handle list */ diff --git a/secure_fw/spm/cmsis_psa/static_load.c b/secure_fw/spm/cmsis_psa/static_load.c index cdd0104a8f..3563dbc865 100644 --- a/secure_fw/spm/cmsis_psa/static_load.c +++ b/secure_fw/spm/cmsis_psa/static_load.c @@ -18,58 +18,62 @@ #include "load/service_defs.h" #include "psa/client.h" -#include "secure_fw/partitions/tfm_service_list.inc" -#include "tfm_spm_db_ipc.inc" - /* Partition load data region */ REGION_DECLARE(Image$$, TFM_SP_LOAD_LIST, $$RO$$Base); REGION_DECLARE(Image$$, TFM_SP_LOAD_LIST, $$RO$$Limit); +/* Partition and service runtime pool region */ +REGION_DECLARE(Image$$, ER_PART_RT_POOL, $$ZI$$Base); +REGION_DECLARE(Image$$, ER_PART_RT_POOL, $$ZI$$Limit); +REGION_DECLARE(Image$$, ER_SERV_RT_POOL, $$ZI$$Base); +REGION_DECLARE(Image$$, ER_SERV_RT_POOL, $$ZI$$Limit); + static uintptr_t ldinf_sa = PART_REGION_ADDR(TFM_SP_LOAD_LIST, $$RO$$Base); static uintptr_t ldinf_ea = PART_REGION_ADDR(TFM_SP_LOAD_LIST, $$RO$$Limit); +static uintptr_t part_pool_sa = PART_REGION_ADDR(ER_PART_RT_POOL, $$ZI$$Base); +static uintptr_t part_pool_ea = PART_REGION_ADDR(ER_PART_RT_POOL, $$ZI$$Limit); +static uintptr_t serv_pool_sa = PART_REGION_ADDR(ER_SERV_RT_POOL, $$ZI$$Base); +static uintptr_t serv_pool_ea = PART_REGION_ADDR(ER_SERV_RT_POOL, $$ZI$$Limit); -/* Allocate runtime space for partition from the pool. Static allocation. */ +/* Allocate runtime space for partition. Panic if pool runs out. */ static struct partition_t *tfm_allocate_partition_assuredly(void) { - static uint32_t partition_pool_pos = 0; - struct partition_t *p_partition_allocated = NULL; + struct partition_t *p_part_allocated = (struct partition_t *)part_pool_sa; - if (partition_pool_pos >= g_spm_partition_db.partition_count) { + part_pool_sa += sizeof(struct partition_t); + if (part_pool_sa > part_pool_ea) { tfm_core_panic(); } - p_partition_allocated = &g_spm_partition_db.partitions[partition_pool_pos]; - partition_pool_pos++; - - return p_partition_allocated; + return p_part_allocated; } -/* Allocate runtime space for service from the pool. Static allocation. */ +/* Allocate runtime space for services. Panic if pool runs out. */ static struct service_t *tfm_allocate_service_assuredly(uint32_t service_count) { - static uint32_t service_pool_pos = 0; - struct service_t *p_service_allocated = NULL; - uint32_t num_of_services = sizeof(g_services) / sizeof(struct service_t); + struct service_t *p_serv_allocated = (struct service_t *)serv_pool_sa; if (service_count == 0) { return NULL; - } else if ((service_count > num_of_services) || - (service_pool_pos >= num_of_services) || - (service_pool_pos + service_count > num_of_services)) { - tfm_core_panic(); } - p_service_allocated = &g_services[service_pool_pos]; - service_pool_pos += service_count; + serv_pool_sa += service_count * sizeof(struct service_t); + if (serv_pool_sa > serv_pool_ea) { + tfm_core_panic(); + } - return p_service_allocated; + return p_serv_allocated; } -struct partition_t *load_a_partition_assuredly(void) +struct partition_t *load_a_partition_assuredly(struct partition_head_t *head) { struct partition_load_info_t *p_ptldinf; struct partition_t *partition; + if (!head) { + tfm_core_panic(); + } + if ((UINTPTR_MAX - ldinf_sa < sizeof(struct partition_load_info_t)) || (ldinf_sa + sizeof(struct partition_load_info_t) >= ldinf_ea)) { return NULL; @@ -102,12 +106,14 @@ struct partition_t *load_a_partition_assuredly(void) ldinf_sa += LOAD_INFSZ_BYTES(p_ptldinf); + UNI_LIST_INSERT_AFTER(head, partition); + return partition; } void load_services_assuredly(struct partition_t *p_partition, - struct service_t **connection_services_listhead, - struct service_t **stateless_service_ref_tbl, + struct service_head_t *services_listhead, + struct service_t **stateless_services_ref_tbl, size_t ref_tbl_size) { uint32_t i, serv_ldflags, hidx; @@ -115,7 +121,7 @@ void load_services_assuredly(struct partition_t *p_partition, const struct partition_load_info_t *p_ptldinf; const struct service_load_info_t *p_servldinf; - if (!p_partition || !connection_services_listhead) { + if (!p_partition || !services_listhead) { tfm_core_panic(); } @@ -131,14 +137,14 @@ void load_services_assuredly(struct partition_t *p_partition, p_partition->signals_allowed |= p_servldinf[i].signal; services[i].p_ldinf = &p_servldinf[i]; services[i].partition = p_partition; + services[i].next = NULL; BI_LIST_INIT_NODE(&services[i].handle_list); - BI_LIST_INIT_NODE(&services[i].list); /* Populate the stateless service reference table */ serv_ldflags = p_servldinf[i].flags; if (SERVICE_IS_STATELESS(serv_ldflags)) { - if ((stateless_service_ref_tbl == NULL) || + if ((stateless_services_ref_tbl == NULL) || (ref_tbl_size == 0) || (ref_tbl_size != STATIC_HANDLE_NUM_LIMIT * sizeof(struct service_t *))) { @@ -148,21 +154,13 @@ void load_services_assuredly(struct partition_t *p_partition, hidx = SERVICE_GET_STATELESS_HINDEX(serv_ldflags); if ((hidx >= STATIC_HANDLE_NUM_LIMIT) || - stateless_service_ref_tbl[hidx]) { + stateless_services_ref_tbl[hidx]) { tfm_core_panic(); } - stateless_service_ref_tbl[hidx] = &services[i]; - - /* Skip chaining stateless services as they won't be looked-up. */ - continue; + stateless_services_ref_tbl[hidx] = &services[i]; } - if (*connection_services_listhead) { - BI_LIST_INSERT_AFTER(&(*connection_services_listhead)->list, - &services[i].list); - } else { - *connection_services_listhead = &services[i]; - } + UNI_LIST_INSERT_AFTER(services_listhead, &services[i]); } } diff --git a/secure_fw/spm/cmsis_psa/tfm_spm_db_ipc.inc.template b/secure_fw/spm/cmsis_psa/tfm_spm_db_ipc.inc.template deleted file mode 100644 index 8081ac7ec0..0000000000 --- a/secure_fw/spm/cmsis_psa/tfm_spm_db_ipc.inc.template +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2019-2021, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -{{utilities.donotedit_warning}} - -#ifndef __TFM_SPM_DB_IPC_INC__ -#define __TFM_SPM_DB_IPC_INC__ - -#include "array.h" -#include "psa_manifest/sid.h" - -{# Produce a build error if heap_size is presented in the manifest, because of the dynamic memory allocation is not supported now. #} -{% for partition in partitions %} - {% if partition.manifest.heap_size %} -#error "Please do not add 'heap_size' for partition '{{partition.manifest.name}}', the dynamic memory allocation is not supported now!" - {% endif %} -{% endfor %} - -/**************************************************************************/ -/** The partition list for the DB */ -/**************************************************************************/ -static struct partition_t partition_list [] = -{ - {{'{0}'}}, /* placeholder for Non-secure internal partition */ - -{% for partition in partitions %} - /* -----------------------------------------------------------------------*/ - /* - Partition DB record for {{partition.manifest.name}} */ - /* -----------------------------------------------------------------------*/ - {% if partition.attr.conditional %} -#ifdef {{partition.attr.conditional}} - {% endif %} - {{'{0}'}}, - {% if partition.attr.conditional %} -#endif /* {{partition.attr.conditional}} */ - {% endif %} - -{% endfor %} -}; - -struct spm_partition_db_t g_spm_partition_db = { - .partition_count = ARRAY_SIZE(partition_list), - .partitions = partition_list, -}; - -#endif /* __TFM_SPM_DB_IPC_INC__ */ diff --git a/secure_fw/spm/include/load/spm_load_api.h b/secure_fw/spm/include/load/spm_load_api.h index 5bc1aed06b..bb8f8993b0 100644 --- a/secure_fw/spm/include/load/spm_load_api.h +++ b/secure_fw/spm/include/load/spm_load_api.h @@ -39,24 +39,37 @@ ((uintptr_t)LOAD_INFO_ASSET(pldinf) + \ (pldinf)->nassets * sizeof(struct asset_desc_t)) + +/* Runtime partition struct list head node type */ +struct partition_head_t { + uint32_t reserved; /* Reserved */ + struct partition_t *next; /* Next partition node */ +}; + +/* Runtime service struct list head node type */ +struct service_head_t { + uint32_t reserved; /* Reserved */ + struct service_t *next; /* Next partition node */ +}; + /* - * Allocate a partition object and return if a load is successful. + * Load a partition object to linked list and return if a load is successful. * An 'assuredly' function, return NULL for no more partitions and * return a valid pointer if succeed. Other errors simply panic * the system and never return. */ -struct partition_t *load_a_partition_assuredly(void); +struct partition_t *load_a_partition_assuredly(struct partition_head_t *head); /* - * Allocated numbers of service objects based on given partition. - * Link services with 'list_head' if it is provided. It also needs the - * stateless service reference table and whole table size for loading. + * Load numbers of service objects to linked list based on given partition. + * It loads connection based services and stateless services that partition + * contains. * As an 'assuredly' function, errors simply panic the system and never * return. */ void load_services_assuredly(struct partition_t *p_partition, - struct service_t **connection_services_listhead, - struct service_t **stateless_service_ref_tbl, + struct service_head_t *services_listhead, + struct service_t **stateless_services_ref_tbl, size_t ref_tbl_size); /* |