[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[RFC v5 6/6] hmp: add virtio commands
From: |
Jonah Palmer |
Subject: |
[RFC v5 6/6] hmp: add virtio commands |
Date: |
Thu, 18 Mar 2021 12:29:44 -0400 |
From: Laurent Vivier <lvivier@redhat.com>
This patch implements HMP version of the virtio QMP commands
[Jonah: Added relative indicies, device type, and used index
in HMP virtio queue-status command.]
Signed-off-by: Laurent Vivier <lvivier@redhat.com>
Signed-off-by: Jonah Palmer <jonah.palmer@oracle.com>
---
docs/system/monitor.rst | 2 +
hmp-commands-virtio.hx | 162 ++++++++++++++++++++++++++++++++++++++
hmp-commands.hx | 10 +++
hw/virtio/virtio.c | 204 +++++++++++++++++++++++++++++++++++++++++++++++-
include/monitor/hmp.h | 4 +
meson.build | 1 +
monitor/misc.c | 17 ++++
7 files changed, 399 insertions(+), 1 deletion(-)
create mode 100644 hmp-commands-virtio.hx
diff --git a/docs/system/monitor.rst b/docs/system/monitor.rst
index ff5c434..10418fc 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 0000000..0ef01b9
--- /dev/null
+++ b/hmp-commands-virtio.hx
@@ -0,0 +1,162 @@
+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.
+
+ Example:
+
+ List all sub-commands::
+
+ (qemu) virtio
+ virtio query -- List all available virtio devices
+ virtio status path -- Display status of a given virtio device
+ virtio queue-status path queue -- Display status of a given virtio queue
+ virtio queue-element path queue [index] -- Display element of a given
virtio queue
+
+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: event-idx, indirect-desc, version-1
+ ctrl-mac-addr, guest-announce, ctrl-vlan, ctrl-rx,
ctrl-vq, status, mrg-rxbuf, host-ufo, host-ecn, host-tso6, host-tso4,
guest-ufo, guest-ecn, guest-tso6, guest-tso4, mac, ctrl-guest-offloads,
guest-csum, csum
+ Host features: event-idx, indirect-desc, bad-feature, version-1,
any-layout, notify-on-empty
+ gso, ctrl-mac-addr, guest-announce, ctrl-rx-extra,
ctrl-vlan, ctrl-rx, ctrl-vq, status, mrg-rxbuf, host-ufo, host-ecn, host-tso6,
host-tso4, guest-ufo, guest-ecn, guest-tso6, guest-tso4, mac,
ctrl-guest-offloads, guest-csum, csum
+ Backend features:
+ 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:
+ device_type: virtio-net
+ index: 0
+ inuse: 0
+ last_avail_idx: 61 (61 % 256)
+ shadow_avail_idx: 292 (36 % 256)
+ used_idx: 61 (61 % 256)
+ signalled_used: 61 (61 % 256)
+ 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)
+
+ (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 d4001f9..19674bf 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1852,6 +1852,16 @@ SRST
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?",
.params = "[subcommand]",
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index 735a6ae..0836c6d 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -32,6 +32,9 @@
#include "sysemu/runstate.h"
#include "standard-headers/linux/virtio_ids.h"
#include CONFIG_DEVICES
+#include "monitor/hmp.h"
+#include "monitor/monitor.h"
+#include "qapi/qmp/qdict.h"
static QTAILQ_HEAD(, VirtIODevice) virtio_list;
@@ -3903,6 +3906,32 @@ VirtioInfoList *qmp_x_debug_query_virtio(Error **errp)
return list;
}
+void hmp_virtio_query(Monitor *mon, const QDict *qdict)
+{
+ Error *err = NULL;
+ VirtioInfoList *list = qmp_x_debug_query_virtio(&err);
+ VirtioInfoList *node;
+
+ if (err != NULL) {
+ hmp_handle_error(mon, err);
+ return;
+ }
+
+ if (list == NULL) {
+ monitor_printf(mon, "No VirtIO devices\n");
+ return;
+ }
+
+ node = list;
+ while (node) {
+ monitor_printf(mon, "%s [%s]\n", node->value->path,
+ VirtioType_str(node->value->type));
+ node = node->next;
+ }
+
+ qapi_free_VirtioInfoList(list);
+}
+
static VirtIODevice *virtio_device_find(const char *path)
{
VirtIODevice *vdev;
@@ -3956,8 +3985,48 @@ VirtQueueStatus *qmp_x_debug_virtio_queue_status(const
char *path,
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_x_debug_virtio_queue_status(path, queue, &err);
+
+ if (err != NULL) {
+ hmp_handle_error(mon, err);
+ return;
+ }
+
+ monitor_printf(mon, "%s:\n", path);
+ monitor_printf(mon, " device_type: %s\n",
+ VirtioType_str(s->device_type));
+ monitor_printf(mon, " index: %d\n", s->queue_index);
+ monitor_printf(mon, " inuse: %d\n", s->inuse);
+ monitor_printf(mon, " last_avail_idx: %d (%"PRId64" %%
%"PRId64")\n",
+ s->last_avail_idx, s->last_avail_idx % s->vring_num,
+ s->vring_num);
+ monitor_printf(mon, " shadow_avail_idx: %d (%"PRId64" %%
%"PRId64")\n",
+ s->shadow_avail_idx, s->shadow_avail_idx % s->vring_num,
+ s->vring_num);
+ monitor_printf(mon, " used_idx: %d (%"PRId64" %%
%"PRId64")\n",
+ s->used_idx, s->used_idx % s->vring_num, s->vring_num);
+ monitor_printf(mon, " signalled_used: %d (%"PRId64" %%
%"PRId64")\n",
+ s->signalled_used, s->signalled_used % s->vring_num,
+ s->vring_num);
+ 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);
+}
+
#define CONVERT_FEATURES(type, map) \
- ({ \
+ ({ \
type *list = NULL; \
type *node; \
for (i = 0; map[i].virtio_bit != -1; i++) {\
@@ -4090,6 +4159,93 @@ VirtioStatus *qmp_x_debug_virtio_status(const char*
path, Error **errp)
return status;
}
+#define DUMP_FEATURES(type, field) \
+ do { \
+ type##FeatureList * list = features->u.field.features; \
+ if (list) { \
+ monitor_printf(mon, " "); \
+ while (list) { \
+ monitor_printf(mon, "%s", type##Feature_str(list->value)); \
+ list = list->next; \
+ if (list != NULL) { \
+ monitor_printf(mon, ", "); \
+ } \
+ } \
+ monitor_printf(mon, "\n"); \
+ } \
+ } while (0)
+
+static void hmp_virtio_dump_features(Monitor *mon,
+ VirtioDeviceFeatures *features)
+{
+ VirtioTransportFeatureList *transport_list = features->transport;
+ while (transport_list) {
+ monitor_printf(mon, "%s",
+ VirtioTransportFeature_str(transport_list->value));
+ transport_list = transport_list->next;
+ if (transport_list != NULL) {
+ monitor_printf(mon, ", ");
+ }
+ }
+ monitor_printf(mon, "\n");
+ switch (features->type) {
+ case VIRTIO_TYPE_VIRTIO_SERIAL:
+ DUMP_FEATURES(VirtioSerial, virtio_serial);
+ break;
+ case VIRTIO_TYPE_VIRTIO_BLK:
+ DUMP_FEATURES(VirtioBlk, virtio_blk);
+ break;
+ case VIRTIO_TYPE_VIRTIO_GPU:
+ DUMP_FEATURES(VirtioGpu, virtio_gpu);
+ break;
+ case VIRTIO_TYPE_VIRTIO_NET:
+ DUMP_FEATURES(VirtioNet, virtio_net);
+ break;
+ case VIRTIO_TYPE_VIRTIO_SCSI:
+ DUMP_FEATURES(VirtioScsi, virtio_scsi);
+ break;
+ case VIRTIO_TYPE_VIRTIO_BALLOON:
+ DUMP_FEATURES(VirtioBalloon, virtio_balloon);
+ break;
+ case VIRTIO_TYPE_VIRTIO_IOMMU:
+ DUMP_FEATURES(VirtioIommu, virtio_iommu);
+ break;
+ default:
+ g_assert_not_reached();
+ }
+ if (features->has_unknown_features) {
+ monitor_printf(mon, " "
+ "unknown-features(0x%016"PRIx64")\n",
+ features->unknown_features);
+ }
+}
+
+void hmp_virtio_status(Monitor *mon, const QDict *qdict)
+{
+ Error *err = NULL;
+ const char *path = qdict_get_try_str(qdict, "path");
+ VirtioStatus *s = qmp_x_debug_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: ");
+ hmp_virtio_dump_features(mon, s->guest_features);
+ monitor_printf(mon, " Host features: ");
+ hmp_virtio_dump_features(mon, s->host_features);
+ monitor_printf(mon, " Backend features: ");
+ hmp_virtio_dump_features(mon, s->backend_features);
+ monitor_printf(mon, " Endianness: %s\n",
+ VirtioStatusEndianness_str(s->device_endian));
+ monitor_printf(mon, " VirtQueues: %d\n", s->num_vqs);
+
+ qapi_free_VirtioStatus(s);
+}
+
static VirtioRingDescFlagsList *qmp_decode_vring_desc_flags(uint16_t flags)
{
VirtioRingDescFlagsList *list = NULL;
@@ -4225,6 +4381,52 @@ done:
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_x_debug_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", list->value->addr,
+ list->value->len);
+ if (list->value->flags) {
+ VirtioRingDescFlagsList *flag = list->value->flags;
+ monitor_printf(mon, " (");
+ while (flag) {
+ monitor_printf(mon, "%s",
VirtioRingDescFlags_str(flag->value));
+ flag = flag->next;
+ if (flag) {
+ monitor_printf(mon, ", ");
+ }
+ }
+ monitor_printf(mon, ")");
+ }
+ 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 ed2913f..7a63744 100644
--- a/include/monitor/hmp.h
+++ b/include/monitor/hmp.h
@@ -98,6 +98,10 @@ void hmp_qom_list(Monitor *mon, const QDict *qdict);
void hmp_qom_get(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/meson.build b/meson.build
index a923f24..2d836b9 100644
--- a/meson.build
+++ b/meson.build
@@ -1695,6 +1695,7 @@ if have_system
hx_headers += [
['hmp-commands.hx', 'hmp-commands.h'],
['hmp-commands-info.hx', 'hmp-commands-info.h'],
+ ['hmp-commands-virtio.hx', 'hmp-commands-virtio.h'],
]
endif
foreach d : hx_headers
diff --git a/monitor/misc.c b/monitor/misc.c
index a7650ed..69542df 100644
--- a/monitor/misc.c
+++ b/monitor/misc.c
@@ -23,6 +23,7 @@
*/
#include "qemu/osdep.h"
+#include CONFIG_DEVICES
#include "monitor-internal.h"
#include "cpu.h"
#include "monitor/qdev.h"
@@ -220,6 +221,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)
{
/*
@@ -1654,6 +1664,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"
--
1.8.3.1
- [RFC v5 0/6] hmp,qmp: Add some commands to introspect virtio deices, Jonah Palmer, 2021/03/18
- [RFC v5 3/6] qmp: decode feature bits in virtio-status, Jonah Palmer, 2021/03/18
- [RFC v5 4/6] qmp: add QMP command x-debug-virtio-queue-status, Jonah Palmer, 2021/03/18
- [RFC v5 5/6] qmp: add QMP command x-debug-virtio-queue-element, Jonah Palmer, 2021/03/18
- [RFC v5 2/6] qmp: add QMP command x-debug-virtio-status, Jonah Palmer, 2021/03/18
- [RFC v5 6/6] hmp: add virtio commands,
Jonah Palmer <=
- [RFC v5 1/6] qmp: add QMP command x-debug-query-virtio, Jonah Palmer, 2021/03/18
- Re: [RFC v5 0/6] hmp, qmp: Add some commands to introspect virtio deices, no-reply, 2021/03/18