Implement the equivalent of the GICv5 stream protocol's Deactivate command, which lets the cpuif tell the IRS to deactivate the specified interrupt.
Signed-off-by: Peter Maydell <[email protected]> --- hw/intc/arm_gicv5.c | 46 ++++++++++++++++++++++++++++++ hw/intc/trace-events | 1 + include/hw/intc/arm_gicv5_stream.h | 14 +++++++++ 3 files changed, 61 insertions(+) diff --git a/hw/intc/arm_gicv5.c b/hw/intc/arm_gicv5.c index 6636a66976..0509a958ff 100644 --- a/hw/intc/arm_gicv5.c +++ b/hw/intc/arm_gicv5.c @@ -1113,6 +1113,52 @@ void gicv5_activate(GICv5Common *cs, uint32_t id, GICv5Domain domain, irs_recalc_hppi(s, domain, iaffid); } +void gicv5_deactivate(GICv5Common *cs, uint32_t id, GICv5Domain domain, + GICv5IntType type, bool virtual) +{ + const GICv5ISTConfig *cfg; + GICv5 *s = ARM_GICV5(cs); + uint32_t *l2_iste_p; + L2_ISTE_Handle h; + uint32_t iaffid; + + trace_gicv5_deactivate(domain_name[domain], inttype_name(type), virtual, id); + + if (virtual) { + qemu_log_mask(LOG_GUEST_ERROR, "gicv5_deactivate: tried to " + "deactivate a virtual interrupt\n"); + return; + } + if (type == GICV5_SPI) { + GICv5SPIState *spi = gicv5_spi_state(cs, id, domain); + + if (!spi) { + qemu_log_mask(LOG_GUEST_ERROR, "gicv5_deactivate: tried to " + "deactivate unreachable SPI %d\n", id); + return; + } + + spi->active = false; + irs_recalc_hppi(s, domain, spi->iaffid); + return; + } + if (type != GICV5_LPI) { + qemu_log_mask(LOG_GUEST_ERROR, "gicv5_deactivate: tried to " + "deactivate bad interrupt type %d\n", type); + return; + } + cfg = &s->phys_lpi_config[domain]; + l2_iste_p = get_l2_iste(cs, cfg, id, &h); + if (!l2_iste_p) { + return; + } + *l2_iste_p = FIELD_DP32(*l2_iste_p, L2_ISTE, ACTIVE, false); + iaffid = FIELD_EX32(*l2_iste_p, L2_ISTE, IAFFID); + put_l2_iste(cs, cfg, &h); + + irs_recalc_hppi(s, domain, iaffid); +} + static void irs_map_l2_istr_write(GICv5 *s, GICv5Domain domain, uint64_t value) { GICv5Common *cs = ARM_GICV5_COMMON(s); diff --git a/hw/intc/trace-events b/hw/intc/trace-events index 636c598970..c6696f0e0a 100644 --- a/hw/intc/trace-events +++ b/hw/intc/trace-events @@ -242,6 +242,7 @@ gicv5_set_handling(const char *domain, const char *type, bool virtual, uint32_t gicv5_set_target(const char *domain, const char *type, bool virtual, uint32_t id, uint32_t iaffid, int irm) "GICv5 IRS SetTarget %s %s virtual:%d ID %u IAFFID %u routingmode %d" gicv5_request_config(const char *domain, const char *type, bool virtual, uint32_t id, uint64_t icsr) "GICv5 IRS RequestConfig %s %s virtual:%d ID %u ICSR 0x%" PRIx64 gicv5_activate(const char *domain, const char *type, bool virtual, uint32_t id) "GICv5 IRS Activate %s %s virtual:%d ID %u" +gicv5_deactivate(const char *domain, const char *type, bool virtual, uint32_t id) "GICv5 IRS Deactivate %s %s virtual:%d ID %u" gicv5_spi_state(uint32_t spi_id, bool level, bool pending, bool active) "GICv5 IRS SPI ID %u now level %d pending %d active %d" gicv5_irs_recalc_hppi_fail(const char *domain, uint32_t iaffid, const char *reason) "GICv5 IRS %s IAFFID %u: no HPPI: %s" gicv5_irs_recalc_hppi(const char *domain, uint32_t iaffid, uint32_t id, uint8_t prio) "GICv5 IRS %s IAFFID %u: new HPPI ID 0x%x prio %u" diff --git a/include/hw/intc/arm_gicv5_stream.h b/include/hw/intc/arm_gicv5_stream.h index 7adb53c86d..f6783cc6b5 100644 --- a/include/hw/intc/arm_gicv5_stream.h +++ b/include/hw/intc/arm_gicv5_stream.h @@ -212,4 +212,18 @@ void gicv5_forward_interrupt(ARMCPU *cpu, GICv5Domain domain); GICv5PendingIrq gicv5_get_hppi(GICv5Common *cs, GICv5Domain domain, uint32_t iaffid); +/** + * gicv5_deactivate + * @cs: GIC IRS to send command to + * @id: interrupt ID + * @domain: interrupt Domain to act on + * @type: interrupt type (LPI or SPI) + * @virtual: true if this is a virtual interrupt + * + * Deactivate the specified interrupt. There is no report back + * of success/failure to the CPUIF in the protocol. + */ +void gicv5_deactivate(GICv5Common *cs, uint32_t id, GICv5Domain domain, + GICv5IntType type, bool virtual); + #endif -- 2.43.0
