From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1Ix8MZ-0000Op-Ls for qemu-devel@nongnu.org; Tue, 27 Nov 2007 16:53:03 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1Ix8MX-0000LP-MI for qemu-devel@nongnu.org; Tue, 27 Nov 2007 16:53:03 -0500 Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Ix8MX-0000LM-GG for qemu-devel@nongnu.org; Tue, 27 Nov 2007 16:53:01 -0500 Received: from mis011-1.exch011.intermedia.net ([64.78.21.128]) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1Ix8MX-00060j-00 for qemu-devel@nongnu.org; Tue, 27 Nov 2007 16:53:01 -0500 Message-ID: <474C8CB0.7010304@qumranet.com> Date: Tue, 27 Nov 2007 23:31:28 +0200 From: Uri Lublin MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="------------050905050901080605060300" Subject: [Qemu-devel] saving/loading PCI irq related state Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org This is a multi-part message in MIME format. --------------050905050901080605060300 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Hello, If one is not lucky he/she may lose PCI interrupts when saving and loading a VM. It seems PCI irq related state is not being saved. When this happens, the guest hangs/spins and the cpu usage of the process stays around 100%. Attached are three patches to fix this: 01 -- when saving/loading a pci device, save/load its irq_state 02 -- save/load PCI-Bus irq related state 03 -- save/load PCI-bridge (i440FX/PIIX3) irq related state There are two alternatives, both recalculate PCI irq related state upon loadvm instead of saving/loading it: (a) Make every PCI device DEV (e.g. rtl8139, ne2000, usb-uhci, etc) call its DEV_update_irq() from its state-load-function. or (b) Keep patch 01 and recalculate 02 and 03 by going over all PCI-devices on the specific Bus/Bridge. Comments welcome. Thanks, Uri. --------------050905050901080605060300 Content-Type: text/x-patch; name="01_saving-loading-a-pci-device.patch" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="01_saving-loading-a-pci-device.patch" --- hw/pci.c 2007-11-27 22:17:33.319404340 +0200 +++ hw/pci.c.1 2007-11-27 22:11:49.889369058 +0200 @@ -83,18 +83,29 @@ void pci_device_save(PCIDevice *s, QEMUFile *f) { - qemu_put_be32(f, 1); /* PCI device version */ + int i; + + qemu_put_be32(f, 2); /* PCI device version */ qemu_put_buffer(f, s->config, 256); + for (i=0; i<4; i++) + qemu_put_be32s(f, &s->irq_state[i]); } int pci_device_load(PCIDevice *s, QEMUFile *f) { uint32_t version_id; + int i; + version_id = qemu_get_be32(f); - if (version_id != 1) + if (version_id > 2) return -EINVAL; qemu_get_buffer(f, s->config, 256); pci_update_mappings(s); + + if (version_id >= 2) + for (i=0; i<4; i++) + qemu_get_be32s(f, &s->irq_state[i]); + return 0; } --------------050905050901080605060300 Content-Type: text/x-patch; name="02_saving-loading-a-pci-bus.patch" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="02_saving-loading-a-pci-bus.patch" --- hw/pci.c 2007-11-27 22:22:05.565379761 +0200 +++ hw/pci.c.2 2007-11-27 22:21:48.820440780 +0200 @@ -42,6 +42,7 @@ PCIBus *next; /* The bus IRQ state is the logical OR of the connected devices. Keep a count of the number of devices with raised IRQs. */ + int nirq; int irq_count[]; }; @@ -52,16 +53,51 @@ static int pci_irq_index; static PCIBus *first_bus; +static void pcibus_save(QEMUFile *f, void *opaque) +{ + PCIBus *bus = (PCIBus *)opaque; + int i; + + qemu_put_be32s(f, &bus->nirq); + for (i=0; inirq; i++) + qemu_put_be32s(f, &bus->irq_count[i]); +} + +static int pcibus_load(QEMUFile *f, void *opaque, int version_id) +{ + PCIBus *bus = (PCIBus *)opaque; + int i, nirq; + + if (version_id != 1) + return -EINVAL; + + qemu_get_be32s(f, &nirq); + if (bus->nirq != nirq) { + fprintf(stderr, "pcibus_load: nirq mismatch: src=%d dst=%d\n", + nirq, bus->nirq); + return -EINVAL; + } + + for (i=0; iirq_count[i]); + + return 0; +} + PCIBus *pci_register_bus(pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, qemu_irq *pic, int devfn_min, int nirq) { PCIBus *bus; + static int nbus = 0; + bus = qemu_mallocz(sizeof(PCIBus) + (nirq * sizeof(int))); bus->set_irq = set_irq; bus->map_irq = map_irq; bus->irq_opaque = pic; bus->devfn_min = devfn_min; + bus->nirq = nirq; first_bus = bus; + register_savevm("PCIBUS", nbus++, 1, pcibus_save, pcibus_load, bus); return bus; } --------------050905050901080605060300 Content-Type: text/x-patch; name="03_saving-loading-a-pci-bridge.patch" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="03_saving-loading-a-pci-bridge.patch" --- hw/piix_pci.c 2007-11-27 22:30:31.214559561 +0200 +++ hw/piix_pci.c.1 2007-11-27 22:23:43.254043529 +0200 @@ -57,6 +57,7 @@ static uint32_t isa_page_descs[384 / 4]; static uint8_t smm_enabled; +static int pci_irq_levels[4]; static void update_pam(PCIDevice *d, uint32_t start, uint32_t end, int r) { @@ -139,22 +140,32 @@ static void i440fx_save(QEMUFile* f, void *opaque) { PCIDevice *d = opaque; + int i; + pci_device_save(d, f); qemu_put_8s(f, &smm_enabled); + + for (i=0; i<4; i++) + qemu_put_be32s(f, &pci_irq_levels[i]); } static int i440fx_load(QEMUFile* f, void *opaque, int version_id) { PCIDevice *d = opaque; - int ret; + int ret, i; - if (version_id != 1) + if (version_id > 2) return -EINVAL; ret = pci_device_load(d, f); if (ret < 0) return ret; i440fx_update_memory_mappings(d); qemu_get_8s(f, &smm_enabled); + + if (version_id >=2 ) + for (i=0; i<4; i++) + qemu_get_be32s(f, &pci_irq_levels[i]); + return 0; } @@ -192,7 +203,7 @@ d->config[0x72] = 0x02; /* SMRAM */ - register_savevm("I440FX", 0, 1, i440fx_save, i440fx_load, d); + register_savevm("I440FX", 0, 2, i440fx_save, i440fx_load, d); *pi440fx_state = d; return b; } @@ -205,8 +216,6 @@ /* just used for simpler irq handling. */ #define PCI_IRQ_WORDS ((PCI_DEVICES_MAX + 31) / 32) -static int pci_irq_levels[4]; - static void piix3_set_irq(qemu_irq *pic, int irq_num, int level) { int i, pic_irq, pic_level; --------------050905050901080605060300--