aboutsummaryrefslogtreecommitdiff
path: root/secure_fw
diff options
context:
space:
mode:
authorKen Liu <Ken.Liu@arm.com>2021-05-22 17:41:25 +0800
committerKen Liu <ken.liu@arm.com>2021-06-30 05:45:14 +0200
commitea45b0d4fb29351c029a13dc66b76898d41d53ce (patch)
treea4fa875f5868b88239d939f55125dc873121ad4a /secure_fw
parente5c151d0c8dd37c0b79ff928109a3b8537162d8c (diff)
downloadtrusted-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.c5
-rw-r--r--secure_fw/partitions/partition_load_info.template7
-rw-r--r--secure_fw/partitions/tfm_service_list.inc.template49
-rwxr-xr-xsecure_fw/spm/CMakeLists.txt2
-rw-r--r--secure_fw/spm/cmsis_psa/spm_ipc.c65
-rw-r--r--secure_fw/spm/cmsis_psa/spm_ipc.h8
-rw-r--r--secure_fw/spm/cmsis_psa/static_load.c76
-rw-r--r--secure_fw/spm/cmsis_psa/tfm_spm_db_ipc.inc.template50
-rw-r--r--secure_fw/spm/include/load/spm_load_api.h27
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);
/*