On May 10 10:57, Mateusz Nowicki wrote:
> Add an 'info nvme' HMP command for inspecting emulated NVMe
> controllers from the QEMU monitor.
> 
> For each NVMe controller in the QOM tree the command prints:
> 
>   - PCI BDF, vendor/device ID and BAR0 base address;
>   - Identify Controller fields visible to the host driver: SN, MN, FR
>     and CNTLID;
>   - the CC, CSTS and AQA registers (raw 32-bit values);
>   - the number of admin and active I/O submission/completion queues.
> 
> Useful when debugging the Linux NVMe driver against the QEMU emulation
> without attaching gdb to the QEMU process.
> 
> Example:
> 
>   (qemu) info nvme
>   /machine/peripheral-anon/device[0]
>     PCI:    BDF 00:04.0  VID=8086 DID=5845  BAR0=0x00000000feb50000
>     ID:     SN=NVME0001  MN=QEMU NVMe Ctrl  FR=...  CNTLID=0x0000
>     CC:     0x00460001
>     CSTS:   0x00000001
>     AQA:    0x001f001f
>     Queues: 1 admin + 4 IO SQ / 4 IO CQ
> 
> Signed-off-by: Mateusz Nowicki <[email protected]>
> ---
>  hmp-commands-info.hx | 13 ++++++++
>  hw/nvme/meson.build  |  2 +-
>  hw/nvme/monitor.c    | 76 ++++++++++++++++++++++++++++++++++++++++++++
>  qapi/machine.json    | 17 ++++++++++
>  4 files changed, 107 insertions(+), 1 deletion(-)
>  create mode 100644 hw/nvme/monitor.c
> 
> diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx
> index 82134eb6c2..b984691c3c 100644
> --- a/hmp-commands-info.hx
> +++ b/hmp-commands-info.hx
> @@ -340,6 +340,19 @@ SRST
>      Show guest USB devices.
>  ERST
>  
> +    {
> +        .name       = "nvme",
> +        .args_type  = "",
> +        .params     = "",
> +        .help       = "show emulated NVMe controllers",
> +        .cmd_info_hrt = qmp_x_query_nvme,
> +    },
> +
> +SRST
> +  ``info nvme``
> +    Show emulated NVMe controllers.
> +ERST
> +
>      {
>          .name       = "usbhost",
>          .args_type  = "",
> diff --git a/hw/nvme/meson.build b/hw/nvme/meson.build
> index 7d5caa53c2..3017f058f9 100644
> --- a/hw/nvme/meson.build
> +++ b/hw/nvme/meson.build
> @@ -1 +1 @@
> -system_ss.add(when: 'CONFIG_NVME_PCI', if_true: files('ctrl.c', 'dif.c', 
> 'ns.c', 'subsys.c', 'nguid.c'))
> \ No newline at end of file
> +system_ss.add(when: 'CONFIG_NVME_PCI', if_true: files('ctrl.c', 'dif.c', 
> 'ns.c', 'subsys.c', 'nguid.c', 'monitor.c'))
> \ No newline at end of file
> diff --git a/hw/nvme/monitor.c b/hw/nvme/monitor.c
> new file mode 100644
> index 0000000000..95a6754437
> --- /dev/null
> +++ b/hw/nvme/monitor.c
> @@ -0,0 +1,76 @@
> +/*
> + * QEMU NVMe Controller monitor commands
> + *
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qapi/error.h"
> +#include "qapi/qapi-commands-machine.h"
> +#include "qapi/type-helpers.h"
> +#include "hw/pci/pci.h"
> +
> +#include "nvme.h"
> +
> +static int collect_one(Object *obj, void *opaque)
> +{
> +    GString *buf = opaque;
> +    NvmeCtrl *n;
> +    PCIDevice *pci;
> +    pcibus_t bar0;
> +    unsigned io_sq = 0, io_cq = 0;
> +
> +    if (!object_dynamic_cast(obj, TYPE_NVME)) {
> +        return 0;
> +    }
> +    n = NVME(obj);
> +    pci = PCI_DEVICE(n);
> +    bar0 = pci_get_bar_addr(pci, 0);
> +
> +    for (unsigned i = 1; i <= n->params.max_ioqpairs; i++) {

I think this needs to run over n->conf_ioqpairs to also work for SR-IOV
VFs? Same goes for patch 2 I think.

> +        if (n->sq && n->sq[i]) {
> +            io_sq++;
> +        }
> +        if (n->cq && n->cq[i]) {
> +            io_cq++;
> +        }
> +    }
> +
> +    g_string_append_printf(buf, "%s\n", object_get_canonical_path(obj));
> +    g_string_append_printf(buf,
> +        "  PCI:    BDF %02x:%02x.%x  VID=%04x DID=%04x  ",
> +        pci_dev_bus_num(pci), PCI_SLOT(pci->devfn), PCI_FUNC(pci->devfn),
> +        pci_get_word(pci->config + PCI_VENDOR_ID),
> +        pci_get_word(pci->config + PCI_DEVICE_ID));
> +    if (bar0 == PCI_BAR_UNMAPPED) {
> +        g_string_append(buf, "BAR0=unmapped\n");
> +    } else {
> +        g_string_append_printf(buf, "BAR0=0x%016" PRIx64 "\n",
> +                               (uint64_t)bar0);
> +    }
> +    g_string_append_printf(buf,
> +        "  ID:     SN=%.20s  MN=%.40s  FR=%.8s  CNTLID=0x%04x\n",
> +        n->id_ctrl.sn, n->id_ctrl.mn, n->id_ctrl.fr, n->cntlid);
> +    g_string_append_printf(buf, "  CC:     0x%08x\n",
> +                           ldl_le_p(&n->bar.cc));
> +    g_string_append_printf(buf, "  CSTS:   0x%08x\n",
> +                           ldl_le_p(&n->bar.csts));
> +    g_string_append_printf(buf, "  AQA:    0x%08x\n",
> +                           ldl_le_p(&n->bar.aqa));
> +    g_string_append_printf(buf,
> +        "  Queues: 1 admin + %u IO SQ / %u IO CQ\n", io_sq, io_cq);
> +    return 0;
> +}
> +
> +HumanReadableText *qmp_x_query_nvme(Error **errp)
> +{
> +    g_autoptr(GString) buf = g_string_new("");
> +
> +    object_child_foreach_recursive(object_get_root(), collect_one, buf);
> +
> +    if (buf->len == 0) {
> +        g_string_append(buf, "no NVMe controllers\n");
> +    }
> +
> +    return human_readable_text_from_str(buf);
> +}
> diff --git a/qapi/machine.json b/qapi/machine.json
> index 685e4e29b8..d4a589e768 100644
> --- a/qapi/machine.json
> +++ b/qapi/machine.json
> @@ -1772,6 +1772,23 @@
>    'returns': 'HumanReadableText',
>    'features': [ 'unstable' ] }
>  
> +##
> +# @x-query-nvme:
> +#
> +# Query state of emulated NVMe controllers.
> +#
> +# Features:
> +#
> +# @unstable: This command is meant for debugging.
> +#
> +# Returns: NVMe controller state as human-readable text
> +#
> +# Since: 11.1
> +##
> +{ 'command': 'x-query-nvme',
> +  'returns': 'HumanReadableText',
> +  'features': [ 'unstable' ] }
> +
>  ##
>  # @SmbiosEntryPointType:
>  #
> -- 
> 2.53.0
> 
> 

Attachment: signature.asc
Description: PGP signature

Reply via email to