From: "Marc-André Lureau" <marcandre.lureau@redhat.com>
To: qemu-devel@nongnu.org
Cc: "Marc-André Lureau" <marcandre.lureau@redhat.com>
Subject: [PATCH v4 12/13] monitor: add 'info ramblock-attributes' command
Date: Mon, 04 May 2026 16:30:18 +0400 [thread overview]
Message-ID: <20260504-rdm5-v4-12-bdf61e57c1e1@redhat.com> (raw)
In-Reply-To: <20260504-rdm5-v4-0-bdf61e57c1e1@redhat.com>
Add a new 'info ramblock-attributes' HMP command and the corresponding
'x-query-ramblock-attributes' QMP command to display the shared/private
memory attributes for ram blocks.
The QMP command returns structured data (RamBlockAttributesInfo list
with per-range shared/populated attributes), while HMP formats it for
human consumption.
This is useful for debugging confidential guests (TDX, SNP) to inspect
which memory regions are shared vs private, and their population state
when a RamDiscardManager is present (e.g. virtio-mem).
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
qapi/machine.json | 55 +++++++++++++++++++++++++++++++++
include/monitor/hmp.h | 1 +
hw/core/machine-hmp-cmds.c | 32 +++++++++++++++++++
system/ram-block-attributes.c | 72 +++++++++++++++++++++++++++++++++++++++++++
hmp-commands-info.hx | 13 ++++++++
5 files changed, 173 insertions(+)
diff --git a/qapi/machine.json b/qapi/machine.json
index 685e4e29b87..aac8a235cf6 100644
--- a/qapi/machine.json
+++ b/qapi/machine.json
@@ -1738,6 +1738,61 @@
'returns': 'HumanReadableText',
'features': [ 'unstable' ] }
+##
+# @RamBlockAttributeRange:
+#
+# A contiguous range within a ram block with uniform attributes.
+#
+# @start: start offset in bytes within the ram block
+#
+# @length: length in bytes of the range
+#
+# @shared: true if the range is shared, false if private
+#
+# @populated: true if the range is populated (only present when a
+# RamDiscardManager is managing the block)
+#
+# Since: 11.1
+##
+{ 'struct': 'RamBlockAttributeRange',
+ 'data': { 'start': 'uint64',
+ 'length': 'uint64',
+ 'shared': 'bool',
+ '*populated': 'bool' } }
+
+##
+# @RamBlockAttributesInfo:
+#
+# Shared/private memory attributes for a ram block.
+#
+# @name: the ram block identifier
+#
+# @ranges: list of attribute ranges
+#
+# Since: 11.1
+##
+{ 'struct': 'RamBlockAttributesInfo',
+ 'data': { 'name': 'str',
+ 'ranges': [ 'RamBlockAttributeRange' ] } }
+
+##
+# @x-query-ramblock-attributes:
+#
+# Query ram block shared/private attributes. This is useful
+# to debug confidential guests.
+#
+# Features:
+#
+# @unstable: This command is meant for debugging.
+#
+# Returns: list of ram block attributes
+#
+# Since: 11.1
+##
+{ 'command': 'x-query-ramblock-attributes',
+ 'returns': [ 'RamBlockAttributesInfo' ],
+ 'features': [ 'unstable' ] }
+
##
# @x-query-roms:
#
diff --git a/include/monitor/hmp.h b/include/monitor/hmp.h
index e222bea60cd..4493952b417 100644
--- a/include/monitor/hmp.h
+++ b/include/monitor/hmp.h
@@ -143,6 +143,7 @@ void hmp_info_dump(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_ramblock_attributes(Monitor *mon, const QDict *qdict);
void hmp_info_replay(Monitor *mon, const QDict *qdict);
void hmp_replay_break(Monitor *mon, const QDict *qdict);
void hmp_replay_delete_break(Monitor *mon, const QDict *qdict);
diff --git a/hw/core/machine-hmp-cmds.c b/hw/core/machine-hmp-cmds.c
index 46846f741a2..122e1a0f735 100644
--- a/hw/core/machine-hmp-cmds.c
+++ b/hw/core/machine-hmp-cmds.c
@@ -24,6 +24,7 @@
#include "qapi/string-output-visitor.h"
#include "qemu/error-report.h"
#include "system/numa.h"
+#include "system/ramblock.h"
#include "hw/core/boards.h"
void hmp_info_cpus(Monitor *mon, const QDict *qdict)
@@ -388,3 +389,34 @@ void hmp_info_memory_size_summary(Monitor *mon, const QDict *qdict)
}
hmp_handle_error(mon, err);
}
+
+void hmp_info_ramblock_attributes(Monitor *mon, const QDict *qdict)
+{
+ Error *err = NULL;
+ g_autoptr(RamBlockAttributesInfoList) list = NULL;
+ RamBlockAttributesInfoList *it;
+
+ list = qmp_x_query_ramblock_attributes(&err);
+ if (hmp_handle_error(mon, err)) {
+ return;
+ }
+
+ for (it = list; it; it = it->next) {
+ RamBlockAttributesInfo *rba = it->value;
+ RamBlockAttributeRangeList *r;
+
+ monitor_printf(mon, "%s:\n", rba->name);
+ for (r = rba->ranges; r; r = r->next) {
+ RamBlockAttributeRange *range = r->value;
+ const char *shared = range->shared ? "shared" : "private";
+ const char *pop = range->has_populated ?
+ (range->populated ? "+populated" : "-populated") : "";
+
+ monitor_printf(mon,
+ " 0x%016" PRIx64 "-0x%016" PRIx64 " %s%s\n",
+ range->start,
+ range->start + range->length - 1,
+ shared, pop);
+ }
+ }
+}
diff --git a/system/ram-block-attributes.c b/system/ram-block-attributes.c
index 59ec7a28eb0..f9573801b60 100644
--- a/system/ram-block-attributes.c
+++ b/system/ram-block-attributes.c
@@ -11,6 +11,7 @@
#include "qemu/osdep.h"
#include "qemu/error-report.h"
+#include "qapi/qapi-commands-machine.h"
#include "system/ramblock.h"
#include "trace.h"
@@ -221,3 +222,74 @@ static void ram_block_attributes_class_init(ObjectClass *klass,
rdsc->get_min_granularity = ram_block_attributes_rds_get_min_granularity;
rdsc->is_populated = ram_block_attributes_rds_is_populated;
}
+
+RamBlockAttributesInfoList *qmp_x_query_ramblock_attributes(Error **errp)
+{
+ RamBlockAttributesInfoList *head = NULL, **tail = &head;
+ RAMBlock *block;
+ size_t rba_block_size = ram_block_attributes_get_block_size();
+
+ RCU_READ_LOCK_GUARD();
+
+ RAMBLOCK_FOREACH(block) {
+ RamBlockAttributesInfo *rba;
+ RamBlockAttributeRangeList **range_tail;
+ RamBlockAttributes *attr = block->attributes;
+ RamDiscardManager *rdm;
+ bool has_rdm;
+ unsigned long pos;
+
+ if (!attr) {
+ continue;
+ }
+
+ rdm = memory_region_get_ram_discard_manager(block->mr);
+ has_rdm = rdm != NULL;
+
+ rba = g_new0(RamBlockAttributesInfo, 1);
+ rba->name = g_strdup(block->idstr);
+ range_tail = &rba->ranges;
+
+ pos = 0;
+ while (pos < attr->bitmap_size) {
+ bool is_shared = test_bit(pos, attr->bitmap);
+ unsigned long next;
+ uint64_t start_offset, length;
+ RamBlockAttributeRange *range;
+
+ if (is_shared) {
+ next = find_next_zero_bit(attr->bitmap,
+ attr->bitmap_size, pos);
+ } else {
+ next = find_next_bit(attr->bitmap,
+ attr->bitmap_size, pos);
+ }
+
+ start_offset = (uint64_t)pos * rba_block_size;
+ length = (uint64_t)(next - pos) * rba_block_size;
+
+ range = g_new0(RamBlockAttributeRange, 1);
+ range->start = start_offset;
+ range->length = length;
+ range->shared = is_shared;
+
+ if (has_rdm) {
+ MemoryRegionSection section = {
+ .mr = block->mr,
+ .offset_within_region = start_offset,
+ .size = int128_make64(length),
+ };
+ range->has_populated = true;
+ range->populated =
+ ram_discard_manager_is_populated(rdm, §ion);
+ }
+
+ QAPI_LIST_APPEND(range_tail, range);
+ pos = next;
+ }
+
+ QAPI_LIST_APPEND(tail, rba);
+ }
+
+ return head;
+}
diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx
index 74c741f80e2..1168b4c20ca 100644
--- a/hmp-commands-info.hx
+++ b/hmp-commands-info.hx
@@ -774,6 +774,19 @@ SRST
Dump all the ramblocks of the system.
ERST
+ {
+ .name = "ramblock-attributes",
+ .args_type = "",
+ .params = "",
+ .help = "Display ramblock shared/private attributes",
+ .cmd = hmp_info_ramblock_attributes,
+ },
+
+SRST
+ ``info ramblock-attributes``
+ Display the shared/private memory attributes for ram blocks.
+ERST
+
{
.name = "hotpluggable-cpus",
.args_type = "",
--
2.54.0
next prev parent reply other threads:[~2026-05-04 12:31 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-04 12:30 [PATCH v4 00/13] Make RamDiscardManager work with multiple sources & virtio-mem Marc-André Lureau
2026-05-04 12:30 ` [PATCH v4 01/13] system/memory: split RamDiscardManager into source and manager Marc-André Lureau
2026-05-04 12:30 ` [PATCH v4 02/13] system/memory: move RamDiscardManager to separate compilation unit Marc-André Lureau
2026-05-04 12:30 ` [PATCH v4 03/13] system/memory: constify section arguments Marc-André Lureau
2026-05-04 12:30 ` [PATCH v4 04/13] system/ram-discard-manager: implement replay via is_populated iteration Marc-André Lureau
2026-05-13 20:40 ` Peter Xu
2026-05-04 12:30 ` [PATCH v4 05/13] virtio-mem: remove replay_populated/replay_discarded implementation Marc-André Lureau
2026-05-13 20:40 ` Peter Xu
2026-05-04 12:30 ` [PATCH v4 06/13] system/ram-discard-manager: drop replay from source interface Marc-André Lureau
2026-05-13 20:40 ` Peter Xu
2026-05-04 12:30 ` [PATCH v4 07/13] system/memory: implement RamDiscardManager multi-source aggregation Marc-André Lureau
2026-05-04 12:30 ` [PATCH v4 08/13] system/physmem: destroy ram block attributes before RCU-deferred reclaim Marc-André Lureau
2026-05-04 12:30 ` [PATCH v4 09/13] system/memory: add RamDiscardManager reference counting and cleanup Marc-André Lureau
2026-05-04 12:30 ` [PATCH v4 10/13] tests: add unit tests for RamDiscardManager multi-source aggregation Marc-André Lureau
2026-05-04 12:30 ` [PATCH v4 11/13] system/physmem: make ram_block_discard_range() handle guest_memfd Marc-André Lureau
2026-05-13 20:37 ` Peter Xu
2026-05-04 12:30 ` Marc-André Lureau [this message]
2026-05-13 20:39 ` [PATCH v4 12/13] monitor: add 'info ramblock-attributes' command Peter Xu
2026-05-04 12:30 ` [PATCH v4 13/13] RFC: hw/virtio: start virtio-mem guest_memfd regions as shared Marc-André Lureau
2026-05-13 20:47 ` Peter Xu
2026-05-14 7:32 ` Chenyi Qiang
2026-05-13 20:53 ` [PATCH v4 00/13] Make RamDiscardManager work with multiple sources & virtio-mem Peter Xu
2026-05-14 5:15 ` Chenyi Qiang
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=20260504-rdm5-v4-12-bdf61e57c1e1@redhat.com \
--to=marcandre.lureau@redhat.com \
--cc=qemu-devel@nongnu.org \
/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.