Commit 50e27dad authored by Vikram Kanigiri's avatar Vikram Kanigiri
Browse files

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
parent dd2bdee6
......@@ -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__*/
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment