Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
adam.huang
Arm Trusted Firmware
Commits
d9ec0c14
Commit
d9ec0c14
authored
Aug 01, 2014
by
danh-arm
Browse files
Merge pull request #175 from vikramkanigiri/vk/spd-init-by-stack-unwinding
Vk/spd init by stack unwinding
parents
dd2bdee6
faaa2e76
Changes
9
Hide whitespace changes
Inline
Side-by-side
bl31/bl31_main.c
View file @
d9ec0c14
...
...
@@ -51,7 +51,7 @@ static int32_t (*bl32_init)(void);
* Variable to indicate whether next image to execute after BL31 is BL33
* (non-secure & default) or BL32 (secure).
******************************************************************************/
static
uint32_t
next_image_type
;
static
uint32_t
next_image_type
=
NON_SECURE
;
/*******************************************************************************
* Simple function to initialise all BL31 helper libraries.
...
...
@@ -89,9 +89,6 @@ void bl31_main(void)
/* Clean caches before re-entering normal world */
dcsw_op_all
(
DCCSW
);
/* By default run the non-secure BL3-3 image next */
next_image_type
=
NON_SECURE
;
/*
* All the cold boot actions on the primary cpu are done. We now need to
* decide which is the next image (BL32 or BL33) and how to execute it.
...
...
bl32/tsp/tsp.mk
View file @
d9ec0c14
...
...
@@ -39,6 +39,14 @@ BL32_SOURCES += bl32/tsp/tsp_main.c \
BL32_LINKERFILE
:=
bl32/tsp/tsp.ld.S
# This flag determines if the TSPD initializes BL3-2 in tspd_init() (synchronous
# method) or configures BL3-1 to pass control to BL3-2 instead of BL3-3
# (asynchronous method).
TSP_INIT_ASYNC
:=
0
$(eval
$(call
assert_boolean,TSP_INIT_ASYNC))
$(eval
$(call
add_define,TSP_INIT_ASYNC))
# Include the platform-specific TSP Makefile
# If no platform-specific TSP Makefile exists, it means TSP is not supported
# on this platform.
...
...
docs/firmware-design.md
View file @
d9ec0c14
...
...
@@ -811,10 +811,10 @@ and is registered using the `bl31_register_bl32_init()` function.
Trusted Firmware supports two approaches for the SPD to pass control to BL3-2
before returning through EL3 and running the non-trusted firmware (BL3-3):
1.
In the BL3-2
initialization
function, se
t up a secure context (see below
for more details of CPU cont
ext
support) for this CPU and use
`bl31_set_next_image_type()`
to request that the exit from
`bl31_main()`
is
to the BL3-2 entrypoint in Secure-EL1
.
1.
In the BL3-2
setup
function,
u
se
`bl31_set_next_image_type()`
to
request that the
ex
i
t
from
`bl31_main()`
is to the BL3-2 entrypoint in
Secure-EL1. BL3-1 will exit to BL3-2 using the asynchronous method by
calling bl31_prepare_next_image_entry() and el3_exit()
.
When the BL3-2 has completed initialization at Secure-EL1, it returns to
BL3-1 by issuing an SMC, using a Function ID allocated to the SPD. On
...
...
@@ -824,7 +824,8 @@ before returning through EL3 and running the non-trusted firmware (BL3-3):
the normal world firmware BL3-3. On return from the handler the framework
will exit to EL2 and run BL3-3.
2.
In the BL3-2 initialization function, use an SPD-defined mechanism to
2.
The BL3-2 setup function registers a initialization function using
`bl31_register_bl32_init()`
which provides a SPD-defined mechanism to
invoke a 'world-switch synchronous call' to Secure-EL1 to run the BL3-2
entrypoint.
NOTE: The Test SPD service included with the Trusted Firmware provides one
...
...
docs/user-guide.md
View file @
d9ec0c14
...
...
@@ -186,6 +186,13 @@ performed.
value of
`DEBUG`
- i.e. by default this is only enabled for a debug
build of the firmware.
*
`TSP_INIT_ASYNC`
: Choose BL3-2 initialization method as asynchronous or
synchronous, e.g. "(see "Initializing a BL3-2 Image" section in [Firmware
Design])". It can take the value 0 (BL3-2 is initialized using
synchronous method) or 1 (BL3-2 is initialized using asynchronous method).
Default is 0.
### Creating a Firmware Image Package
FIPs are automatically created as part of the build instructions described in
...
...
plat/fvp/bl31_fvp_setup.c
View file @
d9ec0c14
...
...
@@ -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
...
...
services/spd/tspd/tspd_common.c
View file @
d9ec0c14
...
...
@@ -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 int
o
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
an
d
entry
po
int
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
));
}
/*******************************************************************************
...
...
services/spd/tspd/tspd_main.c
View file @
d9ec0c14
...
...
@@ -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,19 +176,21 @@ 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
]);
#if TSP_INIT_ASYNC
bl31_set_next_image_type
(
SECURE
);
#else
/*
* All TSPD initialization done. Now register our init function with
* BL31 for deferred invocation
*/
bl31_register_bl32_init
(
&
tspd_init
);
return
rc
;
#endif
return
0
;
}
/*******************************************************************************
...
...
@@ -199,37 +205,26 @@ int32_t tspd_setup(void)
int32_t
tspd_init
(
void
)
{
uint64_t
mpidr
=
read_mpidr
();
uint32_t
linear_id
=
platform_get_core_pos
(
mpidr
),
flags
;
uint64_t
rc
;
uint32_t
linear_id
=
platform_get_core_pos
(
mpidr
);
tsp_context_t
*
tsp_ctx
=
&
tspd_sp_context
[
linear_id
];
entry_point_info_t
*
tsp_entry_point
;
uint64_t
rc
;
/*
*
Arrange for an entry into the test s
ecure
p
ayload
. We expect an array
*
of vectors in return
*
Get information about the S
ecure
P
ayload
(BL32) image. Its
*
absence is a critical failure.
*/
rc
=
tspd_synchronous_sp_entry
(
tsp_ctx
);
assert
(
rc
!=
0
);
if
(
rc
)
{
set_tsp_pstate
(
tsp_ctx
->
state
,
TSP_PSTATE_ON
);
tsp_entry_point
=
bl31_plat_get_next_image_ep_info
(
SECURE
);
assert
(
tsp_entry_point
);
/*
* TSP has been successfully initialized. Register power
* managemnt hooks with PSCI
*/
psci_register_spd_pm_hook
(
&
tspd_pm
);
}
cm_init_context
(
mpidr
,
tsp_entry_point
);
/*
*
Register an interrupt handler for S-EL1 interrupts when generated
*
during code executing in the non-secure state.
*
Arrange for an entry into the test secure payload. It will be
*
returned via TSP_ENTRY_DONE case
*/
flags
=
0
;
set_interrupt_rm_flag
(
flags
,
NON_SECURE
);
rc
=
register_interrupt_type_handler
(
INTR_TYPE_S_EL1
,
tspd_sel1_interrupt_handler
,
flags
);
if
(
rc
)
panic
();
rc
=
tspd_synchronous_sp_entry
(
tsp_ctx
);
assert
(
rc
!=
0
);
return
rc
;
}
...
...
@@ -256,6 +251,10 @@ uint64_t tspd_smc_handler(uint32_t smc_fid,
unsigned
long
mpidr
=
read_mpidr
();
uint32_t
linear_id
=
platform_get_core_pos
(
mpidr
),
ns
;
tsp_context_t
*
tsp_ctx
=
&
tspd_sp_context
[
linear_id
];
uint64_t
rc
;
#if TSP_INIT_ASYNC
entry_point_info_t
*
next_image_info
;
#endif
/* Determine which security state this SMC originated from */
ns
=
is_caller_non_secure
(
flags
);
...
...
@@ -369,6 +368,45 @@ uint64_t tspd_smc_handler(uint32_t smc_fid,
assert
(
tsp_vectors
==
NULL
);
tsp_vectors
=
(
tsp_vectors_t
*
)
x1
;
if
(
tsp_vectors
)
{
set_tsp_pstate
(
tsp_ctx
->
state
,
TSP_PSTATE_ON
);
/*
* TSP has been successfully initialized. Register power
* managemnt hooks with PSCI
*/
psci_register_spd_pm_hook
(
&
tspd_pm
);
/*
* Register an interrupt handler for S-EL1 interrupts
* when generated during code executing in the
* non-secure state.
*/
flags
=
0
;
set_interrupt_rm_flag
(
flags
,
NON_SECURE
);
rc
=
register_interrupt_type_handler
(
INTR_TYPE_S_EL1
,
tspd_sel1_interrupt_handler
,
flags
);
if
(
rc
)
panic
();
}
#if TSP_INIT_ASYNC
/* Save the Secure EL1 system register context */
assert
(
cm_get_context
(
SECURE
)
==
&
tsp_ctx
->
cpu_ctx
);
cm_el1_sysregs_context_save
(
SECURE
);
/* Program EL3 registers to enable entry into the next EL */
next_image_info
=
bl31_plat_get_next_image_ep_info
(
NON_SECURE
);
assert
(
next_image_info
);
assert
(
NON_SECURE
==
GET_SECURITY_STATE
(
next_image_info
->
h
.
attr
));
cm_init_context
(
read_mpidr_el1
(),
next_image_info
);
cm_prepare_el3_exit
(
NON_SECURE
);
SMC_RET0
(
cm_get_context
(
NON_SECURE
));
#else
/*
* SP reports completion. The SPD must have initiated
* the original request through a synchronous entry
...
...
@@ -376,6 +414,7 @@ uint64_t tspd_smc_handler(uint32_t smc_fid,
* context.
*/
tspd_synchronous_sp_exit
(
tsp_ctx
,
x1
);
#endif
/*
* These function IDs is used only by the SP to indicate it has
...
...
services/spd/tspd/tspd_pm.c
View file @
d9ec0c14
...
...
@@ -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
);
...
...
services/spd/tspd/tspd_private.h
View file @
d9ec0c14
...
...
@@ -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__*/
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment