@samitouri / QOSamiQemu / commits / 5beb48ab53

hw/intc/arm_gicv5: Make gicv5_set_* update SPI state

The GIC CD* insns that update interrupt state also work for SPIs. Instead of ignoring the GICV5_SPI type in gicv5_set_priority() and friends, update the state in our SPI state array. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Message-id: 20260327111700.795099-25-peter.maydell@linaro.org

Peter Maydell committed Mar 27, 2026 at 11:16 UTC 5beb48ab53d57c0378c19c04941ccab2d2ab925e
2 files changed +104
hw/intc/arm_gicv5.c
+64
@@ -490,6 +490,19 @@ void gicv5_set_priority(GICv5Common *cs, uint32_t id, uint8_t priority,
490 put_l2_iste(cs, cfg, &h);
491 break;
492 }
493 + case GICV5_SPI:
494 + {
495 + GICv5SPIState *spi = gicv5_spi_state(cs, id, domain);
496 +
497 + if (!spi) {
498 + qemu_log_mask(LOG_GUEST_ERROR, "gicv5_set_priority: tried to set "
499 + "priority of unreachable SPI %d\n", id);
500 + return;
501 + }
502 +
503 + spi->priority = priority;
504 + break;
505 + }
506 default:
507 qemu_log_mask(LOG_GUEST_ERROR, "gicv5_set_priority: tried to set "
508 "priority of bad interrupt type %d\n", type);
@@ -524,6 +537,19 @@ void gicv5_set_enabled(GICv5Common *cs, uint32_t id, bool enabled,
537 put_l2_iste(cs, cfg, &h);
538 break;
539 }
540 + case GICV5_SPI:
541 + {
542 + GICv5SPIState *spi = gicv5_spi_state(cs, id, domain);
543 +
544 + if (!spi) {
545 + qemu_log_mask(LOG_GUEST_ERROR, "gicv5_set_enabled: tried to set "
546 + "enable state of unreachable SPI %d\n", id);
547 + return;
548 + }
549 +
550 + spi->enabled = true;
551 + break;
552 + }
553 default:
554 qemu_log_mask(LOG_GUEST_ERROR, "gicv5_set_enabled: tried to set "
555 "enable state of bad interrupt type %d\n", type);
@@ -558,6 +584,19 @@ void gicv5_set_pending(GICv5Common *cs, uint32_t id, bool pending,
584 put_l2_iste(cs, cfg, &h);
585 break;
586 }
587 + case GICV5_SPI:
588 + {
589 + GICv5SPIState *spi = gicv5_spi_state(cs, id, domain);
590 +
591 + if (!spi) {
592 + qemu_log_mask(LOG_GUEST_ERROR, "gicv5_set_pending: tried to set "
593 + "pending state of unreachable SPI %d\n", id);
594 + return;
595 + }
596 +
597 + spi->pending = true;
598 + break;
599 + }
600 default:
601 qemu_log_mask(LOG_GUEST_ERROR, "gicv5_set_pending: tried to set "
602 "pending state of bad interrupt type %d\n", type);
@@ -593,6 +632,18 @@ void gicv5_set_handling(GICv5Common *cs, uint32_t id,
632 put_l2_iste(cs, cfg, &h);
633 break;
634 }
635 + case GICV5_SPI:
636 + {
637 + GICv5SPIState *spi = gicv5_spi_state(cs, id, domain);
638 +
639 + if (!spi) {
640 + qemu_log_mask(LOG_GUEST_ERROR, "gicv5_set_handling: tried to set "
641 + "priority of unreachable SPI %d\n", id);
642 + }
643 +
644 + spi->hm = handling;
645 + break;
646 + }
647 default:
648 qemu_log_mask(LOG_GUEST_ERROR, "gicv5_set_handling: tried to set "
649 "handling mode of bad interrupt type %d\n", type);
@@ -642,6 +693,19 @@ void gicv5_set_target(GICv5Common *cs, uint32_t id, uint32_t iaffid,
693 put_l2_iste(cs, cfg, &h);
694 break;
695 }
696 + case GICV5_SPI:
697 + {
698 + GICv5SPIState *spi = gicv5_spi_state(cs, id, domain);
699 +
700 + if (!spi) {
701 + qemu_log_mask(LOG_GUEST_ERROR, "gicv5_set_target: tried to set "
702 + "target of unreachable SPI %d\n", id);
703 + return;
704 + }
705 +
706 + spi->iaffid = iaffid;
707 + break;
708 + }
709 default:
710 qemu_log_mask(LOG_GUEST_ERROR, "gicv5_set_target: tried to set "
711 "target of bad interrupt type %d\n", type);
include/hw/intc/arm_gicv5_common.h
+40
@@ -200,4 +200,44 @@ static inline const char *gicv5_class_name(void)
200 return "arm-gicv5";
201 }
202
203 +/**
204 + * gicv5_raw_spi_state
205 + * @cs: GIC object
206 + * @id: INTID of SPI to look up
207 + *
208 + * Return pointer to the GICv5SPIState for this SPI, or NULL if the
209 + * interrupt ID is out of range. This does not do a check that the SPI
210 + * is assigned to the right domain: generally you should call it via
211 + * some other wrapper that performs an appropriate further check.
212 + */
213 +static inline GICv5SPIState *gicv5_raw_spi_state(GICv5Common *cs, uint32_t id)
214 +{
215 + if (id < cs->spi_base || id >= cs->spi_base + cs->spi_irs_range) {
216 + return NULL;
217 + }
218 +
219 + return cs->spi + (id - cs->spi_base);
220 +}
221 +
222 +/**
223 + * gicv5_spi_state:
224 + * @cs: GIC object
225 + * @id: INTID of SPI to look up
226 + * @domain: domain to check
227 + *
228 + * Return pointer to the GICv5SPIState for this SPI, or NULL if the
229 + * interrupt is unreachable (which can be because the INTID is out of
230 + * range, or because the SPI is configured for a different domain).
231 + */
232 +static inline GICv5SPIState *gicv5_spi_state(GICv5Common *cs, uint32_t id,
233 + GICv5Domain domain)
234 +{
235 + GICv5SPIState *spi = gicv5_raw_spi_state(cs, id);
236 +
237 + if (!spi || spi->domain != domain) {
238 + return NULL;
239 + }
240 + return spi;
241 +}
242 +
243 #endif