The GICv5 IRS may have inbound GPIO lines corresponding to SPIs
(shared peripheral interrupts). Unlike the GICv3, it does not deal
with PPIs (private peripheral interrupts, i.e. per-CPU interrupts):
in a GICv5 system those are handled entirely within the CPU
interface. The inbound GPIO array is therefore a simple sequence of
one GPIO per SPI that this IRS handles.
Create the GPIO input array in gicv5_common_init_irqs_and_mmio().
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
---
hw/intc/arm_gicv5.c | 11 ++++++++++-
hw/intc/arm_gicv5_common.c | 5 +++++
hw/intc/trace-events | 1 +
include/hw/intc/arm_gicv5_common.h | 4 ++++
4 files changed, 20 insertions(+), 1 deletion(-)
diff --git a/hw/intc/arm_gicv5.c b/hw/intc/arm_gicv5.c
index 64bec16bdd..cb1234b022 100644
--- a/hw/intc/arm_gicv5.c
+++ b/hw/intc/arm_gicv5.c
@@ -160,6 +160,15 @@ static const MemoryRegionOps config_frame_ops[NUM_GICV5_DOMAINS] = {
FRAME_OP_ENTRY(el3, GICV5_ID_EL3),
};
+static void gicv5_set_spi(void *opaque, int irq, int level)
+{
+ /* These irqs are all SPIs; the INTID is irq + s->spi_base */
+ GICv5Common *cs = ARM_GICV5_COMMON(opaque);
+ uint32_t spi_id = irq + cs->spi_base;
+
+ trace_gicv5_spi(spi_id, level);
+}
+
static void gicv5_reset_hold(Object *obj, ResetType type)
{
GICv5 *s = ARM_GICV5(obj);
@@ -196,7 +205,7 @@ static void gicv5_realize(DeviceState *dev, Error **errp)
* NS domain.
*/
cs->implemented_domains = (1 << GICV5_ID_NS);
- gicv5_common_init_irqs_and_mmio(cs, config_frame_ops);
+ gicv5_common_init_irqs_and_mmio(cs, gicv5_set_spi, config_frame_ops);
}
static void gicv5_init(Object *obj)
diff --git a/hw/intc/arm_gicv5_common.c b/hw/intc/arm_gicv5_common.c
index 3448734686..b58913b970 100644
--- a/hw/intc/arm_gicv5_common.c
+++ b/hw/intc/arm_gicv5_common.c
@@ -38,10 +38,15 @@ static const MemoryRegionOps bad_frame_ops = {
};
void gicv5_common_init_irqs_and_mmio(GICv5Common *cs,
+ qemu_irq_handler handler,
const MemoryRegionOps config_ops[NUM_GICV5_DOMAINS])
{
SysBusDevice *sbd = SYS_BUS_DEVICE(cs);
+ if (cs->spi_irs_range) {
+ qdev_init_gpio_in(DEVICE(cs), handler, cs->spi_irs_range);
+ }
+
for (int i = 0; i < NUM_GICV5_DOMAINS; i++) {
g_autofree char *memname = g_strdup_printf("gicv5-irs-%d", i);
const MemoryRegionOps *ops = gicv5_domain_implemented(cs, i) ?
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
index 54777f6da3..0797a23c1a 100644
--- a/hw/intc/trace-events
+++ b/hw/intc/trace-events
@@ -232,6 +232,7 @@ gicv5_read(const char *domain, uint64_t offset, uint64_t data, unsigned size) "G
gicv5_badread(const char *domain, uint64_t offset, unsigned size) "GICv5 IRS %s config frame read: offset 0x%" PRIx64 " size %u: error"
gicv5_write(const char *domain, uint64_t offset, uint64_t data, unsigned size) "GICv5 IRS %s config frame write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
gicv5_badwrite(const char *domain, uint64_t offset, uint64_t data, unsigned size) "GICv5 IRS %s config frame write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u: error"
+gicv5_spi(uint32_t id, int level) "GICv5 SPI ID %u asserted at level %d"
# arm_gicv5_common.c
gicv5_common_realize(uint32_t irsid, uint32_t num_cpus, uint32_t spi_base, uint32_t spi_irs_range, uint32_t spi_range) "GICv5 IRS realized: IRS ID %u, %u CPUs, SPI base %u, SPI IRS range %u, SPI range %u"
diff --git a/include/hw/intc/arm_gicv5_common.h b/include/hw/intc/arm_gicv5_common.h
index ea01b2a1db..10276d652f 100644
--- a/include/hw/intc/arm_gicv5_common.h
+++ b/include/hw/intc/arm_gicv5_common.h
@@ -29,6 +29,9 @@
* IRS (this is IRS_IDR7.SPI_BASE); default is 0
* + QOM property "spi-irs-range": number of SPI INTID.ID managed on this
* IRS (this is IRS_IDR6.SPI_IRS_RANGE); defaults to value of spi-range
+ * + unnamed GPIO inputs: the SPIs handled by this IRS
+ * (so GPIO input 0 is the SPI with INTID SPI_BASE, input 1 is
+ * SPI_BASE + 1, and so on up to SPI_BASE + SPI_IRS_RANGE - 1)
*
* sysbus MMIO regions (in order matching IRS_IDR0.INT_DOM encoding):
* - IRS config frame for the Secure Interrupt Domain
@@ -91,6 +94,7 @@ struct GICv5CommonClass {
* of MemoryRegionOps structs.
*/
void gicv5_common_init_irqs_and_mmio(GICv5Common *cs,
+ qemu_irq_handler handler,
const MemoryRegionOps ops[NUM_GICV5_DOMAINS]);
/**
--
2.43.0