Core: Add non-secure thread entry
The non-secure thread entry is used to replace the idle thread.
It takes over the main init process, and jump to the non-secure
world at last.
- Set the non-secure thread entry with the lowest priority.
- Delete the idle thread which is unused anymore.
- Refine tfm_pendsv_do_schedule() function, does not need to handle
the idle thread.
Change-Id: Id2b04647db26b92c61f5f63fb0ac0f814a55aab4
Signed-off-by: Edison Ai <edison.ai@arm.com>
diff --git a/platform/ext/target/mps2/an521/spm_hal.c b/platform/ext/target/mps2/an521/spm_hal.c
index d7a3bb0..9b05a75 100644
--- a/platform/ext/target/mps2/an521/spm_hal.c
+++ b/platform/ext/target/mps2/an521/spm_hal.c
@@ -48,12 +48,17 @@
#define MPU_REGION_VENEERS 0
#define MPU_REGION_TFM_UNPRIV_CODE 1
#define MPU_REGION_TFM_UNPRIV_DATA 2
-#define MPU_REGION_NS_DATA 3
#define PARTITION_REGION_RO 4
#define PARTITION_REGION_RW_STACK 5
#define PARTITION_REGION_PERIPH 6
#define PARTITION_REGION_SHARE 7
+#if TFM_LVL == 2
+#define MPU_REGION_NS_STACK 3
+#elif TFM_LVL == 3
+#define MPU_REGION_NS_DATA 3
+#endif
+
REGION_DECLARE(Image$$, TFM_UNPRIV_CODE, $$RO$$Base);
REGION_DECLARE(Image$$, TFM_UNPRIV_CODE, $$RO$$Limit);
REGION_DECLARE(Image$$, TFM_UNPRIV_RO_DATA, $$RW$$Base);
@@ -65,6 +70,8 @@
REGION_DECLARE(Image$$, TFM_APP_CODE_END, $$Base);
REGION_DECLARE(Image$$, TFM_APP_RW_STACK_START, $$Base);
REGION_DECLARE(Image$$, TFM_APP_RW_STACK_END, $$Base);
+REGION_DECLARE(Image$$, ARM_LIB_STACK, $$ZI$$Base);
+REGION_DECLARE(Image$$, ARM_LIB_STACK, $$ZI$$Limit);
#endif
static enum spm_err_t tfm_spm_mpu_init(void)
@@ -113,6 +120,7 @@
return SPM_ERR_INVALID_CONFIG;
}
+#if TFM_LVL == 3
/* TFM Core unprivileged non-secure data region */
region_cfg.region_nr = MPU_REGION_NS_DATA;
region_cfg.region_base = NS_DATA_START;
@@ -124,8 +132,22 @@
if (mpu_armv8m_region_enable(&dev_mpu_s, ®ion_cfg) != MPU_ARMV8M_OK) {
return SPM_ERR_INVALID_CONFIG;
}
+#endif
#if TFM_LVL == 2
+ /* NSPM PSP */
+ region_cfg.region_nr = MPU_REGION_NS_STACK;
+ region_cfg.region_base =
+ (uint32_t)®ION_NAME(Image$$, ARM_LIB_STACK, $$ZI$$Base);
+ region_cfg.region_limit =
+ (uint32_t)®ION_NAME(Image$$, ARM_LIB_STACK, $$ZI$$Limit);
+ region_cfg.attr_access = MPU_ARMV8M_AP_RW_PRIV_UNPRIV;
+ region_cfg.attr_sh = MPU_ARMV8M_SH_NONE;
+ region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_NEVER;
+ if (mpu_armv8m_region_enable(&dev_mpu_s, ®ion_cfg) != MPU_ARMV8M_OK) {
+ return SPM_ERR_INVALID_CONFIG;
+ }
+
/* RO region */
region_cfg.region_nr = PARTITION_REGION_RO;
region_cfg.region_base =
diff --git a/secure_fw/core/ipc/tfm_spm.c b/secure_fw/core/ipc/tfm_spm.c
index 54b7d04..4181616 100644
--- a/secure_fw/core/ipc/tfm_spm.c
+++ b/secure_fw/core/ipc/tfm_spm.c
@@ -524,10 +524,10 @@
for (i = 0; i < SPM_MAX_PARTITIONS; i++) {
part = &g_spm_partition_db.partitions[i];
tfm_spm_hal_configure_default_isolation(part->platform_data);
+ g_spm_ipc_partition[i].index = i;
if ((tfm_spm_partition_get_flags(i) & SPM_PART_FLAG_IPC) == 0) {
continue;
}
- g_spm_ipc_partition[i].index = i;
g_spm_ipc_partition[i].id = tfm_spm_partition_get_partition_id(i);
tfm_event_init(&g_spm_ipc_partition[i].signal_evnt);
diff --git a/secure_fw/core/ipc/tfm_thread.c b/secure_fw/core/ipc/tfm_thread.c
index 0ea94b8..b349732 100644
--- a/secure_fw/core/ipc/tfm_thread.c
+++ b/secure_fw/core/ipc/tfm_thread.c
@@ -126,42 +126,9 @@
update_running_head(&RUNN_HEAD, pth);
}
-/*
- * TEMP WORKAROUND: The caller function who called thread module init needs to
- * be returned. The caller is not a thread. Create a dummy IDLE thread to
- * collect caller context; and schedule back to the caller with this context
- * after all other real threads blocked.
- *
- * This WORKAROUND needs to be removed after IPC NSPM takes place.
- */
-#define DUMMY_IDLE_TAG 0xDEEDDEED
-static uint8_t idle_stack[32] __attribute__((aligned(8)));
-static struct tfm_thrd_ctx idle_thread;
-static struct tfm_thrd_ctx *init_idle_thread(struct tfm_thrd_ctx *pth)
-{
- /*
- * IDLE thread is a thread with the lowest priority.
- * It gets scheduled after all other higher priority threads get blocked.
- * The entry of IDLE thread is a dummy and has no mean.
- */
- tfm_thrd_init(pth, (tfm_thrd_func_t)DUMMY_IDLE_TAG, NULL,
- (uint8_t *)&idle_stack[32], (uint8_t *)idle_stack);
- tfm_thrd_priority(pth, THRD_PRIOR_LOWEST);
- tfm_thrd_start(pth);
- return pth;
-}
-
/* Scheduling won't happen immediately but after the exception returns */
void tfm_thrd_activate_schedule(void)
{
- /*
- * The current thread can be NULL only when initializing. Create the IDLE
- * thread and set it as the current thread to collect caller context.
- */
- if (CURR_THRD == NULL) {
- CURR_THRD = init_idle_thread(&idle_thread);
- }
-
tfm_trigger_pendsv();
}
diff --git a/secure_fw/core/tfm_core.c b/secure_fw/core/tfm_core.c
index 27411d4..1c53071 100644
--- a/secure_fw/core/tfm_core.c
+++ b/secure_fw/core/tfm_core.c
@@ -207,6 +207,13 @@
tfm_spm_partition_set_state(TFM_SP_CORE_ID, SPM_PARTITION_STATE_CLOSED);
tfm_spm_partition_set_state(TFM_SP_NON_SECURE_ID,
SPM_PARTITION_STATE_RUNNING);
+
+#ifdef TFM_CORE_DEBUG
+ /* Jumps to non-secure code */
+ LOG_MSG("Jumping to non-secure code...");
+#endif
+
+ jump_to_ns_code();
#else
/*
* Prioritise secure exceptions to avoid NS being able to pre-empt
@@ -215,11 +222,4 @@
tfm_core_set_secure_exception_priorities();
tfm_spm_init();
#endif
-
-#ifdef TFM_CORE_DEBUG
- /* Jumps to non-secure code */
- LOG_MSG("Jumping to non-secure code...");
-#endif
-
- jump_to_ns_code();
}
diff --git a/secure_fw/core/tfm_nspm.c b/secure_fw/core/tfm_nspm.c
index 3188e28..3db30c2 100644
--- a/secure_fw/core/tfm_nspm.c
+++ b/secure_fw/core/tfm_nspm.c
@@ -6,8 +6,13 @@
*/
#include <stdio.h>
+#include <stdbool.h>
#include "secure_utilities.h"
#include "tfm_api.h"
+#if TFM_PSA_API
+#include "tfm_utils.h"
+#include "tfm_internal.h"
+#endif
#ifndef TFM_MAX_NS_THREAD_COUNT
#define TFM_MAX_NS_THREAD_COUNT 8
@@ -300,3 +305,20 @@
return TFM_SUCCESS;
}
#endif
+
+#ifdef TFM_PSA_API
+__attribute__((section("SFN")))
+psa_status_t tfm_nspm_thread_entry(void)
+{
+#ifdef TFM_CORE_DEBUG
+ /* Jumps to non-secure code */
+ LOG_MSG("Jumping to non-secure code...");
+#endif
+
+ jump_to_ns_code();
+
+ /* Should not run here */
+ TFM_ASSERT(false);
+ return PSA_SUCCESS;
+}
+#endif
diff --git a/secure_fw/core/tfm_nspm.h b/secure_fw/core/tfm_nspm.h
index b485462..572c734 100644
--- a/secure_fw/core/tfm_nspm.h
+++ b/secure_fw/core/tfm_nspm.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
@@ -23,4 +23,15 @@
*/
int32_t tfm_nspm_get_current_client_id(void);
+#ifdef TFM_PSA_API
+/**
+ * \brief NSPM thread main entry function
+ *
+ * \return PSA_SUCCESS indicates failed.
+ *
+ * Note: This function should not return back.
+ */
+psa_status_t tfm_nspm_thread_entry(void);
+#endif
+
#endif /* __TFM_NSPM_H__ */
diff --git a/secure_fw/spm/spm_api.c b/secure_fw/spm/spm_api.c
index a1ee127..05d6c8d 100644
--- a/secure_fw/spm/spm_api.c
+++ b/secure_fw/spm/spm_api.c
@@ -110,7 +110,14 @@
part_ptr = &(g_spm_partition_db.partitions[
g_spm_partition_db.partition_count]);
part_ptr->static_data.partition_id = TFM_SP_NON_SECURE_ID;
+#if TFM_PSA_API
+ part_ptr->static_data.partition_flags = SPM_PART_FLAG_APP_ROT |
+ SPM_PART_FLAG_IPC;
+ part_ptr->static_data.partition_priority = TFM_PRIORITY_LOW;
+ part_ptr->static_data.partition_init = tfm_nspm_thread_entry;
+#else
part_ptr->static_data.partition_flags = 0;
+#endif
#if TFM_LVL != 1
part_ptr->memory_data.stack_bottom = psp_stack_bottom;