Skip to content

Commit

Permalink
qmp: add QMP commands for virtio/vhost queue-status
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
vivier authored and mstsirkin committed Oct 9, 2022
1 parent f3034ad commit 07536dd
Show file tree
Hide file tree
Showing 3 changed files with 373 additions and 0 deletions.
14 changes: 14 additions & 0 deletions hw/virtio/virtio-stub.c
Expand Up @@ -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);
}
103 changes: 103 additions & 0 deletions hw/virtio/virtio.c
Expand Up @@ -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,
Expand Down
256 changes: 256 additions & 0 deletions qapi/virtio.json
Expand Up @@ -499,3 +499,259 @@
'data': { 'transports': [ 'str' ],
'*dev-features': [ 'str' ],
'*unknown-dev-features': 'uint64' } }

##
# @VirtQueueStatus:
#
# Information of a VirtIODevice VirtQueue, including most members of
# the VirtQueue data structure.
#
# @name: Name of the VirtIODevice that uses this VirtQueue
#
# @queue-index: VirtQueue queue_index
#
# @inuse: VirtQueue inuse
#
# @vring-num: VirtQueue vring.num
#
# @vring-num-default: VirtQueue vring.num_default
#
# @vring-align: VirtQueue vring.align
#
# @vring-desc: VirtQueue vring.desc (descriptor area)
#
# @vring-avail: VirtQueue vring.avail (driver area)
#
# @vring-used: VirtQueue vring.used (device area)
#
# @last-avail-idx: VirtQueue last_avail_idx or return of vhost_dev
# vhost_get_vring_base (if vhost active)
#
# @shadow-avail-idx: VirtQueue shadow_avail_idx
#
# @used-idx: VirtQueue used_idx
#
# @signalled-used: VirtQueue signalled_used
#
# @signalled-used-valid: VirtQueue signalled_used_valid flag
#
# Since: 7.1
#
##

{ 'struct': 'VirtQueueStatus',
'data': { 'name': 'str',
'queue-index': 'uint16',
'inuse': 'uint32',
'vring-num': 'uint32',
'vring-num-default': 'uint32',
'vring-align': 'uint32',
'vring-desc': 'uint64',
'vring-avail': 'uint64',
'vring-used': 'uint64',
'*last-avail-idx': 'uint16',
'*shadow-avail-idx': 'uint16',
'used-idx': 'uint16',
'signalled-used': 'uint16',
'signalled-used-valid': 'bool' } }

##
# @x-query-virtio-queue-status:
#
# Return the status of a given VirtIODevice's VirtQueue
#
# @path: VirtIODevice canonical QOM path
#
# @queue: VirtQueue index to examine
#
# Features:
# @unstable: This command is meant for debugging.
#
# Returns: VirtQueueStatus of the VirtQueue
#
# Notes: last_avail_idx will not be displayed in the case where
# the selected VirtIODevice has a running vhost device and
# the VirtIODevice VirtQueue index (queue) does not exist for
# the corresponding vhost device vhost_virtqueue. Also,
# shadow_avail_idx will not be displayed in the case where
# the selected VirtIODevice has a running vhost device.
#
# Since: 7.1
#
# Examples:
#
# 1. Get VirtQueueStatus for virtio-vsock (vhost-vsock running)
#
# -> { "execute": "x-query-virtio-queue-status",
# "arguments": { "path": "/machine/peripheral/vsock0/virtio-backend",
# "queue": 1 }
# }
# <- { "return": {
# "signalled-used": 0,
# "inuse": 0,
# "name": "vhost-vsock",
# "vring-align": 4096,
# "vring-desc": 5217370112,
# "signalled-used-valid": false,
# "vring-num-default": 128,
# "vring-avail": 5217372160,
# "queue-index": 1,
# "last-avail-idx": 0,
# "vring-used": 5217372480,
# "used-idx": 0,
# "vring-num": 128
# }
# }
#
# 2. Get VirtQueueStatus for virtio-serial (no vhost)
#
# -> { "execute": "x-query-virtio-queue-status",
# "arguments": { "path": "/machine/peripheral-anon/device[0]/virtio-backend",
# "queue": 20 }
# }
# <- { "return": {
# "signalled-used": 0,
# "inuse": 0,
# "name": "virtio-serial",
# "vring-align": 4096,
# "vring-desc": 5182074880,
# "signalled-used-valid": false,
# "vring-num-default": 128,
# "vring-avail": 5182076928,
# "queue-index": 20,
# "last-avail-idx": 0,
# "vring-used": 5182077248,
# "used-idx": 0,
# "shadow-avail-idx": 0,
# "vring-num": 128
# }
# }
#
##

