* [PATCH v5 1/1] system: improve visual representation of node hierarchy
2025-04-30 16:43 [PATCH v5 0/1] Optimizing the print format of the QEMU monitor 'info mtree' Chao Liu
@ 2025-04-30 16:43 ` Chao Liu
2025-04-30 21:35 ` [PATCH v5 0/1] Optimizing the print format of the QEMU monitor 'info mtree' BALATON Zoltan
1 sibling, 0 replies; 3+ messages in thread
From: Chao Liu @ 2025-04-30 16:43 UTC (permalink / raw)
To: pbonzini, peterx, david, philmd, armbru, balaton
Cc: zhangtj, zqz00548, lc00631, qemu-devel
Make the hierarchical relationship between nodes clearer by adding characters.
e.g.
```
$ qemu-system-riscv64 -M virt -monitor stdio -display none
(qemu) info mtree
...
address-space: memory
`-- 0000000000000000-ffffffffffffffff (prio 0, i/o): system
|-- 0000000000001000-000000000000ffff (prio 0, rom): riscv_virt_board.mrom
...
|-- 0000000003000000-000000000300ffff (prio 0, i/o): gpex_ioport_window
| `-- 0000000003000000-000000000300ffff (prio 0, i/o): gpex_ioport
|-- 0000000004000000-0000000005ffffff (prio 0, i/o): platform bus
...
|-- 0000000080000000-0000000087ffffff (prio 0, ram): riscv_virt_board.ram
`-- 0000000400000000-00000007ffffffff (prio 0, i/o): alias pcie-mmio-high @gpex_mmio_window
```
Signed-off-by: Chao Liu <lc00631@tecorigin.com>
Reviewed-by: Qingze Zhao <zqz00548@tecorigin.com>
Reviewed-by: Tingjian Zhang <zhangtj@tecorigin.com>
---
system/memory.c | 122 +++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 111 insertions(+), 11 deletions(-)
diff --git a/system/memory.c b/system/memory.c
index 71434e7ad0..ec40ef09aa 100644
--- a/system/memory.c
+++ b/system/memory.c
@@ -3283,10 +3283,20 @@ static const char *memory_region_type(MemoryRegion *mr)
}
}
+typedef struct PrintCol PrintCol;
+
+struct PrintCol {
+ bool print_col;
+ QTAILQ_ENTRY(PrintCol) queue;
+};
+
+typedef QTAILQ_HEAD(, PrintCol) PrintColHead;
+
typedef struct MemoryRegionList MemoryRegionList;
struct MemoryRegionList {
const MemoryRegion *mr;
+ PrintColHead *col_string;
QTAILQ_ENTRY(MemoryRegionList) mrqueue;
};
@@ -3296,6 +3306,94 @@ typedef QTAILQ_HEAD(, MemoryRegionList) MemoryRegionListHead;
int128_sub((size), int128_one())) : 0)
#define MTREE_INDENT " "
+static void mtree_print_col(PrintColHead *col_string, unsigned int level)
+{
+ PrintCol *col = NULL;
+ int i = 0;
+
+ /* Level 0 always has not a col. */
+ if (level == 0 || col_string == NULL) {
+ return;
+ }
+
+ /*
+ * If the parent node is not a tail node,
+ * print a column at the corresponding level.
+ */
+ if (col_string != NULL) {
+ QTAILQ_FOREACH(col, col_string, queue) {
+ if (i++ == level) {
+ break;
+ }
+ }
+ }
+
+ if (col != NULL && col->print_col) {
+ qemu_printf("|");
+ } else {
+ qemu_printf(" ");
+ }
+
+ /* Align with the first character of the parent node. */
+ qemu_printf(" ");
+}
+
+static void mtree_print_node(bool is_tail)
+{
+ if (is_tail) {
+ qemu_printf("`-- ");
+ } else {
+ qemu_printf("|-- ");
+ }
+}
+
+static void mtree_print_head(PrintColHead *col_string, unsigned int level,
+ bool is_tail)
+{
+ for (int i = 0; i < level; i++) {
+ mtree_print_col(col_string, i);
+ }
+ mtree_print_node(is_tail);
+}
+
+static PrintColHead *mtree_col_string_new(PrintColHead *col_string, int level,
+ bool is_tail)
+{
+ PrintColHead *new_col_string = g_new(PrintColHead, 1);
+ PrintCol *col, *new_col;
+ int i = 0;
+
+ QTAILQ_INIT(new_col_string);
+ if (col_string != NULL) {
+ QTAILQ_FOREACH(col, col_string, queue) {
+ new_col = g_new(PrintCol, 1);
+ new_col->print_col = col->print_col;
+ QTAILQ_INSERT_TAIL(new_col_string, new_col, queue);
+ i++;
+ }
+ } else {
+ new_col = g_new(PrintCol, 1);
+ new_col->print_col = true;
+ QTAILQ_INSERT_TAIL(new_col_string, new_col, queue);
+ i++;
+ }
+ for (; i < level; i++) {
+ new_col = g_new(PrintCol, 1);
+ new_col->print_col = ((i == (level - 1)) && is_tail) ? false : true;
+ QTAILQ_INSERT_TAIL(new_col_string, new_col, queue);
+ }
+ return new_col_string;
+}
+
+static void mtree_col_string_free(PrintColHead *col_string)
+{
+ PrintCol *col, *next_col;
+ QTAILQ_FOREACH_SAFE(col, col_string, queue, next_col) {
+ g_free(col);
+ }
+ g_free(col_string);
+}
+
static void mtree_expand_owner(const char *label, Object *obj)
{
DeviceState *dev = (DeviceState *) object_dynamic_cast(obj, TYPE_DEVICE);
@@ -3335,12 +3433,13 @@ static void mtree_print_mr_owner(const MemoryRegion *mr)
static void mtree_print_mr(const MemoryRegion *mr, unsigned int level,
hwaddr base,
MemoryRegionListHead *alias_print_queue,
- bool owner, bool display_disabled)
+ bool owner, bool display_disabled,
+ PrintColHead *col_string,
+ bool is_tail)
{
MemoryRegionList *new_ml, *ml, *next_ml;
MemoryRegionListHead submr_print_queue;
const MemoryRegion *submr;
- unsigned int i;
hwaddr cur_start, cur_end;
if (!mr) {
@@ -3375,9 +3474,7 @@ static void mtree_print_mr(const MemoryRegion *mr, unsigned int level,
QTAILQ_INSERT_TAIL(alias_print_queue, ml, mrqueue);
}
if (mr->enabled || display_disabled) {
- for (i = 0; i < level; i++) {
- qemu_printf(MTREE_INDENT);
- }
+ mtree_print_head(col_string, level, is_tail);
qemu_printf(HWADDR_FMT_plx "-" HWADDR_FMT_plx
" (prio %d, %s%s): alias %s @%s " HWADDR_FMT_plx
"-" HWADDR_FMT_plx "%s",
@@ -3397,9 +3494,7 @@ static void mtree_print_mr(const MemoryRegion *mr, unsigned int level,
}
} else {
if (mr->enabled || display_disabled) {
- for (i = 0; i < level; i++) {
- qemu_printf(MTREE_INDENT);
- }
+ mtree_print_head(col_string, level, is_tail);
qemu_printf(HWADDR_FMT_plx "-" HWADDR_FMT_plx
" (prio %d, %s%s): %s%s",
cur_start, cur_end,
@@ -3420,6 +3515,8 @@ static void mtree_print_mr(const MemoryRegion *mr, unsigned int level,
QTAILQ_FOREACH(submr, &mr->subregions, subregions_link) {
new_ml = g_new(MemoryRegionList, 1);
new_ml->mr = submr;
+ new_ml->col_string = mtree_col_string_new(col_string,
+ level + 1, is_tail);
QTAILQ_FOREACH(ml, &submr_print_queue, mrqueue) {
if (new_ml->mr->addr < ml->mr->addr ||
(new_ml->mr->addr == ml->mr->addr &&
@@ -3436,10 +3533,12 @@ static void mtree_print_mr(const MemoryRegion *mr, unsigned int level,
QTAILQ_FOREACH(ml, &submr_print_queue, mrqueue) {
mtree_print_mr(ml->mr, level + 1, cur_start,
- alias_print_queue, owner, display_disabled);
+ alias_print_queue, owner, display_disabled,
+ ml->col_string, ml == QTAILQ_LAST(&submr_print_queue));
}
QTAILQ_FOREACH_SAFE(ml, &submr_print_queue, mrqueue, next_ml) {
+ mtree_col_string_free(ml->col_string);
g_free(ml);
}
}
@@ -3614,7 +3713,8 @@ static void mtree_print_as(gpointer key, gpointer value, gpointer user_data)
struct AddressSpaceInfo *asi = user_data;
g_slist_foreach(as_same_root_mr_list, mtree_print_as_name, NULL);
- mtree_print_mr(mr, 1, 0, asi->ml_head, asi->owner, asi->disabled);
+ mtree_print_mr(mr, 1, 0, asi->ml_head, asi->owner, asi->disabled,
+ NULL, true);
qemu_printf("\n");
}
@@ -3659,7 +3759,7 @@ static void mtree_info_as(bool dispatch_tree, bool owner, bool disabled)
/* print aliased regions */
QTAILQ_FOREACH(ml, &ml_head, mrqueue) {
qemu_printf("memory-region: %s\n", memory_region_name(ml->mr));
- mtree_print_mr(ml->mr, 1, 0, &ml_head, owner, disabled);
+ mtree_print_mr(ml->mr, 1, 0, &ml_head, owner, disabled, NULL, true);
qemu_printf("\n");
}
--
2.48.1
^ permalink raw reply related [flat|nested] 3+ messages in thread