> 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
> ---
> hw/virtio/meson.build | 2 ++
> hw/virtio/virtio-stub.c| 14 ++
> hw/virtio/virtio.c | 44 ++
> include/hw/virtio/virtio.h | 1 +
> qapi/meson.build | 1 +
> qapi/qapi-schema.json | 1 +
> qapi/virtio.json | 68
> ++
> tests/qtest/qmp-cmd-test.c | 1 +
> 8 files changed, 132 insertions(+)
> create mode 100644 hw/virtio/virtio-stub.c
> create mode 100644 qapi/virtio.json
>
> diff --git a/hw/virtio/meson.build b/hw/virtio/meson.build
> index 521f7d6..d893f5f 100644
> --- a/hw/virtio/meson.build
> +++ b/hw/virtio/meson.build
> @@ -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'))
> diff --git a/hw/virtio/virtio-stub.c b/hw/virtio/virtio-stub.c
> new file mode 100644
> index 000..05a81ed
> --- /dev/null
> +++ b/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);
> +}
> diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
> index 7c1b1dd..e59f0d7 100644
> --- a/hw/virtio/virtio.c
> +++ b/hw/virtio/virtio.c
> @@ -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"
> @@ -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
> @@ -3687,6 +3696,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)
> @@ -3701,6 +3711,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;
> }
> @@ -3874,6 +3885,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)
> @@ -3884,6 +3897,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);
> +