Rework the TSPD setup code
There is no mechanism which allows the TSPD to specify what SPSR to use when entering BL3-2 instead of BL3-3. This patch divides the responsibility between tspd_setup() and tspd_init() for initializing the TSPD and TSP to support the alternate BL3-2 initialization flow where BL3-1 handsover control to BL3-2 instead of BL3-3. SPSR generated by TSPD for TSP is preserved due the new division of labour which fixes #174. This patch also moves the cpu_context initialization code from tspd_setup() to tspd_init() immediately before entering the TSP. Instead tspd_setup() updates the BL3-2 entrypoint info structure with the state required for initializing the TSP later. Fixes ARM-software/TF-issues#174 Change-Id: Ida0a8a48d466c71d5b07b8c7f2af169b73f96940
This commit is contained in:
parent
dd2bdee616
commit
50e27dadbc
|
@ -73,7 +73,8 @@ extern unsigned long __COHERENT_RAM_END__;
|
|||
|
||||
|
||||
#if RESET_TO_BL31
|
||||
static entry_point_info_t next_image_ep_info;
|
||||
static entry_point_info_t bl32_image_ep_info;
|
||||
static entry_point_info_t bl33_image_ep_info;
|
||||
#else
|
||||
/*******************************************************************************
|
||||
* Reference to structure which holds the arguments that have been passed to
|
||||
|
@ -91,28 +92,12 @@ static bl31_params_t *bl2_to_bl31_params;
|
|||
entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
|
||||
{
|
||||
#if RESET_TO_BL31
|
||||
|
||||
assert(sec_state_is_valid(type));
|
||||
SET_PARAM_HEAD(&next_image_ep_info,
|
||||
PARAM_EP,
|
||||
VERSION_1,
|
||||
0);
|
||||
|
||||
SET_SECURITY_STATE(next_image_ep_info.h.attr, type);
|
||||
|
||||
if (type == NON_SECURE) {
|
||||
/*
|
||||
* Tell BL31 where the non-trusted software image
|
||||
* is located and the entry state information
|
||||
*/
|
||||
next_image_ep_info.pc = plat_get_ns_image_entrypoint();
|
||||
next_image_ep_info.spsr = fvp_get_spsr_for_bl33_entry();
|
||||
} else {
|
||||
next_image_ep_info.pc = BL32_BASE;
|
||||
next_image_ep_info.spsr = fvp_get_spsr_for_bl32_entry();
|
||||
}
|
||||
|
||||
return &next_image_ep_info;
|
||||
if (type == NON_SECURE)
|
||||
return &bl33_image_ep_info;
|
||||
else
|
||||
return &bl32_image_ep_info;
|
||||
#else
|
||||
entry_point_info_t *next_image_info;
|
||||
|
||||
|
@ -155,7 +140,6 @@ void bl31_early_platform_setup(bl31_params_t *from_bl2,
|
|||
assert(from_bl2 == NULL);
|
||||
assert(plat_params_from_bl2 == NULL);
|
||||
|
||||
|
||||
/*
|
||||
* Do initial security configuration to allow DRAM/device access. On
|
||||
* Base FVP only DRAM security is programmable (via TrustZone), but
|
||||
|
@ -163,6 +147,28 @@ void bl31_early_platform_setup(bl31_params_t *from_bl2,
|
|||
* present.
|
||||
*/
|
||||
fvp_security_setup();
|
||||
|
||||
/* Populate entry point information for BL3-2 and BL3-3 */
|
||||
SET_PARAM_HEAD(&bl32_image_ep_info,
|
||||
PARAM_EP,
|
||||
VERSION_1,
|
||||
0);
|
||||
SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE);
|
||||
bl32_image_ep_info.pc = BL32_BASE;
|
||||
bl32_image_ep_info.spsr = fvp_get_spsr_for_bl32_entry();
|
||||
|
||||
SET_PARAM_HEAD(&bl33_image_ep_info,
|
||||
PARAM_EP,
|
||||
VERSION_1,
|
||||
0);
|
||||
/*
|
||||
* Tell BL31 where the non-trusted software image
|
||||
* is located and the entry state information
|
||||
*/
|
||||
bl33_image_ep_info.pc = plat_get_ns_image_entrypoint();
|
||||
bl33_image_ep_info.spsr = fvp_get_spsr_for_bl33_entry();
|
||||
SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
|
||||
|
||||
#else
|
||||
/* Check params passed from BL2 should not be NULL,
|
||||
* We are not checking plat_params_from_bl2 as NULL as we are not
|
||||
|
|
|
@ -36,20 +36,21 @@
|
|||
#include "tspd_private.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* Given a secure payload entrypoint, register width, cpu id & pointer to a
|
||||
* context data structure, this function will create a secure context ready for
|
||||
* programming an entry into the secure payload.
|
||||
* Given a secure payload entrypoint info pointer, entry point PC, register
|
||||
* width, cpu id & pointer to a context data structure, this function will
|
||||
* initialize tsp context and entry point info for the secure payload
|
||||
******************************************************************************/
|
||||
int32_t tspd_init_secure_context(uint64_t entrypoint,
|
||||
uint32_t rw,
|
||||
uint64_t mpidr,
|
||||
tsp_context_t *tsp_ctx)
|
||||
void tspd_init_tsp_ep_state(struct entry_point_info *tsp_entry_point,
|
||||
uint32_t rw,
|
||||
uint64_t pc,
|
||||
tsp_context_t *tsp_ctx)
|
||||
{
|
||||
entry_point_info_t ep;
|
||||
uint32_t ep_attr;
|
||||
|
||||
/* Passing a NULL context is a critical programming error */
|
||||
assert(tsp_ctx);
|
||||
assert(tsp_entry_point);
|
||||
assert(pc);
|
||||
|
||||
/*
|
||||
* We support AArch64 TSP for now.
|
||||
|
@ -58,25 +59,24 @@ int32_t tspd_init_secure_context(uint64_t entrypoint,
|
|||
assert(rw == TSP_AARCH64);
|
||||
|
||||
/* Associate this context with the cpu specified */
|
||||
tsp_ctx->mpidr = mpidr;
|
||||
tsp_ctx->mpidr = read_mpidr_el1();
|
||||
tsp_ctx->state = 0;
|
||||
set_tsp_pstate(tsp_ctx->state, TSP_PSTATE_OFF);
|
||||
clr_std_smc_active_flag(tsp_ctx->state);
|
||||
|
||||
cm_set_context_by_mpidr(mpidr, &tsp_ctx->cpu_ctx, SECURE);
|
||||
cm_set_context(&tsp_ctx->cpu_ctx, SECURE);
|
||||
|
||||
/* initialise an entrypoint to set up the CPU context */
|
||||
ep_attr = SECURE | EP_ST_ENABLE;
|
||||
if (read_sctlr_el3() & SCTLR_EE_BIT)
|
||||
ep_attr |= EP_EE_BIG;
|
||||
SET_PARAM_HEAD(&ep, PARAM_EP, VERSION_1, ep_attr);
|
||||
ep.pc = entrypoint;
|
||||
ep.spsr = SPSR_64(MODE_EL1, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
|
||||
memset(&ep.args, 0, sizeof(ep.args));
|
||||
SET_PARAM_HEAD(tsp_entry_point, PARAM_EP, VERSION_1, ep_attr);
|
||||
|
||||
cm_init_context(mpidr, &ep);
|
||||
|
||||
return 0;
|
||||
tsp_entry_point->pc = pc;
|
||||
tsp_entry_point->spsr = SPSR_64(MODE_EL1,
|
||||
MODE_SP_ELX,
|
||||
DISABLE_ALL_EXCEPTIONS);
|
||||
memset(&tsp_entry_point->args, 0, sizeof(tsp_entry_point->args));
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
|
|
@ -144,8 +144,7 @@ static uint64_t tspd_sel1_interrupt_handler(uint32_t id,
|
|||
******************************************************************************/
|
||||
int32_t tspd_setup(void)
|
||||
{
|
||||
entry_point_info_t *image_info;
|
||||
int32_t rc;
|
||||
entry_point_info_t *tsp_ep_info;
|
||||
uint64_t mpidr = read_mpidr();
|
||||
uint32_t linear_id;
|
||||
|
||||
|
@ -156,15 +155,20 @@ int32_t tspd_setup(void)
|
|||
* absence is a critical failure. TODO: Add support to
|
||||
* conditionally include the SPD service
|
||||
*/
|
||||
image_info = bl31_plat_get_next_image_ep_info(SECURE);
|
||||
assert(image_info);
|
||||
tsp_ep_info = bl31_plat_get_next_image_ep_info(SECURE);
|
||||
if (!tsp_ep_info) {
|
||||
WARN("No TSP provided by BL2 boot loader, Booting device"
|
||||
" without TSP initialization. SMC`s destined for TSP"
|
||||
" will return SMC_UNK\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* If there's no valid entry point for SP, we return a non-zero value
|
||||
* signalling failure initializing the service. We bail out without
|
||||
* registering any handlers
|
||||
*/
|
||||
if (!image_info->pc)
|
||||
if (!tsp_ep_info->pc)
|
||||
return 1;
|
||||
|
||||
/*
|
||||
|
@ -172,11 +176,10 @@ int32_t tspd_setup(void)
|
|||
* state i.e whether AArch32 or AArch64. Assuming it's AArch64
|
||||
* for the time being.
|
||||
*/
|
||||
rc = tspd_init_secure_context(image_info->pc,
|
||||
TSP_AARCH64,
|
||||
mpidr,
|
||||
&tspd_sp_context[linear_id]);
|
||||
assert(rc == 0);
|
||||
tspd_init_tsp_ep_state(tsp_ep_info,
|
||||
TSP_AARCH64,
|
||||
tsp_ep_info->pc,
|
||||
&tspd_sp_context[linear_id]);
|
||||
|
||||
/*
|
||||
* All TSPD initialization done. Now register our init function with
|
||||
|
@ -184,7 +187,7 @@ int32_t tspd_setup(void)
|
|||
*/
|
||||
bl31_register_bl32_init(&tspd_init);
|
||||
|
||||
return rc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
@ -202,6 +205,16 @@ int32_t tspd_init(void)
|
|||
uint32_t linear_id = platform_get_core_pos(mpidr), flags;
|
||||
uint64_t rc;
|
||||
tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id];
|
||||
entry_point_info_t *tsp_entry_point;
|
||||
|
||||
/*
|
||||
* Get information about the Secure Payload (BL32) image. Its
|
||||
* absence is a critical failure.
|
||||
*/
|
||||
tsp_entry_point = bl31_plat_get_next_image_ep_info(SECURE);
|
||||
assert(tsp_entry_point);
|
||||
|
||||
cm_init_context(mpidr, tsp_entry_point);
|
||||
|
||||
/*
|
||||
* Arrange for an entry into the test secure payload. We expect an array
|
||||
|
|
|
@ -123,16 +123,19 @@ static void tspd_cpu_on_finish_handler(uint64_t cookie)
|
|||
uint64_t mpidr = read_mpidr();
|
||||
uint32_t linear_id = platform_get_core_pos(mpidr);
|
||||
tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id];
|
||||
entry_point_info_t tsp_on_entrypoint;
|
||||
|
||||
assert(tsp_vectors);
|
||||
assert(get_tsp_pstate(tsp_ctx->state) == TSP_PSTATE_OFF);
|
||||
|
||||
/* Initialise this cpu's secure context */
|
||||
tspd_init_secure_context((uint64_t) &tsp_vectors->cpu_on_entry,
|
||||
tspd_init_tsp_ep_state(&tsp_on_entrypoint,
|
||||
TSP_AARCH64,
|
||||
mpidr,
|
||||
(uint64_t) &tsp_vectors->cpu_on_entry,
|
||||
tsp_ctx);
|
||||
|
||||
/* Initialise this cpu's secure context */
|
||||
cm_init_context(mpidr, &tsp_on_entrypoint);
|
||||
|
||||
/* Enter the TSP */
|
||||
rc = tspd_synchronous_sp_entry(tsp_ctx);
|
||||
|
||||
|
|
|
@ -192,10 +192,11 @@ uint64_t tspd_enter_sp(uint64_t *c_rt_ctx);
|
|||
void __dead2 tspd_exit_sp(uint64_t c_rt_ctx, uint64_t ret);
|
||||
uint64_t tspd_synchronous_sp_entry(tsp_context_t *tsp_ctx);
|
||||
void __dead2 tspd_synchronous_sp_exit(tsp_context_t *tsp_ctx, uint64_t ret);
|
||||
int32_t tspd_init_secure_context(uint64_t entrypoint,
|
||||
uint32_t rw,
|
||||
uint64_t mpidr,
|
||||
tsp_context_t *tsp_ctx);
|
||||
void tspd_init_tsp_ep_state(struct entry_point_info *tsp_ep,
|
||||
uint32_t rw,
|
||||
uint64_t pc,
|
||||
tsp_context_t *tsp_ctx);
|
||||
|
||||
extern tsp_context_t tspd_sp_context[TSPD_CORE_COUNT];
|
||||
extern struct tsp_vectors *tsp_vectors;
|
||||
#endif /*__ASSEMBLY__*/
|
||||
|
|
Loading…
Reference in New Issue