* [PATCH] vhost: Always initialize cached vring data
@ 2025-12-08 11:30 Hanna Czenczek
2025-12-09 7:10 ` [PATCH-for-10.2] " Philippe Mathieu-Daudé
0 siblings, 1 reply; 2+ messages in thread
From: Hanna Czenczek @ 2025-12-08 11:30 UTC (permalink / raw)
To: qemu-devel; +Cc: Hanna Czenczek, Stefano Garzarella, Michael S . Tsirkin
vhost_virtqueue_start() can exit early if the descriptor ring address is
0, assuming the virtqueue isn’t ready to start.
In this case, all cached vring information (size, physical address,
pointer) is left as-is. This is OK at first startup, when that info is
still initialized to 0, but after a reset, it will retain old (outdated)
information.
vhost_virtqueue_start() must make sure these values are (re-)set
properly before exiting.
(When using an IOMMU, these outdated values can stall the device:
vhost_dev_start() deliberately produces an IOMMU miss event for each
used vring. If used_phys contains an outdated value, the resulting
lookup may fail, forcing the device to be stopped.)
Cc: qemu-stable@nongnu.org
Signed-off-by: Hanna Czenczek <hreitz@redhat.com>
---
hw/virtio/vhost.c | 38 +++++++++++++++++++++++---------------
1 file changed, 23 insertions(+), 15 deletions(-)
diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index 266a11514a..e654ea468a 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -1261,7 +1261,7 @@ int vhost_virtqueue_start(struct vhost_dev *dev,
BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
VirtioBusState *vbus = VIRTIO_BUS(qbus);
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(vbus);
- hwaddr s, l, a;
+ hwaddr l;
int r;
int vhost_vq_index = dev->vhost_ops->vhost_get_vq_index(dev, idx);
struct vhost_vring_file file = {
@@ -1272,8 +1272,17 @@ int vhost_virtqueue_start(struct vhost_dev *dev,
};
struct VirtQueue *vvq = virtio_get_queue(vdev, idx);
- a = virtio_queue_get_desc_addr(vdev, idx);
- if (a == 0) {
+ vq->desc_size = virtio_queue_get_desc_size(vdev, idx);
+ vq->desc_phys = virtio_queue_get_desc_addr(vdev, idx);
+ vq->desc = NULL;
+ vq->avail_size = virtio_queue_get_avail_size(vdev, idx);
+ vq->avail_phys = virtio_queue_get_avail_addr(vdev, idx);
+ vq->avail = NULL;
+ vq->used_size = virtio_queue_get_used_size(vdev, idx);
+ vq->used_phys = virtio_queue_get_used_addr(vdev, idx);
+ vq->used = NULL;
+
+ if (vq->desc_phys == 0) {
/* Queue might not be ready for start */
return 0;
}
@@ -1301,24 +1310,23 @@ int vhost_virtqueue_start(struct vhost_dev *dev,
}
}
- vq->desc_size = s = l = virtio_queue_get_desc_size(vdev, idx);
- vq->desc_phys = a;
- vq->desc = vhost_memory_map(dev, a, &l, false);
- if (!vq->desc || l != s) {
+ l = vq->desc_size;
+ vq->desc = vhost_memory_map(dev, vq->desc_phys, &l, false);
+ if (!vq->desc || l != vq->desc_size) {
r = -ENOMEM;
goto fail_alloc_desc;
}
- vq->avail_size = s = l = virtio_queue_get_avail_size(vdev, idx);
- vq->avail_phys = a = virtio_queue_get_avail_addr(vdev, idx);
- vq->avail = vhost_memory_map(dev, a, &l, false);
- if (!vq->avail || l != s) {
+
+ l = vq->avail_size;
+ vq->avail = vhost_memory_map(dev, vq->avail_phys, &l, false);
+ if (!vq->avail || l != vq->avail_size) {
r = -ENOMEM;
goto fail_alloc_avail;
}
- vq->used_size = s = l = virtio_queue_get_used_size(vdev, idx);
- vq->used_phys = a = virtio_queue_get_used_addr(vdev, idx);
- vq->used = vhost_memory_map(dev, a, &l, true);
- if (!vq->used || l != s) {
+
+ l = vq->used_size;
+ vq->used = vhost_memory_map(dev, vq->used_phys, &l, true);
+ if (!vq->used || l != vq->used_size) {
r = -ENOMEM;
goto fail_alloc_used;
}
--
2.52.0
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH-for-10.2] vhost: Always initialize cached vring data
2025-12-08 11:30 [PATCH] vhost: Always initialize cached vring data Hanna Czenczek
@ 2025-12-09 7:10 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 2+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-12-09 7:10 UTC (permalink / raw)
To: Hanna Czenczek, qemu-devel; +Cc: Stefano Garzarella, Michael S . Tsirkin
On 8/12/25 12:30, Hanna Czenczek wrote:
> vhost_virtqueue_start() can exit early if the descriptor ring address is
> 0, assuming the virtqueue isn’t ready to start.
>
> In this case, all cached vring information (size, physical address,
> pointer) is left as-is. This is OK at first startup, when that info is
> still initialized to 0, but after a reset, it will retain old (outdated)
> information.
>
> vhost_virtqueue_start() must make sure these values are (re-)set
> properly before exiting.
>
> (When using an IOMMU, these outdated values can stall the device:
> vhost_dev_start() deliberately produces an IOMMU miss event for each
> used vring. If used_phys contains an outdated value, the resulting
> lookup may fail, forcing the device to be stopped.)
>
> Cc: qemu-stable@nongnu.org
> Signed-off-by: Hanna Czenczek <hreitz@redhat.com>
> ---
> hw/virtio/vhost.c | 38 +++++++++++++++++++++++---------------
> 1 file changed, 23 insertions(+), 15 deletions(-)
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2025-12-09 7:11 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-12-08 11:30 [PATCH] vhost: Always initialize cached vring data Hanna Czenczek
2025-12-09 7:10 ` [PATCH-for-10.2] " Philippe Mathieu-Daudé
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).