This patch implements HMP version of the virtio QMP commands Signed-off-by: Laurent Vivier <lviv...@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