From 2c9ecdeb9fbad9e414c2a7da676804992b568d13 Mon Sep 17 00:00:00 2001 From: Pavel Dovgalyuk Date: Thu, 28 Aug 2014 15:19:19 +0400 Subject: [PATCH] piix: do not set irq while loading vmstate This patch avoids setting an irq while loading the state of the ISA bridge. Because the i8259 has not been deserialized yet, raising an interrupt could bring the system out-of-sync with the migration source. For example, the migration source could have masked the interrupt in the i8259. On the destination, the i8259 device model would not know that yet and would trigger an interrupt in the CPU. This patch eliminates setting the irq and just restores the calculated state fields in post_load function. Interrupt state will be deserialized separately through the IRR field of the i8259. Signed-off-by: Pavel Dovgalyuk Reviewed-by: Michael S. Tsirkin Signed-off-by: Paolo Bonzini --- hw/pci-host/piix.c | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c index e0e0946..1530038 100644 --- a/hw/pci-host/piix.c +++ b/hw/pci-host/piix.c @@ -409,7 +409,7 @@ static void piix3_set_irq_pic(PIIX3State *piix3, int pic_irq) (pic_irq * PIIX_NUM_PIRQS)))); } -static void piix3_set_irq_level(PIIX3State *piix3, int pirq, int level) +static void piix3_set_irq_level_internal(PIIX3State *piix3, int pirq, int level) { int pic_irq; uint64_t mask; @@ -422,6 +422,18 @@ static void piix3_set_irq_level(PIIX3State *piix3, int pirq, int level) mask = 1ULL << ((pic_irq * PIIX_NUM_PIRQS) + pirq); piix3->pic_levels &= ~mask; piix3->pic_levels |= mask * !!level; +} + +static void piix3_set_irq_level(PIIX3State *piix3, int pirq, int level) +{ + int pic_irq; + + pic_irq = piix3->dev.config[PIIX_PIRQC + pirq]; + if (pic_irq >= PIIX_NUM_PIC_IRQS) { + return; + } + + piix3_set_irq_level_internal(piix3, pirq, level); piix3_set_irq_pic(piix3, pic_irq); } @@ -527,7 +539,21 @@ static void piix3_reset(void *opaque) static int piix3_post_load(void *opaque, int version_id) { PIIX3State *piix3 = opaque; - piix3_update_irq_levels(piix3); + int pirq; + + /* Because the i8259 has not been deserialized yet, qemu_irq_raise + * might bring the system to a different state than the saved one; + * for example, the interrupt could be masked but the i8259 would + * not know that yet and would trigger an interrupt in the CPU. + * + * Here, we update irq levels without raising the interrupt. + * Interrupt state will be deserialized separately through the i8259. + */ + piix3->pic_levels = 0; + for (pirq = 0; pirq < PIIX_NUM_PIRQS; pirq++) { + piix3_set_irq_level_internal(piix3, pirq, + pci_bus_get_irq_level(piix3->dev.bus, pirq)); + } return 0; } -- 2.7.4