qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [RFC 5/5] hmp: add virtio commands


From: Dr. David Alan Gilbert
Subject: Re: [RFC 5/5] hmp: add virtio commands
Date: Thu, 2 Apr 2020 16:08:07 +0100
User-agent: Mutt/1.13.4 (2020-02-15)

* Laurent Vivier (address@hidden) wrote:
> This patch implements HMP version of the virtio QMP commands
> 
> Signed-off-by: Laurent Vivier <address@hidden>
> ---
>  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 / address@hidden / Manchester, UK




reply via email to

[Prev in Thread] Current Thread [Next in Thread]