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
4ca473db
Commit
4ca473db
authored
Dec 09, 2015
by
danh-arm
Browse files
Merge pull request #456 from soby-mathew/sm/gicv3-tsp-plat-changes-v2
Modify TSP and ARM standard platforms for new GIC drivers v2
parents
8d297cc9
63b8440f
Changes
44
Hide whitespace changes
Inline
Side-by-side
services/spd/tspd/tspd.mk
View file @
4ca473db
...
@@ -55,7 +55,17 @@ NEED_BL32 := yes
...
@@ -55,7 +55,17 @@ NEED_BL32 := yes
# Flag used to enable routing of non-secure interrupts to EL3 when they are
# Flag used to enable routing of non-secure interrupts to EL3 when they are
# generated while the code is executing in S-EL1/0.
# generated while the code is executing in S-EL1/0.
TSP
D_ROUTE_IRQ_TO_EL3
:=
0
TSP
_NS_INTR_ASYNC_PREEMPT
:=
0
$(eval
$(call
assert_boolean,TSPD_ROUTE_IRQ_TO_EL3))
# If TSPD_ROUTE_IRQ_TO_EL3 build flag is defined, use it to define value for
$(eval
$(call
add_define,TSPD_ROUTE_IRQ_TO_EL3))
# TSP_NS_INTR_ASYNC_PREEMPT for backward compatibility.
ifdef
TSPD_ROUTE_IRQ_TO_EL3
ifeq
(${ERROR_DEPRECATED},1)
$(error
"TSPD_ROUTE_IRQ_TO_EL3 is deprecated. Please use the new build flag TSP_NS_INTR_ASYNC_PREEMPT"
)
endif
$(warning
"TSPD_ROUTE_IRQ_TO_EL3 is deprecated. Please use the new build flag TSP_NS_INTR_ASYNC_PREEMPT"
)
TSP_NS_INTR_ASYNC_PREEMPT
:=
${TSPD_ROUTE_IRQ_TO_EL3}
endif
$(eval
$(call
assert_boolean,TSP_NS_INTR_ASYNC_PREEMPT))
$(eval
$(call
add_define,TSP_NS_INTR_ASYNC_PREEMPT))
services/spd/tspd/tspd_main.c
View file @
4ca473db
...
@@ -72,9 +72,16 @@ DEFINE_SVC_UUID(tsp_uuid,
...
@@ -72,9 +72,16 @@ DEFINE_SVC_UUID(tsp_uuid,
int32_t
tspd_init
(
void
);
int32_t
tspd_init
(
void
);
/*
* This helper function handles Secure EL1 preemption. The preemption could be
* due Non Secure interrupts or EL3 interrupts. In both the cases we context
* switch to the normal world and in case of EL3 interrupts, it will again be
* routed to EL3 which will get handled at the exception vectors.
*/
uint64_t
tspd_handle_sp_preemption
(
void
*
handle
)
uint64_t
tspd_handle_sp_preemption
(
void
*
handle
)
{
{
cpu_context_t
*
ns_cpu_context
;
cpu_context_t
*
ns_cpu_context
;
assert
(
handle
==
cm_get_context
(
SECURE
));
assert
(
handle
==
cm_get_context
(
SECURE
));
cm_el1_sysregs_context_save
(
SECURE
);
cm_el1_sysregs_context_save
(
SECURE
);
/* Get a reference to the non-secure context */
/* Get a reference to the non-secure context */
...
@@ -82,18 +89,30 @@ uint64_t tspd_handle_sp_preemption(void *handle)
...
@@ -82,18 +89,30 @@ uint64_t tspd_handle_sp_preemption(void *handle)
assert
(
ns_cpu_context
);
assert
(
ns_cpu_context
);
/*
/*
* Restore non-secure state. The secure system
* To allow Secure EL1 interrupt handler to re-enter TSP while TSP
* register context will be saved when required.
* is preempted, the secure system register context which will get
* overwritten must be additionally saved. This is currently done
* by the TSPD S-EL1 interrupt handler.
*/
/*
* Restore non-secure state.
*/
*/
cm_el1_sysregs_context_restore
(
NON_SECURE
);
cm_el1_sysregs_context_restore
(
NON_SECURE
);
cm_set_next_eret_context
(
NON_SECURE
);
cm_set_next_eret_context
(
NON_SECURE
);
/*
* The TSP was preempted during STD SMC execution.
* Return back to the normal world with SMC_PREEMPTED as error
* code in x0.
*/
SMC_RET1
(
ns_cpu_context
,
SMC_PREEMPTED
);
SMC_RET1
(
ns_cpu_context
,
SMC_PREEMPTED
);
}
}
/*******************************************************************************
/*******************************************************************************
* This function is the handler registered for S-EL1 interrupts by the TSPD. It
* This function is the handler registered for S-EL1 interrupts by the TSPD. It
* validates the interrupt and upon success arranges entry into the TSP at
* validates the interrupt and upon success arranges entry into the TSP at
* 'tsp_
fiq
_entry()' for handling the interrupt.
* 'tsp_
sel1_intr
_entry()' for handling the interrupt.
******************************************************************************/
******************************************************************************/
static
uint64_t
tspd_sel1_interrupt_handler
(
uint32_t
id
,
static
uint64_t
tspd_sel1_interrupt_handler
(
uint32_t
id
,
uint32_t
flags
,
uint32_t
flags
,
...
@@ -121,44 +140,44 @@ static uint64_t tspd_sel1_interrupt_handler(uint32_t id,
...
@@ -121,44 +140,44 @@ static uint64_t tspd_sel1_interrupt_handler(uint32_t id,
* Determine if the TSP was previously preempted. Its last known
* Determine if the TSP was previously preempted. Its last known
* context has to be preserved in this case.
* context has to be preserved in this case.
* The TSP should return control to the TSPD after handling this
* The TSP should return control to the TSPD after handling this
*
FIQ
. Preserve essential EL3 context to allow entry into
the
*
S-EL1 interrupt
. Preserve essential EL3 context to allow entry into
* TSP at the
FIQ
entry point using the 'cpu_context'
structure.
*
the
TSP at the
S-EL1 interrupt
entry point using the 'cpu_context'
* There is no need to save the secure system register
context
*
structure.
There is no need to save the secure system register
* since the TSP is supposed to preserve it during S-EL1
interrupt
*
context
since the TSP is supposed to preserve it during S-EL1
* handling.
*
interrupt
handling.
*/
*/
if
(
get_std_smc_active_flag
(
tsp_ctx
->
state
))
{
if
(
get_std_smc_active_flag
(
tsp_ctx
->
state
))
{
tsp_ctx
->
saved_spsr_el3
=
SMC_GET_EL3
(
&
tsp_ctx
->
cpu_ctx
,
tsp_ctx
->
saved_spsr_el3
=
SMC_GET_EL3
(
&
tsp_ctx
->
cpu_ctx
,
CTX_SPSR_EL3
);
CTX_SPSR_EL3
);
tsp_ctx
->
saved_elr_el3
=
SMC_GET_EL3
(
&
tsp_ctx
->
cpu_ctx
,
tsp_ctx
->
saved_elr_el3
=
SMC_GET_EL3
(
&
tsp_ctx
->
cpu_ctx
,
CTX_ELR_EL3
);
CTX_ELR_EL3
);
#if TSP
D_ROUTE_IRQ_TO_EL3
#if TSP
_NS_INTR_ASYNC_PREEMPT
/*Need to save the previously interrupted secure context */
/*Need to save the previously interrupted secure context */
memcpy
(
&
tsp_ctx
->
sp_ctx
,
&
tsp_ctx
->
cpu_ctx
,
TSPD_SP_CTX_SIZE
);
memcpy
(
&
tsp_ctx
->
sp_ctx
,
&
tsp_ctx
->
cpu_ctx
,
TSPD_SP_CTX_SIZE
);
#endif
#endif
}
}
cm_el1_sysregs_context_restore
(
SECURE
);
cm_el1_sysregs_context_restore
(
SECURE
);
cm_set_elr_spsr_el3
(
SECURE
,
(
uint64_t
)
&
tsp_vectors
->
fiq
_entry
,
cm_set_elr_spsr_el3
(
SECURE
,
(
uint64_t
)
&
tsp_vectors
->
sel1_intr
_entry
,
SPSR_64
(
MODE_EL1
,
MODE_SP_ELX
,
DISABLE_ALL_EXCEPTIONS
));
SPSR_64
(
MODE_EL1
,
MODE_SP_ELX
,
DISABLE_ALL_EXCEPTIONS
));
cm_set_next_eret_context
(
SECURE
);
cm_set_next_eret_context
(
SECURE
);
/*
/*
* Tell the TSP that it has to handle a
n FIQ
synchronously.
Also the
* Tell the TSP that it has to handle a
S-EL1 interrupt
synchronously.
* instruction in normal world where the interrupt was
generated is
*
Also the
instruction in normal world where the interrupt was
* passed for debugging purposes. It is safe to retrieve
this address
*
generated is
passed for debugging purposes. It is safe to retrieve
* from ELR_EL3 as the secure context will not take effect
until
*
this address
from ELR_EL3 as the secure context will not take effect
* el3_exit().
*
until
el3_exit().
*/
*/
SMC_RET2
(
&
tsp_ctx
->
cpu_ctx
,
TSP_HANDLE_
FIQ
_AND_RETURN
,
read_elr_el3
());
SMC_RET2
(
&
tsp_ctx
->
cpu_ctx
,
TSP_HANDLE_
SEL1_INTR
_AND_RETURN
,
read_elr_el3
());
}
}
#if TSP
D_ROUTE_IRQ_TO_EL3
#if TSP
_NS_INTR_ASYNC_PREEMPT
/*******************************************************************************
/*******************************************************************************
* This function is the handler registered for
S-EL1
interrupts by the
TSPD. It
* This function is the handler registered for
Non secure
interrupts by the
* validates the interrupt and upon success arranges entry into the
TSP at
*
TSPD. It
validates the interrupt and upon success arranges entry into the
*
'tsp_fiq_entry()'
for handling the interrupt.
*
normal world
for handling the interrupt.
******************************************************************************/
******************************************************************************/
static
uint64_t
tspd_ns_interrupt_handler
(
uint32_t
id
,
static
uint64_t
tspd_ns_interrupt_handler
(
uint32_t
id
,
uint32_t
flags
,
uint32_t
flags
,
...
@@ -312,10 +331,11 @@ uint64_t tspd_smc_handler(uint32_t smc_fid,
...
@@ -312,10 +331,11 @@ uint64_t tspd_smc_handler(uint32_t smc_fid,
/*
/*
* This function ID is used only by the TSP to indicate that it has
* This function ID is used only by the TSP to indicate that it has
* finished handling a S-EL1 FIQ interrupt. Execution should resume
* finished handling a S-EL1 interrupt or was preempted by a higher
* priority pending EL3 interrupt. Execution should resume
* in the normal world.
* in the normal world.
*/
*/
case
TSP_HANDLED_S_EL1_
FIQ
:
case
TSP_HANDLED_S_EL1_
INTR
:
if
(
ns
)
if
(
ns
)
SMC_RET1
(
handle
,
SMC_UNK
);
SMC_RET1
(
handle
,
SMC_UNK
);
...
@@ -332,7 +352,7 @@ uint64_t tspd_smc_handler(uint32_t smc_fid,
...
@@ -332,7 +352,7 @@ uint64_t tspd_smc_handler(uint32_t smc_fid,
SMC_SET_EL3
(
&
tsp_ctx
->
cpu_ctx
,
SMC_SET_EL3
(
&
tsp_ctx
->
cpu_ctx
,
CTX_ELR_EL3
,
CTX_ELR_EL3
,
tsp_ctx
->
saved_elr_el3
);
tsp_ctx
->
saved_elr_el3
);
#if TSP
D_ROUTE_IRQ_TO_EL3
#if TSP
_NS_INTR_ASYNC_PREEMPT
/*
/*
* Need to restore the previously interrupted
* Need to restore the previously interrupted
* secure context.
* secure context.
...
@@ -356,35 +376,6 @@ uint64_t tspd_smc_handler(uint32_t smc_fid,
...
@@ -356,35 +376,6 @@ uint64_t tspd_smc_handler(uint32_t smc_fid,
SMC_RET0
((
uint64_t
)
ns_cpu_context
);
SMC_RET0
((
uint64_t
)
ns_cpu_context
);
/*
* This function ID is used only by the TSP to indicate that it was
* interrupted due to a EL3 FIQ interrupt. Execution should resume
* in the normal world.
*/
case
TSP_EL3_FIQ
:
if
(
ns
)
SMC_RET1
(
handle
,
SMC_UNK
);
assert
(
handle
==
cm_get_context
(
SECURE
));
/* Assert that standard SMC execution has been preempted */
assert
(
get_std_smc_active_flag
(
tsp_ctx
->
state
));
/* Save the secure system register state */
cm_el1_sysregs_context_save
(
SECURE
);
/* Get a reference to the non-secure context */
ns_cpu_context
=
cm_get_context
(
NON_SECURE
);
assert
(
ns_cpu_context
);
/* Restore non-secure state */
cm_el1_sysregs_context_restore
(
NON_SECURE
);
cm_set_next_eret_context
(
NON_SECURE
);
SMC_RET1
(
ns_cpu_context
,
TSP_EL3_FIQ
);
/*
/*
* This function ID is used only by the SP to indicate it has
* This function ID is used only by the SP to indicate it has
* finished initialising itself after a cold boot
* finished initialising itself after a cold boot
...
@@ -422,7 +413,7 @@ uint64_t tspd_smc_handler(uint32_t smc_fid,
...
@@ -422,7 +413,7 @@ uint64_t tspd_smc_handler(uint32_t smc_fid,
if
(
rc
)
if
(
rc
)
panic
();
panic
();
#if TSP
D_ROUTE_IRQ_TO_EL3
#if TSP
_NS_INTR_ASYNC_PREEMPT
/*
/*
* Register an interrupt handler for NS interrupts when
* Register an interrupt handler for NS interrupts when
* generated during code executing in secure state are
* generated during code executing in secure state are
...
@@ -438,8 +429,7 @@ uint64_t tspd_smc_handler(uint32_t smc_fid,
...
@@ -438,8 +429,7 @@ uint64_t tspd_smc_handler(uint32_t smc_fid,
panic
();
panic
();
/*
/*
* Disable the interrupt NS locally since it will be enabled globally
* Disable the NS interrupt locally.
* within cm_init_my_context.
*/
*/
disable_intr_rm_local
(
INTR_TYPE_NS
,
SECURE
);
disable_intr_rm_local
(
INTR_TYPE_NS
,
SECURE
);
#endif
#endif
...
@@ -561,7 +551,7 @@ uint64_t tspd_smc_handler(uint32_t smc_fid,
...
@@ -561,7 +551,7 @@ uint64_t tspd_smc_handler(uint32_t smc_fid,
set_std_smc_active_flag
(
tsp_ctx
->
state
);
set_std_smc_active_flag
(
tsp_ctx
->
state
);
cm_set_elr_el3
(
SECURE
,
(
uint64_t
)
cm_set_elr_el3
(
SECURE
,
(
uint64_t
)
&
tsp_vectors
->
std_smc_entry
);
&
tsp_vectors
->
std_smc_entry
);
#if TSP
D_ROUTE_IRQ_TO_EL3
#if TSP
_NS_INTR_ASYNC_PREEMPT
/*
/*
* Enable the routing of NS interrupts to EL3
* Enable the routing of NS interrupts to EL3
* during STD SMC processing on this core.
* during STD SMC processing on this core.
...
@@ -592,7 +582,7 @@ uint64_t tspd_smc_handler(uint32_t smc_fid,
...
@@ -592,7 +582,7 @@ uint64_t tspd_smc_handler(uint32_t smc_fid,
cm_set_next_eret_context
(
NON_SECURE
);
cm_set_next_eret_context
(
NON_SECURE
);
if
(
GET_SMC_TYPE
(
smc_fid
)
==
SMC_TYPE_STD
)
{
if
(
GET_SMC_TYPE
(
smc_fid
)
==
SMC_TYPE_STD
)
{
clr_std_smc_active_flag
(
tsp_ctx
->
state
);
clr_std_smc_active_flag
(
tsp_ctx
->
state
);
#if TSP
D_ROUTE_IRQ_TO_EL3
#if TSP
_NS_INTR_ASYNC_PREEMPT
/*
/*
* Disable the routing of NS interrupts to EL3
* Disable the routing of NS interrupts to EL3
* after STD SMC processing is finished on this
* after STD SMC processing is finished on this
...
@@ -635,7 +625,7 @@ uint64_t tspd_smc_handler(uint32_t smc_fid,
...
@@ -635,7 +625,7 @@ uint64_t tspd_smc_handler(uint32_t smc_fid,
* We are done stashing the non-secure context. Ask the
* We are done stashing the non-secure context. Ask the
* secure payload to do the work now.
* secure payload to do the work now.
*/
*/
#if TSP
D_ROUTE_IRQ_TO_EL3
#if TSP
_NS_INTR_ASYNC_PREEMPT
/*
/*
* Enable the routing of NS interrupts to EL3 during resumption
* Enable the routing of NS interrupts to EL3 during resumption
* of STD SMC call on this core.
* of STD SMC call on this core.
...
...
services/spd/tspd/tspd_pm.c
View file @
4ca473db
...
@@ -130,7 +130,7 @@ static void tspd_cpu_on_finish_handler(uint64_t unused)
...
@@ -130,7 +130,7 @@ static void tspd_cpu_on_finish_handler(uint64_t unused)
/* Initialise this cpu's secure context */
/* Initialise this cpu's secure context */
cm_init_my_context
(
&
tsp_on_entrypoint
);
cm_init_my_context
(
&
tsp_on_entrypoint
);
#if TSP
D_ROUTE_IRQ_TO_EL3
#if TSP
_NS_INTR_ASYNC_PREEMPT
/*
/*
* Disable the NS interrupt locally since it will be enabled globally
* Disable the NS interrupt locally since it will be enabled globally
* within cm_init_my_context.
* within cm_init_my_context.
...
...
services/spd/tspd/tspd_private.h
View file @
4ca473db
...
@@ -183,10 +183,10 @@ CASSERT(TSPD_SP_CTX_SIZE == sizeof(sp_ctx_regs_t), \
...
@@ -183,10 +183,10 @@ CASSERT(TSPD_SP_CTX_SIZE == sizeof(sp_ctx_regs_t), \
/*******************************************************************************
/*******************************************************************************
* Structure which helps the SPD to maintain the per-cpu state of the SP.
* Structure which helps the SPD to maintain the per-cpu state of the SP.
* 'saved_spsr_el3' - temporary copy to allow
FIQ handling when the TSP has be
en
* 'saved_spsr_el3' - temporary copy to allow
S-EL1 interrupt handling wh
en
* preempted.
*
the TSP has been
preempted.
* 'saved_elr_el3' - temporary copy to allow
FIQ handling when the TSP has be
en
* 'saved_elr_el3' - temporary copy to allow
S-EL1 interrupt handling wh
en
* preempted.
*
the TSP has been
preempted.
* 'state' - collection of flags to track SP state e.g. on/off
* 'state' - collection of flags to track SP state e.g. on/off
* 'mpidr' - mpidr to associate a context with a cpu
* 'mpidr' - mpidr to associate a context with a cpu
* 'c_rt_ctx' - stack address to restore C runtime context from after
* 'c_rt_ctx' - stack address to restore C runtime context from after
...
@@ -207,7 +207,7 @@ typedef struct tsp_context {
...
@@ -207,7 +207,7 @@ typedef struct tsp_context {
uint64_t
c_rt_ctx
;
uint64_t
c_rt_ctx
;
cpu_context_t
cpu_ctx
;
cpu_context_t
cpu_ctx
;
uint64_t
saved_tsp_args
[
TSP_NUM_ARGS
];
uint64_t
saved_tsp_args
[
TSP_NUM_ARGS
];
#if TSP
D_ROUTE_IRQ_TO_EL3
#if TSP
_NS_INTR_ASYNC_PREEMPT
sp_ctx_regs_t
sp_ctx
;
sp_ctx_regs_t
sp_ctx
;
#endif
#endif
}
tsp_context_t
;
}
tsp_context_t
;
...
...
Prev
1
2
3
Next
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