Enable use of FIQs and IRQs as TSP interrupts

On a GICv2 system, interrupts that should be handled in the secure world are
typically signalled as FIQs. On a GICv3 system, these interrupts are signalled
as IRQs instead. The mechanism for handling both types of interrupts is the same
in both cases. This patch enables the TSP to run on a GICv3 system by:

1. adding support for handling IRQs in the exception handling code.
2. removing use of "fiq" in the names of data structures, macros and functions.

The build option TSPD_ROUTE_IRQ_TO_EL3 is deprecated and is replaced with a
new build flag TSP_NS_INTR_ASYNC_PREEMPT. For compatibility reasons, if the
former build flag is defined, it will be used to define the value for the
new build flag. The documentation is also updated accordingly.

Change-Id: I1807d371f41c3656322dd259340a57649833065e
This commit is contained in:
Soby Mathew 2015-09-03 18:29:38 +01:00
parent 404dba53ef
commit 02446137a4
11 changed files with 153 additions and 136 deletions

View File

@ -177,7 +177,7 @@ func tsp_vector_table
b tsp_cpu_off_entry b tsp_cpu_off_entry
b tsp_cpu_resume_entry b tsp_cpu_resume_entry
b tsp_cpu_suspend_entry b tsp_cpu_suspend_entry
b tsp_fiq_entry b tsp_sel1_intr_entry
b tsp_system_off_entry b tsp_system_off_entry
b tsp_system_reset_entry b tsp_system_reset_entry
endfunc tsp_vector_table endfunc tsp_vector_table
@ -325,13 +325,13 @@ func tsp_cpu_suspend_entry
restore_args_call_smc restore_args_call_smc
endfunc tsp_cpu_suspend_entry endfunc tsp_cpu_suspend_entry
/*--------------------------------------------- /*-------------------------------------------------
* This entrypoint is used by the TSPD to pass * This entrypoint is used by the TSPD to pass
* control for handling a pending S-EL1 FIQ. * control for handling a pending S-EL1 Interrupt.
* 'x0' contains a magic number which indicates * 'x0' contains a magic number which indicates
* this. TSPD expects control to be handed back * this. TSPD expects control to be handed back
* at the end of FIQ processing. This is done * at the end of interrupt processing. This is
* through an SMC. The handover agreement is: * done through an SMC. The handover agreement is:
* *
* 1. PSTATE.DAIF are set upon entry. 'x1' has * 1. PSTATE.DAIF are set upon entry. 'x1' has
* the ELR_EL3 from the non-secure state. * the ELR_EL3 from the non-secure state.
@ -343,40 +343,41 @@ endfunc tsp_cpu_suspend_entry
* 4. TSP can use 'x0-x18' to enable its C * 4. TSP can use 'x0-x18' to enable its C
* runtime. * runtime.
* 5. TSP returns to TSPD using an SMC with * 5. TSP returns to TSPD using an SMC with
* 'x0' = TSP_HANDLED_S_EL1_FIQ * 'x0' = TSP_HANDLED_S_EL1_INTR
* --------------------------------------------- * ------------------------------------------------
*/ */
func tsp_fiq_entry func tsp_sel1_intr_entry
#if DEBUG #if DEBUG
mov x2, #(TSP_HANDLE_FIQ_AND_RETURN & ~0xffff) mov x2, #(TSP_HANDLE_SEL1_INTR_AND_RETURN & ~0xffff)
movk x2, #(TSP_HANDLE_FIQ_AND_RETURN & 0xffff) movk x2, #(TSP_HANDLE_SEL1_INTR_AND_RETURN & 0xffff)
cmp x0, x2 cmp x0, x2
b.ne tsp_fiq_entry_panic b.ne tsp_sel1_int_entry_panic
#endif #endif
/*--------------------------------------------- /*-------------------------------------------------
* Save any previous context needed to perform * Save any previous context needed to perform
* an exception return from S-EL1 e.g. context * an exception return from S-EL1 e.g. context
* from a previous IRQ. Update statistics and * from a previous Non secure Interrupt.
* handle the FIQ before returning to the TSPD. * Update statistics and handle the S-EL1
* interrupt before returning to the TSPD.
* IRQ/FIQs are not enabled since that will * IRQ/FIQs are not enabled since that will
* complicate the implementation. Execution * complicate the implementation. Execution
* will be transferred back to the normal world * will be transferred back to the normal world
* in any case. A non-zero return value from the * in any case. A non-zero return value from the
* fiq handler is an error. * interrupt handler is an error.
* --------------------------------------------- * ------------------------------------------------
*/ */
save_eret_context x2 x3 save_eret_context x2 x3
bl tsp_update_sync_fiq_stats bl tsp_update_sync_sel1_intr_stats
bl tsp_fiq_handler bl tsp_common_int_handler
cbnz x0, tsp_fiq_entry_panic cbnz x0, tsp_sel1_int_entry_panic
restore_eret_context x2 x3 restore_eret_context x2 x3
mov x0, #(TSP_HANDLED_S_EL1_FIQ & ~0xffff) mov x0, #(TSP_HANDLED_S_EL1_INTR & ~0xffff)
movk x0, #(TSP_HANDLED_S_EL1_FIQ & 0xffff) movk x0, #(TSP_HANDLED_S_EL1_INTR & 0xffff)
smc #0 smc #0
tsp_fiq_entry_panic: tsp_sel1_int_entry_panic:
b tsp_fiq_entry_panic b tsp_sel1_int_entry_panic
endfunc tsp_fiq_entry endfunc tsp_sel1_intr_entry
/*--------------------------------------------- /*---------------------------------------------
* This entrypoint is used by the TSPD when this * This entrypoint is used by the TSPD when this

View File

@ -70,6 +70,28 @@
add sp, sp, SCRATCH_REG_SIZE add sp, sp, SCRATCH_REG_SIZE
.endm .endm
/* ----------------------------------------------------
* Common TSP interrupt handling routine
* ----------------------------------------------------
*/
.macro handle_tsp_interrupt label
/* Enable the SError interrupt */
msr daifclr, #DAIF_ABT_BIT
save_caller_regs_and_lr
bl tsp_common_int_handler
cbz x0, interrupt_exit_\label
/*
* This interrupt was not targetted to S-EL1 so send it to
* the monitor and wait for execution to resume.
*/
smc #0
interrupt_exit_\label:
restore_caller_regs_and_lr
eret
.endm
.globl tsp_exceptions .globl tsp_exceptions
/* ----------------------------------------------------- /* -----------------------------------------------------
@ -120,36 +142,12 @@ sync_exception_sp_elx:
.align 7 .align 7
irq_sp_elx: irq_sp_elx:
/* Enable the SError interrupt */ handle_tsp_interrupt irq_sp_elx
msr daifclr, #DAIF_ABT_BIT
save_caller_regs_and_lr
/* We just update some statistics in the handler */
bl tsp_handle_preemption
/* Hand over control to the normal world to handle the IRQ */
smc #0
/* The resume std smc starts from here */
restore_caller_regs_and_lr
eret
check_vector_size irq_sp_elx check_vector_size irq_sp_elx
.align 7 .align 7
fiq_sp_elx: fiq_sp_elx:
/* Enable the SError interrupt */ handle_tsp_interrupt fiq_sp_elx
msr daifclr, #DAIF_ABT_BIT
save_caller_regs_and_lr
bl tsp_fiq_handler
cbz x0, fiq_sp_elx_done
/*
* This FIQ was not targetted to S-EL1 so send it to
* the monitor and wait for execution to resume.
*/
smc #0
fiq_sp_elx_done:
restore_caller_regs_and_lr
eret
check_vector_size fiq_sp_elx check_vector_size fiq_sp_elx
.align 7 .align 7

