Merge changes from topic "bk/gicv5_full"
* changes:
feat(realm): set the PMU IRQ number depending on GIC version
feat(fvp): set the timer IRQ number depending on GIC version
refactor(gic): defer IRQ handler management to the GIC driver
refactor(gic): make the concept of SGI generic
feat(gicv5): add a GICv5 driver
feat(gicv5): add GICv5 instructions and register accessors
diff --git a/drivers/arm/gic/aarch64/gic_v5.c b/drivers/arm/gic/aarch64/gic_v5.c
new file mode 100644
index 0000000..74fc590
--- /dev/null
+++ b/drivers/arm/gic/aarch64/gic_v5.c
@@ -0,0 +1,445 @@
+/*
+ * Copyright (c) 2025, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <arch.h>
+#include <arch_features.h>
+#include <arch_helpers.h>
+#include <drivers/arm/gic_v5.h>
+#include <platform.h>
+
+#include <platform_def.h>
+
+/*
+ * Data structure to store the GIC per CPU context before entering
+ * a suspend to powerdown (with loss of context).
+ */
+struct gicv5_pcpu_ctx {
+ /* CPU IF registers. Only those currently in use */
+ u_register_t icc_cr0_el1;
+ /* PPI registers. We don't touch handling mode. */
+ u_register_t icc_ppi_enabler[2];
+ u_register_t icc_ppi_xpendr[2];
+ u_register_t icc_ppi_priorityr[16];
+};
+
+static uintptr_t irs_base;
+static struct gicv5_pcpu_ctx cpu_ctx[PLATFORM_CORE_COUNT];
+
+/* CPU MPIDR != GICv5 IAFFID. This holds the mapping, initialised on CPU_ON. */
+static uint16_t iaffids[PLATFORM_CORE_COUNT];
+
+/* the IST is a power of 2 since that's what goes in IRS_IST_CFGR.LPI_ID_BITS */
+struct l2_iste ist[next_power_of_2(PLATFORM_CORE_COUNT) * IRQ_NUM_SGIS];
+
+static ppi_desc ppi_desc_table[PLATFORM_CORE_COUNT][GICV5_MAX_PPI_ID];
+static spi_desc spi_desc_table[PLAT_MAX_SPI_OFFSET_ID];
+static spi_desc lpi_desc_table[PLATFORM_CORE_COUNT * IRQ_NUM_SGIS];
+
+static inline uint8_t log2(uint32_t num)
+{
+ return (31 - __builtin_clz(num));
+}
+
+static inline bool is_interrupt(unsigned int interrupt_id)
+{
+ unsigned int_type = EXTRACT(INT_TYPE, interrupt_id);
+
+ return int_type == INT_PPI || int_type == INT_LPI || int_type == INT_SPI;
+}
+
+static inline u_register_t read_icc_ppi_priorityrn(unsigned n)
+{
+ switch (n) {
+ case 0:
+ return read_icc_ppi_priorityr0();
+ case 1:
+ return read_icc_ppi_priorityr1();
+ case 2:
+ return read_icc_ppi_priorityr2();
+ case 3:
+ return read_icc_ppi_priorityr3();
+ case 4:
+ return read_icc_ppi_priorityr4();
+ case 5:
+ return read_icc_ppi_priorityr5();
+ case 6:
+ return read_icc_ppi_priorityr6();
+ case 7:
+ return read_icc_ppi_priorityr7();
+ case 8:
+ return read_icc_ppi_priorityr8();
+ case 9:
+ return read_icc_ppi_priorityr9();
+ case 10:
+ return read_icc_ppi_priorityr10();
+ case 11:
+ return read_icc_ppi_priorityr11();
+ case 12:
+ return read_icc_ppi_priorityr12();
+ case 13:
+ return read_icc_ppi_priorityr13();
+ case 14:
+ return read_icc_ppi_priorityr14();
+ case 15:
+ return read_icc_ppi_priorityr15();
+ default:
+ panic();
+ }
+}
+
+static inline void write_icc_ppi_priorityrn(unsigned n, u_register_t val)
+{
+ switch (n) {
+ case 0:
+ return write_icc_ppi_priorityr0(val);
+ case 1:
+ return write_icc_ppi_priorityr1(val);
+ case 2:
+ return write_icc_ppi_priorityr2(val);
+ case 3:
+ return write_icc_ppi_priorityr3(val);
+ case 4:
+ return write_icc_ppi_priorityr4(val);
+ case 5:
+ return write_icc_ppi_priorityr5(val);
+ case 6:
+ return write_icc_ppi_priorityr6(val);
+ case 7:
+ return write_icc_ppi_priorityr7(val);
+ case 8:
+ return write_icc_ppi_priorityr8(val);
+ case 9:
+ return write_icc_ppi_priorityr9(val);
+ case 10:
+ return write_icc_ppi_priorityr10(val);
+ case 11:
+ return write_icc_ppi_priorityr11(val);
+ case 12:
+ return write_icc_ppi_priorityr12(val);
+ case 13:
+ return write_icc_ppi_priorityr13(val);
+ case 14:
+ return write_icc_ppi_priorityr14(val);
+ case 15:
+ return write_icc_ppi_priorityr15(val);
+ default:
+ panic();
+ }
+}
+
+bool is_gicv5_mode(void)
+{
+ return is_feat_gcie_supported();
+}
+
+bool gicv5_is_irq_spi(unsigned int irq_num)
+{
+ return EXTRACT(INT_TYPE, irq_num) == INT_SPI;
+}
+
+void gicv5_enable_cpuif(void)
+{
+ write_icc_cr0_el1(read_icc_cr0_el1() | ICC_CR0_EL1_EN_BIT);
+ /* make sure effects are visible */
+ isb();
+}
+
+void gicv5_setup_cpuif(void)
+{
+ iaffids[platform_get_core_pos(read_mpidr_el1())] = read_icc_iaffidr_el1();
+
+ write_icc_pcr_el1(GICV5_IDLE_PRIORITY);
+
+ gicv5_enable_cpuif();
+}
+
+void gicv5_disable_cpuif(void)
+{
+ write_icc_cr0_el1(read_icc_cr0_el1() & ~ICC_CR0_EL1_EN_BIT);
+ /* make sure effects are visible */
+ isb();
+}
+
+void gicv5_save_cpuif_context(void)
+{
+ unsigned int core_pos = platform_get_core_pos(read_mpidr_el1());
+
+ cpu_ctx[core_pos].icc_cr0_el1 = read_icc_cr0_el1();
+ cpu_ctx[core_pos].icc_ppi_enabler[0] = read_icc_ppi_enabler0();
+ cpu_ctx[core_pos].icc_ppi_enabler[1] = read_icc_ppi_enabler1();
+
+ cpu_ctx[core_pos].icc_ppi_xpendr[0] = read_icc_ppi_spendr0();
+ cpu_ctx[core_pos].icc_ppi_xpendr[1] = read_icc_ppi_spendr1();
+
+ for (int i = 0; i < 15; i++) {
+ cpu_ctx[core_pos].icc_ppi_priorityr[i] = read_icc_ppi_priorityrn(i);
+ }
+
+ /* Make sure all PPIs are inactive, i.e. not suspending mid interrupt */
+ assert(read_icc_ppi_sactiver0() == 0UL && read_icc_ppi_sactiver1() == 0UL);
+}
+
+void gicv5_restore_cpuif_context(void)
+{
+ unsigned int core_pos = platform_get_core_pos(read_mpidr_el1());
+
+ write_icc_ppi_enabler0(cpu_ctx[core_pos].icc_ppi_enabler[0]);
+ write_icc_ppi_enabler1(cpu_ctx[core_pos].icc_ppi_enabler[1]);
+
+ write_icc_ppi_spendr0(cpu_ctx[core_pos].icc_ppi_xpendr[0]);
+ write_icc_ppi_spendr1(cpu_ctx[core_pos].icc_ppi_xpendr[1]);
+ /* clear interrupts that shouldn't be pending */
+ write_icc_ppi_cpendr0(~cpu_ctx[core_pos].icc_ppi_xpendr[0]);
+ write_icc_ppi_cpendr1(~cpu_ctx[core_pos].icc_ppi_xpendr[1]);
+
+ for (int i = 0; i < 15; i++) {
+ write_icc_ppi_priorityrn(i, cpu_ctx[core_pos].icc_ppi_priorityr[i]);
+ }
+
+ /* don't bother saving it, just put the same value in */
+ write_icc_pcr_el1(GICV5_IDLE_PRIORITY);
+
+ write_icc_cr0_el1(cpu_ctx[core_pos].icc_cr0_el1);
+ /* make sure effects are visible */
+ isb();
+}
+
+void gicv5_set_priority(unsigned int interrupt_id, unsigned int priority)
+{
+ unsigned irq_idx, irq_reg;
+ u_register_t priorityr;
+
+ assert(priority < (1UL << GICCDPRI_PRIORITY_WIDTH));
+ assert(is_interrupt(interrupt_id));
+
+ if (EXTRACT(INT_TYPE, interrupt_id) != INT_PPI) {
+ giccdpri(interrupt_id | INPLACE(GICCDPRI_PRIORITY, priority));
+ return;
+ }
+
+ /* it's a PPI, get rid of the INTR TYPE field */
+ interrupt_id = EXTRACT(INT_ID, interrupt_id);
+ irq_reg = interrupt_id / ICC_PPI_PRIORITYR_FIELD_NUM;
+ irq_idx = interrupt_id % ICC_PPI_PRIORITYR_FIELD_NUM;
+
+ priorityr = read_icc_ppi_priorityrn(irq_reg) &
+ ICC_PPI_PRIORITYR_FIELD_MASK <<
+ (irq_idx * ICC_PPI_PRIORITYR_FIELD_NUM);
+ write_icc_ppi_priorityrn(irq_reg, priorityr |
+ (priority << (irq_idx * ICC_PPI_PRIORITYR_FIELD_NUM)));
+}
+
+void gicv5_send_sgi(unsigned int sgi_id, unsigned int core_pos)
+{
+ giccdpend(gicv5_get_sgi_num(sgi_id, core_pos) | GICCDPEND_PENDING_BIT);
+}
+
+void gicv5_set_intr_route(unsigned int interrupt_id, unsigned int core_pos)
+{
+ assert(is_interrupt(interrupt_id));
+
+ /* PPIs are local to the CPU, can't be rerouted */
+ if (EXTRACT(INT_TYPE, interrupt_id) == INT_PPI) {
+ return;
+ }
+
+ /*
+ * The expecation is that a core will be up (CPU_ON) before it gets
+ * targetted by interrupts. Otherwise the IAFFID isn't available yet
+ * and the interrupt will be misrouted.
+ */
+ assert(iaffids[core_pos] != 0 || core_pos == 0);
+ giccdaff(INPLACE(GICCDAFF_IAFFID, iaffids[core_pos]) | interrupt_id);
+
+ /* wait for the target to take effect so retargetting an already
+ * enabled interrupt ends up in the correct destination */
+ gsbsys();
+}
+
+void gicv5_intr_enable(unsigned int interrupt_id)
+{
+ unsigned int irq_idx;
+
+ assert(is_interrupt(interrupt_id));
+
+ if (EXTRACT(INT_TYPE, interrupt_id) != INT_PPI) {
+ giccden(interrupt_id);
+ return;
+ }
+
+ /* it's a PPI, get rid of the INTR TYPE field */
+ interrupt_id = EXTRACT(INT_ID, interrupt_id);
+ irq_idx = interrupt_id % ICC_PPI_ENABLER_FIELD_NUM;
+
+ if (interrupt_id / ICC_PPI_ENABLER_FIELD_NUM == 0) {
+ write_icc_ppi_enabler0(read_icc_ppi_enabler0() | (1UL << irq_idx));
+ } else {
+ write_icc_ppi_enabler1(read_icc_ppi_enabler1() | (1UL << irq_idx));
+ }
+}
+
+void gicv5_intr_disable(unsigned int interrupt_id)
+{
+ unsigned int irq_idx;
+
+ assert(is_interrupt(interrupt_id));
+
+ if (EXTRACT(INT_TYPE, interrupt_id) != INT_PPI) {
+ giccddis(interrupt_id);
+ /* wait for the interrupt to become disabled */
+ gsbsys();
+ return;
+ }
+
+ /* it's a PPI, get rid of the INTR TYPE field */
+ interrupt_id = EXTRACT(INT_ID, interrupt_id);
+ irq_idx = interrupt_id % ICC_PPI_ENABLER_FIELD_NUM;
+
+ if (interrupt_id / ICC_PPI_ENABLER_FIELD_NUM == 0) {
+ write_icc_ppi_enabler0(read_icc_ppi_enabler0() & ~(1UL << irq_idx));
+ } else {
+ write_icc_ppi_enabler1(read_icc_ppi_enabler1() & ~(1UL << irq_idx));
+ }
+}
+
+unsigned int gicv5_acknowledge_interrupt(void)
+{
+ u_register_t iar = gicrcdia();
+ assert((iar & GICRCDIA_VALID_BIT) != 0);
+
+ /* wait for the intr ack to complete (i.e. make it Active) and refetch
+ * instructions so they don't operate on anything stale */
+ gsback();
+ isb();
+
+ return iar & ~GICRCDIA_VALID_BIT;
+}
+
+unsigned int gicv5_is_intr_pending(unsigned int interrupt_id)
+{
+ u_register_t icsr;
+ u_register_t ppi_spendr;
+
+ assert(is_interrupt(interrupt_id));
+
+ if (EXTRACT(INT_TYPE, interrupt_id) != INT_PPI) {
+ /* request interrupt information */
+ giccdrcfg(interrupt_id);
+ /* wait for the register to update */
+ isb();
+ icsr = read_icc_icsr_el1();
+
+ /* interrupt is unreachable, something has gone wrong */
+ assert((icsr & ICC_ICSR_EL1_F_BIT) == 0);
+ return !!(icsr & ICC_ICSR_EL1_PENDING_BIT);
+ }
+
+ /* it's a PPI, get rid of the INTR TYPE field */
+ interrupt_id = EXTRACT(INT_ID, interrupt_id);
+
+ if (interrupt_id / ICC_PPI_XPENDR_FIELD_NUM == 0) {
+ ppi_spendr = read_icc_ppi_spendr0();
+ } else {
+ ppi_spendr = read_icc_ppi_spendr1();
+ }
+
+ return !!(ppi_spendr & BIT(interrupt_id % ICC_PPI_XPENDR_FIELD_NUM));
+}
+
+void gicv5_intr_clear(unsigned int interrupt_id)
+{
+ unsigned int irq_idx;
+
+ assert(is_interrupt(interrupt_id));
+
+ if (EXTRACT(INT_TYPE, interrupt_id) != INT_PPI) {
+ giccdpend(interrupt_id);
+ return;
+ }
+
+ /* it's a PPI, get rid of the INTR TYPE field */
+ interrupt_id = EXTRACT(INT_ID, interrupt_id);
+ irq_idx = interrupt_id % ICC_PPI_XPENDR_FIELD_NUM;
+
+ if (interrupt_id / ICC_PPI_XPENDR_FIELD_NUM == 0) {
+ write_icc_ppi_cpendr0(read_icc_ppi_cpendr0() | (1UL << irq_idx));
+ } else {
+ write_icc_ppi_cpendr1(read_icc_ppi_cpendr1() | (1UL << irq_idx));
+ }
+}
+
+void gicv5_end_of_interrupt(unsigned int raw_iar)
+{
+ giccddi(raw_iar);
+ giccdeoi();
+ /* no isb as we won't interact with the gic before the eret */
+}
+
+/* currently a single IRS is expected and an ITS/IWB are not used */
+void gicv5_setup(void)
+{
+#if ENABLE_ASSERTIONS
+ uint32_t irs_idr2 = read_IRS_IDR2(irs_base);
+#endif
+ uint8_t id_bits = log2(ARRAY_SIZE(ist));
+ /* min_id_bits <= log2(length(ist)) <= id_bits */
+ assert(EXTRACT(IRS_IDR2_MIN_LPI_ID_BITS, irs_idr2) <= id_bits);
+ assert(EXTRACT(IRS_IDR2_ID_BITS, irs_idr2) >= id_bits);
+
+ /* make sure all ISTEs aren't enabled */
+ memset(ist, 0x0, sizeof(ist));
+
+ /* write zeroes throughout except LPI_ID_Bits which is the lowest 5 bits */
+ write_IRS_IST_CFGR(irs_base, id_bits);
+ /* make the IST valid */
+ write_IRS_IST_BASER(irs_base,
+ (((uintptr_t) &ist) & MASK(IRS_IST_BASER_ADDR)) |
+ IRS_IST_BASER_VALID_BIT);
+ WAIT_FOR_IDLE(irs_base, IRS_IST_STATUSR);
+
+ /* enable the IRS */
+ write_IRS_CR0(irs_base, IRS_CR0_IRSEN_BIT);
+ WAIT_FOR_IDLE(irs_base, IRS_CR0);
+}
+
+uint32_t gicv5_get_sgi_num(uint32_t index, unsigned int core_pos)
+{
+ assert(index <= IRQ_NUM_SGIS);
+
+ return (core_pos * IRQ_NUM_SGIS + index) | INPLACE(INT_TYPE, INT_LPI);
+}
+
+irq_handler_t *gicv5_get_irq_handler(unsigned int irq_num)
+{
+ unsigned int linear_id;
+
+ if (EXTRACT(INT_TYPE, irq_num) == INT_PPI) {
+ linear_id = platform_get_core_pos(read_mpidr_el1());
+ return &ppi_desc_table[linear_id][EXTRACT(INT_ID, irq_num)].handler;
+ }
+
+ if (EXTRACT(INT_TYPE, irq_num) == INT_LPI) {
+ return &lpi_desc_table[EXTRACT(INT_ID, irq_num)].handler;
+ }
+
+ if (EXTRACT(INT_TYPE, irq_num) == INT_SPI) {
+ return &spi_desc_table[EXTRACT(INT_ID, irq_num)].handler;
+ }
+
+ /* Interrupt should have been handled */
+ panic();
+ return NULL;
+}
+
+void gicv5_init(uintptr_t irs_base_addr)
+{
+ irs_base = irs_base_addr;
+ memset(ppi_desc_table, 0, sizeof(ppi_desc_table));
+ memset(spi_desc_table, 0, sizeof(spi_desc_table));
+ memset(lpi_desc_table, 0, sizeof(lpi_desc_table));
+}
diff --git a/drivers/arm/gic/arm_gic.c b/drivers/arm/gic/arm_gic.c
index d3b2536..2f05a48 100644
--- a/drivers/arm/gic/arm_gic.c
+++ b/drivers/arm/gic/arm_gic.c
@@ -4,6 +4,8 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
+#include <stdbool.h>
+
#include <arch.h>
#include <arch_helpers.h>
#include <assert.h>
@@ -11,15 +13,32 @@
#include <drivers/arm/gic_v2v3_common.h>
#include <drivers/arm/gic_v2.h>
#include <drivers/arm/gic_v3.h>
-#include <stdbool.h>
+#include <drivers/arm/gic_v5.h>
/* Record whether a GICv3 was detected on the system */
static unsigned int gicv3_detected;
+static unsigned int gicv5_detected;
+static bool gic_done_init;
+
+int arm_gic_get_version(void)
+{
+ assert(gic_done_init);
+
+ if (gicv3_detected) {
+ return 3;
+ } else if (gicv5_detected) {
+ return 5;
+ } else {
+ return 2;
+ }
+}
void arm_gic_enable_interrupts_local(void)
{
if (gicv3_detected)
gicv3_enable_cpuif();
+ else if (gicv5_detected)
+ gicv5_enable_cpuif();
else
gicv2_enable_cpuif();
}
@@ -29,6 +48,8 @@
if (gicv3_detected) {
gicv3_probe_redistif_addr();
gicv3_setup_cpuif();
+ } else if (gicv5_detected) {
+ gicv5_setup_cpuif();
} else {
gicv2_probe_gic_cpu_id();
gicv2_setup_cpuif();
@@ -39,6 +60,8 @@
{
if (gicv3_detected)
gicv3_disable_cpuif();
+ else if (gicv5_detected)
+ gicv5_disable_cpuif();
else
gicv2_disable_cpuif();
}
@@ -47,6 +70,8 @@
{
if (gicv3_detected)
gicv3_save_cpuif_context();
+ else if (gicv5_detected)
+ gicv5_save_cpuif_context();
else
gicv2_save_cpuif_context();
}
@@ -55,16 +80,21 @@
{
if (gicv3_detected)
gicv3_restore_cpuif_context();
+ else if (gicv5_detected)
+ gicv5_restore_cpuif_context();
else
gicv2_restore_cpuif_context();
}
void arm_gic_save_context_global(void)
{
- if (gicv3_detected)
+ if (gicv3_detected) {
gicv3_save_sgi_ppi_context();
- else
+ } else if (gicv5_detected) {
+ /* NOP, done by EL3 */
+ } else {
gicv2_save_sgi_ppi_context();
+ }
}
void arm_gic_restore_context_global(void)
@@ -72,6 +102,8 @@
if (gicv3_detected) {
gicv3_setup_distif();
gicv3_restore_sgi_ppi_context();
+ } else if (gicv5_detected) {
+ /* NOP, done by EL3 */
} else {
gicv2_setup_distif();
gicv2_restore_sgi_ppi_context();
@@ -82,6 +114,8 @@
{
if (gicv3_detected)
gicv3_setup_distif();
+ else if (gicv5_detected)
+ gicv5_setup();
else
gicv2_setup_distif();
}
@@ -90,7 +124,11 @@
{
if (gicv3_detected)
return gicv3_get_ipriorityr(num);
- else
+ /* TODO only used for SDEI, currently not supported/ported */
+ else if (gicv5_detected) {
+ assert(0);
+ return 0;
+ } else
return gicv2_gicd_get_ipriorityr(num);
}
@@ -99,14 +137,27 @@
{
if (gicv3_detected)
gicv3_set_ipriorityr(num, priority);
+ else if (gicv5_detected)
+ gicv5_set_priority(num, priority);
else
gicv2_gicd_set_ipriorityr(num, priority);
}
+uint32_t arm_gic_get_sgi_num(uint32_t seq_id, unsigned int core_pos)
+{
+ if (gicv5_detected) {
+ return gicv5_get_sgi_num(seq_id, core_pos);
+ } else {
+ return gicv2v3_get_sgi_num(seq_id, core_pos);
+ }
+}
+
void arm_gic_send_sgi(unsigned int sgi_id, unsigned int core_pos)
{
if (gicv3_detected)
gicv3_send_sgi(sgi_id, core_pos);
+ else if (gicv5_detected)
+ gicv5_send_sgi(sgi_id, core_pos);
else
gicv2_send_sgi(sgi_id, core_pos);
}
@@ -115,6 +166,8 @@
{
if (gicv3_detected)
gicv3_set_intr_route(num, core_pos);
+ else if (gicv5_detected)
+ gicv5_set_intr_route(num, core_pos);
else
gicv2_set_itargetsr(num, core_pos);
}
@@ -123,7 +176,11 @@
{
if (gicv3_detected)
return gicv3_get_isenabler(num) != 0;
- else
+ /* TODO only used for SDEI, currently not supported/ported */
+ else if (gicv5_detected) {
+ assert(0);
+ return 0;
+ } else
return gicv2_gicd_get_isenabler(num) != 0;
}
@@ -131,6 +188,8 @@
{
if (gicv3_detected)
gicv3_set_isenabler(num);
+ else if (gicv5_detected)
+ gicv5_intr_enable(num);
else
gicv2_gicd_set_isenabler(num);
}
@@ -139,6 +198,8 @@
{
if (gicv3_detected)
gicv3_set_icenabler(num);
+ else if (gicv5_detected)
+ gicv5_intr_disable(num);
else
gicv2_gicd_set_icenabler(num);
}
@@ -150,6 +211,9 @@
if (gicv3_detected) {
*raw_iar = gicv3_acknowledge_interrupt();
return *raw_iar;
+ } else if (gicv5_detected) {
+ *raw_iar = gicv5_acknowledge_interrupt();
+ return *raw_iar;
} else {
*raw_iar = gicv2_gicc_read_iar();
return get_gicc_iar_intid(*raw_iar);
@@ -160,6 +224,8 @@
{
if (gicv3_detected)
return gicv3_get_ispendr(num);
+ else if (gicv5_detected)
+ return gicv5_is_intr_pending(num);
else
return gicv2_gicd_get_ispendr(num);
}
@@ -168,6 +234,8 @@
{
if (gicv3_detected)
gicv3_set_icpendr(num);
+ else if (gicv5_detected)
+ gicv5_intr_clear(num);
else
gicv2_gicd_set_icpendr(num);
}
@@ -176,28 +244,44 @@
{
if (gicv3_detected)
gicv3_end_of_interrupt(raw_iar);
+ else if (gicv5_detected)
+ gicv5_end_of_interrupt(raw_iar);
else
gicv2_gicc_write_eoir(raw_iar);
}
+void arm_gic_probe(void)
+{
+ if (is_gicv3_mode()) {
+ gicv3_detected = 1;
+ INFO("GICv3 mode detected\n");
+ } else if (is_gicv5_mode()) {
+ gicv5_detected = 1;
+ INFO("GICv5 mode detected\n");
+ } else {
+ INFO("GICv2 mode detected\n");
+ }
+
+ gic_done_init = true;
+}
+
+/* to not change the API, pretend the IRS is a distributor */
void arm_gic_init(uintptr_t gicc_base,
uintptr_t gicd_base,
uintptr_t gicr_base)
{
-
- if (is_gicv3_mode()) {
- gicv3_detected = 1;
+ if (gicv3_detected) {
gicv3_init(gicr_base, gicd_base);
+ } else if (gicv5_detected) {
+ gicv5_init(gicd_base);
} else {
gicv2_init(gicc_base, gicd_base);
}
-
- INFO("%s mode detected\n", (gicv3_detected) ?
- "GICv3" : "GICv2");
}
bool arm_gic_is_espi_supported(void)
{
+ /* TODO only used for FFA, currently not supported/ported on GICv5 */
if (!gicv3_detected) {
return false;
}
@@ -209,3 +293,21 @@
return false;
}
+
+irq_handler_t *arm_gic_get_irq_handler(unsigned int irq_num)
+{
+ if (gicv5_detected) {
+ return gicv5_get_irq_handler(irq_num);
+ } else {
+ return gicv2v3_get_irq_handler(irq_num);
+ }
+}
+
+bool arm_gic_is_irq_shared(unsigned int irq_num)
+{
+ if (gicv5_detected) {
+ return gicv5_is_irq_spi(irq_num);
+ } else {
+ return gicv2v3_is_irq_spi(irq_num);
+ }
+}
diff --git a/drivers/arm/gic/gic_v2.c b/drivers/arm/gic/gic_v2.c
index f5fdc44..4a93406 100644
--- a/drivers/arm/gic/gic_v2.c
+++ b/drivers/arm/gic/gic_v2.c
@@ -364,4 +364,6 @@
assert(!is_gicv3_mode());
gicc_base_addr = gicc_base;
gicd_base_addr = gicd_base;
+
+ gicv2v3_irq_setup();
}
diff --git a/drivers/arm/gic/gic_v2v3_common.c b/drivers/arm/gic/gic_v2v3_common.c
index 4eafa59..a929b92 100644
--- a/drivers/arm/gic/gic_v2v3_common.c
+++ b/drivers/arm/gic/gic_v2v3_common.c
@@ -11,6 +11,7 @@
#include <drivers/arm/gic_v2v3_common.h>
#include <drivers/arm/gic_v3.h>
#include <mmio.h>
+#include <platform.h>
/*******************************************************************************
* GIC Distributor interface accessors for reading entire registers
@@ -197,3 +198,46 @@
/* Check whether the system register interface is enabled */
return !!is_sre_enabled();
}
+
+bool gicv2v3_is_irq_spi(unsigned int irq_num)
+{
+ return IS_PLAT_SPI(irq_num);
+}
+
+static spi_desc spi_desc_table[PLAT_MAX_SPI_OFFSET_ID + 1];
+static ppi_desc ppi_desc_table[PLATFORM_CORE_COUNT][
+ (MAX_PPI_ID + 1) - MIN_PPI_ID];
+static sgi_desc sgi_desc_table[PLATFORM_CORE_COUNT][MAX_SGI_ID + 1];
+static spurious_desc spurious_desc_handler;
+
+void gicv2v3_irq_setup(void)
+{
+ memset(spi_desc_table, 0, sizeof(spi_desc_table));
+ memset(ppi_desc_table, 0, sizeof(ppi_desc_table));
+ memset(sgi_desc_table, 0, sizeof(sgi_desc_table));
+ memset(&spurious_desc_handler, 0, sizeof(spurious_desc_handler));
+}
+
+irq_handler_t *gicv2v3_get_irq_handler(unsigned int irq_num)
+{
+ if (IS_PLAT_SPI(irq_num)) {
+ return &spi_desc_table[irq_num - MIN_SPI_ID].handler;
+ }
+
+ unsigned int linear_id = platform_get_core_pos(read_mpidr_el1());
+
+ if (IS_PPI(irq_num)) {
+ return &ppi_desc_table[linear_id][irq_num - MIN_PPI_ID].handler;
+ }
+
+ if (IS_SGI(irq_num)) {
+ return &sgi_desc_table[linear_id][irq_num - MIN_SGI_ID].handler;
+ }
+
+ /*
+ * The only possibility is for it to be a spurious
+ * interrupt.
+ */
+ assert(irq_num == GIC_SPURIOUS_INTERRUPT);
+ return &spurious_desc_handler;
+}
diff --git a/drivers/arm/gic/gic_v3.c b/drivers/arm/gic/gic_v3.c
index 8bbea48..953ea38 100644
--- a/drivers/arm/gic/gic_v3.c
+++ b/drivers/arm/gic/gic_v3.c
@@ -351,6 +351,11 @@
assert(core_pos < PLATFORM_CORE_COUNT);
assert(mpidr_list[core_pos] != UINT64_MAX);
+ /* only relevant for SPIs */
+ if (!IS_PLAT_SPI(interrupt_id)) {
+ return;
+ }
+
/* Routing information can be set only for SPIs */
assert(IS_SPI(interrupt_id));
route_affinity = mpidr_list[core_pos];
@@ -501,6 +506,8 @@
gicr_base_addr = gicr_base;
gicd_base_addr = gicd_base;
+
+ gicv2v3_irq_setup();
}
unsigned int gicv3_get_gicd_typer(void)
diff --git a/include/drivers/arm/arm_gic.h b/include/drivers/arm/arm_gic.h
index 528ec6e..1cb45fe 100644
--- a/include/drivers/arm/arm_gic.h
+++ b/include/drivers/arm/arm_gic.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2025, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -10,33 +10,16 @@
#include <stdbool.h>
#include <stdint.h>
-/***************************************************************************
- * Defines and prototypes for ARM GIC driver.
- **************************************************************************/
-#define MAX_SGIS 16
-#define MIN_SGI_ID 0
-#define MAX_SGI_ID 15
-#define MIN_PPI_ID 16
-#define MAX_PPI_ID 31
-#define MIN_SPI_ID 32
-#define MAX_SPI_ID 1019
-
-#define IS_SGI(irq_num) \
- (((irq_num) >= MIN_SGI_ID) && ((irq_num) <= MAX_SGI_ID))
-
-#define IS_PPI(irq_num) \
- (((irq_num) >= MIN_PPI_ID) && ((irq_num) <= MAX_PPI_ID))
-
-#define IS_SPI(irq_num) \
- (((irq_num) >= MIN_SPI_ID) && ((irq_num) <= MAX_SPI_ID))
-
-#define IS_VALID_INTR_ID(irq_num) \
- (((irq_num) >= MIN_SGI_ID) && ((irq_num) <= MAX_SPI_ID))
-
#define GIC_HIGHEST_NS_PRIORITY 0
#define GIC_LOWEST_NS_PRIORITY 254 /* 255 would disable an interrupt */
#define GIC_SPURIOUS_INTERRUPT 1023
+/* Prototype of a handler function for an IRQ */
+typedef int (*irq_handler_t)(void *data);
+
+/* return the GIC version detected */
+int arm_gic_get_version(void);
+
/******************************************************************************
* Setup the global GIC interface. In case of GICv2, it would be the GIC
* Distributor and in case of GICv3 it would be GIC Distributor and
@@ -65,6 +48,12 @@
void arm_gic_send_sgi(unsigned int sgi_id, unsigned int core_pos);
/******************************************************************************
+ * Get the INTID for an SGI with number `seq_id` for a core with index
+ * `core_pos`.
+ *****************************************************************************/
+unsigned int arm_gic_get_sgi_num(unsigned int seq_id, unsigned int core_pos);
+
+/******************************************************************************
* Set the interrupt target of interrupt ID `num` to a core with index
* `core_pos`
*****************************************************************************/
@@ -121,6 +110,11 @@
void arm_gic_intr_clear(unsigned int num);
/******************************************************************************
+ * Discover the GIC version in use.
+ *****************************************************************************/
+void arm_gic_probe(void);
+
+/******************************************************************************
* Initialize the GIC Driver. This function will detect the GIC Architecture
* present on the system and initialize the appropriate driver. The
* `gicr_base` argument will be ignored on GICv2 systems.
@@ -156,4 +150,15 @@
*****************************************************************************/
bool arm_gic_is_espi_supported(void);
+/******************************************************************************
+ * Gets the handler for an interrupt
+ *****************************************************************************/
+irq_handler_t *arm_gic_get_irq_handler(unsigned int irq_num);
+
+/******************************************************************************
+ * Returns true if the IRQ number is shared between cores (as opposed to
+ * individual or banked for each).
+ *****************************************************************************/
+bool arm_gic_is_irq_shared(unsigned int irq_num);
+
#endif /* __ARM_GIC_H__ */
diff --git a/include/drivers/arm/gic_v2v3_common.h b/include/drivers/arm/gic_v2v3_common.h
index 7bcae6a..761ae01 100644
--- a/include/drivers/arm/gic_v2v3_common.h
+++ b/include/drivers/arm/gic_v2v3_common.h
@@ -9,6 +9,34 @@
#include <stdbool.h>
+#include <drivers/arm/arm_gic.h>
+
+/***************************************************************************
+ * Defines and prototypes for ARM GIC driver.
+ **************************************************************************/
+#define MIN_SGI_ID 0
+#define MAX_SGI_ID 15
+#define MIN_PPI_ID 16
+#define MAX_PPI_ID 31
+#define MIN_SPI_ID 32
+#define MAX_SPI_ID 1019
+
+#define IS_SGI(irq_num) \
+ (((irq_num) >= MIN_SGI_ID) && ((irq_num) <= MAX_SGI_ID))
+
+#define IS_PPI(irq_num) \
+ (((irq_num) >= MIN_PPI_ID) && ((irq_num) <= MAX_PPI_ID))
+
+#define IS_SPI(irq_num) \
+ (((irq_num) >= MIN_SPI_ID) && ((irq_num) <= MAX_SPI_ID))
+
+#define IS_PLAT_SPI(irq_num) \
+ (((irq_num) >= MIN_SPI_ID) && \
+ ((irq_num) <= MIN_SPI_ID + PLAT_MAX_SPI_OFFSET_ID))
+
+#define IS_VALID_INTR_ID(irq_num) \
+ (((irq_num) >= MIN_SGI_ID) && ((irq_num) <= MAX_SPI_ID))
+
/***************************************************************************
* Defines and prototypes common to GIC v2 and v3 drivers.
**************************************************************************/
@@ -90,6 +118,16 @@
void gicd_set_icactiver(uintptr_t base, unsigned int interrupt_id);
void gicd_set_ipriorityr(uintptr_t base, unsigned int interrupt_id,
unsigned int priority);
+bool gicv2v3_is_irq_spi(unsigned int irq_num);
+void gicv2v3_irq_setup(void);
+irq_handler_t *gicv2v3_get_irq_handler(unsigned int irq_num);
+
+static inline unsigned int gicv2v3_get_sgi_num(unsigned int irq_num,
+ unsigned int core_pos)
+{
+ /* the SGI index is the INTID */
+ return irq_num;
+}
/*******************************************************************************
* Private GIC Distributor interface accessors for reading and writing
diff --git a/include/drivers/arm/gic_v5.h b/include/drivers/arm/gic_v5.h
new file mode 100644
index 0000000..e8f3734
--- /dev/null
+++ b/include/drivers/arm/gic_v5.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2025, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __GIC_V5_H__
+#define __GIC_V5_H__
+
+#include <drivers/arm/arm_gic.h>
+#include <lib/mmio.h>
+
+#define INT_PPI 1
+#define INT_LPI 2
+#define INT_SPI 3
+
+#define GICV5_MAX_PPI_ID 128
+
+#define GICV5_IDLE_PRIORITY 0xff
+
+#define INT_TYPE_SHIFT U(29)
+#define INT_TYPE_WIDTH U(3)
+#define INT_ID_SHIFT U(0)
+#define INT_ID_WIDTH U(24)
+
+#define IRM_TARGETTED 0
+#define IRM_1OFN 1
+
+#define HM_EDGE 0
+#define HM_LEVEL 1
+
+struct l2_iste {
+ uint16_t iaffid;
+ uint8_t priority : 5;
+ uint8_t hwu : 2;
+ uint8_t res0 : 4;
+ uint8_t irm : 1;
+ uint8_t enable : 1;
+ uint8_t hm : 1;
+ uint8_t active : 1;
+ uint8_t pending : 1;
+};
+
+#define DEFINE_GICV5_MMIO_WRITE_FUNC(_name, _offset) \
+static inline void write_##_name(uintptr_t base, uint32_t val) \
+{ \
+ mmio_write_32(base + _offset, val); \
+}
+
+#define DEFINE_GICV5_MMIO_READ_FUNC(_name, _offset) \
+static inline uint32_t read_##_name(uintptr_t base) \
+{ \
+ return mmio_read_32(base + _offset); \
+}
+
+#define DEFINE_GICV5_MMIO_RW_FUNCS(_name, _offset) \
+ DEFINE_GICV5_MMIO_READ_FUNC(_name, _offset) \
+ DEFINE_GICV5_MMIO_WRITE_FUNC(_name, _offset)
+
+#define IRS_IDR2_MIN_LPI_ID_BITS_WIDTH UL(4)
+#define IRS_IDR2_MIN_LPI_ID_BITS_SHIFT U(5)
+#define IRS_IDR2_ID_BITS_WIDTH UL(5)
+#define IRS_IDR2_ID_BITS_SHIFT U(0)
+#define IRS_CR0_IRSEN_BIT BIT(0)
+#define IRS_CR0_IDLE_BIT BIT(1)
+#define IRS_IST_STATUSR_IDLE_BIT BIT(0)
+#define IRS_IST_BASER_VALID_BIT BIT(0)
+#define IRS_IST_BASER_ADDR_SHIFT 6UL
+#define IRS_IST_BASER_ADDR_WIDTH 50UL
+
+DEFINE_GICV5_MMIO_READ_FUNC(IRS_IDR2, 0x0008)
+DEFINE_GICV5_MMIO_RW_FUNCS( IRS_CR0, 0x0080)
+DEFINE_GICV5_MMIO_RW_FUNCS( IRS_IST_BASER, 0x0180)
+DEFINE_GICV5_MMIO_RW_FUNCS( IRS_IST_CFGR, 0x0190)
+DEFINE_GICV5_MMIO_RW_FUNCS( IRS_IST_STATUSR, 0x0194)
+
+#define WAIT_FOR_IDLE(base, reg) \
+ do { \
+ while ((read_##reg(base) & reg##_IDLE_BIT) == 0) {} \
+ } while (0)
+
+#ifdef __aarch64__
+bool is_gicv5_mode(void);
+bool gicv5_is_irq_spi(unsigned int interrupt_id);
+void gicv5_enable_cpuif(void);
+void gicv5_setup_cpuif(void);
+void gicv5_disable_cpuif(void);
+void gicv5_save_cpuif_context(void);
+void gicv5_restore_cpuif_context(void);
+void gicv5_set_priority(unsigned int interrupt_id, unsigned int priority);
+void gicv5_send_sgi(unsigned int sgi_id, unsigned int core_pos);
+void gicv5_set_intr_route(unsigned int interrupt_id, unsigned int core_pos);
+void gicv5_intr_enable(unsigned int interrupt_id);
+void gicv5_intr_disable(unsigned int interrupt_id);
+unsigned int gicv5_acknowledge_interrupt(void);
+unsigned int gicv5_is_intr_pending(unsigned int interrupt_id);
+void gicv5_intr_clear(unsigned int interrupt_id);
+void gicv5_end_of_interrupt(unsigned int raw_iar);
+void gicv5_setup(void);
+uint32_t gicv5_get_sgi_num(uint32_t index, unsigned int core_pos);
+irq_handler_t *gicv5_get_irq_handler(unsigned int interrupt_id);
+void gicv5_init(uintptr_t irs_base_addr);
+#else
+static inline bool is_gicv5_mode(void) { return false; }
+static inline bool gicv5_is_irq_spi(unsigned int interrupt_id) { return false; }
+static inline void gicv5_enable_cpuif(void) {}
+static inline void gicv5_setup_cpuif(void) {}
+static inline void gicv5_disable_cpuif(void) {}
+static inline void gicv5_save_cpuif_context(void) {}
+static inline void gicv5_restore_cpuif_context(void) {}
+static inline void gicv5_set_priority(unsigned int interrupt_id, unsigned int priority) {}
+static inline void gicv5_send_sgi(unsigned int sgi_id, unsigned int core_pos) {}
+static inline void gicv5_set_intr_route(unsigned int interrupt_id, unsigned int core_pos) {}
+static inline void gicv5_intr_enable(unsigned int interrupt_id) {}
+static inline void gicv5_intr_disable(unsigned int interrupt_id) {}
+static inline unsigned int gicv5_acknowledge_interrupt(void) { return -1; }
+static inline unsigned int gicv5_is_intr_pending(unsigned int interrupt_id) { return -1; }
+static inline void gicv5_intr_clear(unsigned int interrupt_id) {}
+static inline void gicv5_end_of_interrupt(unsigned int raw_iar) {}
+static inline void gicv5_setup(void) {}
+static inline uint32_t gicv5_get_sgi_num(uint32_t index, unsigned int core_pos) { return 0; }
+static inline irq_handler_t *gicv5_get_irq_handler(unsigned int interrupt_id) {return NULL; }
+static inline void gicv5_init(uintptr_t irs_base_addr) {}
+#endif
+
+#endif /* __GIC_V5_H__ */
diff --git a/include/lib/aarch32/arch_features.h b/include/lib/aarch32/arch_features.h
index 44a6845..7c5aed7 100644
--- a/include/lib/aarch32/arch_features.h
+++ b/include/lib/aarch32/arch_features.h
@@ -71,4 +71,10 @@
return EXTRACT(ID_PFR1_GIC, read_id_pfr1()) >= 1;
}
+static inline bool is_feat_gcie_supported(void)
+{
+ /* v9 only, we can't have AArch32 in EL2 */
+ return 0;
+}
+
#endif /* ARCH_FEATURES_H */
diff --git a/include/lib/aarch64/arch.h b/include/lib/aarch64/arch.h
index c73c68f..fbef12f 100644
--- a/include/lib/aarch64/arch.h
+++ b/include/lib/aarch64/arch.h
@@ -111,6 +111,58 @@
#define ICV_PMR_EL1 S3_0_C4_C6_0
/*******************************************************************************
+ * Definitions for CPU system register interface to GICv5
+ ******************************************************************************/
+#define ICC_CR0_EL1 S3_1_C12_C0_1
+#define ICC_PCR_EL1 S3_1_C12_C0_2
+#define ICC_IAFFIDR_EL1 S3_0_C12_C10_5
+#define ICC_ICSR_EL1 S3_0_C12_C10_4
+
+#define ICC_PPI_ENABLER0 S3_0_C12_C10_6
+#define ICC_PPI_ENABLER1 S3_0_C12_C10_7
+
+#define ICC_PPI_CPENDR0 S3_0_C12_C13_4
+#define ICC_PPI_CPENDR1 S3_0_C12_C13_5
+#define ICC_PPI_SPENDR0 S3_0_C12_C13_6
+#define ICC_PPI_SPENDR1 S3_0_C12_C13_7
+
+#define ICC_PPI_CACTIVER0 S3_0_C12_C13_0
+#define ICC_PPI_CACTIVER1 S3_0_C12_C13_1
+#define ICC_PPI_SACTIVER0 S3_0_C12_C13_2
+#define ICC_PPI_SACTIVER1 S3_0_C12_C13_3
+
+#define ICC_PPI_PRIORITYR0 S3_0_C12_C14_0
+#define ICC_PPI_PRIORITYR1 S3_0_C12_C14_1
+#define ICC_PPI_PRIORITYR2 S3_0_C12_C14_2
+#define ICC_PPI_PRIORITYR3 S3_0_C12_C14_3
+#define ICC_PPI_PRIORITYR4 S3_0_C12_C14_4
+#define ICC_PPI_PRIORITYR5 S3_0_C12_C14_5
+#define ICC_PPI_PRIORITYR6 S3_0_C12_C14_6
+#define ICC_PPI_PRIORITYR7 S3_0_C12_C14_7
+#define ICC_PPI_PRIORITYR8 S3_0_C12_C15_0
+#define ICC_PPI_PRIORITYR9 S3_0_C12_C15_1
+#define ICC_PPI_PRIORITYR10 S3_0_C12_C15_2
+#define ICC_PPI_PRIORITYR11 S3_0_C12_C15_3
+#define ICC_PPI_PRIORITYR12 S3_0_C12_C15_4
+#define ICC_PPI_PRIORITYR13 S3_0_C12_C15_5
+#define ICC_PPI_PRIORITYR14 S3_0_C12_C15_6
+#define ICC_PPI_PRIORITYR15 S3_0_C12_C15_7
+
+#define ICC_CR0_EL1_EN_BIT BIT(0)
+#define ICC_ICSR_EL1_F_BIT BIT(0)
+#define ICC_ICSR_EL1_PENDING_BIT BIT(2)
+#define ICC_PPI_PRIORITYR_FIELD_NUM 8UL
+#define ICC_PPI_PRIORITYR_FIELD_MASK GENMASK(7, 0)
+#define ICC_PPI_ENABLER_FIELD_NUM 64UL
+#define ICC_PPI_XPENDR_FIELD_NUM 64UL
+
+#define GICCDAFF_IAFFID_SHIFT 32UL
+#define GICCDPRI_PRIORITY_SHIFT 35UL
+#define GICCDPRI_PRIORITY_WIDTH 5UL
+#define GICCDPEND_PENDING_BIT BIT(32)
+#define GICRCDIA_VALID_BIT BIT(32)
+
+/*******************************************************************************
* Definitions for EL2 system registers.
******************************************************************************/
#define CNTPOFF_EL2 S3_4_C14_C0_6
@@ -568,6 +620,11 @@
#define ID_AA64PFR2_EL1_FPMR_WIDTH U(4)
#define ID_AA64PFR2_EL1_FPMR_SUPPORTED ULL(0x1)
+#define ID_AA64PFR2_EL1_GCIE_SHIFT U(12)
+#define ID_AA64PFR2_EL1_GCIE_MASK ULL(0xf)
+#define ID_AA64PFR2_EL1_GCIE_WIDTH U(4)
+#define ID_AA64PFR2_EL1_GCIE_SUPPORTED ULL(0x1)
+
/* ID_PFR1_EL1 definitions */
#define ID_PFR1_VIRTEXT_SHIFT U(12)
#define ID_PFR1_VIRTEXT_MASK U(0xf)
diff --git a/include/lib/aarch64/arch_features.h b/include/lib/aarch64/arch_features.h
index eb846cd..a873501 100644
--- a/include/lib/aarch64/arch_features.h
+++ b/include/lib/aarch64/arch_features.h
@@ -619,4 +619,10 @@
return EXTRACT(ID_AA64PFR0_GIC, read_id_aa64pfr0_el1())
>= ID_AA64PFR0_GICV3_GICV4_SUPPORTED;
}
+
+static inline bool is_feat_gcie_supported(void)
+{
+ return EXTRACT(ID_AA64PFR2_EL1_GCIE, read_id_aa64pfr2_el1())
+ >= ID_AA64PFR2_EL1_GCIE_SUPPORTED;
+}
#endif /* ARCH_FEATURES_H */
diff --git a/include/lib/aarch64/arch_helpers.h b/include/lib/aarch64/arch_helpers.h
index 76e2431..13b9a4f 100644
--- a/include/lib/aarch64/arch_helpers.h
+++ b/include/lib/aarch64/arch_helpers.h
@@ -89,6 +89,28 @@
__asm__ (#_op " " #_type ", %0" : : "r" (v)); \
}
+/* Define an instruction with an encoding. Useful when no compiler support */
+#define DEFINE_INSN(_op, _type, _op1, _CRn, _CRm, _op2) \
+static inline void _op ## _type(void) \
+{ \
+ __asm__ ("sys " #_op1 ", " #_CRn ", " #_CRm ", " #_op2 : : : "memory"); \
+}
+
+#define DEFINE_INSN_RET(_op, _type, _op1, _CRn, _CRm, _op2) \
+static inline u_register_t _op ## _type(void) \
+{ \
+ u_register_t v; \
+ __asm__ ("sysl %0, " #_op1 ", " #_CRn ", " #_CRm ", " #_op2 : "=r" (v));\
+ return v; \
+}
+
+/* Define an instruction with an encoding. Useful when no compiler support */
+#define DEFINE_INSN_PARAM(_op, _type, _op1, _CRn, _CRm, _op2) \
+static inline void _op ## _type(u_register_t v) \
+{ \
+ __asm__ ("sys " #_op1 ", " #_CRn ", " #_CRm ", " #_op2 ", %0" : : "r" (v));\
+}
+
/*******************************************************************************
* TLB maintenance accessor prototypes
******************************************************************************/
@@ -167,6 +189,25 @@
DEFINE_SYSOP_TYPE_PARAM_FUNC(at, s1e2r)
DEFINE_SYSOP_TYPE_PARAM_FUNC(at, s1e3r)
+/*******************************************************************************
+ * GICv5 system instructions for the Current Interrupt Domain
+ ******************************************************************************/
+DEFINE_INSN_PARAM(gic, cddis, 0, c12, c1, 0)
+DEFINE_INSN_PARAM(gic, cden, 0, c12, c1, 1)
+DEFINE_INSN_PARAM(gic, cdpri, 0, c12, c1, 2)
+DEFINE_INSN_PARAM(gic, cdaff, 0, c12, c1, 3)
+DEFINE_INSN_PARAM(gic, cdpend, 0, c12, c1, 4)
+DEFINE_INSN_PARAM(gic, cdrcfg, 0, c12, c1, 5)
+DEFINE_INSN_RET(gicr, cdia, 0, c12, c3, 0)
+DEFINE_INSN_PARAM(gic, cddi, 0, c12, c2, 0)
+DEFINE_INSN(gic, cdeoi, 0, c12, c1, 7)
+
+/*******************************************************************************
+ * GICv5 barriers
+ ******************************************************************************/
+DEFINE_INSN(gsb, sys, 0, c12, c0, 0)
+DEFINE_INSN(gsb, ack, 0, c12, c0, 1)
+
void flush_dcache_range(uintptr_t addr, size_t size);
void clean_dcache_range(uintptr_t addr, size_t size);
void inv_dcache_range(uintptr_t addr, size_t size);
@@ -520,6 +561,42 @@
DEFINE_RENAME_SYSREG_RW_FUNCS(amcntenclr1_el0, AMCNTENCLR1_EL0)
DEFINE_RENAME_SYSREG_RW_FUNCS(amcntenset1_el0, AMCNTENSET1_EL0)
+/* GICv5 System Registers */
+DEFINE_RENAME_SYSREG_RW_FUNCS(icc_cr0_el1, ICC_CR0_EL1)
+DEFINE_RENAME_SYSREG_RW_FUNCS(icc_pcr_el1, ICC_PCR_EL1)
+DEFINE_RENAME_SYSREG_READ_FUNC(icc_iaffidr_el1, ICC_IAFFIDR_EL1)
+DEFINE_RENAME_SYSREG_READ_FUNC(icc_icsr_el1, ICC_ICSR_EL1)
+
+DEFINE_RENAME_SYSREG_RW_FUNCS(icc_ppi_enabler0, ICC_PPI_ENABLER0)
+DEFINE_RENAME_SYSREG_RW_FUNCS(icc_ppi_enabler1, ICC_PPI_ENABLER1)
+
+DEFINE_RENAME_SYSREG_RW_FUNCS(icc_ppi_cpendr0, ICC_PPI_CPENDR0)
+DEFINE_RENAME_SYSREG_RW_FUNCS(icc_ppi_cpendr1, ICC_PPI_CPENDR1)
+DEFINE_RENAME_SYSREG_RW_FUNCS(icc_ppi_spendr0, ICC_PPI_SPENDR0)
+DEFINE_RENAME_SYSREG_RW_FUNCS(icc_ppi_spendr1, ICC_PPI_SPENDR1)
+
+DEFINE_RENAME_SYSREG_RW_FUNCS(icc_ppi_cactiver0, ICC_PPI_CACTIVER0)
+DEFINE_RENAME_SYSREG_RW_FUNCS(icc_ppi_cactiver1, ICC_PPI_CACTIVER1)
+DEFINE_RENAME_SYSREG_RW_FUNCS(icc_ppi_sactiver0, ICC_PPI_SACTIVER0)
+DEFINE_RENAME_SYSREG_RW_FUNCS(icc_ppi_sactiver1, ICC_PPI_SACTIVER1)
+
+DEFINE_RENAME_SYSREG_RW_FUNCS(icc_ppi_priorityr0, ICC_PPI_PRIORITYR0)
+DEFINE_RENAME_SYSREG_RW_FUNCS(icc_ppi_priorityr1, ICC_PPI_PRIORITYR1)
+DEFINE_RENAME_SYSREG_RW_FUNCS(icc_ppi_priorityr2, ICC_PPI_PRIORITYR2)
+DEFINE_RENAME_SYSREG_RW_FUNCS(icc_ppi_priorityr3, ICC_PPI_PRIORITYR3)
+DEFINE_RENAME_SYSREG_RW_FUNCS(icc_ppi_priorityr4, ICC_PPI_PRIORITYR4)
+DEFINE_RENAME_SYSREG_RW_FUNCS(icc_ppi_priorityr5, ICC_PPI_PRIORITYR5)
+DEFINE_RENAME_SYSREG_RW_FUNCS(icc_ppi_priorityr6, ICC_PPI_PRIORITYR6)
+DEFINE_RENAME_SYSREG_RW_FUNCS(icc_ppi_priorityr7, ICC_PPI_PRIORITYR7)
+DEFINE_RENAME_SYSREG_RW_FUNCS(icc_ppi_priorityr8, ICC_PPI_PRIORITYR8)
+DEFINE_RENAME_SYSREG_RW_FUNCS(icc_ppi_priorityr9, ICC_PPI_PRIORITYR9)
+DEFINE_RENAME_SYSREG_RW_FUNCS(icc_ppi_priorityr10, ICC_PPI_PRIORITYR10)
+DEFINE_RENAME_SYSREG_RW_FUNCS(icc_ppi_priorityr11, ICC_PPI_PRIORITYR11)
+DEFINE_RENAME_SYSREG_RW_FUNCS(icc_ppi_priorityr12, ICC_PPI_PRIORITYR12)
+DEFINE_RENAME_SYSREG_RW_FUNCS(icc_ppi_priorityr13, ICC_PPI_PRIORITYR13)
+DEFINE_RENAME_SYSREG_RW_FUNCS(icc_ppi_priorityr14, ICC_PPI_PRIORITYR14)
+DEFINE_RENAME_SYSREG_RW_FUNCS(icc_ppi_priorityr15, ICC_PPI_PRIORITYR15)
+
/* Armv8.4 Memory Partitioning and Monitoring Extension Registers */
DEFINE_RENAME_SYSREG_READ_FUNC(mpamidr_el1, MPAMIDR_EL1)
DEFINE_RENAME_SYSREG_RW_FUNCS(mpam3_el3, MPAM3_EL3)
diff --git a/include/lib/irq.h b/include/lib/irq.h
index 17993a8..cdd34df 100644
--- a/include/lib/irq.h
+++ b/include/lib/irq.h
@@ -10,18 +10,30 @@
#include <cdefs.h>
#include <platform_def.h> /* For CACHE_WRITEBACK_GRANULE */
#include <stdint.h>
+#include <drivers/arm/arm_gic.h>
+
+/*******************************************************************************
+ * Non-Secure Software Generated Interupts IDs
+ ******************************************************************************/
+#define IRQ_NS_SGI_0 0
+#define IRQ_NS_SGI_1 1
+#define IRQ_NS_SGI_2 2
+#define IRQ_NS_SGI_3 3
+#define IRQ_NS_SGI_4 4
+#define IRQ_NS_SGI_5 5
+#define IRQ_NS_SGI_6 6
+#define IRQ_NS_SGI_7 7
+#define IRQ_NUM_SGIS (IRQ_NS_SGI_7 + 1)
/*
* SGI sent by the timer management framework to notify CPUs when the system
* timer fires off
*/
#define IRQ_WAKE_SGI IRQ_NS_SGI_7
+#define IRQ_NUM_SGIS (IRQ_NS_SGI_7 + 1)
#ifndef __ASSEMBLY__
-/* Prototype of a handler function for an IRQ */
-typedef int (*irq_handler_t)(void *data);
-
/* Keep track of the IRQ handler registered for a given SPI */
typedef struct {
irq_handler_t handler;
@@ -50,6 +62,11 @@
void tftf_irq_setup(void);
/*
+ * Get the INTID for an SGI with sequential number seq_id
+ */
+unsigned int tftf_irq_get_my_sgi_num(unsigned int seq_id);
+
+/*
* Generic handler called upon reception of an IRQ.
*
* This function acknowledges the interrupt, calls the user-defined handler
@@ -67,11 +84,13 @@
* Enable interrupt #irq_num for the calling core.
*/
void tftf_irq_enable(unsigned int irq_num, uint8_t irq_priority);
+void tftf_irq_enable_sgi(unsigned int sgi_id, uint8_t irq_priority);
/*
* Disable interrupt #irq_num for the calling core.
*/
void tftf_irq_disable(unsigned int irq_num);
+void tftf_irq_disable_sgi(unsigned int sgi_id);
/*
* Register an interrupt handler for a given interrupt number.
@@ -81,6 +100,7 @@
* Return 0 on success, a negative value otherwise.
*/
int tftf_irq_register_handler(unsigned int num, irq_handler_t irq_handler);
+int tftf_irq_register_handler_sgi(unsigned int sgi_id, irq_handler_t irq_handler);
/*
* Unregister an interrupt handler for a given interrupt number.
@@ -89,6 +109,7 @@
* Return 0 on success, a negative value otherwise.
*/
int tftf_irq_unregister_handler(unsigned int irq_num);
+int tftf_irq_unregister_handler_sgi(unsigned int sgi_id);
#endif /* __ASSEMBLY__ */
diff --git a/include/lib/utils_def.h b/include/lib/utils_def.h
index c9bd527..ae85a81 100644
--- a/include/lib/utils_def.h
+++ b/include/lib/utils_def.h
@@ -233,4 +233,14 @@
0; \
}))
+/*
+ * Get the next power of 2 for x. Eg. next_power_of_2(12) is 16
+ */
+#define b2(x) ((x) | ((x) >> 1))
+#define b4(x) (b2(x) | (b2(x) >> 2))
+#define b8(x) (b4(x) | (b4(x) >> 4))
+#define b16(x) (b8(x) | (b8(x) >> 8))
+#define b32(x) (b16(x) | (b16(x) >> 16))
+#define next_power_of_2(x) (b32(x - 1) + 1)
+
#endif /* UTILS_DEF_H */
diff --git a/lib/exceptions/irq.c b/lib/exceptions/irq.c
index b99857c..289a17a 100644
--- a/lib/exceptions/irq.c
+++ b/lib/exceptions/irq.c
@@ -18,16 +18,6 @@
#include <tftf.h>
#include <tftf_lib.h>
-#define IS_PLAT_SPI(irq_num) \
- (((irq_num) >= MIN_SPI_ID) && \
- ((irq_num) <= MIN_SPI_ID + PLAT_MAX_SPI_OFFSET_ID))
-
-static spi_desc spi_desc_table[PLAT_MAX_SPI_OFFSET_ID + 1];
-static ppi_desc ppi_desc_table[PLATFORM_CORE_COUNT][
- (MAX_PPI_ID + 1) - MIN_PPI_ID];
-static sgi_desc sgi_desc_table[PLATFORM_CORE_COUNT][MAX_SGI_ID + 1];
-static spurious_desc spurious_desc_handler;
-
/*
* For a given SPI, the associated IRQ handler is common to all CPUs.
* Therefore, we need a lock to prevent simultaneous updates.
@@ -37,34 +27,17 @@
* saves memory. Updating an SPI handler shouldn't occur that often anyway so we
* shouldn't suffer from this restriction too much.
*/
-static spinlock_t spi_lock;
+static spinlock_t shared_irq_lock;
-static irq_handler_t *get_irq_handler(unsigned int irq_num)
+
+unsigned int tftf_irq_get_my_sgi_num(unsigned int seq_id)
{
- if (IS_PLAT_SPI(irq_num))
- return &spi_desc_table[irq_num - MIN_SPI_ID].handler;
-
- unsigned int mpid = read_mpidr_el1();
- unsigned int linear_id = platform_get_core_pos(mpid);
-
- if (IS_PPI(irq_num))
- return &ppi_desc_table[linear_id][irq_num - MIN_PPI_ID].handler;
-
- if (IS_SGI(irq_num))
- return &sgi_desc_table[linear_id][irq_num - MIN_SGI_ID].handler;
-
- /*
- * The only possibility is for it to be a spurious
- * interrupt.
- */
- assert(irq_num == GIC_SPURIOUS_INTERRUPT);
- return &spurious_desc_handler;
+ unsigned int core_pos = platform_get_core_pos(read_mpidr_el1());
+ return arm_gic_get_sgi_num(seq_id, core_pos);
}
void tftf_send_sgi(unsigned int sgi_id, unsigned int core_pos)
{
- assert(IS_SGI(sgi_id));
-
/*
* Ensure that all memory accesses prior to sending the SGI are
* completed.
@@ -86,20 +59,20 @@
void tftf_irq_enable(unsigned int irq_num, uint8_t irq_priority)
{
- if (IS_PLAT_SPI(irq_num)) {
- /*
- * Instruct the GIC Distributor to forward the interrupt to
- * the calling core
- */
- arm_gic_set_intr_target(irq_num, platform_get_core_pos(read_mpidr_el1()));
- }
-
+ arm_gic_set_intr_target(irq_num, platform_get_core_pos(read_mpidr_el1()));
arm_gic_set_intr_priority(irq_num, irq_priority);
arm_gic_intr_enable(irq_num);
VERBOSE("Enabled IRQ #%u\n", irq_num);
}
+void tftf_irq_enable_sgi(unsigned int sgi_id, uint8_t irq_priority)
+{
+ unsigned int irq_num = tftf_irq_get_my_sgi_num(sgi_id);
+
+ tftf_irq_enable(irq_num, irq_priority);
+}
+
void tftf_irq_disable(unsigned int irq_num)
{
/* Disable the interrupt */
@@ -108,6 +81,13 @@
VERBOSE("Disabled IRQ #%u\n", irq_num);
}
+void tftf_irq_disable_sgi(unsigned int sgi_id)
+{
+ unsigned int irq_num = tftf_irq_get_my_sgi_num(sgi_id);
+
+ tftf_irq_disable(irq_num);
+}
+
#define HANDLER_VALID(handler, expect_handler) \
((expect_handler) ? ((handler) != NULL) : ((handler) == NULL))
@@ -118,9 +98,9 @@
irq_handler_t *cur_handler;
int ret = -1;
- cur_handler = get_irq_handler(irq_num);
- if (IS_PLAT_SPI(irq_num))
- spin_lock(&spi_lock);
+ cur_handler = arm_gic_get_irq_handler(irq_num);
+ if (arm_gic_is_irq_shared(irq_num))
+ spin_lock(&shared_irq_lock);
/*
* Update the IRQ handler, if the current handler is in the expected
@@ -132,8 +112,8 @@
ret = 0;
}
- if (IS_PLAT_SPI(irq_num))
- spin_unlock(&spi_lock);
+ if (arm_gic_is_irq_shared(irq_num))
+ spin_unlock(&shared_irq_lock);
return ret;
}
@@ -150,6 +130,12 @@
return ret;
}
+int tftf_irq_register_handler_sgi(unsigned int sgi_id, irq_handler_t irq_handler)
+{
+ unsigned int irq_num = tftf_irq_get_my_sgi_num(sgi_id);
+ return tftf_irq_register_handler(irq_num, irq_handler);
+}
+
int tftf_irq_unregister_handler(unsigned int irq_num)
{
int ret;
@@ -161,6 +147,12 @@
return ret;
}
+int tftf_irq_unregister_handler_sgi(unsigned int sgi_id)
+{
+ unsigned int irq_num = tftf_irq_get_my_sgi_num(sgi_id);
+ return tftf_irq_unregister_handler(irq_num);
+}
+
int tftf_irq_handler_dispatcher(void)
{
unsigned int raw_iar;
@@ -172,7 +164,7 @@
/* Acknowledge the interrupt */
irq_num = arm_gic_intr_ack(&raw_iar);
- handler = get_irq_handler(irq_num);
+ handler = arm_gic_get_irq_handler(irq_num);
irq_data = &irq_num;
if (*handler != NULL)
@@ -187,9 +179,5 @@
void tftf_irq_setup(void)
{
- memset(spi_desc_table, 0, sizeof(spi_desc_table));
- memset(ppi_desc_table, 0, sizeof(ppi_desc_table));
- memset(sgi_desc_table, 0, sizeof(sgi_desc_table));
- memset(&spurious_desc_handler, 0, sizeof(spurious_desc_handler));
- init_spinlock(&spi_lock);
+ init_spinlock(&shared_irq_lock);
}
diff --git a/lib/power_management/hotplug/hotplug.c b/lib/power_management/hotplug/hotplug.c
index 7d534b5..cb00cff 100644
--- a/lib/power_management/hotplug/hotplug.c
+++ b/lib/power_management/hotplug/hotplug.c
@@ -301,7 +301,7 @@
arm_gic_setup_local();
/* Enable the SGI used by the timer management framework */
- tftf_irq_enable(IRQ_WAKE_SGI, GIC_HIGHEST_NS_PRIORITY);
+ tftf_irq_enable_sgi(IRQ_WAKE_SGI, GIC_HIGHEST_NS_PRIORITY);
tftf_initialise_timer_secondary_core();
enable_irq();
diff --git a/lib/psci/psci.c b/lib/psci/psci.c
index 720d319..2c86e1c 100644
--- a/lib/psci/psci.c
+++ b/lib/psci/psci.c
@@ -269,7 +269,7 @@
return;
}
- tftf_irq_enable(IRQ_NS_SGI_0, GIC_HIGHEST_NS_PRIORITY);
+ tftf_irq_enable_sgi(IRQ_NS_SGI_0, GIC_HIGHEST_NS_PRIORITY);
/*
* Mask IRQ to prevent the interrupt handler being invoked
@@ -298,7 +298,7 @@
enable_irq();
isb();
- tftf_irq_disable(IRQ_NS_SGI_0);
+ tftf_irq_disable_sgi(IRQ_NS_SGI_0);
/*
* The NULL State-ID returned SUCCESS. Hence State-ID is NULL
diff --git a/plat/amd/versal2/include/platform_def.h b/plat/amd/versal2/include/platform_def.h
index 206f292..814ea85 100644
--- a/plat/amd/versal2/include/platform_def.h
+++ b/plat/amd/versal2/include/platform_def.h
@@ -87,18 +87,6 @@
#define CRASH_CONSOLE_BASE PL011_UART1_BASE
#define CRASH_CONSOLE_SIZE PLAT_ARM_UART_SIZE
-/*******************************************************************************
- * Non-Secure Software Generated Interrupts IDs
- ******************************************************************************/
-#define IRQ_NS_SGI_0 0
-#define IRQ_NS_SGI_1 1
-#define IRQ_NS_SGI_2 2
-#define IRQ_NS_SGI_3 3
-#define IRQ_NS_SGI_4 4
-#define IRQ_NS_SGI_5 5
-#define IRQ_NS_SGI_6 6
-#define IRQ_NS_SGI_7 7
-
/* Per-CPU Hypervisor Timer Interrupt ID */
#define IRQ_PCPU_HP_TIMER U(29)
/* Datasheet: TIME00 event*/
diff --git a/plat/arm/common/arm_timers.c b/plat/arm/common/arm_timers.c
index f43fdaa..35171c9 100644
--- a/plat/arm/common/arm_timers.c
+++ b/plat/arm/common/arm_timers.c
@@ -1,10 +1,11 @@
/*
- * Copyright (c) 2018, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2025, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
+#include <drivers/arm/gic_v5.h>
#include <drivers/arm/system_timer.h>
#include <platform.h>
#include <stddef.h>
@@ -12,12 +13,11 @@
#pragma weak plat_initialise_timer_ops
-static const plat_timer_t plat_timers = {
+static plat_timer_t plat_timers = {
.program = program_systimer,
.cancel = cancel_systimer,
.handler = handler_systimer,
.timer_step_value = 2,
- .timer_irq = IRQ_CNTPSIRQ1
};
int plat_initialise_timer_ops(const plat_timer_t **timer_ops)
@@ -25,6 +25,20 @@
assert(timer_ops != NULL);
*timer_ops = &plat_timers;
+ /*
+ * on GICv2/3 platforms give the INTID verbatim (eg SPI 60, ie. INTID
+ * 92) although can be a PPI too
+ * on GICv5 take the same SPI ID but re-use the GICv3 macro for
+ * compatibility.
+ * TODO: currently unclear how non-fvp platforms will use this; refactor
+ * to work elsewhere.
+ */
+ if (arm_gic_get_version() != 5) {
+ plat_timers.timer_irq = IRQ_CNTPSIRQ1;
+ } else {
+ plat_timers.timer_irq = (IRQ_CNTPSIRQ1 - 32) | INPLACE(INT_TYPE, INT_SPI);
+ }
+
/* Initialise the system timer */
init_systimer(SYS_CNT_BASE1);
diff --git a/plat/arm/corstone1000/include/platform_def.h b/plat/arm/corstone1000/include/platform_def.h
index a0d6f7b..91f4cda 100644
--- a/plat/arm/corstone1000/include/platform_def.h
+++ b/plat/arm/corstone1000/include/platform_def.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022, Arm Limited. All rights reserved.
+ * Copyright (c) 2022-2025, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -134,18 +134,6 @@
#define CACHE_WRITEBACK_SHIFT 6
#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
-/*******************************************************************************
- * Non-Secure Software Generated Interupts IDs
- ******************************************************************************/
-#define IRQ_NS_SGI_0 0
-#define IRQ_NS_SGI_1 1
-#define IRQ_NS_SGI_2 2
-#define IRQ_NS_SGI_3 3
-#define IRQ_NS_SGI_4 4
-#define IRQ_NS_SGI_5 5
-#define IRQ_NS_SGI_6 6
-#define IRQ_NS_SGI_7 7
-
#define PLAT_MAX_SPI_OFFSET_ID 220
/* The IRQ generated by Ethernet controller */
diff --git a/plat/arm/fvp/fvp_def.h b/plat/arm/fvp/fvp_def.h
index 222fadd..1d4e507 100644
--- a/plat/arm/fvp/fvp_def.h
+++ b/plat/arm/fvp/fvp_def.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018-2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2025, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -71,6 +71,11 @@
#define GICC_BASE 0x2c000000
/*******************************************************************************
+ * GICv5 related constants
+ ******************************************************************************/
+#define IRS_BASE 0x2f1a0000
+
+/*******************************************************************************
* PL011 related constants
******************************************************************************/
#define PL011_UART0_BASE 0x1c090000
diff --git a/plat/arm/fvp/include/platform_def.h b/plat/arm/fvp/include/platform_def.h
index 322d264..089e0a8 100644
--- a/plat/arm/fvp/include/platform_def.h
+++ b/plat/arm/fvp/include/platform_def.h
@@ -274,18 +274,6 @@
#define CACHE_WRITEBACK_SHIFT 6
#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
-/*******************************************************************************
- * Non-Secure Software Generated Interupts IDs
- ******************************************************************************/
-#define IRQ_NS_SGI_0 0
-#define IRQ_NS_SGI_1 1
-#define IRQ_NS_SGI_2 2
-#define IRQ_NS_SGI_3 3
-#define IRQ_NS_SGI_4 4
-#define IRQ_NS_SGI_5 5
-#define IRQ_NS_SGI_6 6
-#define IRQ_NS_SGI_7 7
-
/*
* On FVP, consider that the last SPI is the Trusted Random Number Generator
* interrupt.
diff --git a/plat/arm/fvp/plat_setup.c b/plat/arm/fvp/plat_setup.c
index f09bf59..c897289 100644
--- a/plat/arm/fvp/plat_setup.c
+++ b/plat/arm/fvp/plat_setup.c
@@ -52,5 +52,9 @@
void plat_arm_gic_init(void)
{
- arm_gic_init(GICC_BASE, GICD_BASE, GICR_BASE);
+ if (arm_gic_get_version() != 5) {
+ arm_gic_init(GICC_BASE, GICD_BASE, GICR_BASE);
+ } else {
+ arm_gic_init(0, IRS_BASE, 0);
+ }
}
diff --git a/plat/arm/juno/include/platform_def.h b/plat/arm/juno/include/platform_def.h
index 2de11fd..89e5601 100644
--- a/plat/arm/juno/include/platform_def.h
+++ b/plat/arm/juno/include/platform_def.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2025, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -225,18 +225,6 @@
#define CACHE_WRITEBACK_SHIFT 6
#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
-/*******************************************************************************
- * Non-Secure Software Generated Interupts IDs
- ******************************************************************************/
-#define IRQ_NS_SGI_0 0
-#define IRQ_NS_SGI_1 1
-#define IRQ_NS_SGI_2 2
-#define IRQ_NS_SGI_3 3
-#define IRQ_NS_SGI_4 4
-#define IRQ_NS_SGI_5 5
-#define IRQ_NS_SGI_6 6
-#define IRQ_NS_SGI_7 7
-
#define PLAT_MAX_SPI_OFFSET_ID 220
/* The IRQ generated by Ethernet controller */
diff --git a/plat/arm/n1sdp/include/platform_def.h b/plat/arm/n1sdp/include/platform_def.h
index 71409fc..91d6b3c 100644
--- a/plat/arm/n1sdp/include/platform_def.h
+++ b/plat/arm/n1sdp/include/platform_def.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022, Arm Limited. All rights reserved.
+ * Copyright (c) 2022-2025, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -135,10 +135,6 @@
#define CACHE_WRITEBACK_SHIFT 6
#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
-/* Non-Secure Software Generated Interupts IDs */
-#define IRQ_NS_SGI_0 0
-#define IRQ_NS_SGI_7 7
-
/*
* AP UART1 interrupt is considered as the maximum SPI.
* MAX_SPI_ID = MIN_SPI_ID + PLAT_MAX_SPI_OFFSET_ID = 96
diff --git a/plat/arm/neoverse_rd/common/include/nrd2/nrd_plat_arm_def2.h b/plat/arm/neoverse_rd/common/include/nrd2/nrd_plat_arm_def2.h
index ba1ddb8..26515b3 100644
--- a/plat/arm/neoverse_rd/common/include/nrd2/nrd_plat_arm_def2.h
+++ b/plat/arm/neoverse_rd/common/include/nrd2/nrd_plat_arm_def2.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2024-2025, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
@@ -76,14 +76,6 @@
#define MAX_IO_DEVICES U(1)
#define MAX_IO_HANDLES U(1)
-/*******************************************************************************
- * Non-Secure Software Generated Interupts IDs
- ******************************************************************************/
-
-/* Non-Secure Software Generated Interupts IDs */
-#define IRQ_NS_SGI_0 U(0)
-#define IRQ_NS_SGI_7 U(7)
-
/* Maximum SPI */
#define PLAT_MAX_SPI_OFFSET_ID U(256)
@@ -162,4 +154,4 @@
#define FLASH_SIZE NRD_ROS_FLASH_SIZE
#define NOR_FLASH_BLOCK_SIZE UL(0x40000) /* 256KB */
-#endif /* NRD_PLAT_ARM_DEF2_H */
\ No newline at end of file
+#endif /* NRD_PLAT_ARM_DEF2_H */
diff --git a/plat/arm/neoverse_rd/common/include/nrd3/nrd_plat_arm_def3.h b/plat/arm/neoverse_rd/common/include/nrd3/nrd_plat_arm_def3.h
index 20c748e..5c2f59e 100644
--- a/plat/arm/neoverse_rd/common/include/nrd3/nrd_plat_arm_def3.h
+++ b/plat/arm/neoverse_rd/common/include/nrd3/nrd_plat_arm_def3.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2024-2025, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
@@ -68,13 +68,6 @@
#define MAX_IO_DEVICES U(1)
#define MAX_IO_HANDLES U(1)
-/*******************************************************************************
- * Non-Secure Software Generated Interupts IDs
- ******************************************************************************/
-
-#define IRQ_NS_SGI_0 U(0)
-#define IRQ_NS_SGI_7 U(7)
-
/* Maximum SPI */
#define PLAT_MAX_SPI_OFFSET_ID U(256)
@@ -152,4 +145,4 @@
#define FLASH_SIZE NRD_ROS_FLASH_SIZE
#define NOR_FLASH_BLOCK_SIZE UL(0x40000) /* 256KB */
-#endif /* NRD_PLAT_ARM_DEF3_H */
\ No newline at end of file
+#endif /* NRD_PLAT_ARM_DEF3_H */
diff --git a/plat/arm/tc/include/platform_def.h b/plat/arm/tc/include/platform_def.h
index 82fa6c2..28325c3 100644
--- a/plat/arm/tc/include/platform_def.h
+++ b/plat/arm/tc/include/platform_def.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2025, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -129,10 +129,6 @@
#define CACHE_WRITEBACK_SHIFT 6
#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
-/* Non-Secure Software Generated Interupts IDs */
-#define IRQ_NS_SGI_0 0
-#define IRQ_NS_SGI_7 7
-
/* AP UART1 interrupt is considered as the maximum SPI */
#define PLAT_MAX_SPI_OFFSET_ID 64
diff --git a/plat/hisilicon/hikey960/include/platform_def.h b/plat/hisilicon/hikey960/include/platform_def.h
index e3e878f..8119c51 100644
--- a/plat/hisilicon/hikey960/include/platform_def.h
+++ b/plat/hisilicon/hikey960/include/platform_def.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2025, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -80,18 +80,6 @@
#define PL011_BAUDRATE 115200
#define PL011_UART_CLK_IN_HZ 19200000
-/*******************************************************************************
- * Non-Secure Software Generated Interupts IDs
- ******************************************************************************/
-#define IRQ_NS_SGI_0 0
-#define IRQ_NS_SGI_1 1
-#define IRQ_NS_SGI_2 2
-#define IRQ_NS_SGI_3 3
-#define IRQ_NS_SGI_4 4
-#define IRQ_NS_SGI_5 5
-#define IRQ_NS_SGI_6 6
-#define IRQ_NS_SGI_7 7
-
/* Per-CPU Hypervisor Timer Interrupt ID */
#define IRQ_PCPU_HP_TIMER 26
/* Datasheet: TIME00 event*/
diff --git a/plat/nvidia/tegra186/include/platform_def.h b/plat/nvidia/tegra186/include/platform_def.h
index 8ad93ad..76ebd60 100644
--- a/plat/nvidia/tegra186/include/platform_def.h
+++ b/plat/nvidia/tegra186/include/platform_def.h
@@ -104,18 +104,6 @@
#define PLAT_SUSPEND_ENTRY_EXIT_TIME 1000
/*******************************************************************************
- * Non-Secure Software Generated Interupts IDs
- ******************************************************************************/
-#define IRQ_NS_SGI_0 0
-#define IRQ_NS_SGI_1 1
-#define IRQ_NS_SGI_2 2
-#define IRQ_NS_SGI_3 3
-#define IRQ_NS_SGI_4 4
-#define IRQ_NS_SGI_5 5
-#define IRQ_NS_SGI_6 6
-#define IRQ_NS_SGI_7 7
-
-/*******************************************************************************
* Per-CPU Hypervisor Timer Interrupt ID
******************************************************************************/
#define IRQ_PCPU_HP_TIMER 26
diff --git a/plat/nvidia/tegra194/include/platform_def.h b/plat/nvidia/tegra194/include/platform_def.h
index 0cd3ecd..6d3a0bb 100644
--- a/plat/nvidia/tegra194/include/platform_def.h
+++ b/plat/nvidia/tegra194/include/platform_def.h
@@ -105,18 +105,6 @@
#define PLAT_SUSPEND_ENTRY_EXIT_TIME 1000
/*******************************************************************************
- * Non-Secure Software Generated Interupts IDs
- ******************************************************************************/
-#define IRQ_NS_SGI_0 0
-#define IRQ_NS_SGI_1 1
-#define IRQ_NS_SGI_2 2
-#define IRQ_NS_SGI_3 3
-#define IRQ_NS_SGI_4 4
-#define IRQ_NS_SGI_5 5
-#define IRQ_NS_SGI_6 6
-#define IRQ_NS_SGI_7 7
-
-/*******************************************************************************
* Per-CPU Hypervisor Timer Interrupt ID
******************************************************************************/
#define IRQ_PCPU_HP_TIMER 26
diff --git a/plat/nvidia/tegra210/include/platform_def.h b/plat/nvidia/tegra210/include/platform_def.h
index 0e369b3..29f4252 100644
--- a/plat/nvidia/tegra210/include/platform_def.h
+++ b/plat/nvidia/tegra210/include/platform_def.h
@@ -102,18 +102,6 @@
#define PLAT_SUSPEND_ENTRY_TIME 500
#define PLAT_SUSPEND_ENTRY_EXIT_TIME 1000
-/******************************************************************************
-* Non-Secure Software Generated Interupts IDs
-******************************************************************************/
-#define IRQ_NS_SGI_0 0
-#define IRQ_NS_SGI_1 1
-#define IRQ_NS_SGI_2 2
-#define IRQ_NS_SGI_3 3
-#define IRQ_NS_SGI_4 4
-#define IRQ_NS_SGI_5 5
-#define IRQ_NS_SGI_6 6
-#define IRQ_NS_SGI_7 7
-
/*******************************************************************************
* Per-CPU Hypervisor Timer Interrupt ID
******************************************************************************/
diff --git a/plat/xilinx/versal/include/platform_def.h b/plat/xilinx/versal/include/platform_def.h
index 1e6bd5d..09b4acc 100644
--- a/plat/xilinx/versal/include/platform_def.h
+++ b/plat/xilinx/versal/include/platform_def.h
@@ -85,18 +85,6 @@
#define CRASH_CONSOLE_BASE PL011_UART0_BASE
#define CRASH_CONSOLE_SIZE PLAT_ARM_UART_SIZE
-/*******************************************************************************
- * Non-Secure Software Generated Interrupts IDs
- ******************************************************************************/
-#define IRQ_NS_SGI_0 0
-#define IRQ_NS_SGI_1 1
-#define IRQ_NS_SGI_2 2
-#define IRQ_NS_SGI_3 3
-#define IRQ_NS_SGI_4 4
-#define IRQ_NS_SGI_5 5
-#define IRQ_NS_SGI_6 6
-#define IRQ_NS_SGI_7 7
-
/* Per-CPU Hypervisor Timer Interrupt ID */
#define IRQ_PCPU_HP_TIMER U(29)
/* Datasheet: TIME00 event*/
diff --git a/plat/xilinx/versal_net/include/platform_def.h b/plat/xilinx/versal_net/include/platform_def.h
index 12c5910..fce271d 100644
--- a/plat/xilinx/versal_net/include/platform_def.h
+++ b/plat/xilinx/versal_net/include/platform_def.h
@@ -86,18 +86,6 @@
#define CRASH_CONSOLE_BASE PL011_UART0_BASE
#define CRASH_CONSOLE_SIZE PLAT_ARM_UART_SIZE
-/*******************************************************************************
- * Non-Secure Software Generated Interrupts IDs
- ******************************************************************************/
-#define IRQ_NS_SGI_0 0
-#define IRQ_NS_SGI_1 1
-#define IRQ_NS_SGI_2 2
-#define IRQ_NS_SGI_3 3
-#define IRQ_NS_SGI_4 4
-#define IRQ_NS_SGI_5 5
-#define IRQ_NS_SGI_6 6
-#define IRQ_NS_SGI_7 7
-
/* Per-CPU Hypervisor Timer Interrupt ID */
#define IRQ_PCPU_HP_TIMER U(26)
/* Datasheet: TIME00 event*/
diff --git a/plat/xilinx/zynqmp/include/platform_def.h b/plat/xilinx/zynqmp/include/platform_def.h
index cb3a707..e7128de 100644
--- a/plat/xilinx/zynqmp/include/platform_def.h
+++ b/plat/xilinx/zynqmp/include/platform_def.h
@@ -70,17 +70,6 @@
#define CACHE_WRITEBACK_SHIFT 6
#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
-/* Non-Secure Software Generated Interrupts IDs */
-
-#define IRQ_NS_SGI_0 0
-#define IRQ_NS_SGI_1 1
-#define IRQ_NS_SGI_2 2
-#define IRQ_NS_SGI_3 3
-#define IRQ_NS_SGI_4 4
-#define IRQ_NS_SGI_5 5
-#define IRQ_NS_SGI_6 6
-#define IRQ_NS_SGI_7 7
-
/* Platform specific page table and MMU setup constants */
#define PLAT_PHY_ADDR_SPACE_SIZE (ULL(1) << 32)
diff --git a/tftf/framework/framework.mk b/tftf/framework/framework.mk
index edcae60..f920cbf 100644
--- a/tftf/framework/framework.mk
+++ b/tftf/framework/framework.mk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2018-2024, Arm Limited. All rights reserved.
+# Copyright (c) 2018-2025, Arm Limited. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -90,6 +90,7 @@
ifeq (${ARCH},aarch64)
# ARMv8.3 Pointer Authentication support files
FRAMEWORK_SOURCES += \
+ drivers/arm/gic/aarch64/gic_v5.c \
lib/exceptions/aarch64/sync.c \
lib/exceptions/aarch64/serror.c \
lib/extensions/pauth/aarch64/pauth.c \
diff --git a/tftf/framework/main.c b/tftf/framework/main.c
index 0ae03e5..9543704 100644
--- a/tftf/framework/main.c
+++ b/tftf/framework/main.c
@@ -564,6 +564,8 @@
pauth_init_enable();
#endif /* ENABLE_PAUTH */
+ arm_gic_probe();
+
tftf_platform_setup();
tftf_init_topology();
@@ -576,7 +578,7 @@
}
/* Enable the SGI used by the timer management framework */
- tftf_irq_enable(IRQ_WAKE_SGI, GIC_HIGHEST_NS_PRIORITY);
+ tftf_irq_enable_sgi(IRQ_WAKE_SGI, GIC_HIGHEST_NS_PRIORITY);
enable_irq();
if (new_test_session()) {
diff --git a/tftf/framework/timer/timer_framework.c b/tftf/framework/timer/timer_framework.c
index 556d46e..0972ceb 100644
--- a/tftf/framework/timer/timer_framework.c
+++ b/tftf/framework/timer/timer_framework.c
@@ -97,7 +97,7 @@
void tftf_initialise_timer_secondary_core(void)
{
- if (!IS_SPI(TIMER_IRQ)) {
+ if (!arm_gic_is_irq_shared(TIMER_IRQ)) {
arm_gic_set_intr_priority(TIMER_IRQ, GIC_HIGHEST_NS_PRIORITY);
arm_gic_intr_enable(TIMER_IRQ);
}
@@ -186,7 +186,7 @@
if ((!get_current_prog_time()) || (interrupt_req_time[core_pos] <
(get_current_prog_time() - TIMER_STEP_VALUE))) {
- if (IS_SPI(TIMER_IRQ)) {
+ if (arm_gic_is_irq_shared(TIMER_IRQ)) {
arm_gic_set_intr_target(TIMER_IRQ, core_pos);
}
@@ -490,7 +490,7 @@
* Also register same handler to IRQ_WAKE_SGI, as it can be waken
* by it.
*/
- ret = tftf_irq_register_handler(IRQ_WAKE_SGI, irq_handler);
+ ret = tftf_irq_register_handler_sgi(IRQ_WAKE_SGI, irq_handler);
assert(!ret);
return ret;
@@ -504,7 +504,7 @@
/*
* Unregister the handler for IRQ_WAKE_SGI also
*/
- ret = tftf_irq_unregister_handler(IRQ_WAKE_SGI);
+ ret = tftf_irq_unregister_handler_sgi(IRQ_WAKE_SGI);
assert(!ret);
/* Validate a handler is registered */
assert(timer_handler[core_pos]);
diff --git a/tftf/tests/framework_validation_tests/test_timer_framework.c b/tftf/tests/framework_validation_tests/test_timer_framework.c
index 421ddc6..51b6f9b 100644
--- a/tftf/tests/framework_validation_tests/test_timer_framework.c
+++ b/tftf/tests/framework_validation_tests/test_timer_framework.c
@@ -7,6 +7,7 @@
#include <arch.h>
#include <arch_helpers.h>
#include <debug.h>
+#include <drivers/arm/arm_gic.h>
#include <events.h>
#include <irq.h>
#include <mmio.h>
@@ -48,7 +49,7 @@
unsigned int core_pos = platform_get_core_pos(read_mpidr_el1());
unsigned int irq_id = *(unsigned int *) data;
- assert(irq_id == IRQ_WAKE_SGI || irq_id == tftf_get_timer_irq());
+ assert(irq_id == tftf_irq_get_my_sgi_num(IRQ_WAKE_SGI) || irq_id == tftf_get_timer_irq());
assert(requested_irq_received[core_pos] == 0);
if (irq_id == tftf_get_timer_irq()) {
@@ -71,10 +72,10 @@
unsigned int core_pos = platform_get_core_pos(read_mpidr_el1());
unsigned int irq_id = *(unsigned int *) data;
- assert(irq_id == IRQ_WAKE_SGI || irq_id == tftf_get_timer_irq());
+ assert(irq_id == tftf_irq_get_my_sgi_num(IRQ_WAKE_SGI) || irq_id == tftf_get_timer_irq());
assert(requested_irq_received[core_pos] == 0);
- if (irq_id == IRQ_WAKE_SGI) {
+ if (irq_id == tftf_irq_get_my_sgi_num(IRQ_WAKE_SGI)) {
spin_lock(&irq_handler_lock);
multiple_timer_count++;
spin_unlock(&irq_handler_lock);
diff --git a/tftf/tests/framework_validation_tests/test_validation_irq.c b/tftf/tests/framework_validation_tests/test_validation_irq.c
index 914a1ca..6955191 100644
--- a/tftf/tests/framework_validation_tests/test_validation_irq.c
+++ b/tftf/tests/framework_validation_tests/test_validation_irq.c
@@ -46,13 +46,13 @@
counter = 0;
/* Now register a handler */
- ret = tftf_irq_register_handler(sgi_id, increment_counter);
+ ret = tftf_irq_register_handler_sgi(sgi_id, increment_counter);
if (ret != 0) {
tftf_testcase_printf("Failed to register initial IRQ handler\n");
return TEST_RESULT_FAIL;
}
- tftf_irq_enable(sgi_id, GIC_HIGHEST_NS_PRIORITY);
+ tftf_irq_enable_sgi(IRQ_NS_SGI_0, GIC_HIGHEST_NS_PRIORITY);
/*
* Send the SGI to the calling core and check the IRQ handler has been
@@ -64,6 +64,8 @@
while (counter != 1)
;
+ // TODO all this crap tests tftf itself. It's just slow. Drop?
+ // or add it to some test group that's not built/run by default.
/*
* Try to overwrite the IRQ handler. This should fail.
* In debug builds, it would trigger an assertion so we can't test that
@@ -72,7 +74,7 @@
* replace the existing handler and that's something that can be tested.
*/
#if !DEBUG
- ret = tftf_irq_register_handler(sgi_id, set_counter_to_42);
+ ret = tftf_irq_register_handler_sgi(sgi_id, set_counter_to_42);
if (ret == 0) {
tftf_testcase_printf(
"Overwriting the IRQ handler should have failed\n");
@@ -85,7 +87,7 @@
;
/* Unregister the IRQ handler */
- ret = tftf_irq_unregister_handler(sgi_id);
+ ret = tftf_irq_unregister_handler_sgi(IRQ_NS_SGI_0);
if (ret != 0) {
tftf_testcase_printf("Failed to unregister IRQ handler\n");
return TEST_RESULT_FAIL;
@@ -116,7 +118,7 @@
* In release builds though, it should just do nothing.
*/
#if !DEBUG
- ret = tftf_irq_unregister_handler(sgi_id);
+ ret = tftf_irq_unregister_handler_sgi(sgi_id);
if (ret == 0) {
tftf_testcase_printf(
"Unregistering the IRQ handler again should have failed\n");
@@ -124,7 +126,7 @@
}
#endif
- tftf_irq_disable(sgi_id);
+ tftf_irq_disable_sgi(sgi_id);
return TEST_RESULT_SUCCESS;
}
diff --git a/tftf/tests/framework_validation_tests/test_validation_sgi.c b/tftf/tests/framework_validation_tests/test_validation_sgi.c
index 0f9ac9b..cafcb7a 100644
--- a/tftf/tests/framework_validation_tests/test_validation_sgi.c
+++ b/tftf/tests/framework_validation_tests/test_validation_sgi.c
@@ -45,17 +45,18 @@
unsigned int mpid = read_mpidr_el1();
unsigned int core_pos = platform_get_core_pos(mpid);
const unsigned int sgi_id = IRQ_NS_SGI_0;
+ const unsigned int sgi_irq = tftf_irq_get_my_sgi_num(sgi_id);
test_result_t test_res = TEST_RESULT_SUCCESS;
int ret;
/* Register the local IRQ handler for the SGI */
- ret = tftf_irq_register_handler(sgi_id, sgi_handler);
+ ret = tftf_irq_register_handler_sgi(sgi_id, sgi_handler);
if (ret != 0) {
tftf_testcase_printf("Failed to register IRQ %u (%d)",
sgi_id, ret);
return TEST_RESULT_FAIL;
}
- tftf_irq_enable(sgi_id, GIC_HIGHEST_NS_PRIORITY);
+ tftf_irq_enable_sgi(sgi_id, GIC_HIGHEST_NS_PRIORITY);
/* Send the SGI to the lead CPU */
tftf_send_sgi(sgi_id, core_pos);
@@ -68,14 +69,14 @@
continue;
/* Verify the data received in the SGI handler */
- if (sgi_data != sgi_id) {
+ if (sgi_data != sgi_irq) {
tftf_testcase_printf("Wrong IRQ ID, expected %u, got %u\n",
- sgi_id, sgi_data);
+ sgi_irq, sgi_data);
test_res = TEST_RESULT_FAIL;
}
- tftf_irq_disable(sgi_id);
- tftf_irq_unregister_handler(sgi_id);
+ tftf_irq_disable_sgi(sgi_id);
+ tftf_irq_unregister_handler_sgi(sgi_id);
return test_res;
}
diff --git a/tftf/tests/misc_tests/test_pmu_leakage.c b/tftf/tests/misc_tests/test_pmu_leakage.c
index 9b2f735..82b81f4 100644
--- a/tftf/tests/misc_tests/test_pmu_leakage.c
+++ b/tftf/tests/misc_tests/test_pmu_leakage.c
@@ -182,7 +182,7 @@
power_state = tftf_make_psci_pstate(MPIDR_AFFLVL0,
PSTATE_TYPE_STANDBY, stateid);
- tftf_irq_enable(IRQ_NS_SGI_0, GIC_HIGHEST_NS_PRIORITY);
+ tftf_irq_enable_sgi(IRQ_NS_SGI_0, GIC_HIGHEST_NS_PRIORITY);
/*
* Mask IRQ to prevent the interrupt handler being invoked
@@ -203,7 +203,7 @@
enable_irq();
isb();
- tftf_irq_disable(IRQ_NS_SGI_0);
+ tftf_irq_disable_sgi(IRQ_NS_SGI_0);
return evt_cnt;
}
@@ -241,7 +241,7 @@
cnt_sum += evt_cnt;
- tftf_irq_disable(IRQ_NS_SGI_0);
+ tftf_irq_disable_sgi(IRQ_NS_SGI_0);
}
avg_cnt = cnt_sum / ITERATIONS_CNT;
diff --git a/tftf/tests/misc_tests/test_ras_kfh_reflect.c b/tftf/tests/misc_tests/test_ras_kfh_reflect.c
index 7d771a4..9392231 100644
--- a/tftf/tests/misc_tests/test_ras_kfh_reflect.c
+++ b/tftf/tests/misc_tests/test_ras_kfh_reflect.c
@@ -89,12 +89,12 @@
waitms(50);
- ret = tftf_irq_register_handler(sgi_id, irq_handler);
+ ret = tftf_irq_register_handler_sgi(sgi_id, irq_handler);
if (ret != 0) {
tftf_testcase_printf("Failed to register initial IRQ handler\n");
return TEST_RESULT_FAIL;
}
- tftf_irq_enable(sgi_id, GIC_HIGHEST_NS_PRIORITY);
+ tftf_irq_enable_sgi(sgi_id, GIC_HIGHEST_NS_PRIORITY);
tftf_send_sgi(sgi_id, core_pos);
if ((serror_triggered == false) || (irq_triggered == false)) {
@@ -102,7 +102,7 @@
return TEST_RESULT_FAIL;
}
- ret = tftf_irq_unregister_handler(sgi_id);
+ ret = tftf_irq_unregister_handler_sgi(sgi_id);
if (ret != 0) {
tftf_testcase_printf("Failed to unregister IRQ handler\n");
return TEST_RESULT_FAIL;
diff --git a/tftf/tests/runtime_services/realm_payload/host_realm_payload_multiple_rec_tests.c b/tftf/tests/runtime_services/realm_payload/host_realm_payload_multiple_rec_tests.c
index 883102e..fb60988 100644
--- a/tftf/tests/runtime_services/realm_payload/host_realm_payload_multiple_rec_tests.c
+++ b/tftf/tests/runtime_services/realm_payload/host_realm_payload_multiple_rec_tests.c
@@ -284,12 +284,12 @@
}
destroy_realm:
- tftf_irq_enable(IRQ_NS_SGI_7, GIC_HIGHEST_NS_PRIORITY);
+ tftf_irq_enable_sgi(IRQ_NS_SGI_7, GIC_HIGHEST_NS_PRIORITY);
for (unsigned int i = 1U; i < rec_count; i++) {
INFO("Raising NS IRQ for rec %u\n", i);
host_rec_send_sgi(&realm, IRQ_NS_SGI_7, i);
}
- tftf_irq_disable(IRQ_NS_SGI_7);
+ tftf_irq_disable_sgi(IRQ_NS_SGI_7);
ret2 = host_destroy_realm(&realm);
if (!ret1 || !ret2) {
ERROR("%s(): enter=%d destroy=%d\n",
diff --git a/tftf/tests/runtime_services/realm_payload/host_realm_payload_tests.c b/tftf/tests/runtime_services/realm_payload/host_realm_payload_tests.c
index be999c3..015728d 100644
--- a/tftf/tests/runtime_services/realm_payload/host_realm_payload_tests.c
+++ b/tftf/tests/runtime_services/realm_payload/host_realm_payload_tests.c
@@ -12,6 +12,7 @@
#include <irq.h>
#include <drivers/arm/arm_gic.h>
#include <drivers/arm/gic_v3.h>
+#include <drivers/arm/gic_v5.h>
#include <heap/page_alloc.h>
#include <lib/context_mgmt/context_el1.h>
#include <lib/context_mgmt/context_el2.h>
@@ -39,6 +40,22 @@
static uint128_t pauth_keys_after[NUM_KEYS];
#endif
+static unsigned int tftf_get_pmu_irq(void)
+{
+ if (arm_gic_get_version() == 5)
+ return PMU_PPI | INPLACE(INT_TYPE, INT_PPI);
+ else
+ return PMU_PPI;
+}
+
+static unsigned int tftf_get_pmu_virq(void)
+{
+ if (arm_gic_get_version() == 5)
+ return PMU_VIRQ | INPLACE(INT_TYPE, INT_PPI);
+ else
+ return PMU_VIRQ;
+}
+
/*
* @Test_Aim@ Test RSI_PLANE_SYSREG_READ/WRITE
*/
@@ -669,8 +686,8 @@
u_register_t exit_reason, retrmm;
int ret;
- tftf_irq_disable(PMU_PPI);
- ret = tftf_irq_unregister_handler(PMU_PPI);
+ tftf_irq_disable(tftf_get_pmu_irq());
+ ret = tftf_irq_unregister_handler(tftf_get_pmu_irq());
if (ret != 0) {
ERROR("Failed to %sregister IRQ handler\n", "un");
return false;
@@ -679,10 +696,10 @@
/* Inject PMU virtual interrupt */
run->entry.gicv3_lrs[0] =
ICH_LRn_EL2_STATE_Pending | ICH_LRn_EL2_Group_1 |
- (PMU_VIRQ << ICH_LRn_EL2_vINTID_SHIFT);
+ (tftf_get_pmu_virq() << ICH_LRn_EL2_vINTID_SHIFT);
/* Re-enter Realm */
- INFO("Re-entering Realm with vIRQ %lu pending\n", PMU_VIRQ);
+ INFO("Re-entering Realm with vIRQ %u pending\n", tftf_get_pmu_virq());
retrmm = host_realm_rec_enter(realm_ptr, &exit_reason,
&host_call_result, rec_num);
@@ -810,17 +827,17 @@
test_result_t ret;
/* Register PMU IRQ handler */
- if (tftf_irq_register_handler(PMU_PPI, host_overflow_interrupt) != 0) {
+ if (tftf_irq_register_handler(tftf_get_pmu_irq(), host_overflow_interrupt) != 0) {
tftf_testcase_printf("Failed to %sregister IRQ handler\n", "");
return TEST_RESULT_FAIL;
}
- tftf_irq_enable(PMU_PPI, GIC_HIGHEST_NS_PRIORITY);
+ tftf_irq_enable(tftf_get_pmu_irq(), GIC_HIGHEST_NS_PRIORITY);
ret = host_test_realm_pmuv3(cmd);
if (ret != TEST_RESULT_SUCCESS) {
- tftf_irq_disable(PMU_PPI);
- if (tftf_irq_unregister_handler(PMU_PPI) != 0) {
+ tftf_irq_disable(tftf_get_pmu_irq());
+ if (tftf_irq_unregister_handler(tftf_get_pmu_irq()) != 0) {
ERROR("Failed to %sregister IRQ handler\n", "un");
return TEST_RESULT_FAIL;
}
diff --git a/tftf/tests/runtime_services/standard_service/psci/api_tests/affinity_info/test_psci_affinity_info.c b/tftf/tests/runtime_services/standard_service/psci/api_tests/affinity_info/test_psci_affinity_info.c
index 2697fac..6e7f3f7 100644
--- a/tftf/tests/runtime_services/standard_service/psci/api_tests/affinity_info/test_psci_affinity_info.c
+++ b/tftf/tests/runtime_services/standard_service/psci/api_tests/affinity_info/test_psci_affinity_info.c
@@ -354,7 +354,7 @@
* Enable reception of SGI 0 on the calling CPU.
* SGI 0 will serve as the wake-up event to come out of suspend.
*/
- tftf_irq_enable(IRQ_NS_SGI_0, GIC_HIGHEST_NS_PRIORITY);
+ tftf_irq_enable_sgi(IRQ_NS_SGI_0, GIC_HIGHEST_NS_PRIORITY);
expected_return_val = tftf_psci_make_composite_state_id(
PSTATE_AFF_LVL_0, PSTATE_TYPE_POWERDOWN, &stateid);
@@ -377,7 +377,7 @@
psci_ret = tftf_cpu_suspend(power_state);
- tftf_irq_disable(IRQ_NS_SGI_0);
+ tftf_irq_disable_sgi(IRQ_NS_SGI_0);
if (psci_ret != PSCI_E_SUCCESS) {
tftf_testcase_printf("Failed to suspend (%i)\n", psci_ret);
diff --git a/tftf/tests/runtime_services/standard_service/psci/api_tests/cpu_suspend/test_suspend.c b/tftf/tests/runtime_services/standard_service/psci/api_tests/cpu_suspend/test_suspend.c
index e802d43..ba67ab1 100644
--- a/tftf/tests/runtime_services/standard_service/psci/api_tests/cpu_suspend/test_suspend.c
+++ b/tftf/tests/runtime_services/standard_service/psci/api_tests/cpu_suspend/test_suspend.c
@@ -49,7 +49,7 @@
unsigned int irq_id = *(unsigned int *) data;
#endif
- assert(irq_id == IRQ_WAKE_SGI || irq_id == tftf_get_timer_irq());
+ assert(irq_id == tftf_irq_get_my_sgi_num(IRQ_WAKE_SGI) || irq_id == tftf_get_timer_irq());
assert(requested_irq_received[core_pos] == 0);
requested_irq_received[core_pos] = 1;
diff --git a/tftf/tests/runtime_services/standard_service/psci/api_tests/system_suspend/test_psci_system_suspend.c b/tftf/tests/runtime_services/standard_service/psci/api_tests/system_suspend/test_psci_system_suspend.c
index e79293b..4563bcb 100644
--- a/tftf/tests/runtime_services/standard_service/psci/api_tests/system_suspend/test_psci_system_suspend.c
+++ b/tftf/tests/runtime_services/standard_service/psci/api_tests/system_suspend/test_psci_system_suspend.c
@@ -323,14 +323,14 @@
int sgi_ret;
/* Register the local IRQ handler for the SGI */
- sgi_ret = tftf_irq_register_handler(sgi_id, sgi_handler);
+ sgi_ret = tftf_irq_register_handler_sgi(sgi_id, sgi_handler);
if (sgi_ret != 0) {
tftf_testcase_printf("Failed to register IRQ %u (%d)",
sgi_id, sgi_ret);
return TEST_RESULT_FAIL;
}
/* Enable SGI */
- tftf_irq_enable(sgi_id, GIC_HIGHEST_NS_PRIORITY);
+ tftf_irq_enable_sgi(sgi_id, GIC_HIGHEST_NS_PRIORITY);
/* Signal to the lead CPU that we are ready to receive SGI */
tftf_send_event(&cpu_ready[core_pos]);
@@ -342,8 +342,8 @@
tftf_send_event(&sgi_received[core_pos]);
/* Unregister SGI handler */
- tftf_irq_disable(sgi_id);
- tftf_irq_unregister_handler(sgi_id);
+ tftf_irq_disable_sgi(sgi_id);
+ tftf_irq_unregister_handler_sgi(sgi_id);
return TEST_RESULT_SUCCESS;
}
@@ -458,6 +458,7 @@
{
unsigned int core_pos = platform_get_core_pos(read_mpidr_el1());
const unsigned int sgi_id = IRQ_NS_SGI_0;
+ const unsigned int sgi_irq = tftf_irq_get_my_sgi_num(sgi_id);
int sgi_ret;
int psci_ret;
test_result_t ret = TEST_RESULT_SUCCESS;
@@ -473,7 +474,7 @@
wakeup_irq_rcvd[core_pos] = 0;
/* Register the local IRQ handler for the SGI */
- sgi_ret = tftf_irq_register_handler(sgi_id, sgi_handler);
+ sgi_ret = tftf_irq_register_handler_sgi(sgi_id, sgi_handler);
if (sgi_ret != 0) {
tftf_testcase_printf("Failed to register IRQ %u (%d)",
sgi_id, sgi_ret);
@@ -489,7 +490,7 @@
*/
tftf_program_timer(SUSPEND_TIME_3_SECS);
- tftf_irq_enable(sgi_id, GIC_HIGHEST_NS_PRIORITY);
+ tftf_irq_enable_sgi(sgi_id, GIC_HIGHEST_NS_PRIORITY);
disable_irq();
/* Send the SGI to the lead CPU */
@@ -517,9 +518,9 @@
;
/* Verify the sgi data received by the SGI handler */
- if (sgi_data != sgi_id) {
+ if (sgi_data != sgi_irq) {
tftf_testcase_printf("Wrong IRQ ID, expected %u, got %u\n",
- sgi_id, sgi_data);
+ sgi_irq, sgi_data);
ret = TEST_RESULT_FAIL;
}
@@ -531,8 +532,8 @@
tftf_cancel_timer();
/* Unregister SGI handler */
- tftf_irq_disable(sgi_id);
- tftf_irq_unregister_handler(sgi_id);
+ tftf_irq_disable_sgi(sgi_id);
+ tftf_irq_unregister_handler_sgi(sgi_id);
return ret;
}
@@ -662,13 +663,13 @@
unsigned int core_pos = platform_get_core_pos(mpid);
int ret;
- tftf_irq_enable(IRQ_NS_SGI_0, GIC_HIGHEST_NS_PRIORITY);
+ tftf_irq_enable_sgi(IRQ_NS_SGI_0, GIC_HIGHEST_NS_PRIORITY);
/* Tell the lead CPU that the calling CPU is about to suspend itself */
tftf_send_event(&cpu_ready[core_pos]);
ret = tftf_cpu_suspend(deepest_power_state);
- tftf_irq_disable(IRQ_NS_SGI_0);
+ tftf_irq_disable_sgi(IRQ_NS_SGI_0);
if (ret) {
ERROR(" CPU suspend failed with error %x\n", ret);
diff --git a/tftf/tests/runtime_services/standard_service/psci/api_tests/validate_power_state/test_validate_power_state.c b/tftf/tests/runtime_services/standard_service/psci/api_tests/validate_power_state/test_validate_power_state.c
index 565914b..ac3b338 100644
--- a/tftf/tests/runtime_services/standard_service/psci/api_tests/validate_power_state/test_validate_power_state.c
+++ b/tftf/tests/runtime_services/standard_service/psci/api_tests/validate_power_state/test_validate_power_state.c
@@ -408,8 +408,8 @@
test_result_t ret;
unsigned int core_pos = platform_get_core_pos(read_mpidr_el1());
- tftf_irq_register_handler(IRQ_NS_SGI_0, validate_pstate_sgi_handler);
- tftf_irq_enable(IRQ_NS_SGI_0, GIC_HIGHEST_NS_PRIORITY);
+ tftf_irq_register_handler_sgi(IRQ_NS_SGI_0, validate_pstate_sgi_handler);
+ tftf_irq_enable_sgi(IRQ_NS_SGI_0, GIC_HIGHEST_NS_PRIORITY);
/*
* Mask IRQ to prevent the interrupt handler being invoked
@@ -428,8 +428,8 @@
while (!sgi_received[core_pos])
;
- tftf_irq_disable(IRQ_NS_SGI_0);
- tftf_irq_unregister_handler(IRQ_NS_SGI_0);
+ tftf_irq_disable_sgi(IRQ_NS_SGI_0);
+ tftf_irq_unregister_handler_sgi(IRQ_NS_SGI_0);
return ret;
}
diff --git a/tftf/tests/runtime_services/standard_service/sdei/system_tests/test_sdei_bind_failure.c b/tftf/tests/runtime_services/standard_service/sdei/system_tests/test_sdei_bind_failure.c
index a553adf..6a8c0e0 100644
--- a/tftf/tests/runtime_services/standard_service/sdei/system_tests/test_sdei_bind_failure.c
+++ b/tftf/tests/runtime_services/standard_service/sdei/system_tests/test_sdei_bind_failure.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2024-2025, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -8,6 +8,7 @@
#include <tftf_lib.h>
#include <sdei.h>
#include <drivers/arm/arm_gic.h>
+#include <drivers/arm/gic_v2v3_common.h>
/*
* Only this many events can be bound in the PPI range. If you attempt to bind
diff --git a/tftf/tests/runtime_services/trusted_os/tsp/test_irq_preempted_std_smc.c b/tftf/tests/runtime_services/trusted_os/tsp/test_irq_preempted_std_smc.c
index 3e24ccd..3af35ad 100644
--- a/tftf/tests/runtime_services/trusted_os/tsp/test_irq_preempted_std_smc.c
+++ b/tftf/tests/runtime_services/trusted_os/tsp/test_irq_preempted_std_smc.c
@@ -66,7 +66,7 @@
{
/* SGIs #0 - #6 are freely available. */
- int ret = tftf_irq_register_handler(IRQ_NS_SGI_0, test_handler);
+ int ret = tftf_irq_register_handler_sgi(IRQ_NS_SGI_0, test_handler);
if (ret != 0) {
tftf_testcase_printf(
@@ -75,7 +75,7 @@
return -1;
}
- tftf_irq_enable(IRQ_NS_SGI_0, GIC_HIGHEST_NS_PRIORITY);
+ tftf_irq_enable_sgi(IRQ_NS_SGI_0, GIC_HIGHEST_NS_PRIORITY);
return 0;
}
@@ -83,9 +83,9 @@
/* Disable and unregister the dummy handler for SGI #0. */
static void unregister_and_disable_test_sgi_handler(void)
{
- tftf_irq_disable(IRQ_NS_SGI_0);
+ tftf_irq_disable_sgi(IRQ_NS_SGI_0);
- tftf_irq_unregister_handler(IRQ_NS_SGI_0);
+ tftf_irq_unregister_handler_sgi(IRQ_NS_SGI_0);
}
/*
diff --git a/tftf/tests/runtime_services/trusted_os/tsp/test_normal_int_switch.c b/tftf/tests/runtime_services/trusted_os/tsp/test_normal_int_switch.c
index eb04006..d038f86 100644
--- a/tftf/tests/runtime_services/trusted_os/tsp/test_normal_int_switch.c
+++ b/tftf/tests/runtime_services/trusted_os/tsp/test_normal_int_switch.c
@@ -64,7 +64,7 @@
shared_data.wait_for_fiq = 1;
/* Register Handler for the interrupt. SGIs #0 - #6 are available. */
- rc = tftf_irq_register_handler(IRQ_NS_SGI_0, sgi_handler);
+ rc = tftf_irq_register_handler_sgi(IRQ_NS_SGI_0, sgi_handler);
if (rc != 0) {
tftf_testcase_printf("Failed to register SGI handler. "
"Error code = %d\n", rc);
@@ -72,7 +72,7 @@
}
/* Enable SGI #0 */
- tftf_irq_enable(IRQ_NS_SGI_0, GIC_HIGHEST_NS_PRIORITY);
+ tftf_irq_enable_sgi(IRQ_NS_SGI_0, GIC_HIGHEST_NS_PRIORITY);
/* Set PSTATE.I to 0. */
disable_irq();
@@ -99,10 +99,10 @@
enable_irq();
/* Disable SGI #0 */
- tftf_irq_disable(IRQ_NS_SGI_0);
+ tftf_irq_disable_sgi(IRQ_NS_SGI_0);
/* Unregister handler */
- rc = tftf_irq_unregister_handler(IRQ_NS_SGI_0);
+ rc = tftf_irq_unregister_handler_sgi(IRQ_NS_SGI_0);
if (rc != 0) {
tftf_testcase_printf("Failed to unregister IRQ handler. "
"Error code = %d\n", rc);