aboutsummaryrefslogtreecommitdiff
path: root/bl32
diff options
context:
space:
mode:
authorSoby Mathew <soby.mathew@arm.com>2015-09-03 18:29:38 +0100
committerSoby Mathew <soby.mathew@arm.com>2015-12-04 12:02:12 +0000
commit02446137a4e2a504706fb1f4059467643e2930a5 (patch)
tree765f2c757d123cf6c63157cb9d2972008a7773c0 /bl32
parent404dba53ef9be643f80babdd4ab81501bdbaba16 (diff)
downloadtrusted-firmware-a-02446137a4e2a504706fb1f4059467643e2930a5.tar.gz
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
Diffstat (limited to 'bl32')
-rw-r--r--bl32/tsp/aarch64/tsp_entrypoint.S49
-rw-r--r--bl32/tsp/aarch64/tsp_exceptions.S50
-rw-r--r--bl32/tsp/tsp_interrupt.c55
-rw-r--r--bl32/tsp/tsp_private.h13
4 files changed, 85 insertions, 82 deletions
diff --git a/bl32/tsp/aarch64/tsp_entrypoint.S b/bl32/tsp/aarch64/tsp_entrypoint.S
index 9732ff2cdf..d183dff9fa 100644
--- a/bl32/tsp/aarch64/tsp_entrypoint.S
+++ b/bl32/tsp/aarch64/tsp_entrypoint.S
@@ -177,7 +177,7 @@ func tsp_vector_table
b tsp_cpu_off_entry
b tsp_cpu_resume_entry
b tsp_cpu_suspend_entry
- b tsp_fiq_entry
+ b tsp_sel1_intr_entry
b tsp_system_off_entry
b tsp_system_reset_entry
endfunc tsp_vector_table
@@ -325,13 +325,13 @@ func tsp_cpu_suspend_entry
restore_args_call_smc
endfunc tsp_cpu_suspend_entry
- /*---------------------------------------------
+ /*-------------------------------------------------
* 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
* this. TSPD expects control to be handed back
- * at the end of FIQ processing. This is done
- * through an SMC. The handover agreement is:
+ * at the end of interrupt processing. This is
+ * done through an SMC. The handover agreement is:
*
* 1. PSTATE.DAIF are set upon entry. 'x1' has
* 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
* runtime.
* 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
- mov x2, #(TSP_HANDLE_FIQ_AND_RETURN & ~0xffff)
- movk x2, #(TSP_HANDLE_FIQ_AND_RETURN & 0xffff)
+ mov x2, #(TSP_HANDLE_SEL1_INTR_AND_RETURN & ~0xffff)
+ movk x2, #(TSP_HANDLE_SEL1_INTR_AND_RETURN & 0xffff)
cmp x0, x2
- b.ne tsp_fiq_entry_panic
+ b.ne tsp_sel1_int_entry_panic
#endif
- /*---------------------------------------------
+ /*-------------------------------------------------
* Save any previous context needed to perform
* an exception return from S-EL1 e.g. context
- * from a previous IRQ. Update statistics and
- * handle the FIQ before returning to the TSPD.
+ * from a previous Non secure Interrupt.
+ * Update statistics and handle the S-EL1
+ * interrupt before returning to the TSPD.
* IRQ/FIQs are not enabled since that will
* complicate the implementation. Execution
* will be transferred back to the normal world
* 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
- bl tsp_update_sync_fiq_stats
- bl tsp_fiq_handler
- cbnz x0, tsp_fiq_entry_panic
+ bl tsp_update_sync_sel1_intr_stats
+ bl tsp_common_int_handler
+ cbnz x0, tsp_sel1_int_entry_panic
restore_eret_context x2 x3
- mov x0, #(TSP_HANDLED_S_EL1_FIQ & ~0xffff)
- movk x0, #(TSP_HANDLED_S_EL1_FIQ & 0xffff)
+ mov x0, #(TSP_HANDLED_S_EL1_INTR & ~0xffff)
+ movk x0, #(TSP_HANDLED_S_EL1_INTR & 0xffff)
smc #0
-tsp_fiq_entry_panic:
- b tsp_fiq_entry_panic
-endfunc tsp_fiq_entry
+tsp_sel1_int_entry_panic:
+ b tsp_sel1_int_entry_panic
+endfunc tsp_sel1_intr_entry
/*---------------------------------------------
* This entrypoint is used by the TSPD when this
diff --git a/bl32/tsp/aarch64/tsp_exceptions.S b/bl32/tsp/aarch64/tsp_exceptions.S
index 272d94b7b7..d5e089f6e8 100644
--- a/bl32/tsp/aarch64/tsp_exceptions.S
+++ b/bl32/tsp/aarch64/tsp_exceptions.S
@@ -70,6 +70,28 @@
add sp, sp, SCRATCH_REG_SIZE
.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
/* -----------------------------------------------------
@@ -120,36 +142,12 @@ sync_exception_sp_elx:
.align 7
irq_sp_elx:
- /* Enable the SError interrupt */
- 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
+ handle_tsp_interrupt irq_sp_elx
check_vector_size irq_sp_elx
.align 7
fiq_sp_elx:
- /* Enable the SError interrupt */
- 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
+ handle_tsp_interrupt fiq_sp_elx
check_vector_size fiq_sp_elx
.align 7
diff --git a/bl32/tsp/tsp_interrupt.c b/bl32/tsp/tsp_interrupt.c
index d5379cdc6a..7654d2e86d 100644
--- a/bl32/tsp/tsp_interrupt.c
+++ b/bl32/tsp/tsp_interrupt.c
@@ -31,38 +31,39 @@
#include <arch_helpers.h>
#include <assert.h>
#include <debug.h>
-#include <gic_v2.h>
#include <platform.h>
#include <platform_def.h>
#include <tsp.h>
#include "tsp_private.h"
/*******************************************************************************
- * This function updates the TSP statistics for FIQs handled synchronously i.e
- * the ones that have been handed over by the TSPD. It also keeps count of the
- * number of times control was passed back to the TSPD after handling an FIQ.
- * In the future it will be possible that the TSPD hands over an FIQ to the TSP
- * but does not expect it to return execution. This statistic will be useful to
- * distinguish between these two models of synchronous FIQ handling.
- * The 'elr_el3' parameter contains the address of the instruction in normal
- * world where this FIQ was generated.
+ * This function updates the TSP statistics for S-EL1 interrupts handled
+ * synchronously i.e the ones that have been handed over by the TSPD. It also
+ * keeps count of the number of times control was passed back to the TSPD
+ * after handling the interrupt. In the future it will be possible that the
+ * TSPD hands over an S-EL1 interrupt to the TSP but does not expect it to
+ * return execution. This statistic will be useful to distinguish between these
+ * two models of synchronous S-EL1 interrupt handling. The 'elr_el3' parameter
+ * 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();
- tsp_stats[linear_id].sync_fiq_count++;
- if (type == TSP_HANDLE_FIQ_AND_RETURN)
- tsp_stats[linear_id].sync_fiq_ret_count++;
+ tsp_stats[linear_id].sync_sel1_intr_count++;
+ if (type == TSP_HANDLE_SEL1_INTR_AND_RETURN)
+ tsp_stats[linear_id].sync_sel1_intr_ret_count++;
#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
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);
- 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(),
- tsp_stats[linear_id].sync_fiq_count,
- tsp_stats[linear_id].sync_fiq_ret_count);
+ tsp_stats[linear_id].sync_sel1_intr_count,
+ tsp_stats[linear_id].sync_sel1_intr_ret_count);
spin_unlock(&console_lock);
#endif
}
@@ -87,13 +88,13 @@ int32_t tsp_handle_preemption(void)
}
/*******************************************************************************
- * TSP FIQ handler called as a part of both synchronous and asynchronous
- * handling of FIQ interrupts. It returns 0 upon successfully handling a S-EL1
- * FIQ and treats all other FIQs as EL3 interrupts. It assumes that the GIC
- * architecture version in v2.0 and the secure physical timer interrupt is the
- * only S-EL1 interrupt that it needs to handle.
+ * TSP interrupt handler is called as a part of both synchronous and
+ * asynchronous handling of TSP interrupts. Currently the physical timer
+ * interrupt is the only S-EL1 interrupt that this handler expects. It returns
+ * 0 upon successfully handling the expected interrupt and all other
+ * 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;
@@ -123,13 +124,13 @@ int32_t tsp_fiq_handler(void)
plat_ic_end_of_interrupt(id);
/* 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
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);
- VERBOSE("TSP: cpu 0x%lx: %d fiq requests\n",
- read_mpidr(), tsp_stats[linear_id].fiq_count);
+ VERBOSE("TSP: cpu 0x%lx: %d S-EL1 requests\n",
+ read_mpidr(), tsp_stats[linear_id].sel1_intr_count);
spin_unlock(&console_lock);
#endif
return 0;
diff --git a/bl32/tsp/tsp_private.h b/bl32/tsp/tsp_private.h
index 346351c0c4..e341cfd7da 100644
--- a/bl32/tsp/tsp_private.h
+++ b/bl32/tsp/tsp_private.h
@@ -54,11 +54,14 @@
typedef struct work_statistics {
- uint32_t fiq_count; /* Number of FIQs on this cpu */
- uint32_t sync_fiq_count; /* Number of sync. fiqs on this cpu */
- uint32_t sync_fiq_ret_count; /* Number of fiq returns on this cpu */
+ /* Number of s-el1 interrupts on this cpu */
+ uint32_t sel1_intr_count;
/* Number of non s-el1 interrupts on this cpu which preempted TSP */
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 eret_count; /* Number of entries on this cpu */
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_restore(void);
-/* FIQ management functions */
-void tsp_update_sync_fiq_stats(uint32_t type, uint64_t elr_el3);
+/* S-EL1 interrupt management functions */
+void tsp_update_sync_sel1_intr_stats(uint32_t type, uint64_t elr_el3);
/* Data structure to keep track of TSP statistics */