Commit 4ca473db authored by danh-arm's avatar 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
...@@ -67,18 +67,15 @@ typedef struct intr_type_desc { ...@@ -67,18 +67,15 @@ typedef struct intr_type_desc {
static intr_type_desc_t intr_type_descs[MAX_INTR_TYPES]; static intr_type_desc_t intr_type_descs[MAX_INTR_TYPES];
/******************************************************************************* /*******************************************************************************
* This function validates the interrupt type. EL3 interrupts are currently not * This function validates the interrupt type.
* supported.
******************************************************************************/ ******************************************************************************/
static int32_t validate_interrupt_type(uint32_t type) static int32_t validate_interrupt_type(uint32_t type)
{ {
if (type == INTR_TYPE_EL3) if (type == INTR_TYPE_S_EL1 || type == INTR_TYPE_NS ||
return -ENOTSUP; type == INTR_TYPE_EL3)
return 0;
if (type != INTR_TYPE_S_EL1 && type != INTR_TYPE_NS)
return -EINVAL; return -EINVAL;
return 0;
} }
/******************************************************************************* /*******************************************************************************
...@@ -95,6 +92,9 @@ static int32_t validate_routing_model(uint32_t type, uint32_t flags) ...@@ -95,6 +92,9 @@ static int32_t validate_routing_model(uint32_t type, uint32_t flags)
if (type == INTR_TYPE_NS) if (type == INTR_TYPE_NS)
return validate_ns_interrupt_rm(flags); return validate_ns_interrupt_rm(flags);
if (type == INTR_TYPE_EL3)
return validate_el3_interrupt_rm(flags);
return -EINVAL; return -EINVAL;
} }
......
...@@ -177,7 +177,7 @@ func tsp_vector_table ...@@ -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,15 @@ func tsp_cpu_suspend_entry ...@@ -325,13 +325,15 @@ 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 `synchronously` handling a S-EL1
* 'x0' contains a magic number which indicates * Interrupt which was triggered while executing
* this. TSPD expects control to be handed back * in normal world. 'x0' contains a magic number
* at the end of FIQ processing. This is done * which indicates this. TSPD expects control to
* through an SMC. The handover agreement is: * be handed back 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 * 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 +345,54 @@ endfunc tsp_cpu_suspend_entry ...@@ -343,40 +345,54 @@ 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_imm x2, TSP_HANDLE_SEL1_INTR_AND_RETURN
movk x2, #(TSP_HANDLE_FIQ_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. The handler can return 0
* fiq handler is an error. * if the interrupt was handled or TSP_PREEMPTED
* --------------------------------------------- * if the expected interrupt was preempted
* by an interrupt that should be handled in EL3
* e.g. Group 0 interrupt in GICv3. In both
* the cases switch to EL3 using SMC with id
* TSP_HANDLED_S_EL1_INTR. Any other return value
* from the handler will result in panic.
* ------------------------------------------------
*/ */
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 /* Check if the S-EL1 interrupt has been handled */
cbnz x0, tsp_sel1_intr_check_preemption
b tsp_sel1_intr_return
tsp_sel1_intr_check_preemption:
/* Check if the S-EL1 interrupt has been preempted */
mov_imm x1, TSP_PREEMPTED
cmp x0, x1
b.ne tsp_sel1_int_entry_panic
tsp_sel1_intr_return:
mov_imm x0, TSP_HANDLED_S_EL1_INTR
restore_eret_context x2 x3 restore_eret_context x2 x3
mov x0, #(TSP_HANDLED_S_EL1_FIQ & ~0xffff)
movk x0, #(TSP_HANDLED_S_EL1_FIQ & 0xffff)
smc #0 smc #0
tsp_fiq_entry_panic: /* Should never reach here */
b tsp_fiq_entry_panic tsp_sel1_int_entry_panic:
endfunc tsp_fiq_entry b tsp_sel1_int_entry_panic
endfunc tsp_sel1_intr_entry
/*--------------------------------------------- /*---------------------------------------------
* This entrypoint is used by the TSPD when this * This entrypoint is used by the TSPD when this
......
...@@ -70,6 +70,28 @@ ...@@ -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: ...@@ -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_irq_received
/* 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
......
...@@ -31,50 +31,70 @@ ...@@ -31,50 +31,70 @@
#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
} }
/******************************************************************************
* This function is invoked when a non S-EL1 interrupt is received and causes
* the preemption of TSP. This function returns TSP_PREEMPTED and results
* in the control being handed over to EL3 for handling the interrupt.
*****************************************************************************/
int32_t tsp_handle_preemption(void)
{
uint32_t linear_id = plat_my_core_pos();
tsp_stats[linear_id].preempt_intr_count++;
#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
spin_lock(&console_lock);
VERBOSE("TSP: cpu 0x%lx: %d preempt interrupt requests\n",
read_mpidr(), tsp_stats[linear_id].preempt_intr_count);
spin_unlock(&console_lock);
#endif
return TSP_PREEMPTED;
}
/******************************************************************************* /*******************************************************************************
* 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;
...@@ -82,16 +102,21 @@ int32_t tsp_fiq_handler(void) ...@@ -82,16 +102,21 @@ int32_t tsp_fiq_handler(void)
* Get the highest priority pending interrupt id and see if it is the * Get the highest priority pending interrupt id and see if it is the
* secure physical generic timer interrupt in which case, handle it. * secure physical generic timer interrupt in which case, handle it.
* Otherwise throw this interrupt at the EL3 firmware. * Otherwise throw this interrupt at the EL3 firmware.
*
* There is a small time window between reading the highest priority
* pending interrupt and acknowledging it during which another
* interrupt of higher priority could become the highest pending
* interrupt. This is not expected to happen currently for TSP.
*/ */
id = plat_ic_get_pending_interrupt_id(); id = plat_ic_get_pending_interrupt_id();
/* TSP can only handle the secure physical timer interrupt */ /* TSP can only handle the secure physical timer interrupt */
if (id != TSP_IRQ_SEC_PHY_TIMER) if (id != TSP_IRQ_SEC_PHY_TIMER)
return TSP_EL3_FIQ; return tsp_handle_preemption();
/* /*
* Handle the interrupt. Also sanity check if it has been preempted by * Acknowledge and handle the secure timer interrupt. Also sanity check
* another secure interrupt through an assertion. * if it has been preempted by another interrupt through an assertion.
*/ */
id = plat_ic_acknowledge_interrupt(); id = plat_ic_acknowledge_interrupt();
assert(id == TSP_IRQ_SEC_PHY_TIMER); assert(id == TSP_IRQ_SEC_PHY_TIMER);
...@@ -99,29 +124,14 @@ int32_t tsp_fiq_handler(void) ...@@ -99,29 +124,14 @@ 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;
} }
int32_t tsp_irq_received(void)
{
uint32_t linear_id = plat_my_core_pos();
tsp_stats[linear_id].irq_count++;
#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
spin_lock(&console_lock);
VERBOSE("TSP: cpu 0x%lx received irq\n", read_mpidr());
VERBOSE("TSP: cpu 0x%lx: %d irq requests\n",
read_mpidr(), tsp_stats[linear_id].irq_count);
spin_unlock(&console_lock);
#endif
return TSP_PREEMPTED;
}
...@@ -54,10 +54,14 @@ ...@@ -54,10 +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 irq_count; /* Number of IRQs on this cpu */ uint32_t sel1_intr_count;
uint32_t sync_fiq_count; /* Number of sync. fiqs on this cpu */ /* Number of non s-el1 interrupts on this cpu which preempted TSP */
uint32_t sync_fiq_ret_count; /* Number of fiq returns on this cpu */ 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 */
...@@ -115,8 +119,8 @@ void tsp_generic_timer_stop(void); ...@@ -115,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 */
......
...@@ -399,12 +399,12 @@ requirements mentioned earlier. ...@@ -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. ...@@ -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. ...@@ -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. ...@@ -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. ...@@ -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 ...@@ -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.
......
...@@ -278,10 +278,13 @@ performed. ...@@ -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
......
...@@ -312,7 +312,7 @@ void gicv3_secure_spis_configure(uintptr_t gicd_base, ...@@ -312,7 +312,7 @@ void gicv3_secure_spis_configure(uintptr_t gicd_base,
unsigned int index, irq_num; unsigned int index, irq_num;
uint64_t gic_affinity_val; uint64_t gic_affinity_val;
assert((int_grp == INT_TYPE_G1S) || (int_grp == INT_TYPE_G0)); assert((int_grp == INTR_GROUP1S) || (int_grp == INTR_GROUP0));
/* If `num_ints` is not 0, ensure that `sec_intr_list` is not NULL */ /* If `num_ints` is not 0, ensure that `sec_intr_list` is not NULL */
assert(num_ints ? (uintptr_t)sec_intr_list : 1); assert(num_ints ? (uintptr_t)sec_intr_list : 1);
...@@ -324,7 +324,7 @@ void gicv3_secure_spis_configure(uintptr_t gicd_base, ...@@ -324,7 +324,7 @@ void gicv3_secure_spis_configure(uintptr_t gicd_base,
gicd_clr_igroupr(gicd_base, irq_num); gicd_clr_igroupr(gicd_base, irq_num);
/* Configure this interrupt as G0 or a G1S interrupt */ /* Configure this interrupt as G0 or a G1S interrupt */
if (int_grp == INT_TYPE_G1S) if (int_grp == INTR_GROUP1S)
gicd_set_igrpmodr(gicd_base, irq_num); gicd_set_igrpmodr(gicd_base, irq_num);
else else
gicd_clr_igrpmodr(gicd_base, irq_num); gicd_clr_igrpmodr(gicd_base, irq_num);
...@@ -386,7 +386,7 @@ void gicv3_secure_ppi_sgi_configure(uintptr_t gicr_base, ...@@ -386,7 +386,7 @@ void gicv3_secure_ppi_sgi_configure(uintptr_t gicr_base,
{ {
unsigned int index, irq_num; unsigned int index, irq_num;
assert((int_grp == INT_TYPE_G1S) || (int_grp == INT_TYPE_G0)); assert((int_grp == INTR_GROUP1S) || (int_grp == INTR_GROUP0));
/* If `num_ints` is not 0, ensure that `sec_intr_list` is not NULL */ /* If `num_ints` is not 0, ensure that `sec_intr_list` is not NULL */
assert(num_ints ? (uintptr_t)sec_intr_list : 1); assert(num_ints ? (uintptr_t)sec_intr_list : 1);
...@@ -398,7 +398,7 @@ void gicv3_secure_ppi_sgi_configure(uintptr_t gicr_base, ...@@ -398,7 +398,7 @@ void gicv3_secure_ppi_sgi_configure(uintptr_t gicr_base,
gicr_clr_igroupr0(gicr_base, irq_num); gicr_clr_igroupr0(gicr_base, irq_num);
/* Configure this interrupt as G0 or a G1S interrupt */ /* Configure this interrupt as G0 or a G1S interrupt */
if (int_grp == INT_TYPE_G1S) if (int_grp == INTR_GROUP1S)
gicr_set_igrpmodr0(gicr_base, irq_num); gicr_set_igrpmodr0(gicr_base, irq_num);
else else
gicr_clr_igrpmodr0(gicr_base, irq_num); gicr_clr_igrpmodr0(gicr_base, irq_num);
......
...@@ -144,13 +144,13 @@ void gicv3_distif_init(void) ...@@ -144,13 +144,13 @@ void gicv3_distif_init(void)
gicv3_secure_spis_configure(driver_data->gicd_base, gicv3_secure_spis_configure(driver_data->gicd_base,
driver_data->g1s_interrupt_num, driver_data->g1s_interrupt_num,
driver_data->g1s_interrupt_array, driver_data->g1s_interrupt_array,
INT_TYPE_G1S); INTR_GROUP1S);
/* Configure the G0 SPIs */ /* Configure the G0 SPIs */
gicv3_secure_spis_configure(driver_data->gicd_base, gicv3_secure_spis_configure(driver_data->gicd_base,
driver_data->g0_interrupt_num, driver_data->g0_interrupt_num,
driver_data->g0_interrupt_array, driver_data->g0_interrupt_array,
INT_TYPE_G0); INTR_GROUP0);
/* Enable the secure SPIs now that they have been configured */ /* Enable the secure SPIs now that they have been configured */
gicd_set_ctlr(driver_data->gicd_base, gicd_set_ctlr(driver_data->gicd_base,
...@@ -186,13 +186,13 @@ void gicv3_rdistif_init(unsigned int proc_num) ...@@ -186,13 +186,13 @@ void gicv3_rdistif_init(unsigned int proc_num)
gicv3_secure_ppi_sgi_configure(gicr_base, gicv3_secure_ppi_sgi_configure(gicr_base,
driver_data->g1s_interrupt_num, driver_data->g1s_interrupt_num,
driver_data->g1s_interrupt_array, driver_data->g1s_interrupt_array,
INT_TYPE_G1S); INTR_GROUP1S);
/* Configure the G0 SGIs/PPIs */ /* Configure the G0 SGIs/PPIs */
gicv3_secure_ppi_sgi_configure(gicr_base, gicv3_secure_ppi_sgi_configure(gicr_base,
driver_data->g0_interrupt_num, driver_data->g0_interrupt_num,
driver_data->g0_interrupt_array, driver_data->g0_interrupt_array,
INT_TYPE_G0); INTR_GROUP0);
} }
/******************************************************************************* /*******************************************************************************
...@@ -332,9 +332,9 @@ unsigned int gicv3_get_pending_interrupt_type(void) ...@@ -332,9 +332,9 @@ unsigned int gicv3_get_pending_interrupt_type(void)
* this interrupt has been configured under by the interrupt controller i.e. * this interrupt has been configured under by the interrupt controller i.e.
* group0 or group1 Secure / Non Secure. The return value can be one of the * group0 or group1 Secure / Non Secure. The return value can be one of the
* following : * following :
* INT_TYPE_G0 : The interrupt type is a Secure Group 0 interrupt * INTR_GROUP0 : The interrupt type is a Secure Group 0 interrupt
* INT_TYPE_G1S : The interrupt type is a Secure Group 1 secure interrupt * INTR_GROUP1S : The interrupt type is a Secure Group 1 secure interrupt
* INT_TYPE_G1NS: The interrupt type is a Secure Group 1 non secure * INTR_GROUP1NS: The interrupt type is a Secure Group 1 non secure
* interrupt. * interrupt.
******************************************************************************/ ******************************************************************************/
unsigned int gicv3_get_interrupt_type(unsigned int id, unsigned int gicv3_get_interrupt_type(unsigned int id,
...@@ -352,7 +352,7 @@ unsigned int gicv3_get_interrupt_type(unsigned int id, ...@@ -352,7 +352,7 @@ unsigned int gicv3_get_interrupt_type(unsigned int id,
/* All LPI interrupts are Group 1 non secure */ /* All LPI interrupts are Group 1 non secure */
if (id >= MIN_LPI_ID) if (id >= MIN_LPI_ID)
return INT_TYPE_G1NS; return INTR_GROUP1NS;
if (id < MIN_SPI_ID) { if (id < MIN_SPI_ID) {
assert(driver_data->rdistif_base_addrs); assert(driver_data->rdistif_base_addrs);
...@@ -370,12 +370,12 @@ unsigned int gicv3_get_interrupt_type(unsigned int id, ...@@ -370,12 +370,12 @@ unsigned int gicv3_get_interrupt_type(unsigned int id,
* interrupt * interrupt
*/ */
if (igroup) if (igroup)
return INT_TYPE_G1NS; return INTR_GROUP1NS;
/* If the GRPMOD bit is set, then it is a Group 1 Secure interrupt */ /* If the GRPMOD bit is set, then it is a Group 1 Secure interrupt */
if (grpmodr) if (grpmodr)
return INT_TYPE_G1S; return INTR_GROUP1S;
/* Else it is a Group 0 Secure interrupt */ /* Else it is a Group 0 Secure interrupt */
return INT_TYPE_G0; return INTR_GROUP0;
} }
...@@ -63,6 +63,10 @@ ...@@ -63,6 +63,10 @@
#define INTR_NS_VALID_RM0 0x0 #define INTR_NS_VALID_RM0 0x0
/* Routed to EL1/EL2 from NS and to EL3 from Secure */ /* Routed to EL1/EL2 from NS and to EL3 from Secure */
#define INTR_NS_VALID_RM1 0x1 #define INTR_NS_VALID_RM1 0x1
/* Routed to EL3 from NS. Taken to S-EL1 from Secure and handed over to EL3 */
#define INTR_EL3_VALID_RM0 0x2
/* Routed to EL3 from NS and Secure */
#define INTR_EL3_VALID_RM1 0x3
/* This is the default routing model */ /* This is the default routing model */
#define INTR_DEFAULT_RM 0x0 #define INTR_DEFAULT_RM 0x0
...@@ -87,12 +91,16 @@ ...@@ -87,12 +91,16 @@
* of interrupt. If the model does not match one of the valid masks * of interrupt. If the model does not match one of the valid masks
* -EINVAL is returned. * -EINVAL is returned.
******************************************************************************/ ******************************************************************************/
#define validate_sel1_interrupt_rm(x) (x == INTR_SEL1_VALID_RM0 ? 0 : \ #define validate_sel1_interrupt_rm(x) ((x) == INTR_SEL1_VALID_RM0 ? 0 : \
(x == INTR_SEL1_VALID_RM1 ? 0 :\ ((x) == INTR_SEL1_VALID_RM1 ? 0 :\
-EINVAL))
#define validate_ns_interrupt_rm(x) ((x) == INTR_NS_VALID_RM0 ? 0 : \
((x) == INTR_NS_VALID_RM1 ? 0 :\
-EINVAL)) -EINVAL))
#define validate_ns_interrupt_rm(x) (x == INTR_NS_VALID_RM0 ? 0 : \ #define validate_el3_interrupt_rm(x) ((x) == INTR_EL3_VALID_RM0 ? 0 : \
(x == INTR_NS_VALID_RM1 ? 0 :\ ((x) == INTR_EL3_VALID_RM1 ? 0 :\
-EINVAL)) -EINVAL))
/******************************************************************************* /*******************************************************************************
......
...@@ -45,12 +45,12 @@ ...@@ -45,12 +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
#define TSP_EL3_FIQ 0xf2000007
/* 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
...@@ -63,7 +63,7 @@ ...@@ -63,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
...@@ -115,7 +115,7 @@ typedef struct tsp_vectors { ...@@ -115,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;
......
...@@ -35,9 +35,9 @@ ...@@ -35,9 +35,9 @@
* GICv3 miscellaneous definitions * GICv3 miscellaneous definitions
******************************************************************************/ ******************************************************************************/
/* Interrupt group definitions */ /* Interrupt group definitions */
#define INT_TYPE_G1S 0 #define INTR_GROUP1S 0
#define INT_TYPE_G0 1 #define INTR_GROUP0 1
#define INT_TYPE_G1NS 2 #define INTR_GROUP1NS 2
/* Interrupt IDs reported by the HPPIR and IAR registers */ /* Interrupt IDs reported by the HPPIR and IAR registers */
#define PENDING_G1S_INTID 1020 #define PENDING_G1S_INTID 1020
......
...@@ -31,12 +31,21 @@ ...@@ -31,12 +31,21 @@
#define __ARM_MACROS_S__ #define __ARM_MACROS_S__
#include <cci.h> #include <cci.h>
#include <gic_v2.h> #include <gic_common.h>
#include <gicv2.h>
#include <gicv3.h>
#include <platform_def.h> #include <platform_def.h>
.section .rodata.gic_reg_name, "aS" .section .rodata.gic_reg_name, "aS"
/* Applicable only to GICv2 and GICv3 with SRE disabled (legacy mode) */
gicc_regs: gicc_regs:
.asciz "gicc_hppir", "gicc_ahppir", "gicc_ctlr", "" .asciz "gicc_hppir", "gicc_ahppir", "gicc_ctlr", ""
/* Applicable only to GICv3 with SRE enabled */
icc_regs:
.asciz "icc_hppir0_el1", "icc_hppir1_el1", "icc_ctlr_el3", ""
/* Registers common to both GICv2 and GICv3 */
gicd_pend_reg: gicd_pend_reg:
.asciz "gicd_ispendr regs (Offsets 0x200 - 0x278)\n" \ .asciz "gicd_ispendr regs (Offsets 0x200 - 0x278)\n" \
" Offset:\t\t\tvalue\n" " Offset:\t\t\tvalue\n"
...@@ -54,6 +63,28 @@ spacer: ...@@ -54,6 +63,28 @@ spacer:
* --------------------------------------------- * ---------------------------------------------
*/ */
.macro arm_print_gic_regs .macro arm_print_gic_regs
/* Check for GICv3 system register access */
mrs x7, id_aa64pfr0_el1
ubfx x7, x7, #ID_AA64PFR0_GIC_SHIFT, #ID_AA64PFR0_GIC_WIDTH
cmp x7, #1
b.ne print_gicv2
/* Check for SRE enable */
mrs x8, ICC_SRE_EL3
tst x8, #ICC_SRE_SRE_BIT
b.eq print_gicv2
/* Load the icc reg list to x6 */
adr x6, icc_regs
/* Load the icc regs to gp regs used by str_in_crash_buf_print */
mrs x8, ICC_HPPIR0_EL1
mrs x9, ICC_HPPIR1_EL1
mrs x10, ICC_CTLR_EL3
/* Store to the crash buf and print to console */
bl str_in_crash_buf_print
b print_gic_common
print_gicv2:
/* Load the gicc reg list to x6 */ /* Load the gicc reg list to x6 */
adr x6, gicc_regs adr x6, gicc_regs
/* Load the gicc regs to gp regs used by str_in_crash_buf_print */ /* Load the gicc regs to gp regs used by str_in_crash_buf_print */
...@@ -63,6 +94,7 @@ spacer: ...@@ -63,6 +94,7 @@ spacer:
/* Store to the crash buf and print to console */ /* Store to the crash buf and print to console */
bl str_in_crash_buf_print bl str_in_crash_buf_print
print_gic_common:
/* Print the GICD_ISPENDR regs */ /* Print the GICD_ISPENDR regs */
add x7, x16, #GICD_ISPENDR add x7, x16, #GICD_ISPENDR
adr x4, gicd_pend_reg adr x4, gicd_pend_reg
......
...@@ -42,12 +42,6 @@ enum arm_config_flags { ...@@ -42,12 +42,6 @@ enum arm_config_flags {
}; };
typedef struct arm_config { typedef struct arm_config {
uintptr_t gicd_base;
uintptr_t gicc_base;
uintptr_t gich_base;
uintptr_t gicv_base;
unsigned int max_aff0;
unsigned int max_aff1;
unsigned long flags; unsigned long flags;
} arm_config_t; } arm_config_t;
......
...@@ -135,6 +135,22 @@ ...@@ -135,6 +135,22 @@
#define ARM_IRQ_SEC_SGI_6 14 #define ARM_IRQ_SEC_SGI_6 14
#define ARM_IRQ_SEC_SGI_7 15 #define ARM_IRQ_SEC_SGI_7 15
/*
* Define a list of Group 1 Secure and Group 0 interrupts as per GICv3
* terminology. On a GICv2 system or mode, the lists will be merged and treated
* as Group 0 interrupts.
*/
#define ARM_G1S_IRQS ARM_IRQ_SEC_PHY_TIMER, \
ARM_IRQ_SEC_SGI_1, \
ARM_IRQ_SEC_SGI_2, \
ARM_IRQ_SEC_SGI_3, \
ARM_IRQ_SEC_SGI_4, \
ARM_IRQ_SEC_SGI_5, \
ARM_IRQ_SEC_SGI_7
#define ARM_G0_IRQS ARM_IRQ_SEC_SGI_0, \
ARM_IRQ_SEC_SGI_6
#define ARM_SHARED_RAM_ATTR ((PLAT_ARM_SHARED_RAM_CACHED ? \ #define ARM_SHARED_RAM_ATTR ((PLAT_ARM_SHARED_RAM_CACHED ? \
MT_MEMORY : MT_DEVICE) \ MT_MEMORY : MT_DEVICE) \
| MT_RW | MT_SECURE) | MT_RW | MT_SECURE)
......
...@@ -37,7 +37,6 @@ ...@@ -37,7 +37,6 @@
#include <stdint.h> #include <stdint.h>
#include <xlat_tables.h> #include <xlat_tables.h>
/* /*
* Extern declarations common to ARM standard platforms * Extern declarations common to ARM standard platforms
*/ */
...@@ -179,7 +178,11 @@ void arm_tsp_early_platform_setup(void); ...@@ -179,7 +178,11 @@ void arm_tsp_early_platform_setup(void);
/* /*
* Mandatory functions required in ARM standard platforms * Mandatory functions required in ARM standard platforms
*/ */
void plat_arm_gic_driver_init(void);
void plat_arm_gic_init(void); void plat_arm_gic_init(void);
void plat_arm_gic_cpuif_enable(void);
void plat_arm_gic_cpuif_disable(void);
void plat_arm_gic_pcpu_init(void);
void plat_arm_security_setup(void); void plat_arm_security_setup(void);
void plat_arm_pwrc_setup(void); void plat_arm_pwrc_setup(void);
......
...@@ -41,8 +41,8 @@ ...@@ -41,8 +41,8 @@
* --------------------------------------------- * ---------------------------------------------
*/ */
.macro plat_print_gic_regs .macro plat_print_gic_regs
mov_imm x16, PLAT_CSS_GICD_BASE mov_imm x16, PLAT_ARM_GICD_BASE
mov_imm x17, PLAT_CSS_GICC_BASE mov_imm x17, PLAT_ARM_GICC_BASE
arm_print_gic_regs arm_print_gic_regs
.endm .endm
......
...@@ -60,6 +60,16 @@ ...@@ -60,6 +60,16 @@
#define CSS_IRQ_TZ_WDOG 86 #define CSS_IRQ_TZ_WDOG 86
#define CSS_IRQ_SEC_SYS_TIMER 91 #define CSS_IRQ_SEC_SYS_TIMER 91
/*
* Define a list of Group 1 Secure interrupts as per GICv3 terminology. On a
* GICv2 system or mode, the interrupts will be treated as Group 0 interrupts.
*/
#define CSS_G1S_IRQS CSS_IRQ_MHU, \
CSS_IRQ_GPU_SMMU_0, \
CSS_IRQ_TZC, \
CSS_IRQ_TZ_WDOG, \
CSS_IRQ_SEC_SYS_TIMER
/* /*
* SCP <=> AP boot configuration * SCP <=> AP boot configuration
* *
......
...@@ -30,14 +30,23 @@ ...@@ -30,14 +30,23 @@
#include <arm_config.h> #include <arm_config.h>
#include <arm_def.h> #include <arm_def.h>
#include <arm_gic.h>
#include <cci.h> #include <cci.h>
#include <debug.h> #include <debug.h>
#include <gicv2.h>
#include <mmio.h> #include <mmio.h>
#include <plat_arm.h> #include <plat_arm.h>
#include <v2m_def.h> #include <v2m_def.h>
#include "../fvp_def.h" #include "../fvp_def.h"
#if (FVP_USE_GIC_DRIVER == FVP_GICV2)
extern gicv2_driver_data_t arm_gic_data;
#endif
/* Defines for GIC Driver build time selection */
#define FVP_GICV2 1
#define FVP_GICV3 2
#define FVP_GICV3_LEGACY 3
/******************************************************************************* /*******************************************************************************
* arm_config holds the characteristics of the differences between the three FVP * arm_config holds the characteristics of the differences between the three FVP
* platforms (Base, A53_A57 & Foundation). It will be populated during cold boot * platforms (Base, A53_A57 & Foundation). It will be populated during cold boot
...@@ -110,33 +119,6 @@ const mmap_region_t plat_arm_mmap[] = { ...@@ -110,33 +119,6 @@ const mmap_region_t plat_arm_mmap[] = {
ARM_CASSERT_MMAP ARM_CASSERT_MMAP
#if IMAGE_BL31 || IMAGE_BL32
/* Array of secure interrupts to be configured by the gic driver */
const unsigned int irq_sec_array[] = {
ARM_IRQ_SEC_PHY_TIMER,
ARM_IRQ_SEC_SGI_0,
ARM_IRQ_SEC_SGI_1,
ARM_IRQ_SEC_SGI_2,
ARM_IRQ_SEC_SGI_3,
ARM_IRQ_SEC_SGI_4,
ARM_IRQ_SEC_SGI_5,
ARM_IRQ_SEC_SGI_6,
ARM_IRQ_SEC_SGI_7,
FVP_IRQ_TZ_WDOG,
FVP_IRQ_SEC_SYS_TIMER
};
void plat_arm_gic_init(void)
{
arm_gic_init(arm_config.gicc_base,
arm_config.gicd_base,
BASE_GICR_BASE,
irq_sec_array,
ARRAY_SIZE(irq_sec_array));
}
#endif
/******************************************************************************* /*******************************************************************************
* A single boot loader stack is expected to work on both the Foundation FVP * A single boot loader stack is expected to work on both the Foundation FVP
* models and the two flavours of the Base FVP models (AEMv8 & Cortex). The * models and the two flavours of the Base FVP models (AEMv8 & Cortex). The
...@@ -165,16 +147,28 @@ void fvp_config_setup(void) ...@@ -165,16 +147,28 @@ void fvp_config_setup(void)
*/ */
switch (bld) { switch (bld) {
case BLD_GIC_VE_MMAP: case BLD_GIC_VE_MMAP:
arm_config.gicd_base = VE_GICD_BASE; #if IMAGE_BL31 || IMAGE_BL32
arm_config.gicc_base = VE_GICC_BASE; #if FVP_USE_GIC_DRIVER == FVP_GICV2
arm_config.gich_base = VE_GICH_BASE; /*
arm_config.gicv_base = VE_GICV_BASE; * If the FVP implements the VE compatible memory map, then the
* GICv2 driver must be included in the build. Update the platform
* data with the correct GICv2 base addresses before it is used
* to initialise the driver.
*
* This update of platform data is temporary and will be removed
* once VE memory map for FVP is no longer supported by Trusted
* Firmware.
*/
arm_gic_data.gicd_base = VE_GICD_BASE;
arm_gic_data.gicc_base = VE_GICC_BASE;
#else
ERROR("Only GICv2 driver supported for VE memory map\n");
panic();
#endif /* __FVP_USE_GIC_DRIVER == FVP_GICV2__ */
#endif /* __IMAGE_BL31 || IMAGE_BL32__ */
break; break;
case BLD_GIC_A53A57_MMAP: case BLD_GIC_A53A57_MMAP:
arm_config.gicd_base = BASE_GICD_BASE;
arm_config.gicc_base = BASE_GICC_BASE;
arm_config.gich_base = BASE_GICH_BASE;
arm_config.gicv_base = BASE_GICV_BASE;
break; break;
default: default:
ERROR("Unsupported board build %x\n", bld); ERROR("Unsupported board build %x\n", bld);
...@@ -187,8 +181,6 @@ void fvp_config_setup(void) ...@@ -187,8 +181,6 @@ void fvp_config_setup(void)
*/ */
switch (hbi) { switch (hbi) {
case HBI_FOUNDATION_FVP: case HBI_FOUNDATION_FVP:
arm_config.max_aff0 = 4;
arm_config.max_aff1 = 1;
arm_config.flags = 0; arm_config.flags = 0;
/* /*
...@@ -206,8 +198,6 @@ void fvp_config_setup(void) ...@@ -206,8 +198,6 @@ void fvp_config_setup(void)
} }
break; break;
case HBI_BASE_FVP: case HBI_BASE_FVP:
arm_config.max_aff0 = 4;
arm_config.max_aff1 = 2;
arm_config.flags |= ARM_CONFIG_BASE_MMAP | arm_config.flags |= ARM_CONFIG_BASE_MMAP |
ARM_CONFIG_HAS_CCI | ARM_CONFIG_HAS_TZC; ARM_CONFIG_HAS_CCI | ARM_CONFIG_HAS_TZC;
......
...@@ -30,7 +30,8 @@ ...@@ -30,7 +30,8 @@
#include <arch.h> #include <arch.h>
#include <asm_macros.S> #include <asm_macros.S>
#include <gic_v2.h> #include <gicv2.h>
#include <gicv3.h>
#include <platform_def.h> #include <platform_def.h>
#include <v2m_def.h> #include <v2m_def.h>
#include "../drivers/pwrc/fvp_pwrc.h" #include "../drivers/pwrc/fvp_pwrc.h"
...@@ -74,9 +75,26 @@ func plat_secondary_cold_boot_setup ...@@ -74,9 +75,26 @@ func plat_secondary_cold_boot_setup
str w0, [x1, #PPOFFR_OFF] str w0, [x1, #PPOFFR_OFF]
/* --------------------------------------------- /* ---------------------------------------------
* Deactivate the gic cpu interface as well * Disable GIC bypass as well
* --------------------------------------------- * ---------------------------------------------
*/ */
/* Check for GICv3 system register access */
mrs x0, id_aa64pfr0_el1
ubfx x0, x0, #ID_AA64PFR0_GIC_SHIFT, #ID_AA64PFR0_GIC_WIDTH
cmp x0, #1
b.ne gicv2_bypass_disable
/* Check for SRE enable */
mrs x1, ICC_SRE_EL3
tst x1, #ICC_SRE_SRE_BIT
b.eq gicv2_bypass_disable
mrs x2, ICC_SRE_EL3
orr x2, x2, #(ICC_SRE_DIB_BIT | ICC_SRE_DFB_BIT)
msr ICC_SRE_EL3, x2
b secondary_cold_boot_wait
gicv2_bypass_disable:
ldr x0, =VE_GICC_BASE ldr x0, =VE_GICC_BASE
ldr x1, =BASE_GICC_BASE ldr x1, =BASE_GICC_BASE
fvp_choose_gicmmap x0, x1, x2, w2, x1 fvp_choose_gicmmap x0, x1, x2, w2, x1
...@@ -84,6 +102,7 @@ func plat_secondary_cold_boot_setup ...@@ -84,6 +102,7 @@ func plat_secondary_cold_boot_setup
orr w0, w0, #(IRQ_BYP_DIS_GRP0 | FIQ_BYP_DIS_GRP0) orr w0, w0, #(IRQ_BYP_DIS_GRP0 | FIQ_BYP_DIS_GRP0)
str w0, [x1, #GICC_CTLR] str w0, [x1, #GICC_CTLR]
secondary_cold_boot_wait:
/* --------------------------------------------- /* ---------------------------------------------
* There is no sane reason to come out of this * There is no sane reason to come out of this
* wfi so panic if we do. This cpu will be pow- * wfi so panic if we do. This cpu will be pow-
......
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