diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2020-11-01 14:02:19 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2020-11-01 14:02:19 +0000 |
commit | 700d20b49e303549b32d3a7a3efbfcee8c7a4f6c (patch) | |
tree | 60bd4a9c0062f1efa17c12b2022cb73a2dcb2908 | |
parent | 2ab6c494339652e69ec405dc779d83c46c8faf98 (diff) | |
parent | 73beb01ec54969f76ab32d1e0605a759b6c95ab0 (diff) | |
download | qemu-700d20b49e303549b32d3a7a3efbfcee8c7a4f6c.zip |
Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging
pc,pci,vhost,virtio: misc fixes
Just a bunch of bugfixes all over the place.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
# gpg: Signature made Fri 30 Oct 2020 12:44:31 GMT
# gpg: using RSA key 5D09FD0871C8F85B94CA8A0D281F0DB8D28D5469
# gpg: issuer "mst@redhat.com"
# gpg: Good signature from "Michael S. Tsirkin <mst@kernel.org>" [full]
# gpg: aka "Michael S. Tsirkin <mst@redhat.com>" [full]
# Primary key fingerprint: 0270 606B 6F3C DF3D 0B17 0970 C350 3912 AFBE 8E67
# Subkey fingerprint: 5D09 FD08 71C8 F85B 94CA 8A0D 281F 0DB8 D28D 5469
* remotes/mst/tags/for_upstream:
intel_iommu: Fix two misuse of "0x%u" prints
virtio: skip guest index check on device load
vhost-blk: set features before setting inflight feature
pci: Disallow improper BAR registration for type 1
pci: Change error_report to assert(3)
pci: advertise a page aligned ATS
pc: Implement -no-hpet as sugar for -machine hpet=on
vhost: Don't special case vq->used_phys in vhost_get_log_size()
pci: Assert irqnum is between 0 and bus->nirqs in pci_bus_change_irq_level
hw/pci: Extract pci_bus_change_irq_level() from pci_change_irq_level()
hw/virtio/vhost-vdpa: Fix Coverity CID 1432864
acpi/crs: Support ranges > 32b for hosts
acpi/crs: Prevent bad ranges for host bridges
vhost-vsock: set vhostfd to non-blocking mode
vhost-vdpa: negotiate VIRTIO_NET_F_STATUS with driver
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r-- | hw/block/vhost-user-blk.c | 6 | ||||
-rw-r--r-- | hw/i386/acpi-build.c | 12 | ||||
-rw-r--r-- | hw/i386/intel_iommu.c | 4 | ||||
-rw-r--r-- | hw/i386/pc.c | 61 | ||||
-rw-r--r-- | hw/i386/pc_piix.c | 2 | ||||
-rw-r--r-- | hw/pci/pci.c | 23 | ||||
-rw-r--r-- | hw/pci/pcie.c | 5 | ||||
-rw-r--r-- | hw/virtio/vhost-vdpa.c | 4 | ||||
-rw-r--r-- | hw/virtio/vhost-vsock.c | 10 | ||||
-rw-r--r-- | hw/virtio/vhost.c | 28 | ||||
-rw-r--r-- | hw/virtio/virtio.c | 13 | ||||
-rw-r--r-- | include/hw/i386/pc.h | 1 | ||||
-rw-r--r-- | include/hw/i386/x86.h | 3 | ||||
-rw-r--r-- | include/hw/virtio/vhost.h | 1 | ||||
-rw-r--r-- | net/vhost-vdpa.c | 1 | ||||
-rw-r--r-- | softmmu/vl.c | 4 |
16 files changed, 122 insertions, 56 deletions
diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c index a076b1e54d..f67b29bbf3 100644 --- a/hw/block/vhost-user-blk.c +++ b/hw/block/vhost-user-blk.c @@ -131,6 +131,12 @@ static int vhost_user_blk_start(VirtIODevice *vdev) s->dev.acked_features = vdev->guest_features; + ret = vhost_dev_prepare_inflight(&s->dev); + if (ret < 0) { + error_report("Error set inflight format: %d", -ret); + goto err_guest_notifiers; + } + if (!s->inflight->addr) { ret = vhost_dev_get_inflight(&s->dev, s->queue_size, s->inflight); if (ret < 0) { diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index e3a4bc206c..4f66642d88 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -786,8 +786,14 @@ static Aml *build_crs(PCIHostState *host, CrsRangeSet *range_set) crs_range_insert(temp_range_set.io_ranges, range_base, range_limit); } else { /* "memory" */ - crs_range_insert(temp_range_set.mem_ranges, - range_base, range_limit); + uint64_t length = range_limit - range_base + 1; + if (range_limit <= UINT32_MAX && length <= UINT32_MAX) { + crs_range_insert(temp_range_set.mem_ranges, range_base, + range_limit); + } else { + crs_range_insert(temp_range_set.mem_64bit_ranges, + range_base, range_limit); + } } } @@ -866,6 +872,8 @@ static Aml *build_crs(PCIHostState *host, CrsRangeSet *range_set) crs_range_merge(temp_range_set.mem_ranges); for (i = 0; i < temp_range_set.mem_ranges->len; i++) { entry = g_ptr_array_index(temp_range_set.mem_ranges, i); + assert(entry->limit <= UINT32_MAX && + (entry->limit - entry->base + 1) <= UINT32_MAX); aml_append(crs, aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED, AML_NON_CACHEABLE, diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c index 749eb6ad63..70ac837733 100644 --- a/hw/i386/intel_iommu.c +++ b/hw/i386/intel_iommu.c @@ -2665,7 +2665,7 @@ static uint64_t vtd_mem_read(void *opaque, hwaddr addr, unsigned size) if (addr + size > DMAR_REG_SIZE) { error_report_once("%s: MMIO over range: addr=0x%" PRIx64 - " size=0x%u", __func__, addr, size); + " size=0x%x", __func__, addr, size); return (uint64_t)-1; } @@ -2716,7 +2716,7 @@ static void vtd_mem_write(void *opaque, hwaddr addr, if (addr + size > DMAR_REG_SIZE) { error_report_once("%s: MMIO over range: addr=0x%" PRIx64 - " size=0x%u", __func__, addr, size); + " size=0x%x", __func__, addr, size); return; } diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 0d9bd7d635..5e6c0023e0 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -1142,28 +1142,31 @@ void pc_basic_device_init(struct PCMachineState *pcms, * Without KVM_CAP_PIT_STATE2, we cannot switch off the in-kernel PIT * when the HPET wants to take over. Thus we have to disable the latter. */ - if (!no_hpet && (!kvm_irqchip_in_kernel() || kvm_has_pit_state2())) { + if (pcms->hpet_enabled && (!kvm_irqchip_in_kernel() || + kvm_has_pit_state2())) { hpet = qdev_try_new(TYPE_HPET); - if (hpet) { - /* For pc-piix-*, hpet's intcap is always IRQ2. For pc-q35-1.7 - * and earlier, use IRQ2 for compat. Otherwise, use IRQ16~23, - * IRQ8 and IRQ2. - */ - uint8_t compat = object_property_get_uint(OBJECT(hpet), - HPET_INTCAP, NULL); - if (!compat) { - qdev_prop_set_uint32(hpet, HPET_INTCAP, hpet_irqs); - } - sysbus_realize_and_unref(SYS_BUS_DEVICE(hpet), &error_fatal); - sysbus_mmio_map(SYS_BUS_DEVICE(hpet), 0, HPET_BASE); + if (!hpet) { + error_report("couldn't create HPET device"); + exit(1); + } + /* For pc-piix-*, hpet's intcap is always IRQ2. For pc-q35-1.7 + * and earlier, use IRQ2 for compat. Otherwise, use IRQ16~23, + * IRQ8 and IRQ2. + */ + uint8_t compat = object_property_get_uint(OBJECT(hpet), + HPET_INTCAP, NULL); + if (!compat) { + qdev_prop_set_uint32(hpet, HPET_INTCAP, hpet_irqs); + } + sysbus_realize_and_unref(SYS_BUS_DEVICE(hpet), &error_fatal); + sysbus_mmio_map(SYS_BUS_DEVICE(hpet), 0, HPET_BASE); - for (i = 0; i < GSI_NUM_PINS; i++) { - sysbus_connect_irq(SYS_BUS_DEVICE(hpet), i, gsi[i]); - } - pit_isa_irq = -1; - pit_alt_irq = qdev_get_gpio_in(hpet, HPET_LEGACY_PIT_INT); - rtc_irq = qdev_get_gpio_in(hpet, HPET_LEGACY_RTC_INT); + for (i = 0; i < GSI_NUM_PINS; i++) { + sysbus_connect_irq(SYS_BUS_DEVICE(hpet), i, gsi[i]); } + pit_isa_irq = -1; + pit_alt_irq = qdev_get_gpio_in(hpet, HPET_LEGACY_PIT_INT); + rtc_irq = qdev_get_gpio_in(hpet, HPET_LEGACY_RTC_INT); } *rtc_state = mc146818_rtc_init(isa_bus, 2000, rtc_irq); @@ -1529,6 +1532,20 @@ static void pc_machine_set_pit(Object *obj, bool value, Error **errp) pcms->pit_enabled = value; } +static bool pc_machine_get_hpet(Object *obj, Error **errp) +{ + PCMachineState *pcms = PC_MACHINE(obj); + + return pcms->hpet_enabled; +} + +static void pc_machine_set_hpet(Object *obj, bool value, Error **errp) +{ + PCMachineState *pcms = PC_MACHINE(obj); + + pcms->hpet_enabled = value; +} + static void pc_machine_get_max_ram_below_4g(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) @@ -1579,6 +1596,9 @@ static void pc_machine_initfn(Object *obj) pcms->smbus_enabled = true; pcms->sata_enabled = true; pcms->pit_enabled = true; +#ifdef CONFIG_HPET + pcms->hpet_enabled = true; +#endif pc_system_flash_create(pcms); pcms->pcspk = isa_new(TYPE_PC_SPEAKER); @@ -1699,6 +1719,9 @@ static void pc_machine_class_init(ObjectClass *oc, void *data) object_class_property_add_bool(oc, PC_MACHINE_PIT, pc_machine_get_pit, pc_machine_set_pit); + + object_class_property_add_bool(oc, "hpet", + pc_machine_get_hpet, pc_machine_set_hpet); } static const TypeInfo pc_machine_info = { diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index 0cf22a57ad..13d1628f13 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -216,7 +216,7 @@ static void pc_init1(MachineState *machine, i440fx_state = NULL; isa_bus = isa_bus_new(NULL, get_system_memory(), system_io, &error_abort); - no_hpet = 1; + pcms->hpet_enabled = false; } isa_bus_irqs(isa_bus, x86ms->gsi); diff --git a/hw/pci/pci.c b/hw/pci/pci.c index 100c9381c2..0131d9d02c 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -248,6 +248,14 @@ static inline void pci_set_irq_state(PCIDevice *d, int irq_num, int level) d->irq_state |= level << irq_num; } +static void pci_bus_change_irq_level(PCIBus *bus, int irq_num, int change) +{ + assert(irq_num >= 0); + assert(irq_num < bus->nirq); + bus->irq_count[irq_num] += change; + bus->set_irq(bus->irq_opaque, irq_num, bus->irq_count[irq_num] != 0); +} + static void pci_change_irq_level(PCIDevice *pci_dev, int irq_num, int change) { PCIBus *bus; @@ -258,8 +266,7 @@ static void pci_change_irq_level(PCIDevice *pci_dev, int irq_num, int change) break; pci_dev = bus->parent_dev; } - bus->irq_count[irq_num] += change; - bus->set_irq(bus->irq_opaque, irq_num, bus->irq_count[irq_num] != 0); + pci_bus_change_irq_level(bus, irq_num, change); } int pci_bus_get_irq_level(PCIBus *bus, int irq_num) @@ -1141,14 +1148,16 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num, uint32_t addr; /* offset in pci config space */ uint64_t wmask; pcibus_t size = memory_region_size(memory); + uint8_t hdr_type; assert(region_num >= 0); assert(region_num < PCI_NUM_REGIONS); - if (size & (size-1)) { - error_report("ERROR: PCI region size must be pow2 " - "type=0x%x, size=0x%"FMT_PCIBUS"", type, size); - exit(1); - } + assert(is_power_of_2(size)); + + /* A PCI bridge device (with Type 1 header) may only have at most 2 BARs */ + hdr_type = + pci_dev->config[PCI_HEADER_TYPE] & ~PCI_HEADER_TYPE_MULTI_FUNCTION; + assert(hdr_type != PCI_HEADER_TYPE_BRIDGE || region_num < 2); r = &pci_dev->io_regions[region_num]; r->addr = PCI_BAR_UNMAPPED; diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c index 5b48bae0f6..d4010cf8f3 100644 --- a/hw/pci/pcie.c +++ b/hw/pci/pcie.c @@ -971,8 +971,9 @@ void pcie_ats_init(PCIDevice *dev, uint16_t offset) dev->exp.ats_cap = offset; - /* Invalidate Queue Depth 0, Page Aligned Request 0 */ - pci_set_word(dev->config + offset + PCI_ATS_CAP, 0); + /* Invalidate Queue Depth 0, Page Aligned Request 1 */ + pci_set_word(dev->config + offset + PCI_ATS_CAP, + PCI_ATS_CAP_PAGE_ALIGNED); /* STU 0, Disabled by default */ pci_set_word(dev->config + offset + PCI_ATS_CTRL, 0); diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c index 4f1039910a..01d2101d09 100644 --- a/hw/virtio/vhost-vdpa.c +++ b/hw/virtio/vhost-vdpa.c @@ -90,7 +90,7 @@ static void vhost_vdpa_listener_begin(MemoryListener *listener) { struct vhost_vdpa *v = container_of(listener, struct vhost_vdpa, listener); struct vhost_dev *dev = v->dev; - struct vhost_msg_v2 msg; + struct vhost_msg_v2 msg = {}; int fd = v->device_fd; if (!(dev->backend_cap & (0x1ULL << VHOST_BACKEND_F_IOTLB_BATCH))) { @@ -110,7 +110,7 @@ static void vhost_vdpa_listener_commit(MemoryListener *listener) { struct vhost_vdpa *v = container_of(listener, struct vhost_vdpa, listener); struct vhost_dev *dev = v->dev; - struct vhost_msg_v2 msg; + struct vhost_msg_v2 msg = {}; int fd = v->device_fd; if (!(dev->backend_cap & (0x1ULL << VHOST_BACKEND_F_IOTLB_BATCH))) { diff --git a/hw/virtio/vhost-vsock.c b/hw/virtio/vhost-vsock.c index f9db4beb47..8ddfb9abfe 100644 --- a/hw/virtio/vhost-vsock.c +++ b/hw/virtio/vhost-vsock.c @@ -16,6 +16,7 @@ #include "qapi/error.h" #include "hw/virtio/virtio-access.h" #include "qemu/error-report.h" +#include "qemu/sockets.h" #include "hw/qdev-properties.h" #include "hw/virtio/vhost-vsock.h" #include "monitor/monitor.h" @@ -148,6 +149,13 @@ static void vhost_vsock_device_realize(DeviceState *dev, Error **errp) error_prepend(errp, "vhost-vsock: unable to parse vhostfd: "); return; } + + ret = qemu_try_set_nonblock(vhostfd); + if (ret < 0) { + error_setg_errno(errp, -ret, + "vhost-vsock: unable to set non-blocking mode"); + return; + } } else { vhostfd = open("/dev/vhost-vsock", O_RDWR); if (vhostfd < 0) { @@ -155,6 +163,8 @@ static void vhost_vsock_device_realize(DeviceState *dev, Error **errp) "vhost-vsock: failed to open vhost device"); return; } + + qemu_set_nonblock(vhostfd); } vhost_vsock_common_realize(vdev, "vhost-vsock"); diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index 3077fa6ef5..f2482378c6 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -172,16 +172,6 @@ static uint64_t vhost_get_log_size(struct vhost_dev *dev) reg->memory_size); log_size = MAX(log_size, last / VHOST_LOG_CHUNK + 1); } - for (i = 0; i < dev->nvqs; ++i) { - struct vhost_virtqueue *vq = dev->vqs + i; - - if (!vq->used_phys && !vq->used_size) { - continue; - } - - uint64_t last = vq->used_phys + vq->used_size - 1; - log_size = MAX(log_size, last / VHOST_LOG_CHUNK + 1); - } return log_size; } @@ -1655,6 +1645,24 @@ int vhost_dev_load_inflight(struct vhost_inflight *inflight, QEMUFile *f) return 0; } +int vhost_dev_prepare_inflight(struct vhost_dev *hdev) +{ + int r; + + if (hdev->vhost_ops->vhost_get_inflight_fd == NULL || + hdev->vhost_ops->vhost_set_inflight_fd == NULL) { + return 0; + } + + r = vhost_dev_set_features(hdev, hdev->log_enabled); + if (r < 0) { + VHOST_OPS_DEBUG("vhost_dev_prepare_inflight failed"); + return r; + } + + return 0; +} + int vhost_dev_set_inflight(struct vhost_dev *dev, struct vhost_inflight *inflight) { diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index 6f8f865aff..ceb58fda6c 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -17,6 +17,7 @@ #include "trace.h" #include "exec/address-spaces.h" #include "qemu/error-report.h" +#include "qemu/log.h" #include "qemu/main-loop.h" #include "qemu/module.h" #include "hw/virtio/virtio.h" @@ -3160,12 +3161,12 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id) nheads = vring_avail_idx(&vdev->vq[i]) - vdev->vq[i].last_avail_idx; /* Check it isn't doing strange things with descriptor numbers. */ if (nheads > vdev->vq[i].vring.num) { - error_report("VQ %d size 0x%x Guest index 0x%x " - "inconsistent with Host index 0x%x: delta 0x%x", - i, vdev->vq[i].vring.num, - vring_avail_idx(&vdev->vq[i]), - vdev->vq[i].last_avail_idx, nheads); - return -1; + qemu_log_mask(LOG_GUEST_ERROR, + "VQ %d size 0x%x Guest index 0x%x " + "inconsistent with Host index 0x%x: delta 0x%x", + i, vdev->vq[i].vring.num, + vring_avail_idx(&vdev->vq[i]), + vdev->vq[i].last_avail_idx, nheads); } vdev->vq[i].used_idx = vring_used_idx(&vdev->vq[i]); vdev->vq[i].shadow_avail_idx = vring_avail_idx(&vdev->vq[i]); diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index 84639d0ebc..911e460097 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -43,6 +43,7 @@ typedef struct PCMachineState { bool smbus_enabled; bool sata_enabled; bool pit_enabled; + bool hpet_enabled; /* NUMA information: */ uint64_t numa_nodes; diff --git a/include/hw/i386/x86.h b/include/hw/i386/x86.h index bfa9cb2a25..739fac5087 100644 --- a/include/hw/i386/x86.h +++ b/include/hw/i386/x86.h @@ -126,7 +126,4 @@ qemu_irq x86_allocate_cpu_irq(void); void gsi_handler(void *opaque, int n, int level); void ioapic_init_gsi(GSIState *gsi_state, const char *parent_name); -/* hpet.c */ -extern int no_hpet; - #endif diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h index 94585067f7..839bfb153c 100644 --- a/include/hw/virtio/vhost.h +++ b/include/hw/virtio/vhost.h @@ -141,6 +141,7 @@ void vhost_dev_reset_inflight(struct vhost_inflight *inflight); void vhost_dev_free_inflight(struct vhost_inflight *inflight); void vhost_dev_save_inflight(struct vhost_inflight *inflight, QEMUFile *f); int vhost_dev_load_inflight(struct vhost_inflight *inflight, QEMUFile *f); +int vhost_dev_prepare_inflight(struct vhost_dev *hdev); int vhost_dev_set_inflight(struct vhost_dev *dev, struct vhost_inflight *inflight); int vhost_dev_get_inflight(struct vhost_dev *dev, uint16_t queue_size, diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c index e2b3ba85bf..99c476db8c 100644 --- a/net/vhost-vdpa.c +++ b/net/vhost-vdpa.c @@ -55,6 +55,7 @@ const int vdpa_feature_bits[] = { VIRTIO_F_IOMMU_PLATFORM, VIRTIO_F_RING_PACKED, VIRTIO_NET_F_GUEST_ANNOUNCE, + VIRTIO_NET_F_STATUS, VHOST_INVALID_FEATURE_BIT }; diff --git a/softmmu/vl.c b/softmmu/vl.c index 7c1c6d37ef..a537a0377f 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -146,7 +146,6 @@ static Chardev **serial_hds; Chardev *parallel_hds[MAX_PARALLEL_PORTS]; int win2k_install_hack = 0; int singlestep = 0; -int no_hpet = 0; int fd_bootchk = 1; static int no_reboot; int no_shutdown = 0; @@ -3562,7 +3561,8 @@ void qemu_init(int argc, char **argv, char **envp) qemu_opts_parse_noisily(olist, "acpi=off", false); break; case QEMU_OPTION_no_hpet: - no_hpet = 1; + olist = qemu_find_opts("machine"); + qemu_opts_parse_noisily(olist, "hpet=off", false); break; case QEMU_OPTION_no_reboot: no_reboot = 1; |