View File

@ -31,38 +31,39 @@
#include <arch_helpers.h> #include <arch_helpers.h>
#include <assert.h> #include <assert.h>
#include <debug.h> #include <debug.h>
#include <gic_v2.h>
#include <platform.h> #include <platform.h>
#include <platform_def.h> #include <platform_def.h>
#include <tsp.h> #include <tsp.h>
#include "tsp_private.h" #include "tsp_private.h"
/******************************************************************************* /*******************************************************************************
* This function updates the TSP statistics for FIQs handled synchronously i.e * This function updates the TSP statistics for S-EL1 interrupts handled
* the ones that have been handed over by the TSPD. It also keeps count of the * synchronously i.e the ones that have been handed over by the TSPD. It also
* number of times control was passed back to the TSPD after handling an FIQ. * keeps count of the number of times control was passed back to the TSPD
* In the future it will be possible that the TSPD hands over an FIQ to the TSP * after handling the interrupt. In the future it will be possible that the
* but does not expect it to return execution. This statistic will be useful to * TSPD hands over an S-EL1 interrupt to the TSP but does not expect it to
* distinguish between these two models of synchronous FIQ handling. * return execution. This statistic will be useful to distinguish between these
* The 'elr_el3' parameter contains the address of the instruction in normal * two models of synchronous S-EL1 interrupt handling. The 'elr_el3' parameter
* world where this FIQ was generated. * contains the address of the instruction in normal world where this S-EL1
* interrupt was generated.
******************************************************************************/ ******************************************************************************/
void tsp_update_sync_fiq_stats(uint32_t type, uint64_t elr_el3) void tsp_update_sync_sel1_intr_stats(uint32_t type, uint64_t elr_el3)
{ {
uint32_t linear_id = plat_my_core_pos(); uint32_t linear_id = plat_my_core_pos();
tsp_stats[linear_id].sync_fiq_count++; tsp_stats[linear_id].sync_sel1_intr_count++;
if (type == TSP_HANDLE_FIQ_AND_RETURN) if (type == TSP_HANDLE_SEL1_INTR_AND_RETURN)
tsp_stats[linear_id].sync_fiq_ret_count++; tsp_stats[linear_id].sync_sel1_intr_ret_count++;
#if LOG_LEVEL >= LOG_LEVEL_VERBOSE #if LOG_LEVEL >= LOG_LEVEL_VERBOSE
spin_lock(&console_lock); spin_lock(&console_lock);
VERBOSE("TSP: cpu 0x%lx sync fiq request from 0x%lx\n", VERBOSE("TSP: cpu 0x%lx sync s-el1 interrupt request from 0x%lx\n",
read_mpidr(), elr_el3); read_mpidr(), elr_el3);
VERBOSE("TSP: cpu 0x%lx: %d sync fiq requests, %d sync fiq returns\n", VERBOSE("TSP: cpu 0x%lx: %d sync s-el1 interrupt requests,"
" %d sync s-el1 interrupt returns\n",
read_mpidr(), read_mpidr(),
tsp_stats[linear_id].sync_fiq_count, tsp_stats[linear_id].sync_sel1_intr_count,
tsp_stats[linear_id].sync_fiq_ret_count); tsp_stats[linear_id].sync_sel1_intr_ret_count);
spin_unlock(&console_lock); spin_unlock(&console_lock);
#endif #endif
} }
@ -87,13 +88,13 @@ int32_t tsp_handle_preemption(void)
} }
/******************************************************************************* /*******************************************************************************
* TSP FIQ handler called as a part of both synchronous and asynchronous * TSP interrupt handler is called as a part of both synchronous and
* handling of FIQ interrupts. It returns 0 upon successfully handling a S-EL1 * asynchronous handling of TSP interrupts. Currently the physical timer
* FIQ and treats all other FIQs as EL3 interrupts. It assumes that the GIC * interrupt is the only S-EL1 interrupt that this handler expects. It returns
* architecture version in v2.0 and the secure physical timer interrupt is the * 0 upon successfully handling the expected interrupt and all other
* only S-EL1 interrupt that it needs to handle. * interrupts are treated as normal world or EL3 interrupts.
******************************************************************************/ ******************************************************************************/
int32_t tsp_fiq_handler(void) int32_t tsp_common_int_handler(void)
{ {
uint32_t linear_id = plat_my_core_pos(), id; uint32_t linear_id = plat_my_core_pos(), id;
@ -123,13 +124,13 @@ int32_t tsp_fiq_handler(void)
plat_ic_end_of_interrupt(id); plat_ic_end_of_interrupt(id);
/* Update the statistics and print some messages */ /* Update the statistics and print some messages */
tsp_stats[linear_id].fiq_count++; tsp_stats[linear_id].sel1_intr_count++;
#if LOG_LEVEL >= LOG_LEVEL_VERBOSE #if LOG_LEVEL >= LOG_LEVEL_VERBOSE
spin_lock(&console_lock); spin_lock(&console_lock);
VERBOSE("TSP: cpu 0x%lx handled fiq %d\n", VERBOSE("TSP: cpu 0x%lx handled S-EL1 interrupt %d\n",
read_mpidr(), id); read_mpidr(), id);
VERBOSE("TSP: cpu 0x%lx: %d fiq requests\n", VERBOSE("TSP: cpu 0x%lx: %d S-EL1 requests\n",
read_mpidr(), tsp_stats[linear_id].fiq_count); read_mpidr(), tsp_stats[linear_id].sel1_intr_count);
spin_unlock(&console_lock); spin_unlock(&console_lock);
#endif #endif
return 0; return 0;

View File

@ -54,11 +54,14 @@
typedef struct work_statistics { typedef struct work_statistics {
uint32_t fiq_count; /* Number of FIQs on this cpu */ /* Number of s-el1 interrupts on this cpu */
uint32_t sync_fiq_count; /* Number of sync. fiqs on this cpu */ uint32_t sel1_intr_count;
uint32_t sync_fiq_ret_count; /* Number of fiq returns on this cpu */
/* Number of non s-el1 interrupts on this cpu which preempted TSP */ /* Number of non s-el1 interrupts on this cpu which preempted TSP */
uint32_t preempt_intr_count; uint32_t preempt_intr_count;
/* Number of sync s-el1 interrupts on this cpu */
uint32_t sync_sel1_intr_count;
/* Number of s-el1 interrupts returns on this cpu */
uint32_t sync_sel1_intr_ret_count;
uint32_t smc_count; /* Number of returns on this cpu */ uint32_t smc_count; /* Number of returns on this cpu */
uint32_t eret_count; /* Number of entries on this cpu */ uint32_t eret_count; /* Number of entries on this cpu */
uint32_t cpu_on_count; /* Number of cpu on requests */ uint32_t cpu_on_count; /* Number of cpu on requests */
@ -116,8 +119,8 @@ void tsp_generic_timer_stop(void);
void tsp_generic_timer_save(void); void tsp_generic_timer_save(void);
void tsp_generic_timer_restore(void); void tsp_generic_timer_restore(void);
/* FIQ management functions */ /* S-EL1 interrupt management functions */
void tsp_update_sync_fiq_stats(uint32_t type, uint64_t elr_el3); void tsp_update_sync_sel1_intr_stats(uint32_t type, uint64_t elr_el3);
/* Data structure to keep track of TSP statistics */ /* Data structure to keep track of TSP statistics */

View File

@ -399,12 +399,12 @@ requirements mentioned earlier.
1. It passes control to the Test Secure Payload to perform its 1. It passes control to the Test Secure Payload to perform its
initialisation. The TSP provides the address of the vector table initialisation. The TSP provides the address of the vector table
`tsp_vectors` in the SP which also includes the handler for Secure-EL1 `tsp_vectors` in the SP which also includes the handler for Secure-EL1
interrupts in the `fiq_entry` field. The TSPD passes control to the TSP at interrupts in the `sel1_intr_entry` field. The TSPD passes control to the TSP at
this address when it receives a Secure-EL1 interrupt. this address when it receives a Secure-EL1 interrupt.
The handover agreement between the TSP and the TSPD requires that the TSPD The handover agreement between the TSP and the TSPD requires that the TSPD
masks all interrupts (`PSTATE.DAIF` bits) when it calls masks all interrupts (`PSTATE.DAIF` bits) when it calls
`tsp_fiq_entry()`. The TSP has to preserve the callee saved general `tsp_sel1_intr_entry()`. The TSP has to preserve the callee saved general
purpose, SP_EL1/Secure-EL0, LR, VFP and system registers. It can use purpose, SP_EL1/Secure-EL0, LR, VFP and system registers. It can use
`x0-x18` to enable its C runtime. `x0-x18` to enable its C runtime.
@ -514,7 +514,7 @@ runtime firmware is not aware of through its platform port.
The routing model for Secure-EL1 and non-secure interrupts chosen by the TSP is The routing model for Secure-EL1 and non-secure interrupts chosen by the TSP is
described in Section 2.2.2. It is known to the TSPD service at build time. described in Section 2.2.2. It is known to the TSPD service at build time.
The TSP implements an entrypoint (`tsp_fiq_entry()`) for handling Secure-EL1 The TSP implements an entrypoint (`tsp_sel1_intr_entry()`) for handling Secure-EL1
interrupts taken in non-secure state and routed through the TSPD service interrupts taken in non-secure state and routed through the TSPD service
(synchronous handling model). It passes the reference to this entrypoint via (synchronous handling model). It passes the reference to this entrypoint via
`tsp_vectors` to the TSPD service. `tsp_vectors` to the TSPD service.
@ -700,9 +700,9 @@ takes the following actions upon being invoked.
3. It saves the system register context for the non-secure state by calling 3. It saves the system register context for the non-secure state by calling
`cm_el1_sysregs_context_save(NON_SECURE);`. `cm_el1_sysregs_context_save(NON_SECURE);`.
4. It sets the `ELR_EL3` system register to `tsp_fiq_entry` and sets the 4. It sets the `ELR_EL3` system register to `tsp_sel1_intr_entry` and sets the
`SPSR_EL3.DAIF` bits in the secure CPU context. It sets `x0` to `SPSR_EL3.DAIF` bits in the secure CPU context. It sets `x0` to
`TSP_HANDLE_FIQ_AND_RETURN`. If the TSP was in the middle of handling a `TSP_HANDLE_SEL1_INTR_AND_RETURN`. If the TSP was in the middle of handling a
standard SMC, then the `ELR_EL3` and `SPSR_EL3` registers in the secure CPU standard SMC, then the `ELR_EL3` and `SPSR_EL3` registers in the secure CPU
context are saved first. context are saved first.
@ -723,20 +723,20 @@ state.
![Image 1](diagrams/sec-int-handling.png?raw=true) ![Image 1](diagrams/sec-int-handling.png?raw=true)
The TSP issues an SMC with `TSP_HANDLED_S_EL1_FIQ` as the function identifier to The TSP issues an SMC with `TSP_HANDLED_S_EL1_INTR` as the function identifier to
signal completion of interrupt handling. signal completion of interrupt handling.
The TSP issues an SMC with `TSP_PREEMPTED` as the function identifier to signal The TSP issues an SMC with `TSP_PREEMPTED` as the function identifier to signal
generation of a non-secure interrupt in Secure-EL1. generation of a non-secure interrupt in Secure-EL1.
The TSPD service takes the following actions in `tspd_smc_handler()` function The TSPD service takes the following actions in `tspd_smc_handler()` function
upon receiving an SMC with `TSP_HANDLED_S_EL1_FIQ` and `TSP_PREEMPTED` as the upon receiving an SMC with `TSP_HANDLED_S_EL1_INTR` and `TSP_PREEMPTED` as the
function identifiers: function identifiers:
1. It ensures that the call originated from the secure state otherwise 1. It ensures that the call originated from the secure state otherwise
execution returns to the non-secure state with `SMC_UNK` in `x0`. execution returns to the non-secure state with `SMC_UNK` in `x0`.
2. If the function identifier is `TSP_HANDLED_S_EL1_FIQ`, it restores the 2. If the function identifier is `TSP_HANDLED_S_EL1_INTR`, it restores the
saved `ELR_EL3` and `SPSR_EL3` system registers back to the secure CPU saved `ELR_EL3` and `SPSR_EL3` system registers back to the secure CPU
context (see step 4 above) in case the TSP had been preempted by a non context (see step 4 above) in case the TSP had been preempted by a non
secure interrupt earlier. It does not save the secure context since the secure interrupt earlier. It does not save the secure context since the
@ -811,7 +811,7 @@ state.
##### 2.3.3.1 Test secure payload behavior ##### 2.3.3.1 Test secure payload behavior
The TSPD hands control of a Secure-EL1 interrupt to the TSP at the The TSPD hands control of a Secure-EL1 interrupt to the TSP at the
`tsp_fiq_entry()`. The TSP handles the interrupt while ensuring that the `tsp_sel1_intr_entry()`. The TSP handles the interrupt while ensuring that the
handover agreement described in Section 2.2.2.1 is maintained. It updates some handover agreement described in Section 2.2.2.1 is maintained. It updates some
statistics by calling `tsp_update_sync_fiq_stats()`. It then calls statistics by calling `tsp_update_sync_fiq_stats()`. It then calls
`tsp_fiq_handler()` which. `tsp_fiq_handler()` which.
@ -827,7 +827,7 @@ statistics by calling `tsp_update_sync_fiq_stats()`. It then calls
end of interrupt processing. end of interrupt processing.
The TSP passes control back to the TSPD by issuing an SMC64 with The TSP passes control back to the TSPD by issuing an SMC64 with
`TSP_HANDLED_S_EL1_FIQ` as the function identifier. `TSP_HANDLED_S_EL1_INTR` as the function identifier.
The TSP handles interrupts under the asynchronous model as follows. The TSP handles interrupts under the asynchronous model as follows.

View File

@ -278,10 +278,13 @@ performed.
(Coherent memory region is included) or 0 (Coherent memory region is (Coherent memory region is included) or 0 (Coherent memory region is
excluded). Default is 1. excluded). Default is 1.
* `TSPD_ROUTE_IRQ_TO_EL3`: A non zero value enables the routing model * `TSP_NS_INTR_ASYNC_PREEMPT`: A non zero value enables the interrupt
for non-secure interrupts in which they are routed to EL3 (TSPD). The routing model which routes non-secure interrupts asynchronously from TSP
default model (when the value is 0) is to route non-secure interrupts to EL3 causing immediate preemption of TSP. The EL3 is responsible
to S-EL1 (TSP). for saving and restoring the TSP context in this routing model. The
default routing model (when the value is 0) is to route non-secure
interrupts to TSP allowing it to save its context and hand over
synchronously to EL3 via an SMC.
* `TRUSTED_BOARD_BOOT`: Boolean flag to include support for the Trusted Board * `TRUSTED_BOARD_BOOT`: Boolean flag to include support for the Trusted Board
Boot feature. When set to '1', BL1 and BL2 images include support to load Boot feature. When set to '1', BL1 and BL2 images include support to load

View File

@ -45,11 +45,12 @@
#define TSP_SYSTEM_RESET_DONE 0xf2000009 #define TSP_SYSTEM_RESET_DONE 0xf2000009
/* /*
* Function identifiers to handle FIQs through the synchronous handling model. * Function identifiers to handle S-El1 interrupt through the synchronous
* If the TSP was previously interrupted then control has to be returned to * handling model. If the TSP was previously interrupted then control has to
* the TSPD after handling the interrupt else execution can remain in the TSP. * be returned to the TSPD after handling the interrupt else execution can
* remain in the TSP.
*/ */
#define TSP_HANDLED_S_EL1_FIQ 0xf2000006 #define TSP_HANDLED_S_EL1_INTR 0xf2000006
/* SMC function ID that TSP uses to request service from secure monitor */ /* SMC function ID that TSP uses to request service from secure monitor */
#define TSP_GET_ARGS 0xf2001000 #define TSP_GET_ARGS 0xf2001000
@ -62,7 +63,7 @@
#define TSP_SUB 0x2001 #define TSP_SUB 0x2001
#define TSP_MUL 0x2002 #define TSP_MUL 0x2002
#define TSP_DIV 0x2003 #define TSP_DIV 0x2003
#define TSP_HANDLE_FIQ_AND_RETURN 0x2004 #define TSP_HANDLE_SEL1_INTR_AND_RETURN 0x2004
/* /*
* Generate function IDs for TSP services to be used in SMC calls, by * Generate function IDs for TSP services to be used in SMC calls, by
@ -114,7 +115,7 @@ typedef struct tsp_vectors {
tsp_vector_isn_t cpu_off_entry; tsp_vector_isn_t cpu_off_entry;
tsp_vector_isn_t cpu_resume_entry; tsp_vector_isn_t cpu_resume_entry;
tsp_vector_isn_t cpu_suspend_entry; tsp_vector_isn_t cpu_suspend_entry;
tsp_vector_isn_t fiq_entry; tsp_vector_isn_t sel1_intr_entry;
tsp_vector_isn_t system_off_entry; tsp_vector_isn_t system_off_entry;
tsp_vector_isn_t system_reset_entry; tsp_vector_isn_t system_reset_entry;
} tsp_vectors_t; } tsp_vectors_t;

View File

@ -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.
TSPD_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))

View File

@ -108,7 +108,7 @@ uint64_t tspd_handle_sp_preemption(void *handle)
/******************************************************************************* /*******************************************************************************
* 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,
@ -136,44 +136,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 TSPD_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 an 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 TSPD_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,
@ -327,10 +327,10 @@ 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. 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);
@ -347,7 +347,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 TSPD_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.
@ -408,7 +408,7 @@ uint64_t tspd_smc_handler(uint32_t smc_fid,
if (rc) if (rc)
panic(); panic();
#if TSPD_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
@ -546,7 +546,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 TSPD_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.
@ -577,7 +577,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 TSPD_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
@ -620,7 +620,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 TSPD_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.

View File

@ -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 TSPD_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.

View File

@ -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 been * 'saved_spsr_el3' - temporary copy to allow S-EL1 interrupt handling when
* preempted. * the TSP has been preempted.
* 'saved_elr_el3' - temporary copy to allow FIQ handling when the TSP has been * 'saved_elr_el3' - temporary copy to allow S-EL1 interrupt handling when
* 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 {
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 TSPD_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;