aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2020-11-01 14:02:19 +0000
committerPeter Maydell <peter.maydell@linaro.org>2020-11-01 14:02:19 +0000
commit700d20b49e303549b32d3a7a3efbfcee8c7a4f6c (patch)
tree60bd4a9c0062f1efa17c12b2022cb73a2dcb2908 /hw
parent2ab6c494339652e69ec405dc779d83c46c8faf98 (diff)
parent73beb01ec54969f76ab32d1e0605a759b6c95ab0 (diff)
downloadqemu-700d20b49e303549b32d3a7a3efbfcee8c7a4f6c.zip
qemu-700d20b49e303549b32d3a7a3efbfcee8c7a4f6c.tar.gz
qemu-700d20b49e303549b32d3a7a3efbfcee8c7a4f6c.tar.bz2
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>
Diffstat (limited to 'hw')
-rw-r--r--hw/block/vhost-user-blk.c6
-rw-r--r--hw/i386/acpi-build.c12
-rw-r--r--hw/i386/intel_iommu.c4
-rw-r--r--hw/i386/pc.c61
-rw-r--r--hw/i386/pc_piix.c2
-rw-r--r--hw/pci/pci.c23
-rw-r--r--hw/pci/pcie.c5
-rw-r--r--hw/virtio/vhost-vdpa.c4
-rw-r--r--hw/virtio/vhost-vsock.c10
-rw-r--r--hw/virtio/vhost.c28
-rw-r--r--hw/virtio/virtio.c13
11 files changed, 117 insertions, 51 deletions
diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c
index a076b1e..f67b29b 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 e3a4bc2..4f66642 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 749eb6a..70ac837 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 0d9bd7d..5e6c002 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 0cf22a5..13d1628 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 100c938..0131d9d 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 5b48bae..d4010cf 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 4f10399..01d2101 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 f9db4be..8ddfb9a 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 3077fa6..f248237 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 6f8f865..ceb58fd 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]);