aboutsummaryrefslogtreecommitdiff
path: root/hw/virtio
diff options
context:
space:
mode:
Diffstat (limited to 'hw/virtio')
-rw-r--r--hw/virtio/trace-events10
-rw-r--r--hw/virtio/vhost-scsi-pci.c2
-rw-r--r--hw/virtio/vhost-shadow-virtqueue.c35
-rw-r--r--hw/virtio/vhost-shadow-virtqueue.h6
-rw-r--r--hw/virtio/vhost-user-blk-pci.c2
-rw-r--r--hw/virtio/vhost-user-fs-pci.c2
-rw-r--r--hw/virtio/vhost-user-fs.c10
-rw-r--r--hw/virtio/vhost-user-i2c-pci.c2
-rw-r--r--hw/virtio/vhost-user-i2c.c7
-rw-r--r--hw/virtio/vhost-user-input-pci.c2
-rw-r--r--hw/virtio/vhost-user-rng-pci.c2
-rw-r--r--hw/virtio/vhost-user-rng.c9
-rw-r--r--hw/virtio/vhost-user-scsi-pci.c2
-rw-r--r--hw/virtio/vhost-user-vsock-pci.c2
-rw-r--r--hw/virtio/vhost-user-vsock.c2
-rw-r--r--hw/virtio/vhost-user.c133
-rw-r--r--hw/virtio/vhost-vdpa.c29
-rw-r--r--hw/virtio/vhost-vsock-common.c12
-rw-r--r--hw/virtio/vhost-vsock-pci.c2
-rw-r--r--hw/virtio/vhost-vsock.c2
-rw-r--r--hw/virtio/vhost.c4
-rw-r--r--hw/virtio/virtio-9p-pci.c2
-rw-r--r--hw/virtio/virtio-balloon-pci.c2
-rw-r--r--hw/virtio/virtio-balloon.c3
-rw-r--r--hw/virtio/virtio-blk-pci.c2
-rw-r--r--hw/virtio/virtio-bus.c22
-rw-r--r--hw/virtio/virtio-crypto.c18
-rw-r--r--hw/virtio/virtio-input-host-pci.c2
-rw-r--r--hw/virtio/virtio-input-pci.c2
-rw-r--r--hw/virtio/virtio-iommu-pci.c2
-rw-r--r--hw/virtio/virtio-iommu.c3
-rw-r--r--hw/virtio/virtio-mem.c3
-rw-r--r--hw/virtio/virtio-net-pci.c2
-rw-r--r--hw/virtio/virtio-pci.c5
-rw-r--r--hw/virtio/virtio-pci.h255
-rw-r--r--hw/virtio/virtio-pmem.c3
-rw-r--r--hw/virtio/virtio-rng-pci.c2
-rw-r--r--hw/virtio/virtio-rng.c2
-rw-r--r--hw/virtio/virtio-scsi-pci.c2
-rw-r--r--hw/virtio/virtio-serial-pci.c2
-rw-r--r--hw/virtio/virtio.c56
41 files changed, 305 insertions, 362 deletions
diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events
index 333348d9d5..ab8e095b73 100644
--- a/hw/virtio/trace-events
+++ b/hw/virtio/trace-events
@@ -21,6 +21,9 @@ vhost_user_set_mem_table_withfd(int index, const char *name, uint64_t memory_siz
vhost_user_postcopy_waker(const char *rb, uint64_t rb_offset) "%s + 0x%"PRIx64
vhost_user_postcopy_waker_found(uint64_t client_addr) "0x%"PRIx64
vhost_user_postcopy_waker_nomatch(const char *rb, uint64_t rb_offset) "%s + 0x%"PRIx64
+vhost_user_read(uint32_t req, uint32_t flags) "req:%d flags:0x%"PRIx32""
+vhost_user_write(uint32_t req, uint32_t flags) "req:%d flags:0x%"PRIx32""
+vhost_user_create_notifier(int idx, void *n) "idx:%d n:%p"
# vhost-vdpa.c
vhost_vdpa_dma_map(void *vdpa, int fd, uint32_t msg_type, uint64_t iova, uint64_t size, uint64_t uaddr, uint8_t perm, uint8_t type) "vdpa:%p fd: %d msg_type: %"PRIu32" iova: 0x%"PRIx64" size: 0x%"PRIx64" uaddr: 0x%"PRIx64" perm: 0x%"PRIx8" type: %"PRIu8
@@ -89,7 +92,12 @@ virtio_mmio_guest_page(uint64_t size, int shift) "guest page size 0x%" PRIx64 "
virtio_mmio_queue_write(uint64_t value, int max_size) "mmio_queue write 0x%" PRIx64 " max %d"
virtio_mmio_setting_irq(int level) "virtio_mmio setting IRQ %d"
-# virtio-iommu.c
+# virtio-pci.c
+virtio_pci_notify(uint16_t vector) "virtio_pci_notify vec 0x%x"
+virtio_pci_notify_write(uint64_t addr, uint64_t val, unsigned int size) "0x%" PRIx64" = 0x%" PRIx64 " (%d)"
+virtio_pci_notify_write_pio(uint64_t addr, uint64_t val, unsigned int size) "0x%" PRIx64" = 0x%" PRIx64 " (%d)"
+
+# hw/virtio/virtio-iommu.c
virtio_iommu_device_reset(void) "reset!"
virtio_iommu_system_reset(void) "system reset!"
virtio_iommu_get_features(uint64_t features) "device supports features=0x%"PRIx64
diff --git a/hw/virtio/vhost-scsi-pci.c b/hw/virtio/vhost-scsi-pci.c
index cb71a294fa..08980bc23b 100644
--- a/hw/virtio/vhost-scsi-pci.c
+++ b/hw/virtio/vhost-scsi-pci.c
@@ -21,7 +21,7 @@
#include "hw/virtio/vhost-scsi.h"
#include "qapi/error.h"
#include "qemu/module.h"
-#include "virtio-pci.h"
+#include "hw/virtio/virtio-pci.h"
#include "qom/object.h"
typedef struct VHostSCSIPCI VHostSCSIPCI;
diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c
index 1e5cfe2af6..56c96ebd13 100644
--- a/hw/virtio/vhost-shadow-virtqueue.c
+++ b/hw/virtio/vhost-shadow-virtqueue.c
@@ -138,6 +138,7 @@ static void vhost_vring_write_descs(VhostShadowVirtqueue *svq, hwaddr *sg,
for (n = 0; n < num; n++) {
if (more_descs || (n + 1 < num)) {
descs[i].flags = flags | cpu_to_le16(VRING_DESC_F_NEXT);
+ descs[i].next = cpu_to_le16(svq->desc_next[i]);
} else {
descs[i].flags = flags;
}
@@ -145,10 +146,10 @@ static void vhost_vring_write_descs(VhostShadowVirtqueue *svq, hwaddr *sg,
descs[i].len = cpu_to_le32(iovec[n].iov_len);
last = i;
- i = cpu_to_le16(descs[i].next);
+ i = cpu_to_le16(svq->desc_next[i]);
}
- svq->free_head = le16_to_cpu(descs[last].next);
+ svq->free_head = le16_to_cpu(svq->desc_next[last]);
}
static bool vhost_svq_add_split(VhostShadowVirtqueue *svq,
@@ -198,11 +199,19 @@ static bool vhost_svq_add_split(VhostShadowVirtqueue *svq,
return true;
}
+/**
+ * Add an element to a SVQ.
+ *
+ * The caller must check that there is enough slots for the new element. It
+ * takes ownership of the element: In case of failure, it is free and the SVQ
+ * is considered broken.
+ */
static bool vhost_svq_add(VhostShadowVirtqueue *svq, VirtQueueElement *elem)
{
unsigned qemu_head;
bool ok = vhost_svq_add_split(svq, elem, &qemu_head);
if (unlikely(!ok)) {
+ g_free(elem);
return false;
}
@@ -333,13 +342,22 @@ static void vhost_svq_disable_notification(VhostShadowVirtqueue *svq)
svq->vring.avail->flags |= cpu_to_le16(VRING_AVAIL_F_NO_INTERRUPT);
}
+static uint16_t vhost_svq_last_desc_of_chain(const VhostShadowVirtqueue *svq,
+ uint16_t num, uint16_t i)
+{
+ for (uint16_t j = 0; j < (num - 1); ++j) {
+ i = le16_to_cpu(svq->desc_next[i]);
+ }
+
+ return i;
+}
+
static VirtQueueElement *vhost_svq_get_buf(VhostShadowVirtqueue *svq,
uint32_t *len)
{
- vring_desc_t *descs = svq->vring.desc;
const vring_used_t *used = svq->vring.used;
vring_used_elem_t used_elem;
- uint16_t last_used;
+ uint16_t last_used, last_used_chain, num;
if (!vhost_svq_more_used(svq)) {
return NULL;
@@ -365,7 +383,10 @@ static VirtQueueElement *vhost_svq_get_buf(VhostShadowVirtqueue *svq,
return NULL;
}
- descs[used_elem.id].next = svq->free_head;
+ num = svq->ring_id_maps[used_elem.id]->in_num +
+ svq->ring_id_maps[used_elem.id]->out_num;
+ last_used_chain = vhost_svq_last_desc_of_chain(svq, num, used_elem.id);
+ svq->desc_next[last_used_chain] = svq->free_head;
svq->free_head = used_elem.id;
*len = used_elem.len;
@@ -540,8 +561,9 @@ void vhost_svq_start(VhostShadowVirtqueue *svq, VirtIODevice *vdev,
svq->vring.used = qemu_memalign(qemu_real_host_page_size(), device_size);
memset(svq->vring.used, 0, device_size);
svq->ring_id_maps = g_new0(VirtQueueElement *, svq->vring.num);
+ svq->desc_next = g_new0(uint16_t, svq->vring.num);
for (unsigned i = 0; i < svq->vring.num - 1; i++) {
- svq->vring.desc[i].next = cpu_to_le16(i + 1);
+ svq->desc_next[i] = cpu_to_le16(i + 1);
}
}
@@ -574,6 +596,7 @@ void vhost_svq_stop(VhostShadowVirtqueue *svq)
virtqueue_detach_element(svq->vq, next_avail_elem, 0);
}
svq->vq = NULL;
+ g_free(svq->desc_next);
g_free(svq->ring_id_maps);
qemu_vfree(svq->vring.desc);
qemu_vfree(svq->vring.used);
diff --git a/hw/virtio/vhost-shadow-virtqueue.h b/hw/virtio/vhost-shadow-virtqueue.h
index e5e24c536d..c132c994e9 100644
--- a/hw/virtio/vhost-shadow-virtqueue.h
+++ b/hw/virtio/vhost-shadow-virtqueue.h
@@ -53,6 +53,12 @@ typedef struct VhostShadowVirtqueue {
/* Next VirtQueue element that guest made available */
VirtQueueElement *next_guest_avail_elem;
+ /*
+ * Backup next field for each descriptor so we can recover securely, not
+ * needing to trust the device access.
+ */
+ uint16_t *desc_next;
+
/* Next head to expose to the device */
uint16_t shadow_avail_idx;
diff --git a/hw/virtio/vhost-user-blk-pci.c b/hw/virtio/vhost-user-blk-pci.c
index 33b404d8a2..eef8641a98 100644
--- a/hw/virtio/vhost-user-blk-pci.c
+++ b/hw/virtio/vhost-user-blk-pci.c
@@ -26,7 +26,7 @@
#include "qapi/error.h"
#include "qemu/error-report.h"
#include "qemu/module.h"
-#include "virtio-pci.h"
+#include "hw/virtio/virtio-pci.h"
#include "qom/object.h"
typedef struct VHostUserBlkPCI VHostUserBlkPCI;
diff --git a/hw/virtio/vhost-user-fs-pci.c b/hw/virtio/vhost-user-fs-pci.c
index 2ed8492b3f..6829b8b743 100644
--- a/hw/virtio/vhost-user-fs-pci.c
+++ b/hw/virtio/vhost-user-fs-pci.c
@@ -14,7 +14,7 @@
#include "qemu/osdep.h"
#include "hw/qdev-properties.h"
#include "hw/virtio/vhost-user-fs.h"
-#include "virtio-pci.h"
+#include "hw/virtio/virtio-pci.h"
#include "qom/object.h"
struct VHostUserFSPCI {
diff --git a/hw/virtio/vhost-user-fs.c b/hw/virtio/vhost-user-fs.c
index c595957983..e513e4fdda 100644
--- a/hw/virtio/vhost-user-fs.c
+++ b/hw/virtio/vhost-user-fs.c
@@ -219,8 +219,7 @@ static void vuf_device_realize(DeviceState *dev, Error **errp)
return;
}
- virtio_init(vdev, "vhost-user-fs", VIRTIO_ID_FS,
- sizeof(struct virtio_fs_config));
+ virtio_init(vdev, VIRTIO_ID_FS, sizeof(struct virtio_fs_config));
/* Hiprio queue */
fs->hiprio_vq = virtio_add_queue(vdev, fs->conf.queue_size, vuf_handle_output);
@@ -277,6 +276,12 @@ static void vuf_device_unrealize(DeviceState *dev)
fs->vhost_dev.vqs = NULL;
}
+static struct vhost_dev *vuf_get_vhost(VirtIODevice *vdev)
+{
+ VHostUserFS *fs = VHOST_USER_FS(vdev);
+ return &fs->vhost_dev;
+}
+
static const VMStateDescription vuf_vmstate = {
.name = "vhost-user-fs",
.unmigratable = 1,
@@ -314,6 +319,7 @@ static void vuf_class_init(ObjectClass *klass, void *data)
vdc->set_status = vuf_set_status;
vdc->guest_notifier_mask = vuf_guest_notifier_mask;
vdc->guest_notifier_pending = vuf_guest_notifier_pending;
+ vdc->get_vhost = vuf_get_vhost;
}
static const TypeInfo vuf_info = {
diff --git a/hw/virtio/vhost-user-i2c-pci.c b/hw/virtio/vhost-user-i2c-pci.c
index 70b7b65fd9..00ac10941f 100644
--- a/hw/virtio/vhost-user-i2c-pci.c
+++ b/hw/virtio/vhost-user-i2c-pci.c
@@ -9,7 +9,7 @@
#include "qemu/osdep.h"
#include "hw/qdev-properties.h"
#include "hw/virtio/vhost-user-i2c.h"
-#include "virtio-pci.h"
+#include "hw/virtio/virtio-pci.h"
struct VHostUserI2CPCI {
VirtIOPCIProxy parent_obj;
diff --git a/hw/virtio/vhost-user-i2c.c b/hw/virtio/vhost-user-i2c.c
index 42c7f6d9e5..6020eee093 100644
--- a/hw/virtio/vhost-user-i2c.c
+++ b/hw/virtio/vhost-user-i2c.c
@@ -14,11 +14,6 @@
#include "qemu/error-report.h"
#include "standard-headers/linux/virtio_ids.h"
-/* Remove this once the header is updated in Linux kernel */
-#ifndef VIRTIO_ID_I2C_ADAPTER
-#define VIRTIO_ID_I2C_ADAPTER 34
-#endif
-
static const int feature_bits[] = {
VIRTIO_I2C_F_ZERO_LENGTH_REQUEST,
VHOST_INVALID_FEATURE_BIT
@@ -227,7 +222,7 @@ static void vu_i2c_device_realize(DeviceState *dev, Error **errp)
return;
}
- virtio_init(vdev, "vhost-user-i2c", VIRTIO_ID_I2C_ADAPTER, 0);
+ virtio_init(vdev, VIRTIO_ID_I2C_ADAPTER, 0);
i2c->vhost_dev.nvqs = 1;
i2c->vq = virtio_add_queue(vdev, 4, vu_i2c_handle_output);
diff --git a/hw/virtio/vhost-user-input-pci.c b/hw/virtio/vhost-user-input-pci.c
index c9d3e9113a..b858898a36 100644
--- a/hw/virtio/vhost-user-input-pci.c
+++ b/hw/virtio/vhost-user-input-pci.c
@@ -9,7 +9,7 @@
#include "hw/virtio/virtio-input.h"
#include "qapi/error.h"
#include "qemu/error-report.h"
-#include "virtio-pci.h"
+#include "hw/virtio/virtio-pci.h"
#include "qom/object.h"
typedef struct VHostUserInputPCI VHostUserInputPCI;
diff --git a/hw/virtio/vhost-user-rng-pci.c b/hw/virtio/vhost-user-rng-pci.c
index c83dc86813..f64935453b 100644
--- a/hw/virtio/vhost-user-rng-pci.c
+++ b/hw/virtio/vhost-user-rng-pci.c
@@ -9,7 +9,7 @@
#include "qemu/osdep.h"
#include "hw/qdev-properties.h"
#include "hw/virtio/vhost-user-rng.h"
-#include "virtio-pci.h"
+#include "hw/virtio/virtio-pci.h"
struct VHostUserRNGPCI {
VirtIOPCIProxy parent_obj;
diff --git a/hw/virtio/vhost-user-rng.c b/hw/virtio/vhost-user-rng.c
index 209ee5bf9a..3a7bf8e32d 100644
--- a/hw/virtio/vhost-user-rng.c
+++ b/hw/virtio/vhost-user-rng.c
@@ -203,7 +203,7 @@ static void vu_rng_device_realize(DeviceState *dev, Error **errp)
return;
}
- virtio_init(vdev, "vhost-user-rng", VIRTIO_ID_RNG, 0);
+ virtio_init(vdev, VIRTIO_ID_RNG, 0);
rng->req_vq = virtio_add_queue(vdev, 4, vu_rng_handle_output);
if (!rng->req_vq) {
@@ -247,6 +247,12 @@ static void vu_rng_device_unrealize(DeviceState *dev)
vhost_user_cleanup(&rng->vhost_user);
}
+static struct vhost_dev *vu_rng_get_vhost(VirtIODevice *vdev)
+{
+ VHostUserRNG *rng = VHOST_USER_RNG(vdev);
+ return &rng->vhost_dev;
+}
+
static const VMStateDescription vu_rng_vmstate = {
.name = "vhost-user-rng",
.unmigratable = 1,
@@ -272,6 +278,7 @@ static void vu_rng_class_init(ObjectClass *klass, void *data)
vdc->set_status = vu_rng_set_status;
vdc->guest_notifier_mask = vu_rng_guest_notifier_mask;
vdc->guest_notifier_pending = vu_rng_guest_notifier_pending;
+ vdc->get_vhost = vu_rng_get_vhost;
}
static const TypeInfo vu_rng_info = {
diff --git a/hw/virtio/vhost-user-scsi-pci.c b/hw/virtio/vhost-user-scsi-pci.c
index d5343412a1..75882e3cf9 100644
--- a/hw/virtio/vhost-user-scsi-pci.c
+++ b/hw/virtio/vhost-user-scsi-pci.c
@@ -30,7 +30,7 @@
#include "hw/pci/msix.h"
#include "hw/loader.h"
#include "sysemu/kvm.h"
-#include "virtio-pci.h"
+#include "hw/virtio/virtio-pci.h"
#include "qom/object.h"
typedef struct VHostUserSCSIPCI VHostUserSCSIPCI;
diff --git a/hw/virtio/vhost-user-vsock-pci.c b/hw/virtio/vhost-user-vsock-pci.c
index 72a96199cd..e5a86e8013 100644
--- a/hw/virtio/vhost-user-vsock-pci.c
+++ b/hw/virtio/vhost-user-vsock-pci.c
@@ -10,7 +10,7 @@
#include "qemu/osdep.h"
-#include "virtio-pci.h"
+#include "hw/virtio/virtio-pci.h"
#include "hw/qdev-properties.h"
#include "hw/virtio/vhost-user-vsock.h"
#include "qom/object.h"
diff --git a/hw/virtio/vhost-user-vsock.c b/hw/virtio/vhost-user-vsock.c
index 52bd682c34..0f8ff99f85 100644
--- a/hw/virtio/vhost-user-vsock.c
+++ b/hw/virtio/vhost-user-vsock.c
@@ -107,7 +107,7 @@ static void vuv_device_realize(DeviceState *dev, Error **errp)
return;
}
- vhost_vsock_common_realize(vdev, "vhost-user-vsock");
+ vhost_vsock_common_realize(vdev);
vhost_dev_set_config_notifier(&vvc->vhost_dev, &vsock_ops);
diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
index afd51f79b3..b040c1ad2b 100644
--- a/hw/virtio/vhost-user.c
+++ b/hw/virtio/vhost-user.c
@@ -489,6 +489,8 @@ static int vhost_user_write(struct vhost_dev *dev, VhostUserMsg *msg,
return ret < 0 ? -saved_errno : -EIO;
}
+ trace_vhost_user_write(msg->hdr.request, msg->hdr.flags);
+
return 0;
}
@@ -542,6 +544,8 @@ static int vhost_user_set_log_base(struct vhost_dev *dev, uint64_t base,
}
}
+ trace_vhost_user_read(msg.hdr.request, msg.hdr.flags);
+
return 0;
}
@@ -1170,14 +1174,16 @@ static void vhost_user_host_notifier_free(VhostUserHostNotifier *n)
n->unmap_addr = NULL;
}
-static void vhost_user_host_notifier_remove(VhostUserState *user,
- VirtIODevice *vdev, int queue_idx)
+/*
+ * clean-up function for notifier, will finally free the structure
+ * under rcu.
+ */
+static void vhost_user_host_notifier_remove(VhostUserHostNotifier *n,
+ VirtIODevice *vdev)
{
- VhostUserHostNotifier *n = &user->notifier[queue_idx];
-
if (n->addr) {
if (vdev) {
- virtio_queue_set_host_notifier_mr(vdev, queue_idx, &n->mr, false);
+ virtio_queue_set_host_notifier_mr(vdev, n->idx, &n->mr, false);
}
assert(!n->unmap_addr);
n->unmap_addr = n->addr;
@@ -1221,6 +1227,15 @@ static int vhost_user_set_vring_enable(struct vhost_dev *dev, int enable)
return 0;
}
+static VhostUserHostNotifier *fetch_notifier(VhostUserState *u,
+ int idx)
+{
+ if (idx >= u->notifiers->len) {
+ return NULL;
+ }
+ return g_ptr_array_index(u->notifiers, idx);
+}
+
static int vhost_user_get_vring_base(struct vhost_dev *dev,
struct vhost_vring_state *ring)
{
@@ -1233,7 +1248,10 @@ static int vhost_user_get_vring_base(struct vhost_dev *dev,
};
struct vhost_user *u = dev->opaque;
- vhost_user_host_notifier_remove(u->user, dev->vdev, ring->index);
+ VhostUserHostNotifier *n = fetch_notifier(u->user, ring->index);
+ if (n) {
+ vhost_user_host_notifier_remove(n, dev->vdev);
+ }
ret = vhost_user_write(dev, &msg, NULL, 0);
if (ret < 0) {
@@ -1498,6 +1516,29 @@ static int vhost_user_slave_handle_config_change(struct vhost_dev *dev)
return dev->config_ops->vhost_dev_config_notifier(dev);
}
+/*
+ * Fetch or create the notifier for a given idx. Newly created
+ * notifiers are added to the pointer array that tracks them.
+ */
+static VhostUserHostNotifier *fetch_or_create_notifier(VhostUserState *u,
+ int idx)
+{
+ VhostUserHostNotifier *n = NULL;
+ if (idx >= u->notifiers->len) {
+ g_ptr_array_set_size(u->notifiers, idx);
+ }
+
+ n = g_ptr_array_index(u->notifiers, idx);
+ if (!n) {
+ n = g_new0(VhostUserHostNotifier, 1);
+ n->idx = idx;
+ g_ptr_array_insert(u->notifiers, idx, n);
+ trace_vhost_user_create_notifier(idx, n);
+ }
+
+ return n;
+}
+
static int vhost_user_slave_handle_vring_host_notifier(struct vhost_dev *dev,
VhostUserVringArea *area,
int fd)
@@ -1517,9 +1558,12 @@ static int vhost_user_slave_handle_vring_host_notifier(struct vhost_dev *dev,
return -EINVAL;
}
- n = &user->notifier[queue_idx];
-
- vhost_user_host_notifier_remove(user, vdev, queue_idx);
+ /*
+ * Fetch notifier and invalidate any old data before setting up
+ * new mapped address.
+ */
+ n = fetch_or_create_notifier(user, queue_idx);
+ vhost_user_host_notifier_remove(n, vdev);
if (area->u64 & VHOST_USER_VRING_NOFD_MASK) {
return 0;
@@ -1945,14 +1989,15 @@ static int vhost_user_postcopy_notifier(NotifierWithReturn *notifier,
static int vhost_user_backend_init(struct vhost_dev *dev, void *opaque,
Error **errp)
{
- uint64_t features, protocol_features, ram_slots;
+ uint64_t features, ram_slots;
struct vhost_user *u;
+ VhostUserState *vus = (VhostUserState *) opaque;
int err;
assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_USER);
u = g_new0(struct vhost_user, 1);
- u->user = opaque;
+ u->user = vus;
u->dev = dev;
dev->opaque = u;
@@ -1963,6 +2008,10 @@ static int vhost_user_backend_init(struct vhost_dev *dev, void *opaque,
}
if (virtio_has_feature(features, VHOST_USER_F_PROTOCOL_FEATURES)) {
+ bool supports_f_config = vus->supports_config ||
+ (dev->config_ops && dev->config_ops->vhost_dev_config_notifier);
+ uint64_t protocol_features;
+
dev->backend_features |= 1ULL << VHOST_USER_F_PROTOCOL_FEATURES;
err = vhost_user_get_u64(dev, VHOST_USER_GET_PROTOCOL_FEATURES,
@@ -1972,19 +2021,34 @@ static int vhost_user_backend_init(struct vhost_dev *dev, void *opaque,
return -EPROTO;
}
- dev->protocol_features =
- protocol_features & VHOST_USER_PROTOCOL_FEATURE_MASK;
-
- if (!dev->config_ops || !dev->config_ops->vhost_dev_config_notifier) {
- /* Don't acknowledge CONFIG feature if device doesn't support it */
- dev->protocol_features &= ~(1ULL << VHOST_USER_PROTOCOL_F_CONFIG);
- } else if (!(protocol_features &
- (1ULL << VHOST_USER_PROTOCOL_F_CONFIG))) {
- error_setg(errp, "Device expects VHOST_USER_PROTOCOL_F_CONFIG "
- "but backend does not support it.");
- return -EINVAL;
+ /*
+ * We will use all the protocol features we support - although
+ * we suppress F_CONFIG if we know QEMUs internal code can not support
+ * it.
+ */
+ protocol_features &= VHOST_USER_PROTOCOL_FEATURE_MASK;
+
+ if (supports_f_config) {
+ if (!virtio_has_feature(protocol_features,
+ VHOST_USER_PROTOCOL_F_CONFIG)) {
+ error_setg(errp, "vhost-user device %s expecting "
+ "VHOST_USER_PROTOCOL_F_CONFIG but the vhost-user backend does "
+ "not support it.", dev->vdev->name);
+ return -EPROTO;
+ }
+ } else {
+ if (virtio_has_feature(protocol_features,
+ VHOST_USER_PROTOCOL_F_CONFIG)) {
+ warn_reportf_err(*errp, "vhost-user backend supports "
+ "VHOST_USER_PROTOCOL_F_CONFIG for "
+ "device %s but QEMU does not.",
+ dev->vdev->name);
+ protocol_features &= ~(1ULL << VHOST_USER_PROTOCOL_F_CONFIG);
+ }
}
+ /* final set of protocol features */
+ dev->protocol_features = protocol_features;
err = vhost_user_set_protocol_features(dev, dev->protocol_features);
if (err < 0) {
error_setg_errno(errp, EPROTO, "vhost_backend_init failed");
@@ -2502,6 +2566,20 @@ static int vhost_user_set_inflight_fd(struct vhost_dev *dev,
return vhost_user_write(dev, &msg, &inflight->fd, 1);
}
+static void vhost_user_state_destroy(gpointer data)
+{
+ VhostUserHostNotifier *n = (VhostUserHostNotifier *) data;
+ if (n) {
+ vhost_user_host_notifier_remove(n, NULL);
+ object_unparent(OBJECT(&n->mr));
+ /*
+ * We can't free until vhost_user_host_notifier_remove has
+ * done it's thing so schedule the free with RCU.
+ */
+ g_free_rcu(n, rcu);
+ }
+}
+
bool vhost_user_init(VhostUserState *user, CharBackend *chr, Error **errp)
{
if (user->chr) {
@@ -2510,23 +2588,18 @@ bool vhost_user_init(VhostUserState *user, CharBackend *chr, Error **errp)
}
user->chr = chr;
user->memory_slots = 0;
+ user->notifiers = g_ptr_array_new_full(VIRTIO_QUEUE_MAX / 4,
+ &vhost_user_state_destroy);
return true;
}
void vhost_user_cleanup(VhostUserState *user)
{
- int i;
- VhostUserHostNotifier *n;
-
if (!user->chr) {
return;
}
memory_region_transaction_begin();
- for (i = 0; i < VIRTIO_QUEUE_MAX; i++) {
- n = &user->notifier[i];
- vhost_user_host_notifier_remove(user, NULL, i);
- object_unparent(OBJECT(&n->mr));
- }
+ user->notifiers = (GPtrArray *) g_ptr_array_free(user->notifiers, true);
memory_region_transaction_commit();
user->chr = NULL;
}
diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c
index a30510ed17..66f054a12c 100644
--- a/hw/virtio/vhost-vdpa.c
+++ b/hw/virtio/vhost-vdpa.c
@@ -368,11 +368,18 @@ static void vhost_vdpa_get_iova_range(struct vhost_vdpa *v)
v->iova_range.last);
}
-static bool vhost_vdpa_one_time_request(struct vhost_dev *dev)
+/*
+ * The use of this function is for requests that only need to be
+ * applied once. Typically such request occurs at the beginning
+ * of operation, and before setting up queues. It should not be
+ * used for request that performs operation until all queues are
+ * set, which would need to check dev->vq_index_end instead.
+ */
+static bool vhost_vdpa_first_dev(struct vhost_dev *dev)
{
struct vhost_vdpa *v = dev->opaque;
- return v->index != 0;
+ return v->index == 0;
}
static int vhost_vdpa_get_dev_features(struct vhost_dev *dev,
@@ -453,7 +460,7 @@ static int vhost_vdpa_init(struct vhost_dev *dev, void *opaque, Error **errp)
vhost_vdpa_get_iova_range(v);
- if (vhost_vdpa_one_time_request(dev)) {
+ if (!vhost_vdpa_first_dev(dev)) {
return 0;
}
@@ -596,7 +603,7 @@ static int vhost_vdpa_memslots_limit(struct vhost_dev *dev)
static int vhost_vdpa_set_mem_table(struct vhost_dev *dev,
struct vhost_memory *mem)
{
- if (vhost_vdpa_one_time_request(dev)) {
+ if (!vhost_vdpa_first_dev(dev)) {
return 0;
}
@@ -625,7 +632,7 @@ static int vhost_vdpa_set_features(struct vhost_dev *dev,
struct vhost_vdpa *v = dev->opaque;
int ret;
- if (vhost_vdpa_one_time_request(dev)) {
+ if (!vhost_vdpa_first_dev(dev)) {
return 0;
}
@@ -667,7 +674,7 @@ static int vhost_vdpa_set_backend_cap(struct vhost_dev *dev)
features &= f;
- if (vhost_vdpa_one_time_request(dev)) {
+ if (vhost_vdpa_first_dev(dev)) {
r = vhost_vdpa_call(dev, VHOST_SET_BACKEND_FEATURES, &features);
if (r) {
return -EFAULT;
@@ -1018,7 +1025,7 @@ static bool vhost_vdpa_svqs_start(struct vhost_dev *dev)
VirtQueue *vq = virtio_get_queue(dev->vdev, dev->vq_index + i);
VhostShadowVirtqueue *svq = g_ptr_array_index(v->shadow_vqs, i);
struct vhost_vring_addr addr = {
- .index = i,
+ .index = dev->vq_index + i,
};
int r;
bool ok = vhost_vdpa_svq_setup(dev, svq, i, &err);
@@ -1120,7 +1127,7 @@ static int vhost_vdpa_set_log_base(struct vhost_dev *dev, uint64_t base,
struct vhost_log *log)
{
struct vhost_vdpa *v = dev->opaque;
- if (v->shadow_vqs_enabled || vhost_vdpa_one_time_request(dev)) {
+ if (v->shadow_vqs_enabled || !vhost_vdpa_first_dev(dev)) {
return 0;
}
@@ -1172,11 +1179,11 @@ static int vhost_vdpa_get_vring_base(struct vhost_dev *dev,
struct vhost_vring_state *ring)
{
struct vhost_vdpa *v = dev->opaque;
+ int vdpa_idx = ring->index - dev->vq_index;
int ret;
if (v->shadow_vqs_enabled) {
- VhostShadowVirtqueue *svq = g_ptr_array_index(v->shadow_vqs,
- ring->index);
+ VhostShadowVirtqueue *svq = g_ptr_array_index(v->shadow_vqs, vdpa_idx);
/*
* Setting base as last used idx, so destination will see as available
@@ -1242,7 +1249,7 @@ static int vhost_vdpa_get_features(struct vhost_dev *dev,
static int vhost_vdpa_set_owner(struct vhost_dev *dev)
{
- if (vhost_vdpa_one_time_request(dev)) {
+ if (!vhost_vdpa_first_dev(dev)) {
return 0;
}
diff --git a/hw/virtio/vhost-vsock-common.c b/hw/virtio/vhost-vsock-common.c
index ed706681ac..7394818e00 100644
--- a/hw/virtio/vhost-vsock-common.c
+++ b/hw/virtio/vhost-vsock-common.c
@@ -224,12 +224,11 @@ int vhost_vsock_common_post_load(void *opaque, int version_id)
return 0;
}
-void vhost_vsock_common_realize(VirtIODevice *vdev, const char *name)
+void vhost_vsock_common_realize(VirtIODevice *vdev)
{
VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev);
- virtio_init(vdev, name, VIRTIO_ID_VSOCK,
- sizeof(struct virtio_vsock_config));
+ virtio_init(vdev, VIRTIO_ID_VSOCK, sizeof(struct virtio_vsock_config));
/* Receive and transmit queues belong to vhost */
vvc->recv_vq = virtio_add_queue(vdev, VHOST_VSOCK_QUEUE_SIZE,
@@ -259,6 +258,12 @@ void vhost_vsock_common_unrealize(VirtIODevice *vdev)
virtio_cleanup(vdev);
}
+static struct vhost_dev *vhost_vsock_common_get_vhost(VirtIODevice *vdev)
+{
+ VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev);
+ return &vvc->vhost_dev;
+}
+
static Property vhost_vsock_common_properties[] = {
DEFINE_PROP_ON_OFF_AUTO("seqpacket", VHostVSockCommon, seqpacket,
ON_OFF_AUTO_AUTO),
@@ -274,6 +279,7 @@ static void vhost_vsock_common_class_init(ObjectClass *klass, void *data)
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
vdc->guest_notifier_mask = vhost_vsock_common_guest_notifier_mask;
vdc->guest_notifier_pending = vhost_vsock_common_guest_notifier_pending;
+ vdc->get_vhost = vhost_vsock_common_get_vhost;
}
static const TypeInfo vhost_vsock_common_info = {
diff --git a/hw/virtio/vhost-vsock-pci.c b/hw/virtio/vhost-vsock-pci.c
index 205da8d1f5..9f34414d38 100644
--- a/hw/virtio/vhost-vsock-pci.c
+++ b/hw/virtio/vhost-vsock-pci.c
@@ -13,7 +13,7 @@
#include "qemu/osdep.h"
-#include "virtio-pci.h"
+#include "hw/virtio/virtio-pci.h"
#include "hw/qdev-properties.h"
#include "hw/virtio/vhost-vsock.h"
#include "qemu/module.h"
diff --git a/hw/virtio/vhost-vsock.c b/hw/virtio/vhost-vsock.c
index 714046210b..0338de892f 100644
--- a/hw/virtio/vhost-vsock.c
+++ b/hw/virtio/vhost-vsock.c
@@ -169,7 +169,7 @@ static void vhost_vsock_device_realize(DeviceState *dev, Error **errp)
}
}
- vhost_vsock_common_realize(vdev, "vhost-vsock");
+ vhost_vsock_common_realize(vdev);
ret = vhost_dev_init(&vvc->vhost_dev, (void *)(uintptr_t)vhostfd,
VHOST_BACKEND_TYPE_KERNEL, 0, errp);
diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index 2bc72c27c5..dd3263df56 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -1738,6 +1738,7 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev)
/* should only be called after backend is connected */
assert(hdev->vhost_ops);
+ vdev->vhost_started = true;
hdev->started = true;
hdev->vdev = vdev;
@@ -1810,7 +1811,7 @@ fail_vq:
fail_mem:
fail_features:
-
+ vdev->vhost_started = false;
hdev->started = false;
return r;
}
@@ -1841,6 +1842,7 @@ void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev)
}
vhost_log_put(hdev, true);
hdev->started = false;
+ vdev->vhost_started = false;
hdev->vdev = NULL;
}
diff --git a/hw/virtio/virtio-9p-pci.c b/hw/virtio/virtio-9p-pci.c
index e07adcd9ea..94c14f0b98 100644
--- a/hw/virtio/virtio-9p-pci.c
+++ b/hw/virtio/virtio-9p-pci.c
@@ -15,7 +15,7 @@
#include "qemu/osdep.h"
-#include "virtio-pci.h"
+#include "hw/virtio/virtio-pci.h"
#include "hw/9pfs/virtio-9p.h"
#include "hw/qdev-properties.h"
#include "qemu/module.h"
diff --git a/hw/virtio/virtio-balloon-pci.c b/hw/virtio/virtio-balloon-pci.c
index 79a3ba979a..ce2645ba71 100644
--- a/hw/virtio/virtio-balloon-pci.c
+++ b/hw/virtio/virtio-balloon-pci.c
@@ -14,7 +14,7 @@
#include "qemu/osdep.h"
-#include "virtio-pci.h"
+#include "hw/virtio/virtio-pci.h"
#include "hw/qdev-properties.h"
#include "hw/virtio/virtio-balloon.h"
#include "qapi/error.h"
diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
index 8f1b38ef5c..73ac5eb675 100644
--- a/hw/virtio/virtio-balloon.c
+++ b/hw/virtio/virtio-balloon.c
@@ -882,8 +882,7 @@ static void virtio_balloon_device_realize(DeviceState *dev, Error **errp)
VirtIOBalloon *s = VIRTIO_BALLOON(dev);
int ret;
- virtio_init(vdev, "virtio-balloon", VIRTIO_ID_BALLOON,
- virtio_balloon_config_size(s));
+ virtio_init(vdev, VIRTIO_ID_BALLOON, virtio_balloon_config_size(s));
ret = qemu_add_balloon_handler(virtio_balloon_to_target,
virtio_balloon_stat, s);
diff --git a/hw/virtio/virtio-blk-pci.c b/hw/virtio/virtio-blk-pci.c
index 9d5795810c..9743bee965 100644
--- a/hw/virtio/virtio-blk-pci.c
+++ b/hw/virtio/virtio-blk-pci.c
@@ -19,7 +19,7 @@
#include "hw/qdev-properties.h"
#include "hw/virtio/virtio-blk.h"
-#include "virtio-pci.h"
+#include "hw/virtio/virtio-pci.h"
#include "qapi/error.h"
#include "qemu/module.h"
#include "qom/object.h"
diff --git a/hw/virtio/virtio-bus.c b/hw/virtio/virtio-bus.c
index 0f69d1c742..d7ec023adf 100644
--- a/hw/virtio/virtio-bus.c
+++ b/hw/virtio/virtio-bus.c
@@ -78,17 +78,23 @@ void virtio_bus_device_plugged(VirtIODevice *vdev, Error **errp)
return;
}
- vdev_has_iommu = virtio_host_has_feature(vdev, VIRTIO_F_IOMMU_PLATFORM);
- if (klass->get_dma_as != NULL && has_iommu) {
+ vdev->dma_as = &address_space_memory;
+ if (has_iommu) {
+ vdev_has_iommu = virtio_host_has_feature(vdev, VIRTIO_F_IOMMU_PLATFORM);
+ /*
+ * Present IOMMU_PLATFORM to the driver iff iommu_plattform=on and
+ * device operational. If the driver does not accept IOMMU_PLATFORM
+ * we fail the device.
+ */
virtio_add_feature(&vdev->host_features, VIRTIO_F_IOMMU_PLATFORM);
- vdev->dma_as = klass->get_dma_as(qbus->parent);
- if (!vdev_has_iommu && vdev->dma_as != &address_space_memory) {
- error_setg(errp,
+ if (klass->get_dma_as) {
+ vdev->dma_as = klass->get_dma_as(qbus->parent);
+ if (!vdev_has_iommu && vdev->dma_as != &address_space_memory) {
+ error_setg(errp,
"iommu_platform=true is not supported by the device");
- return;
+ return;
+ }
}
- } else {
- vdev->dma_as = &address_space_memory;
}
}
diff --git a/hw/virtio/virtio-crypto.c b/hw/virtio/virtio-crypto.c
index dcd80b904d..c3829e7498 100644
--- a/hw/virtio/virtio-crypto.c
+++ b/hw/virtio/virtio-crypto.c
@@ -242,7 +242,7 @@ static void virtio_crypto_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
}
out_num = elem->out_num;
- out_iov_copy = g_memdup(elem->out_sg, sizeof(out_iov[0]) * out_num);
+ out_iov_copy = g_memdup2(elem->out_sg, sizeof(out_iov[0]) * out_num);
out_iov = out_iov_copy;
in_num = elem->in_num;
@@ -605,11 +605,11 @@ virtio_crypto_handle_request(VirtIOCryptoReq *request)
}
out_num = elem->out_num;
- out_iov_copy = g_memdup(elem->out_sg, sizeof(out_iov[0]) * out_num);
+ out_iov_copy = g_memdup2(elem->out_sg, sizeof(out_iov[0]) * out_num);
out_iov = out_iov_copy;
in_num = elem->in_num;
- in_iov_copy = g_memdup(elem->in_sg, sizeof(in_iov[0]) * in_num);
+ in_iov_copy = g_memdup2(elem->in_sg, sizeof(in_iov[0]) * in_num);
in_iov = in_iov_copy;
if (unlikely(iov_to_buf(out_iov, out_num, 0, &req, sizeof(req))
@@ -810,7 +810,7 @@ static void virtio_crypto_device_realize(DeviceState *dev, Error **errp)
return;
}
- virtio_init(vdev, "virtio-crypto", VIRTIO_ID_CRYPTO, vcrypto->config_size);
+ virtio_init(vdev, VIRTIO_ID_CRYPTO, vcrypto->config_size);
vcrypto->curr_queues = 1;
vcrypto->vqs = g_new0(VirtIOCryptoQueue, vcrypto->max_queues);
for (i = 0; i < vcrypto->max_queues; i++) {
@@ -961,6 +961,15 @@ static bool virtio_crypto_guest_notifier_pending(VirtIODevice *vdev, int idx)
return cryptodev_vhost_virtqueue_pending(vdev, queue, idx);
}
+static struct vhost_dev *virtio_crypto_get_vhost(VirtIODevice *vdev)
+{
+ VirtIOCrypto *vcrypto = VIRTIO_CRYPTO(vdev);
+ CryptoDevBackend *b = vcrypto->cryptodev;
+ CryptoDevBackendClient *cc = b->conf.peers.ccs[0];
+ CryptoDevBackendVhost *vhost_crypto = cryptodev_get_vhost(cc, b, 0);
+ return &vhost_crypto->dev;
+}
+
static void virtio_crypto_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@@ -977,6 +986,7 @@ static void virtio_crypto_class_init(ObjectClass *klass, void *data)
vdc->set_status = virtio_crypto_set_status;
vdc->guest_notifier_mask = virtio_crypto_guest_notifier_mask;
vdc->guest_notifier_pending = virtio_crypto_guest_notifier_pending;
+ vdc->get_vhost = virtio_crypto_get_vhost;
}
static void virtio_crypto_instance_init(Object *obj)
diff --git a/hw/virtio/virtio-input-host-pci.c b/hw/virtio/virtio-input-host-pci.c
index 0ac360de4f..cf8a9cf9e8 100644
--- a/hw/virtio/virtio-input-host-pci.c
+++ b/hw/virtio/virtio-input-host-pci.c
@@ -8,7 +8,7 @@
#include "qemu/osdep.h"
-#include "virtio-pci.h"
+#include "hw/virtio/virtio-pci.h"
#include "hw/virtio/virtio-input.h"
#include "qemu/module.h"
#include "qom/object.h"
diff --git a/hw/virtio/virtio-input-pci.c b/hw/virtio/virtio-input-pci.c
index 48e9ff38e2..a9d0992389 100644
--- a/hw/virtio/virtio-input-pci.c
+++ b/hw/virtio/virtio-input-pci.c
@@ -8,7 +8,7 @@
#include "qemu/osdep.h"
-#include "virtio-pci.h"
+#include "hw/virtio/virtio-pci.h"
#include "hw/qdev-properties.h"
#include "hw/virtio/virtio-input.h"
#include "qemu/module.h"
diff --git a/hw/virtio/virtio-iommu-pci.c b/hw/virtio/virtio-iommu-pci.c
index 6a1df7fe50..844d647704 100644
--- a/hw/virtio/virtio-iommu-pci.c
+++ b/hw/virtio/virtio-iommu-pci.c
@@ -11,7 +11,7 @@
#include "qemu/osdep.h"
-#include "virtio-pci.h"
+#include "hw/virtio/virtio-pci.h"
#include "hw/virtio/virtio-iommu.h"
#include "hw/qdev-properties.h"
#include "hw/qdev-properties-system.h"
diff --git a/hw/virtio/virtio-iommu.c b/hw/virtio/virtio-iommu.c
index 57c09d98a9..2597e166f9 100644
--- a/hw/virtio/virtio-iommu.c
+++ b/hw/virtio/virtio-iommu.c
@@ -1033,8 +1033,7 @@ static void virtio_iommu_device_realize(DeviceState *dev, Error **errp)
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
VirtIOIOMMU *s = VIRTIO_IOMMU(dev);
- virtio_init(vdev, "virtio-iommu", VIRTIO_ID_IOMMU,
- sizeof(struct virtio_iommu_config));
+ virtio_init(vdev, VIRTIO_ID_IOMMU, sizeof(struct virtio_iommu_config));
memset(s->iommu_pcibus_by_bus_num, 0, sizeof(s->iommu_pcibus_by_bus_num));
diff --git a/hw/virtio/virtio-mem.c b/hw/virtio/virtio-mem.c
index 5aca408726..30d03e987a 100644
--- a/hw/virtio/virtio-mem.c
+++ b/hw/virtio/virtio-mem.c
@@ -867,8 +867,7 @@ static void virtio_mem_device_realize(DeviceState *dev, Error **errp)
vmem->block_size;
vmem->bitmap = bitmap_new(vmem->bitmap_size);
- virtio_init(vdev, TYPE_VIRTIO_MEM, VIRTIO_ID_MEM,
- sizeof(struct virtio_mem_config));
+ virtio_init(vdev, VIRTIO_ID_MEM, sizeof(struct virtio_mem_config));
vmem->vq = virtio_add_queue(vdev, 128, virtio_mem_handle_request);
host_memory_backend_set_mapped(vmem->memdev, true);
diff --git a/hw/virtio/virtio-net-pci.c b/hw/virtio/virtio-net-pci.c
index aa0b3caecb..e03543a70a 100644
--- a/hw/virtio/virtio-net-pci.c
+++ b/hw/virtio/virtio-net-pci.c
@@ -19,7 +19,7 @@
#include "hw/qdev-properties.h"
#include "hw/virtio/virtio-net.h"
-#include "virtio-pci.h"
+#include "hw/virtio/virtio-pci.h"
#include "qapi/error.h"
#include "qemu/module.h"
#include "qom/object.h"
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index 7cf1231c1c..0566ad7d00 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -33,11 +33,12 @@
#include "hw/pci/msix.h"
#include "hw/loader.h"
#include "sysemu/kvm.h"
-#include "virtio-pci.h"
+#include "hw/virtio/virtio-pci.h"
#include "qemu/range.h"
#include "hw/virtio/virtio-bus.h"
#include "qapi/visitor.h"
#include "sysemu/replay.h"
+#include "trace.h"
#define VIRTIO_PCI_REGION_SIZE(dev) VIRTIO_PCI_CONFIG_OFF(msix_present(dev))
@@ -1380,6 +1381,7 @@ static void virtio_pci_notify_write(void *opaque, hwaddr addr,
unsigned queue = addr / virtio_pci_queue_mem_mult(proxy);
if (vdev != NULL && queue < VIRTIO_QUEUE_MAX) {
+ trace_virtio_pci_notify_write(addr, val, size);
virtio_queue_notify(vdev, queue);
}
}
@@ -1393,6 +1395,7 @@ static void virtio_pci_notify_write_pio(void *opaque, hwaddr addr,
unsigned queue = val;
if (vdev != NULL && queue < VIRTIO_QUEUE_MAX) {
+ trace_virtio_pci_notify_write_pio(addr, val, size);
virtio_queue_notify(vdev, queue);
}
}
diff --git a/hw/virtio/virtio-pci.h b/hw/virtio/virtio-pci.h
deleted file mode 100644
index 2446dcd9ae..0000000000
--- a/hw/virtio/virtio-pci.h
+++ /dev/null
@@ -1,255 +0,0 @@
-/*
- * Virtio PCI Bindings
- *
- * Copyright IBM, Corp. 2007
- * Copyright (c) 2009 CodeSourcery
- *
- * Authors:
- * Anthony Liguori <aliguori@us.ibm.com>
- * Paul Brook <paul@codesourcery.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2. See
- * the COPYING file in the top-level directory.
- */
-
-#ifndef QEMU_VIRTIO_PCI_H
-#define QEMU_VIRTIO_PCI_H
-
-#include "hw/pci/msi.h"
-#include "hw/virtio/virtio-bus.h"
-#include "qom/object.h"
-
-
-/* virtio-pci-bus */
-
-typedef struct VirtioBusState VirtioPCIBusState;
-typedef struct VirtioBusClass VirtioPCIBusClass;
-
-#define TYPE_VIRTIO_PCI_BUS "virtio-pci-bus"
-DECLARE_OBJ_CHECKERS(VirtioPCIBusState, VirtioPCIBusClass,
- VIRTIO_PCI_BUS, TYPE_VIRTIO_PCI_BUS)
-
-enum {
- VIRTIO_PCI_FLAG_BUS_MASTER_BUG_MIGRATION_BIT,
- VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT,
- VIRTIO_PCI_FLAG_MIGRATE_EXTRA_BIT,
- VIRTIO_PCI_FLAG_MODERN_PIO_NOTIFY_BIT,
- VIRTIO_PCI_FLAG_DISABLE_PCIE_BIT,
- VIRTIO_PCI_FLAG_PAGE_PER_VQ_BIT,
- VIRTIO_PCI_FLAG_ATS_BIT,
- VIRTIO_PCI_FLAG_INIT_DEVERR_BIT,
- VIRTIO_PCI_FLAG_INIT_LNKCTL_BIT,
- VIRTIO_PCI_FLAG_INIT_PM_BIT,
- VIRTIO_PCI_FLAG_INIT_FLR_BIT,
- VIRTIO_PCI_FLAG_AER_BIT,
- VIRTIO_PCI_FLAG_ATS_PAGE_ALIGNED_BIT,
-};
-
-/* Need to activate work-arounds for buggy guests at vmstate load. */
-#define VIRTIO_PCI_FLAG_BUS_MASTER_BUG_MIGRATION \
- (1 << VIRTIO_PCI_FLAG_BUS_MASTER_BUG_MIGRATION_BIT)
-
-/* Performance improves when virtqueue kick processing is decoupled from the
- * vcpu thread using ioeventfd for some devices. */
-#define VIRTIO_PCI_FLAG_USE_IOEVENTFD (1 << VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT)
-
-/* virtio version flags */
-#define VIRTIO_PCI_FLAG_DISABLE_PCIE (1 << VIRTIO_PCI_FLAG_DISABLE_PCIE_BIT)
-
-/* migrate extra state */
-#define VIRTIO_PCI_FLAG_MIGRATE_EXTRA (1 << VIRTIO_PCI_FLAG_MIGRATE_EXTRA_BIT)
-
-/* have pio notification for modern device ? */
-#define VIRTIO_PCI_FLAG_MODERN_PIO_NOTIFY \
- (1 << VIRTIO_PCI_FLAG_MODERN_PIO_NOTIFY_BIT)
-
-/* page per vq flag to be used by split drivers within guests */
-#define VIRTIO_PCI_FLAG_PAGE_PER_VQ \
- (1 << VIRTIO_PCI_FLAG_PAGE_PER_VQ_BIT)
-
-/* address space translation service */
-#define VIRTIO_PCI_FLAG_ATS (1 << VIRTIO_PCI_FLAG_ATS_BIT)
-
-/* Init error enabling flags */
-#define VIRTIO_PCI_FLAG_INIT_DEVERR (1 << VIRTIO_PCI_FLAG_INIT_DEVERR_BIT)
-
-/* Init Link Control register */
-#define VIRTIO_PCI_FLAG_INIT_LNKCTL (1 << VIRTIO_PCI_FLAG_INIT_LNKCTL_BIT)
-
-/* Init Power Management */
-#define VIRTIO_PCI_FLAG_INIT_PM (1 << VIRTIO_PCI_FLAG_INIT_PM_BIT)
-
-/* Init Function Level Reset capability */
-#define VIRTIO_PCI_FLAG_INIT_FLR (1 << VIRTIO_PCI_FLAG_INIT_FLR_BIT)
-
-/* Advanced Error Reporting capability */
-#define VIRTIO_PCI_FLAG_AER (1 << VIRTIO_PCI_FLAG_AER_BIT)
-
-/* Page Aligned Address space Translation Service */
-#define VIRTIO_PCI_FLAG_ATS_PAGE_ALIGNED \
- (1 << VIRTIO_PCI_FLAG_ATS_PAGE_ALIGNED_BIT)
-
-typedef struct {
- MSIMessage msg;
- int virq;
- unsigned int users;
-} VirtIOIRQFD;
-
-/*
- * virtio-pci: This is the PCIDevice which has a virtio-pci-bus.
- */
-#define TYPE_VIRTIO_PCI "virtio-pci"
-OBJECT_DECLARE_TYPE(VirtIOPCIProxy, VirtioPCIClass, VIRTIO_PCI)
-
-struct VirtioPCIClass {
- PCIDeviceClass parent_class;
- DeviceRealize parent_dc_realize;
- void (*realize)(VirtIOPCIProxy *vpci_dev, Error **errp);
-};
-
-typedef struct VirtIOPCIRegion {
- MemoryRegion mr;
- uint32_t offset;
- uint32_t size;
- uint32_t type;
-} VirtIOPCIRegion;
-
-typedef struct VirtIOPCIQueue {
- uint16_t num;
- bool enabled;
- uint32_t desc[2];
- uint32_t avail[2];
- uint32_t used[2];
-} VirtIOPCIQueue;
-
-struct VirtIOPCIProxy {
- PCIDevice pci_dev;
- MemoryRegion bar;
- union {
- struct {
- VirtIOPCIRegion common;
- VirtIOPCIRegion isr;
- VirtIOPCIRegion device;
- VirtIOPCIRegion notify;
- VirtIOPCIRegion notify_pio;
- };
- VirtIOPCIRegion regs[5];
- };
- MemoryRegion modern_bar;
- MemoryRegion io_bar;
- uint32_t legacy_io_bar_idx;
- uint32_t msix_bar_idx;
- uint32_t modern_io_bar_idx;
- uint32_t modern_mem_bar_idx;
- int config_cap;
- uint32_t flags;
- bool disable_modern;
- bool ignore_backend_features;
- OnOffAuto disable_legacy;
- uint32_t class_code;
- uint32_t nvectors;
- uint32_t dfselect;
- uint32_t gfselect;
- uint32_t guest_features[2];
- VirtIOPCIQueue vqs[VIRTIO_QUEUE_MAX];
-
- VirtIOIRQFD *vector_irqfd;
- int nvqs_with_notifiers;
- VirtioBusState bus;
-};
-
-static inline bool virtio_pci_modern(VirtIOPCIProxy *proxy)
-{
- return !proxy->disable_modern;
-}
-
-static inline bool virtio_pci_legacy(VirtIOPCIProxy *proxy)
-{
- return proxy->disable_legacy == ON_OFF_AUTO_OFF;
-}
-
-static inline void virtio_pci_force_virtio_1(VirtIOPCIProxy *proxy)
-{
- proxy->disable_modern = false;
- proxy->disable_legacy = ON_OFF_AUTO_ON;
-}
-
-static inline void virtio_pci_disable_modern(VirtIOPCIProxy *proxy)
-{
- proxy->disable_modern = true;
-}
-
-/*
- * virtio-input-pci: This extends VirtioPCIProxy.
- */
-#define TYPE_VIRTIO_INPUT_PCI "virtio-input-pci"
-
-/* Virtio ABI version, if we increment this, we break the guest driver. */
-#define VIRTIO_PCI_ABI_VERSION 0
-
-/* Input for virtio_pci_types_register() */
-typedef struct VirtioPCIDeviceTypeInfo {
- /*
- * Common base class for the subclasses below.
- *
- * Required only if transitional_name or non_transitional_name is set.
- *
- * We need a separate base type instead of making all types
- * inherit from generic_name for two reasons:
- * 1) generic_name implements INTERFACE_PCIE_DEVICE, but
- * transitional_name does not.
- * 2) generic_name has the "disable-legacy" and "disable-modern"
- * properties, transitional_name and non_transitional name don't.
- */
- const char *base_name;
- /*
- * Generic device type. Optional.
- *
- * Supports both transitional and non-transitional modes,
- * using the disable-legacy and disable-modern properties.
- * If disable-legacy=auto, (non-)transitional mode is selected
- * depending on the bus where the device is plugged.
- *
- * Implements both INTERFACE_PCIE_DEVICE and INTERFACE_CONVENTIONAL_PCI_DEVICE,
- * but PCI Express is supported only in non-transitional mode.
- *
- * The only type implemented by QEMU 3.1 and older.
- */
- const char *generic_name;
- /*
- * The transitional device type. Optional.
- *
- * Implements both INTERFACE_PCIE_DEVICE and INTERFACE_CONVENTIONAL_PCI_DEVICE.
- */
- const char *transitional_name;
- /*
- * The non-transitional device type. Optional.
- *
- * Implements INTERFACE_CONVENTIONAL_PCI_DEVICE only.
- */
- const char *non_transitional_name;
-
- /* Parent type. If NULL, TYPE_VIRTIO_PCI is used */
- const char *parent;
-
- /* Same as TypeInfo fields: */
- size_t instance_size;
- size_t class_size;
- void (*instance_init)(Object *obj);
- void (*class_init)(ObjectClass *klass, void *data);
- InterfaceInfo *interfaces;
-} VirtioPCIDeviceTypeInfo;
-
-/* Register virtio-pci type(s). @t must be static. */
-void virtio_pci_types_register(const VirtioPCIDeviceTypeInfo *t);
-
-/**
- * virtio_pci_optimal_num_queues:
- * @fixed_queues: number of queues that are always present
- *
- * Returns: The optimal number of queues for a multi-queue device, excluding
- * @fixed_queues.
- */
-unsigned virtio_pci_optimal_num_queues(unsigned fixed_queues);
-
-#endif
diff --git a/hw/virtio/virtio-pmem.c b/hw/virtio/virtio-pmem.c
index 5dd21c2c44..a1abfe0e1b 100644
--- a/hw/virtio/virtio-pmem.c
+++ b/hw/virtio/virtio-pmem.c
@@ -122,8 +122,7 @@ static void virtio_pmem_realize(DeviceState *dev, Error **errp)
}
host_memory_backend_set_mapped(pmem->memdev, true);
- virtio_init(vdev, TYPE_VIRTIO_PMEM, VIRTIO_ID_PMEM,
- sizeof(struct virtio_pmem_config));
+ virtio_init(vdev, VIRTIO_ID_PMEM, sizeof(struct virtio_pmem_config));
pmem->rq_vq = virtio_add_queue(vdev, 128, virtio_pmem_flush);
}
diff --git a/hw/virtio/virtio-rng-pci.c b/hw/virtio/virtio-rng-pci.c
index c1f916268b..151ece6f94 100644
--- a/hw/virtio/virtio-rng-pci.c
+++ b/hw/virtio/virtio-rng-pci.c
@@ -11,7 +11,7 @@
#include "qemu/osdep.h"
-#include "virtio-pci.h"
+#include "hw/virtio/virtio-pci.h"
#include "hw/virtio/virtio-rng.h"
#include "qapi/error.h"
#include "qemu/module.h"
diff --git a/hw/virtio/virtio-rng.c b/hw/virtio/virtio-rng.c
index cc8e9f775d..7e12fc03bf 100644
--- a/hw/virtio/virtio-rng.c
+++ b/hw/virtio/virtio-rng.c
@@ -215,7 +215,7 @@ static void virtio_rng_device_realize(DeviceState *dev, Error **errp)
return;
}
- virtio_init(vdev, "virtio-rng", VIRTIO_ID_RNG, 0);
+ virtio_init(vdev, VIRTIO_ID_RNG, 0);
vrng->vq = virtio_add_queue(vdev, 8, handle_input);
vrng->quota_remaining = vrng->conf.max_bytes;
diff --git a/hw/virtio/virtio-scsi-pci.c b/hw/virtio/virtio-scsi-pci.c
index 97fab74236..e8e3442f38 100644
--- a/hw/virtio/virtio-scsi-pci.c
+++ b/hw/virtio/virtio-scsi-pci.c
@@ -18,7 +18,7 @@
#include "hw/qdev-properties.h"
#include "hw/virtio/virtio-scsi.h"
#include "qemu/module.h"
-#include "virtio-pci.h"
+#include "hw/virtio/virtio-pci.h"
#include "qom/object.h"
typedef struct VirtIOSCSIPCI VirtIOSCSIPCI;
diff --git a/hw/virtio/virtio-serial-pci.c b/hw/virtio/virtio-serial-pci.c
index 35bcd961c9..cea31adcc4 100644
--- a/hw/virtio/virtio-serial-pci.c
+++ b/hw/virtio/virtio-serial-pci.c
@@ -20,7 +20,7 @@
#include "hw/qdev-properties.h"
#include "hw/virtio/virtio-serial.h"
#include "qemu/module.h"
-#include "virtio-pci.h"
+#include "hw/virtio/virtio-pci.h"
#include "qom/object.h"
typedef struct VirtIOSerialPCI VirtIOSerialPCI;
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index 67a873f54a..5d607aeaa0 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -132,6 +132,56 @@ struct VirtQueue
QLIST_ENTRY(VirtQueue) node;
};
+const char *virtio_device_names[] = {
+ [VIRTIO_ID_NET] = "virtio-net",
+ [VIRTIO_ID_BLOCK] = "virtio-blk",
+ [VIRTIO_ID_CONSOLE] = "virtio-serial",
+ [VIRTIO_ID_RNG] = "virtio-rng",
+ [VIRTIO_ID_BALLOON] = "virtio-balloon",
+ [VIRTIO_ID_IOMEM] = "virtio-iomem",
+ [VIRTIO_ID_RPMSG] = "virtio-rpmsg",
+ [VIRTIO_ID_SCSI] = "virtio-scsi",
+ [VIRTIO_ID_9P] = "virtio-9p",
+ [VIRTIO_ID_MAC80211_WLAN] = "virtio-mac-wlan",
+ [VIRTIO_ID_RPROC_SERIAL] = "virtio-rproc-serial",
+ [VIRTIO_ID_CAIF] = "virtio-caif",
+ [VIRTIO_ID_MEMORY_BALLOON] = "virtio-mem-balloon",
+ [VIRTIO_ID_GPU] = "virtio-gpu",
+ [VIRTIO_ID_CLOCK] = "virtio-clk",
+ [VIRTIO_ID_INPUT] = "virtio-input",
+ [VIRTIO_ID_VSOCK] = "vhost-vsock",
+ [VIRTIO_ID_CRYPTO] = "virtio-crypto",
+ [VIRTIO_ID_SIGNAL_DIST] = "virtio-signal",
+ [VIRTIO_ID_PSTORE] = "virtio-pstore",
+ [VIRTIO_ID_IOMMU] = "virtio-iommu",
+ [VIRTIO_ID_MEM] = "virtio-mem",
+ [VIRTIO_ID_SOUND] = "virtio-sound",
+ [VIRTIO_ID_FS] = "virtio-user-fs",
+ [VIRTIO_ID_PMEM] = "virtio-pmem",
+ [VIRTIO_ID_RPMB] = "virtio-rpmb",
+ [VIRTIO_ID_MAC80211_HWSIM] = "virtio-mac-hwsim",
+ [VIRTIO_ID_VIDEO_ENCODER] = "virtio-vid-encoder",
+ [VIRTIO_ID_VIDEO_DECODER] = "virtio-vid-decoder",
+ [VIRTIO_ID_SCMI] = "virtio-scmi",
+ [VIRTIO_ID_NITRO_SEC_MOD] = "virtio-nitro-sec-mod",
+ [VIRTIO_ID_I2C_ADAPTER] = "vhost-user-i2c",
+ [VIRTIO_ID_WATCHDOG] = "virtio-watchdog",
+ [VIRTIO_ID_CAN] = "virtio-can",
+ [VIRTIO_ID_DMABUF] = "virtio-dmabuf",
+ [VIRTIO_ID_PARAM_SERV] = "virtio-param-serv",
+ [VIRTIO_ID_AUDIO_POLICY] = "virtio-audio-pol",
+ [VIRTIO_ID_BT] = "virtio-bluetooth",
+ [VIRTIO_ID_GPIO] = "virtio-gpio"
+};
+
+static const char *virtio_id_to_name(uint16_t device_id)
+{
+ assert(device_id < G_N_ELEMENTS(virtio_device_names));
+ const char *name = virtio_device_names[device_id];
+ assert(name != NULL);
+ return name;
+}
+
/* Called within call_rcu(). */
static void virtio_free_region_cache(VRingMemoryRegionCaches *caches)
{
@@ -3207,8 +3257,7 @@ void virtio_instance_init_common(Object *proxy_obj, void *data,
qdev_alias_all_properties(vdev, proxy_obj);
}
-void virtio_init(VirtIODevice *vdev, const char *name,
- uint16_t device_id, size_t config_size)
+void virtio_init(VirtIODevice *vdev, uint16_t device_id, size_t config_size)
{
BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
@@ -3222,6 +3271,7 @@ void virtio_init(VirtIODevice *vdev, const char *name,
vdev->start_on_kick = false;
vdev->started = false;
+ vdev->vhost_started = false;
vdev->device_id = device_id;
vdev->status = 0;
qatomic_set(&vdev->isr, 0);
@@ -3237,7 +3287,7 @@ void virtio_init(VirtIODevice *vdev, const char *name,
vdev->vq[i].host_notifier_enabled = false;
}
- vdev->name = name;
+ vdev->name = virtio_id_to_name(device_id);
vdev->config_len = config_size;
if (vdev->config_len) {
vdev->config = g_malloc0(config_size);