Skip to content

Commit

Permalink
qmp: add QMP command x-query-virtio
Browse files Browse the repository at this point in the history
This new command lists all the instances of VirtIODevices with
their canonical QOM path and name.

[Jonah: @virtio_list duplicates information that already exists in
 the QOM composition tree. However, extracting necessary information
 from this tree seems to be a bit convoluted.

 Instead, we still create our own list of realized virtio devices
 but use @qmp_qom_get with the device's canonical QOM path to confirm
 that the device exists and is realized. If the device exists but
 is actually not realized, then we remove it from our list (for
 synchronicity to the QOM composition tree).

 Also, the QMP command @x-query-virtio is redundant as @qom-list
 and @qom-get are sufficient to search '/machine/' for realized
 virtio devices. However, @x-query-virtio is much more convenient
 in listing realized virtio devices.]

Signed-off-by: Jonah Palmer <jonah.palmer@oracle.com>
Message-Id: <1642678168-20447-4-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 Feb 5, 2022
1 parent 751e9f6 commit dc8aa2a
Show file tree
Hide file tree
Showing 8 changed files with 132 additions and 0 deletions.
2 changes: 2 additions & 0 deletions hw/virtio/meson.build
Expand Up @@ -6,8 +6,10 @@ softmmu_virtio_ss.add(when: 'CONFIG_VHOST', if_false: files('vhost-stub.c'))

softmmu_ss.add_all(when: 'CONFIG_VIRTIO', if_true: softmmu_virtio_ss)
softmmu_ss.add(when: 'CONFIG_VIRTIO', if_false: files('vhost-stub.c'))
softmmu_ss.add(when: 'CONFIG_VIRTIO', if_false: files('virtio-stub.c'))

softmmu_ss.add(when: 'CONFIG_ALL', if_true: files('vhost-stub.c'))
softmmu_ss.add(when: 'CONFIG_ALL', if_true: files('virtio-stub.c'))

virtio_ss = ss.source_set()
virtio_ss.add(files('virtio.c'))
Expand Down
14 changes: 14 additions & 0 deletions hw/virtio/virtio-stub.c
@@ -0,0 +1,14 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "qapi/qapi-commands-virtio.h"

static void *qmp_virtio_unsupported(Error **errp)
{
error_setg(errp, "Virtio is disabled");
return NULL;
}

VirtioInfoList *qmp_x_query_virtio(Error **errp)
{
return qmp_virtio_unsupported(errp);
}
44 changes: 44 additions & 0 deletions hw/virtio/virtio.c
Expand Up @@ -13,12 +13,18 @@

#include "qemu/osdep.h"
#include "qapi/error.h"
#include "qapi/qmp/qdict.h"
#include "qapi/qapi-commands-virtio.h"
#include "qapi/qapi-commands-qom.h"
#include "qapi/qapi-visit-virtio.h"
#include "qapi/qmp/qjson.h"
#include "cpu.h"
#include "trace.h"
#include "qemu/error-report.h"
#include "qemu/log.h"
#include "qemu/main-loop.h"
#include "qemu/module.h"
#include "qom/object_interfaces.h"
#include "hw/virtio/virtio.h"
#include "migration/qemu-file-types.h"
#include "qemu/atomic.h"
Expand All @@ -29,6 +35,9 @@
#include "sysemu/runstate.h"
#include "standard-headers/linux/virtio_ids.h"

/* QAPI list of realized VirtIODevices */
static QTAILQ_HEAD(, VirtIODevice) virtio_list;

