aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2020-07-23 13:38:21 +0100
committerPeter Maydell <peter.maydell@linaro.org>2020-07-23 13:38:21 +0100
commit8ffa52c20d5693d454f65f2024a1494edfea65d4 (patch)
tree7b5f89665820ae2c3969342044a3ca7841062b04 /hw
parent53ce7b47b5bf47db067b81c18c786ed7b792d031 (diff)
parentccec7e9603f446fe75c6c563ba335c00cfda6a06 (diff)
Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging
acpi,virtio,pc: bugfixes Fix bug in ACPI which were tripping up guests. Fix a use-after-free with hotplug of virtio devices. Block ability to create legacy devices which shouldn't have been there in the first place. Fix migration error handling with balloon. Drop some dead code in virtio. vtd emulation fixup. Signed-off-by: Michael S. Tsirkin <mst@redhat.com> # gpg: Signature made Wed 22 Jul 2020 13:07:26 BST # 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: virtio-pci: Changed vdev to proxy for VirtIO PCI BAR callbacks. intel_iommu: Use correct shift for 256 bits qi descriptor virtio: verify that legacy support is not accidentally on virtio: list legacy-capable devices virtio-balloon: Replace free page hinting references to 'report' with 'hint' virtio-balloon: Add locking to prevent possible race when starting hinting virtio-balloon: Prevent guest from starting a report when we didn't request one virtio: Drop broken and superfluous object_property_set_link() acpi: accept byte and word access to core ACPI registers Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw')
-rw-r--r--hw/acpi/core.c9
-rw-r--r--hw/i386/intel_iommu.c7
-rw-r--r--hw/i386/intel_iommu_internal.h3
-rw-r--r--hw/s390x/virtio-ccw-crypto.c3
-rw-r--r--hw/s390x/virtio-ccw-rng.c3
-rw-r--r--hw/s390x/virtio-ccw.c6
-rw-r--r--hw/virtio/virtio-balloon.c79
-rw-r--r--hw/virtio/virtio-crypto-pci.c2
-rw-r--r--hw/virtio/virtio-pci.c38
-rw-r--r--hw/virtio/virtio-rng-pci.c3
-rw-r--r--hw/virtio/virtio.c25
11 files changed, 115 insertions, 63 deletions
diff --git a/hw/acpi/core.c b/hw/acpi/core.c
index f6d9ec4f13..ac06db3450 100644
--- a/hw/acpi/core.c
+++ b/hw/acpi/core.c
@@ -458,7 +458,8 @@ static void acpi_pm_evt_write(void *opaque, hwaddr addr, uint64_t val,
static const MemoryRegionOps acpi_pm_evt_ops = {
.read = acpi_pm_evt_read,
.write = acpi_pm_evt_write,
- .valid.min_access_size = 2,
+ .impl.min_access_size = 2,
+ .valid.min_access_size = 1,
.valid.max_access_size = 2,
.endianness = DEVICE_LITTLE_ENDIAN,
};
@@ -527,7 +528,8 @@ static void acpi_pm_tmr_write(void *opaque, hwaddr addr, uint64_t val,
static const MemoryRegionOps acpi_pm_tmr_ops = {
.read = acpi_pm_tmr_read,
.write = acpi_pm_tmr_write,
- .valid.min_access_size = 4,
+ .impl.min_access_size = 4,
+ .valid.min_access_size = 1,
.valid.max_access_size = 4,
.endianness = DEVICE_LITTLE_ENDIAN,
};
@@ -599,7 +601,8 @@ static void acpi_pm_cnt_write(void *opaque, hwaddr addr, uint64_t val,
static const MemoryRegionOps acpi_pm_cnt_ops = {
.read = acpi_pm_cnt_read,
.write = acpi_pm_cnt_write,
- .valid.min_access_size = 2,
+ .impl.min_access_size = 2,
+ .valid.min_access_size = 1,
.valid.max_access_size = 2,
.endianness = DEVICE_LITTLE_ENDIAN,
};
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index c56398e991..0c286635cf 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -2549,6 +2549,11 @@ static bool vtd_process_inv_desc(IntelIOMMUState *s)
/* Try to fetch and process more Invalidation Descriptors */
static void vtd_fetch_inv_desc(IntelIOMMUState *s)
{
+ int qi_shift;
+
+ /* Refer to 10.4.23 of VT-d spec 3.0 */
+ qi_shift = s->iq_dw ? VTD_IQH_QH_SHIFT_5 : VTD_IQH_QH_SHIFT_4;
+
trace_vtd_inv_qi_fetch();
if (s->iq_tail >= s->iq_size) {
@@ -2567,7 +2572,7 @@ static void vtd_fetch_inv_desc(IntelIOMMUState *s)
}
/* Must update the IQH_REG in time */
vtd_set_quad_raw(s, DMAR_IQH_REG,
- (((uint64_t)(s->iq_head)) << VTD_IQH_QH_SHIFT) &
+ (((uint64_t)(s->iq_head)) << qi_shift) &
VTD_IQH_QH_MASK);
}
}
diff --git a/hw/i386/intel_iommu_internal.h b/hw/i386/intel_iommu_internal.h
index 862033ebe6..3d5487fe2c 100644
--- a/hw/i386/intel_iommu_internal.h
+++ b/hw/i386/intel_iommu_internal.h
@@ -230,7 +230,8 @@
#define VTD_IQA_DW_MASK 0x800
/* IQH_REG */
-#define VTD_IQH_QH_SHIFT 4
+#define VTD_IQH_QH_SHIFT_4 4
+#define VTD_IQH_QH_SHIFT_5 5
#define VTD_IQH_QH_MASK 0x7fff0ULL
/* ICS_REG */
diff --git a/hw/s390x/virtio-ccw-crypto.c b/hw/s390x/virtio-ccw-crypto.c
index 570c0333fc..358c74fb4b 100644
--- a/hw/s390x/virtio-ccw-crypto.c
+++ b/hw/s390x/virtio-ccw-crypto.c
@@ -23,9 +23,6 @@ static void virtio_ccw_crypto_realize(VirtioCcwDevice *ccw_dev, Error **errp)
if (!qdev_realize(vdev, BUS(&ccw_dev->bus), errp)) {
return;
}
-
- object_property_set_link(OBJECT(vdev), "cryptodev",
- OBJECT(dev->vdev.conf.cryptodev), NULL);
}
static void virtio_ccw_crypto_instance_init(Object *obj)
diff --git a/hw/s390x/virtio-ccw-rng.c b/hw/s390x/virtio-ccw-rng.c
index 4bb8c16d79..2e3a9da5e8 100644
--- a/hw/s390x/virtio-ccw-rng.c
+++ b/hw/s390x/virtio-ccw-rng.c
@@ -24,9 +24,6 @@ static void virtio_ccw_rng_realize(VirtioCcwDevice *ccw_dev, Error **errp)
if (!qdev_realize(vdev, BUS(&ccw_dev->bus), errp)) {
return;
}
-
- object_property_set_link(OBJECT(dev), "rng", OBJECT(dev->vdev.conf.rng),
- NULL);
}
static void virtio_ccw_rng_instance_init(Object *obj)
diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index 3c988a000b..0e60270297 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -1121,6 +1121,12 @@ static void virtio_ccw_device_plugged(DeviceState *d, Error **errp)
dev->max_rev = 0;
}
+ if (!virtio_ccw_rev_max(dev) && !virtio_legacy_allowed(vdev)) {
+ error_setg(errp, "Invalid value of property max_rev "
+ "(is %d expected >= 1)", virtio_ccw_rev_max(dev));
+ return;
+ }
+
if (virtio_get_num_queues(vdev) > VIRTIO_QUEUE_MAX) {
error_setg(errp, "The number of virtqueues %d "
"exceeds virtio limit %d", n,
diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
index e670f1e595..22cb5df717 100644
--- a/hw/virtio/virtio-balloon.c
+++ b/hw/virtio/virtio-balloon.c
@@ -526,21 +526,22 @@ static bool get_free_page_hints(VirtIOBalloon *dev)
ret = false;
goto out;
}
- if (id == dev->free_page_report_cmd_id) {
- dev->free_page_report_status = FREE_PAGE_REPORT_S_START;
+ if (dev->free_page_hint_status == FREE_PAGE_HINT_S_REQUESTED &&
+ id == dev->free_page_hint_cmd_id) {
+ dev->free_page_hint_status = FREE_PAGE_HINT_S_START;
} else {
/*
* Stop the optimization only when it has started. This
* avoids a stale stop sign for the previous command.
*/
- if (dev->free_page_report_status == FREE_PAGE_REPORT_S_START) {
- dev->free_page_report_status = FREE_PAGE_REPORT_S_STOP;
+ if (dev->free_page_hint_status == FREE_PAGE_HINT_S_START) {
+ dev->free_page_hint_status = FREE_PAGE_HINT_S_STOP;
}
}
}
if (elem->in_num) {
- if (dev->free_page_report_status == FREE_PAGE_REPORT_S_START) {
+ if (dev->free_page_hint_status == FREE_PAGE_HINT_S_START) {
qemu_guest_free_page_hint(elem->in_sg[0].iov_base,
elem->in_sg[0].iov_len);
}
@@ -566,11 +567,11 @@ static void virtio_ballloon_get_free_page_hints(void *opaque)
qemu_mutex_unlock(&dev->free_page_lock);
virtio_notify(vdev, vq);
/*
- * Start to poll the vq once the reporting started. Otherwise, continue
+ * Start to poll the vq once the hinting started. Otherwise, continue
* only when there are entries on the vq, which need to be given back.
*/
} while (continue_to_get_hints ||
- dev->free_page_report_status == FREE_PAGE_REPORT_S_START);
+ dev->free_page_hint_status == FREE_PAGE_HINT_S_START);
virtio_queue_set_notification(vq, 1);
}
@@ -591,14 +592,18 @@ static void virtio_balloon_free_page_start(VirtIOBalloon *s)
return;
}
- if (s->free_page_report_cmd_id == UINT_MAX) {
- s->free_page_report_cmd_id =
- VIRTIO_BALLOON_FREE_PAGE_REPORT_CMD_ID_MIN;
+ qemu_mutex_lock(&s->free_page_lock);
+
+ if (s->free_page_hint_cmd_id == UINT_MAX) {
+ s->free_page_hint_cmd_id =
+ VIRTIO_BALLOON_FREE_PAGE_HINT_CMD_ID_MIN;
} else {
- s->free_page_report_cmd_id++;
+ s->free_page_hint_cmd_id++;
}
- s->free_page_report_status = FREE_PAGE_REPORT_S_REQUESTED;
+ s->free_page_hint_status = FREE_PAGE_HINT_S_REQUESTED;
+ qemu_mutex_unlock(&s->free_page_lock);
+
virtio_notify_config(vdev);
}
@@ -606,18 +611,18 @@ static void virtio_balloon_free_page_stop(VirtIOBalloon *s)
{
VirtIODevice *vdev = VIRTIO_DEVICE(s);
- if (s->free_page_report_status != FREE_PAGE_REPORT_S_STOP) {
+ if (s->free_page_hint_status != FREE_PAGE_HINT_S_STOP) {
/*
* The lock also guarantees us that the
* virtio_ballloon_get_free_page_hints exits after the
- * free_page_report_status is set to S_STOP.
+ * free_page_hint_status is set to S_STOP.
*/
qemu_mutex_lock(&s->free_page_lock);
/*
- * The guest hasn't done the reporting, so host sends a notification
- * to the guest to actively stop the reporting.
+ * The guest isn't done hinting, so send a notification
+ * to the guest to actively stop the hinting.
*/
- s->free_page_report_status = FREE_PAGE_REPORT_S_STOP;
+ s->free_page_hint_status = FREE_PAGE_HINT_S_STOP;
qemu_mutex_unlock(&s->free_page_lock);
virtio_notify_config(vdev);
}
@@ -627,20 +632,20 @@ static void virtio_balloon_free_page_done(VirtIOBalloon *s)
{
VirtIODevice *vdev = VIRTIO_DEVICE(s);
- if (s->free_page_report_status != FREE_PAGE_REPORT_S_DONE) {
+ if (s->free_page_hint_status != FREE_PAGE_HINT_S_DONE) {
/* See virtio_balloon_free_page_stop() */
qemu_mutex_lock(&s->free_page_lock);
- s->free_page_report_status = FREE_PAGE_REPORT_S_DONE;
+ s->free_page_hint_status = FREE_PAGE_HINT_S_DONE;
qemu_mutex_unlock(&s->free_page_lock);
virtio_notify_config(vdev);
}
}
static int
-virtio_balloon_free_page_report_notify(NotifierWithReturn *n, void *data)
+virtio_balloon_free_page_hint_notify(NotifierWithReturn *n, void *data)
{
VirtIOBalloon *dev = container_of(n, VirtIOBalloon,
- free_page_report_notify);
+ free_page_hint_notify);
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
PrecopyNotifyData *pnd = data;
@@ -698,7 +703,7 @@ static size_t virtio_balloon_config_size(VirtIOBalloon *s)
if (virtio_has_feature(features, VIRTIO_BALLOON_F_FREE_PAGE_HINT)) {
return offsetof(struct virtio_balloon_config, poison_val);
}
- return offsetof(struct virtio_balloon_config, free_page_report_cmd_id);
+ return offsetof(struct virtio_balloon_config, free_page_hint_cmd_id);
}
static void virtio_balloon_get_config(VirtIODevice *vdev, uint8_t *config_data)
@@ -710,14 +715,14 @@ static void virtio_balloon_get_config(VirtIODevice *vdev, uint8_t *config_data)
config.actual = cpu_to_le32(dev->actual);
config.poison_val = cpu_to_le32(dev->poison_val);
- if (dev->free_page_report_status == FREE_PAGE_REPORT_S_REQUESTED) {
- config.free_page_report_cmd_id =
- cpu_to_le32(dev->free_page_report_cmd_id);
- } else if (dev->free_page_report_status == FREE_PAGE_REPORT_S_STOP) {
- config.free_page_report_cmd_id =
+ if (dev->free_page_hint_status == FREE_PAGE_HINT_S_REQUESTED) {
+ config.free_page_hint_cmd_id =
+ cpu_to_le32(dev->free_page_hint_cmd_id);
+ } else if (dev->free_page_hint_status == FREE_PAGE_HINT_S_STOP) {
+ config.free_page_hint_cmd_id =
cpu_to_le32(VIRTIO_BALLOON_CMD_ID_STOP);
- } else if (dev->free_page_report_status == FREE_PAGE_REPORT_S_DONE) {
- config.free_page_report_cmd_id =
+ } else if (dev->free_page_hint_status == FREE_PAGE_HINT_S_DONE) {
+ config.free_page_hint_cmd_id =
cpu_to_le32(VIRTIO_BALLOON_CMD_ID_DONE);
}
@@ -830,14 +835,14 @@ static int virtio_balloon_post_load_device(void *opaque, int version_id)
return 0;
}
-static const VMStateDescription vmstate_virtio_balloon_free_page_report = {
+static const VMStateDescription vmstate_virtio_balloon_free_page_hint = {
.name = "virtio-balloon-device/free-page-report",
.version_id = 1,
.minimum_version_id = 1,
.needed = virtio_balloon_free_page_support,
.fields = (VMStateField[]) {
- VMSTATE_UINT32(free_page_report_cmd_id, VirtIOBalloon),
- VMSTATE_UINT32(free_page_report_status, VirtIOBalloon),
+ VMSTATE_UINT32(free_page_hint_cmd_id, VirtIOBalloon),
+ VMSTATE_UINT32(free_page_hint_status, VirtIOBalloon),
VMSTATE_END_OF_LIST()
}
};
@@ -864,7 +869,7 @@ static const VMStateDescription vmstate_virtio_balloon_device = {
VMSTATE_END_OF_LIST()
},
.subsections = (const VMStateDescription * []) {
- &vmstate_virtio_balloon_free_page_report,
+ &vmstate_virtio_balloon_free_page_hint,
&vmstate_virtio_balloon_page_poison,
NULL
}
@@ -903,7 +908,7 @@ static void virtio_balloon_device_realize(DeviceState *dev, Error **errp)
VIRTIO_BALLOON_F_FREE_PAGE_HINT)) {
s->free_page_vq = virtio_add_queue(vdev, VIRTQUEUE_MAX_SIZE,
virtio_balloon_handle_free_page_vq);
- precopy_add_notifier(&s->free_page_report_notify);
+ precopy_add_notifier(&s->free_page_hint_notify);
object_ref(OBJECT(s->iothread));
s->free_page_bh = aio_bh_new(iothread_get_aio_context(s->iothread),
@@ -927,7 +932,7 @@ static void virtio_balloon_device_unrealize(DeviceState *dev)
qemu_bh_delete(s->free_page_bh);
object_unref(OBJECT(s->iothread));
virtio_balloon_free_page_stop(s);
- precopy_remove_notifier(&s->free_page_report_notify);
+ precopy_remove_notifier(&s->free_page_hint_notify);
}
balloon_stats_destroy_timer(s);
qemu_remove_balloon_handler(s);
@@ -999,8 +1004,8 @@ static void virtio_balloon_instance_init(Object *obj)
qemu_mutex_init(&s->free_page_lock);
qemu_cond_init(&s->free_page_cond);
- s->free_page_report_cmd_id = VIRTIO_BALLOON_FREE_PAGE_REPORT_CMD_ID_MIN;
- s->free_page_report_notify.notify = virtio_balloon_free_page_report_notify;
+ s->free_page_hint_cmd_id = VIRTIO_BALLOON_FREE_PAGE_HINT_CMD_ID_MIN;
+ s->free_page_hint_notify.notify = virtio_balloon_free_page_hint_notify;
object_property_add(obj, "guest-stats", "guest statistics",
balloon_stats_get_all, NULL, NULL, s);
diff --git a/hw/virtio/virtio-crypto-pci.c b/hw/virtio/virtio-crypto-pci.c
index f1cc979d33..198f86e08c 100644
--- a/hw/virtio/virtio-crypto-pci.c
+++ b/hw/virtio/virtio-crypto-pci.c
@@ -57,8 +57,6 @@ static void virtio_crypto_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
if (!qdev_realize(vdev, BUS(&vpci_dev->bus), errp)) {
return;
}
- object_property_set_link(OBJECT(vcrypto), "cryptodev",
- OBJECT(vcrypto->vdev.conf.cryptodev), NULL);
}
static void virtio_crypto_pci_class_init(ObjectClass *klass, void *data)
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index 8554cf2a03..ada1101d07 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -1333,11 +1333,12 @@ static uint64_t virtio_pci_notify_read(void *opaque, hwaddr addr,
static void virtio_pci_notify_write(void *opaque, hwaddr addr,
uint64_t val, unsigned size)
{
- VirtIODevice *vdev = opaque;
- VirtIOPCIProxy *proxy = VIRTIO_PCI(DEVICE(vdev)->parent_bus->parent);
+ VirtIOPCIProxy *proxy = opaque;
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
+
unsigned queue = addr / virtio_pci_queue_mem_mult(proxy);
- if (queue < VIRTIO_QUEUE_MAX) {
+ if (vdev != NULL && queue < VIRTIO_QUEUE_MAX) {
virtio_queue_notify(vdev, queue);
}
}
@@ -1345,10 +1346,12 @@ static void virtio_pci_notify_write(void *opaque, hwaddr addr,
static void virtio_pci_notify_write_pio(void *opaque, hwaddr addr,
uint64_t val, unsigned size)
{
- VirtIODevice *vdev = opaque;
+ VirtIOPCIProxy *proxy = opaque;
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
+
unsigned queue = val;
- if (queue < VIRTIO_QUEUE_MAX) {
+ if (vdev != NULL && queue < VIRTIO_QUEUE_MAX) {
virtio_queue_notify(vdev, queue);
}
}
@@ -1372,9 +1375,14 @@ static void virtio_pci_isr_write(void *opaque, hwaddr addr,
static uint64_t virtio_pci_device_read(void *opaque, hwaddr addr,
unsigned size)
{
- VirtIODevice *vdev = opaque;
+ VirtIOPCIProxy *proxy = opaque;
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
uint64_t val = 0;
+ if (vdev == NULL) {
+ return val;
+ }
+
switch (size) {
case 1:
val = virtio_config_modern_readb(vdev, addr);
@@ -1392,7 +1400,13 @@ static uint64_t virtio_pci_device_read(void *opaque, hwaddr addr,
static void virtio_pci_device_write(void *opaque, hwaddr addr,
uint64_t val, unsigned size)
{
- VirtIODevice *vdev = opaque;
+ VirtIOPCIProxy *proxy = opaque;
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
+
+ if (vdev == NULL) {
+ return;
+ }
+
switch (size) {
case 1:
virtio_config_modern_writeb(vdev, addr, val);
@@ -1469,19 +1483,19 @@ static void virtio_pci_modern_regions_init(VirtIOPCIProxy *proxy)
memory_region_init_io(&proxy->device.mr, OBJECT(proxy),
&device_ops,
- virtio_bus_get_device(&proxy->bus),
+ proxy,
"virtio-pci-device",
proxy->device.size);
memory_region_init_io(&proxy->notify.mr, OBJECT(proxy),
&notify_ops,
- virtio_bus_get_device(&proxy->bus),
+ proxy,
"virtio-pci-notify",
proxy->notify.size);
memory_region_init_io(&proxy->notify_pio.mr, OBJECT(proxy),
&notify_pio_ops,
- virtio_bus_get_device(&proxy->bus),
+ proxy,
"virtio-pci-notify-pio",
proxy->notify_pio.size);
}
@@ -1581,6 +1595,10 @@ static void virtio_pci_device_plugged(DeviceState *d, Error **errp)
}
if (legacy) {
+ if (!virtio_legacy_allowed(vdev)) {
+ error_setg(errp, "device is modern-only, use disable-legacy=on");
+ return;
+ }
if (virtio_host_has_feature(vdev, VIRTIO_F_IOMMU_PLATFORM)) {
error_setg(errp, "VIRTIO_F_IOMMU_PLATFORM was supported by"
" neither legacy nor transitional device");
diff --git a/hw/virtio/virtio-rng-pci.c b/hw/virtio/virtio-rng-pci.c
index 2f0b529b62..8afbb4c209 100644
--- a/hw/virtio/virtio-rng-pci.c
+++ b/hw/virtio/virtio-rng-pci.c
@@ -38,9 +38,6 @@ static void virtio_rng_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
if (!qdev_realize(vdev, BUS(&vpci_dev->bus), errp)) {
return;
}
-
- object_property_set_link(OBJECT(vrng), "rng", OBJECT(vrng->vdev.conf.rng),
- NULL);
}
static void virtio_rng_pci_class_init(ObjectClass *klass, void *data)
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index 5bd2a2f621..546a198e79 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -27,6 +27,7 @@
#include "hw/virtio/virtio-access.h"
#include "sysemu/dma.h"
#include "sysemu/runstate.h"
+#include "standard-headers/linux/virtio_ids.h"
/*
* The alignment to use between consumer and producer parts of vring.
@@ -3279,6 +3280,30 @@ void virtio_init(VirtIODevice *vdev, const char *name,
vdev->use_guest_notifier_mask = true;
}
+/*
+ * Only devices that have already been around prior to defining the virtio
+ * standard support legacy mode; this includes devices not specified in the
+ * standard. All newer devices conform to the virtio standard only.
+ */
+bool virtio_legacy_allowed(VirtIODevice *vdev)
+{
+ switch (vdev->device_id) {
+ case VIRTIO_ID_NET:
+ case VIRTIO_ID_BLOCK:
+ case VIRTIO_ID_CONSOLE:
+ case VIRTIO_ID_RNG:
+ case VIRTIO_ID_BALLOON:
+ case VIRTIO_ID_RPMSG:
+ case VIRTIO_ID_SCSI:
+ case VIRTIO_ID_9P:
+ case VIRTIO_ID_RPROC_SERIAL:
+ case VIRTIO_ID_CAIF:
+ return true;
+ default:
+ return false;
+ }
+}
+
hwaddr virtio_queue_get_desc_addr(VirtIODevice *vdev, int n)
{
return vdev->vq[n].vring.desc;