diff --git a/services/spd/tspd/tspd_common.c b/services/spd/tspd/tspd_common.c index a4c3936..9168ffc 100644 --- a/services/spd/tspd/tspd_common.c +++ b/services/spd/tspd/tspd_common.c @@ -85,7 +85,14 @@ 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 9fda307..6200d57 100644 --- a/services/spd/tspd/tspd_main.c +++ b/services/spd/tspd/tspd_main.c @@ -155,7 +155,7 @@ 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 2447d9e..75b4b30 100644 --- a/services/spd/tspd/tspd_pm.c +++ b/services/spd/tspd/tspd_pm.c @@ -56,7 +56,7 @@ 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 @@ * 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 81484e1..bb0afcd 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