/*
* The alignment to use between consumer and producer parts of vring.
* x86 pagesize again. This is the default, used by transports like PCI
Expand Down Expand Up @@ -3686,6 +3695,7 @@ static void virtio_device_realize(DeviceState *dev, Error **errp)
vdev->listener.commit = virtio_memory_listener_commit;
vdev->listener.name = "virtio";
memory_listener_register(&vdev->listener, vdev->dma_as);
QTAILQ_INSERT_TAIL(&virtio_list, vdev, next);
}

static void virtio_device_unrealize(DeviceState *dev)
Expand All @@ -3700,6 +3710,7 @@ static void virtio_device_unrealize(DeviceState *dev)
vdc->unrealize(dev);
}

QTAILQ_REMOVE(&virtio_list, vdev, next);
g_free(vdev->bus_name);
vdev->bus_name = NULL;
}
Expand Down Expand Up @@ -3873,6 +3884,8 @@ static void virtio_device_class_init(ObjectClass *klass, void *data)
vdc->stop_ioeventfd = virtio_device_stop_ioeventfd_impl;

vdc->legacy_features |= VIRTIO_LEGACY_FEATURES;

QTAILQ_INIT(&virtio_list);
}

bool virtio_device_ioeventfd_enabled(VirtIODevice *vdev)
Expand All @@ -3883,6 +3896,37 @@ bool virtio_device_ioeventfd_enabled(VirtIODevice *vdev)
return virtio_bus_ioeventfd_enabled(vbus);
}

VirtioInfoList *qmp_x_query_virtio(Error **errp)
{
VirtioInfoList *list = NULL;
VirtioInfoList *node;
VirtIODevice *vdev;

QTAILQ_FOREACH(vdev, &virtio_list, next) {
DeviceState *dev = DEVICE(vdev);
Error *err = NULL;
QObject *obj = qmp_qom_get(dev->canonical_path, "realized", &err);

if (err == NULL) {
GString *is_realized = qobject_to_json_pretty(obj, true);
/* virtio device is NOT realized, remove it from list */
if (!strncmp(is_realized->str, "false", 4)) {
QTAILQ_REMOVE(&virtio_list, vdev, next);
} else {
node = g_new0(VirtioInfoList, 1);
node->value = g_new(VirtioInfo, 1);
node->value->path = g_strdup(dev->canonical_path);
node->value->name = g_strdup(vdev->name);
QAPI_LIST_PREPEND(list, node->value);
}
g_string_free(is_realized, true);
}
qobject_unref(obj);
}

return list;
}

static const TypeInfo virtio_device_info = {
.name = TYPE_VIRTIO_DEVICE,
.parent = TYPE_DEVICE,
Expand Down
1 change: 1 addition & 0 deletions include/hw/virtio/virtio.h
Expand Up @@ -110,6 +110,7 @@ struct VirtIODevice
bool use_guest_notifier_mask;
AddressSpace *dma_as;
QLIST_HEAD(, VirtQueue) *vector_queues;
QTAILQ_ENTRY(VirtIODevice) next;
};

struct VirtioDeviceClass {
Expand Down
1 change: 1 addition & 0 deletions qapi/meson.build
Expand Up @@ -48,6 +48,7 @@ qapi_all_modules = [
'sockets',
'trace',
'transaction',
'virtio',
'yank',
]
if have_system
Expand Down
1 change: 1 addition & 0 deletions qapi/qapi-schema.json
Expand Up @@ -93,3 +93,4 @@
{ 'include': 'audio.json' }
{ 'include': 'acpi.json' }
{ 'include': 'pci.json' }
{ 'include': 'virtio.json' }
68 changes: 68 additions & 0 deletions qapi/virtio.json
@@ -0,0 +1,68 @@
# -*- Mode: Python -*-
# vim: filetype=python
#

##
# = Virtio devices
##

##
# @VirtioInfo:
#
# Basic information about a given VirtIODevice
#
# @path: The VirtIODevice's canonical QOM path
#
# @name: Name of the VirtIODevice
#
# Since: 7.0
#
##
{ 'struct': 'VirtioInfo',
'data': { 'path': 'str',
'name': 'str' } }

##
# @x-query-virtio:
#
# Returns a list of all realized VirtIODevices
#
# Features:
# @unstable: This command is meant for debugging.
#
# Returns: List of gathered VirtIODevices
#
# Since: 7.0
#
# Example:
#
# -> { "execute": "x-query-virtio" }
# <- { "return": [
# {
# "path": "/machine/peripheral-anon/device[4]/virtio-backend",
# "name": "virtio-input"
# },
# {
# "path": "/machine/peripheral/crypto0/virtio-backend",
# "name": "virtio-crypto"
# },
# {
# "path": "/machine/peripheral-anon/device[2]/virtio-backend",
# "name": "virtio-scsi"
# },
# {
# "path": "/machine/peripheral-anon/device[1]/virtio-backend",
# "name": "virtio-net"
# },
# {
# "path": "/machine/peripheral-anon/device[0]/virtio-backend",
# "name": "virtio-serial"
# }
# ]
# }
#
##

{ 'command': 'x-query-virtio',
'returns': [ 'VirtioInfo' ],
'features': [ 'unstable' ] }
1 change: 1 addition & 0 deletions tests/qtest/qmp-cmd-test.c
Expand Up @@ -103,6 +103,7 @@ static bool query_is_ignored(const char *cmd)
"query-gic-capabilities", /* arm */
/* Success depends on target-specific build configuration: */
"query-pci", /* CONFIG_PCI */
"x-query-virtio", /* CONFIG_VIRTIO */
/* Success depends on launching SEV guest */
"query-sev-launch-measure",
/* Success depends on Host or Hypervisor SEV support */
Expand Down

0 comments on commit dc8aa2a

Please sign in to comment.