diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2019-05-21 14:56:57 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2019-05-21 14:56:57 +0100 |
commit | 247ba27c528c52e4a41c233c1c9a699f40e4d2a5 (patch) | |
tree | cec47b9b84e1e099b1295468f59fe31490c6e379 /hw/virtio | |
parent | 62516a0a18cd156d913dd625baca52c46743223b (diff) | |
parent | ba02ff90ee1dcaf7aa5645075217e555ae2c54ea (diff) | |
download | qemu-247ba27c528c52e4a41c233c1c9a699f40e4d2a5.zip qemu-247ba27c528c52e4a41c233c1c9a699f40e4d2a5.tar.gz qemu-247ba27c528c52e4a41c233c1c9a699f40e4d2a5.tar.bz2 |
Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging
pci, pc, virtio: features, fixes
reconnect for vhost blk
tests for UEFI
misc other stuff
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
# gpg: Signature made Tue 21 May 2019 14:41:32 BST
# gpg: using RSA key 281F0DB8D28D5469
# 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: (34 commits)
tests: acpi: print error unable to dump ACPI table during rebuild
tests: acpi: refactor rebuild-expected-aml.sh to dump ACPI tables for a specified list of targets
tests: acpi: allow to override default accelerator
tests: acpi: ignore SMBIOS tests when UEFI firmware is used
tests: acpi: add a way to start tests with UEFI firmware
tests: acpi: add acpi_find_rsdp_address_uefi() helper
tests: acpi: move boot_sector_init() into x86 tests branch
tests: acpi: skip FACS table if board uses hw reduced ACPI profile
tests: acpi: fetch X_DSDT if pointer to DSDT is 0
tests: acpi: make pointer to RSDP 64bit
tests: acpi: make RSDT test routine handle XSDT
tests: acpi: make acpi_fetch_table() take size of fetched table pointer
tests: acpi: rename acpi_parse_rsdp_table() into acpi_fetch_rsdp_table()
pci: Simplify pci_bus_is_root()
pcie: Remove redundant test in pcie_mmcfg_data_{read,write}()
libvhost-user: fix bad vu_log_write
hw/arm/virt-acpi-build: pass AcpiMcfgInfo to build_mcfg()
i386, acpi: remove mcfg_ prefix in AcpiMcfgInfo members
hw/arm/virt-acpi-build: remove unnecessary variable mcfg_start
do not call vhost_net_cleanup() on running net from char user event
...
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/virtio')
-rw-r--r-- | hw/virtio/virtio-crypto-pci.c | 4 | ||||
-rw-r--r-- | hw/virtio/virtio-input-pci.c | 4 | ||||
-rw-r--r-- | hw/virtio/virtio-pci.c | 27 | ||||
-rw-r--r-- | hw/virtio/virtio-pci.h | 31 | ||||
-rw-r--r-- | hw/virtio/virtio.c | 54 |
5 files changed, 99 insertions, 21 deletions
diff --git a/hw/virtio/virtio-crypto-pci.c b/hw/virtio/virtio-crypto-pci.c index 90a6e0d..13807e5 100644 --- a/hw/virtio/virtio-crypto-pci.c +++ b/hw/virtio/virtio-crypto-pci.c @@ -51,7 +51,9 @@ static void virtio_crypto_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp) } qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus)); - virtio_pci_force_virtio_1(vpci_dev); + if (!virtio_pci_force_virtio_1(vpci_dev, errp)) { + return; + } object_property_set_bool(OBJECT(vdev), true, "realized", errp); object_property_set_link(OBJECT(vcrypto), OBJECT(vcrypto->vdev.conf.cryptodev), "cryptodev", diff --git a/hw/virtio/virtio-input-pci.c b/hw/virtio/virtio-input-pci.c index 2c13978..2847772 100644 --- a/hw/virtio/virtio-input-pci.c +++ b/hw/virtio/virtio-input-pci.c @@ -48,7 +48,9 @@ static void virtio_input_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp) DeviceState *vdev = DEVICE(&vinput->vdev); qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus)); - virtio_pci_force_virtio_1(vpci_dev); + if (!virtio_pci_force_virtio_1(vpci_dev, errp)) { + return; + } object_property_set_bool(OBJECT(vdev), true, "realized", errp); } diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index cb44e19..9056cdf 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -20,6 +20,7 @@ #include "standard-headers/linux/virtio_pci.h" #include "hw/virtio/virtio.h" #include "hw/pci/pci.h" +#include "hw/pci/pci_bus.h" #include "qapi/error.h" #include "qemu/error-report.h" #include "hw/pci/msi.h" @@ -1721,16 +1722,22 @@ static void virtio_pci_realize(PCIDevice *pci_dev, Error **errp) /* PCI BAR regions must be powers of 2 */ pow2ceil(proxy->notify.offset + proxy->notify.size)); - if (proxy->disable_legacy == ON_OFF_AUTO_AUTO) { - proxy->disable_legacy = pcie_port ? ON_OFF_AUTO_ON : ON_OFF_AUTO_OFF; - } - - if (!virtio_pci_modern(proxy) && !virtio_pci_legacy(proxy)) { - error_setg(errp, "device cannot work as neither modern nor legacy mode" - " is enabled"); - error_append_hint(errp, "Set either disable-modern or disable-legacy" - " to off\n"); - return; + if ((proxy->disable_legacy == ON_OFF_AUTO_ON) || + ((proxy->disable_legacy == ON_OFF_AUTO_AUTO) && pcie_port)) { + if (proxy->disable_modern) { + error_setg(errp, "device cannot work as neither modern nor " + "legacy mode is enabled"); + error_append_hint(errp, "Set either disable-modern or " + "disable-legacy to off\n"); + return; + } + proxy->mode = VIRTIO_PCI_MODE_MODERN; + } else { + if (proxy->disable_modern) { + proxy->mode = VIRTIO_PCI_MODE_LEGACY; + } else { + proxy->mode = VIRTIO_PCI_MODE_TRANSITIONAL; + } } if (pcie_port && pci_is_express(pci_dev)) { diff --git a/hw/virtio/virtio-pci.h b/hw/virtio/virtio-pci.h index 1858185..bfea289 100644 --- a/hw/virtio/virtio-pci.h +++ b/hw/virtio/virtio-pci.h @@ -15,6 +15,7 @@ #ifndef QEMU_VIRTIO_PCI_H #define QEMU_VIRTIO_PCI_H +#include "qapi/error.h" #include "hw/pci/msi.h" #include "hw/virtio/virtio-bus.h" @@ -118,6 +119,12 @@ typedef struct VirtIOPCIQueue { uint32_t used[2]; } VirtIOPCIQueue; +typedef enum { + VIRTIO_PCI_MODE_LEGACY, + VIRTIO_PCI_MODE_TRANSITIONAL, + VIRTIO_PCI_MODE_MODERN, +} VirtIOPCIMode; + struct VirtIOPCIProxy { PCIDevice pci_dev; MemoryRegion bar; @@ -142,6 +149,7 @@ struct VirtIOPCIProxy { bool disable_modern; bool ignore_backend_features; OnOffAuto disable_legacy; + VirtIOPCIMode mode; uint32_t class_code; uint32_t nvectors; uint32_t dfselect; @@ -156,23 +164,34 @@ struct VirtIOPCIProxy { static inline bool virtio_pci_modern(VirtIOPCIProxy *proxy) { - return !proxy->disable_modern; + return proxy->mode != VIRTIO_PCI_MODE_LEGACY; } static inline bool virtio_pci_legacy(VirtIOPCIProxy *proxy) { - return proxy->disable_legacy == ON_OFF_AUTO_OFF; + return proxy->mode != VIRTIO_PCI_MODE_MODERN; } -static inline void virtio_pci_force_virtio_1(VirtIOPCIProxy *proxy) +static inline bool virtio_pci_force_virtio_1(VirtIOPCIProxy *proxy, + Error **errp) { - proxy->disable_modern = false; - proxy->disable_legacy = ON_OFF_AUTO_ON; + if (proxy->disable_legacy == ON_OFF_AUTO_OFF) { + error_setg(errp, "Unable to set disable-legacy=off on a virtio-1.0 " + "only device"); + return false; + } + if (proxy->disable_modern == true) { + error_setg(errp, "Unable to set disable-modern=on on a virtio-1.0 " + "only device"); + return false; + } + proxy->mode = VIRTIO_PCI_MODE_MODERN; + return true; } static inline void virtio_pci_disable_modern(VirtIOPCIProxy *proxy) { - proxy->disable_modern = true; + proxy->mode = VIRTIO_PCI_MODE_LEGACY; } /* diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index 28056a7..4805727 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -1162,10 +1162,16 @@ int virtio_set_status(VirtIODevice *vdev, uint8_t val) } } } + vdev->started = val & VIRTIO_CONFIG_S_DRIVER_OK; + if (unlikely(vdev->start_on_kick && vdev->started)) { + vdev->start_on_kick = false; + } + if (k->set_status) { k->set_status(vdev, val); } vdev->status = val; + return 0; } @@ -1208,6 +1214,9 @@ void virtio_reset(void *opaque) k->reset(vdev); } + vdev->start_on_kick = (virtio_host_has_feature(vdev, VIRTIO_F_VERSION_1) && + !virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1)); + vdev->started = false; vdev->broken = false; vdev->guest_features = 0; vdev->queue_sel = 0; @@ -1518,14 +1527,21 @@ void virtio_queue_set_align(VirtIODevice *vdev, int n, int align) static bool virtio_queue_notify_aio_vq(VirtQueue *vq) { + bool ret = false; + if (vq->vring.desc && vq->handle_aio_output) { VirtIODevice *vdev = vq->vdev; trace_virtio_queue_notify(vdev, vq - vdev->vq, vq); - return vq->handle_aio_output(vdev, vq); + ret = vq->handle_aio_output(vdev, vq); + + if (unlikely(vdev->start_on_kick)) { + vdev->started = true; + vdev->start_on_kick = false; + } } - return false; + return ret; } static void virtio_queue_notify_vq(VirtQueue *vq) @@ -1539,6 +1555,11 @@ static void virtio_queue_notify_vq(VirtQueue *vq) trace_virtio_queue_notify(vdev, vq - vdev->vq, vq); vq->handle_output(vdev, vq); + + if (unlikely(vdev->start_on_kick)) { + vdev->started = true; + vdev->start_on_kick = false; + } } } @@ -1556,6 +1577,11 @@ void virtio_queue_notify(VirtIODevice *vdev, int n) } else if (vq->handle_output) { vq->handle_output(vdev, vq); } + + if (unlikely(vdev->start_on_kick)) { + vdev->started = true; + vdev->start_on_kick = false; + } } uint16_t virtio_queue_vector(VirtIODevice *vdev, int n) @@ -1770,6 +1796,13 @@ static bool virtio_broken_needed(void *opaque) return vdev->broken; } +static bool virtio_started_needed(void *opaque) +{ + VirtIODevice *vdev = opaque; + + return vdev->started; +} + static const VMStateDescription vmstate_virtqueue = { .name = "virtqueue_state", .version_id = 1, @@ -1898,6 +1931,17 @@ static const VMStateDescription vmstate_virtio_broken = { } }; +static const VMStateDescription vmstate_virtio_started = { + .name = "virtio/started", + .version_id = 1, + .minimum_version_id = 1, + .needed = &virtio_started_needed, + .fields = (VMStateField[]) { + VMSTATE_BOOL(started, VirtIODevice), + VMSTATE_END_OF_LIST() + } +}; + static const VMStateDescription vmstate_virtio = { .name = "virtio", .version_id = 1, @@ -1913,6 +1957,7 @@ static const VMStateDescription vmstate_virtio = { &vmstate_virtio_ringsize, &vmstate_virtio_broken, &vmstate_virtio_extra_state, + &vmstate_virtio_started, NULL } }; @@ -2246,7 +2291,7 @@ static void virtio_vmstate_change(void *opaque, int running, RunState state) VirtIODevice *vdev = opaque; BusState *qbus = qdev_get_parent_bus(DEVICE(vdev)); VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); - bool backend_run = running && (vdev->status & VIRTIO_CONFIG_S_DRIVER_OK); + bool backend_run = running && vdev->started; vdev->vm_running = running; if (backend_run) { @@ -2286,6 +2331,9 @@ void virtio_init(VirtIODevice *vdev, const char *name, g_malloc0(sizeof(*vdev->vector_queues) * nvectors); } + vdev->start_on_kick = (virtio_host_has_feature(vdev, VIRTIO_F_VERSION_1) && + !virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1)); + vdev->started = false; vdev->device_id = device_id; vdev->status = 0; atomic_set(&vdev->isr, 0); |