@samitouri / QOSamiQemu / commits / 927d0beaad

vhost: move svq next desc array to descs state struct

It's the right place for it as it is part of the descriptor state. We save the memory management of the array, and make the code changes of the next patches easier. Signed-off-by: Eugenio Pérez <eperezma@redhat.com> Acked-by: Jason Wang <jasowang@redhat.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com> Message-Id: <20260304173535.2702587-3-eperezma@redhat.com>

Eugenio Pérez committed Mar 4, 2026 at 18:35 UTC 927d0beaad0ac6db96865a96fdad0c1a93b3477d
2 files changed +12 -14
hw/virtio/vhost-shadow-virtqueue.c
+6 -8
@@ -175,7 +175,7 @@ static bool vhost_svq_vring_write_descs(VhostShadowVirtqueue *svq, hwaddr *sg,
175 for (n = 0; n < num; n++) {
176 if (more_descs || (n + 1 < num)) {
177 descs[i].flags = flags | cpu_to_le16(VRING_DESC_F_NEXT);
178 - descs[i].next = cpu_to_le16(svq->desc_next[i]);
178 + descs[i].next = cpu_to_le16(svq->desc_state[i].next);
179 } else {
180 descs[i].flags = flags;
181 }
@@ -183,10 +183,10 @@ static bool vhost_svq_vring_write_descs(VhostShadowVirtqueue *svq, hwaddr *sg,
183 descs[i].len = cpu_to_le32(iovec[n].iov_len);
184
185 last = i;
186 - i = svq->desc_next[i];
186 + i = svq->desc_state[i].next;
187 }
188
189 - svq->free_head = svq->desc_next[last];
189 + svq->free_head = svq->desc_state[last].next;
190 return true;
191 }
192
@@ -432,7 +432,7 @@ static uint16_t vhost_svq_last_desc_of_chain(const VhostShadowVirtqueue *svq,
432 uint16_t num, uint16_t i)
433 {
434 for (uint16_t j = 0; j < (num - 1); ++j) {
435 - i = svq->desc_next[i];
435 + i = svq->desc_state[i].next;
436 }
437
438 return i;
@@ -473,7 +473,7 @@ static VirtQueueElement *vhost_svq_get_buf(VhostShadowVirtqueue *svq,
473 num = svq->desc_state[used_elem.id].ndescs;
474 svq->desc_state[used_elem.id].ndescs = 0;
475 last_used_chain = vhost_svq_last_desc_of_chain(svq, num, used_elem.id);
476 - svq->desc_next[last_used_chain] = svq->free_head;
476 + svq->desc_state[last_used_chain].next = svq->free_head;
477 svq->free_head = used_elem.id;
478 svq->num_free += num;
479
@@ -705,9 +705,8 @@ void vhost_svq_start(VhostShadowVirtqueue *svq, VirtIODevice *vdev,
705 PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS,
706 -1, 0);
707 svq->desc_state = g_new0(SVQDescState, svq->vring.num);
708 - svq->desc_next = g_new0(uint16_t, svq->vring.num);
708 for (unsigned i = 0; i < svq->vring.num - 1; i++) {
710 - svq->desc_next[i] = i + 1;
709 + svq->desc_state[i].next = i + 1;
710 }
711 }
712
@@ -744,7 +743,6 @@ void vhost_svq_stop(VhostShadowVirtqueue *svq)
743 virtqueue_unpop(svq->vq, next_avail_elem, 0);
744 }
745 svq->vq = NULL;
747 - g_free(svq->desc_next);
746 g_free(svq->desc_state);
747 munmap(svq->vring.desc, vhost_svq_driver_area_size(svq));
748 munmap(svq->vring.used, vhost_svq_device_area_size(svq));
hw/virtio/vhost-shadow-virtqueue.h
+6 -6
@@ -23,6 +23,12 @@ typedef struct SVQDescState {
23 * guest's
24 */
25 unsigned int ndescs;
26 +
27 + /*
28 + * Backup next field for each descriptor so we can recover securely, not
29 + * needing to trust the device access.
30 + */
31 + uint16_t next;
32 } SVQDescState;
33
34 typedef struct VhostShadowVirtqueue VhostShadowVirtqueue;
@@ -84,12 +90,6 @@ typedef struct VhostShadowVirtqueue {
90 /* Next VirtQueue element that guest made available */
91 VirtQueueElement *next_guest_avail_elem;
92
87 - /*
88 - * Backup next field for each descriptor so we can recover securely, not
89 - * needing to trust the device access.
90 - */
91 - uint16_t *desc_next;
92 -
93 /* Caller callbacks */
94 const VhostShadowVirtqueueOps *ops;
95