From: Laurent Vivier <lvivier@redhat.com>
This new command lists all the instances of VirtIODevices with
their canonical QOM path and name.
Signed-off-by: Jonah Palmer <jonah.palmer@oracle.com>
---
hw/virtio/meson.build | 2 ++
hw/virtio/virtio-stub.c | 14 ++++++++++
hw/virtio/virtio.c | 27 ++++++++++++++++++
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, 115 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 0000000..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 867834d..76a63a0 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -13,6 +13,8 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
+#include "qapi/qapi-commands-virtio.h"
+#include "qapi/qapi-visit-virtio.h"
#include "cpu.h"
#include "trace.h"
#include "qemu/error-report.h"
@@ -29,6 +31,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
@@ -3700,6 +3705,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)
@@ -3714,6 +3720,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;
}
@@ -3887,6 +3894,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)
@@ -3897,6 +3906,24 @@ 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);
+ 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);
+ }
+
+ return list;
+}
+
static const TypeInfo virtio_device_info = {
.name = TYPE_VIRTIO_DEVICE,
.parent = TYPE_DEVICE,
diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
index 0a12bd5..3b4eb85 100644
--- a/include/hw/virtio/virtio.h
+++ b/include/hw/virtio/virtio.h
@@ -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 {
diff --git a/qapi/meson.build b/qapi/meson.build
index c0c49c1..e332f28 100644
--- a/qapi/meson.build
+++ b/qapi/meson.build
@@ -48,6 +48,7 @@ qapi_all_modules = [
'sockets',
'trace',
'transaction',
+ 'virtio',
'yank',
]
if have_system
diff --git a/qapi/qapi-schema.json b/qapi/qapi-schema.json
index 4912b97..1512ada 100644
--- a/qapi/qapi-schema.json
+++ b/qapi/qapi-schema.json
@@ -93,3 +93,4 @@
{ 'include': 'audio.json' }
{ 'include': 'acpi.json' }
{ 'include': 'pci.json' }
+{ 'include': 'virtio.json' }
diff --git a/qapi/virtio.json b/qapi/virtio.json
new file mode 100644
index 0000000..5372cde
--- /dev/null
+++ b/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' ] }
diff --git a/tests/qtest/qmp-cmd-test.c b/tests/qtest/qmp-cmd-test.c
index 7f103ea..fd00ee2 100644
--- a/tests/qtest/qmp-cmd-test.c
+++ b/tests/qtest/qmp-cmd-test.c
@@ -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 */
--
1.8.3.1
Jonah Palmer <jonah.palmer@oracle.com> writes:
> From: Laurent Vivier <lvivier@redhat.com>
>
> This new command lists all the instances of VirtIODevices with
> their canonical QOM path and name.
>
> Signed-off-by: Jonah Palmer <jonah.palmer@oracle.com>
> ---
> hw/virtio/meson.build | 2 ++
> hw/virtio/virtio-stub.c | 14 ++++++++++
> hw/virtio/virtio.c | 27 ++++++++++++++++++
> 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, 115 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 0000000..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 867834d..76a63a0 100644
> --- a/hw/virtio/virtio.c
> +++ b/hw/virtio/virtio.c
> @@ -13,6 +13,8 @@
>
> #include "qemu/osdep.h"
> #include "qapi/error.h"
> +#include "qapi/qapi-commands-virtio.h"
> +#include "qapi/qapi-visit-virtio.h"
> #include "cpu.h"
> #include "trace.h"
> #include "qemu/error-report.h"
> @@ -29,6 +31,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
> @@ -3700,6 +3705,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)
> @@ -3714,6 +3720,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;
> }
> @@ -3887,6 +3894,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);
> }
@virtio_list duplicates information that exists in the QOM composition
tree. It needs to stay in sync. You could search the composition tree
instead. I don't particularly care, but a virtio or QOM maintainer
might have a preference.
>
> bool virtio_device_ioeventfd_enabled(VirtIODevice *vdev)
> @@ -3897,6 +3906,24 @@ 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);
> + 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);
> + }
> +
> + return list;
> +}
> +
> static const TypeInfo virtio_device_info = {
> .name = TYPE_VIRTIO_DEVICE,
> .parent = TYPE_DEVICE,
> diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
> index 0a12bd5..3b4eb85 100644
> --- a/include/hw/virtio/virtio.h
> +++ b/include/hw/virtio/virtio.h
> @@ -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 {
> diff --git a/qapi/meson.build b/qapi/meson.build
> index c0c49c1..e332f28 100644
> --- a/qapi/meson.build
> +++ b/qapi/meson.build
> @@ -48,6 +48,7 @@ qapi_all_modules = [
> 'sockets',
> 'trace',
> 'transaction',
> + 'virtio',
> 'yank',
> ]
> if have_system
> diff --git a/qapi/qapi-schema.json b/qapi/qapi-schema.json
> index 4912b97..1512ada 100644
> --- a/qapi/qapi-schema.json
> +++ b/qapi/qapi-schema.json
> @@ -93,3 +93,4 @@
> { 'include': 'audio.json' }
> { 'include': 'acpi.json' }
> { 'include': 'pci.json' }
> +{ 'include': 'virtio.json' }
> diff --git a/qapi/virtio.json b/qapi/virtio.json
> new file mode 100644
> index 0000000..5372cde
> --- /dev/null
> +++ b/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
End with a period for consistency with existing docs.
> +#
> +# 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' ] }
This command is actually redundant: qom-list and qom-get suffice to
search /machine/ for virtio devices whose property realized is true.
To recognize virtio devices without relying on a naming convention, you
can use
{"execute": "qom-list-types",
"arguments": {"implements": "virtio-device"}}
Perhaps we want the command anyway, for convenience. That's for to the
virtio maintainer to decide, I guess. In case of "wanted":
QAPI schema
Reviewed-by: Markus Armbruster <armbru@redhat.com>
But please point out the redundancy in the commit message and/or a
comment.
[...]
© 2016 - 2026 Red Hat, Inc.