pc,pci,vhost,virtio: misc fixes

Just a bunch of bugfixes all over the place.
 
 Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
 -----BEGIN PGP SIGNATURE-----
 
 iQFDBAABCAAtFiEEXQn9CHHI+FuUyooNKB8NuNKNVGkFAl+cCq8PHG1zdEByZWRo
 YXQuY29tAAoJECgfDbjSjVRpKWkH/0qq+u2z/q0KYzmodcdW2eFNsvKF2e+Dz3Af
 zZGMREH93DsKAQ2k3t84sz2RAaAP45cCqrq+v8kSzmpaC7GqKYA/VceeLwy8e6Eu
 YKvu5QixrOVTpNg2QV/w44ywgtA4NbWy5Fr9S4qhzPyyD/gtE609weZ1vQnSFT7B
 Gg4vr1lcqskwYTH7sh+bpsDTUeANr7QaknWKnaomroz+IUO8m9ig6RKtegaXhQCj
 xswI4458S3nklqnoGMa56j46VYwft8YHO1lBiR1WefTHylknyng9Tdvf9G5mnzVg
 wyrMTuT36lMXIa5KcSZeECIt2ZUT6KSSjWzEKZNXL5lS3gfUo7o=
 =powp
 -----END PGP SIGNATURE-----

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>
This commit is contained in:
Peter Maydell 2020-11-01 14:02:19 +00:00
commit 700d20b49e
16 changed files with 123 additions and 57 deletions

View File

@ -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) {

View File

@ -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,

View File

@ -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;
}

View File

@ -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);
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);
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);
}
*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 = {

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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))) {

View File

@ -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");

View File

@ -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)
{

View File

@ -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]);

View File

@ -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;

View File

@ -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

View File

@ -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,

View File

@ -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
};

View File

@ -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;