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;
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
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);
* 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;
}
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),
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);
}
/*******************************************************************************
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,
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);
}
/*******************************************************************************
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),
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);
}
/*******************************************************************************
/*******************************************************************************
* 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