{ 'command': 'x-query-virtio-queue-status',
'data': { 'path': 'str', 'queue': 'uint16' },
'returns': 'VirtQueueStatus',
'features': [ 'unstable' ] }

##
# @VirtVhostQueueStatus:
#
# Information of a vhost device's vhost_virtqueue, including most
# members of the vhost_dev vhost_virtqueue data structure.
#
# @name: Name of the VirtIODevice that uses this vhost_virtqueue
#
# @kick: vhost_virtqueue kick
#
# @call: vhost_virtqueue call
#
# @desc: vhost_virtqueue desc
#
# @avail: vhost_virtqueue avail
#
# @used: vhost_virtqueue used
#
# @num: vhost_virtqueue num
#
# @desc-phys: vhost_virtqueue desc_phys (descriptor area phys. addr.)
#
# @desc-size: vhost_virtqueue desc_size
#
# @avail-phys: vhost_virtqueue avail_phys (driver area phys. addr.)
#
# @avail-size: vhost_virtqueue avail_size
#
# @used-phys: vhost_virtqueue used_phys (device area phys. addr.)
#
# @used-size: vhost_virtqueue used_size
#
# Since: 7.1
#
##

{ 'struct': 'VirtVhostQueueStatus',
'data': { 'name': 'str',
'kick': 'int',
'call': 'int',
'desc': 'uint64',
'avail': 'uint64',
'used': 'uint64',
'num': 'int',
'desc-phys': 'uint64',
'desc-size': 'uint32',
'avail-phys': 'uint64',
'avail-size': 'uint32',
'used-phys': 'uint64',
'used-size': 'uint32' } }

##
# @x-query-virtio-vhost-queue-status:
#
# Return information of a given vhost device's vhost_virtqueue
#
# @path: VirtIODevice canonical QOM path
#
# @queue: vhost_virtqueue index to examine
#
# Features:
# @unstable: This command is meant for debugging.
#
# Returns: VirtVhostQueueStatus of the vhost_virtqueue
#
# Since: 7.1
#
# Examples:
#
# 1. Get vhost_virtqueue status for vhost-crypto
#
# -> { "execute": "x-query-virtio-vhost-queue-status",
# "arguments": { "path": "/machine/peripheral/crypto0/virtio-backend",
# "queue": 0 }
# }
# <- { "return": {
# "avail-phys": 5216124928,
# "name": "virtio-crypto",
# "used-phys": 5216127040,
# "avail-size": 2054,
# "desc-size": 16384,
# "used-size": 8198,
# "desc": 140141447430144,
# "num": 1024,
# "call": 0,
# "avail": 140141447446528,
# "desc-phys": 5216108544,
# "used": 140141447448640,
# "kick": 0
# }
# }
#
# 2. Get vhost_virtqueue status for vhost-vsock
#
# -> { "execute": "x-query-virtio-vhost-queue-status",
# "arguments": { "path": "/machine/peripheral/vsock0/virtio-backend",
# "queue": 0 }
# }
# <- { "return": {
# "avail-phys": 5182261248,
# "name": "vhost-vsock",
# "used-phys": 5182261568,
# "avail-size": 262,
# "desc-size": 2048,
# "used-size": 1030,
# "desc": 140141413580800,
# "num": 128,
# "call": 0,
# "avail": 140141413582848,
# "desc-phys": 5182259200,
# "used": 140141413583168,
# "kick": 0
# }
# }
#
##

{ 'command': 'x-query-virtio-vhost-queue-status',
'data': { 'path': 'str', 'queue': 'uint16' },
'returns': 'VirtVhostQueueStatus',
'features': [ 'unstable' ] }

0 comments on commit 07536dd

Please sign in to comment.