This patch implements HMP version of the virtio QMP commands
Signed-off-by: Laurent Vivier <lvivier@redhat.com>
---
Makefile | 2 +-
Makefile.target | 7 +-
docs/system/monitor.rst | 2 +
hmp-commands-virtio.hx | 148 ++++++++++++++++++++++++++++++++++++++++
hmp-commands.hx | 10 +++
hw/virtio/virtio.c | 115 +++++++++++++++++++++++++++++++
include/monitor/hmp.h | 4 ++
monitor/misc.c | 17 +++++
8 files changed, 302 insertions(+), 3 deletions(-)
create mode 100644 hmp-commands-virtio.hx
diff --git a/Makefile b/Makefile
index 84ef88160006..5f70ea16a566 100644
--- a/Makefile
+++ b/Makefile
@@ -1100,7 +1100,7 @@ $(MANUAL_BUILDDIR)/interop/index.html: $(call manual-deps,interop)
$(MANUAL_BUILDDIR)/specs/index.html: $(call manual-deps,specs)
$(call build-manual,specs,html)
-$(MANUAL_BUILDDIR)/system/index.html: $(call manual-deps,system) $(SRC_PATH)/hmp-commands.hx $(SRC_PATH)/hmp-commands-info.hx $(SRC_PATH)/qemu-options.hx
+$(MANUAL_BUILDDIR)/system/index.html: $(call manual-deps,system) $(SRC_PATH)/hmp-commands.hx $(SRC_PATH)/hmp-commands-info.hx $(SRC_PATH)/qemu-options.hx $(SRC_PATH)/hmp-commands-virtio.hx
$(call build-manual,system,html)
$(MANUAL_BUILDDIR)/tools/index.html: $(call manual-deps,tools) $(SRC_PATH)/qemu-img-cmds.hx $(SRC_PATH)/docs/qemu-option-trace.rst.inc
diff --git a/Makefile.target b/Makefile.target
index 8ed1eba95b9c..66d3ff9bc350 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -171,7 +171,7 @@ else
obj-y += hw/$(TARGET_BASE_ARCH)/
endif
-generated-files-y += hmp-commands.h hmp-commands-info.h
+generated-files-y += hmp-commands.h hmp-commands-info.h hmp-commands-virtio.h
generated-files-y += config-devices.h
endif # CONFIG_SOFTMMU
@@ -220,10 +220,13 @@ hmp-commands.h: $(SRC_PATH)/hmp-commands.hx $(SRC_PATH)/scripts/hxtool
hmp-commands-info.h: $(SRC_PATH)/hmp-commands-info.hx $(SRC_PATH)/scripts/hxtool
$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@,"GEN","$(TARGET_DIR)$@")
+hmp-commands-virtio.h: $(SRC_PATH)/hmp-commands-virtio.hx $(SRC_PATH)/scripts/hxtool
+ $(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@,"GEN","$(TARGET_DIR)$@")
+
clean: clean-target
rm -f *.a *~ $(PROGS)
rm -f $(shell find . -name '*.[od]')
- rm -f hmp-commands.h gdbstub-xml.c
+ rm -f hmp-commands.h hmp-commands-virtio.h gdbstub-xml.c
rm -f trace/generated-helpers.c trace/generated-helpers.c-timestamp
ifdef CONFIG_TRACE_SYSTEMTAP
rm -f *.stp
diff --git a/docs/system/monitor.rst b/docs/system/monitor.rst
index 0bcd5da21644..985c3f51ffe7 100644
--- a/docs/system/monitor.rst
+++ b/docs/system/monitor.rst
@@ -21,6 +21,8 @@ The following commands are available:
.. hxtool-doc:: hmp-commands.hx
+.. hxtool-doc:: hmp-commands-virtio.hx
+
.. hxtool-doc:: hmp-commands-info.hx
Integer expressions
diff --git a/hmp-commands-virtio.hx b/hmp-commands-virtio.hx
new file mode 100644
index 000000000000..a8d49f0b2b46
--- /dev/null
+++ b/hmp-commands-virtio.hx
@@ -0,0 +1,148 @@
+HXCOMM Use DEFHEADING() to define headings in both help text and rST.
+HXCOMM Text between SRST and ERST is copied to the rST version and
+HXCOMM discarded from C version.
+HXCOMM DEF(command, args, callback, arg_string, help) is used to construct
+HXCOMM monitor info commands
+HXCOMM HXCOMM can be used for comments, discarded from both rST and C.
+HXCOMM
+HXCOMM In this file, generally SRST fragments should have two extra
+HXCOMM spaces of indent, so that the documentation list item for "virtio cmd"
+HXCOMM appears inside the documentation list item for the top level
+HXCOMM "virtio" documentation entry. The exception is the first SRST
+HXCOMM fragment that defines that top level entry.
+
+SRST
+``virtio`` *subcommand*
+ Show various information about virtio.
+
+ERST
+
+ {
+ .name = "query",
+ .args_type = "",
+ .params = "",
+ .help = "List all available virtio devices",
+ .cmd = hmp_virtio_query,
+ .flags = "p",
+ },
+
+SRST
+ ``virtio query``
+ List all available virtio devices
+
+ Example:
+
+ List all available virtio devices in the machine::
+
+ (qemu) virtio query
+ /machine/peripheral-anon/device[3]/virtio-backend [virtio-net]
+ /machine/peripheral-anon/device[1]/virtio-backend [virtio-serial]
+ /machine/peripheral-anon/device[0]/virtio-backend [virtio-blk]
+
+ERST
+
+ {
+ .name = "status",
+ .args_type = "path:s",
+ .params = "path",
+ .help = "Display status of a given virtio device",
+ .cmd = hmp_virtio_status,
+ .flags = "p",
+ },
+
+SRST
+ ``virtio status`` *path*
+ Display status of a given virtio device
+
+ Example:
+
+ Dump the status of the first virtio device::
+
+ (qemu) virtio status /machine/peripheral-anon/device[3]/virtio-backend
+ /machine/peripheral-anon/device[3]/virtio-backend:
+ Device Id: 1
+ Guest features: 0x0000000130afffa7
+ Host features: 0x0000000179bfffe7
+ Backend features: 0x0000000000000000
+ Endianness: little
+ VirtQueues: 3
+
+ERST
+
+ {
+ .name = "queue-status",
+ .args_type = "path:s,queue:i",
+ .params = "path queue",
+ .help = "Display status of a given virtio queue",
+ .cmd = hmp_virtio_queue_status,
+ .flags = "p",
+ },
+
+SRST
+ ``virtio queue-status`` *path* *queue*
+ Display status of a given virtio queue
+
+ Example:
+
+ Dump the status of the first queue of the first virtio device::
+
+ (qemu) virtio queue-status /machine/peripheral-anon/device[3]/virtio-backend 0
+ /machine/peripheral-anon/device[3]/virtio-backend:
+ index: 0
+ inuse: 0
+ last_avail_idx: 61
+ shadow_avail_idx: 292
+ signalled_used: 61
+ signalled_used_valid: 1
+ VRing:
+ num: 256
+ num_default: 256
+ align: 4096
+ desc: 0x000000006c352000
+ avail: 0x000000006c353000
+ used: 0x000000006c353240
+
+ERST
+
+ {
+ .name = "queue-element",
+ .args_type = "path:s,queue:i,index:i?",
+ .params = "path queue [index]",
+ .help = "Display element of a given virtio queue",
+ .cmd = hmp_virtio_queue_element,
+ .flags = "p",
+ },
+
+SRST
+ ``virtio queue-element`` *path* *queue* [*index*]
+ Display element of a given virtio queue
+
+ Example:
+
+ Dump the information of the head element of the first queue of
+ the first virtio device::
+
+ (qemu) virtio queue-element/machine/peripheral-anon/device[3]/virtio-backend 0
+ index: 67
+ ndescs: 1
+ descs: addr 0x6fe69800 len 1536 (write-only)
+
+ (qemu) xp/128bx 0x6fe69800
+ 000000006fe69800: 0x02 0x00 0x00 0x00 0x00 0x00 0x00 0x00
+ 000000006fe69808: 0x00 0x00 0x01 0x00 0x52 0x54 0x00 0x12
+ 000000006fe69810: 0x34 0x56 0x52 0x54 0x00 0x09 0x51 0xde
+ 000000006fe69818: 0x08 0x00 0x45 0x00 0x00 0x4c 0x8f 0x32
+
+ device[3] is a virtio-net device and we can see in the element buffer the
+ MAC address of the card::
+
+ [root@localhost ~]# ip link show ens4
+ 2: ens4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP m0
+ link/ether 52:54:00:12:34:56 brd ff:ff:ff:ff:ff:ff
+
+ and the MAC address of the gateway::
+
+ [root@localhost ~]# arp -a
+ _gateway (192.168.122.1) at 52:54:00:09:51:de [ether] on ens4
+
+ERST
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 7f0f3974ad90..14568b406dbc 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1804,6 +1804,16 @@ SRST
Set QOM property *property* of object at location *path* to value *value*
ERST
+ {
+ .name = "virtio",
+ .args_type = "name:S?",
+ .params = "[cmd]",
+ .help = "show various information about virtio",
+ .cmd = hmp_virtio_help,
+ .sub_table = hmp_virtio_cmds,
+ .flags = "p",
+ },
+
{
.name = "info",
.args_type = "item:s?",
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index 28848b9e64cf..d52d41169fb4 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -29,6 +29,9 @@
#include "hw/virtio/virtio-access.h"
#include "sysemu/dma.h"
#include "sysemu/runstate.h"
+#include "monitor/hmp.h"
+#include "monitor/monitor.h"
+#include "qapi/qmp/qdict.h"
static QTAILQ_HEAD(, VirtIODevice) virtio_list;
@@ -3839,6 +3842,29 @@ VirtioInfoList *qmp_query_virtio(Error **errp)
return list;
}
+void hmp_virtio_query(Monitor *mon, const QDict *qdict)
+{
+ Error *err = NULL;
+ VirtioInfoList *l = qmp_query_virtio(&err);
+
+ if (err != NULL) {
+ hmp_handle_error(mon, err);
+ return;
+ }
+
+ if (l == NULL) {
+ monitor_printf(mon, "No VirtIO devices\n");
+ return;
+ }
+
+ while (l) {
+ monitor_printf(mon, "%s [%s]\n", l->value->path, l->value->type);
+ l = l->next;
+ }
+
+ qapi_free_VirtioInfoList(l);
+}
+
static VirtIODevice *virtio_device_find(const char *path)
{
VirtIODevice *vdev;
@@ -3890,6 +3916,36 @@ VirtQueueStatus *qmp_virtio_queue_status(const char *path, uint16_t queue,
return status;
}
+void hmp_virtio_queue_status(Monitor *mon, const QDict *qdict)
+{
+ Error *err = NULL;
+ const char *path = qdict_get_try_str(qdict, "path");
+ int queue = qdict_get_int(qdict, "queue");
+ VirtQueueStatus *s = qmp_virtio_queue_status(path, queue, &err);
+
+ if (err != NULL) {
+ hmp_handle_error(mon, err);
+ return;
+ }
+ monitor_printf(mon, "%s:\n", path);
+ monitor_printf(mon, " index: %d\n", s->queue_index);
+ monitor_printf(mon, " inuse: %d\n", s->inuse);
+ monitor_printf(mon, " last_avail_idx: %d\n", s->last_avail_idx);
+ monitor_printf(mon, " shadow_avail_idx: %d\n", s->shadow_avail_idx);
+ monitor_printf(mon, " signalled_used: %d\n", s->signalled_used);
+ monitor_printf(mon, " signalled_used_valid: %d\n",
+ s->signalled_used_valid);
+ monitor_printf(mon, " VRing:\n");
+ monitor_printf(mon, " num: %"PRId64"\n", s->vring_num);
+ monitor_printf(mon, " num_default: %"PRId64"\n", s->vring_num_default);
+ monitor_printf(mon, " align: %"PRId64"\n", s->vring_align);
+ monitor_printf(mon, " desc: 0x%016"PRIx64"\n", s->vring_desc);
+ monitor_printf(mon, " avail: 0x%016"PRIx64"\n", s->vring_avail);
+ monitor_printf(mon, " used: 0x%016"PRIx64"\n", s->vring_used);
+
+ qapi_free_VirtQueueStatus(s);
+}
+
VirtioStatus *qmp_virtio_status(const char* path, Error **errp)
{
VirtIODevice *vdev;
@@ -3925,6 +3981,31 @@ VirtioStatus *qmp_virtio_status(const char* path, Error **errp)
return status;
}
+void hmp_virtio_status(Monitor *mon, const QDict *qdict)
+{
+ Error *err = NULL;
+ const char *path = qdict_get_try_str(qdict, "path");
+ VirtioStatus *s = qmp_virtio_status(path, &err);
+
+ if (err != NULL) {
+ hmp_handle_error(mon, err);
+ return;
+ }
+
+ monitor_printf(mon, "%s:\n", path);
+ monitor_printf(mon, " Device Id: %"PRId64"\n", s->device_id);
+ monitor_printf(mon, " Guest features: 0x%016"PRIx64"\n",
+ s->guest_features);
+ monitor_printf(mon, " Host features: 0x%016"PRIx64"\n",
+ s->host_features);
+ monitor_printf(mon, " Backend features: 0x%016"PRIx64"\n",
+ s->backend_features);
+ monitor_printf(mon, " Endianness: %s\n", s->device_endian);
+ monitor_printf(mon, " VirtQueues: %d\n", s->num_vqs);
+
+ qapi_free_VirtioStatus(s);
+}
+
VirtioQueueElement *qmp_virtio_queue_element(const char* path, uint16_t queue,
bool has_index, uint16_t index,
Error **errp)
@@ -4010,6 +4091,40 @@ VirtioQueueElement *qmp_virtio_queue_element(const char* path, uint16_t queue,
return element;
}
+void hmp_virtio_queue_element(Monitor *mon, const QDict *qdict)
+{
+ Error *err = NULL;
+ const char *path = qdict_get_try_str(qdict, "path");
+ int queue = qdict_get_int(qdict, "queue");
+ int index = qdict_get_try_int(qdict, "index", -1);
+ VirtioQueueElement *element;
+ VirtioRingDescList *list;
+
+ element = qmp_virtio_queue_element(path, queue, index != -1, index, &err);
+ if (err != NULL) {
+ hmp_handle_error(mon, err);
+ return;
+ }
+
+ monitor_printf(mon, "index: %d\n", element->index);
+ monitor_printf(mon, "ndescs: %d\n", element->ndescs);
+ monitor_printf(mon, "descs: ");
+
+ list = element->descs;
+ while (list) {
+ monitor_printf(mon, "addr 0x%"PRIx64" len %d %s", list->value->addr,
+ list->value->len, list->value->flags &
+ VRING_DESC_F_WRITE ? "(write-only)" : "(read-only)");
+ list = list->next;
+ if (list) {
+ monitor_printf(mon, ", ");
+ }
+ }
+ monitor_printf(mon, "\n");
+
+ qapi_free_VirtioQueueElement(element);
+}
+
static const TypeInfo virtio_device_info = {
.name = TYPE_VIRTIO_DEVICE,
.parent = TYPE_DEVICE,
diff --git a/include/monitor/hmp.h b/include/monitor/hmp.h
index e33ca5a911a5..9f1c118dde31 100644
--- a/include/monitor/hmp.h
+++ b/include/monitor/hmp.h
@@ -98,6 +98,10 @@ void hmp_info_memory_devices(Monitor *mon, const QDict *qdict);
void hmp_qom_list(Monitor *mon, const QDict *qdict);
void hmp_qom_set(Monitor *mon, const QDict *qdict);
void hmp_info_qom_tree(Monitor *mon, const QDict *dict);
+void hmp_virtio_query(Monitor *mon, const QDict *qdict);
+void hmp_virtio_status(Monitor *mon, const QDict *qdict);
+void hmp_virtio_queue_status(Monitor *mon, const QDict *qdict);
+void hmp_virtio_queue_element(Monitor *mon, const QDict *qdict);
void object_add_completion(ReadLineState *rs, int nb_args, const char *str);
void object_del_completion(ReadLineState *rs, int nb_args, const char *str);
void device_add_completion(ReadLineState *rs, int nb_args, const char *str);
diff --git a/monitor/misc.c b/monitor/misc.c
index 6c45fa490ff5..5eacfa7079fc 100644
--- a/monitor/misc.c
+++ b/monitor/misc.c
@@ -23,6 +23,7 @@
*/
#include "qemu/osdep.h"
+#include "config-devices.h"
#include "monitor-internal.h"
#include "cpu.h"
#include "monitor/qdev.h"
@@ -232,6 +233,15 @@ static void hmp_info_help(Monitor *mon, const QDict *qdict)
help_cmd(mon, "info");
}
+static void hmp_virtio_help(Monitor *mon, const QDict *qdict)
+{
+#if defined(CONFIG_VIRTIO)
+ help_cmd(mon, "virtio");
+#else
+ monitor_printf(mon, "Virtio is disabled\n");
+#endif
+}
+
static void monitor_init_qmp_commands(void)
{
/*
@@ -1683,6 +1693,13 @@ static HMPCommand hmp_info_cmds[] = {
{ NULL, NULL, },
};
+static HMPCommand hmp_virtio_cmds[] = {
+#if defined(CONFIG_VIRTIO)
+#include "hmp-commands-virtio.h"
+#endif
+ { NULL, NULL, },
+};
+
/* hmp_cmds and hmp_info_cmds would be sorted at runtime */
HMPCommand hmp_cmds[] = {
#include "hmp-commands.h"
--
2.25.1
* Laurent Vivier (lvivier@redhat.com) wrote:
> This patch implements HMP version of the virtio QMP commands
>
> Signed-off-by: Laurent Vivier <lvivier@redhat.com>
> ---
> Makefile | 2 +-
> Makefile.target | 7 +-
> docs/system/monitor.rst | 2 +
> hmp-commands-virtio.hx | 148 ++++++++++++++++++++++++++++++++++++++++
> hmp-commands.hx | 10 +++
> hw/virtio/virtio.c | 115 +++++++++++++++++++++++++++++++
> include/monitor/hmp.h | 4 ++
> monitor/misc.c | 17 +++++
> 8 files changed, 302 insertions(+), 3 deletions(-)
> create mode 100644 hmp-commands-virtio.hx
>
> diff --git a/Makefile b/Makefile
> index 84ef88160006..5f70ea16a566 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -1100,7 +1100,7 @@ $(MANUAL_BUILDDIR)/interop/index.html: $(call manual-deps,interop)
> $(MANUAL_BUILDDIR)/specs/index.html: $(call manual-deps,specs)
> $(call build-manual,specs,html)
>
> -$(MANUAL_BUILDDIR)/system/index.html: $(call manual-deps,system) $(SRC_PATH)/hmp-commands.hx $(SRC_PATH)/hmp-commands-info.hx $(SRC_PATH)/qemu-options.hx
> +$(MANUAL_BUILDDIR)/system/index.html: $(call manual-deps,system) $(SRC_PATH)/hmp-commands.hx $(SRC_PATH)/hmp-commands-info.hx $(SRC_PATH)/qemu-options.hx $(SRC_PATH)/hmp-commands-virtio.hx
> $(call build-manual,system,html)
>
> $(MANUAL_BUILDDIR)/tools/index.html: $(call manual-deps,tools) $(SRC_PATH)/qemu-img-cmds.hx $(SRC_PATH)/docs/qemu-option-trace.rst.inc
> diff --git a/Makefile.target b/Makefile.target
> index 8ed1eba95b9c..66d3ff9bc350 100644
> --- a/Makefile.target
> +++ b/Makefile.target
> @@ -171,7 +171,7 @@ else
> obj-y += hw/$(TARGET_BASE_ARCH)/
> endif
>
> -generated-files-y += hmp-commands.h hmp-commands-info.h
> +generated-files-y += hmp-commands.h hmp-commands-info.h hmp-commands-virtio.h
> generated-files-y += config-devices.h
>
> endif # CONFIG_SOFTMMU
> @@ -220,10 +220,13 @@ hmp-commands.h: $(SRC_PATH)/hmp-commands.hx $(SRC_PATH)/scripts/hxtool
> hmp-commands-info.h: $(SRC_PATH)/hmp-commands-info.hx $(SRC_PATH)/scripts/hxtool
> $(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@,"GEN","$(TARGET_DIR)$@")
>
> +hmp-commands-virtio.h: $(SRC_PATH)/hmp-commands-virtio.hx $(SRC_PATH)/scripts/hxtool
> + $(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@,"GEN","$(TARGET_DIR)$@")
> +
(It would be great if these files moved into monitor at some point)
> clean: clean-target
> rm -f *.a *~ $(PROGS)
> rm -f $(shell find . -name '*.[od]')
> - rm -f hmp-commands.h gdbstub-xml.c
> + rm -f hmp-commands.h hmp-commands-virtio.h gdbstub-xml.c
> rm -f trace/generated-helpers.c trace/generated-helpers.c-timestamp
> ifdef CONFIG_TRACE_SYSTEMTAP
> rm -f *.stp
> diff --git a/docs/system/monitor.rst b/docs/system/monitor.rst
> index 0bcd5da21644..985c3f51ffe7 100644
> --- a/docs/system/monitor.rst
> +++ b/docs/system/monitor.rst
> @@ -21,6 +21,8 @@ The following commands are available:
>
> .. hxtool-doc:: hmp-commands.hx
>
> +.. hxtool-doc:: hmp-commands-virtio.hx
> +
> .. hxtool-doc:: hmp-commands-info.hx
>
> Integer expressions
> diff --git a/hmp-commands-virtio.hx b/hmp-commands-virtio.hx
> new file mode 100644
> index 000000000000..a8d49f0b2b46
> --- /dev/null
> +++ b/hmp-commands-virtio.hx
> @@ -0,0 +1,148 @@
> +HXCOMM Use DEFHEADING() to define headings in both help text and rST.
> +HXCOMM Text between SRST and ERST is copied to the rST version and
> +HXCOMM discarded from C version.
> +HXCOMM DEF(command, args, callback, arg_string, help) is used to construct
> +HXCOMM monitor info commands
> +HXCOMM HXCOMM can be used for comments, discarded from both rST and C.
> +HXCOMM
> +HXCOMM In this file, generally SRST fragments should have two extra
> +HXCOMM spaces of indent, so that the documentation list item for "virtio cmd"
> +HXCOMM appears inside the documentation list item for the top level
> +HXCOMM "virtio" documentation entry. The exception is the first SRST
> +HXCOMM fragment that defines that top level entry.
> +
> +SRST
> +``virtio`` *subcommand*
> + Show various information about virtio.
> +
> +ERST
> +
> + {
> + .name = "query",
> + .args_type = "",
> + .params = "",
> + .help = "List all available virtio devices",
> + .cmd = hmp_virtio_query,
> + .flags = "p",
> + },
> +
> +SRST
> + ``virtio query``
> + List all available virtio devices
> +
> + Example:
> +
> + List all available virtio devices in the machine::
> +
> + (qemu) virtio query
> + /machine/peripheral-anon/device[3]/virtio-backend [virtio-net]
> + /machine/peripheral-anon/device[1]/virtio-backend [virtio-serial]
> + /machine/peripheral-anon/device[0]/virtio-backend [virtio-blk]
> +
> +ERST
> +
> + {
> + .name = "status",
> + .args_type = "path:s",
> + .params = "path",
> + .help = "Display status of a given virtio device",
> + .cmd = hmp_virtio_status,
> + .flags = "p",
> + },
> +
> +SRST
> + ``virtio status`` *path*
> + Display status of a given virtio device
> +
> + Example:
> +
> + Dump the status of the first virtio device::
> +
> + (qemu) virtio status /machine/peripheral-anon/device[3]/virtio-backend
> + /machine/peripheral-anon/device[3]/virtio-backend:
> + Device Id: 1
> + Guest features: 0x0000000130afffa7
> + Host features: 0x0000000179bfffe7
> + Backend features: 0x0000000000000000
> + Endianness: little
> + VirtQueues: 3
> +
> +ERST
> +
> + {
> + .name = "queue-status",
> + .args_type = "path:s,queue:i",
> + .params = "path queue",
> + .help = "Display status of a given virtio queue",
> + .cmd = hmp_virtio_queue_status,
> + .flags = "p",
> + },
> +
> +SRST
> + ``virtio queue-status`` *path* *queue*
> + Display status of a given virtio queue
> +
> + Example:
> +
> + Dump the status of the first queue of the first virtio device::
> +
> + (qemu) virtio queue-status /machine/peripheral-anon/device[3]/virtio-backend 0
> + /machine/peripheral-anon/device[3]/virtio-backend:
> + index: 0
> + inuse: 0
> + last_avail_idx: 61
> + shadow_avail_idx: 292
> + signalled_used: 61
> + signalled_used_valid: 1
> + VRing:
> + num: 256
> + num_default: 256
> + align: 4096
> + desc: 0x000000006c352000
> + avail: 0x000000006c353000
> + used: 0x000000006c353240
> +
> +ERST
> +
> + {
> + .name = "queue-element",
> + .args_type = "path:s,queue:i,index:i?",
> + .params = "path queue [index]",
> + .help = "Display element of a given virtio queue",
> + .cmd = hmp_virtio_queue_element,
> + .flags = "p",
> + },
> +
> +SRST
> + ``virtio queue-element`` *path* *queue* [*index*]
> + Display element of a given virtio queue
> +
> + Example:
> +
> + Dump the information of the head element of the first queue of
> + the first virtio device::
> +
> + (qemu) virtio queue-element/machine/peripheral-anon/device[3]/virtio-backend 0
> + index: 67
> + ndescs: 1
> + descs: addr 0x6fe69800 len 1536 (write-only)
> +
> + (qemu) xp/128bx 0x6fe69800
> + 000000006fe69800: 0x02 0x00 0x00 0x00 0x00 0x00 0x00 0x00
> + 000000006fe69808: 0x00 0x00 0x01 0x00 0x52 0x54 0x00 0x12
> + 000000006fe69810: 0x34 0x56 0x52 0x54 0x00 0x09 0x51 0xde
> + 000000006fe69818: 0x08 0x00 0x45 0x00 0x00 0x4c 0x8f 0x32
> +
> + device[3] is a virtio-net device and we can see in the element buffer the
> + MAC address of the card::
> +
> + [root@localhost ~]# ip link show ens4
> + 2: ens4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP m0
> + link/ether 52:54:00:12:34:56 brd ff:ff:ff:ff:ff:ff
> +
> + and the MAC address of the gateway::
> +
> + [root@localhost ~]# arp -a
> + _gateway (192.168.122.1) at 52:54:00:09:51:de [ether] on ens4
> +
> +ERST
> diff --git a/hmp-commands.hx b/hmp-commands.hx
> index 7f0f3974ad90..14568b406dbc 100644
> --- a/hmp-commands.hx
> +++ b/hmp-commands.hx
> @@ -1804,6 +1804,16 @@ SRST
> Set QOM property *property* of object at location *path* to value *value*
> ERST
>
> + {
> + .name = "virtio",
> + .args_type = "name:S?",
> + .params = "[cmd]",
> + .help = "show various information about virtio",
> + .cmd = hmp_virtio_help,
> + .sub_table = hmp_virtio_cmds,
> + .flags = "p",
> + },
> +
> {
> .name = "info",
> .args_type = "item:s?",
> diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
> index 28848b9e64cf..d52d41169fb4 100644
> --- a/hw/virtio/virtio.c
> +++ b/hw/virtio/virtio.c
> @@ -29,6 +29,9 @@
> #include "hw/virtio/virtio-access.h"
> #include "sysemu/dma.h"
> #include "sysemu/runstate.h"
> +#include "monitor/hmp.h"
> +#include "monitor/monitor.h"
> +#include "qapi/qmp/qdict.h"
>
> static QTAILQ_HEAD(, VirtIODevice) virtio_list;
>
> @@ -3839,6 +3842,29 @@ VirtioInfoList *qmp_query_virtio(Error **errp)
> return list;
> }
>
> +void hmp_virtio_query(Monitor *mon, const QDict *qdict)
> +{
> + Error *err = NULL;
> + VirtioInfoList *l = qmp_query_virtio(&err);
> +
> + if (err != NULL) {
> + hmp_handle_error(mon, err);
> + return;
> + }
> +
> + if (l == NULL) {
> + monitor_printf(mon, "No VirtIO devices\n");
> + return;
> + }
> +
> + while (l) {
> + monitor_printf(mon, "%s [%s]\n", l->value->path, l->value->type);
> + l = l->next;
> + }
> +
> + qapi_free_VirtioInfoList(l);
I think you've made the same mistake there that I made in the vnc code;
you're walking 'l' along the list and then freeing l at the end, but l
is always null.
> +}
> +
> static VirtIODevice *virtio_device_find(const char *path)
> {
> VirtIODevice *vdev;
> @@ -3890,6 +3916,36 @@ VirtQueueStatus *qmp_virtio_queue_status(const char *path, uint16_t queue,
> return status;
> }
>
> +void hmp_virtio_queue_status(Monitor *mon, const QDict *qdict)
> +{
> + Error *err = NULL;
> + const char *path = qdict_get_try_str(qdict, "path");
> + int queue = qdict_get_int(qdict, "queue");
> + VirtQueueStatus *s = qmp_virtio_queue_status(path, queue, &err);
> +
> + if (err != NULL) {
> + hmp_handle_error(mon, err);
> + return;
> + }
> + monitor_printf(mon, "%s:\n", path);
> + monitor_printf(mon, " index: %d\n", s->queue_index);
> + monitor_printf(mon, " inuse: %d\n", s->inuse);
> + monitor_printf(mon, " last_avail_idx: %d\n", s->last_avail_idx);
> + monitor_printf(mon, " shadow_avail_idx: %d\n", s->shadow_avail_idx);
> + monitor_printf(mon, " signalled_used: %d\n", s->signalled_used);
> + monitor_printf(mon, " signalled_used_valid: %d\n",
> + s->signalled_used_valid);
> + monitor_printf(mon, " VRing:\n");
> + monitor_printf(mon, " num: %"PRId64"\n", s->vring_num);
> + monitor_printf(mon, " num_default: %"PRId64"\n", s->vring_num_default);
> + monitor_printf(mon, " align: %"PRId64"\n", s->vring_align);
> + monitor_printf(mon, " desc: 0x%016"PRIx64"\n", s->vring_desc);
> + monitor_printf(mon, " avail: 0x%016"PRIx64"\n", s->vring_avail);
> + monitor_printf(mon, " used: 0x%016"PRIx64"\n", s->vring_used);
> +
> + qapi_free_VirtQueueStatus(s);
> +}
> +
> VirtioStatus *qmp_virtio_status(const char* path, Error **errp)
> {
> VirtIODevice *vdev;
> @@ -3925,6 +3981,31 @@ VirtioStatus *qmp_virtio_status(const char* path, Error **errp)
> return status;
> }
>
> +void hmp_virtio_status(Monitor *mon, const QDict *qdict)
> +{
> + Error *err = NULL;
> + const char *path = qdict_get_try_str(qdict, "path");
> + VirtioStatus *s = qmp_virtio_status(path, &err);
> +
> + if (err != NULL) {
> + hmp_handle_error(mon, err);
> + return;
> + }
> +
> + monitor_printf(mon, "%s:\n", path);
> + monitor_printf(mon, " Device Id: %"PRId64"\n", s->device_id);
> + monitor_printf(mon, " Guest features: 0x%016"PRIx64"\n",
> + s->guest_features);
> + monitor_printf(mon, " Host features: 0x%016"PRIx64"\n",
> + s->host_features);
> + monitor_printf(mon, " Backend features: 0x%016"PRIx64"\n",
> + s->backend_features);
> + monitor_printf(mon, " Endianness: %s\n", s->device_endian);
> + monitor_printf(mon, " VirtQueues: %d\n", s->num_vqs);
> +
> + qapi_free_VirtioStatus(s);
> +}
> +
> VirtioQueueElement *qmp_virtio_queue_element(const char* path, uint16_t queue,
> bool has_index, uint16_t index,
> Error **errp)
> @@ -4010,6 +4091,40 @@ VirtioQueueElement *qmp_virtio_queue_element(const char* path, uint16_t queue,
> return element;
> }
>
> +void hmp_virtio_queue_element(Monitor *mon, const QDict *qdict)
> +{
> + Error *err = NULL;
> + const char *path = qdict_get_try_str(qdict, "path");
> + int queue = qdict_get_int(qdict, "queue");
> + int index = qdict_get_try_int(qdict, "index", -1);
> + VirtioQueueElement *element;
> + VirtioRingDescList *list;
> +
> + element = qmp_virtio_queue_element(path, queue, index != -1, index, &err);
> + if (err != NULL) {
> + hmp_handle_error(mon, err);
> + return;
> + }
> +
> + monitor_printf(mon, "index: %d\n", element->index);
> + monitor_printf(mon, "ndescs: %d\n", element->ndescs);
> + monitor_printf(mon, "descs: ");
> +
> + list = element->descs;
> + while (list) {
> + monitor_printf(mon, "addr 0x%"PRIx64" len %d %s", list->value->addr,
> + list->value->len, list->value->flags &
> + VRING_DESC_F_WRITE ? "(write-only)" : "(read-only)");
> + list = list->next;
> + if (list) {
> + monitor_printf(mon, ", ");
> + }
> + }
> + monitor_printf(mon, "\n");
> +
> + qapi_free_VirtioQueueElement(element);
> +}
> +
> static const TypeInfo virtio_device_info = {
> .name = TYPE_VIRTIO_DEVICE,
> .parent = TYPE_DEVICE,
> diff --git a/include/monitor/hmp.h b/include/monitor/hmp.h
> index e33ca5a911a5..9f1c118dde31 100644
> --- a/include/monitor/hmp.h
> +++ b/include/monitor/hmp.h
> @@ -98,6 +98,10 @@ void hmp_info_memory_devices(Monitor *mon, const QDict *qdict);
> void hmp_qom_list(Monitor *mon, const QDict *qdict);
> void hmp_qom_set(Monitor *mon, const QDict *qdict);
> void hmp_info_qom_tree(Monitor *mon, const QDict *dict);
> +void hmp_virtio_query(Monitor *mon, const QDict *qdict);
> +void hmp_virtio_status(Monitor *mon, const QDict *qdict);
> +void hmp_virtio_queue_status(Monitor *mon, const QDict *qdict);
> +void hmp_virtio_queue_element(Monitor *mon, const QDict *qdict);
> void object_add_completion(ReadLineState *rs, int nb_args, const char *str);
> void object_del_completion(ReadLineState *rs, int nb_args, const char *str);
> void device_add_completion(ReadLineState *rs, int nb_args, const char *str);
> diff --git a/monitor/misc.c b/monitor/misc.c
> index 6c45fa490ff5..5eacfa7079fc 100644
> --- a/monitor/misc.c
> +++ b/monitor/misc.c
> @@ -23,6 +23,7 @@
> */
>
> #include "qemu/osdep.h"
> +#include "config-devices.h"
> #include "monitor-internal.h"
> #include "cpu.h"
> #include "monitor/qdev.h"
> @@ -232,6 +233,15 @@ static void hmp_info_help(Monitor *mon, const QDict *qdict)
> help_cmd(mon, "info");
> }
>
> +static void hmp_virtio_help(Monitor *mon, const QDict *qdict)
> +{
> +#if defined(CONFIG_VIRTIO)
> + help_cmd(mon, "virtio");
> +#else
> + monitor_printf(mon, "Virtio is disabled\n");
> +#endif
> +}
> +
> static void monitor_init_qmp_commands(void)
> {
> /*
> @@ -1683,6 +1693,13 @@ static HMPCommand hmp_info_cmds[] = {
> { NULL, NULL, },
> };
>
> +static HMPCommand hmp_virtio_cmds[] = {
> +#if defined(CONFIG_VIRTIO)
> +#include "hmp-commands-virtio.h"
> +#endif
> + { NULL, NULL, },
> +};
> +
> /* hmp_cmds and hmp_info_cmds would be sorted at runtime */
> HMPCommand hmp_cmds[] = {
> #include "hmp-commands.h"
> --
> 2.25.1
>
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
© 2016 - 2025 Red Hat, Inc.