[PATCH] hw/virtio/virtio: Rebuild vring caches when packed ring changes

Munkhbaatar Enkhbaatar posted 1 patch 1 month ago
Patches applied successfully (tree, apply log)
git fetch https://github.com/patchew-project/qemu tags/patchew/20260507145100.4861-1-munkhuu0825@gmail.com
Maintainers: "Michael S. Tsirkin" <mst@redhat.com>
hw/virtio/virtio.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
[PATCH] hw/virtio/virtio: Rebuild vring caches when packed ring changes
Posted by Munkhbaatar Enkhbaatar 1 month ago
A guest can enable a virtqueue before feature negotiation completes, so
virtio_queue_set_rings() creates caches before VIRTIO_F_RING_PACKED is
loaded into guest_features.
Packed rings need a writable descriptor cache because used descriptors are
written back into the descriptor ring. If the cache was created as a split
ring cache, this can later trigger an assertion.
Rebuild existing vring caches when VIRTIO_F_RING_PACKED changes, as already
done for VIRTIO_RING_F_EVENT_IDX.

Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3466

Signed-off-by: Munkhbaatar Enkhbaatar <munkhuu0825@gmail.com>
---
 hw/virtio/virtio.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index 63e2faee99..14e7dd70be 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -3223,8 +3223,9 @@ int virtio_set_features_ex(VirtIODevice *vdev, const uint64_t *features)
     }
 
     ret = virtio_set_features_nocheck(vdev, features);
-    if (virtio_vdev_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) {
+    if (virtio_vdev_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX) || virtio_vdev_has_feature(vdev, VIRTIO_F_RING_PACKED)) {
         /* VIRTIO_RING_F_EVENT_IDX changes the size of the caches.  */
+        /* VIRTIO_F_RING_PACKED changes the cache->is_write value. */
         int i;
         for (i = 0; i < VIRTIO_QUEUE_MAX; i++) {
             if (vdev->vq[i].vring.num != 0) {
-- 
2.50.1 (Apple Git-155)
Re: [PATCH] hw/virtio/virtio: Rebuild vring caches when packed ring changes
Posted by Munkhbaatar Enkhbaatar 3 days, 10 hours ago
Hi,

Just a gentle ping on this patch.

It fixes a virtio-sound assertion with packed=on by rebuilding existing
vring caches when VIRTIO_F_RING_PACKED changes. The issue is tracked here:

https://gitlab.com/qemu-project/qemu/-/work_items/3466

Please let me know if any changes are needed.

Thanks,
Munkhbaatar

> On 7 May 2026, at 22:51, Munkhbaatar Enkhbaatar <munkhuu0825@gmail.com> wrote:
> 
> A guest can enable a virtqueue before feature negotiation completes, so
> virtio_queue_set_rings() creates caches before VIRTIO_F_RING_PACKED is
> loaded into guest_features.
> Packed rings need a writable descriptor cache because used descriptors are
> written back into the descriptor ring. If the cache was created as a split
> ring cache, this can later trigger an assertion.
> Rebuild existing vring caches when VIRTIO_F_RING_PACKED changes, as already
> done for VIRTIO_RING_F_EVENT_IDX.
> 
> Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3466
> 
> Signed-off-by: Munkhbaatar Enkhbaatar <munkhuu0825@gmail.com>
> ---
> hw/virtio/virtio.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
> index 63e2faee99..14e7dd70be 100644
> --- a/hw/virtio/virtio.c
> +++ b/hw/virtio/virtio.c
> @@ -3223,8 +3223,9 @@ int virtio_set_features_ex(VirtIODevice *vdev, const uint64_t *features)
>     }
> 
>     ret = virtio_set_features_nocheck(vdev, features);
> -    if (virtio_vdev_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) {
> +    if (virtio_vdev_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX) || virtio_vdev_has_feature(vdev, VIRTIO_F_RING_PACKED)) {
>         /* VIRTIO_RING_F_EVENT_IDX changes the size of the caches.  */
> +        /* VIRTIO_F_RING_PACKED changes the cache->is_write value. */
>         int i;
>         for (i = 0; i < VIRTIO_QUEUE_MAX; i++) {
>             if (vdev->vq[i].vring.num != 0) {
> -- 
> 2.50.1 (Apple Git-155)
>