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)
