hw/intc/arm_gicv5: Implement Deactivate command

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 <peter.maydell@linaro.org>
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
Message-id: 20260327111700.795099-51-peter.maydell@linaro.org
This commit is contained in:
Peter Maydell
2026-03-27 11:16:45 +00:00
parent 7070e62c1b
commit 576891bc31
3 changed files with 67 additions and 0 deletions

View File

@@ -1153,6 +1153,58 @@ 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)
{
GICv5 *s = ARM_GICV5(cs);
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;
}
switch (type) {
case GICV5_LPI:
{
const GICv5ISTConfig *cfg = &s->phys_lpi_config[domain];
L2_ISTE_Handle h;
uint32_t *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);
break;
}
case 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;
iaffid = spi->iaffid;
break;
}
default:
qemu_log_mask(LOG_GUEST_ERROR, "gicv5_deactivate: tried to "
"deactivate bad interrupt type %d\n", type);
return;
}
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);

View File

@@ -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"

View File

@@ -211,4 +211,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