From: "Dr. David Alan Gilbert" <dave@treblig.org>
To: Mateusz Nowicki <mateusz.nowicki@posteo.net>,
Markus Armbruster <armbru@redhat.com>
Cc: qemu-devel@nongnu.org, qemu-block@nongnu.org,
"Keith Busch" <kbusch@kernel.org>,
"Klaus Jensen" <its@irrelevant.dk>,
"Jesper Devantier" <foss@defmacro.it>,
"Philippe Mathieu-Daudé" <philmd@linaro.org>,
"Zhao Liu" <zhao1.liu@intel.com>,
"Eric Blake" <eblake@redhat.com>
Subject: Re: [PATCH 2/2] hw/nvme: add 'info nvme-queues' HMP command
Date: Tue, 12 May 2026 00:08:02 +0000 [thread overview]
Message-ID: <agJvYo00GNefQNwS@gallifrey> (raw)
In-Reply-To: <786a781251d3898b979656b9e5390e50bb35100f.1778409416.git.mateusz.nowicki@posteo.net>
* Mateusz Nowicki (mateusz.nowicki@posteo.net) wrote:
> Add an 'info nvme-queues' HMP command that lists, for every emulated
> NVMe controller, the admin SQ/CQ and every active I/O SQ/CQ.
>
> For each queue the command prints:
>
> - the ring size, head and tail indices;
> - the associated CQ id (for SQ) or interrupt vector (for CQ);
> - the queue's PRP1 (DMA base address of the ring);
> - the BAR0-relative doorbell offset (SQyTDBL / CQyHDBL);
> - the current CQ phase tag.
>
> The doorbell offsets are computed from CAP.DSTRD so they remain
> correct if the emulation ever exposes a non-zero stride.
>
> Useful when debugging the Linux NVMe driver against the QEMU
> emulation - queue setup, doorbell rings, AERs held in the admin SQ
> etc. - without attaching gdb to the QEMU process.
>
> Example, with the long PRP1 ring address and BAR0-relative doorbell
> offset replaced by '...'; phase tag column omitted for brevity:
>
> (qemu) info nvme-queues
> /machine/peripheral-anon/device[0]
> SQ 0 size=32 head=9 tail=9 cqid=0 prp1=... SQTDBL=...
> CQ 0 size=32 head=8 tail=8 iv=0 prp1=... CQHDBL=...
> SQ 1 size=1024 head=2 tail=2 cqid=1 prp1=... SQTDBL=...
> CQ 1 size=1024 head=2 tail=2 iv=1 prp1=... CQHDBL=...
>
> Signed-off-by: Mateusz Nowicki <mateusz.nowicki@posteo.net>
as the previous patch; looks OK from HMP but check where the json should live.
Acked-by: Dr. David Alan Gilbert <dave@treblig.org>
> ---
> hmp-commands-info.hx | 15 +++++++++++
> hw/nvme/monitor.c | 63 ++++++++++++++++++++++++++++++++++++++++++++
> qapi/machine.json | 17 ++++++++++++
> 3 files changed, 95 insertions(+)
>
> diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx
> index b984691c3c..874c1e1970 100644
> --- a/hmp-commands-info.hx
> +++ b/hmp-commands-info.hx
> @@ -353,6 +353,21 @@ SRST
> Show emulated NVMe controllers.
> ERST
>
> + {
> + .name = "nvme-queues",
> + .args_type = "",
> + .params = "",
> + .help = "show active NVMe queues and their doorbells",
> + .cmd_info_hrt = qmp_x_query_nvme_queues,
> + },
> +
> +SRST
> + ``info nvme-queues``
> + Show all active NVMe submission and completion queues, including
> + head/tail, DMA address of the ring and BAR0-relative doorbell
> + offset.
> +ERST
> +
> {
> .name = "usbhost",
> .args_type = "",
> diff --git a/hw/nvme/monitor.c b/hw/nvme/monitor.c
> index 95a6754437..c8161943c0 100644
> --- a/hw/nvme/monitor.c
> +++ b/hw/nvme/monitor.c
> @@ -74,3 +74,66 @@ HumanReadableText *qmp_x_query_nvme(Error **errp)
>
> return human_readable_text_from_str(buf);
> }
> +
> +static void append_sq(GString *buf, NvmeSQueue *sq, unsigned stride)
> +{
> + hwaddr db_off = 0x1000 + 2 * sq->sqid * stride;
> +
> + g_string_append_printf(buf,
> + " SQ %u size=%-5u head=%-5u tail=%-5u cqid=%-3u "
> + "prp1=0x%016" PRIx64 " SQTDBL=BAR0+0x%03" HWADDR_PRIx "\n",
> + sq->sqid, sq->size, sq->head, sq->tail, sq->cqid,
> + sq->dma_addr, db_off);
> +}
> +
> +static void append_cq(GString *buf, NvmeCQueue *cq, unsigned stride)
> +{
> + hwaddr db_off = 0x1000 + (2 * cq->cqid + 1) * stride;
> +
> + g_string_append_printf(buf,
> + " CQ %u size=%-5u head=%-5u tail=%-5u iv=%-5u "
> + "prp1=0x%016" PRIx64 " CQHDBL=BAR0+0x%03" HWADDR_PRIx
> + " phaseTag=%u\n",
> + cq->cqid, cq->size, cq->head, cq->tail, cq->vector,
> + cq->dma_addr, db_off, cq->phase);
> +}
> +
> +static int collect_queues(Object *obj, void *opaque)
> +{
> + GString *buf = opaque;
> + NvmeCtrl *n;
> + unsigned stride;
> +
> + if (!object_dynamic_cast(obj, TYPE_NVME)) {
> + return 0;
> + }
> + n = NVME(obj);
> + stride = 4u << NVME_CAP_DSTRD(ldq_le_p(&n->bar.cap));
> +
> + g_string_append_printf(buf, "%s\n", object_get_canonical_path(obj));
> + append_sq(buf, &n->admin_sq, stride);
> + append_cq(buf, &n->admin_cq, stride);
> +
> + for (unsigned i = 1; i <= n->params.max_ioqpairs; i++) {
> + if (n->sq && n->sq[i]) {
> + append_sq(buf, n->sq[i], stride);
> + }
> + if (n->cq && n->cq[i]) {
> + append_cq(buf, n->cq[i], stride);
> + }
> + }
> + return 0;
> +}
> +
> +HumanReadableText *qmp_x_query_nvme_queues(Error **errp)
> +{
> + g_autoptr(GString) buf = g_string_new("");
> +
> + object_child_foreach_recursive(object_get_root(), collect_queues, 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 d4a589e768..c21b128e0a 100644
> --- a/qapi/machine.json
> +++ b/qapi/machine.json
> @@ -1789,6 +1789,23 @@
> 'returns': 'HumanReadableText',
> 'features': [ 'unstable' ] }
>
> +##
> +# @x-query-nvme-queues:
> +#
> +# Query state of all active SQ/CQ for emulated NVMe controllers.
> +#
> +# Features:
> +#
> +# @unstable: This command is meant for debugging.
> +#
> +# Returns: per-queue state as human-readable text
> +#
> +# Since: 11.1
> +##
> +{ 'command': 'x-query-nvme-queues',
> + 'returns': 'HumanReadableText',
> + 'features': [ 'unstable' ] }
> +
> ##
> # @SmbiosEntryPointType:
> #
> --
> 2.53.0
>
--
-----Open up your eyes, open up your mind, open up your code -------
/ Dr. David Alan Gilbert | Running GNU/Linux | Happy \
\ dave @ treblig.org | | In Hex /
\ _________________________|_____ http://www.treblig.org |_______/
next prev parent reply other threads:[~2026-05-12 0:08 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-10 10:57 [PATCH 0/2] hw/nvme: add monitor commands for inspecting state Mateusz Nowicki
2026-05-10 10:57 ` [PATCH 1/2] hw/nvme: add 'info nvme' HMP command Mateusz Nowicki
2026-05-12 0:03 ` Dr. David Alan Gilbert
2026-05-13 11:51 ` Markus Armbruster
2026-05-13 18:15 ` Mateusz Nowicki
2026-05-18 12:52 ` Klaus Jensen
2026-05-18 15:01 ` mateusz.nowicki
2026-05-10 10:57 ` [PATCH 2/2] hw/nvme: add 'info nvme-queues' " Mateusz Nowicki
2026-05-12 0:08 ` Dr. David Alan Gilbert [this message]
2026-05-13 11:52 ` Markus Armbruster
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=agJvYo00GNefQNwS@gallifrey \
--to=dave@treblig.org \
--cc=armbru@redhat.com \
--cc=eblake@redhat.com \
--cc=foss@defmacro.it \
--cc=its@irrelevant.dk \
--cc=kbusch@kernel.org \
--cc=mateusz.nowicki@posteo.net \
--cc=philmd@linaro.org \
--cc=qemu-block@nongnu.org \
--cc=qemu-devel@nongnu.org \
--cc=zhao1.liu@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.