diff --git a/services/spd/tspd/tspd_common.c b/services/spd/tspd/tspd_common.c index a4c393630c80400b88c1547465086f9483eae1e1..9168ffc1b4c93aff2447d3409fba598db7491ea2 100644 --- a/services/spd/tspd/tspd_common.c +++ b/services/spd/tspd/tspd_common.c @@ -85,7 +85,14 @@ int32_t tspd_init_secure_context(uint64_t entrypoint, write_ctx_reg(el1_state, CTX_SCTLR_EL1, sctlr); /* Set this context as ready to be initialised i.e OFF */ - tsp_ctx->state = TSP_STATE_OFF; + set_tsp_pstate(tsp_ctx->state, TSP_PSTATE_OFF); + + /* + * This context has not been used yet. It will become valid + * when the TSP is interrupted and wants the TSPD to preserve + * the context. + */ + clr_std_smc_active_flag(tsp_ctx->state); /* Associate this context with the cpu specified */ tsp_ctx->mpidr = mpidr; diff --git a/services/spd/tspd/tspd_main.c b/services/spd/tspd/tspd_main.c index 9fda3074b67f267146307c85ea59844ae83a747c..6200d571d8d271c0a683b88e10b878b20d694985 100644 --- a/services/spd/tspd/tspd_main.c +++ b/services/spd/tspd/tspd_main.c @@ -155,7 +155,7 @@ int32_t tspd_init(meminfo_t *bl32_meminfo) rc = tspd_synchronous_sp_entry(tsp_ctx); assert(rc != 0); if (rc) { - tsp_ctx->state = TSP_STATE_ON; + set_tsp_pstate(tsp_ctx->state, TSP_PSTATE_ON); /* * TSP has been successfully initialized. Register power diff --git a/services/spd/tspd/tspd_pm.c b/services/spd/tspd/tspd_pm.c index 2447d9e837c44010bca69e58775742d4a31d994f..75b4b30081247f5ddb8cd87c36236715d008da1b 100644 --- a/services/spd/tspd/tspd_pm.c +++ b/services/spd/tspd/tspd_pm.c @@ -56,7 +56,7 @@ static int32_t tspd_cpu_off_handler(uint64_t cookie) tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id]; assert(tsp_entry_info); - assert(tsp_ctx->state == TSP_STATE_ON); + assert(get_tsp_pstate(tsp_ctx->state) == TSP_PSTATE_ON); /* Program the entry point and enter the TSP */ cm_set_el3_elr(SECURE, (uint64_t) tsp_entry_info->cpu_off_entry); @@ -73,7 +73,7 @@ static int32_t tspd_cpu_off_handler(uint64_t cookie) * Reset TSP's context for a fresh start when this cpu is turned on * subsequently. */ - tsp_ctx->state = TSP_STATE_OFF; + set_tsp_pstate(tsp_ctx->state, TSP_PSTATE_OFF); return 0; } @@ -90,7 +90,7 @@ static void tspd_cpu_suspend_handler(uint64_t power_state) tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id]; assert(tsp_entry_info); - assert(tsp_ctx->state == TSP_STATE_ON); + assert(get_tsp_pstate(tsp_ctx->state) == TSP_PSTATE_ON); /* Program the entry point, power_state parameter and enter the TSP */ write_ctx_reg(get_gpregs_ctx(&tsp_ctx->cpu_ctx), @@ -107,7 +107,7 @@ static void tspd_cpu_suspend_handler(uint64_t power_state) panic(); /* Update its context to reflect the state the TSP is in */ - tsp_ctx->state = TSP_STATE_SUSPEND; + set_tsp_pstate(tsp_ctx->state, TSP_PSTATE_SUSPEND); } /******************************************************************************* @@ -124,7 +124,7 @@ static void tspd_cpu_on_finish_handler(uint64_t cookie) tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id]; assert(tsp_entry_info); - assert(tsp_ctx->state == TSP_STATE_OFF); + assert(get_tsp_pstate(tsp_ctx->state) == TSP_PSTATE_OFF); /* Initialise this cpu's secure context */ tspd_init_secure_context((uint64_t) tsp_entry_info->cpu_on_entry, @@ -143,7 +143,7 @@ static void tspd_cpu_on_finish_handler(uint64_t cookie) panic(); /* Update its context to reflect the state the SP is in */ - tsp_ctx->state = TSP_STATE_ON; + set_tsp_pstate(tsp_ctx->state, TSP_PSTATE_ON); } /******************************************************************************* @@ -159,7 +159,7 @@ static void tspd_cpu_suspend_finish_handler(uint64_t suspend_level) tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id]; assert(tsp_entry_info); - assert(tsp_ctx->state == TSP_STATE_SUSPEND); + assert(get_tsp_pstate(tsp_ctx->state) == TSP_PSTATE_SUSPEND); /* Program the entry point, suspend_level and enter the SP */ write_ctx_reg(get_gpregs_ctx(&tsp_ctx->cpu_ctx), @@ -176,7 +176,7 @@ static void tspd_cpu_suspend_finish_handler(uint64_t suspend_level) panic(); /* Update its context to reflect the state the SP is in */ - tsp_ctx->state = TSP_STATE_ON; + set_tsp_pstate(tsp_ctx->state, TSP_PSTATE_ON); } /******************************************************************************* diff --git a/services/spd/tspd/tspd_private.h b/services/spd/tspd/tspd_private.h index 81484e1cf3e88d6507c7f4fa416fcf23ec2b313d..bb0afcd960901a316fc7db5f8f8d3fd97c19efad 100644 --- a/services/spd/tspd/tspd_private.h +++ b/services/spd/tspd/tspd_private.h @@ -38,10 +38,41 @@ /******************************************************************************* * Secure Payload PM state information e.g. SP is suspended, uninitialised etc + * and macros to access the state information in the per-cpu 'state' flags ******************************************************************************/ -#define TSP_STATE_OFF 0 -#define TSP_STATE_ON 1 -#define TSP_STATE_SUSPEND 2 +#define TSP_PSTATE_OFF 0 +#define TSP_PSTATE_ON 1 +#define TSP_PSTATE_SUSPEND 2 +#define TSP_PSTATE_SHIFT 0 +#define TSP_PSTATE_MASK 0x3 +#define get_tsp_pstate(state) ((state >> TSP_PSTATE_SHIFT) & TSP_PSTATE_MASK) +#define clr_tsp_pstate(state) (state &= ~(TSP_PSTATE_MASK \ + << TSP_PSTATE_SHIFT)) +#define set_tsp_pstate(st, pst) do { \ + clr_tsp_pstate(st); \ + st |= (pst & TSP_PSTATE_MASK) << \ + TSP_PSTATE_SHIFT; \ + } while (0); + + +/* + * This flag is used by the TSPD to determine if the TSP is servicing a standard + * SMC request prior to programming the next entry into the TSP e.g. if TSP + * execution is preempted by a non-secure interrupt and handed control to the + * normal world. If another request which is distinct from what the TSP was + * previously doing arrives, then this flag will be help the TSPD to either + * reject the new request or service it while ensuring that the previous context + * is not corrupted. + */ +#define STD_SMC_ACTIVE_FLAG_SHIFT 2 +#define STD_SMC_ACTIVE_FLAG_MASK 1 +#define get_std_smc_active_flag(state) ((state >> STD_SMC_ACTIVE_FLAG_SHIFT) \ + & STD_SMC_ACTIVE_FLAG_MASK) +#define set_std_smc_active_flag(state) (state |= \ + 1 << STD_SMC_ACTIVE_FLAG_SHIFT) +#define clr_std_smc_active_flag(state) (state &= \ + ~(STD_SMC_ACTIVE_FLAG_MASK \ + << STD_SMC_ACTIVE_FLAG_SHIFT)) /******************************************************************************* * Secure Payload execution state information i.e. aarch32 or aarch64