diff options
author | Jeenu Viswambharan <jeenu.viswambharan@arm.com> | 2017-09-22 08:32:09 +0100 |
---|---|---|
committer | Jeenu Viswambharan <jeenu.viswambharan@arm.com> | 2017-10-16 16:50:02 +0100 |
commit | 8db978b5a8606a658c65b16fab7edd7a17c7c940 (patch) | |
tree | bfef9510b0bbb1f8560a45a7ef760217d49ddab4 /drivers | |
parent | 74dce7fa6e42cab3aa54a9543e4a546c1450b2ae (diff) |
GIC: Add API to raise secure SGI
API documentation updated.
Change-Id: I129725059299af6cc612bafa8d74817f779d7c4f
Signed-off-by: Jeenu Viswambharan <jeenu.viswambharan@arm.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/arm/gic/v2/gicv2_main.c | 35 | ||||
-rw-r--r-- | drivers/arm/gic/v2/gicv2_private.h | 8 | ||||
-rw-r--r-- | drivers/arm/gic/v3/gicv3_main.c | 39 |
3 files changed, 82 insertions, 0 deletions
diff --git a/drivers/arm/gic/v2/gicv2_main.c b/drivers/arm/gic/v2/gicv2_main.c index 8048c6a7..b59e4586 100644 --- a/drivers/arm/gic/v2/gicv2_main.c +++ b/drivers/arm/gic/v2/gicv2_main.c @@ -368,3 +368,38 @@ void gicv2_set_interrupt_type(unsigned int id, unsigned int type) } spin_unlock(&gic_lock); } + +/******************************************************************************* + * This function raises the specified SGI to requested targets. + * + * The proc_num parameter must be the linear index of the target PE in the + * system. + ******************************************************************************/ +void gicv2_raise_sgi(int sgi_num, int proc_num) +{ + unsigned int sgir_val, target; + + assert(driver_data); + assert(proc_num < GICV2_MAX_TARGET_PE); + assert(driver_data->gicd_base); + + /* + * Target masks array must have been supplied, and the core position + * should be valid. + */ + assert(driver_data->target_masks); + assert(proc_num < driver_data->target_masks_num); + + /* Don't raise SGI if the mask hasn't been populated */ + target = driver_data->target_masks[proc_num]; + assert(target != 0); + + sgir_val = GICV2_SGIR_VALUE(SGIR_TGT_SPECIFIC, target, sgi_num); + + /* + * Ensure that any shared variable updates depending on out of band + * interrupt trigger are observed before raising SGI. + */ + dsbishst(); + gicd_write_sgir(driver_data->gicd_base, sgir_val); +} diff --git a/drivers/arm/gic/v2/gicv2_private.h b/drivers/arm/gic/v2/gicv2_private.h index 7703cbe5..915fc3a7 100644 --- a/drivers/arm/gic/v2/gicv2_private.h +++ b/drivers/arm/gic/v2/gicv2_private.h @@ -32,6 +32,14 @@ static inline unsigned int gicd_read_pidr2(uintptr_t base) } /******************************************************************************* + * GIC Distributor interface accessors for writing entire registers + ******************************************************************************/ +static inline void gicd_write_sgir(uintptr_t base, unsigned int val) +{ + mmio_write_32(base + GICD_SGIR, val); +} + +/******************************************************************************* * GIC CPU interface accessors for reading entire registers ******************************************************************************/ diff --git a/drivers/arm/gic/v3/gicv3_main.c b/drivers/arm/gic/v3/gicv3_main.c index 04b47129..a5067322 100644 --- a/drivers/arm/gic/v3/gicv3_main.c +++ b/drivers/arm/gic/v3/gicv3_main.c @@ -960,3 +960,42 @@ void gicv3_set_interrupt_type(unsigned int id, unsigned int proc_num, spin_unlock(&gic_lock); } } + +/******************************************************************************* + * This function raises the specified Secure Group 0 SGI. + * + * The target parameter must be a valid MPIDR in the system. + ******************************************************************************/ +void gicv3_raise_secure_g0_sgi(int sgi_num, u_register_t target) +{ + unsigned int tgt, aff3, aff2, aff1, aff0; + uint64_t sgi_val; + + /* Verify interrupt number is in the SGI range */ + assert((sgi_num >= MIN_SGI_ID) && (sgi_num < MIN_PPI_ID)); + + /* Extract affinity fields from target */ + aff0 = MPIDR_AFFLVL0_VAL(target); + aff1 = MPIDR_AFFLVL1_VAL(target); + aff2 = MPIDR_AFFLVL2_VAL(target); + aff3 = MPIDR_AFFLVL3_VAL(target); + + /* + * Make target list from affinity 0, and ensure GICv3 SGI can target + * this PE. + */ + assert(aff0 < GICV3_MAX_SGI_TARGETS); + tgt = BIT(aff0); + + /* Raise SGI to PE specified by its affinity */ + sgi_val = GICV3_SGIR_VALUE(aff3, aff2, aff1, sgi_num, SGIR_IRM_TO_AFF, + tgt); + + /* + * Ensure that any shared variable updates depending on out of band + * interrupt trigger are observed before raising SGI. + */ + dsbishst(); + write_icc_sgi0r_el1(sgi_val); + isb(); +} |