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 <[email protected]>
---
 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)


Reply via email to