SPM: Use Main Stack for initialization
On reset, the Main Stack is used by default.
TF-M changes the stack to Processor Stack.
This patch remove the change to PSP in startup.s and:
- Rename the ARM_LIB_STACK to ER_INITIAL_PSP
- Rename the ARM_LIB_STACK_MSP to ARM_LIB_STACK
The renaming is to align the __main function of ARMClang where the
ARM_LIB_STACK is set to the current SP (MSP)
For Library Mode, the stacks are set to back to use PSP before entering
c code to avoid massive corresponding changes.
For FF-M implementations, this patch also:
- Seal the Main Stack before entering c code
- Manually free the Main Stack usage after initialization as the init
function does not return
Change-Id: Ie1b6f2fca1f774c4812a89fa45bb039b16fe5af0
Signed-off-by: Kevin Peng <kevin.peng@arm.com>
Co-authored-by: Summer Qin <summer.qin@arm.com>
diff --git a/secure_fw/partitions/ns_agent/load_info_ns_agent.c b/secure_fw/partitions/ns_agent/load_info_ns_agent.c
index 6e3ec2a..960cca2 100644
--- a/secure_fw/partitions/ns_agent/load_info_ns_agent.c
+++ b/secure_fw/partitions/ns_agent/load_info_ns_agent.c
@@ -23,8 +23,8 @@
#endif
/* Memory region declaration */
-REGION_DECLARE(Image$$, ARM_LIB_STACK, $$ZI$$Base);
-REGION_DECLARE(Image$$, ARM_LIB_STACK, $$ZI$$Limit);
+REGION_DECLARE(Image$$, ER_INITIAL_PSP, $$ZI$$Base);
+REGION_DECLARE(Image$$, ER_INITIAL_PSP, $$ZI$$Limit);
/* Entrypoint function declaration */
extern void tfm_nspm_thread_entry(void);
@@ -65,15 +65,15 @@
.nassets = TFM_SP_NS_AGENT_NASSETS,
#endif
},
- .stack_addr = PART_REGION_ADDR(ARM_LIB_STACK,
+ .stack_addr = PART_REGION_ADDR(ER_INITIAL_PSP,
$$ZI$$Base),
.heap_addr = 0,
#if TFM_LVL == 3
.assets = {
{
- .mem.start = PART_REGION_ADDR(ARM_LIB_STACK,
+ .mem.start = PART_REGION_ADDR(ER_INITIAL_PSP,
$$ZI$$Base),
- .mem.limit = PART_REGION_ADDR(ARM_LIB_STACK,
+ .mem.limit = PART_REGION_ADDR(ER_INITIAL_PSP,
$$ZI$$Limit),
.attr = ASSET_ATTR_READ_WRITE,
},
diff --git a/secure_fw/spm/cmsis_func/include/tfm_spm_services.h b/secure_fw/spm/cmsis_func/include/tfm_spm_services.h
index a556573..ff846c0 100644
--- a/secure_fw/spm/cmsis_func/include/tfm_spm_services.h
+++ b/secure_fw/spm/cmsis_func/include/tfm_spm_services.h
@@ -10,8 +10,6 @@
#include <stdint.h>
-typedef uint32_t psa_signal_t;
-
void tfm_enable_irq(psa_signal_t irq_signal);
void tfm_disable_irq(psa_signal_t irq_signal);
diff --git a/secure_fw/spm/cmsis_func/main.c b/secure_fw/spm/cmsis_func/main.c
index c9ef011..4cbecd8 100644
--- a/secure_fw/spm/cmsis_func/main.c
+++ b/secure_fw/spm/cmsis_func/main.c
@@ -33,7 +33,7 @@
#error Only TFM_LVL 1 is supported for library model!
#endif
-REGION_DECLARE(Image$$, ARM_LIB_STACK_MSP, $$ZI$$Base);
+REGION_DECLARE(Image$$, ARM_LIB_STACK, $$ZI$$Base);
static fih_int tfm_core_init(void)
{
@@ -134,14 +134,33 @@
FIH_RET(fih_int_encode(TFM_SUCCESS));
}
+__attribute__((naked))
int main(void)
{
+ __ASM volatile(
+#if !defined(__ICCARM__)
+ ".syntax unified \n"
+#endif
+ "ldr r0, =Image$$ARM_LIB_STACK$$ZI$$Limit \n"
+ "msr msp, r0 \n"
+ "ldr r0, =Image$$ER_INITIAL_PSP$$ZI$$Limit \n"
+ "msr psp, r0 \n"
+ "mrs r0, control \n"
+ "movs r1, #2 \n"
+ "orrs r0, r0, r1 \n" /* Switch to PSP */
+ "msr control, r0 \n"
+ "bl c_main \n"
+ );
+}
+
+int c_main(void)
+{
enum spm_err_t spm_err = SPM_ERR_GENERIC_ERR;
fih_int fih_rc = FIH_FAILURE;
/* set Main Stack Pointer limit */
tfm_arch_init_secure_msp((uint32_t)®ION_NAME(Image$$,
- ARM_LIB_STACK_MSP,
+ ARM_LIB_STACK,
$$ZI$$Base));
/* Seal the PSP stacks viz ARM_LIB_STACK and TFM_SECURE_STACK */
@@ -167,9 +186,9 @@
tfm_spm_partition_set_state(TFM_SP_CORE_ID, SPM_PARTITION_STATE_RUNNING);
- REGION_DECLARE(Image$$, ARM_LIB_STACK, $$ZI$$Base)[];
+ REGION_DECLARE(Image$$, ER_INITIAL_PSP, $$ZI$$Base)[];
uint32_t psp_stack_bottom =
- (uint32_t)REGION_NAME(Image$$, ARM_LIB_STACK, $$ZI$$Base);
+ (uint32_t)REGION_NAME(Image$$, ER_INITIAL_PSP, $$ZI$$Base);
tfm_arch_set_psplim(psp_stack_bottom);
@@ -206,4 +225,6 @@
#endif
jump_to_ns_code();
+
+ return 0;
}
diff --git a/secure_fw/spm/cmsis_func/spm_func.c b/secure_fw/spm/cmsis_func/spm_func.c
index 882f517..5326f94 100644
--- a/secure_fw/spm/cmsis_func/spm_func.c
+++ b/secure_fw/spm/cmsis_func/spm_func.c
@@ -56,7 +56,7 @@
static uint32_t *tfm_secure_stack_seal =
((uint32_t *)®ION_NAME(Image$$, TFM_SECURE_STACK, $$ZI$$Limit)[-1]) - 2;
-REGION_DECLARE_T(Image$$, ARM_LIB_STACK_SEAL, $$ZI$$Base, uint32_t)[];
+REGION_DECLARE_T(Image$$, ER_INITIAL_PSP_SEAL, $$ZI$$Base, uint32_t)[];
/*
* Function to seal the psp stacks for Function model of TF-M.
@@ -84,11 +84,11 @@
*(tfm_secure_stack_seal + 1) = TFM_STACK_SEAL_VALUE;
/*
- * Seal the ARM_LIB_STACK by writing the seal value to the reserved
+ * Seal the ER_INITIAL_PSP by writing the seal value to the reserved
* region.
*/
uint32_t *arm_lib_stck_seal_base =
- ((uint32_t *)®ION_NAME(Image$$, ARM_LIB_STACK_SEAL, $$ZI$$Base)[-1]) - 2;
+ ((uint32_t *)®ION_NAME(Image$$, ER_INITIAL_PSP_SEAL, $$ZI$$Base)[-1]) - 2;
*(arm_lib_stck_seal_base) = TFM_STACK_SEAL_VALUE;
*(arm_lib_stck_seal_base + 1) = TFM_STACK_SEAL_VALUE;
@@ -652,9 +652,9 @@
(struct tfm_state_context_t *)ret_part_data->stack_ptr);
*excReturn = ret_part_data->lr;
__set_PSP(ret_part_data->stack_ptr);
- REGION_DECLARE_T(Image$$, ARM_LIB_STACK, $$ZI$$Base, uint32_t)[];
+ REGION_DECLARE_T(Image$$, ER_INITIAL_PSP, $$ZI$$Base, uint32_t)[];
uint32_t psp_stack_bottom =
- (uint32_t)REGION_NAME(Image$$, ARM_LIB_STACK, $$ZI$$Base);
+ (uint32_t)REGION_NAME(Image$$, ER_INITIAL_PSP, $$ZI$$Base);
tfm_arch_set_psplim(psp_stack_bottom);
iovec_args = ®ION_NAME(Image$$, TFM_SECURE_STACK, $$ZI$$Limit)[-1];
diff --git a/secure_fw/spm/cmsis_psa/arch/tfm_arch.c b/secure_fw/spm/cmsis_psa/arch/tfm_arch.c
index 3d9f076..1d3e371 100644
--- a/secure_fw/spm/cmsis_psa/arch/tfm_arch.c
+++ b/secure_fw/spm/cmsis_psa/arch/tfm_arch.c
@@ -8,7 +8,23 @@
#include "svc_num.h"
#include "tfm_arch.h"
#include "tfm_core_utils.h"
+#include "utilities.h"
+__attribute__((naked)) void tfm_arch_free_msp_and_exc_ret(uint32_t exc_return)
+{
+ __ASM volatile(
+#if !defined(__ICCARM__)
+ ".syntax unified \n"
+#endif
+ "MOV lr, r0 \n"
+ "LDR r0, ="M2S(VTOR_BASE)" \n" /* VTOR */
+ "LDR r0, [r0] \n" /* MSP address */
+ "LDR r0, [r0] \n" /* MSP */
+ "SUBS r0, #8 \n" /* Exclude stack seal */
+ "MSR msp, r0 \n" /* Free Main Stack space */
+ "BX lr \n"
+ );
+}
static void tfm_arch_init_state_ctx(struct tfm_state_context_t *p_stat_ctx,
void *param, uintptr_t pfn)
diff --git a/secure_fw/spm/cmsis_psa/arch/tfm_arch_v6m_v7m.h b/secure_fw/spm/cmsis_psa/arch/tfm_arch_v6m_v7m.h
index b29af05..fca3fa0 100644
--- a/secure_fw/spm/cmsis_psa/arch/tfm_arch_v6m_v7m.h
+++ b/secure_fw/spm/cmsis_psa/arch/tfm_arch_v6m_v7m.h
@@ -35,6 +35,8 @@
#define EXC_NUM_SVCALL (11)
#define EXC_NUM_PENDSV (14)
+#define VTOR_BASE (0xE000ED08)
+
struct tfm_arch_ctx_t {
uint32_t r8;
uint32_t r9;
@@ -110,6 +112,20 @@
}
/**
+ * \brief Set MSP limit value.
+ *
+ * \param[in] msplim MSP limit value to be written.
+ */
+__STATIC_INLINE void tfm_arch_set_msplim(uint32_t msplim)
+{
+ /*
+ * Defined as an empty function now.
+ * The MSP limit value can be used in more strict memory check.
+ */
+ (void)msplim;
+}
+
+/**
* \brief Seal the thread stack.
*
* \param[in] stk Thread stack address.
diff --git a/secure_fw/spm/cmsis_psa/main.c b/secure_fw/spm/cmsis_psa/main.c
index 7d34578..30cae8b 100644
--- a/secure_fw/spm/cmsis_psa/main.c
+++ b/secure_fw/spm/cmsis_psa/main.c
@@ -31,7 +31,7 @@
#error Invalid TFM_LVL value. Only TFM_LVL 1, 2 and 3 are supported in IPC model!
#endif
-REGION_DECLARE(Image$$, ARM_LIB_STACK_MSP, $$ZI$$Base);
+REGION_DECLARE(Image$$, ARM_LIB_STACK, $$ZI$$Base);
static fih_int tfm_core_init(void)
{
@@ -123,13 +123,24 @@
FIH_RET(fih_int_encode(TFM_SUCCESS));
}
+__attribute__((naked))
int main(void)
{
+ __ASM volatile(
+ "ldr r0, =0xFEF5EDA5 \n" /* Seal Main Stack before using */
+ "ldr r1, =0xFEF5EDA5 \n"
+ "push {r0, r1} \n"
+ "bl c_main \n"
+ );
+}
+
+int c_main(void)
+{
fih_int fih_rc = FIH_FAILURE;
/* set Main Stack Pointer limit */
- tfm_arch_init_secure_msp((uint32_t)®ION_NAME(Image$$, ARM_LIB_STACK_MSP,
- $$ZI$$Base));
+ tfm_arch_set_msplim((uint32_t)®ION_NAME(Image$$, ARM_LIB_STACK,
+ $$ZI$$Base));
fih_delay_init();
@@ -152,4 +163,6 @@
/* Move to handler mode for further SPM initialization. */
tfm_core_handler_mode();
+
+ return 0;
}
diff --git a/secure_fw/spm/cmsis_psa/tfm_core_svcalls_ipc.c b/secure_fw/spm/cmsis_psa/tfm_core_svcalls_ipc.c
index dd3c48c..0987f07 100644
--- a/secure_fw/spm/cmsis_psa/tfm_core_svcalls_ipc.c
+++ b/secure_fw/spm/cmsis_psa/tfm_core_svcalls_ipc.c
@@ -22,7 +22,7 @@
#include "psa/client.h"
/* MSP bottom (higher address) */
-REGION_DECLARE(Image$$, ARM_LIB_STACK_MSP, $$ZI$$Limit);
+REGION_DECLARE(Image$$, ARM_LIB_STACK, $$ZI$$Limit);
#ifdef PLATFORM_SVC_HANDLERS
extern int32_t platform_svc_handlers(uint8_t svc_num,
@@ -176,7 +176,7 @@
struct partition_t *curr_sp, *prev_sp;
struct tfm_svc_flih_ctx_t *flih_ctx;
uint32_t msp_top =
- (uint32_t)®ION_NAME(Image$$, ARM_LIB_STACK_MSP, $$ZI$$Limit);
+ (uint32_t)®ION_NAME(Image$$, ARM_LIB_STACK, $$ZI$$Limit);
/* Skip one tfm_svc_flih_ctx_t + 8 words (R4- R11) + seals (2 words) */
flih_ctx = (struct tfm_svc_flih_ctx_t *)
@@ -257,6 +257,8 @@
case TFM_SVC_SPM_INIT:
tfm_arch_clear_fp_status();
exc_return = tfm_spm_init();
+ /* The following call does not return */
+ tfm_arch_free_msp_and_exc_ret(exc_return);
break;
case TFM_SVC_GET_BOOT_DATA:
tfm_core_get_boot_data_handler(svc_args);
@@ -268,7 +270,7 @@
exc_return = tfm_flih_return_to_isr(flih_ctx, svc_args[0]);
break;
default:
- if (((uint32_t)®ION_NAME(Image$$, ARM_LIB_STACK_MSP, $$ZI$$Limit)
+ if (((uint32_t)®ION_NAME(Image$$, ARM_LIB_STACK, $$ZI$$Limit)
- (uint32_t)msp) > TFM_STACK_SEALED_SIZE) {
/* The Main Stack has contents, not calling from Partition thread */
tfm_core_panic();
diff --git a/secure_fw/spm/include/tfm_arch.h b/secure_fw/spm/include/tfm_arch.h
index 8a96d9f..8eb24b8 100644
--- a/secure_fw/spm/include/tfm_arch.h
+++ b/secure_fw/spm/include/tfm_arch.h
@@ -103,6 +103,13 @@
*/
void tfm_arch_clear_fp_status(void);
+/*
+ * This function is called after SPM has initialized.
+ * It frees the stack used by SPM initialization and do Exception Return.
+ * It does not return.
+ */
+void tfm_arch_free_msp_and_exc_ret(uint32_t exc_return);
+
void tfm_arch_init_context(struct tfm_arch_ctx_t *p_actx,
void *param, uintptr_t pfn,
uintptr_t stk_btm, uintptr_t stk_top);
diff --git a/secure_fw/spm/include/tfm_arch_v8m.h b/secure_fw/spm/include/tfm_arch_v8m.h
index e615c3c..a532a51 100644
--- a/secure_fw/spm/include/tfm_arch_v8m.h
+++ b/secure_fw/spm/include/tfm_arch_v8m.h
@@ -45,6 +45,8 @@
#define EXC_NUM_SVCALL (11)
#define EXC_NUM_PENDSV (14)
+#define VTOR_BASE (0xE000ED08)
+
#if defined(__ARM_ARCH_8_1M_MAIN__) || defined(__ARM_ARCH_8M_MAIN__)
struct tfm_arch_ctx_t {
uint32_t r4;
@@ -123,6 +125,16 @@
}
/**
+ * \brief Set MSP limit value.
+ *
+ * \param[in] msplim MSP limit value to be written.
+ */
+__STATIC_INLINE void tfm_arch_set_msplim(uint32_t msplim)
+{
+ __set_MSPLIM(msplim);
+}
+
+/**
* \brief Seal the thread stack.
*
* This function must be called only when the caller is using MSP.
diff --git a/secure_fw/spm/include/utilities.h b/secure_fw/spm/include/utilities.h
index f527071..aec3ea0 100644
--- a/secure_fw/spm/include/utilities.h
+++ b/secure_fw/spm/include/utilities.h
@@ -37,4 +37,8 @@
/* FixMe: Replace ERROR_MSG() in platform code with a suitable API */
#define ERROR_MSG(msg) SPMLOG_ERRMSG(msg "\r\n")
+/* Preprocessor to reference C MACRO to string in inline asm */
+#define M2S_HELPER(x) #x
+#define M2S(m) M2S_HELPER(m)
+
#endif /* __TFM_UTILS_H__ */