@@ -17,6 +17,10 @@
#include "qemu/error-report.h"
#include "qemu/main-loop.h"
+typedef struct SVQElement {
+ VirtQueueElement elem;
+} SVQElement;
+
/* Shadow virtqueue to relay notifications */
struct VhostShadowVirtqueue {
/* Shadow vring */
@@ -50,10 +54,10 @@ struct VhostShadowVirtqueue {
VhostIOVATree *iova_tree;
/* Map for returning guest's descriptors */
- VirtQueueElement **ring_id_maps;
+ SVQElement **ring_id_maps;
/* Next VirtQueue element that guest made available */
- VirtQueueElement *next_guest_avail_elem;
+ SVQElement *next_guest_avail_elem;
/* Next head to expose to device */
uint16_t avail_idx_shadow;
@@ -281,9 +285,10 @@ static void vhost_vring_write_descs(VhostShadowVirtqueue *svq,
}
static bool vhost_svq_add_split(VhostShadowVirtqueue *svq,
- VirtQueueElement *elem,
+ SVQElement *svq_elem,
unsigned *head)
{
+ const VirtQueueElement *elem = &svq_elem->elem;
unsigned avail_idx;
vring_avail_t *avail = svq->vring.avail;
bool ok;
@@ -324,7 +329,7 @@ static bool vhost_svq_add_split(VhostShadowVirtqueue *svq,
return true;
}
-static bool vhost_svq_add(VhostShadowVirtqueue *svq, VirtQueueElement *elem)
+static bool vhost_svq_add(VhostShadowVirtqueue *svq, SVQElement *elem)
{
unsigned qemu_head;
bool ok = vhost_svq_add_split(svq, elem, &qemu_head);
@@ -372,19 +377,21 @@ static void vhost_handle_guest_kick(VhostShadowVirtqueue *svq)
}
while (true) {
+ SVQElement *svq_elem;
VirtQueueElement *elem;
bool ok;
if (svq->next_guest_avail_elem) {
- elem = g_steal_pointer(&svq->next_guest_avail_elem);
+ svq_elem = g_steal_pointer(&svq->next_guest_avail_elem);
} else {
- elem = virtqueue_pop(svq->vq, sizeof(*elem));
+ svq_elem = virtqueue_pop(svq->vq, sizeof(*elem));
}
- if (!elem) {
+ if (!svq_elem) {
break;
}
+ elem = &svq_elem->elem;
if (elem->out_num + elem->in_num >
vhost_svq_available_slots(svq)) {
/*
@@ -398,11 +405,11 @@ static void vhost_handle_guest_kick(VhostShadowVirtqueue *svq)
* queue the current guest descriptor and ignore further kicks
* until some elements are used.
*/
- svq->next_guest_avail_elem = elem;
+ svq->next_guest_avail_elem = svq_elem;
return;
}
- ok = vhost_svq_add(svq, elem);
+ ok = vhost_svq_add(svq, svq_elem);
if (unlikely(!ok)) {
/* VQ is broken, just return and ignore any other kicks */
return;
@@ -437,7 +444,7 @@ static bool vhost_svq_more_used(VhostShadowVirtqueue *svq)
return svq->last_used_idx != svq->shadow_used_idx;
}
-static VirtQueueElement *vhost_svq_get_buf(VhostShadowVirtqueue *svq)
+static SVQElement *vhost_svq_get_buf(VhostShadowVirtqueue *svq)
{
vring_desc_t *descs = svq->vring.desc;
const vring_used_t *used = svq->vring.used;
@@ -471,7 +478,7 @@ static VirtQueueElement *vhost_svq_get_buf(VhostShadowVirtqueue *svq)
descs[used_elem.id].next = svq->free_head;
svq->free_head = used_elem.id;
- svq->ring_id_maps[used_elem.id]->len = used_elem.len;
+ svq->ring_id_maps[used_elem.id]->elem.len = used_elem.len;
return g_steal_pointer(&svq->ring_id_maps[used_elem.id]);
}
@@ -486,11 +493,13 @@ static void vhost_svq_flush(VhostShadowVirtqueue *svq,
vhost_svq_set_notification(svq, false);
while (true) {
- g_autofree VirtQueueElement *elem = vhost_svq_get_buf(svq);
- if (!elem) {
+ g_autofree SVQElement *svq_elem = vhost_svq_get_buf(svq);
+ VirtQueueElement *elem;
+ if (!svq_elem) {
break;
}
+ elem = &svq_elem->elem;
if (unlikely(i >= svq->vring.num)) {
virtio_error(svq->vdev,
"More than %u used buffers obtained in a %u size SVQ",
@@ -667,7 +676,7 @@ void vhost_svq_start(VhostShadowVirtqueue *svq, VirtIODevice *vdev,
void vhost_svq_stop(VhostShadowVirtqueue *svq)
{
event_notifier_set_handler(&svq->svq_kick, NULL);
- g_autofree VirtQueueElement *next_avail_elem = NULL;
+ g_autofree SVQElement *next_avail_elem = NULL;
if (!svq->vq) {
return;
@@ -677,17 +686,18 @@ void vhost_svq_stop(VhostShadowVirtqueue *svq)
vhost_svq_flush(svq, false);
for (unsigned i = 0; i < svq->vring.num; ++i) {
- g_autofree VirtQueueElement *elem = NULL;
- elem = g_steal_pointer(&svq->ring_id_maps[i]);
- if (elem) {
- virtqueue_detach_element(svq->vq, elem, elem->len);
+ g_autofree SVQElement *svq_elem = NULL;
+ svq_elem = g_steal_pointer(&svq->ring_id_maps[i]);
+ if (svq_elem) {
+ virtqueue_detach_element(svq->vq, &svq_elem->elem,
+ svq_elem->elem.len);
}
}
next_avail_elem = g_steal_pointer(&svq->next_guest_avail_elem);
if (next_avail_elem) {
- virtqueue_detach_element(svq->vq, next_avail_elem,
- next_avail_elem->len);
+ virtqueue_detach_element(svq->vq, &next_avail_elem->elem,
+ next_avail_elem->elem.len);
}
}
@@ -735,7 +745,7 @@ VhostShadowVirtqueue *vhost_svq_new(uint16_t qsize, VhostIOVATree *iova_tree)
svq->vring.used = qemu_memalign(qemu_real_host_page_size, device_size);
memset(svq->vring.used, 0, device_size);
svq->iova_tree = iova_tree;
- svq->ring_id_maps = g_new0(VirtQueueElement *, qsize);
+ svq->ring_id_maps = g_new0(SVQElement *, qsize);
event_notifier_set_handler(&svq->hdev_call, vhost_svq_handle_call);
return g_steal_pointer(&svq);
This allows SVQ to add metadata to the different queue elements Signed-off-by: Eugenio PĂ©rez <eperezma@redhat.com> --- hw/virtio/vhost-shadow-virtqueue.c | 52 ++++++++++++++++++------------ 1 file changed, 31 insertions(+), 21 deletions(-)