aboutsummaryrefslogtreecommitdiff
path: root/hw/virtio
diff options
context:
space:
mode:
authorLaurent Vivier <lvivier@redhat.com>2022-08-11 08:24:42 -0400
committerMichael S. Tsirkin <mst@redhat.com>2022-10-09 16:38:45 -0400
commit07536ddda73a07bba6da8087fed5dd5a02320b11 (patch)
tree7d3b3dae7e4ea9bb8a7dcf50d2cb96281867fa84 /hw/virtio
parentf3034ad71fcd0a6a58bc37830f182b307f089159 (diff)
qmp: add QMP commands for virtio/vhost queue-status
These new commands show the internal status of a VirtIODevice's VirtQueue and a vhost device's vhost_virtqueue (if active). Signed-off-by: Laurent Vivier <lvivier@redhat.com> Signed-off-by: Jonah Palmer <jonah.palmer@oracle.com> Message-Id: <1660220684-24909-5-git-send-email-jonah.palmer@oracle.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Diffstat (limited to 'hw/virtio')
-rw-r--r--hw/virtio/virtio-stub.c14
-rw-r--r--hw/virtio/virtio.c103
2 files changed, 117 insertions, 0 deletions
diff --git a/hw/virtio/virtio-stub.c b/hw/virtio/virtio-stub.c
index 0b432e8de7..13e5f93652 100644
--- a/hw/virtio/virtio-stub.c
+++ b/hw/virtio/virtio-stub.c
@@ -17,3 +17,17 @@ VirtioStatus *qmp_x_query_virtio_status(const char *path, Error **errp)
{
return qmp_virtio_unsupported(errp);
}
+
+VirtVhostQueueStatus *qmp_x_query_virtio_vhost_queue_status(const char *path,
+ uint16_t queue,
+ Error **errp)
+{
+ return qmp_virtio_unsupported(errp);
+}
+
+VirtQueueStatus *qmp_x_query_virtio_queue_status(const char *path,
+ uint16_t queue,
+ Error **errp)
+{
+ return qmp_virtio_unsupported(errp);
+}
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index 6c530567b0..da869e7b51 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -4679,6 +4679,109 @@ VirtioStatus *qmp_x_query_virtio_status(const char *path, Error **errp)
return status;
}
+VirtVhostQueueStatus *qmp_x_query_virtio_vhost_queue_status(const char *path,
+ uint16_t queue,
+ Error **errp)
+{
+ VirtIODevice *vdev;
+ VirtVhostQueueStatus *status;
+
+ vdev = virtio_device_find(path);
+ if (vdev == NULL) {
+ error_setg(errp, "Path %s is not a VirtIODevice", path);
+ return NULL;
+ }
+
+ if (!vdev->vhost_started) {
+ error_setg(errp, "Error: vhost device has not started yet");
+ return NULL;
+ }
+
+ VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev);
+ struct vhost_dev *hdev = vdc->get_vhost(vdev);
+
+ if (queue < hdev->vq_index || queue >= hdev->vq_index + hdev->nvqs) {
+ error_setg(errp, "Invalid vhost virtqueue number %d", queue);
+ return NULL;
+ }
+
+ status = g_new0(VirtVhostQueueStatus, 1);
+ status->name = g_strdup(vdev->name);
+ status->kick = hdev->vqs[queue].kick;
+ status->call = hdev->vqs[queue].call;
+ status->desc = (uintptr_t)hdev->vqs[queue].desc;
+ status->avail = (uintptr_t)hdev->vqs[queue].avail;
+ status->used = (uintptr_t)hdev->vqs[queue].used;
+ status->num = hdev->vqs[queue].num;
+ status->desc_phys = hdev->vqs[queue].desc_phys;
+ status->desc_size = hdev->vqs[queue].desc_size;
+ status->avail_phys = hdev->vqs[queue].avail_phys;
+ status->avail_size = hdev->vqs[queue].avail_size;
+ status->used_phys = hdev->vqs[queue].used_phys;
+ status->used_size = hdev->vqs[queue].used_size;
+
+ return status;
+}
+
+VirtQueueStatus *qmp_x_query_virtio_queue_status(const char *path,
+ uint16_t queue,
+ Error **errp)
+{
+ VirtIODevice *vdev;
+ VirtQueueStatus *status;
+
+ vdev = virtio_device_find(path);
+ if (vdev == NULL) {
+ error_setg(errp, "Path %s is not a VirtIODevice", path);
+ return NULL;
+ }
+
+ if (queue >= VIRTIO_QUEUE_MAX || !virtio_queue_get_num(vdev, queue)) {
+ error_setg(errp, "Invalid virtqueue number %d", queue);
+ return NULL;
+ }
+
+ status = g_new0(VirtQueueStatus, 1);
+ status->name = g_strdup(vdev->name);
+ status->queue_index = vdev->vq[queue].queue_index;
+ status->inuse = vdev->vq[queue].inuse;
+ status->vring_num = vdev->vq[queue].vring.num;
+ status->vring_num_default = vdev->vq[queue].vring.num_default;
+ status->vring_align = vdev->vq[queue].vring.align;
+ status->vring_desc = vdev->vq[queue].vring.desc;
+ status->vring_avail = vdev->vq[queue].vring.avail;
+ status->vring_used = vdev->vq[queue].vring.used;
+ status->used_idx = vdev->vq[queue].used_idx;
+ status->signalled_used = vdev->vq[queue].signalled_used;
+ status->signalled_used_valid = vdev->vq[queue].signalled_used_valid;
+
+ if (vdev->vhost_started) {
+ VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev);
+ struct vhost_dev *hdev = vdc->get_vhost(vdev);
+
+ /* check if vq index exists for vhost as well */
+ if (queue >= hdev->vq_index && queue < hdev->vq_index + hdev->nvqs) {
+ status->has_last_avail_idx = true;
+
+ int vhost_vq_index =
+ hdev->vhost_ops->vhost_get_vq_index(hdev, queue);
+ struct vhost_vring_state state = {
+ .index = vhost_vq_index,
+ };
+
+ status->last_avail_idx =
+ hdev->vhost_ops->vhost_get_vring_base(hdev, &state);
+ }
+ } else {
+ status->has_shadow_avail_idx = true;
+ status->has_last_avail_idx = true;
+ status->last_avail_idx = vdev->vq[queue].last_avail_idx;
+ status->shadow_avail_idx = vdev->vq[queue].shadow_avail_idx;
+ }
+
+ return status;
+}
+
static const TypeInfo virtio_device_info = {
.name = TYPE_VIRTIO_DEVICE,
.parent = TYPE_DEVICE,