From nobody Thu May 2 06:05:06 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (208.118.235.17 [208.118.235.17]) by mx.zohomail.com with SMTPS id 1506535393665311.1181872676134; Wed, 27 Sep 2017 11:03:13 -0700 (PDT) Received: from localhost ([::1]:55822 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dxGfZ-0006xS-7B for importer@patchew.org; Wed, 27 Sep 2017 14:02:49 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:46204) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dxGef-0006eB-LN for qemu-devel@nongnu.org; Wed, 27 Sep 2017 14:01:55 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dxGec-0002wO-FX for qemu-devel@nongnu.org; Wed, 27 Sep 2017 14:01:53 -0400 Received: from mailhub.sw.ru ([195.214.232.25]:18786 helo=relay.sw.ru) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dxGeP-0002sy-Hw; Wed, 27 Sep 2017 14:01:38 -0400 Received: from work.sw.ru. (msk-vpn.virtuozzo.com [195.214.232.6]) by relay.sw.ru (8.13.4/8.13.4) with ESMTP id v8RI1UFT028949; Wed, 27 Sep 2017 21:01:31 +0300 (MSK) From: Jan Dakinevich To: qemu-devel@nongnu.org, qemu-block@nongnu.org Date: Wed, 27 Sep 2017 21:01:29 +0300 Message-Id: <1506535289-14430-1-git-send-email-jan.dakinevich@virtuozzo.com> X-Mailer: git-send-email 2.1.4 X-detected-operating-system: by eggs.gnu.org: OpenBSD 3.x [fuzzy] X-Received-From: 195.214.232.25 Subject: [Qemu-devel] [PATCH v3] virtio: introduce `info virtio' hmp command X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , "Denis V. Lunev" , "Michael S. Tsirkin" , Markus Armbruster , Jason Wang , Cornelia Huck , "Dr. David Alan Gilbert" , Amit Shah , Max Reitz , Jan Dakinevich , Stefan Hajnoczi , Paolo Bonzini Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" The command is intended for exposing device specific virtio feature bits and their negotiation status. It is convenient and useful for debug purpose. Names of features are taken from a devices via get_feature_name() within VirtioDeviceClass. If certain device doesn't implement it, the command will print only hexadecimal value of feature mask. Cc: Denis V. Lunev Signed-off-by: Jan Dakinevich --- v3: * Avoid signed int * Use virtio_vdev_has_feature()/virtio_host_has_feature() v2: http://lists.nongnu.org/archive/html/qemu-devel/2017-09/msg07527.html v1: http://lists.nongnu.org/archive/html/qemu-devel/2017-09/msg07247.html --- hmp-commands-info.hx | 14 +++++ hmp.c | 149 ++++++++++++++++++++++++++++++++++++++++= ++++ hmp.h | 1 + hw/block/virtio-blk.c | 21 +++++++ hw/char/virtio-serial-bus.c | 15 +++++ hw/display/virtio-gpu.c | 13 ++++ hw/net/virtio-net.c | 35 +++++++++++ hw/scsi/virtio-scsi.c | 16 +++++ hw/virtio/virtio-balloon.c | 15 +++++ hw/virtio/virtio-bus.c | 1 + include/hw/virtio/virtio.h | 2 + monitor.c | 1 + 12 files changed, 283 insertions(+) diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx index 4f1ece9..2550027 100644 --- a/hmp-commands-info.hx +++ b/hmp-commands-info.hx @@ -868,6 +868,20 @@ ETEXI }, =20 STEXI +@item info virtio +@findex virtio +Display guest and host fetures for all virtio devices. +ETEXI + + { + .name =3D "virtio", + .args_type =3D "", + .params =3D "", + .help =3D "show virtio info", + .cmd =3D hmp_info_virtio, + }, + +STEXI @end table ETEXI =20 diff --git a/hmp.c b/hmp.c index ace729d..f231395 100644 --- a/hmp.c +++ b/hmp.c @@ -43,6 +43,7 @@ #include "hw/intc/intc.h" #include "migration/snapshot.h" #include "migration/misc.h" +#include "hw/virtio/virtio.h" =20 #ifdef CONFIG_SPICE #include @@ -2894,3 +2895,151 @@ void hmp_info_memory_size_summary(Monitor *mon, con= st QDict *qdict) } hmp_handle_error(mon, &err); } + +#define HMP_INFO_VIRTIO_INDENT 2 +#define HMP_INFO_VIRTIO_FIELD 32 + +static void hmp_info_virtio_print_status(Monitor *mon, VirtIODevice *vdev) +{ + uint8_t status[] =3D { + VIRTIO_CONFIG_S_ACKNOWLEDGE, + VIRTIO_CONFIG_S_DRIVER, + VIRTIO_CONFIG_S_DRIVER_OK, + VIRTIO_CONFIG_S_FEATURES_OK, + VIRTIO_CONFIG_S_NEEDS_RESET, + VIRTIO_CONFIG_S_FAILED, + }; + const char *names[] =3D { + "acknowledge", + "driver", + "driver_ok", + "features_ok", + "needs_reset" + "failed", + }; + const char *comma =3D ""; + unsigned idx; + + monitor_printf(mon, "%*sstatus: 0x%02"PRIx8" ", + HMP_INFO_VIRTIO_INDENT, "", vdev->status); + + for (idx =3D 0; idx < ARRAY_SIZE(status); idx++) { + if (!(vdev->status & status[idx])) { + continue; + } + monitor_printf(mon, "%s%s", comma, names[idx]); + if (names[idx]) { + comma =3D ","; + } + } + monitor_printf(mon, "\n"); +} + +static void hmp_info_virtio_print_common_features(Monitor *mon, + VirtIODevice *vdev) +{ + uint64_t features[] =3D { + VIRTIO_RING_F_INDIRECT_DESC, + VIRTIO_RING_F_EVENT_IDX, + VIRTIO_F_NOTIFY_ON_EMPTY, + VIRTIO_F_ANY_LAYOUT, + VIRTIO_F_IOMMU_PLATFORM, + VIRTIO_F_VERSION_1, + }; + const char *names[] =3D { + "indirect_desc", + "event_idx", + "notify_on_empty", + "any_layout", + "iommu_platform", + "version_1", + }; + unsigned idx; + + monitor_printf(mon, "%*scommon features:\n", HMP_INFO_VIRTIO_INDENT, "= "); + + for (idx =3D 0; idx < ARRAY_SIZE(features); idx++) { + const char *ack =3D virtio_vdev_has_feature(vdev, features[idx]) + ? "acked" : ""; + + if (!virtio_host_has_feature(vdev, features[idx])) { + continue; + } + monitor_printf(mon, "%*s%*s%*s\n", HMP_INFO_VIRTIO_INDENT, "", + HMP_INFO_VIRTIO_FIELD, names[idx], + HMP_INFO_VIRTIO_FIELD, ack); + } +} + +static void hmp_info_virtio_print_specific_features(Monitor *mon, + VirtIODevice *vdev) +{ + VirtioDeviceClass *vdc =3D VIRTIO_DEVICE_GET_CLASS(vdev); + unsigned idx; + + if (!vdc->get_feature_name) { + return; + } + + monitor_printf(mon, "%*sspecific features:\n", HMP_INFO_VIRTIO_INDENT,= ""); + + for (idx =3D 0; idx < 64; idx++) { + const char *name =3D vdc->get_feature_name(vdev, idx); + const char *ack =3D virtio_vdev_has_feature(vdev, idx) ? "acked" := ""; + + if (!name) { + continue; + } + if (!virtio_host_has_feature(vdev, idx)) { + continue; + } + monitor_printf(mon, "%*s%*s%*s\n", HMP_INFO_VIRTIO_INDENT, "", + HMP_INFO_VIRTIO_FIELD, name, HMP_INFO_VIRTIO_FIELD,= ack); + } +} + +static void hmp_info_virtio_print(Monitor *mon, VirtIODevice *vdev) +{ + char *path =3D qdev_get_dev_path(DEVICE(vdev)); + + monitor_printf(mon, "%s at %s\n", object_get_typename(OBJECT(vdev)), p= ath); + g_free(path); + + hmp_info_virtio_print_status(mon, vdev); + + monitor_printf(mon, "%*shost features: 0x%016"PRIx64"\n", + HMP_INFO_VIRTIO_INDENT, "", vdev->host_features); + monitor_printf(mon, "%*sguest features: 0x%016"PRIx64"\n", + HMP_INFO_VIRTIO_INDENT, "", vdev->guest_features); + + hmp_info_virtio_print_common_features(mon, vdev); + hmp_info_virtio_print_specific_features(mon, vdev); +} + +static void hmp_info_virtio_recursive(Monitor *mon, BusState *bus) +{ + BusChild *kid; + + QTAILQ_FOREACH(kid, &bus->children, sibling) { + DeviceState *dev =3D kid->child; + BusState *child; + + if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_DEVICE)) { + hmp_info_virtio_print(mon, VIRTIO_DEVICE(dev)); + } + QLIST_FOREACH(child, &dev->child_bus, sibling) { + hmp_info_virtio_recursive(mon, child); + } + } +} + +void hmp_info_virtio(Monitor *mon, const QDict *qdict) +{ + BusState *bus =3D sysbus_get_default(); + + if (!bus) { + return; + } + + hmp_info_virtio_recursive(mon, bus); +} diff --git a/hmp.h b/hmp.h index 3605003..3e8f30a 100644 --- a/hmp.h +++ b/hmp.h @@ -146,5 +146,6 @@ void hmp_info_ramblock(Monitor *mon, const QDict *qdict= ); void hmp_hotpluggable_cpus(Monitor *mon, const QDict *qdict); void hmp_info_vm_generation_id(Monitor *mon, const QDict *qdict); void hmp_info_memory_size_summary(Monitor *mon, const QDict *qdict); +void hmp_info_virtio(Monitor *mon, const QDict *qdict); =20 #endif diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c index 05d1440..c77f651 100644 --- a/hw/block/virtio-blk.c +++ b/hw/block/virtio-blk.c @@ -1017,6 +1017,26 @@ static Property virtio_blk_properties[] =3D { DEFINE_PROP_END_OF_LIST(), }; =20 +static const char *virtio_blk_get_feature_name(VirtIODevice *vdev, + unsigned feature) +{ + static const char *names[] =3D { + [VIRTIO_BLK_F_BARRIER] =3D "barrier", + [VIRTIO_BLK_F_SIZE_MAX] =3D "size_max", + [VIRTIO_BLK_F_SEG_MAX] =3D "seg_max", + [VIRTIO_BLK_F_RO] =3D "ro", + [VIRTIO_BLK_F_BLK_SIZE] =3D "blk_size", + [VIRTIO_BLK_F_SCSI] =3D "scsi", + [VIRTIO_BLK_F_TOPOLOGY] =3D "topology", + [VIRTIO_BLK_F_FLUSH] =3D "flush", + [VIRTIO_BLK_F_MQ] =3D "mq", + }; + if (feature >=3D ARRAY_SIZE(names)) { + return NULL; + } + return names[feature]; +} + static void virtio_blk_class_init(ObjectClass *klass, void *data) { DeviceClass *dc =3D DEVICE_CLASS(klass); @@ -1030,6 +1050,7 @@ static void virtio_blk_class_init(ObjectClass *klass,= void *data) vdc->get_config =3D virtio_blk_update_config; vdc->set_config =3D virtio_blk_set_config; vdc->get_features =3D virtio_blk_get_features; + vdc->get_feature_name =3D virtio_blk_get_feature_name; vdc->set_status =3D virtio_blk_set_status; vdc->reset =3D virtio_blk_reset; vdc->save =3D virtio_blk_save_device; diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c index 9470bd7..41f4466 100644 --- a/hw/char/virtio-serial-bus.c +++ b/hw/char/virtio-serial-bus.c @@ -1156,6 +1156,20 @@ static Property virtio_serial_properties[] =3D { DEFINE_PROP_END_OF_LIST(), }; =20 +static const char *virtio_serial_get_feature_name(VirtIODevice *vdev, + unsigned feature) +{ + static const char *names[] =3D { + [VIRTIO_CONSOLE_F_SIZE] =3D "size", + [VIRTIO_CONSOLE_F_MULTIPORT] =3D "multiport", + [VIRTIO_CONSOLE_F_EMERG_WRITE] =3D "emerg_write", + }; + if (feature >=3D ARRAY_SIZE(names)) { + return NULL; + } + return names[feature]; +} + static void virtio_serial_class_init(ObjectClass *klass, void *data) { DeviceClass *dc =3D DEVICE_CLASS(klass); @@ -1170,6 +1184,7 @@ static void virtio_serial_class_init(ObjectClass *kla= ss, void *data) vdc->realize =3D virtio_serial_device_realize; vdc->unrealize =3D virtio_serial_device_unrealize; vdc->get_features =3D get_features; + vdc->get_feature_name =3D virtio_serial_get_feature_name; vdc->get_config =3D get_config; vdc->set_config =3D set_config; vdc->set_status =3D set_status; diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c index 3a8f1e1..49aa214 100644 --- a/hw/display/virtio-gpu.c +++ b/hw/display/virtio-gpu.c @@ -1307,6 +1307,18 @@ static Property virtio_gpu_properties[] =3D { DEFINE_PROP_END_OF_LIST(), }; =20 +static const char *virtio_gpu_get_feature_name(VirtIODevice *vdev, + unsigned feature) +{ + static const char *names[] =3D { + [VIRTIO_GPU_F_VIRGL] =3D "virgl", + }; + if (feature >=3D ARRAY_SIZE(names)) { + return NULL; + } + return names[feature]; +} + static void virtio_gpu_class_init(ObjectClass *klass, void *data) { DeviceClass *dc =3D DEVICE_CLASS(klass); @@ -1317,6 +1329,7 @@ static void virtio_gpu_class_init(ObjectClass *klass,= void *data) vdc->get_config =3D virtio_gpu_get_config; vdc->set_config =3D virtio_gpu_set_config; vdc->get_features =3D virtio_gpu_get_features; + vdc->get_feature_name =3D virtio_gpu_get_feature_name; vdc->set_features =3D virtio_gpu_set_features; =20 vdc->reset =3D virtio_gpu_reset; diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index 148071a..f4d20a85 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -2154,6 +2154,40 @@ static Property virtio_net_properties[] =3D { DEFINE_PROP_END_OF_LIST(), }; =20 +static const char *virtio_net_get_feature_name(VirtIODevice *vdev, + unsigned feature) +{ + static const char *names[] =3D { + [VIRTIO_NET_F_CSUM] =3D "csum", + [VIRTIO_NET_F_GUEST_CSUM] =3D "guest_csum", + [VIRTIO_NET_F_CTRL_GUEST_OFFLOADS] =3D "ctrl_guest_offloads", + [VIRTIO_NET_F_MTU] =3D "mtu", + [VIRTIO_NET_F_MAC] =3D "mac", + [VIRTIO_NET_F_GSO] =3D "gso", + [VIRTIO_NET_F_GUEST_TSO4] =3D "guest_tso4", + [VIRTIO_NET_F_GUEST_TSO6] =3D "guest_tso6", + [VIRTIO_NET_F_GUEST_ECN] =3D "guest_ecn", + [VIRTIO_NET_F_GUEST_UFO] =3D "guest_ufo", + [VIRTIO_NET_F_HOST_TSO4] =3D "host_tso4", + [VIRTIO_NET_F_HOST_TSO6] =3D "host_tso6", + [VIRTIO_NET_F_HOST_ECN] =3D "host_ecn", + [VIRTIO_NET_F_HOST_UFO] =3D "host_ufo", + [VIRTIO_NET_F_MRG_RXBUF] =3D "mrg_rxbuf", + [VIRTIO_NET_F_STATUS] =3D "status", + [VIRTIO_NET_F_CTRL_VQ] =3D "ctrl_vq", + [VIRTIO_NET_F_CTRL_RX] =3D "ctrl_rx", + [VIRTIO_NET_F_CTRL_VLAN] =3D "ctrl_vlan", + [VIRTIO_NET_F_CTRL_RX_EXTRA] =3D "ctrl_rx_extra", + [VIRTIO_NET_F_GUEST_ANNOUNCE] =3D "guest_announce", + [VIRTIO_NET_F_MQ] =3D "mq", + [VIRTIO_NET_F_CTRL_MAC_ADDR] =3D "ctrl_mac_addr", + }; + if (feature >=3D ARRAY_SIZE(names)) { + return NULL; + } + return names[feature]; +} + static void virtio_net_class_init(ObjectClass *klass, void *data) { DeviceClass *dc =3D DEVICE_CLASS(klass); @@ -2169,6 +2203,7 @@ static void virtio_net_class_init(ObjectClass *klass,= void *data) vdc->get_features =3D virtio_net_get_features; vdc->set_features =3D virtio_net_set_features; vdc->bad_features =3D virtio_net_bad_features; + vdc->get_feature_name =3D virtio_net_get_feature_name; vdc->reset =3D virtio_net_reset; vdc->set_status =3D virtio_net_set_status; vdc->guest_notifier_mask =3D virtio_net_guest_notifier_mask; diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c index 3aa9971..b53cf8b 100644 --- a/hw/scsi/virtio-scsi.c +++ b/hw/scsi/virtio-scsi.c @@ -942,6 +942,21 @@ static const VMStateDescription vmstate_virtio_scsi = =3D { }, }; =20 +static const char *virtio_scsi_get_feature_name(VirtIODevice *vdev, + unsigned feature) +{ + static const char *names[] =3D { + [VIRTIO_SCSI_F_INOUT] =3D "inout", + [VIRTIO_SCSI_F_HOTPLUG] =3D "hotplug", + [VIRTIO_SCSI_F_CHANGE] =3D "change", + [VIRTIO_SCSI_F_T10_PI] =3D "t10_pi", + }; + if (feature >=3D ARRAY_SIZE(names)) { + return NULL; + } + return names[feature]; +} + static void virtio_scsi_common_class_init(ObjectClass *klass, void *data) { VirtioDeviceClass *vdc =3D VIRTIO_DEVICE_CLASS(klass); @@ -964,6 +979,7 @@ static void virtio_scsi_class_init(ObjectClass *klass, = void *data) vdc->unrealize =3D virtio_scsi_device_unrealize; vdc->set_config =3D virtio_scsi_set_config; vdc->get_features =3D virtio_scsi_get_features; + vdc->get_feature_name =3D virtio_scsi_get_feature_name; vdc->reset =3D virtio_scsi_reset; vdc->start_ioeventfd =3D virtio_scsi_dataplane_start; vdc->stop_ioeventfd =3D virtio_scsi_dataplane_stop; diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c index 37cde38..b396eb1 100644 --- a/hw/virtio/virtio-balloon.c +++ b/hw/virtio/virtio-balloon.c @@ -509,6 +509,20 @@ static Property virtio_balloon_properties[] =3D { DEFINE_PROP_END_OF_LIST(), }; =20 +static const char *virtio_balloon_get_feature_name(VirtIODevice *vdev, + unsigned feature) +{ + static const char *names[] =3D { + [VIRTIO_BALLOON_F_MUST_TELL_HOST] =3D "must_tell_host", + [VIRTIO_BALLOON_F_STATS_VQ] =3D "stats_vq", + [VIRTIO_BALLOON_F_DEFLATE_ON_OOM] =3D "deflate_on_oom", + }; + if (feature >=3D ARRAY_SIZE(names)) { + return NULL; + } + return names[feature]; +} + static void virtio_balloon_class_init(ObjectClass *klass, void *data) { DeviceClass *dc =3D DEVICE_CLASS(klass); @@ -523,6 +537,7 @@ static void virtio_balloon_class_init(ObjectClass *klas= s, void *data) vdc->get_config =3D virtio_balloon_get_config; vdc->set_config =3D virtio_balloon_set_config; vdc->get_features =3D virtio_balloon_get_features; + vdc->get_feature_name =3D virtio_balloon_get_feature_name; vdc->set_status =3D virtio_balloon_set_status; vdc->vmsd =3D &vmstate_virtio_balloon_device; } diff --git a/hw/virtio/virtio-bus.c b/hw/virtio/virtio-bus.c index 3042232..e9ae54f 100644 --- a/hw/virtio/virtio-bus.c +++ b/hw/virtio/virtio-bus.c @@ -30,6 +30,7 @@ #include "hw/virtio/virtio-bus.h" #include "hw/virtio/virtio.h" #include "exec/address-spaces.h" +#include "monitor/monitor.h" =20 /* #define DEBUG_VIRTIO_BUS */ =20 diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h index 80c45c3..3ea2cd0 100644 --- a/include/hw/virtio/virtio.h +++ b/include/hw/virtio/virtio.h @@ -141,6 +141,8 @@ typedef struct VirtioDeviceClass { void (*save)(VirtIODevice *vdev, QEMUFile *f); int (*load)(VirtIODevice *vdev, QEMUFile *f, int version_id); const VMStateDescription *vmsd; + /* Get the name of device specific feature */ + const char *(*get_feature_name)(VirtIODevice *vdev, unsigned feature); } VirtioDeviceClass; =20 void virtio_instance_init_common(Object *proxy_obj, void *data, diff --git a/monitor.c b/monitor.c index f4856b9..779f168 100644 --- a/monitor.c +++ b/monitor.c @@ -78,6 +78,7 @@ #include "sysemu/cpus.h" #include "qemu/cutils.h" #include "qapi/qmp/dispatch.h" +#include "hw/virtio/virtio-bus.h" =20 #if defined(TARGET_S390X) #include "hw/s390x/storage-keys.h" --=20 2.1.4