From 0b646f44d9976c33aee78b0427d1b357dde5dd50 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 1 Aug 2016 10:25:05 +0200 Subject: mptsas: really fix migration compatibility Commit 2e2aa316 removed internal flag msi_in_use, but it existed in vmstate. Restore it for migration to older QEMU versions. Reported-by: Amit Shah Suggested-by: Amit Shah Cc: Markus Armbruster Cc: Marcel Apfelbaum Cc: Paolo Bonzini Cc: Michael S. Tsirkin Cc: Amit Shah Cc: Cao jin Signed-off-by: Paolo Bonzini --- hw/scsi/mptsas.c | 4 +++- hw/scsi/mptsas.h | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'hw') diff --git a/hw/scsi/mptsas.c b/hw/scsi/mptsas.c index bebe513..0e0a22f 100644 --- a/hw/scsi/mptsas.c +++ b/hw/scsi/mptsas.c @@ -1295,6 +1295,8 @@ static void mptsas_scsi_init(PCIDevice *dev, Error **errp) /* With msi=auto, we fall back to MSI off silently */ error_free(err); + /* Only used for migration. */ + s->msi_in_use = (ret == 0); } memory_region_init_io(&s->mmio_io, OBJECT(s), &mptsas_mmio_ops, s, @@ -1370,7 +1372,7 @@ static const VMStateDescription vmstate_mptsas = { .post_load = mptsas_post_load, .fields = (VMStateField[]) { VMSTATE_PCI_DEVICE(dev, MPTSASState), - VMSTATE_UNUSED(sizeof(bool)), /* Was msi_in_use */ + VMSTATE_BOOL(msi_in_use, MPTSASState), VMSTATE_UINT32(state, MPTSASState), VMSTATE_UINT8(who_init, MPTSASState), VMSTATE_UINT8(doorbell_state, MPTSASState), diff --git a/hw/scsi/mptsas.h b/hw/scsi/mptsas.h index da014a3..0436a33 100644 --- a/hw/scsi/mptsas.h +++ b/hw/scsi/mptsas.h @@ -31,6 +31,8 @@ struct MPTSASState { OnOffAuto msi; uint64_t sas_addr; + bool msi_in_use; + /* Doorbell register */ uint32_t state; uint8_t who_init; -- cgit v1.1 From 71ae65e552fc6e03572e430009b98b80b40f1c4d Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Wed, 27 Jul 2016 14:39:58 +0200 Subject: i2c: fix migration regression introduced by broadcast support QEMU fails migration with following error: qemu-system-x86_64: Missing section footer for i2c_bus qemu-system-x86_64: load of migration failed: Invalid argument when migrating from: qemu-system-x86_64-v2.6.0 -m 256M rhel72.img -M pc-i440fx-2.6 to qemu-system-x86_64-v2.7.0-rc0 -m 256M rhel72.img -M pc-i440fx-2.6 Regression is added by commit 2293c27f (i2c: implement broadcast write) Fix it by dropping 'broadcast' VMState introduced by 2293c27f and reuse broadcast 0x00 address as broadcast flag in bus->saved_address. Then if there were ongoing broadcast at migration time, set bus->saved_address to it and at i2c_slave_post_load() time check for it instead of transfering and using 'broadcast' VMState. As result of reusing existing saved_address VMState, no compat glue will be needed to keep forward/backward compatiblity. which makes fix much less intrusive. Signed-off-by: Igor Mammedov Message-Id: <1469623198-177227-1-git-send-email-imammedo@redhat.com> Reviewed-by: Dr. David Alan Gilbert Signed-off-by: Paolo Bonzini --- hw/i2c/core.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'hw') diff --git a/hw/i2c/core.c b/hw/i2c/core.c index abb3efb..4afbe0b 100644 --- a/hw/i2c/core.c +++ b/hw/i2c/core.c @@ -17,6 +17,8 @@ struct I2CNode { QLIST_ENTRY(I2CNode) next; }; +#define I2C_BROADCAST 0x00 + struct I2CBus { BusState qbus; @@ -47,6 +49,8 @@ static void i2c_bus_pre_save(void *opaque) if (!QLIST_EMPTY(&bus->current_devs)) { if (!bus->broadcast) { bus->saved_address = QLIST_FIRST(&bus->current_devs)->elt->address; + } else { + bus->saved_address = I2C_BROADCAST; } } } @@ -58,7 +62,6 @@ static const VMStateDescription vmstate_i2c_bus = { .pre_save = i2c_bus_pre_save, .fields = (VMStateField[]) { VMSTATE_UINT8(saved_address, I2CBus), - VMSTATE_BOOL(broadcast, I2CBus), VMSTATE_END_OF_LIST() } }; @@ -93,7 +96,7 @@ int i2c_start_transfer(I2CBus *bus, uint8_t address, int recv) I2CSlaveClass *sc; I2CNode *node; - if (address == 0x00) { + if (address == I2C_BROADCAST) { /* * This is a broadcast, the current_devs will be all the devices of the * bus. @@ -221,7 +224,8 @@ static int i2c_slave_post_load(void *opaque, int version_id) I2CNode *node; bus = I2C_BUS(qdev_get_parent_bus(DEVICE(dev))); - if ((bus->saved_address == dev->address) || (bus->broadcast)) { + if ((bus->saved_address == dev->address) || + (bus->saved_address == I2C_BROADCAST)) { node = g_malloc(sizeof(struct I2CNode)); node->elt = dev; QLIST_INSERT_HEAD(&bus->current_devs, node, next); -- cgit v1.1 From e061fa3ca9cf769aebcc2ef5db7fc385a810abb1 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Fri, 29 Jul 2016 09:29:13 +0200 Subject: fw_cfg: Make base type "fw_cfg" abstract Missed when commit 5712db6 split off "fw_cfg_io" and "fw_cfg_mem". Signed-off-by: Markus Armbruster Message-Id: <1469777353-9383-1-git-send-email-armbru@redhat.com> Reviewed-by: Laszlo Ersek Signed-off-by: Paolo Bonzini --- hw/nvram/fw_cfg.c | 1 + 1 file changed, 1 insertion(+) (limited to 'hw') diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c index 2873030..f10d5ec 100644 --- a/hw/nvram/fw_cfg.c +++ b/hw/nvram/fw_cfg.c @@ -990,6 +990,7 @@ static void fw_cfg_class_init(ObjectClass *klass, void *data) static const TypeInfo fw_cfg_info = { .name = TYPE_FW_CFG, .parent = TYPE_SYS_BUS_DEVICE, + .abstract = true, .instance_size = sizeof(FWCfgState), .class_init = fw_cfg_class_init, }; -- cgit v1.1 From f99b86b94987561580a94838766458e1c7b8685d Mon Sep 17 00:00:00 2001 From: Peter Xu Date: Sun, 31 Jul 2016 22:18:05 +0800 Subject: x86: ioapic: ignore level irq during processing For level triggered interrupts, we will get Remote IRR bit cleared after guest kernel finished processing specific request. Before that, we should ignore the same interrupt from triggering again. Signed-off-by: Peter Xu Message-Id: <1469974685-4144-1-git-send-email-peterx@redhat.com> [Push new "if" up so that it covers KVM split irqchip as well. - Paolo] Signed-off-by: Paolo Bonzini --- hw/intc/ioapic.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'hw') diff --git a/hw/intc/ioapic.c b/hw/intc/ioapic.c index 2d3282a..a00d882 100644 --- a/hw/intc/ioapic.c +++ b/hw/intc/ioapic.c @@ -117,21 +117,25 @@ static void ioapic_service(IOAPICCommonState *s) s->ioredtbl[i] |= IOAPIC_LVT_REMOTE_IRR; } + if (coalesce) { + /* We are level triggered interrupts, and the + * guest should be still working on previous one, + * so skip it. */ + continue; + } + #ifdef CONFIG_KVM if (kvm_irqchip_is_split()) { if (info.trig_mode == IOAPIC_TRIGGER_EDGE) { kvm_set_irq(kvm_state, i, 1); kvm_set_irq(kvm_state, i, 0); } else { - if (!coalesce) { - kvm_set_irq(kvm_state, i, 1); - } + kvm_set_irq(kvm_state, i, 1); } continue; } -#else - (void)coalesce; #endif + /* No matter whether IR is enabled, we translate * the IOAPIC message into a MSI one, and its * address space will decide whether we need a -- cgit v1.1 From 20fd4b7b6d9282fe0cb83601f1821f31bd257458 Mon Sep 17 00:00:00 2001 From: Peter Xu Date: Mon, 1 Aug 2016 21:59:19 +0800 Subject: x86: ioapic: add support for explicit EOI Some old Linux kernels (upstream before v4.0), or any released RHEL kernels has problem in sending APIC EOI when IR is enabled. Meanwhile, many of them only support explicit EOI for IOAPIC, which is only introduced in IOAPIC version 0x20. This patch provide a way to boost QEMU IOAPIC to version 0x20, in order for QEMU to correctly receive EOI messages. Without boosting IOAPIC version to 0x20, kernels before commit d32932d ("x86/irq: Convert IOAPIC to use hierarchical irqdomain interfaces") will have trouble enabling both IR and level-triggered interrupt devices (like e1000). To upgrade IOAPIC to version 0x20, we need to specify: -global ioapic.version=0x20 To be compatible with old systems, 0x11 will still be the default IOAPIC version. Here 0x11 and 0x20 are the only versions to be supported. One thing to mention: this patch only applies to emulated IOAPIC. It does not affect kernel IOAPIC behavior. Signed-off-by: Peter Xu Message-Id: <1470059959-372-1-git-send-email-peterx@redhat.com> Signed-off-by: Paolo Bonzini --- hw/intc/ioapic.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'hw') diff --git a/hw/intc/ioapic.c b/hw/intc/ioapic.c index a00d882..31791b0 100644 --- a/hw/intc/ioapic.c +++ b/hw/intc/ioapic.c @@ -21,6 +21,7 @@ */ #include "qemu/osdep.h" +#include "qemu/error-report.h" #include "monitor/monitor.h" #include "hw/hw.h" #include "hw/i386/pc.h" @@ -269,7 +270,7 @@ ioapic_mem_read(void *opaque, hwaddr addr, unsigned int size) val = s->id << IOAPIC_ID_SHIFT; break; case IOAPIC_REG_VER: - val = IOAPIC_VERSION | + val = s->version | ((IOAPIC_NUM_PINS - 1) << IOAPIC_VER_ENTRIES_SHIFT); break; default: @@ -358,6 +359,13 @@ ioapic_mem_write(void *opaque, hwaddr addr, uint64_t val, } } break; + case IOAPIC_EOI: + /* Explicit EOI is only supported for IOAPIC version 0x20 */ + if (size != 4 || s->version != 0x20) { + break; + } + ioapic_eoi_broadcast(val); + break; } ioapic_update_kvm_routes(s); @@ -391,6 +399,12 @@ static void ioapic_realize(DeviceState *dev, Error **errp) { IOAPICCommonState *s = IOAPIC_COMMON(dev); + if (s->version != 0x11 && s->version != 0x20) { + error_report("IOAPIC only supports version 0x11 or 0x20 " + "(default: 0x11)."); + exit(1); + } + memory_region_init_io(&s->io_memory, OBJECT(s), &ioapic_io_ops, s, "ioapic", 0x1000); @@ -401,6 +415,11 @@ static void ioapic_realize(DeviceState *dev, Error **errp) qemu_add_machine_init_done_notifier(&s->machine_done); } +static Property ioapic_properties[] = { + DEFINE_PROP_UINT8("version", IOAPICCommonState, version, 0x11), + DEFINE_PROP_END_OF_LIST(), +}; + static void ioapic_class_init(ObjectClass *klass, void *data) { IOAPICCommonClass *k = IOAPIC_COMMON_CLASS(klass); @@ -408,6 +427,7 @@ static void ioapic_class_init(ObjectClass *klass, void *data) k->realize = ioapic_realize; dc->reset = ioapic_reset_common; + dc->props = ioapic_properties; } static const TypeInfo ioapic_info = { -- cgit v1.1 From 0d4104e5760221547fad158bbbb655a4e4c22b50 Mon Sep 17 00:00:00 2001 From: Fam Zheng Date: Tue, 2 Aug 2016 11:41:41 +0800 Subject: qdev: Fix use after free in qdev_init_nofail error path Since 69382d8b (qdev: Fix object reference leak in case device.realize() fails), object_property_set_bool could release the object. The error path wants the type name, so hold an reference before realizing it. Cc: Igor Mammedov Signed-off-by: Fam Zheng Message-Id: <1470109301-12966-1-git-send-email-famz@redhat.com> Reviewed-by: John Snow Signed-off-by: Paolo Bonzini --- hw/core/qdev.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'hw') diff --git a/hw/core/qdev.c b/hw/core/qdev.c index ee4a083..5783442 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -354,12 +354,14 @@ void qdev_init_nofail(DeviceState *dev) assert(!dev->realized); + object_ref(OBJECT(dev)); object_property_set_bool(OBJECT(dev), true, "realized", &err); if (err) { error_reportf_err(err, "Initialization of device %s failed: ", object_get_typename(OBJECT(dev))); exit(1); } + object_unref(OBJECT(dev)); } void qdev_machine_creation_done(void) -- cgit v1.1