summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorJeenu Viswambharan <jeenu.viswambharan@arm.com>2017-09-22 08:32:09 +0100
committerJeenu Viswambharan <jeenu.viswambharan@arm.com>2017-10-16 16:50:02 +0100
commit8db978b5a8606a658c65b16fab7edd7a17c7c940 (patch)
treebfef9510b0bbb1f8560a45a7ef760217d49ddab4 /drivers
parent74dce7fa6e42cab3aa54a9543e4a546c1450b2ae (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.c35
-rw-r--r--drivers/arm/gic/v2/gicv2_private.h8
-rw-r--r--drivers/arm/gic/v3/gicv3_main.c39
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();
+}