Instead of switching off the sources, set their state to PENDING to possibly catch a hotplug event occuring while the VM is stopped. At resume, check the previous state and if an interrupt was queued, generate a trigger.
Signed-off-by: Cédric Le Goater <c...@kaod.org> --- hw/intc/spapr_xive_kvm.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/hw/intc/spapr_xive_kvm.c b/hw/intc/spapr_xive_kvm.c index 99a829fb3f60..64d160babb26 100644 --- a/hw/intc/spapr_xive_kvm.c +++ b/hw/intc/spapr_xive_kvm.c @@ -500,8 +500,16 @@ static void kvmppc_xive_change_state_handler(void *opaque, int running, if (running) { for (i = 0; i < xsrc->nr_irqs; i++) { uint8_t pq = xive_source_esb_get(xsrc, i); - if (xive_esb_read(xsrc, i, XIVE_ESB_SET_PQ_00 + (pq << 8)) != 0x1) { - error_report("XIVE: IRQ %d has an invalid state", i); + uint8_t old_pq; + + old_pq = xive_esb_read(xsrc, i, XIVE_ESB_SET_PQ_00 + (pq << 8)); + + /* + * If an interrupt was queued (hotplug event) while VM was + * stopped, generate a trigger. + */ + if (pq == XIVE_ESB_RESET && old_pq == XIVE_ESB_QUEUED) { + xive_esb_trigger(xsrc, i); } } @@ -515,7 +523,15 @@ static void kvmppc_xive_change_state_handler(void *opaque, int running, * migration is in progress. */ for (i = 0; i < xsrc->nr_irqs; i++) { - uint8_t pq = xive_esb_read(xsrc, i, XIVE_ESB_SET_PQ_01); + uint8_t pq = xive_esb_read(xsrc, i, XIVE_ESB_GET); + + /* + * PQ is set to PENDING to possibly catch a hotplug event + * occuring while the VM is stopped. + */ + if (pq != XIVE_ESB_OFF) { + pq = xive_esb_read(xsrc, i, XIVE_ESB_SET_PQ_10); + } xive_source_esb_set(xsrc, i, pq); } -- 2.20.1