Core: use secure partition context for its init
- set appropriate stack pointer for partition init
- move target-independent init code to TF-M core
- set unprivileged execution for init functions if
privilege handling is enabled
- fix naming convention bug related to spm_api.h
- fix header reference for partition ids
Change-Id: I56fe20a247ecde20047658d3227ae95257c95e0f
Signed-off-by: Miklos Balint <miklos.balint@arm.com>
diff --git a/secure_fw/spm/spm_api.c b/secure_fw/spm/spm_api.c
index 40d054d..e83c62e 100644
--- a/secure_fw/spm/spm_api.c
+++ b/secure_fw/spm/spm_api.c
@@ -11,6 +11,7 @@
#include <string.h>
#include "spm_api.h"
#include "spm_db.h"
+#include "tfm_internal.h"
#include "tfm_api.h"
#include "mpu_armv8m_drv.h"
#include "region_defs.h"
@@ -89,6 +90,10 @@
*/
/* For the non secure Execution environment */
+#if TFM_LVL != 1
+ extern uint32_t Stack_Mem[];
+ extern uint32_t Stack_top[];
+#endif
if (g_spm_partition_db.partition_count >= SPM_MAX_PARTITIONS) {
return SPM_ERR_INVALID_CONFIG;
}
@@ -96,6 +101,16 @@
g_spm_partition_db.partition_count]);
part_ptr->static_data.partition_id = TFM_SP_NON_SECURE_ID;
part_ptr->static_data.partition_flags = 0;
+
+#if TFM_LVL != 1
+ part_ptr->static_data.stack_bottom = (uint32_t)Stack_Mem;
+ part_ptr->static_data.stack_top = (uint32_t)Stack_top;
+ /* Since RW, ZI and stack are configured as one MPU region, configure
+ * RW start address to Stack_Mem to get RW access to stack
+ */
+ part_ptr->static_data.rw_start = (uint32_t)Stack_Mem;
+#endif
+
part_ptr->runtime_data.partition_state = SPM_PARTITION_STATE_UNINIT;
++g_spm_partition_db.partition_count;
@@ -140,7 +155,9 @@
region_cfg.attr_access = MPU_ARMV8M_AP_RO_PRIV_UNPRIV;
region_cfg.attr_sh = MPU_ARMV8M_SH_NONE;
region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_OK;
- mpu_armv8m_region_enable(&dev_mpu_s, ®ion_cfg);
+ if (mpu_armv8m_region_enable(&dev_mpu_s, ®ion_cfg) != MPU_ARMV8M_OK) {
+ return SPM_ERR_INVALID_CONFIG;
+ }
/* TFM Core unprivileged code region */
region_cfg.region_nr = MPU_REGION_TFM_UNPRIV_CODE;
@@ -151,7 +168,9 @@
region_cfg.attr_access = MPU_ARMV8M_AP_RO_PRIV_UNPRIV;
region_cfg.attr_sh = MPU_ARMV8M_SH_NONE;
region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_OK;
- mpu_armv8m_region_enable(&dev_mpu_s, ®ion_cfg);
+ if (mpu_armv8m_region_enable(&dev_mpu_s, ®ion_cfg) != MPU_ARMV8M_OK) {
+ return SPM_ERR_INVALID_CONFIG;
+ }
/* TFM Core unprivileged data region */
region_cfg.region_nr = MPU_REGION_TFM_UNPRIV_DATA;
@@ -162,7 +181,9 @@
region_cfg.attr_access = MPU_ARMV8M_AP_RO_PRIV_UNPRIV;
region_cfg.attr_sh = MPU_ARMV8M_SH_NONE;
region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_NEVER;
- mpu_armv8m_region_enable(&dev_mpu_s, ®ion_cfg);
+ if (mpu_armv8m_region_enable(&dev_mpu_s, ®ion_cfg) != MPU_ARMV8M_OK) {
+ return SPM_ERR_INVALID_CONFIG;
+ }
/* TFM Core unprivileged non-secure data region */
region_cfg.region_nr = MPU_REGION_NS_DATA;
@@ -171,7 +192,9 @@
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;
- mpu_armv8m_region_enable(&dev_mpu_s, ®ion_cfg);
+ if (mpu_armv8m_region_enable(&dev_mpu_s, ®ion_cfg) != MPU_ARMV8M_OK) {
+ return SPM_ERR_INVALID_CONFIG;
+ }
mpu_armv8m_enable(&dev_mpu_s, 1, 1);
@@ -234,14 +257,12 @@
enum spm_err_t tfm_spm_partition_init(void)
{
struct spm_partition_desc_t *part;
+ struct tfm_sfn_req_s desc, *desc_ptr = &desc;
+ int32_t args[4] = {0};
int32_t fail_cnt = 0;
uint32_t idx;
/* Call the init function for each partition */
- /* FixMe: This implementation only fits level 1 isolation.
- * On higher levels MPU (and PPC) configuration need to be in place to have
- * proper isolation during init.
- */
for (idx = 0; idx < g_spm_partition_db.partition_count; ++idx) {
part = &g_spm_partition_db.partitions[idx];
if (part->static_data.periph_start) {
@@ -250,8 +271,22 @@
}
if (part->static_data.partition_init == NULL) {
tfm_spm_partition_set_state(idx, SPM_PARTITION_STATE_IDLE);
+ tfm_spm_partition_set_caller_partition_idx(idx,
+ SPM_INVALID_PARTITION_IDX);
} else {
- int32_t ret = part->static_data.partition_init();
+ int32_t ret;
+
+ desc.args = args;
+ desc.exc_num = EXC_NUM_THREAD_MODE;
+ desc.ns_caller = 0;
+ desc.sfn = (sfn_t)part->static_data.partition_init;
+ desc.sp_id = part->static_data.partition_id;
+ __ASM("MOV r0, %1\n"
+ "SVC %2\n"
+ "MOV %0, r0\n"
+ : "=r" (ret)
+ : "r" (desc_ptr), "I" (TFM_SVC_SFN_REQUEST)
+ : "r0");
if (ret == TFM_SUCCESS) {
tfm_spm_partition_set_state(idx, SPM_PARTITION_STATE_IDLE);
@@ -262,6 +297,8 @@
}
}
+ tfm_secure_api_init_done();
+
if (fail_cnt == 0) {
return SPM_ERR_OK;
} else {
@@ -290,15 +327,20 @@
/* Configure Regions */
- /* RO region*/
- region_cfg.region_nr = PARTITION_REGION_RO;
- region_cfg.region_base = part->static_data.ro_start;
- region_cfg.region_limit = part->static_data.ro_limit;
- region_cfg.attr_access = MPU_ARMV8M_AP_RO_PRIV_UNPRIV;
- region_cfg.attr_sh = MPU_ARMV8M_SH_NONE;
- region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_OK;
+ if (part->static_data.ro_start) {
+ /* RO region*/
+ region_cfg.region_nr = PARTITION_REGION_RO;
+ region_cfg.region_base = part->static_data.ro_start;
+ region_cfg.region_limit = part->static_data.ro_limit;
+ region_cfg.attr_access = MPU_ARMV8M_AP_RO_PRIV_UNPRIV;
+ region_cfg.attr_sh = MPU_ARMV8M_SH_NONE;
+ region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_OK;
- mpu_armv8m_region_enable(&dev_mpu_s, ®ion_cfg);
+ if (mpu_armv8m_region_enable(&dev_mpu_s, ®ion_cfg)
+ != MPU_ARMV8M_OK) {
+ return SPM_ERR_INVALID_CONFIG;
+ }
+ }
/* RW, ZI and stack as one region*/
region_cfg.region_nr = PARTITION_REGION_RW_STACK;
@@ -308,7 +350,9 @@
region_cfg.attr_sh = MPU_ARMV8M_SH_NONE;
region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_NEVER;
- mpu_armv8m_region_enable(&dev_mpu_s, ®ion_cfg);
+ if (mpu_armv8m_region_enable(&dev_mpu_s, ®ion_cfg) != MPU_ARMV8M_OK) {
+ return SPM_ERR_INVALID_CONFIG;
+ }
if (part->static_data.periph_start) {
/* Peripheral */
@@ -318,7 +362,10 @@
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;
- mpu_armv8m_region_enable(&dev_mpu_s, ®ion_cfg);
+ if (mpu_armv8m_region_enable(&dev_mpu_s, ®ion_cfg)
+ != MPU_ARMV8M_OK) {
+ return SPM_ERR_INVALID_CONFIG;
+ }
ppc_en_secure_unpriv(part->static_data.periph_ppc_bank,
part->static_data.periph_ppc_loc);
@@ -326,21 +373,6 @@
mpu_armv8m_enable(&dev_mpu_s, 1, 1);
-#ifndef UNPRIV_JUMP_TO_NS
- /* FixMe: if jump_to_ns_code() from unprivileged is solved,
- * this code can be removed
- */
- /* Initialization is done, set thread mode to unprivileged.
- */
- CONTROL_Type ctrl;
-
- ctrl.w = __get_CONTROL();
- ctrl.b.nPRIV = 1;
- __set_CONTROL(ctrl.w);
- __DSB();
- __ISB();
-#endif
-
return SPM_ERR_OK;
}
@@ -350,19 +382,6 @@
* SPM partition for that partition
*/
-#ifndef UNPRIV_JUMP_TO_NS
- /* FixMe: if jump_to_ns_code() from unprivileged is solved,
- * this code can be removed
- */
- CONTROL_Type ctrl;
-
- ctrl.w = __get_CONTROL();
- ctrl.b.nPRIV = 0;
- __set_CONTROL(ctrl.w);
- __DSB();
- __ISB();
-#endif
-
struct spm_partition_desc_t *part;
part = &g_spm_partition_db.partitions[partition_idx];
@@ -428,8 +447,8 @@
}
}
-void tfm_spm_partition_set_caller_partition_id(uint32_t partition_idx,
- uint32_t caller_partition_idx)
+void tfm_spm_partition_set_caller_partition_idx(uint32_t partition_idx,
+ uint32_t caller_partition_idx)
{
g_spm_partition_db.partitions[partition_idx].runtime_data.
caller_partition_idx = caller_partition_idx;